Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2017-06-08 00:16:47 +0300
committerCampbell Barton <ideasman42@gmail.com>2017-06-08 00:42:17 +0300
commit7f480352caaa14a20c0438ae0ed1c2607b6c2c00 (patch)
tree6e938c6173a15d54c681458e361fd61b32fb8cf7 /source/blender/editors
parentbfa5efeebecb24d52bd63d79d6fc08518568f5e6 (diff)
WM: move manipulator library into editors
As with operators, the window-manager has the API for defining, the editor can implement and register its own manipulators. This exposes wmManipulator, keeping it opaque isn't practical if editors and Python are to implement their own.
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/CMakeLists.txt1
-rw-r--r--source/blender/editors/include/ED_manipulator_library.h139
-rw-r--r--source/blender/editors/manipulator_library/CMakeLists.txt56
-rw-r--r--source/blender/editors/manipulator_library/arrow2d_manipulator.c233
-rw-r--r--source/blender/editors/manipulator_library/arrow3d_manipulator.c550
-rw-r--r--source/blender/editors/manipulator_library/cage2d_manipulator.c598
-rw-r--r--source/blender/editors/manipulator_library/dial3d_manipulator.c376
-rw-r--r--source/blender/editors/manipulator_library/geom_arrow_manipulator.c141
-rw-r--r--source/blender/editors/manipulator_library/geom_cube_manipulator.c75
-rw-r--r--source/blender/editors/manipulator_library/geom_dial_manipulator.c813
-rw-r--r--source/blender/editors/manipulator_library/manipulator_draw_utils.c127
-rw-r--r--source/blender/editors/manipulator_library/manipulator_geometry.h51
-rw-r--r--source/blender/editors/manipulator_library/manipulator_library_intern.h111
-rw-r--r--source/blender/editors/manipulator_library/manipulator_library_utils.c169
-rw-r--r--source/blender/editors/manipulator_library/primitive3d_manipulator.c252
-rw-r--r--source/blender/editors/space_api/spacetypes.c16
-rw-r--r--source/blender/editors/space_node/node_widgets.c11
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulators.c47
-rw-r--r--source/blender/editors/transform/transform_manipulator.c55
-rw-r--r--source/blender/editors/util/CMakeLists.txt1
20 files changed, 3755 insertions, 67 deletions
diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt
index f62db3c1ddb..757fca0a1b2 100644
--- a/source/blender/editors/CMakeLists.txt
+++ b/source/blender/editors/CMakeLists.txt
@@ -29,6 +29,7 @@ if(WITH_BLENDER)
add_subdirectory(gpencil)
add_subdirectory(interface)
add_subdirectory(io)
+ add_subdirectory(manipulator_library)
add_subdirectory(mask)
add_subdirectory(mesh)
add_subdirectory(metaball)
diff --git a/source/blender/editors/include/ED_manipulator_library.h b/source/blender/editors/include/ED_manipulator_library.h
new file mode 100644
index 00000000000..a9c04c8e004
--- /dev/null
+++ b/source/blender/editors/include/ED_manipulator_library.h
@@ -0,0 +1,139 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ED_manipulator_library.h
+ * \ingroup wm
+ *
+ * \name Generic Manipulators.
+ *
+ * This is exposes pre-defined manipulators for re-use.
+ */
+
+
+#ifndef __ED_MANIPULATOR_LIBRARY_H__
+#define __ED_MANIPULATOR_LIBRARY_H__
+
+/* initialize manipulators */
+void ED_manipulatortypes_arrow_2d(void);
+void ED_manipulatortypes_arrow_3d(void);
+void ED_manipulatortypes_cage_2d(void);
+void ED_manipulatortypes_dial_3d(void);
+void ED_manipulatortypes_facemap_3d(void);
+void ED_manipulatortypes_primitive_3d(void);
+
+struct wmManipulatorGroup;
+
+/* -------------------------------------------------------------------- */
+/* 3D Arrow Manipulator */
+
+enum {
+ ED_MANIPULATOR_ARROW_STYLE_NORMAL = 1,
+ ED_MANIPULATOR_ARROW_STYLE_NO_AXIS = (1 << 1),
+ ED_MANIPULATOR_ARROW_STYLE_CROSS = (1 << 2),
+ /* inverted offset during interaction - if set it also sets constrained below */
+ ED_MANIPULATOR_ARROW_STYLE_INVERTED = (1 << 3),
+ /* clamp arrow interaction to property width */
+ ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED = (1 << 4),
+ /* use a box for the arrowhead */
+ ED_MANIPULATOR_ARROW_STYLE_BOX = (1 << 5),
+ ED_MANIPULATOR_ARROW_STYLE_CONE = (1 << 6),
+};
+
+/* slots for properties */
+enum {
+ ED_MANIPULATOR_ARROW_SLOT_OFS_WORLD_SPACE = 0
+};
+
+struct wmManipulator *ED_manipulator_arrow3d_new(
+ struct wmManipulatorGroup *mgroup, const char *name, const int style);
+void ED_manipulator_arrow3d_set_direction(struct wmManipulator *manipulator, const float direction[3]);
+void ED_manipulator_arrow3d_set_up_vector(struct wmManipulator *manipulator, const float direction[3]);
+void ED_manipulator_arrow3d_set_line_len(struct wmManipulator *manipulator, const float len);
+void ED_manipulator_arrow3d_set_ui_range(struct wmManipulator *manipulator, const float min, const float max);
+void ED_manipulator_arrow3d_set_range_fac(struct wmManipulator *manipulator, const float range_fac);
+void ED_manipulator_arrow3d_cone_set_aspect(struct wmManipulator *manipulator, const float aspect[2]);
+
+
+/* -------------------------------------------------------------------- */
+/* 2D Arrow Manipulator */
+
+struct wmManipulator *ED_manipulator_arrow2d_new(struct wmManipulatorGroup *mgroup, const char *name);
+void ED_manipulator_arrow2d_set_angle(struct wmManipulator *manipulator, const float rot_fac);
+void ED_manipulator_arrow2d_set_line_len(struct wmManipulator *manipulator, const float len);
+
+
+/* -------------------------------------------------------------------- */
+/* Cage Manipulator */
+
+enum {
+ ED_MANIPULATOR_RECT_TRANSFORM_STYLE_TRANSLATE = 1, /* Manipulator translates */
+ ED_MANIPULATOR_RECT_TRANSFORM_STYLE_ROTATE = (1 << 1), /* Manipulator rotates */
+ ED_MANIPULATOR_RECT_TRANSFORM_STYLE_SCALE = (1 << 2), /* Manipulator scales */
+ ED_MANIPULATOR_RECT_TRANSFORM_STYLE_SCALE_UNIFORM = (1 << 3), /* Manipulator scales uniformly */
+};
+
+enum {
+ ED_MANIPULATOR_RECT_TX_SLOT_OFFSET = 0,
+ ED_MANIPULATOR_RECT_TX_SLOT_SCALE = 1
+};
+
+struct wmManipulator *ED_manipulator_rect_transform_new(
+ struct wmManipulatorGroup *mgroup, const char *name, const int style);
+void ED_manipulator_rect_transform_set_dimensions(
+ struct wmManipulator *manipulator, const float width, const float height);
+
+
+/* -------------------------------------------------------------------- */
+/* Dial Manipulator */
+
+enum {
+ ED_MANIPULATOR_DIAL_STYLE_RING = 0,
+ ED_MANIPULATOR_DIAL_STYLE_RING_CLIPPED = 1,
+ ED_MANIPULATOR_DIAL_STYLE_RING_FILLED = 2,
+};
+
+struct wmManipulator *ED_manipulator_dial3d_new(
+ struct wmManipulatorGroup *mgroup, const char *name, const int style);
+void ED_manipulator_dial3d_set_up_vector(
+ struct wmManipulator *manipulator, const float direction[3]);
+
+
+/* -------------------------------------------------------------------- */
+/* Facemap Manipulator */
+
+struct wmManipulator *ED_manipulator_facemap_new(
+ struct wmManipulatorGroup *mgroup, const char *name, const int style,
+ struct Object *ob, const int facemap);
+struct bFaceMap *ED_manipulator_facemap_get_fmap(struct wmManipulator *manipulator);
+
+
+/* -------------------------------------------------------------------- */
+/* Primitive Manipulator */
+
+enum {
+ ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE = 0,
+};
+
+struct wmManipulator *ED_manipulator_primitive3d_new(
+ struct wmManipulatorGroup *mgroup, const char *name, const int style);
+void ED_manipulator_primitive3d_set_direction(struct wmManipulator *manipulator, const float direction[3]);
+void ED_manipulator_primitive3d_set_up_vector(struct wmManipulator *manipulator, const float direction[3]);
+
+#endif /* __ED_MANIPULATOR_LIBRARY_H__ */
diff --git a/source/blender/editors/manipulator_library/CMakeLists.txt b/source/blender/editors/manipulator_library/CMakeLists.txt
new file mode 100644
index 00000000000..bcb814e963f
--- /dev/null
+++ b/source/blender/editors/manipulator_library/CMakeLists.txt
@@ -0,0 +1,56 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../bmesh
+ ../../depsgraph
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/eigen
+ ../../../../intern/glew-mx
+)
+
+set(INC_SYS
+ ${GLEW_INCLUDE_PATH}
+)
+
+set(SRC
+ arrow2d_manipulator.c
+ arrow3d_manipulator.c
+ cage2d_manipulator.c
+ dial3d_manipulator.c
+ geom_arrow_manipulator.c
+ geom_cube_manipulator.c
+ manipulator_draw_utils.c
+ manipulator_library_utils.c
+ primitive3d_manipulator.c
+
+ manipulator_geometry.h
+ manipulator_library_intern.h
+)
+
+add_definitions(${GL_DEFINITIONS})
+
+blender_add_lib(bf_editor_manipulator_library "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/manipulator_library/arrow2d_manipulator.c b/source/blender/editors/manipulator_library/arrow2d_manipulator.c
new file mode 100644
index 00000000000..61827723752
--- /dev/null
+++ b/source/blender/editors/manipulator_library/arrow2d_manipulator.c
@@ -0,0 +1,233 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file arrow2d_manipulator.c
+ * \ingroup wm
+ *
+ * \name 2D Arrow Manipulator
+ *
+ * \brief Simple arrow manipulator which is dragged into a certain direction.
+ */
+
+#include "BIF_gl.h"
+
+#include "BKE_context.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_rect.h"
+
+#include "DNA_manipulator_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "ED_screen.h"
+#include "ED_manipulator_library.h"
+
+#include "GPU_draw.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "WM_types.h"
+
+/* own includes */
+#include "WM_api.h"
+
+#include "manipulator_library_intern.h"
+
+
+typedef struct ArrowManipulator2D {
+ struct wmManipulator manipulator;
+
+ float angle;
+ float line_len;
+} ArrowManipulator2D;
+
+
+static void arrow2d_draw_geom(ArrowManipulator2D *arrow, const float origin[2], const float color[4])
+{
+ const float size = 0.11f;
+ const float size_h = size / 2.0f;
+ const float len = arrow->line_len;
+ const float draw_line_ofs = (arrow->manipulator.line_width * 0.5f) / arrow->manipulator.scale;
+
+ unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+
+ gpuPushMatrix();
+ gpuTranslate2fv(origin);
+ gpuScaleUniform(arrow->manipulator.scale);
+ gpuRotate2D(RAD2DEGF(arrow->angle));
+ /* local offset */
+ gpuTranslate2f(arrow->manipulator.offset[0] + draw_line_ofs, arrow->manipulator.offset[1]);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4fv(color);
+
+ immBegin(PRIM_LINES, 2);
+ immVertex2f(pos, 0.0f, 0.0f);
+ immVertex2f(pos, 0.0f, len);
+ immEnd();
+
+ immBegin(PRIM_TRIANGLES, 3);
+ immVertex2f(pos, size_h, len);
+ immVertex2f(pos, -size_h, len);
+ immVertex2f(pos, 0.0f, len + size * 1.7f);
+ immEnd();
+
+ immUnbindProgram();
+
+ gpuPopMatrix();
+}
+
+static void manipulator_arrow2d_draw(const bContext *UNUSED(C), struct wmManipulator *manipulator)
+{
+ ArrowManipulator2D *arrow = (ArrowManipulator2D *)manipulator;
+ float col[4];
+
+ manipulator_color_get(manipulator, manipulator->state & WM_MANIPULATOR_STATE_HIGHLIGHT, col);
+
+ glLineWidth(manipulator->line_width);
+ glEnable(GL_BLEND);
+ arrow2d_draw_geom(arrow, manipulator->origin, col);
+ glDisable(GL_BLEND);
+
+ if (arrow->manipulator.interaction_data) {
+ ManipulatorInteraction *inter = arrow->manipulator.interaction_data;
+
+ glEnable(GL_BLEND);
+ arrow2d_draw_geom(arrow, inter->init_origin, (const float[4]){0.5f, 0.5f, 0.5f, 0.5f});
+ glDisable(GL_BLEND);
+ }
+}
+
+static void manipulator_arrow2d_invoke(
+ bContext *UNUSED(C), struct wmManipulator *manipulator, const wmEvent *UNUSED(event))
+{
+ ManipulatorInteraction *inter = MEM_callocN(sizeof(ManipulatorInteraction), __func__);
+
+ copy_v2_v2(inter->init_origin, manipulator->origin);
+ manipulator->interaction_data = inter;
+}
+
+static int manipulator_arrow2d_intersect(
+ bContext *UNUSED(C), struct wmManipulator *manipulator, const wmEvent *event)
+{
+ ArrowManipulator2D *arrow = (ArrowManipulator2D *)manipulator;
+ const float mval[2] = {event->mval[0], event->mval[1]};
+ const float line_len = arrow->line_len * manipulator->scale;
+ float mval_local[2];
+
+ copy_v2_v2(mval_local, mval);
+ sub_v2_v2(mval_local, manipulator->origin);
+
+ float line[2][2];
+ line[0][0] = line[0][1] = line[1][0] = 0.0f;
+ line[1][1] = line_len;
+
+ /* rotate only if needed */
+ if (arrow->angle != 0.0f) {
+ float rot_point[2];
+ copy_v2_v2(rot_point, line[1]);
+ rotate_v2_v2fl(line[1], rot_point, arrow->angle);
+ }
+
+ /* arrow line intersection check */
+ float isect_1[2], isect_2[2];
+ const int isect = isect_line_sphere_v2(
+ line[0], line[1], mval_local, MANIPULATOR_HOTSPOT + manipulator->line_width * 0.5f,
+ isect_1, isect_2);
+
+ if (isect > 0) {
+ float line_ext[2][2]; /* extended line for segment check including hotspot */
+ copy_v2_v2(line_ext[0], line[0]);
+ line_ext[1][0] = line[1][0] + MANIPULATOR_HOTSPOT * ((line[1][0] - line[0][0]) / line_len);
+ line_ext[1][1] = line[1][1] + MANIPULATOR_HOTSPOT * ((line[1][1] - line[0][1]) / line_len);
+
+ const float lambda_1 = line_point_factor_v2(isect_1, line_ext[0], line_ext[1]);
+ if (isect == 1) {
+ return IN_RANGE_INCL(lambda_1, 0.0f, 1.0f);
+ }
+ else {
+ BLI_assert(isect == 2);
+ const float lambda_2 = line_point_factor_v2(isect_2, line_ext[0], line_ext[1]);
+ return IN_RANGE_INCL(lambda_1, 0.0f, 1.0f) && IN_RANGE_INCL(lambda_2, 0.0f, 1.0f);
+ }
+ }
+
+ return 0;
+}
+
+/* -------------------------------------------------------------------- */
+/** \name 2D Arrow Manipulator API
+ *
+ * \{ */
+
+struct wmManipulator *ED_manipulator_arrow2d_new(wmManipulatorGroup *mgroup, const char *name)
+{
+ const wmManipulatorType *mpt = WM_manipulatortype_find("MANIPULATOR_WT_arrow_2d", false);
+ ArrowManipulator2D *arrow = (ArrowManipulator2D *)WM_manipulator_new(mpt, mgroup, name);
+
+ arrow->manipulator.flag |= WM_MANIPULATOR_DRAW_ACTIVE;
+
+ arrow->line_len = 1.0f;
+
+ return &arrow->manipulator;
+}
+
+void ED_manipulator_arrow2d_set_angle(struct wmManipulator *manipulator, const float angle)
+{
+ ArrowManipulator2D *arrow = (ArrowManipulator2D *)manipulator;
+ arrow->angle = angle;
+}
+
+void ED_manipulator_arrow2d_set_line_len(struct wmManipulator *manipulator, const float len)
+{
+ ArrowManipulator2D *arrow = (ArrowManipulator2D *)manipulator;
+ arrow->line_len = len;
+}
+
+static void MANIPULATOR_WT_arrow_2d(wmManipulatorType *wt)
+{
+ /* identifiers */
+ wt->idname = "MANIPULATOR_WT_arrow_2d";
+
+ /* api callbacks */
+ wt->draw = manipulator_arrow2d_draw;
+ wt->invoke = manipulator_arrow2d_invoke;
+ wt->intersect = manipulator_arrow2d_intersect;
+
+ wt->size = sizeof(ArrowManipulator2D);
+}
+
+void ED_manipulatortypes_arrow_2d(void)
+{
+ WM_manipulatortype_append(MANIPULATOR_WT_arrow_2d);
+}
+
+/** \} */ /* Arrow Manipulator API */
diff --git a/source/blender/editors/manipulator_library/arrow3d_manipulator.c b/source/blender/editors/manipulator_library/arrow3d_manipulator.c
new file mode 100644
index 00000000000..87e26aeba66
--- /dev/null
+++ b/source/blender/editors/manipulator_library/arrow3d_manipulator.c
@@ -0,0 +1,550 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file arrow3d_manipulator.c
+ * \ingroup wm
+ *
+ * \name Arrow Manipulator
+ *
+ * 3D Manipulator
+ *
+ * \brief Simple arrow manipulator which is dragged into a certain direction.
+ * The arrow head can have varying shapes, e.g. cone, box, etc.
+ */
+
+#include "BIF_gl.h"
+
+#include "BKE_context.h"
+
+#include "BLI_math.h"
+
+#include "DNA_manipulator_types.h"
+#include "DNA_view3d_types.h"
+
+#include "ED_view3d.h"
+#include "ED_screen.h"
+#include "ED_manipulator_library.h"
+
+#include "GPU_draw.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+#include "GPU_select.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+/* own includes */
+#include "manipulator_geometry.h"
+#include "manipulator_library_intern.h"
+
+/* to use custom arrows exported to geom_arrow_manipulator.c */
+//#define USE_MANIPULATOR_CUSTOM_ARROWS
+
+/* ArrowManipulator->flag */
+enum {
+ ARROW_UP_VECTOR_SET = (1 << 0),
+ ARROW_CUSTOM_RANGE_SET = (1 << 1),
+};
+
+typedef struct ArrowManipulator3D {
+ wmManipulator manipulator;
+
+ ManipulatorCommonData data;
+
+ int style;
+ int flag;
+
+ float len; /* arrow line length */
+ float direction[3];
+ float up[3];
+ float aspect[2]; /* cone style only */
+} ArrowManipulator3D;
+
+
+/* -------------------------------------------------------------------- */
+
+static void manipulator_arrow_get_final_pos(wmManipulator *manipulator, float r_pos[3])
+{
+ ArrowManipulator3D *arrow = (ArrowManipulator3D *)manipulator;
+
+ mul_v3_v3fl(r_pos, arrow->direction, arrow->data.offset);
+ add_v3_v3(r_pos, arrow->manipulator.origin);
+}
+
+static void arrow_draw_geom(const ArrowManipulator3D *arrow, const bool select, const float color[4])
+{
+ unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT);
+ bool unbind_shader = true;
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ if (arrow->style & ED_MANIPULATOR_ARROW_STYLE_CROSS) {
+ immUniformColor4fv(color);
+
+ immBegin(PRIM_LINES, 4);
+ immVertex3f(pos, -1.0f, 0.0f, 0.0f);
+ immVertex3f(pos, 1.0f, 0.0f, 0.0f);
+ immVertex3f(pos, 0.0f, -1.0f, 0.0f);
+ immVertex3f(pos, 0.0f, 1.0f, 0.0f);
+ immEnd();
+ }
+ else if (arrow->style & ED_MANIPULATOR_ARROW_STYLE_CONE) {
+ const float unitx = arrow->aspect[0];
+ const float unity = arrow->aspect[1];
+ const float vec[4][3] = {
+ {-unitx, -unity, 0},
+ { unitx, -unity, 0},
+ { unitx, unity, 0},
+ {-unitx, unity, 0},
+ };
+
+ glLineWidth(arrow->manipulator.line_width);
+ wm_manipulator_vec_draw(color, vec, ARRAY_SIZE(vec), pos, PRIM_LINE_STRIP);
+ }
+ else {
+#ifdef USE_MANIPULATOR_CUSTOM_ARROWS
+ wm_manipulator_geometryinfo_draw(&wm_manipulator_geom_data_arrow, select, color);
+#else
+
+ const float vec[2][3] = {
+ {0.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, arrow->len},
+ };
+
+ glLineWidth(arrow->manipulator.line_width);
+ wm_manipulator_vec_draw(color, vec, ARRAY_SIZE(vec), pos, PRIM_LINE_STRIP);
+
+
+ /* *** draw arrow head *** */
+
+ gpuPushMatrix();
+
+ if (arrow->style & ED_MANIPULATOR_ARROW_STYLE_BOX) {
+ const float size = 0.05f;
+
+ /* translate to line end with some extra offset so box starts exactly where line ends */
+ gpuTranslate3f(0.0f, 0.0f, arrow->len + size);
+ /* scale down to box size */
+ gpuScale3f(size, size, size);
+
+ /* draw cube */
+ immUnbindProgram();
+ unbind_shader = false;
+ wm_manipulator_geometryinfo_draw(&wm_manipulator_geom_data_cube, select, color);
+ }
+ else {
+ const float len = 0.25f;
+ const float width = 0.06f;
+ const bool use_lighting = select == false && ((U.manipulator_flag & V3D_SHADED_MANIPULATORS) != 0);
+
+ /* translate to line end */
+ gpuTranslate3f(0.0f, 0.0f, arrow->len);
+
+ if (use_lighting) {
+ immUnbindProgram();
+ immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR);
+ }
+
+ imm_draw_circle_fill_3d(pos, 0.0, 0.0, width, 8);
+ imm_draw_cylinder_fill_3d(pos, width, 0.0, len, 8, 1);
+ }
+
+ gpuPopMatrix();
+#endif /* USE_MANIPULATOR_CUSTOM_ARROWS */
+ }
+
+ if (unbind_shader) {
+ immUnbindProgram();
+ }
+}
+
+static void arrow_draw_intern(ArrowManipulator3D *arrow, const bool select, const bool highlight)
+{
+ const float up[3] = {0.0f, 0.0f, 1.0f};
+ float col[4];
+ float rot[3][3];
+ float mat[4][4];
+ float final_pos[3];
+
+ manipulator_color_get(&arrow->manipulator, highlight, col);
+ manipulator_arrow_get_final_pos(&arrow->manipulator, final_pos);
+
+ if (arrow->flag & ARROW_UP_VECTOR_SET) {
+ copy_v3_v3(rot[2], arrow->direction);
+ copy_v3_v3(rot[1], arrow->up);
+ cross_v3_v3v3(rot[0], arrow->up, arrow->direction);
+ }
+ else {
+ rotation_between_vecs_to_mat3(rot, up, arrow->direction);
+ }
+ copy_m4_m3(mat, rot);
+ copy_v3_v3(mat[3], final_pos);
+ mul_mat3_m4_fl(mat, arrow->manipulator.scale);
+
+ gpuPushMatrix();
+ gpuMultMatrix(mat);
+
+ gpuTranslate3fv(arrow->manipulator.offset);
+
+ glEnable(GL_BLEND);
+ arrow_draw_geom(arrow, select, col);
+ glDisable(GL_BLEND);
+
+ gpuPopMatrix();
+
+ if (arrow->manipulator.interaction_data) {
+ ManipulatorInteraction *inter = arrow->manipulator.interaction_data;
+
+ copy_m4_m3(mat, rot);
+ copy_v3_v3(mat[3], inter->init_origin);
+ mul_mat3_m4_fl(mat, inter->init_scale);
+
+ gpuPushMatrix();
+ gpuMultMatrix(mat);
+ gpuTranslate3fv(arrow->manipulator.offset);
+
+ glEnable(GL_BLEND);
+ arrow_draw_geom(arrow, select, (const float [4]){0.5f, 0.5f, 0.5f, 0.5f});
+ glDisable(GL_BLEND);
+
+ gpuPopMatrix();
+ }
+}
+
+static void manipulator_arrow_render_3d_intersect(
+ const bContext *UNUSED(C), wmManipulator *manipulator,
+ int selectionbase)
+{
+ GPU_select_load_id(selectionbase);
+ arrow_draw_intern((ArrowManipulator3D *)manipulator, true, false);
+}
+
+static void manipulator_arrow_draw(const bContext *UNUSED(C), wmManipulator *manipulator)
+{
+ arrow_draw_intern((ArrowManipulator3D *)manipulator, false, (manipulator->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0);
+}
+
+/**
+ * Calculate arrow offset independent from prop min value,
+ * meaning the range will not be offset by min value first.
+ */
+static void manipulator_arrow_handler(bContext *C, wmManipulator *manipulator, const wmEvent *event, const int flag)
+{
+ ArrowManipulator3D *arrow = (ArrowManipulator3D *)manipulator;
+ ManipulatorInteraction *inter = manipulator->interaction_data;
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ float orig_origin[4];
+ float viewvec[3], tangent[3], plane[3];
+ float offset[4];
+ float m_diff[2];
+ float dir_2d[2], dir2d_final[2];
+ float facdir = 1.0f;
+ bool use_vertical = false;
+
+
+ copy_v3_v3(orig_origin, inter->init_origin);
+ orig_origin[3] = 1.0f;
+ add_v3_v3v3(offset, orig_origin, arrow->direction);
+ offset[3] = 1.0f;
+
+ /* calculate view vector */
+ if (rv3d->is_persp) {
+ sub_v3_v3v3(viewvec, orig_origin, rv3d->viewinv[3]);
+ }
+ else {
+ copy_v3_v3(viewvec, rv3d->viewinv[2]);
+ }
+ normalize_v3(viewvec);
+
+ /* first determine if view vector is really close to the direction. If it is, we use
+ * vertical movement to determine offset, just like transform system does */
+ if (RAD2DEG(acos(dot_v3v3(viewvec, arrow->direction))) > 5.0f) {
+ /* multiply to projection space */
+ mul_m4_v4(rv3d->persmat, orig_origin);
+ mul_v4_fl(orig_origin, 1.0f / orig_origin[3]);
+ mul_m4_v4(rv3d->persmat, offset);
+ mul_v4_fl(offset, 1.0f / offset[3]);
+
+ sub_v2_v2v2(dir_2d, offset, orig_origin);
+ dir_2d[0] *= ar->winx;
+ dir_2d[1] *= ar->winy;
+ normalize_v2(dir_2d);
+ }
+ else {
+ dir_2d[0] = 0.0f;
+ dir_2d[1] = 1.0f;
+ use_vertical = true;
+ }
+
+ /* find mouse difference */
+ m_diff[0] = event->mval[0] - inter->init_mval[0];
+ m_diff[1] = event->mval[1] - inter->init_mval[1];
+
+ /* project the displacement on the screen space arrow direction */
+ project_v2_v2v2(dir2d_final, m_diff, dir_2d);
+
+ float zfac = ED_view3d_calc_zfac(rv3d, orig_origin, NULL);
+ ED_view3d_win_to_delta(ar, dir2d_final, offset, zfac);
+
+ add_v3_v3v3(orig_origin, offset, inter->init_origin);
+
+ /* calculate view vector for the new position */
+ if (rv3d->is_persp) {
+ sub_v3_v3v3(viewvec, orig_origin, rv3d->viewinv[3]);
+ }
+ else {
+ copy_v3_v3(viewvec, rv3d->viewinv[2]);
+ }
+
+ normalize_v3(viewvec);
+ if (!use_vertical) {
+ float fac;
+ /* now find a plane parallel to the view vector so we can intersect with the arrow direction */
+ cross_v3_v3v3(tangent, viewvec, offset);
+ cross_v3_v3v3(plane, tangent, viewvec);
+ fac = dot_v3v3(plane, offset) / dot_v3v3(arrow->direction, plane);
+
+ facdir = (fac < 0.0) ? -1.0 : 1.0;
+ mul_v3_v3fl(offset, arrow->direction, fac);
+ }
+ else {
+ facdir = (m_diff[1] < 0.0) ? -1.0 : 1.0;
+ }
+
+
+ ManipulatorCommonData *data = &arrow->data;
+ const float ofs_new = facdir * len_v3(offset);
+ const int slot = ED_MANIPULATOR_ARROW_SLOT_OFS_WORLD_SPACE;
+
+ /* set the property for the operator and call its modal function */
+ if (manipulator->props[slot]) {
+ const bool constrained = arrow->style & ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED;
+ const bool inverted = arrow->style & ED_MANIPULATOR_ARROW_STYLE_INVERTED;
+ const bool use_precision = flag & WM_MANIPULATOR_TWEAK_PRECISE;
+ float value = manipulator_value_from_offset(data, inter, ofs_new, constrained, inverted, use_precision);
+
+ manipulator_property_value_set(C, manipulator, slot, value);
+ /* get clamped value */
+ value = manipulator_property_value_get(manipulator, slot);
+
+ data->offset = manipulator_offset_from_value(data, value, constrained, inverted);
+ }
+ else {
+ data->offset = ofs_new;
+ }
+
+ /* tag the region for redraw */
+ ED_region_tag_redraw(ar);
+ WM_event_add_mousemove(C);
+}
+
+
+static void manipulator_arrow_invoke(
+ bContext *UNUSED(C), wmManipulator *manipulator, const wmEvent *event)
+{
+ ArrowManipulator3D *arrow = (ArrowManipulator3D *)manipulator;
+ ManipulatorInteraction *inter = MEM_callocN(sizeof(ManipulatorInteraction), __func__);
+ PointerRNA ptr = manipulator->ptr[ED_MANIPULATOR_ARROW_SLOT_OFS_WORLD_SPACE];
+ PropertyRNA *prop = manipulator->props[ED_MANIPULATOR_ARROW_SLOT_OFS_WORLD_SPACE];
+
+ if (prop) {
+ inter->init_value = RNA_property_float_get(&ptr, prop);
+ }
+
+ inter->init_offset = arrow->data.offset;
+
+ inter->init_mval[0] = event->mval[0];
+ inter->init_mval[1] = event->mval[1];
+
+ inter->init_scale = manipulator->scale;
+
+ manipulator_arrow_get_final_pos(manipulator, inter->init_origin);
+
+ manipulator->interaction_data = inter;
+}
+
+static void manipulator_arrow_prop_data_update(wmManipulator *manipulator, const int slot)
+{
+ ArrowManipulator3D *arrow = (ArrowManipulator3D *)manipulator;
+ manipulator_property_data_update(
+ manipulator, &arrow->data, slot,
+ (arrow->style & ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED) != 0,
+ (arrow->style & ED_MANIPULATOR_ARROW_STYLE_INVERTED) != 0);
+}
+
+static void manipulator_arrow_exit(bContext *C, wmManipulator *manipulator, const bool cancel)
+{
+ if (!cancel)
+ return;
+
+ ArrowManipulator3D *arrow = (ArrowManipulator3D *)manipulator;
+ ManipulatorCommonData *data = &arrow->data;
+ ManipulatorInteraction *inter = manipulator->interaction_data;
+
+ manipulator_property_value_reset(C, manipulator, inter, ED_MANIPULATOR_ARROW_SLOT_OFS_WORLD_SPACE);
+ data->offset = inter->init_offset;
+}
+
+
+/* -------------------------------------------------------------------- */
+/** \name Arrow Manipulator API
+ *
+ * \{ */
+
+wmManipulator *ED_manipulator_arrow3d_new(wmManipulatorGroup *mgroup, const char *name, const int style)
+{
+ const wmManipulatorType *mpt = WM_manipulatortype_find("MANIPULATOR_WT_arrow_3d", false);
+ ArrowManipulator3D *arrow = (ArrowManipulator3D *)WM_manipulator_new(mpt, mgroup, name);
+
+ int real_style = style;
+
+ /* inverted only makes sense in a constrained arrow */
+ if (real_style & ED_MANIPULATOR_ARROW_STYLE_INVERTED) {
+ real_style |= ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED;
+ }
+
+ const float dir_default[3] = {0.0f, 0.0f, 1.0f};
+
+ arrow->manipulator.flag |= WM_MANIPULATOR_DRAW_ACTIVE;
+
+ arrow->style = real_style;
+ arrow->len = 1.0f;
+ arrow->data.range_fac = 1.0f;
+ copy_v3_v3(arrow->direction, dir_default);
+
+ return &arrow->manipulator;
+}
+
+/**
+ * Define direction the arrow will point towards
+ */
+void ED_manipulator_arrow3d_set_direction(wmManipulator *manipulator, const float direction[3])
+{
+ ArrowManipulator3D *arrow = (ArrowManipulator3D *)manipulator;
+
+ copy_v3_v3(arrow->direction, direction);
+ normalize_v3(arrow->direction);
+}
+
+/**
+ * Define up-direction of the arrow manipulator
+ */
+void ED_manipulator_arrow3d_set_up_vector(wmManipulator *manipulator, const float direction[3])
+{
+ ArrowManipulator3D *arrow = (ArrowManipulator3D *)manipulator;
+
+ if (direction) {
+ copy_v3_v3(arrow->up, direction);
+ normalize_v3(arrow->up);
+ arrow->flag |= ARROW_UP_VECTOR_SET;
+ }
+ else {
+ arrow->flag &= ~ARROW_UP_VECTOR_SET;
+ }
+}
+
+/**
+ * Define a custom arrow line length
+ */
+void ED_manipulator_arrow3d_set_line_len(wmManipulator *manipulator, const float len)
+{
+ ArrowManipulator3D *arrow = (ArrowManipulator3D *)manipulator;
+ arrow->len = len;
+}
+
+/**
+ * Define a custom property UI range
+ *
+ * \note Needs to be called before WM_manipulator_set_property!
+ */
+void ED_manipulator_arrow3d_set_ui_range(wmManipulator *manipulator, const float min, const float max)
+{
+ ArrowManipulator3D *arrow = (ArrowManipulator3D *)manipulator;
+
+ BLI_assert(min < max);
+ BLI_assert(!(arrow->manipulator.props[0] && "Make sure this function "
+ "is called before WM_manipulator_set_property"));
+
+ arrow->data.range = max - min;
+ arrow->data.min = min;
+ arrow->data.flag |= MANIPULATOR_CUSTOM_RANGE_SET;
+}
+
+/**
+ * Define a custom factor for arrow min/max distance
+ *
+ * \note Needs to be called before WM_manipulator_set_property!
+ */
+void ED_manipulator_arrow3d_set_range_fac(wmManipulator *manipulator, const float range_fac)
+{
+ ArrowManipulator3D *arrow = (ArrowManipulator3D *)manipulator;
+
+ BLI_assert(!(arrow->manipulator.props[0] && "Make sure this function "
+ "is called before WM_manipulator_set_property"));
+
+ arrow->data.range_fac = range_fac;
+}
+
+/**
+ * Define xy-aspect for arrow cone
+ */
+void ED_manipulator_arrow3d_cone_set_aspect(wmManipulator *manipulator, const float aspect[2])
+{
+ ArrowManipulator3D *arrow = (ArrowManipulator3D *)manipulator;
+
+ copy_v2_v2(arrow->aspect, aspect);
+}
+
+static void MANIPULATOR_WT_arrow_3d(wmManipulatorType *wt)
+{
+ /* identifiers */
+ wt->idname = "MANIPULATOR_WT_arrow_3d";
+
+ /* api callbacks */
+ wt->draw = manipulator_arrow_draw;
+ wt->draw_select = manipulator_arrow_render_3d_intersect;
+ wt->position_get = manipulator_arrow_get_final_pos;
+ wt->intersect = NULL;
+ wt->handler = manipulator_arrow_handler;
+ wt->invoke = manipulator_arrow_invoke;
+ wt->prop_data_update = manipulator_arrow_prop_data_update;
+ wt->exit = manipulator_arrow_exit;
+
+ wt->size = sizeof(ArrowManipulator3D);
+}
+
+void ED_manipulatortypes_arrow_3d(void)
+{
+ WM_manipulatortype_append(MANIPULATOR_WT_arrow_3d);
+}
+
+/** \} */ /* Arrow Manipulator API */
diff --git a/source/blender/editors/manipulator_library/cage2d_manipulator.c b/source/blender/editors/manipulator_library/cage2d_manipulator.c
new file mode 100644
index 00000000000..97b4e451bc7
--- /dev/null
+++ b/source/blender/editors/manipulator_library/cage2d_manipulator.c
@@ -0,0 +1,598 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file cage2d_manipulator.c
+ * \ingroup wm
+ *
+ * \name Cage Manipulator
+ *
+ * 2D Manipulator
+ *
+ * \brief Rectangular manipulator acting as a 'cage' around its content.
+ * Interacting scales or translates the manipulator.
+ */
+
+#include "BIF_gl.h"
+
+#include "BKE_context.h"
+
+#include "BLI_math.h"
+#include "BLI_rect.h"
+
+#include "DNA_manipulator_types.h"
+
+#include "ED_screen.h"
+#include "ED_manipulator_library.h"
+
+#include "GPU_matrix.h"
+#include "GPU_shader.h"
+#include "GPU_immediate.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/* own includes */
+//#include "wm_manipulator_wmapi.h"
+//#include "wm_manipulator_intern.h"
+
+
+/* wmManipulator->highlighted_part */
+enum {
+ ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_TRANSLATE = 1,
+ ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_SCALEX_LEFT = 2,
+ ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_SCALEX_RIGHT = 3,
+ ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_SCALEY_UP = 4,
+ ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_SCALEY_DOWN = 5
+};
+
+#define MANIPULATOR_RECT_MIN_WIDTH 15.0f
+#define MANIPULATOR_RESIZER_WIDTH 20.0f
+
+typedef struct RectTransformManipulator {
+ wmManipulator manipulator;
+ float w, h; /* dimensions of manipulator */
+ float rotation; /* rotation of the rectangle */
+ float scale[2]; /* scaling for the manipulator for non-destructive editing. */
+ int style;
+} RectTransformManipulator;
+
+
+/* -------------------------------------------------------------------- */
+
+static void rect_transform_draw_corners(
+ const rctf *r, const float offsetx, const float offsety, const float color[3])
+{
+ unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
+
+ immBegin(PRIM_LINES, 16);
+
+ immVertex2f(pos, r->xmin, r->ymin + offsety);
+ immVertex2f(pos, r->xmin, r->ymin);
+ immVertex2f(pos, r->xmin, r->ymin);
+ immVertex2f(pos, r->xmin + offsetx, r->ymin);
+
+ immVertex2f(pos, r->xmax, r->ymin + offsety);
+ immVertex2f(pos, r->xmax, r->ymin);
+ immVertex2f(pos, r->xmax, r->ymin);
+ immVertex2f(pos, r->xmax - offsetx, r->ymin);
+
+ immVertex2f(pos, r->xmax, r->ymax - offsety);
+ immVertex2f(pos, r->xmax, r->ymax);
+ immVertex2f(pos, r->xmax, r->ymax);
+ immVertex2f(pos, r->xmax - offsetx, r->ymax);
+
+ immVertex2f(pos, r->xmin, r->ymax - offsety);
+ immVertex2f(pos, r->xmin, r->ymax);
+ immVertex2f(pos, r->xmin, r->ymax);
+ immVertex2f(pos, r->xmin + offsetx, r->ymax);
+
+ immEnd();
+
+ immUnbindProgram();
+}
+
+static void rect_transform_draw_interaction(
+ const float col[4], const int highlighted,
+ const float half_w, const float half_h,
+ const float w, const float h, const float line_width)
+{
+ /* Why generate coordinates for 4 vertices, when we only use three? */
+ float verts[4][2];
+
+ switch (highlighted) {
+ case ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_SCALEX_LEFT:
+ verts[0][0] = -half_w + w;
+ verts[0][1] = -half_h;
+ verts[1][0] = -half_w;
+ verts[1][1] = -half_h;
+ verts[2][0] = -half_w;
+ verts[2][1] = half_h;
+ verts[3][0] = -half_w + w;
+ verts[3][1] = half_h;
+ break;
+
+ case ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_SCALEX_RIGHT:
+ verts[0][0] = half_w - w;
+ verts[0][1] = -half_h;
+ verts[1][0] = half_w;
+ verts[1][1] = -half_h;
+ verts[2][0] = half_w;
+ verts[2][1] = half_h;
+ verts[3][0] = half_w - w;
+ verts[3][1] = half_h;
+ break;
+
+ case ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_SCALEY_DOWN:
+ verts[0][0] = -half_w;
+ verts[0][1] = -half_h + h;
+ verts[1][0] = -half_w;
+ verts[1][1] = -half_h;
+ verts[2][0] = half_w;
+ verts[2][1] = -half_h;
+ verts[3][0] = half_w;
+ verts[3][1] = -half_h + h;
+ break;
+
+ case ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_SCALEY_UP:
+ verts[0][0] = -half_w;
+ verts[0][1] = half_h - h;
+ verts[1][0] = -half_w;
+ verts[1][1] = half_h;
+ verts[2][0] = half_w;
+ verts[2][1] = half_h;
+ verts[3][0] = half_w;
+ verts[3][1] = half_h - h;
+ break;
+
+ default:
+ return;
+ }
+
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ unsigned int color = VertexFormat_add_attrib(format, "color", COMP_F32, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
+ glLineWidth(line_width + 3.0);
+
+ immBegin(PRIM_LINE_STRIP, 3);
+ immAttrib3f(color, 0.0f, 0.0f, 0.0f);
+ immVertex2fv(pos, verts[0]);
+ immVertex2fv(pos, verts[1]);
+ immVertex2fv(pos, verts[2]);
+ immEnd();
+
+ glLineWidth(line_width);
+
+ immBegin(PRIM_LINE_STRIP, 3);
+ immAttrib3fv(color, col);
+ immVertex2fv(pos, verts[0]);
+ immVertex2fv(pos, verts[1]);
+ immVertex2fv(pos, verts[2]);
+ immEnd();
+
+ immUnbindProgram();
+}
+
+static void manipulator_rect_transform_draw(const bContext *UNUSED(C), wmManipulator *manipulator)
+{
+ RectTransformManipulator *cage = (RectTransformManipulator *)manipulator;
+ rctf r;
+ float w = cage->w;
+ float h = cage->h;
+ float aspx = 1.0f, aspy = 1.0f;
+ const float half_w = w / 2.0f;
+ const float half_h = h / 2.0f;
+
+ r.xmin = -half_w;
+ r.ymin = -half_h;
+ r.xmax = half_w;
+ r.ymax = half_h;
+
+ gpuPushMatrix();
+ gpuTranslate2f(manipulator->origin[0] + manipulator->offset[0],
+ manipulator->origin[1] + manipulator->offset[1]);
+ if (cage->style & ED_MANIPULATOR_RECT_TRANSFORM_STYLE_SCALE_UNIFORM)
+ gpuScaleUniform(cage->scale[0]);
+ else
+ gpuScale2fv(cage->scale);
+
+ if (w > h)
+ aspx = h / w;
+ else
+ aspy = w / h;
+ w = min_ff(aspx * w / MANIPULATOR_RESIZER_WIDTH, MANIPULATOR_RESIZER_WIDTH / cage->scale[0]);
+ h = min_ff(aspy * h / MANIPULATOR_RESIZER_WIDTH, MANIPULATOR_RESIZER_WIDTH /
+ ((cage->style & ED_MANIPULATOR_RECT_TRANSFORM_STYLE_SCALE_UNIFORM) ? cage->scale[0] : cage->scale[1]));
+
+ /* corner manipulators */
+ glLineWidth(cage->manipulator.line_width + 3.0f);
+
+ rect_transform_draw_corners(&r, w, h, (const float[3]){0, 0, 0});
+
+ /* corner manipulators */
+ glLineWidth(cage->manipulator.line_width);
+ rect_transform_draw_corners(&r, w, h, manipulator->col);
+
+ rect_transform_draw_interaction(manipulator->col, manipulator->highlighted_part, half_w, half_h,
+ w, h, cage->manipulator.line_width);
+
+ glLineWidth(1.0);
+ gpuPopMatrix();
+}
+
+static int manipulator_rect_transform_get_cursor(wmManipulator *manipulator)
+{
+ switch (manipulator->highlighted_part) {
+ case ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_TRANSLATE:
+ return BC_HANDCURSOR;
+ case ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_SCALEX_LEFT:
+ case ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_SCALEX_RIGHT:
+ return CURSOR_X_MOVE;
+ case ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_SCALEY_DOWN:
+ case ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_SCALEY_UP:
+ return CURSOR_Y_MOVE;
+ default:
+ return CURSOR_STD;
+ }
+}
+
+static int manipulator_rect_transform_intersect(
+ bContext *UNUSED(C), wmManipulator *manipulator, const wmEvent *event)
+{
+ RectTransformManipulator *cage = (RectTransformManipulator *)manipulator;
+ const float mouse[2] = {event->mval[0], event->mval[1]};
+ //float matrot[2][2];
+ float point_local[2];
+ float w = cage->w;
+ float h = cage->h;
+ float half_w = w / 2.0f;
+ float half_h = h / 2.0f;
+ float aspx = 1.0f, aspy = 1.0f;
+
+ /* rotate mouse in relation to the center and relocate it */
+ sub_v2_v2v2(point_local, mouse, manipulator->origin);
+ point_local[0] -= manipulator->offset[0];
+ point_local[1] -= manipulator->offset[1];
+ //rotate_m2(matrot, -cage->transform.rotation);
+
+ if (cage->style & ED_MANIPULATOR_RECT_TRANSFORM_STYLE_SCALE_UNIFORM)
+ mul_v2_fl(point_local, 1.0f / cage->scale[0]);
+ else {
+ point_local[0] /= cage->scale[0];
+ point_local[1] /= cage->scale[0];
+ }
+
+ if (cage->w > cage->h)
+ aspx = h / w;
+ else
+ aspy = w / h;
+ w = min_ff(aspx * w / MANIPULATOR_RESIZER_WIDTH, MANIPULATOR_RESIZER_WIDTH / cage->scale[0]);
+ h = min_ff(aspy * h / MANIPULATOR_RESIZER_WIDTH, MANIPULATOR_RESIZER_WIDTH /
+ ((cage->style & ED_MANIPULATOR_RECT_TRANSFORM_STYLE_SCALE_UNIFORM) ? cage->scale[0] : cage->scale[1]));
+
+
+ rctf r;
+
+ r.xmin = -half_w + w;
+ r.ymin = -half_h + h;
+ r.xmax = half_w - w;
+ r.ymax = half_h - h;
+
+ bool isect = BLI_rctf_isect_pt_v(&r, point_local);
+
+ if (isect)
+ return ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_TRANSLATE;
+
+ /* if manipulator does not have a scale intersection, don't do it */
+ if (cage->style & (ED_MANIPULATOR_RECT_TRANSFORM_STYLE_SCALE | ED_MANIPULATOR_RECT_TRANSFORM_STYLE_SCALE_UNIFORM)) {
+ r.xmin = -half_w;
+ r.ymin = -half_h;
+ r.xmax = -half_w + w;
+ r.ymax = half_h;
+
+ isect = BLI_rctf_isect_pt_v(&r, point_local);
+
+ if (isect)
+ return ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_SCALEX_LEFT;
+
+ r.xmin = half_w - w;
+ r.ymin = -half_h;
+ r.xmax = half_w;
+ r.ymax = half_h;
+
+ isect = BLI_rctf_isect_pt_v(&r, point_local);
+
+ if (isect)
+ return ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_SCALEX_RIGHT;
+
+ r.xmin = -half_w;
+ r.ymin = -half_h;
+ r.xmax = half_w;
+ r.ymax = -half_h + h;
+
+ isect = BLI_rctf_isect_pt_v(&r, point_local);
+
+ if (isect)
+ return ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_SCALEY_DOWN;
+
+ r.xmin = -half_w;
+ r.ymin = half_h - h;
+ r.xmax = half_w;
+ r.ymax = half_h;
+
+ isect = BLI_rctf_isect_pt_v(&r, point_local);
+
+ if (isect)
+ return ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_SCALEY_UP;
+ }
+
+ return 0;
+}
+
+typedef struct RectTransformInteraction {
+ float orig_mouse[2];
+ float orig_offset[2];
+ float orig_scale[2];
+} RectTransformInteraction;
+
+static bool manipulator_rect_transform_get_prop_value(wmManipulator *manipulator, const int slot, float *value)
+{
+ PropertyType type = RNA_property_type(manipulator->props[slot]);
+
+ if (type != PROP_FLOAT) {
+ fprintf(stderr, "Rect Transform manipulator can only be bound to float properties");
+ return false;
+ }
+ else {
+ if (slot == ED_MANIPULATOR_RECT_TX_SLOT_OFFSET) {
+ if (RNA_property_array_length(&manipulator->ptr[slot], manipulator->props[slot]) != 2) {
+ fprintf(stderr, "Rect Transform manipulator offset not only be bound to array float property");
+ return false;
+ }
+ RNA_property_float_get_array(&manipulator->ptr[slot], manipulator->props[slot], value);
+ }
+ else if (slot == ED_MANIPULATOR_RECT_TX_SLOT_SCALE) {
+ RectTransformManipulator *cage = (RectTransformManipulator *)manipulator;
+ if (cage->style & ED_MANIPULATOR_RECT_TRANSFORM_STYLE_SCALE_UNIFORM) {
+ *value = RNA_property_float_get(&manipulator->ptr[slot], manipulator->props[slot]);
+ }
+ else {
+ if (RNA_property_array_length(&manipulator->ptr[slot], manipulator->props[slot]) != 2) {
+ fprintf(stderr, "Rect Transform manipulator scale not only be bound to array float property");
+ return false;
+ }
+ RNA_property_float_get_array(&manipulator->ptr[slot], manipulator->props[slot], value);
+ }
+ }
+ }
+
+ return true;
+}
+
+static void manipulator_rect_transform_invoke(
+ bContext *UNUSED(C), wmManipulator *manipulator, const wmEvent *event)
+{
+ RectTransformManipulator *cage = (RectTransformManipulator *)manipulator;
+ RectTransformInteraction *data = MEM_callocN(sizeof(RectTransformInteraction), "cage_interaction");
+
+ copy_v2_v2(data->orig_offset, manipulator->offset);
+ copy_v2_v2(data->orig_scale, cage->scale);
+
+ data->orig_mouse[0] = event->mval[0];
+ data->orig_mouse[1] = event->mval[1];
+
+ manipulator->interaction_data = data;
+}
+
+static void manipulator_rect_transform_handler(
+ bContext *C, wmManipulator *manipulator, const wmEvent *event,
+ const int UNUSED(flag))
+{
+ RectTransformManipulator *cage = (RectTransformManipulator *)manipulator;
+ RectTransformInteraction *data = manipulator->interaction_data;
+ /* needed here as well in case clamping occurs */
+ const float orig_ofx = manipulator->offset[0], orig_ofy = manipulator->offset[1];
+
+ const float valuex = (event->mval[0] - data->orig_mouse[0]);
+ const float valuey = (event->mval[1] - data->orig_mouse[1]);
+
+
+ if (manipulator->highlighted_part == ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_TRANSLATE) {
+ manipulator->offset[0] = data->orig_offset[0] + valuex;
+ manipulator->offset[1] = data->orig_offset[1] + valuey;
+ }
+ else if (manipulator->highlighted_part == ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_SCALEX_LEFT) {
+ manipulator->offset[0] = data->orig_offset[0] + valuex / 2.0;
+ cage->scale[0] = (cage->w * data->orig_scale[0] - valuex) / cage->w;
+ }
+ else if (manipulator->highlighted_part == ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_SCALEX_RIGHT) {
+ manipulator->offset[0] = data->orig_offset[0] + valuex / 2.0;
+ cage->scale[0] = (cage->w * data->orig_scale[0] + valuex) / cage->w;
+ }
+ else if (manipulator->highlighted_part == ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_SCALEY_DOWN) {
+ manipulator->offset[1] = data->orig_offset[1] + valuey / 2.0;
+
+ if (cage->style & ED_MANIPULATOR_RECT_TRANSFORM_STYLE_SCALE_UNIFORM) {
+ cage->scale[0] = (cage->h * data->orig_scale[0] - valuey) / cage->h;
+ }
+ else {
+ cage->scale[1] = (cage->h * data->orig_scale[1] - valuey) / cage->h;
+ }
+ }
+ else if (manipulator->highlighted_part == ED_MANIPULATOR_RECT_TRANSFORM_INTERSECT_SCALEY_UP) {
+ manipulator->offset[1] = data->orig_offset[1] + valuey / 2.0;
+
+ if (cage->style & ED_MANIPULATOR_RECT_TRANSFORM_STYLE_SCALE_UNIFORM) {
+ cage->scale[0] = (cage->h * data->orig_scale[0] + valuey) / cage->h;
+ }
+ else {
+ cage->scale[1] = (cage->h * data->orig_scale[1] + valuey) / cage->h;
+ }
+ }
+
+ /* clamping - make sure manipulator is at least 5 pixels wide */
+ if (cage->style & ED_MANIPULATOR_RECT_TRANSFORM_STYLE_SCALE_UNIFORM) {
+ if (cage->scale[0] < MANIPULATOR_RECT_MIN_WIDTH / cage->h ||
+ cage->scale[0] < MANIPULATOR_RECT_MIN_WIDTH / cage->w)
+ {
+ cage->scale[0] = max_ff(MANIPULATOR_RECT_MIN_WIDTH / cage->h, MANIPULATOR_RECT_MIN_WIDTH / cage->w);
+ manipulator->offset[0] = orig_ofx;
+ manipulator->offset[1] = orig_ofy;
+ }
+ }
+ else {
+ if (cage->scale[0] < MANIPULATOR_RECT_MIN_WIDTH / cage->w) {
+ cage->scale[0] = MANIPULATOR_RECT_MIN_WIDTH / cage->w;
+ manipulator->offset[0] = orig_ofx;
+ }
+ if (cage->scale[1] < MANIPULATOR_RECT_MIN_WIDTH / cage->h) {
+ cage->scale[1] = MANIPULATOR_RECT_MIN_WIDTH / cage->h;
+ manipulator->offset[1] = orig_ofy;
+ }
+ }
+
+ if (manipulator->props[ED_MANIPULATOR_RECT_TX_SLOT_OFFSET]) {
+ PointerRNA ptr = manipulator->ptr[ED_MANIPULATOR_RECT_TX_SLOT_OFFSET];
+ PropertyRNA *prop = manipulator->props[ED_MANIPULATOR_RECT_TX_SLOT_OFFSET];
+
+ RNA_property_float_set_array(&ptr, prop, manipulator->offset);
+ RNA_property_update(C, &ptr, prop);
+ }
+
+ if (manipulator->props[ED_MANIPULATOR_RECT_TX_SLOT_SCALE]) {
+ PointerRNA ptr = manipulator->ptr[ED_MANIPULATOR_RECT_TX_SLOT_SCALE];
+ PropertyRNA *prop = manipulator->props[ED_MANIPULATOR_RECT_TX_SLOT_SCALE];
+
+ if (cage->style & ED_MANIPULATOR_RECT_TRANSFORM_STYLE_SCALE_UNIFORM) {
+ RNA_property_float_set(&ptr, prop, cage->scale[0]);
+ }
+ else {
+ RNA_property_float_set_array(&ptr, prop, cage->scale);
+ }
+ RNA_property_update(C, &ptr, prop);
+ }
+
+ /* tag the region for redraw */
+ ED_region_tag_redraw(CTX_wm_region(C));
+}
+
+static void manipulator_rect_transform_prop_data_update(wmManipulator *manipulator, const int slot)
+{
+ RectTransformManipulator *cage = (RectTransformManipulator *)manipulator;
+
+ if (slot == ED_MANIPULATOR_RECT_TX_SLOT_OFFSET)
+ manipulator_rect_transform_get_prop_value(manipulator, ED_MANIPULATOR_RECT_TX_SLOT_OFFSET, manipulator->offset);
+ if (slot == ED_MANIPULATOR_RECT_TX_SLOT_SCALE)
+ manipulator_rect_transform_get_prop_value(manipulator, ED_MANIPULATOR_RECT_TX_SLOT_SCALE, cage->scale);
+}
+
+static void manipulator_rect_transform_exit(bContext *C, wmManipulator *manipulator, const bool cancel)
+{
+ RectTransformManipulator *cage = (RectTransformManipulator *)manipulator;
+ RectTransformInteraction *data = manipulator->interaction_data;
+
+ if (!cancel)
+ return;
+
+ /* reset properties */
+ if (manipulator->props[ED_MANIPULATOR_RECT_TX_SLOT_OFFSET]) {
+ PointerRNA ptr = manipulator->ptr[ED_MANIPULATOR_RECT_TX_SLOT_OFFSET];
+ PropertyRNA *prop = manipulator->props[ED_MANIPULATOR_RECT_TX_SLOT_OFFSET];
+
+ RNA_property_float_set_array(&ptr, prop, data->orig_offset);
+ RNA_property_update(C, &ptr, prop);
+ }
+ if (manipulator->props[ED_MANIPULATOR_RECT_TX_SLOT_SCALE]) {
+ PointerRNA ptr = manipulator->ptr[ED_MANIPULATOR_RECT_TX_SLOT_SCALE];
+ PropertyRNA *prop = manipulator->props[ED_MANIPULATOR_RECT_TX_SLOT_SCALE];
+
+ if (cage->style & ED_MANIPULATOR_RECT_TRANSFORM_STYLE_SCALE_UNIFORM) {
+ RNA_property_float_set(&ptr, prop, data->orig_scale[0]);
+ }
+ else {
+ RNA_property_float_set_array(&ptr, prop, data->orig_scale);
+ }
+ RNA_property_update(C, &ptr, prop);
+ }
+}
+
+
+/* -------------------------------------------------------------------- */
+/** \name Cage Manipulator API
+ *
+ * \{ */
+
+wmManipulator *ED_manipulator_rect_transform_new(wmManipulatorGroup *mgroup, const char *name, const int style)
+{
+ const wmManipulatorType *mpt = WM_manipulatortype_find("MANIPULATOR_WT_cage", false);
+ RectTransformManipulator *cage = (RectTransformManipulator *)WM_manipulator_new(mpt, mgroup, name);
+
+ cage->manipulator.flag |= WM_MANIPULATOR_DRAW_ACTIVE;
+ cage->scale[0] = cage->scale[1] = 1.0f;
+ cage->style = style;
+
+ return &cage->manipulator;
+}
+
+void ED_manipulator_rect_transform_set_dimensions(wmManipulator *manipulator, const float width, const float height)
+{
+ RectTransformManipulator *cage = (RectTransformManipulator *)manipulator;
+ cage->w = width;
+ cage->h = height;
+}
+
+static void MANIPULATOR_WT_cage(wmManipulatorType *wt)
+{
+ /* identifiers */
+ wt->idname = "MANIPULATOR_WT_cage";
+
+ /* api callbacks */
+ wt->draw = manipulator_rect_transform_draw;
+ wt->invoke = manipulator_rect_transform_invoke;
+ wt->prop_data_update = manipulator_rect_transform_prop_data_update;
+ wt->handler = manipulator_rect_transform_handler;
+ wt->intersect = manipulator_rect_transform_intersect;
+ wt->exit = manipulator_rect_transform_exit;
+ wt->cursor_get = manipulator_rect_transform_get_cursor;
+
+ wt->prop_len_max = 2;
+
+ wt->size = sizeof(RectTransformManipulator);
+}
+
+void ED_manipulatortypes_cage_2d(void)
+{
+ WM_manipulatortype_append(MANIPULATOR_WT_cage);
+}
+
+/** \} */ // Cage Manipulator API
diff --git a/source/blender/editors/manipulator_library/dial3d_manipulator.c b/source/blender/editors/manipulator_library/dial3d_manipulator.c
new file mode 100644
index 00000000000..5097c8cab6f
--- /dev/null
+++ b/source/blender/editors/manipulator_library/dial3d_manipulator.c
@@ -0,0 +1,376 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file dial3d_manipulator.c
+ * \ingroup wm
+ *
+ * \name Dial Manipulator
+ *
+ * 3D Manipulator
+ *
+ * \brief Circle shaped manipulator for circular interaction.
+ * Currently no own handling, use with operator only.
+ */
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "BKE_context.h"
+
+#include "BLI_math.h"
+
+#include "DNA_manipulator_types.h"
+
+#include "ED_screen.h"
+#include "ED_view3d.h"
+#include "ED_manipulator_library.h"
+
+#include "GPU_select.h"
+
+#include "GPU_matrix.h"
+
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/* own includes */
+#include "manipulator_geometry.h"
+#include "manipulator_library_intern.h"
+
+/* to use custom dials exported to geom_dial_manipulator.c */
+// #define USE_MANIPULATOR_CUSTOM_DIAL
+
+typedef struct DialManipulator {
+ wmManipulator manipulator;
+ int style;
+ float direction[3];
+} DialManipulator;
+
+typedef struct DialInteraction {
+ float init_mval[2];
+
+ /* cache the last angle to detect rotations bigger than -/+ PI */
+ float last_angle;
+ /* number of full rotations */
+ int rotations;
+} DialInteraction;
+
+#define DIAL_WIDTH 1.0f
+#define DIAL_RESOLUTION 32
+
+/* -------------------------------------------------------------------- */
+
+static void dial_geom_draw(
+ const DialManipulator *dial, const float col[4], const bool select,
+ float axis_modal_mat[4][4], float clip_plane[4])
+{
+#ifdef USE_MANIPULATOR_CUSTOM_DIAL
+ UNUSED_VARS(dial, col, axis_modal_mat, clip_plane);
+ wm_manipulator_geometryinfo_draw(&wm_manipulator_geom_data_dial, select);
+#else
+ const bool filled = (dial->style == ED_MANIPULATOR_DIAL_STYLE_RING_FILLED);
+
+ glLineWidth(dial->manipulator.line_width);
+
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+
+ if (clip_plane) {
+ immBindBuiltinProgram(GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR);
+ float clip_plane_f[4] = {clip_plane[0], clip_plane[1], clip_plane[2], clip_plane[3]};
+ immUniform4fv("ClipPlane", clip_plane_f);
+ immUniformMatrix4fv("ModelMatrix", axis_modal_mat);
+ }
+ else {
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+
+ immUniformColor4fv(col);
+
+ if (filled) {
+ imm_draw_circle_fill(pos, 0, 0, 1.0, DIAL_RESOLUTION);
+ }
+ else {
+ imm_draw_circle_wire(pos, 0, 0, 1.0, DIAL_RESOLUTION);
+ }
+
+ immUnbindProgram();
+
+ UNUSED_VARS(select);
+#endif
+}
+
+/**
+ * Draws a line from (0, 0, 0) to \a co_outer, at \a angle.
+ */
+static void dial_ghostarc_draw_helpline(const float angle, const float co_outer[3], const float col[4])
+{
+ glLineWidth(1.0f);
+
+ gpuPushMatrix();
+ gpuRotate3f(RAD2DEGF(angle), 0.0f, 0.0f, -1.0f);
+
+ unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ immUniformColor4fv(col);
+
+ immBegin(PRIM_LINE_STRIP, 2);
+ immVertex3f(pos, 0.0f, 0.0f, 0.0f);
+ immVertex3fv(pos, co_outer);
+ immEnd();
+
+ immUnbindProgram();
+
+ gpuPopMatrix();
+}
+
+static void dial_ghostarc_draw(
+ const DialManipulator *dial, const float angle_ofs, const float angle_delta, const float color[4])
+{
+ const float width_inner = DIAL_WIDTH - dial->manipulator.line_width * 0.5f / U.manipulator_scale;
+
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv(color);
+ imm_draw_disk_partial_fill(
+ pos, 0, 0, 0.0, width_inner, DIAL_RESOLUTION, RAD2DEGF(angle_ofs), RAD2DEGF(angle_delta));
+ immUnbindProgram();
+}
+
+static void dial_ghostarc_get_angles(
+ const DialManipulator *dial, const wmEvent *event, const ARegion *ar,
+ float mat[4][4], const float co_outer[3],
+ float *r_start, float *r_delta)
+{
+ DialInteraction *inter = dial->manipulator.interaction_data;
+ const RegionView3D *rv3d = ar->regiondata;
+ const float mval[2] = {event->x - ar->winrct.xmin, event->y - ar->winrct.ymin};
+ bool inv = false;
+
+ /* we might need to invert the direction of the angles */
+ float view_vec[3], axis_vec[3];
+ ED_view3d_global_to_vector(rv3d, rv3d->twmat[3], view_vec);
+ normalize_v3_v3(axis_vec, dial->direction);
+ if (dot_v3v3(view_vec, axis_vec) < 0.0f) {
+ inv = true;
+ }
+
+ float co[3], origin2d[2], co2d[2];
+ mul_v3_project_m4_v3(co, mat, co_outer);
+ /* project 3d coordinats to 2d viewplane */
+ ED_view3d_project_float_global(ar, dial->manipulator.origin, origin2d, V3D_PROJ_TEST_NOP);
+ ED_view3d_project_float_global(ar, co, co2d, V3D_PROJ_TEST_NOP);
+
+ /* convert to manipulator relative space */
+ float rel_initmval[2], rel_mval[2], rel_co[2];
+ sub_v2_v2v2(rel_initmval, inter->init_mval, origin2d);
+ sub_v2_v2v2(rel_mval, mval, origin2d);
+ sub_v2_v2v2(rel_co, co2d, origin2d);
+
+ /* return angles */
+ const float start = angle_signed_v2v2(rel_co, rel_initmval) * (inv ? -1 : 1);
+ const float delta = angle_signed_v2v2(rel_initmval, rel_mval) * (inv ? -1 : 1);
+
+ /* Change of sign, we passed the 180 degree threshold. This means we need to add a turn
+ * to distinguish between transition from 0 to -1 and -PI to +PI, use comparison with PI/2.
+ * Logic taken from BLI_dial_angle */
+ if ((delta * inter->last_angle < 0.0f) &&
+ (fabsf(inter->last_angle) > (float)M_PI_2))
+ {
+ if (inter->last_angle < 0.0f)
+ inter->rotations--;
+ else
+ inter->rotations++;
+ }
+ inter->last_angle = delta;
+
+ *r_start = start;
+ *r_delta = fmod(delta + 2.0f * (float)M_PI * inter->rotations, 2 * (float)M_PI);
+}
+
+static void dial_draw_intern(
+ const bContext *C, DialManipulator *dial,
+ const bool select, const bool highlight, float clip_plane[4])
+{
+ float rot[3][3];
+ float mat[4][4];
+ const float up[3] = {0.0f, 0.0f, 1.0f};
+ float col[4];
+
+ BLI_assert(CTX_wm_area(C)->spacetype == SPACE_VIEW3D);
+
+ manipulator_color_get(&dial->manipulator, highlight, col);
+
+ rotation_between_vecs_to_mat3(rot, up, dial->direction);
+ copy_m4_m3(mat, rot);
+ copy_v3_v3(mat[3], dial->manipulator.origin);
+ mul_mat3_m4_fl(mat, dial->manipulator.scale);
+
+ gpuPushMatrix();
+ gpuMultMatrix(mat);
+ gpuTranslate3fv(dial->manipulator.offset);
+
+ /* draw rotation indicator arc first */
+ if ((dial->manipulator.flag & WM_MANIPULATOR_DRAW_VALUE) && (dial->manipulator.state & WM_MANIPULATOR_STATE_ACTIVE)) {
+ wmWindow *win = CTX_wm_window(C);
+ const float co_outer[4] = {0.0f, DIAL_WIDTH, 0.0f}; /* coordinate at which the arc drawing will be started */
+ float angle_ofs, angle_delta;
+
+ dial_ghostarc_get_angles(dial, win->eventstate, CTX_wm_region(C), mat, co_outer, &angle_ofs, &angle_delta);
+ /* draw! */
+ dial_ghostarc_draw(dial, angle_ofs, angle_delta, (const float [4]){0.8f, 0.8f, 0.8f, 0.4f});
+
+ dial_ghostarc_draw_helpline(angle_ofs, co_outer, col); /* starting position */
+ dial_ghostarc_draw_helpline(angle_ofs + angle_delta, co_outer, col); /* starting position + current value */
+ }
+
+ /* draw actual dial manipulator */
+ dial_geom_draw(dial, col, select, mat, clip_plane);
+
+ gpuPopMatrix();
+}
+
+static void manipulator_dial_render_3d_intersect(const bContext *C, wmManipulator *manipulator, int selectionbase)
+{
+ DialManipulator *dial = (DialManipulator *)manipulator;
+ float clip_plane_buf[4];
+ float *clip_plane = (dial->style == ED_MANIPULATOR_DIAL_STYLE_RING_CLIPPED) ? clip_plane_buf : NULL;
+
+ /* enable clipping if needed */
+ if (clip_plane) {
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ copy_v3_v3(clip_plane, rv3d->viewinv[2]);
+ clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], manipulator->origin);
+ glEnable(GL_CLIP_DISTANCE0);
+ }
+
+ GPU_select_load_id(selectionbase);
+ dial_draw_intern(C, dial, true, false, clip_plane);
+
+ if (clip_plane) {
+ glDisable(GL_CLIP_DISTANCE0);
+ }
+}
+
+static void manipulator_dial_draw(const bContext *C, wmManipulator *manipulator)
+{
+ DialManipulator *dial = (DialManipulator *)manipulator;
+ const bool active = manipulator->state & WM_MANIPULATOR_STATE_ACTIVE;
+ const bool highlight = (manipulator->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0;
+ float clip_plane_buf[4];
+ float *clip_plane = (!active && dial->style == ED_MANIPULATOR_DIAL_STYLE_RING_CLIPPED) ? clip_plane_buf : NULL;
+
+ /* enable clipping if needed */
+ if (clip_plane) {
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ copy_v3_v3(clip_plane, rv3d->viewinv[2]);
+ clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], manipulator->origin);
+ clip_plane[3] -= 0.02 * dial->manipulator.scale;
+
+ glEnable(GL_CLIP_DISTANCE0);
+ }
+
+ glEnable(GL_BLEND);
+ dial_draw_intern(C, dial, false, highlight, clip_plane);
+ glDisable(GL_BLEND);
+
+ if (clip_plane) {
+ glDisable(GL_CLIP_DISTANCE0);
+ }
+}
+
+static void manipulator_dial_invoke(
+ bContext *UNUSED(C), wmManipulator *manipulator, const wmEvent *event)
+{
+ DialInteraction *inter = MEM_callocN(sizeof(DialInteraction), __func__);
+
+ inter->init_mval[0] = event->mval[0];
+ inter->init_mval[1] = event->mval[1];
+
+ manipulator->interaction_data = inter;
+}
+
+
+/* -------------------------------------------------------------------- */
+/** \name Dial Manipulator API
+ *
+ * \{ */
+
+wmManipulator *ED_manipulator_dial3d_new(wmManipulatorGroup *mgroup, const char *name, const int style)
+{
+ const wmManipulatorType *mpt = WM_manipulatortype_find("MANIPULATOR_WT_dial", false);
+ DialManipulator *dial = (DialManipulator *)WM_manipulator_new(mpt, mgroup, name);
+
+ const float dir_default[3] = {0.0f, 0.0f, 1.0f};
+
+ dial->style = style;
+
+ /* defaults */
+ copy_v3_v3(dial->direction, dir_default);
+
+ return (wmManipulator *)dial;
+}
+
+/**
+ * Define up-direction of the dial manipulator
+ */
+void ED_manipulator_dial3d_set_up_vector(wmManipulator *manipulator, const float direction[3])
+{
+ DialManipulator *dial = (DialManipulator *)manipulator;
+
+ copy_v3_v3(dial->direction, direction);
+ normalize_v3(dial->direction);
+}
+
+static void MANIPULATOR_WT_dial_3d(wmManipulatorType *wt)
+{
+ /* identifiers */
+ wt->idname = "MANIPULATOR_WT_dial";
+
+ /* api callbacks */
+ wt->draw = manipulator_dial_draw;
+ wt->draw_select = manipulator_dial_render_3d_intersect;
+ wt->invoke = manipulator_dial_invoke;
+
+ wt->size = sizeof(DialManipulator);
+}
+
+void ED_manipulatortypes_dial_3d(void)
+{
+ WM_manipulatortype_append(MANIPULATOR_WT_dial_3d);
+}
+
+/** \} */ // Dial Manipulator API
diff --git a/source/blender/editors/manipulator_library/geom_arrow_manipulator.c b/source/blender/editors/manipulator_library/geom_arrow_manipulator.c
new file mode 100644
index 00000000000..73518e5ac38
--- /dev/null
+++ b/source/blender/editors/manipulator_library/geom_arrow_manipulator.c
@@ -0,0 +1,141 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file geom_arrow_manipulator.c
+ * \ingroup wm
+ */
+
+#include "manipulator_geometry.h"
+
+static float verts[][3] = {
+ {-0.000000, 0.012320, 0.000000},
+ {-0.000000, 0.012320, 0.974306},
+ {0.008711, 0.008711, 0.000000},
+ {0.008711, 0.008711, 0.974306},
+ {0.012320, -0.000000, 0.000000},
+ {0.012320, -0.000000, 0.974306},
+ {0.008711, -0.008711, 0.000000},
+ {0.008711, -0.008711, 0.974306},
+ {-0.000000, -0.012320, 0.000000},
+ {-0.000000, -0.012320, 0.974306},
+ {-0.008711, -0.008711, 0.000000},
+ {-0.008711, -0.008711, 0.974306},
+ {-0.012320, 0.000000, 0.000000},
+ {-0.012320, 0.000000, 0.974306},
+ {-0.008711, 0.008711, 0.000000},
+ {-0.008711, 0.008711, 0.974306},
+ {0.000000, 0.072555, 0.974306},
+ {0.051304, 0.051304, 0.974306},
+ {0.072555, -0.000000, 0.974306},
+ {0.051304, -0.051304, 0.974306},
+ {-0.000000, -0.072555, 0.974306},
+ {-0.051304, -0.051304, 0.974306},
+ {-0.072555, 0.000000, 0.974306},
+ {-0.051304, 0.051304, 0.974306},
+ {0.000000, -0.000000, 1.268098},
+};
+
+static float normals[][3] = {
+ {0.000000, 0.776360, -0.630238},
+ {0.000000, 0.594348, -0.804163},
+ {0.548967, 0.548967, -0.630238},
+ {0.420270, 0.420270, -0.804163},
+ {0.776360, 0.000000, -0.630238},
+ {0.594378, 0.000000, -0.804163},
+ {0.548967, -0.548967, -0.630238},
+ {0.420270, -0.420270, -0.804163},
+ {0.000000, -0.776360, -0.630238},
+ {0.000000, -0.594378, -0.804163},
+ {-0.548967, -0.548967, -0.630238},
+ {-0.420270, -0.420270, -0.804163},
+ {-0.776360, 0.000000, -0.630238},
+ {-0.594378, 0.000000, -0.804163},
+ {-0.548967, 0.548967, -0.630238},
+ {-0.420270, 0.420270, -0.804163},
+ {0.000000, 0.843226, -0.537492},
+ {0.596271, 0.596271, -0.537492},
+ {0.843226, 0.000000, -0.537492},
+ {0.596271, -0.596271, -0.537492},
+ {0.000000, -0.843226, -0.537492},
+ {-0.596271, -0.596271, -0.537492},
+ {-0.843226, 0.000000, -0.537492},
+ {-0.596271, 0.596271, -0.537492},
+ {0.000000, 0.000000, 1.000000},
+};
+
+static unsigned short indices[] = {
+ 1, 3, 2,
+ 3, 5, 4,
+ 5, 7, 6,
+ 7, 9, 8,
+ 9, 11, 10,
+ 11, 13, 12,
+ 5, 18, 19,
+ 15, 1, 0,
+ 13, 15, 14,
+ 6, 10, 14,
+ 11, 21, 22,
+ 7, 19, 20,
+ 13, 22, 23,
+ 3, 17, 18,
+ 9, 20, 21,
+ 15, 23, 16,
+ 1, 16, 17,
+ 23, 22, 24,
+ 21, 20, 24,
+ 19, 18, 24,
+ 17, 16, 24,
+ 16, 23, 24,
+ 22, 21, 24,
+ 20, 19, 24,
+ 18, 17, 24,
+ 0, 1, 2,
+ 2, 3, 4,
+ 4, 5, 6,
+ 6, 7, 8,
+ 8, 9, 10,
+ 10, 11, 12,
+ 7, 5, 19,
+ 14, 15, 0,
+ 12, 13, 14,
+ 14, 0, 2,
+ 2, 4, 6,
+ 6, 8, 10,
+ 10, 12, 14,
+ 14, 2, 6,
+ 13, 11, 22,
+ 9, 7, 20,
+ 15, 13, 23,
+ 5, 3, 18,
+ 11, 9, 21,
+ 1, 15, 16,
+ 3, 1, 17,
+};
+
+ManipulatorGeomInfo wm_manipulator_geom_data_arrow = {
+ .nverts = 25,
+ .ntris = 46,
+ .verts = verts,
+ .normals = normals,
+ .indices = indices,
+};
diff --git a/source/blender/editors/manipulator_library/geom_cube_manipulator.c b/source/blender/editors/manipulator_library/geom_cube_manipulator.c
new file mode 100644
index 00000000000..a79d9161e96
--- /dev/null
+++ b/source/blender/editors/manipulator_library/geom_cube_manipulator.c
@@ -0,0 +1,75 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file geom_cube_manipulator.c
+ * \ingroup wm
+ */
+
+#include "manipulator_geometry.h"
+
+static const float verts[][3] = {
+ {1.000000, 1.000000, -1.000000},
+ {1.000000, -1.000000, -1.000000},
+ {-1.000000, -1.000000, -1.000000},
+ {-1.000000, 1.000000, -1.000000},
+ {1.000000, 1.000000, 1.000000},
+ {0.999999, -1.000001, 1.000000},
+ {-1.000000, -1.000000, 1.000000},
+ {-1.000000, 1.000000, 1.000000},
+};
+
+static const float normals[][3] = {
+ {0.577349, 0.577349, -0.577349},
+ {0.577349, -0.577349, -0.577349},
+ {-0.577349, -0.577349, -0.577349},
+ {-0.577349, 0.577349, -0.577349},
+ {0.577349, 0.577349, 0.577349},
+ {0.577349, -0.577349, 0.577349},
+ {-0.577349, -0.577349, 0.577349},
+ {-0.577349, 0.577349, 0.577349},
+};
+
+static const unsigned short indices[] = {
+ 1, 2, 3,
+ 7, 6, 5,
+ 4, 5, 1,
+ 5, 6, 2,
+ 2, 6, 7,
+ 0, 3, 7,
+ 0, 1, 3,
+ 4, 7, 5,
+ 0, 4, 1,
+ 1, 5, 2,
+ 3, 2, 7,
+ 4, 0, 7,
+};
+
+ManipulatorGeomInfo wm_manipulator_geom_data_cube = {
+ .nverts = 8,
+ .ntris = 12,
+ .verts = verts,
+ .normals = normals,
+ .indices = indices,
+};
diff --git a/source/blender/editors/manipulator_library/geom_dial_manipulator.c b/source/blender/editors/manipulator_library/geom_dial_manipulator.c
new file mode 100644
index 00000000000..dbabe7ad136
--- /dev/null
+++ b/source/blender/editors/manipulator_library/geom_dial_manipulator.c
@@ -0,0 +1,813 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file geom_dial_manipulator.c
+ * \ingroup wm
+ */
+
+#include "manipulator_geometry.h"
+
+static const float verts[][3] = {
+ {1.034000, 0.000000, 0.000000},
+ {1.017000, 0.000000, 0.029445},
+ {0.983000, 0.000000, 0.029445},
+ {0.966000, 0.000000, 0.000000},
+ {0.983000, 0.000000, -0.029445},
+ {1.017000, 0.000000, -0.029445},
+ {1.014132, 0.201723, 0.000000},
+ {0.997459, 0.198407, 0.029445},
+ {0.964112, 0.191774, 0.029445},
+ {0.947439, 0.188457, 0.000000},
+ {0.964112, 0.191774, -0.029445},
+ {0.997459, 0.198407, -0.029445},
+ {0.955292, 0.395695, 0.000000},
+ {0.939586, 0.389189, 0.029445},
+ {0.908174, 0.376178, 0.029445},
+ {0.892468, 0.369672, 0.000000},
+ {0.908174, 0.376178, -0.029445},
+ {0.939586, 0.389189, -0.029445},
+ {0.859740, 0.574460, 0.000000},
+ {0.845605, 0.565015, 0.029445},
+ {0.817335, 0.546126, 0.029445},
+ {0.803200, 0.536681, 0.000000},
+ {0.817335, 0.546126, -0.029445},
+ {0.845605, 0.565015, -0.029445},
+ {0.731148, 0.731148, 0.000000},
+ {0.719128, 0.719128, 0.029445},
+ {0.695086, 0.695086, 0.029445},
+ {0.683065, 0.683065, 0.000000},
+ {0.695086, 0.695086, -0.029445},
+ {0.719128, 0.719128, -0.029445},
+ {0.574460, 0.859740, 0.000000},
+ {0.565015, 0.845605, 0.029445},
+ {0.546125, 0.817335, 0.029445},
+ {0.536681, 0.803200, 0.000000},
+ {0.546125, 0.817335, -0.029445},
+ {0.565015, 0.845605, -0.029445},
+ {0.395695, 0.955291, 0.000000},
+ {0.389189, 0.939585, 0.029445},
+ {0.376178, 0.908173, 0.029445},
+ {0.369672, 0.892467, 0.000000},
+ {0.376178, 0.908173, -0.029445},
+ {0.389189, 0.939585, -0.029445},
+ {0.201724, 1.014132, 0.000000},
+ {0.198407, 0.997459, 0.029445},
+ {0.191774, 0.964112, 0.029445},
+ {0.188457, 0.947439, 0.000000},
+ {0.191774, 0.964112, -0.029445},
+ {0.198407, 0.997459, -0.029445},
+ {0.000000, 1.034000, 0.000000},
+ {0.000000, 1.017000, 0.029445},
+ {0.000000, 0.983000, 0.029445},
+ {0.000000, 0.966000, 0.000000},
+ {0.000000, 0.983000, -0.029445},
+ {0.000000, 1.017000, -0.029445},
+ {-0.201723, 1.014132, 0.000000},
+ {-0.198407, 0.997459, 0.029445},
+ {-0.191774, 0.964112, 0.029445},
+ {-0.188457, 0.947439, 0.000000},
+ {-0.191774, 0.964112, -0.029445},
+ {-0.198407, 0.997459, -0.029445},
+ {-0.395695, 0.955291, 0.000000},
+ {-0.389189, 0.939585, 0.029445},
+ {-0.376178, 0.908174, 0.029445},
+ {-0.369672, 0.892468, 0.000000},
+ {-0.376178, 0.908174, -0.029445},
+ {-0.389189, 0.939585, -0.029445},
+ {-0.574459, 0.859740, 0.000000},
+ {-0.565015, 0.845605, 0.029445},
+ {-0.546125, 0.817335, 0.029445},
+ {-0.536681, 0.803200, 0.000000},
+ {-0.546125, 0.817335, -0.029445},
+ {-0.565015, 0.845605, -0.029445},
+ {-0.731149, 0.731148, 0.000000},
+ {-0.719128, 0.719127, 0.029445},
+ {-0.695086, 0.695086, 0.029445},
+ {-0.683065, 0.683065, 0.000000},
+ {-0.695086, 0.695086, -0.029445},
+ {-0.719128, 0.719127, -0.029445},
+ {-0.859740, 0.574460, 0.000000},
+ {-0.845604, 0.565015, 0.029445},
+ {-0.817335, 0.546126, 0.029445},
+ {-0.803200, 0.536681, 0.000000},
+ {-0.817335, 0.546126, -0.029445},
+ {-0.845604, 0.565015, -0.029445},
+ {-0.955291, 0.395695, 0.000000},
+ {-0.939585, 0.389189, 0.029445},
+ {-0.908173, 0.376178, 0.029445},
+ {-0.892468, 0.369672, 0.000000},
+ {-0.908173, 0.376178, -0.029445},
+ {-0.939585, 0.389189, -0.029445},
+ {-1.014132, 0.201723, 0.000000},
+ {-0.997459, 0.198407, 0.029445},
+ {-0.964112, 0.191774, 0.029445},
+ {-0.947439, 0.188457, 0.000000},
+ {-0.964112, 0.191774, -0.029445},
+ {-0.997459, 0.198407, -0.029445},
+ {-1.034000, 0.000000, 0.000000},
+ {-1.017000, 0.000000, 0.029445},
+ {-0.983000, 0.000000, 0.029445},
+ {-0.966000, 0.000000, 0.000000},
+ {-0.983000, 0.000000, -0.029445},
+ {-1.017000, 0.000000, -0.029445},
+ {-1.014132, -0.201723, 0.000000},
+ {-0.997459, -0.198407, 0.029445},
+ {-0.964112, -0.191774, 0.029445},
+ {-0.947439, -0.188457, 0.000000},
+ {-0.964112, -0.191774, -0.029445},
+ {-0.997459, -0.198407, -0.029445},
+ {-0.955292, -0.395694, 0.000000},
+ {-0.939586, -0.389189, 0.029445},
+ {-0.908174, -0.376177, 0.029445},
+ {-0.892468, -0.369672, 0.000000},
+ {-0.908174, -0.376177, -0.029445},
+ {-0.939586, -0.389189, -0.029445},
+ {-0.859740, -0.574460, 0.000000},
+ {-0.845604, -0.565015, 0.029445},
+ {-0.817335, -0.546126, 0.029445},
+ {-0.803200, -0.536681, 0.000000},
+ {-0.817335, -0.546126, -0.029445},
+ {-0.845604, -0.565015, -0.029445},
+ {-0.731149, -0.731148, 0.000000},
+ {-0.719128, -0.719127, 0.029445},
+ {-0.695086, -0.695086, 0.029445},
+ {-0.683065, -0.683065, 0.000000},
+ {-0.695086, -0.695086, -0.029445},
+ {-0.719128, -0.719127, -0.029445},
+ {-0.574460, -0.859739, 0.000000},
+ {-0.565015, -0.845604, 0.029445},
+ {-0.546126, -0.817334, 0.029445},
+ {-0.536681, -0.803199, 0.000000},
+ {-0.546126, -0.817334, -0.029445},
+ {-0.565015, -0.845604, -0.029445},
+ {-0.395695, -0.955291, 0.000000},
+ {-0.389189, -0.939585, 0.029445},
+ {-0.376178, -0.908174, 0.029445},
+ {-0.369672, -0.892468, 0.000000},
+ {-0.376178, -0.908174, -0.029445},
+ {-0.389189, -0.939585, -0.029445},
+ {-0.201724, -1.014132, 0.000000},
+ {-0.198407, -0.997459, 0.029445},
+ {-0.191774, -0.964112, 0.029445},
+ {-0.188458, -0.947438, 0.000000},
+ {-0.191774, -0.964112, -0.029445},
+ {-0.198407, -0.997459, -0.029445},
+ {0.000000, -1.034000, 0.000000},
+ {0.000000, -1.017000, 0.029445},
+ {0.000000, -0.983000, 0.029445},
+ {0.000000, -0.966000, 0.000000},
+ {0.000000, -0.983000, -0.029445},
+ {0.000000, -1.017000, -0.029445},
+ {0.201723, -1.014132, 0.000000},
+ {0.198407, -0.997459, 0.029445},
+ {0.191773, -0.964112, 0.029445},
+ {0.188457, -0.947439, 0.000000},
+ {0.191773, -0.964112, -0.029445},
+ {0.198407, -0.997459, -0.029445},
+ {0.395695, -0.955291, 0.000000},
+ {0.389189, -0.939585, 0.029445},
+ {0.376178, -0.908173, 0.029445},
+ {0.369672, -0.892467, 0.000000},
+ {0.376178, -0.908173, -0.029445},
+ {0.389189, -0.939585, -0.029445},
+ {0.574460, -0.859740, 0.000000},
+ {0.565015, -0.845605, 0.029445},
+ {0.546125, -0.817335, 0.029445},
+ {0.536681, -0.803200, 0.000000},
+ {0.546125, -0.817335, -0.029445},
+ {0.565015, -0.845605, -0.029445},
+ {0.731148, -0.731149, 0.000000},
+ {0.719127, -0.719128, 0.029445},
+ {0.695086, -0.695086, 0.029445},
+ {0.683065, -0.683066, 0.000000},
+ {0.695086, -0.695086, -0.029445},
+ {0.719127, -0.719128, -0.029445},
+ {0.859740, -0.574460, 0.000000},
+ {0.845605, -0.565015, 0.029445},
+ {0.817335, -0.546126, 0.029445},
+ {0.803200, -0.536681, 0.000000},
+ {0.817335, -0.546126, -0.029445},
+ {0.845605, -0.565015, -0.029445},
+ {0.955291, -0.395695, 0.000000},
+ {0.939585, -0.389189, 0.029445},
+ {0.908173, -0.376178, 0.029445},
+ {0.892467, -0.369673, 0.000000},
+ {0.908173, -0.376178, -0.029445},
+ {0.939585, -0.389189, -0.029445},
+ {1.014132, -0.201723, 0.000000},
+ {0.997459, -0.198407, 0.029445},
+ {0.964112, -0.191774, 0.029445},
+ {0.947439, -0.188457, 0.000000},
+ {0.964112, -0.191774, -0.029445},
+ {0.997459, -0.198407, -0.029445},
+};
+
+static const float normals[][3] = {
+ {1.000000, 0.000000, 0.000000},
+ {0.522691, 0.000000, 0.852504},
+ {-0.475845, 0.000000, 0.879513},
+ {-1.000000, 0.000000, 0.000000},
+ {-0.475845, 0.000000, -0.879513},
+ {0.522691, 0.000000, -0.852504},
+ {0.980773, 0.195074, 0.000000},
+ {0.512650, 0.101962, 0.852504},
+ {-0.466689, -0.092807, 0.879513},
+ {-0.980773, -0.195074, 0.000000},
+ {-0.466689, -0.092807, -0.879513},
+ {0.512650, 0.101962, -0.852504},
+ {0.923856, 0.382672, 0.000000},
+ {0.482894, 0.200018, 0.852504},
+ {-0.439619, -0.182073, 0.879513},
+ {-0.923856, -0.382672, 0.000000},
+ {-0.439619, -0.182073, -0.879513},
+ {0.482894, 0.200018, -0.852504},
+ {0.831446, 0.555559, 0.000000},
+ {0.434614, 0.290384, 0.852504},
+ {-0.395642, -0.264351, 0.879513},
+ {-0.831446, -0.555559, 0.000000},
+ {-0.395642, -0.264351, -0.879513},
+ {0.434614, 0.290384, -0.852504},
+ {0.707083, 0.707083, 0.000000},
+ {0.369610, 0.369610, 0.852504},
+ {-0.336467, -0.336467, 0.879513},
+ {-0.707083, -0.707083, 0.000000},
+ {-0.336467, -0.336467, -0.879513},
+ {0.369610, 0.369610, -0.852504},
+ {0.555559, 0.831446, 0.000000},
+ {0.290384, 0.434614, 0.852504},
+ {-0.264351, -0.395642, 0.879513},
+ {-0.555559, -0.831446, 0.000000},
+ {-0.264351, -0.395642, -0.879513},
+ {0.290384, 0.434614, -0.852504},
+ {0.382672, 0.923856, 0.000000},
+ {0.200018, 0.482894, 0.852504},
+ {-0.182073, -0.439619, 0.879513},
+ {-0.382672, -0.923856, 0.000000},
+ {-0.182073, -0.439619, -0.879513},
+ {0.200018, 0.482894, -0.852504},
+ {0.195074, 0.980773, 0.000000},
+ {0.101962, 0.512650, 0.852504},
+ {-0.092807, -0.466689, 0.879513},
+ {-0.195074, -0.980773, 0.000000},
+ {-0.092807, -0.466689, -0.879513},
+ {0.101962, 0.512650, -0.852504},
+ {0.000000, 1.000000, 0.000000},
+ {0.000000, 0.522691, 0.852504},
+ {0.000000, -0.475845, 0.879513},
+ {0.000000, -1.000000, 0.000000},
+ {0.000000, -0.475845, -0.879513},
+ {0.000000, 0.522691, -0.852504},
+ {-0.195074, 0.980773, 0.000000},
+ {-0.101962, 0.512650, 0.852504},
+ {0.092807, -0.466689, 0.879513},
+ {0.195074, -0.980773, 0.000000},
+ {0.092807, -0.466689, -0.879513},
+ {-0.101962, 0.512650, -0.852504},
+ {-0.382672, 0.923856, 0.000000},
+ {-0.200018, 0.482894, 0.852504},
+ {0.182073, -0.439619, 0.879513},
+ {0.382672, -0.923856, 0.000000},
+ {0.182073, -0.439619, -0.879513},
+ {-0.200018, 0.482894, -0.852504},
+ {-0.555559, 0.831446, 0.000000},
+ {-0.290384, 0.434614, 0.852504},
+ {0.264351, -0.395642, 0.879513},
+ {0.555559, -0.831446, 0.000000},
+ {0.264351, -0.395642, -0.879513},
+ {-0.290384, 0.434614, -0.852504},
+ {-0.707083, 0.707083, 0.000000},
+ {-0.369610, 0.369610, 0.852504},
+ {0.336467, -0.336467, 0.879513},
+ {0.707083, -0.707083, 0.000000},
+ {0.336467, -0.336467, -0.879513},
+ {-0.369610, 0.369610, -0.852504},
+ {-0.831446, 0.555559, 0.000000},
+ {-0.434614, 0.290384, 0.852504},
+ {0.395642, -0.264351, 0.879513},
+ {0.831446, -0.555559, 0.000000},
+ {0.395642, -0.264351, -0.879513},
+ {-0.434614, 0.290384, -0.852504},
+ {-0.923856, 0.382672, 0.000000},
+ {-0.482894, 0.200018, 0.852504},
+ {0.439619, -0.182073, 0.879513},
+ {0.923856, -0.382672, 0.000000},
+ {0.439619, -0.182073, -0.879513},
+ {-0.482894, 0.200018, -0.852504},
+ {-0.980773, 0.195074, 0.000000},
+ {-0.512650, 0.101962, 0.852504},
+ {0.466689, -0.092807, 0.879513},
+ {0.980773, -0.195074, 0.000000},
+ {0.466689, -0.092807, -0.879513},
+ {-0.512650, 0.101962, -0.852504},
+ {-1.000000, 0.000000, 0.000000},
+ {-0.522691, 0.000000, 0.852504},
+ {0.475845, 0.000000, 0.879513},
+ {1.000000, 0.000000, 0.000000},
+ {0.475845, 0.000000, -0.879513},
+ {-0.522691, 0.000000, -0.852504},
+ {-0.980773, -0.195074, 0.000000},
+ {-0.512650, -0.101962, 0.852504},
+ {0.466689, 0.092807, 0.879513},
+ {0.980773, 0.195074, 0.000000},
+ {0.466689, 0.092807, -0.879513},
+ {-0.512650, -0.101962, -0.852504},
+ {-0.923856, -0.382672, 0.000000},
+ {-0.482894, -0.200018, 0.852504},
+ {0.439619, 0.182073, 0.879513},
+ {0.923856, 0.382672, 0.000000},
+ {0.439619, 0.182073, -0.879513},
+ {-0.482894, -0.200018, -0.852504},
+ {-0.831446, -0.555559, 0.000000},
+ {-0.434614, -0.290384, 0.852504},
+ {0.395642, 0.264351, 0.879513},
+ {0.831446, 0.555559, 0.000000},
+ {0.395642, 0.264351, -0.879513},
+ {-0.434614, -0.290384, -0.852504},
+ {-0.707083, -0.707083, 0.000000},
+ {-0.369610, -0.369610, 0.852504},
+ {0.336467, 0.336467, 0.879513},
+ {0.707083, 0.707083, 0.000000},
+ {0.336467, 0.336467, -0.879513},
+ {-0.369610, -0.369610, -0.852504},
+ {-0.555559, -0.831446, 0.000000},
+ {-0.290384, -0.434614, 0.852504},
+ {0.264351, 0.395642, 0.879513},
+ {0.555559, 0.831446, 0.000000},
+ {0.264351, 0.395642, -0.879513},
+ {-0.290384, -0.434614, -0.852504},
+ {-0.382672, -0.923856, 0.000000},
+ {-0.200018, -0.482894, 0.852504},
+ {0.182073, 0.439619, 0.879513},
+ {0.382672, 0.923856, 0.000000},
+ {0.182073, 0.439619, -0.879513},
+ {-0.200018, -0.482894, -0.852504},
+ {-0.195074, -0.980773, 0.000000},
+ {-0.101962, -0.512650, 0.852504},
+ {0.092807, 0.466689, 0.879513},
+ {0.195074, 0.980773, 0.000000},
+ {0.092807, 0.466689, -0.879513},
+ {-0.101962, -0.512650, -0.852504},
+ {0.000000, -1.000000, 0.000000},
+ {0.000000, -0.522691, 0.852504},
+ {0.000000, 0.475845, 0.879513},
+ {0.000000, 1.000000, 0.000000},
+ {0.000000, 0.475845, -0.879513},
+ {0.000000, -0.522691, -0.852504},
+ {0.195074, -0.980773, 0.000000},
+ {0.101962, -0.512650, 0.852504},
+ {-0.092807, 0.466689, 0.879513},
+ {-0.195074, 0.980773, 0.000000},
+ {-0.092807, 0.466689, -0.879513},
+ {0.101962, -0.512650, -0.852504},
+ {0.382672, -0.923856, 0.000000},
+ {0.200018, -0.482894, 0.852504},
+ {-0.182073, 0.439619, 0.879513},
+ {-0.382672, 0.923856, 0.000000},
+ {-0.182073, 0.439619, -0.879513},
+ {0.200018, -0.482894, -0.852504},
+ {0.555559, -0.831446, 0.000000},
+ {0.290384, -0.434614, 0.852504},
+ {-0.264351, 0.395642, 0.879513},
+ {-0.555559, 0.831446, 0.000000},
+ {-0.264351, 0.395642, -0.879513},
+ {0.290384, -0.434614, -0.852504},
+ {0.707083, -0.707083, 0.000000},
+ {0.369610, -0.369610, 0.852504},
+ {-0.336467, 0.336467, 0.879513},
+ {-0.707083, 0.707083, 0.000000},
+ {-0.336467, 0.336467, -0.879513},
+ {0.369610, -0.369610, -0.852504},
+ {0.831446, -0.555559, 0.000000},
+ {0.434614, -0.290384, 0.852504},
+ {-0.395642, 0.264351, 0.879513},
+ {-0.831446, 0.555559, 0.000000},
+ {-0.395642, 0.264351, -0.879513},
+ {0.434614, -0.290384, -0.852504},
+ {0.923856, -0.382672, 0.000000},
+ {0.482894, -0.200018, 0.852504},
+ {-0.439619, 0.182073, 0.879513},
+ {-0.923856, 0.382672, 0.000000},
+ {-0.439619, 0.182073, -0.879513},
+ {0.482894, -0.200018, -0.852504},
+ {0.980773, -0.195074, 0.000000},
+ {0.512650, -0.101962, 0.852504},
+ {-0.466689, 0.092807, 0.879513},
+ {-0.980773, 0.195074, 0.000000},
+ {-0.466689, 0.092807, -0.879513},
+ {0.512650, -0.101962, -0.852504},
+};
+
+static const unsigned short indices[] = {
+ 6, 7, 1,
+ 7, 8, 2,
+ 8, 9, 3,
+ 9, 10, 4,
+ 10, 11, 5,
+ 5, 11, 6,
+ 12, 13, 7,
+ 13, 14, 8,
+ 14, 15, 9,
+ 15, 16, 10,
+ 16, 17, 11,
+ 11, 17, 12,
+ 18, 19, 13,
+ 13, 19, 20,
+ 20, 21, 15,
+ 15, 21, 22,
+ 22, 23, 17,
+ 17, 23, 18,
+ 24, 25, 19,
+ 19, 25, 26,
+ 26, 27, 21,
+ 21, 27, 28,
+ 28, 29, 23,
+ 23, 29, 24,
+ 30, 31, 25,
+ 25, 31, 32,
+ 26, 32, 33,
+ 27, 33, 34,
+ 34, 35, 29,
+ 29, 35, 30,
+ 36, 37, 31,
+ 31, 37, 38,
+ 38, 39, 33,
+ 39, 40, 34,
+ 40, 41, 35,
+ 35, 41, 36,
+ 36, 42, 43,
+ 43, 44, 38,
+ 44, 45, 39,
+ 45, 46, 40,
+ 46, 47, 41,
+ 47, 42, 36,
+ 48, 49, 43,
+ 49, 50, 44,
+ 50, 51, 45,
+ 51, 52, 46,
+ 52, 53, 47,
+ 47, 53, 48,
+ 54, 55, 49,
+ 49, 55, 56,
+ 50, 56, 57,
+ 57, 58, 52,
+ 58, 59, 53,
+ 53, 59, 54,
+ 60, 61, 55,
+ 55, 61, 62,
+ 56, 62, 63,
+ 63, 64, 58,
+ 64, 65, 59,
+ 59, 65, 60,
+ 66, 67, 61,
+ 61, 67, 68,
+ 68, 69, 63,
+ 69, 70, 64,
+ 70, 71, 65,
+ 71, 66, 60,
+ 72, 73, 67,
+ 73, 74, 68,
+ 68, 74, 75,
+ 75, 76, 70,
+ 76, 77, 71,
+ 71, 77, 72,
+ 78, 79, 73,
+ 79, 80, 74,
+ 74, 80, 81,
+ 81, 82, 76,
+ 82, 83, 77,
+ 83, 78, 72,
+ 78, 84, 85,
+ 85, 86, 80,
+ 80, 86, 87,
+ 87, 88, 82,
+ 82, 88, 89,
+ 89, 84, 78,
+ 90, 91, 85,
+ 91, 92, 86,
+ 86, 92, 93,
+ 93, 94, 88,
+ 88, 94, 95,
+ 95, 90, 84,
+ 96, 97, 91,
+ 97, 98, 92,
+ 98, 99, 93,
+ 99, 100, 94,
+ 100, 101, 95,
+ 101, 96, 90,
+ 102, 103, 97,
+ 103, 104, 98,
+ 104, 105, 99,
+ 99, 105, 106,
+ 106, 107, 101,
+ 101, 107, 102,
+ 108, 109, 103,
+ 103, 109, 110,
+ 110, 111, 105,
+ 105, 111, 112,
+ 112, 113, 107,
+ 107, 113, 108,
+ 114, 115, 109,
+ 115, 116, 110,
+ 116, 117, 111,
+ 111, 117, 118,
+ 112, 118, 119,
+ 113, 119, 114,
+ 114, 120, 121,
+ 121, 122, 116,
+ 122, 123, 117,
+ 117, 123, 124,
+ 124, 125, 119,
+ 125, 120, 114,
+ 126, 127, 121,
+ 121, 127, 128,
+ 128, 129, 123,
+ 123, 129, 130,
+ 130, 131, 125,
+ 125, 131, 126,
+ 132, 133, 127,
+ 133, 134, 128,
+ 128, 134, 135,
+ 135, 136, 130,
+ 136, 137, 131,
+ 131, 137, 132,
+ 132, 138, 139,
+ 133, 139, 140,
+ 134, 140, 141,
+ 141, 142, 136,
+ 142, 143, 137,
+ 143, 138, 132,
+ 138, 144, 145,
+ 139, 145, 146,
+ 146, 147, 141,
+ 141, 147, 148,
+ 148, 149, 143,
+ 149, 144, 138,
+ 144, 150, 151,
+ 151, 152, 146,
+ 146, 152, 153,
+ 153, 154, 148,
+ 154, 155, 149,
+ 155, 150, 144,
+ 156, 157, 151,
+ 151, 157, 158,
+ 158, 159, 153,
+ 159, 160, 154,
+ 160, 161, 155,
+ 155, 161, 156,
+ 156, 162, 163,
+ 163, 164, 158,
+ 158, 164, 165,
+ 165, 166, 160,
+ 160, 166, 167,
+ 167, 162, 156,
+ 162, 168, 169,
+ 169, 170, 164,
+ 164, 170, 171,
+ 165, 171, 172,
+ 166, 172, 173,
+ 173, 168, 162,
+ 174, 175, 169,
+ 175, 176, 170,
+ 170, 176, 177,
+ 177, 178, 172,
+ 172, 178, 179,
+ 173, 179, 174,
+ 174, 180, 181,
+ 181, 182, 176,
+ 176, 182, 183,
+ 183, 184, 178,
+ 178, 184, 185,
+ 179, 185, 180,
+ 186, 187, 181,
+ 187, 188, 182,
+ 188, 189, 183,
+ 183, 189, 190,
+ 190, 191, 185,
+ 191, 186, 180,
+ 0, 1, 187,
+ 1, 2, 188,
+ 2, 3, 189,
+ 3, 4, 190,
+ 190, 4, 5,
+ 191, 5, 0,
+ 0, 6, 1,
+ 1, 7, 2,
+ 2, 8, 3,
+ 3, 9, 4,
+ 4, 10, 5,
+ 0, 5, 6,
+ 6, 12, 7,
+ 7, 13, 8,
+ 8, 14, 9,
+ 9, 15, 10,
+ 10, 16, 11,
+ 6, 11, 12,
+ 12, 18, 13,
+ 14, 13, 20,
+ 14, 20, 15,
+ 16, 15, 22,
+ 16, 22, 17,
+ 12, 17, 18,
+ 18, 24, 19,
+ 20, 19, 26,
+ 20, 26, 21,
+ 22, 21, 28,
+ 22, 28, 23,
+ 18, 23, 24,
+ 24, 30, 25,
+ 26, 25, 32,
+ 27, 26, 33,
+ 28, 27, 34,
+ 28, 34, 29,
+ 24, 29, 30,
+ 30, 36, 31,
+ 32, 31, 38,
+ 32, 38, 33,
+ 33, 39, 34,
+ 34, 40, 35,
+ 30, 35, 36,
+ 37, 36, 43,
+ 37, 43, 38,
+ 38, 44, 39,
+ 39, 45, 40,
+ 40, 46, 41,
+ 41, 47, 36,
+ 42, 48, 43,
+ 43, 49, 44,
+ 44, 50, 45,
+ 45, 51, 46,
+ 46, 52, 47,
+ 42, 47, 48,
+ 48, 54, 49,
+ 50, 49, 56,
+ 51, 50, 57,
+ 51, 57, 52,
+ 52, 58, 53,
+ 48, 53, 54,
+ 54, 60, 55,
+ 56, 55, 62,
+ 57, 56, 63,
+ 57, 63, 58,
+ 58, 64, 59,
+ 54, 59, 60,
+ 60, 66, 61,
+ 62, 61, 68,
+ 62, 68, 63,
+ 63, 69, 64,
+ 64, 70, 65,
+ 65, 71, 60,
+ 66, 72, 67,
+ 67, 73, 68,
+ 69, 68, 75,
+ 69, 75, 70,
+ 70, 76, 71,
+ 66, 71, 72,
+ 72, 78, 73,
+ 73, 79, 74,
+ 75, 74, 81,
+ 75, 81, 76,
+ 76, 82, 77,
+ 77, 83, 72,
+ 79, 78, 85,
+ 79, 85, 80,
+ 81, 80, 87,
+ 81, 87, 82,
+ 83, 82, 89,
+ 83, 89, 78,
+ 84, 90, 85,
+ 85, 91, 86,
+ 87, 86, 93,
+ 87, 93, 88,
+ 89, 88, 95,
+ 89, 95, 84,
+ 90, 96, 91,
+ 91, 97, 92,
+ 92, 98, 93,
+ 93, 99, 94,
+ 94, 100, 95,
+ 95, 101, 90,
+ 96, 102, 97,
+ 97, 103, 98,
+ 98, 104, 99,
+ 100, 99, 106,
+ 100, 106, 101,
+ 96, 101, 102,
+ 102, 108, 103,
+ 104, 103, 110,
+ 104, 110, 105,
+ 106, 105, 112,
+ 106, 112, 107,
+ 102, 107, 108,
+ 108, 114, 109,
+ 109, 115, 110,
+ 110, 116, 111,
+ 112, 111, 118,
+ 113, 112, 119,
+ 108, 113, 114,
+ 115, 114, 121,
+ 115, 121, 116,
+ 116, 122, 117,
+ 118, 117, 124,
+ 118, 124, 119,
+ 119, 125, 114,
+ 120, 126, 121,
+ 122, 121, 128,
+ 122, 128, 123,
+ 124, 123, 130,
+ 124, 130, 125,
+ 120, 125, 126,
+ 126, 132, 127,
+ 127, 133, 128,
+ 129, 128, 135,
+ 129, 135, 130,
+ 130, 136, 131,
+ 126, 131, 132,
+ 133, 132, 139,
+ 134, 133, 140,
+ 135, 134, 141,
+ 135, 141, 136,
+ 136, 142, 137,
+ 137, 143, 132,
+ 139, 138, 145,
+ 140, 139, 146,
+ 140, 146, 141,
+ 142, 141, 148,
+ 142, 148, 143,
+ 143, 149, 138,
+ 145, 144, 151,
+ 145, 151, 146,
+ 147, 146, 153,
+ 147, 153, 148,
+ 148, 154, 149,
+ 149, 155, 144,
+ 150, 156, 151,
+ 152, 151, 158,
+ 152, 158, 153,
+ 153, 159, 154,
+ 154, 160, 155,
+ 150, 155, 156,
+ 157, 156, 163,
+ 157, 163, 158,
+ 159, 158, 165,
+ 159, 165, 160,
+ 161, 160, 167,
+ 161, 167, 156,
+ 163, 162, 169,
+ 163, 169, 164,
+ 165, 164, 171,
+ 166, 165, 172,
+ 167, 166, 173,
+ 167, 173, 162,
+ 168, 174, 169,
+ 169, 175, 170,
+ 171, 170, 177,
+ 171, 177, 172,
+ 173, 172, 179,
+ 168, 173, 174,
+ 175, 174, 181,
+ 175, 181, 176,
+ 177, 176, 183,
+ 177, 183, 178,
+ 179, 178, 185,
+ 174, 179, 180,
+ 180, 186, 181,
+ 181, 187, 182,
+ 182, 188, 183,
+ 184, 183, 190,
+ 184, 190, 185,
+ 185, 191, 180,
+ 186, 0, 187,
+ 187, 1, 188,
+ 188, 2, 189,
+ 189, 3, 190,
+ 191, 190, 5,
+ 186, 191, 0,
+};
+
+ManipulatorGeomInfo wm_manipulator_geom_data_dial = {
+ .nverts = 192,
+ .ntris = 384,
+ .verts = verts,
+ .normals = normals,
+ .indices = indices,
+};
diff --git a/source/blender/editors/manipulator_library/manipulator_draw_utils.c b/source/blender/editors/manipulator_library/manipulator_draw_utils.c
new file mode 100644
index 00000000000..fc7b22ac0f0
--- /dev/null
+++ b/source/blender/editors/manipulator_library/manipulator_draw_utils.c
@@ -0,0 +1,127 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file manipulator_draw_utils.c
+ * \ingroup wm
+ */
+
+#include "BKE_context.h"
+
+#include "BLI_listbase.h"
+#include "BLI_ghash.h"
+#include "BLI_math.h"
+#include "BLI_string.h"
+#include "BLI_string_utils.h"
+
+#include "DNA_manipulator_types.h"
+
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "GPU_batch.h"
+#include "GPU_glew.h"
+#include "GPU_immediate.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/* only for own init/exit calls (wm_manipulatortype_init/wm_manipulatortype_free) */
+#include "wm.h"
+
+/* own includes */
+#include "manipulator_library_intern.h"
+
+/**
+ * Main draw call for ManipulatorGeomInfo data
+ */
+void wm_manipulator_geometryinfo_draw(const ManipulatorGeomInfo *info, const bool select, const float color[4])
+{
+ /* TODO store the Batches inside the ManipulatorGeomInfo and updated it when geom changes
+ * So we don't need to re-created and discard it every time */
+
+ const bool use_lighting = true || (!select && ((U.manipulator_flag & V3D_SHADED_MANIPULATORS) != 0));
+ VertexBuffer *vbo;
+ ElementList *el;
+ Batch *batch;
+ ElementListBuilder elb = {0};
+
+ VertexFormat format = {0};
+ unsigned int pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
+ unsigned int nor_id;
+
+ if (use_lighting) {
+ nor_id = VertexFormat_add_attrib(&format, "nor", COMP_I16, 3, NORMALIZE_INT_TO_FLOAT);
+ }
+
+ /* Elements */
+ ElementListBuilder_init(&elb, PRIM_TRIANGLES, info->ntris, info->nverts);
+ for (int i = 0; i < info->ntris; ++i) {
+ const unsigned short *idx = &info->indices[i * 3];
+ add_triangle_vertices(&elb, idx[0], idx[1], idx[2]);
+ }
+ el = ElementList_build(&elb);
+
+ vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, info->nverts);
+
+ VertexBuffer_fill_attrib(vbo, pos_id, info->verts);
+
+ if (use_lighting) {
+ /* Normals are expected to be smooth. */
+ VertexBuffer_fill_attrib(vbo, nor_id, info->normals);
+ }
+
+ batch = Batch_create(PRIM_TRIANGLES, vbo, el);
+ Batch_set_builtin_program(batch, GPU_SHADER_3D_UNIFORM_COLOR);
+
+ Batch_Uniform4fv(batch, "color", color);
+
+ glEnable(GL_CULL_FACE);
+ // glEnable(GL_DEPTH_TEST);
+
+ Batch_draw(batch);
+
+ glDisable(GL_DEPTH_TEST);
+ // glDisable(GL_CULL_FACE);
+
+
+ Batch_discard_all(batch);
+}
+
+void wm_manipulator_vec_draw(
+ const float color[4], const float (*verts)[3], unsigned int vert_count,
+ unsigned int pos, unsigned int primitive_type)
+{
+ immUniformColor4fv(color);
+ immBegin(primitive_type, vert_count);
+ for (int i = 0; i < vert_count; i++) {
+ immVertex3fv(pos, verts[i]);
+ }
+ immEnd();
+}
diff --git a/source/blender/editors/manipulator_library/manipulator_geometry.h b/source/blender/editors/manipulator_library/manipulator_geometry.h
new file mode 100644
index 00000000000..0eff1ca89d8
--- /dev/null
+++ b/source/blender/editors/manipulator_library/manipulator_geometry.h
@@ -0,0 +1,51 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file manipulator_geometry.h
+ * \ingroup wm
+ *
+ * \name Manipulator Geometry
+ *
+ * \brief Prototypes for arrays defining the manipulator geometry. The actual definitions can be found in files usually
+ * called geom_xxx_manipulator.c
+ */
+
+
+#ifndef __MANIPULATOR_GEOMETRY_H__
+#define __MANIPULATOR_GEOMETRY_H__
+
+typedef struct ManipulatorGeomInfo {
+ int nverts;
+ int ntris;
+ const float (*verts)[3];
+ const float (*normals)[3];
+ const unsigned short *indices;
+} ManipulatorGeomInfo;
+
+/* arrow manipulator */
+extern ManipulatorGeomInfo wm_manipulator_geom_data_arrow;
+
+/* cube manipulator */
+extern ManipulatorGeomInfo wm_manipulator_geom_data_cube;
+
+#endif /* __MANIPULATOR_GEOMETRY_H__ */
diff --git a/source/blender/editors/manipulator_library/manipulator_library_intern.h b/source/blender/editors/manipulator_library/manipulator_library_intern.h
new file mode 100644
index 00000000000..c2d750deee0
--- /dev/null
+++ b/source/blender/editors/manipulator_library/manipulator_library_intern.h
@@ -0,0 +1,111 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file manipulator_library_intern.h
+ * \ingroup wm
+ */
+
+#ifndef __MANIPULATOR_LIBRARY_INTERN_H__
+#define __MANIPULATOR_LIBRARY_INTERN_H__
+
+/* distance around which manipulators respond to input (and get highlighted) */
+#define MANIPULATOR_HOTSPOT 14.0f
+
+/**
+ * Data for common interactions. Used in manipulator_library_utils.c functions.
+ */
+typedef struct ManipulatorCommonData {
+ int flag;
+
+ float range_fac; /* factor for arrow min/max distance */
+ float offset;
+
+ /* property range for constrained manipulators */
+ float range;
+ /* min/max value for constrained manipulators */
+ float min, max;
+} ManipulatorCommonData;
+
+typedef struct ManipulatorInteraction {
+ float init_value; /* initial property value */
+ float init_origin[3];
+ float init_mval[2];
+ float init_offset;
+ float init_scale;
+
+ /* offset of last handling step */
+ float prev_offset;
+ /* Total offset added by precision tweaking.
+ * Needed to allow toggling precision on/off without causing jumps */
+ float precision_offset;
+} ManipulatorInteraction;
+
+/* ManipulatorCommonData->flag */
+enum {
+ MANIPULATOR_CUSTOM_RANGE_SET = (1 << 0),
+};
+
+
+float manipulator_offset_from_value(
+ ManipulatorCommonData *data, const float value,
+ const bool constrained, const bool inverted);
+float manipulator_value_from_offset(
+ ManipulatorCommonData *data, ManipulatorInteraction *inter, const float offset,
+ const bool constrained, const bool inverted, const bool use_precision);
+
+void manipulator_property_data_update(
+ struct wmManipulator *manipulator, ManipulatorCommonData *data, const int slot,
+ const bool constrained, const bool inverted);
+
+void manipulator_property_value_set(
+ bContext *C, const struct wmManipulator *manipulator,
+ const int slot, const float value);
+float manipulator_property_value_get(
+ const struct wmManipulator *manipulator, const int slot);
+void manipulator_property_value_reset(
+ bContext *C, const struct wmManipulator *manipulator, ManipulatorInteraction *inter,
+ const int slot);
+
+
+/* -------------------------------------------------------------------- */
+
+void manipulator_color_get(
+ const struct wmManipulator *manipulator, const bool highlight,
+ float r_col[]);
+
+
+/* -------------------------------------------------------------------- */
+/* Manipulator drawing */
+
+#include "manipulator_geometry.h"
+
+void wm_manipulator_geometryinfo_draw(const struct ManipulatorGeomInfo *info, const bool select, const float color[4]);
+void wm_manipulator_vec_draw(
+ const float color[4], const float (*verts)[3], unsigned int vert_count,
+ unsigned int pos, unsigned int primitive_type);
+
+
+#endif /* __MANIPULATOR_LIBRARY_INTERN_H__ */
+
diff --git a/source/blender/editors/manipulator_library/manipulator_library_utils.c b/source/blender/editors/manipulator_library/manipulator_library_utils.c
new file mode 100644
index 00000000000..0950f27213d
--- /dev/null
+++ b/source/blender/editors/manipulator_library/manipulator_library_utils.c
@@ -0,0 +1,169 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file manipulator_library_utils.c
+ * \ingroup wm
+ *
+ * \name Manipulator Library Utilities
+ *
+ * \brief This file contains functions for common behaviors of manipulators.
+ */
+
+#include "BKE_context.h"
+
+#include "BLI_math.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/* own includes */
+#include "manipulator_library_intern.h"
+
+/* factor for precision tweaking */
+#define MANIPULATOR_PRECISION_FAC 0.05f
+
+
+BLI_INLINE float manipulator_offset_from_value_constr(
+ const float range_fac, const float min, const float range, const float value,
+ const bool inverted)
+{
+ return inverted ? (range_fac * (min + range - value) / range) : (range_fac * (value / range));
+}
+
+BLI_INLINE float manipulator_value_from_offset_constr(
+ const float range_fac, const float min, const float range, const float value,
+ const bool inverted)
+{
+ return inverted ? (min + range - (value * range / range_fac)) : (value * range / range_fac);
+}
+
+float manipulator_offset_from_value(
+ ManipulatorCommonData *data, const float value, const bool constrained, const bool inverted)
+{
+ if (constrained)
+ return manipulator_offset_from_value_constr(data->range_fac, data->min, data->range, value, inverted);
+
+ return value;
+}
+
+float manipulator_value_from_offset(
+ ManipulatorCommonData *data, ManipulatorInteraction *inter, const float offset,
+ const bool constrained, const bool inverted, const bool use_precision)
+{
+ const float max = data->min + data->range;
+
+ if (use_precision) {
+ /* add delta offset of this step to total precision_offset */
+ inter->precision_offset += offset - inter->prev_offset;
+ }
+ inter->prev_offset = offset;
+
+ float ofs_new = inter->init_offset + offset - inter->precision_offset * (1.0f - MANIPULATOR_PRECISION_FAC);
+ float value;
+
+ if (constrained) {
+ value = manipulator_value_from_offset_constr(data->range_fac, data->min, data->range, ofs_new, inverted);
+ }
+ else {
+ value = ofs_new;
+ }
+
+ /* clamp to custom range */
+ if (data->flag & MANIPULATOR_CUSTOM_RANGE_SET) {
+ CLAMP(value, data->min, max);
+ }
+
+ return value;
+}
+
+void manipulator_property_data_update(
+ wmManipulator *manipulator, ManipulatorCommonData *data, const int slot,
+ const bool constrained, const bool inverted)
+{
+ if (!manipulator->props[slot]) {
+ data->offset = 0.0f;
+ return;
+ }
+
+ PointerRNA ptr = manipulator->ptr[slot];
+ PropertyRNA *prop = manipulator->props[slot];
+ float value = manipulator_property_value_get(manipulator, slot);
+
+ if (constrained) {
+ if ((data->flag & MANIPULATOR_CUSTOM_RANGE_SET) == 0) {
+ float step, precision;
+ float min, max;
+ RNA_property_float_ui_range(&ptr, prop, &min, &max, &step, &precision);
+ data->range = max - min;
+ data->min = min;
+ }
+ data->offset = manipulator_offset_from_value_constr(data->range_fac, data->min, data->range, value, inverted);
+ }
+ else {
+ data->offset = value;
+ }
+}
+
+void manipulator_property_value_set(
+ bContext *C, const wmManipulator *manipulator,
+ const int slot, const float value)
+{
+ PointerRNA ptr = manipulator->ptr[slot];
+ PropertyRNA *prop = manipulator->props[slot];
+
+ /* reset property */
+ RNA_property_float_set(&ptr, prop, value);
+ RNA_property_update(C, &ptr, prop);
+}
+
+float manipulator_property_value_get(const wmManipulator *manipulator, const int slot)
+{
+ BLI_assert(RNA_property_type(manipulator->props[slot]) == PROP_FLOAT);
+ return RNA_property_float_get(&manipulator->ptr[slot], manipulator->props[slot]);
+}
+
+void manipulator_property_value_reset(
+ bContext *C, const wmManipulator *manipulator, ManipulatorInteraction *inter,
+ const int slot)
+{
+ manipulator_property_value_set(C, manipulator, slot, inter->init_value);
+}
+
+
+/* -------------------------------------------------------------------- */
+
+void manipulator_color_get(
+ const wmManipulator *manipulator, const bool highlight,
+ float r_col[4])
+{
+ if (highlight && !(manipulator->flag & WM_MANIPULATOR_DRAW_HOVER)) {
+ copy_v4_v4(r_col, manipulator->col_hi);
+ }
+ else {
+ copy_v4_v4(r_col, manipulator->col);
+ }
+}
diff --git a/source/blender/editors/manipulator_library/primitive3d_manipulator.c b/source/blender/editors/manipulator_library/primitive3d_manipulator.c
new file mode 100644
index 00000000000..cc8fbeb17d2
--- /dev/null
+++ b/source/blender/editors/manipulator_library/primitive3d_manipulator.c
@@ -0,0 +1,252 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file primitive_manipulator.c
+ * \ingroup wm
+ *
+ * \name Primitive Manipulator
+ *
+ * 3D Manipulator
+ *
+ * \brief Manipulator with primitive drawing type (plane, cube, etc.).
+ * Currently only plane primitive supported without own handling, use with operator only.
+ */
+
+#include "BIF_gl.h"
+
+#include "BKE_context.h"
+
+#include "BLI_math.h"
+
+#include "DNA_view3d_types.h"
+#include "DNA_manipulator_types.h"
+
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+#include "GPU_select.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_manipulator_library.h"
+
+/* own includes */
+#include "manipulator_library_intern.h"
+
+
+/* PrimitiveManipulator->flag */
+enum {
+ PRIM_UP_VECTOR_SET = (1 << 0),
+};
+
+typedef struct PrimitiveManipulator {
+ wmManipulator manipulator;
+
+ float direction[3];
+ float up[3];
+ int style;
+ int flag;
+} PrimitiveManipulator;
+
+
+static float verts_plane[4][3] = {
+ {-1, -1, 0},
+ { 1, -1, 0},
+ { 1, 1, 0},
+ {-1, 1, 0},
+};
+
+
+/* -------------------------------------------------------------------- */
+
+static void manipulator_primitive_draw_geom(
+ const float col_inner[4], const float col_outer[4], const int style)
+{
+ float (*verts)[3];
+ unsigned int vert_count = 0;
+
+ if (style == ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE) {
+ verts = verts_plane;
+ vert_count = ARRAY_SIZE(verts_plane);
+ }
+
+ if (vert_count > 0) {
+ unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ wm_manipulator_vec_draw(col_inner, verts, vert_count, pos, PRIM_TRIANGLE_FAN);
+ wm_manipulator_vec_draw(col_outer, verts, vert_count, pos, PRIM_LINE_LOOP);
+ immUnbindProgram();
+ }
+}
+
+static void manipulator_primitive_draw_intern(
+ PrimitiveManipulator *prim, const bool UNUSED(select),
+ const bool highlight)
+{
+ float col_inner[4], col_outer[4];
+ float rot[3][3];
+ float mat[4][4];
+
+ if (prim->flag & PRIM_UP_VECTOR_SET) {
+ copy_v3_v3(rot[2], prim->direction);
+ copy_v3_v3(rot[1], prim->up);
+ cross_v3_v3v3(rot[0], prim->up, prim->direction);
+ }
+ else {
+ const float up[3] = {0.0f, 0.0f, 1.0f};
+ rotation_between_vecs_to_mat3(rot, up, prim->direction);
+ }
+
+ copy_m4_m3(mat, rot);
+ copy_v3_v3(mat[3], prim->manipulator.origin);
+ mul_mat3_m4_fl(mat, prim->manipulator.scale);
+
+ gpuPushMatrix();
+ gpuMultMatrix(mat);
+
+ manipulator_color_get(&prim->manipulator, highlight, col_outer);
+ copy_v4_v4(col_inner, col_outer);
+ col_inner[3] *= 0.5f;
+
+ glEnable(GL_BLEND);
+ gpuTranslate3fv(prim->manipulator.offset);
+ manipulator_primitive_draw_geom(col_inner, col_outer, prim->style);
+ glDisable(GL_BLEND);
+
+ gpuPopMatrix();
+
+ if (prim->manipulator.interaction_data) {
+ ManipulatorInteraction *inter = prim->manipulator.interaction_data;
+
+ copy_v4_fl(col_inner, 0.5f);
+ copy_v3_fl(col_outer, 0.5f);
+ col_outer[3] = 0.8f;
+
+ copy_m4_m3(mat, rot);
+ copy_v3_v3(mat[3], inter->init_origin);
+ mul_mat3_m4_fl(mat, inter->init_scale);
+
+ gpuPushMatrix();
+ gpuMultMatrix(mat);
+
+ glEnable(GL_BLEND);
+ gpuTranslate3fv(prim->manipulator.offset);
+ manipulator_primitive_draw_geom(col_inner, col_outer, prim->style);
+ glDisable(GL_BLEND);
+
+ gpuPopMatrix();
+ }
+}
+
+static void manipulator_primitive_render_3d_intersect(
+ const bContext *UNUSED(C), wmManipulator *manipulator,
+ int selectionbase)
+{
+ GPU_select_load_id(selectionbase);
+ manipulator_primitive_draw_intern((PrimitiveManipulator *)manipulator, true, false);
+}
+
+static void manipulator_primitive_draw(const bContext *UNUSED(C), wmManipulator *manipulator)
+{
+ manipulator_primitive_draw_intern(
+ (PrimitiveManipulator *)manipulator, false,
+ (manipulator->state & WM_MANIPULATOR_STATE_HIGHLIGHT));
+}
+
+static void manipulator_primitive_invoke(
+ bContext *UNUSED(C), wmManipulator *manipulator, const wmEvent *UNUSED(event))
+{
+ ManipulatorInteraction *inter = MEM_callocN(sizeof(ManipulatorInteraction), __func__);
+
+ copy_v3_v3(inter->init_origin, manipulator->origin);
+ inter->init_scale = manipulator->scale;
+
+ manipulator->interaction_data = inter;
+}
+
+
+/* -------------------------------------------------------------------- */
+/** \name Primitive Manipulator API
+ *
+ * \{ */
+
+wmManipulator *ED_manipulator_primitive3d_new(wmManipulatorGroup *mgroup, const char *name, const int style)
+{
+ const wmManipulatorType *mpt = WM_manipulatortype_find("MANIPULATOR_WT_primitive3d", false);
+ PrimitiveManipulator *prim = (PrimitiveManipulator *)WM_manipulator_new(mpt, mgroup, name);
+
+ const float dir_default[3] = {0.0f, 0.0f, 1.0f};
+
+ prim->manipulator.flag |= WM_MANIPULATOR_DRAW_ACTIVE;
+ prim->style = style;
+
+ /* defaults */
+ copy_v3_v3(prim->direction, dir_default);
+
+ return (wmManipulator *)prim;
+}
+
+/**
+ * Define direction the primitive will point towards
+ */
+void ED_manipulator_primitive3d_set_direction(wmManipulator *manipulator, const float direction[3])
+{
+ PrimitiveManipulator *prim = (PrimitiveManipulator *)manipulator;
+
+ normalize_v3_v3(prim->direction, direction);
+}
+
+/**
+ * Define up-direction of the primitive manipulator
+ */
+void ED_manipulator_primitive3d_set_up_vector(wmManipulator *manipulator, const float direction[3])
+{
+ PrimitiveManipulator *prim = (PrimitiveManipulator *)manipulator;
+
+ if (direction) {
+ normalize_v3_v3(prim->up, direction);
+ prim->flag |= PRIM_UP_VECTOR_SET;
+ }
+ else {
+ prim->flag &= ~PRIM_UP_VECTOR_SET;
+ }
+}
+
+static void MANIPULATOR_WT_primitive3d(wmManipulatorType *wt)
+{
+ /* identifiers */
+ wt->idname = "MANIPULATOR_WT_primitive3d";
+
+ /* api callbacks */
+ wt->draw = manipulator_primitive_draw;
+ wt->draw_select = manipulator_primitive_render_3d_intersect;
+ wt->invoke = manipulator_primitive_invoke;
+
+ wt->size = sizeof(PrimitiveManipulator);
+}
+
+void ED_manipulatortypes_primitive_3d(void)
+{
+ WM_manipulatortype_append(MANIPULATOR_WT_primitive3d);
+}
+
+/** \} */ // Primitive Manipulator API
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index acc197bcc5b..16ccf1da916 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -66,6 +66,7 @@
#include "ED_clip.h"
#include "ED_mask.h"
#include "ED_sequencer.h"
+#include "ED_manipulator_library.h"
#include "io_ops.h"
@@ -126,20 +127,11 @@ void ED_spacetypes_init(void)
ED_operatortypes_ui();
/* manipulator types */
-
- /* FIXME */
- extern void ED_manipulatortypes_dial(void);
- extern void ED_manipulatortypes_arrow_2d(void);
- extern void ED_manipulatortypes_arrow_3d(void);
- extern void ED_manipulatortypes_facemap(void);
- extern void ED_manipulatortypes_primitive(void);
- extern void ED_manipulatortypes_cage(void);
-
- ED_manipulatortypes_dial();
+ ED_manipulatortypes_dial_3d();
ED_manipulatortypes_arrow_2d();
ED_manipulatortypes_arrow_3d();
- ED_manipulatortypes_primitive();
- ED_manipulatortypes_cage();
+ ED_manipulatortypes_primitive_3d();
+ ED_manipulatortypes_cage_2d();
/* register types for operators and manipulators */
spacetypes = BKE_spacetypes_list();
diff --git a/source/blender/editors/space_node/node_widgets.c b/source/blender/editors/space_node/node_widgets.c
index 9e7445b8566..2ff6472f8d0 100644
--- a/source/blender/editors/space_node/node_widgets.c
+++ b/source/blender/editors/space_node/node_widgets.c
@@ -28,6 +28,7 @@
#include "DNA_manipulator_types.h"
#include "ED_screen.h"
+#include "ED_manipulator_library.h"
#include "IMB_imbuf_types.h"
@@ -64,9 +65,9 @@ static void WIDGETGROUP_node_transform_init(const bContext *UNUSED(C), wmManipul
{
wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__);
- wwrapper->manipulator = MANIPULATOR_rect_transform_new(
+ wwrapper->manipulator = ED_manipulator_rect_transform_new(
wgroup, "backdrop_cage",
- MANIPULATOR_RECT_TRANSFORM_STYLE_TRANSLATE | MANIPULATOR_RECT_TRANSFORM_STYLE_SCALE_UNIFORM);
+ ED_MANIPULATOR_RECT_TRANSFORM_STYLE_TRANSLATE | ED_MANIPULATOR_RECT_TRANSFORM_STYLE_SCALE_UNIFORM);
wgroup->customdata = wwrapper;
}
@@ -86,7 +87,7 @@ static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmManipulatorG
const float w = (ibuf->x > 0) ? ibuf->x : 64.0f;
const float h = (ibuf->y > 0) ? ibuf->y : 64.0f;
- MANIPULATOR_rect_transform_set_dimensions(cage, w, h);
+ ED_manipulator_rect_transform_set_dimensions(cage, w, h);
WM_manipulator_set_origin(cage, origin);
WM_manipulator_set_flag(cage, WM_MANIPULATOR_HIDDEN, false);
@@ -94,8 +95,8 @@ static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmManipulatorG
SpaceNode *snode = CTX_wm_space_node(C);
PointerRNA nodeptr;
RNA_pointer_create(snode->id, &RNA_SpaceNodeEditor, snode, &nodeptr);
- WM_manipulator_set_property(cage, RECT_TRANSFORM_SLOT_OFFSET, &nodeptr, "backdrop_offset");
- WM_manipulator_set_property(cage, RECT_TRANSFORM_SLOT_SCALE, &nodeptr, "backdrop_zoom");
+ WM_manipulator_set_property(cage, ED_MANIPULATOR_RECT_TX_SLOT_OFFSET, &nodeptr, "backdrop_offset");
+ WM_manipulator_set_property(cage, ED_MANIPULATOR_RECT_TX_SLOT_SCALE, &nodeptr, "backdrop_zoom");
}
else {
WM_manipulator_set_flag(cage, WM_MANIPULATOR_HIDDEN, true);
diff --git a/source/blender/editors/space_view3d/view3d_manipulators.c b/source/blender/editors/space_view3d/view3d_manipulators.c
index 8d853498740..87513a6294b 100644
--- a/source/blender/editors/space_view3d/view3d_manipulators.c
+++ b/source/blender/editors/space_view3d/view3d_manipulators.c
@@ -43,6 +43,7 @@
#include "ED_armature.h"
#include "ED_screen.h"
+#include "ED_manipulator_library.h"
#include "MEM_guardedalloc.h"
@@ -78,10 +79,10 @@ static void WIDGETGROUP_lamp_init(const bContext *UNUSED(C), wmManipulatorGroup
wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__);
- wwrapper->manipulator = MANIPULATOR_arrow_new(wgroup, propname, MANIPULATOR_ARROW_STYLE_INVERTED);
+ wwrapper->manipulator = ED_manipulator_arrow3d_new(wgroup, propname, ED_MANIPULATOR_ARROW_STYLE_INVERTED);
wgroup->customdata = wwrapper;
- MANIPULATOR_arrow_set_range_fac(wwrapper->manipulator, 4.0f);
+ ED_manipulator_arrow3d_set_range_fac(wwrapper->manipulator, 4.0f);
WM_manipulator_set_color(wwrapper->manipulator, color);
WM_manipulator_set_color_highlight(wwrapper->manipulator, color_hi);
}
@@ -95,14 +96,14 @@ static void WIDGETGROUP_lamp_refresh(const bContext *C, wmManipulatorGroup *wgro
negate_v3_v3(dir, ob->obmat[2]);
- MANIPULATOR_arrow_set_direction(wwrapper->manipulator, dir);
+ ED_manipulator_arrow3d_set_direction(wwrapper->manipulator, dir);
WM_manipulator_set_origin(wwrapper->manipulator, ob->obmat[3]);
/* need to set property here for undo. TODO would prefer to do this in _init */
PointerRNA lamp_ptr;
const char *propname = "spot_size";
RNA_pointer_create(&la->id, &RNA_Lamp, la, &lamp_ptr);
- WM_manipulator_set_property(wwrapper->manipulator, ARROW_SLOT_OFFSET_WORLD_SPACE, &lamp_ptr, propname);
+ WM_manipulator_set_property(wwrapper->manipulator, ED_MANIPULATOR_ARROW_SLOT_OFS_WORLD_SPACE, &lamp_ptr, propname);
}
void VIEW3D_WGT_lamp(wmManipulatorGroupType *wgt)
@@ -158,7 +159,7 @@ static void cameragroup_property_setup(wmManipulator *widget, Object *ob, Camera
RNA_property_float_ui_range(&camera_ptr, prop, &min, &max, &step, &precision);
range = max - min;
- MANIPULATOR_arrow_set_range_fac(widget, is_ortho ? (scale_fac * range) : (drawsize * range / half_sensor));
+ ED_manipulator_arrow3d_set_range_fac(widget, is_ortho ? (scale_fac * range) : (drawsize * range / half_sensor));
}
static void WIDGETGROUP_camera_init(const bContext *C, wmManipulatorGroup *wgroup)
@@ -177,7 +178,7 @@ static void WIDGETGROUP_camera_init(const bContext *C, wmManipulatorGroup *wgrou
const float color[4] = {1.0f, 0.3f, 0.0f, 1.0f};
const float color_hi[4] = {1.0f, 0.3f, 0.0f, 1.0f};
- camgroup->dop_dist = MANIPULATOR_arrow_new(wgroup, "dof_distance", MANIPULATOR_ARROW_STYLE_CROSS);
+ camgroup->dop_dist = ED_manipulator_arrow3d_new(wgroup, "dof_distance", ED_MANIPULATOR_ARROW_STYLE_CROSS);
WM_manipulator_set_flag(camgroup->dop_dist, WM_MANIPULATOR_DRAW_HOVER, true);
WM_manipulator_set_color(camgroup->dop_dist, color);
WM_manipulator_set_color_highlight(camgroup->dop_dist, color_hi);
@@ -189,16 +190,16 @@ static void WIDGETGROUP_camera_init(const bContext *C, wmManipulatorGroup *wgrou
const float color[4] = {1.0f, 1.0, 0.27f, 0.5f};
const float color_hi[4] = {1.0f, 1.0, 0.27f, 1.0f};
- camgroup->focal_len = MANIPULATOR_arrow_new(
+ camgroup->focal_len = ED_manipulator_arrow3d_new(
wgroup, "focal_len",
- (MANIPULATOR_ARROW_STYLE_CONE | MANIPULATOR_ARROW_STYLE_CONSTRAINED));
+ (ED_MANIPULATOR_ARROW_STYLE_CONE | ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED));
WM_manipulator_set_color(camgroup->focal_len, color);
WM_manipulator_set_color_highlight(camgroup->focal_len, color_hi);
cameragroup_property_setup(camgroup->focal_len, ob, ca, false);
- camgroup->ortho_scale = MANIPULATOR_arrow_new(
+ camgroup->ortho_scale = ED_manipulator_arrow3d_new(
wgroup, "ortho_scale",
- (MANIPULATOR_ARROW_STYLE_CONE | MANIPULATOR_ARROW_STYLE_CONSTRAINED));
+ (ED_MANIPULATOR_ARROW_STYLE_CONE | ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED));
WM_manipulator_set_color(camgroup->ortho_scale, color);
WM_manipulator_set_color_highlight(camgroup->ortho_scale, color_hi);
cameragroup_property_setup(camgroup->ortho_scale, ob, ca, true);
@@ -221,14 +222,14 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmManipulatorGroup *wg
negate_v3_v3(dir, ob->obmat[2]);
if (ca->flag & CAM_SHOWLIMITS) {
- MANIPULATOR_arrow_set_direction(camgroup->dop_dist, dir);
- MANIPULATOR_arrow_set_up_vector(camgroup->dop_dist, ob->obmat[1]);
+ ED_manipulator_arrow3d_set_direction(camgroup->dop_dist, dir);
+ ED_manipulator_arrow3d_set_up_vector(camgroup->dop_dist, ob->obmat[1]);
WM_manipulator_set_origin(camgroup->dop_dist, ob->obmat[3]);
WM_manipulator_set_scale(camgroup->dop_dist, ca->drawsize);
WM_manipulator_set_flag(camgroup->dop_dist, WM_MANIPULATOR_HIDDEN, false);
/* need to set property here for undo. TODO would prefer to do this in _init */
- WM_manipulator_set_property(camgroup->dop_dist, ARROW_SLOT_OFFSET_WORLD_SPACE, &camera_ptr, "dof_distance");
+ WM_manipulator_set_property(camgroup->dop_dist, ED_MANIPULATOR_ARROW_SLOT_OFS_WORLD_SPACE, &camera_ptr, "dof_distance");
}
else {
WM_manipulator_set_flag(camgroup->dop_dist, WM_MANIPULATOR_HIDDEN, true);
@@ -263,16 +264,16 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmManipulatorGroup *wg
asp[0] = (sensor_fit == CAMERA_SENSOR_FIT_HOR) ? 1.0 : aspx / aspy;
asp[1] = (sensor_fit == CAMERA_SENSOR_FIT_HOR) ? aspy / aspx : 1.0f;
- MANIPULATOR_arrow_set_up_vector(widget, ob->obmat[1]);
- MANIPULATOR_arrow_set_direction(widget, dir);
- MANIPULATOR_arrow_cone_set_aspect(widget, asp);
+ ED_manipulator_arrow3d_set_up_vector(widget, ob->obmat[1]);
+ ED_manipulator_arrow3d_set_direction(widget, dir);
+ ED_manipulator_arrow3d_cone_set_aspect(widget, asp);
WM_manipulator_set_origin(widget, ob->obmat[3]);
WM_manipulator_set_offset(widget, offset);
WM_manipulator_set_scale(widget, drawsize);
/* need to set property here for undo. TODO would prefer to do this in _init */
- WM_manipulator_set_property(camgroup->focal_len, ARROW_SLOT_OFFSET_WORLD_SPACE, &camera_ptr, "lens");
- WM_manipulator_set_property(camgroup->ortho_scale, ARROW_SLOT_OFFSET_WORLD_SPACE, &camera_ptr, "ortho_scale");
+ WM_manipulator_set_property(camgroup->focal_len, ED_MANIPULATOR_ARROW_SLOT_OFS_WORLD_SPACE, &camera_ptr, "lens");
+ WM_manipulator_set_property(camgroup->ortho_scale, ED_MANIPULATOR_ARROW_SLOT_OFS_WORLD_SPACE, &camera_ptr, "ortho_scale");
}
}
@@ -311,10 +312,10 @@ static void WIDGETGROUP_forcefield_init(const bContext *UNUSED(C), wmManipulator
wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__);
wgroup->customdata = wwrapper;
- wwrapper->manipulator = MANIPULATOR_arrow_new(wgroup, "field_strength", MANIPULATOR_ARROW_STYLE_CONSTRAINED);
+ wwrapper->manipulator = ED_manipulator_arrow3d_new(wgroup, "field_strength", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED);
- MANIPULATOR_arrow_set_ui_range(wwrapper->manipulator, -200.0f, 200.0f);
- MANIPULATOR_arrow_set_range_fac(wwrapper->manipulator, 6.0f);
+ ED_manipulator_arrow3d_set_ui_range(wwrapper->manipulator, -200.0f, 200.0f);
+ ED_manipulator_arrow3d_set_range_fac(wwrapper->manipulator, 6.0f);
WM_manipulator_set_color(wwrapper->manipulator, col);
WM_manipulator_set_color_highlight(wwrapper->manipulator, col_hi);
}
@@ -332,11 +333,11 @@ static void WIDGETGROUP_forcefield_refresh(const bContext *C, wmManipulatorGroup
RNA_pointer_create(&ob->id, &RNA_FieldSettings, pd, &field_ptr);
- MANIPULATOR_arrow_set_direction(wwrapper->manipulator, ob->obmat[2]);
+ ED_manipulator_arrow3d_set_direction(wwrapper->manipulator, ob->obmat[2]);
WM_manipulator_set_origin(wwrapper->manipulator, ob->obmat[3]);
WM_manipulator_set_offset(wwrapper->manipulator, ofs);
WM_manipulator_set_flag(wwrapper->manipulator, WM_MANIPULATOR_HIDDEN, false);
- WM_manipulator_set_property(wwrapper->manipulator, ARROW_SLOT_OFFSET_WORLD_SPACE, &field_ptr, "strength");
+ WM_manipulator_set_property(wwrapper->manipulator, ED_MANIPULATOR_ARROW_SLOT_OFS_WORLD_SPACE, &field_ptr, "strength");
}
else {
WM_manipulator_set_flag(wwrapper->manipulator, WM_MANIPULATOR_HIDDEN, true);
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index 6d38037ab30..2b06eb34bcb 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -74,6 +74,7 @@
#include "ED_view3d.h"
#include "ED_gpencil.h"
#include "ED_screen.h"
+#include "ED_manipulator_library.h"
#include "UI_resources.h"
@@ -1087,29 +1088,29 @@ static ManipulatorGroup *manipulatorgroup_init(wmManipulatorGroup *wgroup)
man = MEM_callocN(sizeof(ManipulatorGroup), "manipulator_data");
/* add/init widgets - order matters! */
- man->rotate_t = MANIPULATOR_dial_new(wgroup, "rotate_t", MANIPULATOR_DIAL_STYLE_RING_FILLED);
-
- man->scale_c = MANIPULATOR_dial_new(wgroup, "scale_c", MANIPULATOR_DIAL_STYLE_RING);
- man->scale_x = MANIPULATOR_arrow_new(wgroup, "scale_x", MANIPULATOR_ARROW_STYLE_BOX);
- man->scale_y = MANIPULATOR_arrow_new(wgroup, "scale_y", MANIPULATOR_ARROW_STYLE_BOX);
- man->scale_z = MANIPULATOR_arrow_new(wgroup, "scale_z", MANIPULATOR_ARROW_STYLE_BOX);
- man->scale_xy = MANIPULATOR_primitive_new(wgroup, "scale_xy", MANIPULATOR_PRIMITIVE_STYLE_PLANE);
- man->scale_yz = MANIPULATOR_primitive_new(wgroup, "scale_yz", MANIPULATOR_PRIMITIVE_STYLE_PLANE);
- man->scale_zx = MANIPULATOR_primitive_new(wgroup, "scale_zx", MANIPULATOR_PRIMITIVE_STYLE_PLANE);
-
- man->rotate_x = MANIPULATOR_dial_new(wgroup, "rotate_x", MANIPULATOR_DIAL_STYLE_RING_CLIPPED);
- man->rotate_y = MANIPULATOR_dial_new(wgroup, "rotate_y", MANIPULATOR_DIAL_STYLE_RING_CLIPPED);
- man->rotate_z = MANIPULATOR_dial_new(wgroup, "rotate_z", MANIPULATOR_DIAL_STYLE_RING_CLIPPED);
+ man->rotate_t = ED_manipulator_dial3d_new(wgroup, "rotate_t", ED_MANIPULATOR_DIAL_STYLE_RING_FILLED);
+
+ man->scale_c = ED_manipulator_dial3d_new(wgroup, "scale_c", ED_MANIPULATOR_DIAL_STYLE_RING);
+ man->scale_x = ED_manipulator_arrow3d_new(wgroup, "scale_x", ED_MANIPULATOR_ARROW_STYLE_BOX);
+ man->scale_y = ED_manipulator_arrow3d_new(wgroup, "scale_y", ED_MANIPULATOR_ARROW_STYLE_BOX);
+ man->scale_z = ED_manipulator_arrow3d_new(wgroup, "scale_z", ED_MANIPULATOR_ARROW_STYLE_BOX);
+ man->scale_xy = ED_manipulator_primitive3d_new(wgroup, "scale_xy", ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE);
+ man->scale_yz = ED_manipulator_primitive3d_new(wgroup, "scale_yz", ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE);
+ man->scale_zx = ED_manipulator_primitive3d_new(wgroup, "scale_zx", ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE);
+
+ man->rotate_x = ED_manipulator_dial3d_new(wgroup, "rotate_x", ED_MANIPULATOR_DIAL_STYLE_RING_CLIPPED);
+ man->rotate_y = ED_manipulator_dial3d_new(wgroup, "rotate_y", ED_MANIPULATOR_DIAL_STYLE_RING_CLIPPED);
+ man->rotate_z = ED_manipulator_dial3d_new(wgroup, "rotate_z", ED_MANIPULATOR_DIAL_STYLE_RING_CLIPPED);
/* init screen aligned widget last here, looks better, behaves better */
- man->rotate_c = MANIPULATOR_dial_new(wgroup, "rotate_c", MANIPULATOR_DIAL_STYLE_RING);
+ man->rotate_c = ED_manipulator_dial3d_new(wgroup, "rotate_c", ED_MANIPULATOR_DIAL_STYLE_RING);
- man->translate_c = MANIPULATOR_dial_new(wgroup, "translate_c", MANIPULATOR_DIAL_STYLE_RING);
- man->translate_x = MANIPULATOR_arrow_new(wgroup, "translate_x", MANIPULATOR_ARROW_STYLE_NORMAL);
- man->translate_y = MANIPULATOR_arrow_new(wgroup, "translate_y", MANIPULATOR_ARROW_STYLE_NORMAL);
- man->translate_z = MANIPULATOR_arrow_new(wgroup, "translate_z", MANIPULATOR_ARROW_STYLE_NORMAL);
- man->translate_xy = MANIPULATOR_primitive_new(wgroup, "translate_xy", MANIPULATOR_PRIMITIVE_STYLE_PLANE);
- man->translate_yz = MANIPULATOR_primitive_new(wgroup, "translate_yz", MANIPULATOR_PRIMITIVE_STYLE_PLANE);
- man->translate_zx = MANIPULATOR_primitive_new(wgroup, "translate_zx", MANIPULATOR_PRIMITIVE_STYLE_PLANE);
+ man->translate_c = ED_manipulator_dial3d_new(wgroup, "translate_c", ED_MANIPULATOR_DIAL_STYLE_RING);
+ man->translate_x = ED_manipulator_arrow3d_new(wgroup, "translate_x", ED_MANIPULATOR_ARROW_STYLE_NORMAL);
+ man->translate_y = ED_manipulator_arrow3d_new(wgroup, "translate_y", ED_MANIPULATOR_ARROW_STYLE_NORMAL);
+ man->translate_z = ED_manipulator_arrow3d_new(wgroup, "translate_z", ED_MANIPULATOR_ARROW_STYLE_NORMAL);
+ man->translate_xy = ED_manipulator_primitive3d_new(wgroup, "translate_xy", ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE);
+ man->translate_yz = ED_manipulator_primitive3d_new(wgroup, "translate_yz", ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE);
+ man->translate_zx = ED_manipulator_primitive3d_new(wgroup, "translate_zx", ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE);
return man;
}
@@ -1253,15 +1254,15 @@ static void WIDGETGROUP_manipulator_refresh(const bContext *C, wmManipulatorGrou
manipulator_line_range(v3d, axis_type, &start_co[2], &len);
- MANIPULATOR_arrow_set_direction(axis, rv3d->twmat[aidx_norm]);
- MANIPULATOR_arrow_set_line_len(axis, len);
+ ED_manipulator_arrow3d_set_direction(axis, rv3d->twmat[aidx_norm]);
+ ED_manipulator_arrow3d_set_line_len(axis, len);
WM_manipulator_set_offset(axis, start_co);
break;
}
case MAN_AXIS_ROT_X:
case MAN_AXIS_ROT_Y:
case MAN_AXIS_ROT_Z:
- MANIPULATOR_dial_set_up_vector(axis, rv3d->twmat[aidx_norm]);
+ ED_manipulator_dial3d_set_up_vector(axis, rv3d->twmat[aidx_norm]);
break;
case MAN_AXIS_TRANS_XY:
case MAN_AXIS_TRANS_YZ:
@@ -1269,8 +1270,8 @@ static void WIDGETGROUP_manipulator_refresh(const bContext *C, wmManipulatorGrou
case MAN_AXIS_SCALE_XY:
case MAN_AXIS_SCALE_YZ:
case MAN_AXIS_SCALE_ZX:
- MANIPULATOR_primitive_set_direction(axis, rv3d->twmat[aidx_norm - 1 < 0 ? 2 : aidx_norm - 1]);
- MANIPULATOR_primitive_set_up_vector(axis, rv3d->twmat[aidx_norm + 1 > 2 ? 0 : aidx_norm + 1]);
+ ED_manipulator_primitive3d_set_direction(axis, rv3d->twmat[aidx_norm - 1 < 0 ? 2 : aidx_norm - 1]);
+ ED_manipulator_primitive3d_set_up_vector(axis, rv3d->twmat[aidx_norm + 1 > 2 ? 0 : aidx_norm + 1]);
break;
}
}
@@ -1322,7 +1323,7 @@ static void WIDGETGROUP_manipulator_draw_prepare(const bContext *C, wmManipulato
case MAN_AXIS_ROT_C:
case MAN_AXIS_SCALE_C:
case MAN_AXIS_ROT_T:
- MANIPULATOR_dial_set_up_vector(axis, rv3d->viewinv[2]);
+ ED_manipulator_dial3d_set_up_vector(axis, rv3d->viewinv[2]);
break;
}
}
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index 766f70d025c..3612aab468f 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -64,6 +64,7 @@ set(SRC
../include/ED_lattice.h
../include/ED_logic.h
../include/ED_markers.h
+ ../include/ED_manipulator_library.h
../include/ED_mask.h
../include/ED_mball.h
../include/ED_mesh.h