2016-10-07 16:34:55 +02:00
|
|
|
/*
|
|
|
|
|
* ***** 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 blender/windowmanager/manipulators/intern/wm_manipulator.c
|
|
|
|
|
* \ingroup wm
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "BKE_context.h"
|
|
|
|
|
|
|
|
|
|
#include "BLI_listbase.h"
|
|
|
|
|
#include "BLI_math.h"
|
|
|
|
|
#include "BLI_string.h"
|
2017-01-16 20:50:10 +01:00
|
|
|
#include "BLI_string_utils.h"
|
2016-10-07 16:34:55 +02:00
|
|
|
|
|
|
|
|
#include "ED_screen.h"
|
|
|
|
|
#include "ED_view3d.h"
|
|
|
|
|
|
2017-04-07 00:35:57 +10:00
|
|
|
#include "GPU_batch.h"
|
|
|
|
|
#include "GPU_glew.h"
|
2017-04-07 16:02:45 +02:00
|
|
|
#include "GPU_immediate.h"
|
2016-10-07 16:34:55 +02:00
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
|
|
#include "RNA_access.h"
|
|
|
|
|
|
|
|
|
|
#include "WM_api.h"
|
|
|
|
|
#include "WM_types.h"
|
|
|
|
|
|
2017-06-10 10:42:35 +10:00
|
|
|
#ifdef WITH_PYTHON
|
|
|
|
|
#include "BPY_extern.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-06-08 05:27:14 +10:00
|
|
|
/* only for own init/exit calls (wm_manipulatortype_init/wm_manipulatortype_free) */
|
|
|
|
|
#include "wm.h"
|
|
|
|
|
|
2016-10-07 16:34:55 +02:00
|
|
|
/* own includes */
|
|
|
|
|
#include "wm_manipulator_wmapi.h"
|
|
|
|
|
#include "wm_manipulator_intern.h"
|
|
|
|
|
|
2017-06-08 05:27:14 +10:00
|
|
|
static void wm_manipulator_register(
|
2017-06-10 10:42:35 +10:00
|
|
|
wmManipulatorGroup *mgroup, wmManipulator *mpr, const char *name);
|
2017-06-08 05:27:14 +10:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \note Follow #wm_operator_create convention.
|
|
|
|
|
*/
|
|
|
|
|
static wmManipulator *wm_manipulator_create(
|
2017-06-17 10:01:22 +10:00
|
|
|
const wmManipulatorType *wt)
|
2017-06-08 05:27:14 +10:00
|
|
|
{
|
2017-06-17 10:01:22 +10:00
|
|
|
BLI_assert(wt != NULL);
|
|
|
|
|
BLI_assert(wt->struct_size >= sizeof(wmManipulator));
|
2017-06-08 05:27:14 +10:00
|
|
|
|
2017-06-17 10:01:22 +10:00
|
|
|
wmManipulator *mpr = MEM_callocN(wt->struct_size, __func__);
|
|
|
|
|
mpr->type = wt;
|
2017-06-18 05:38:10 +10:00
|
|
|
|
|
|
|
|
unit_m4(mpr->matrix);
|
|
|
|
|
unit_m4(mpr->matrix_offset);
|
|
|
|
|
|
2017-06-08 05:27:14 +10:00
|
|
|
return mpr;
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-17 10:01:22 +10:00
|
|
|
wmManipulator *WM_manipulator_new_ptr(const wmManipulatorType *wt, wmManipulatorGroup *mgroup, const char *name)
|
2017-06-06 17:07:26 +10:00
|
|
|
{
|
2017-06-17 10:01:22 +10:00
|
|
|
wmManipulator *mpr = wm_manipulator_create(wt);
|
2017-06-06 17:07:26 +10:00
|
|
|
|
2017-06-08 05:27:14 +10:00
|
|
|
wm_manipulator_register(mgroup, mpr, name);
|
2017-06-06 17:07:26 +10:00
|
|
|
|
2017-06-17 10:01:22 +10:00
|
|
|
if (mpr->type->setup != NULL) {
|
|
|
|
|
mpr->type->setup(mpr);
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-08 05:27:14 +10:00
|
|
|
return mpr;
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
|
2017-06-10 10:42:35 +10:00
|
|
|
/**
|
|
|
|
|
* \param wt: Must be valid,
|
|
|
|
|
* if you need to check it exists use #WM_manipulator_new_ptr
|
|
|
|
|
* because callers of this function don't NULL check the return value.
|
|
|
|
|
*/
|
|
|
|
|
wmManipulator *WM_manipulator_new(const char *idname, wmManipulatorGroup *mgroup, const char *name)
|
|
|
|
|
{
|
|
|
|
|
const wmManipulatorType *wt = WM_manipulatortype_find(idname, false);
|
2017-06-17 10:01:22 +10:00
|
|
|
return WM_manipulator_new_ptr(wt, mgroup, name);
|
2017-06-10 10:42:35 +10:00
|
|
|
}
|
|
|
|
|
|
2016-10-07 16:34:55 +02:00
|
|
|
/**
|
|
|
|
|
* Assign an idname that is unique in \a mgroup to \a manipulator.
|
|
|
|
|
*
|
|
|
|
|
* \param rawname: Name used as basis to define final unique idname.
|
|
|
|
|
*/
|
2017-06-10 10:42:35 +10:00
|
|
|
static void manipulator_unique_idname_set(wmManipulatorGroup *mgroup, wmManipulator *mpr, const char *rawname)
|
2016-10-07 16:34:55 +02:00
|
|
|
{
|
2017-06-10 10:42:35 +10:00
|
|
|
BLI_snprintf(mpr->name, sizeof(mpr->name), "%s_%s", mgroup->type->idname, rawname);
|
2016-10-07 16:34:55 +02:00
|
|
|
|
|
|
|
|
/* ensure name is unique, append '.001', '.002', etc if not */
|
2017-06-10 10:42:35 +10:00
|
|
|
BLI_uniquename(&mgroup->manipulators, mpr, "Manipulator", '.',
|
|
|
|
|
offsetof(wmManipulator, name), sizeof(mpr->name));
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Initialize default values and allocate needed memory for members.
|
|
|
|
|
*/
|
2017-06-08 05:27:14 +10:00
|
|
|
static void manipulator_init(wmManipulator *mpr)
|
2016-10-07 16:34:55 +02:00
|
|
|
{
|
2017-06-10 10:42:35 +10:00
|
|
|
const float color_default[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
2016-10-07 16:34:55 +02:00
|
|
|
|
2017-06-08 05:27:14 +10:00
|
|
|
mpr->user_scale = 1.0f;
|
|
|
|
|
mpr->line_width = 1.0f;
|
2016-10-07 16:34:55 +02:00
|
|
|
|
|
|
|
|
/* defaults */
|
2017-06-10 10:42:35 +10:00
|
|
|
copy_v4_v4(mpr->color, color_default);
|
|
|
|
|
copy_v4_v4(mpr->color_hi, color_default);
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Register \a manipulator.
|
|
|
|
|
*
|
|
|
|
|
* \param name: name used to create a unique idname for \a manipulator in \a mgroup
|
2017-06-10 10:42:35 +10:00
|
|
|
*
|
|
|
|
|
* \note Not to be confused with type registration from RNA.
|
2016-10-07 16:34:55 +02:00
|
|
|
*/
|
2017-06-10 10:42:35 +10:00
|
|
|
static void wm_manipulator_register(wmManipulatorGroup *mgroup, wmManipulator *mpr, const char *name)
|
2016-10-07 16:34:55 +02:00
|
|
|
{
|
2017-06-10 10:42:35 +10:00
|
|
|
manipulator_init(mpr);
|
|
|
|
|
manipulator_unique_idname_set(mgroup, mpr, name);
|
|
|
|
|
wm_manipulatorgroup_manipulator_register(mgroup, mpr);
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Free \a manipulator and unlink from \a manipulatorlist.
|
|
|
|
|
* \a manipulatorlist is allowed to be NULL.
|
|
|
|
|
*/
|
2017-06-10 10:42:35 +10:00
|
|
|
void WM_manipulator_free(ListBase *manipulatorlist, wmManipulatorMap *mmap, wmManipulator *mpr, bContext *C)
|
2016-10-07 16:34:55 +02:00
|
|
|
{
|
2017-06-10 10:42:35 +10:00
|
|
|
#ifdef WITH_PYTHON
|
|
|
|
|
if (mpr->py_instance) {
|
|
|
|
|
/* do this first in case there are any __del__ functions or
|
|
|
|
|
* similar that use properties */
|
|
|
|
|
BPY_DECREF_RNA_INVALIDATE(mpr->py_instance);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) {
|
|
|
|
|
wm_manipulatormap_highlight_set(mmap, C, NULL, 0);
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
2017-06-10 10:42:35 +10:00
|
|
|
if (mpr->state & WM_MANIPULATOR_STATE_ACTIVE) {
|
|
|
|
|
wm_manipulatormap_active_set(mmap, C, NULL, NULL);
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
2017-06-10 10:42:35 +10:00
|
|
|
if (mpr->state & WM_MANIPULATOR_STATE_SELECT) {
|
|
|
|
|
wm_manipulator_deselect(mmap, mpr);
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
|
2017-06-20 04:44:34 +10:00
|
|
|
if (mpr->op_data.ptr.data) {
|
|
|
|
|
WM_operator_properties_free(&mpr->op_data.ptr);
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
2017-06-10 10:42:35 +10:00
|
|
|
BLI_freelistN(&mpr->properties);
|
2016-10-07 16:34:55 +02:00
|
|
|
|
2017-06-16 08:20:27 +10:00
|
|
|
if (manipulatorlist) {
|
2017-06-10 10:42:35 +10:00
|
|
|
BLI_remlink(manipulatorlist, mpr);
|
2017-06-16 08:20:27 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLI_assert(mmap->mmap_context.highlight != mpr);
|
|
|
|
|
BLI_assert(mmap->mmap_context.active != mpr);
|
|
|
|
|
|
2017-06-10 10:42:35 +10:00
|
|
|
MEM_freeN(mpr);
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Manipulator Creation API
|
|
|
|
|
*
|
|
|
|
|
* API for defining data on manipulator creation.
|
|
|
|
|
*
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
|
2017-06-20 04:44:34 +10:00
|
|
|
PointerRNA *WM_manipulator_set_operator(wmManipulator *mpr, wmOperatorType *ot)
|
2016-10-07 16:34:55 +02:00
|
|
|
{
|
2017-06-20 04:44:34 +10:00
|
|
|
mpr->op_data.type = ot;
|
2016-10-07 16:34:55 +02:00
|
|
|
|
2017-06-20 04:44:34 +10:00
|
|
|
if (mpr->op_data.ptr.data) {
|
|
|
|
|
WM_operator_properties_free(&mpr->op_data.ptr);
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
2017-06-20 04:44:34 +10:00
|
|
|
WM_operator_properties_create_ptr(&mpr->op_data.ptr, ot);
|
2016-10-07 16:34:55 +02:00
|
|
|
|
2017-06-20 04:44:34 +10:00
|
|
|
return &mpr->op_data.ptr;
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
|
2017-06-18 07:43:45 +10:00
|
|
|
static void wm_manipulator_set_matrix_rotation_from_z_axis__internal(
|
|
|
|
|
float matrix[4][4], const float z_axis[3])
|
|
|
|
|
{
|
|
|
|
|
/* old code, seems we can use simpler method */
|
|
|
|
|
#if 0
|
|
|
|
|
const float z_global[3] = {0.0f, 0.0f, 1.0f};
|
|
|
|
|
float rot[3][3];
|
|
|
|
|
|
|
|
|
|
rotation_between_vecs_to_mat3(rot, z_global, z_axis);
|
|
|
|
|
copy_v3_v3(matrix[0], rot[0]);
|
|
|
|
|
copy_v3_v3(matrix[1], rot[1]);
|
|
|
|
|
copy_v3_v3(matrix[2], rot[2]);
|
|
|
|
|
#else
|
|
|
|
|
normalize_v3_v3(matrix[2], z_axis);
|
|
|
|
|
ortho_basis_v3v3_v3(matrix[0], matrix[1], matrix[2]);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void wm_manipulator_set_matrix_rotation_from_yz_axis__internal(
|
|
|
|
|
float matrix[4][4], const float y_axis[3], const float z_axis[3])
|
|
|
|
|
{
|
|
|
|
|
normalize_v3_v3(matrix[1], y_axis);
|
|
|
|
|
normalize_v3_v3(matrix[2], z_axis);
|
|
|
|
|
cross_v3_v3v3(matrix[0], matrix[1], matrix[2]);
|
|
|
|
|
normalize_v3(matrix[0]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* wmManipulator.matrix utils.
|
|
|
|
|
*/
|
|
|
|
|
void WM_manipulator_set_matrix_rotation_from_z_axis(
|
|
|
|
|
wmManipulator *mpr, const float z_axis[3])
|
|
|
|
|
{
|
|
|
|
|
wm_manipulator_set_matrix_rotation_from_z_axis__internal(mpr->matrix, z_axis);
|
|
|
|
|
}
|
|
|
|
|
void WM_manipulator_set_matrix_rotation_from_yz_axis(
|
|
|
|
|
wmManipulator *mpr, const float y_axis[3], const float z_axis[3])
|
|
|
|
|
{
|
|
|
|
|
wm_manipulator_set_matrix_rotation_from_yz_axis__internal(mpr->matrix, y_axis, z_axis);
|
|
|
|
|
}
|
|
|
|
|
void WM_manipulator_set_matrix_location(wmManipulator *mpr, const float origin[3])
|
2016-10-07 16:34:55 +02:00
|
|
|
{
|
2017-06-18 05:38:10 +10:00
|
|
|
copy_v3_v3(mpr->matrix[3], origin);
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
|
2017-06-18 07:43:45 +10:00
|
|
|
/**
|
|
|
|
|
* wmManipulator.matrix_offset utils.
|
|
|
|
|
*/
|
|
|
|
|
void WM_manipulator_set_matrix_offset_rotation_from_z_axis(
|
|
|
|
|
wmManipulator *mpr, const float z_axis[3])
|
|
|
|
|
{
|
|
|
|
|
wm_manipulator_set_matrix_rotation_from_z_axis__internal(mpr->matrix_offset, z_axis);
|
|
|
|
|
}
|
|
|
|
|
void WM_manipulator_set_matrix_offset_rotation_from_yz_axis(
|
|
|
|
|
wmManipulator *mpr, const float y_axis[3], const float z_axis[3])
|
|
|
|
|
{
|
|
|
|
|
wm_manipulator_set_matrix_rotation_from_yz_axis__internal(mpr->matrix_offset, y_axis, z_axis);
|
|
|
|
|
}
|
|
|
|
|
void WM_manipulator_set_matrix_offset_location(wmManipulator *mpr, const float offset[3])
|
2016-10-07 16:34:55 +02:00
|
|
|
{
|
2017-06-18 05:38:10 +10:00
|
|
|
copy_v3_v3(mpr->matrix_offset[3], offset);
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
|
2017-06-10 10:42:35 +10:00
|
|
|
void WM_manipulator_set_flag(wmManipulator *mpr, const int flag, const bool enable)
|
2016-10-07 16:34:55 +02:00
|
|
|
{
|
|
|
|
|
if (enable) {
|
2017-06-10 10:42:35 +10:00
|
|
|
mpr->flag |= flag;
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2017-06-10 10:42:35 +10:00
|
|
|
mpr->flag &= ~flag;
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-10 10:42:35 +10:00
|
|
|
void WM_manipulator_set_scale(wmManipulator *mpr, const float scale)
|
2016-10-07 16:34:55 +02:00
|
|
|
{
|
2017-06-10 10:42:35 +10:00
|
|
|
mpr->user_scale = scale;
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
|
2017-06-10 10:42:35 +10:00
|
|
|
void WM_manipulator_set_line_width(wmManipulator *mpr, const float line_width)
|
2016-10-07 16:34:55 +02:00
|
|
|
{
|
2017-06-10 10:42:35 +10:00
|
|
|
mpr->line_width = line_width;
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set manipulator rgba colors.
|
|
|
|
|
*
|
|
|
|
|
* \param col Normal state color.
|
|
|
|
|
* \param col_hi Highlighted state color.
|
|
|
|
|
*/
|
2017-06-10 10:42:35 +10:00
|
|
|
void WM_manipulator_get_color(const wmManipulator *mpr, float col[4])
|
2017-06-07 22:12:32 +10:00
|
|
|
{
|
2017-06-10 10:42:35 +10:00
|
|
|
copy_v4_v4(col, mpr->color);
|
2017-06-07 22:12:32 +10:00
|
|
|
}
|
2017-06-10 10:42:35 +10:00
|
|
|
void WM_manipulator_set_color(wmManipulator *mpr, const float col[4])
|
2016-10-07 16:34:55 +02:00
|
|
|
{
|
2017-06-10 10:42:35 +10:00
|
|
|
copy_v4_v4(mpr->color, col);
|
2017-06-07 22:12:32 +10:00
|
|
|
}
|
|
|
|
|
|
2017-06-10 10:42:35 +10:00
|
|
|
void WM_manipulator_get_color_highlight(const wmManipulator *mpr, float color_hi[4])
|
2017-06-07 22:12:32 +10:00
|
|
|
{
|
2017-06-10 10:42:35 +10:00
|
|
|
copy_v4_v4(color_hi, mpr->color_hi);
|
2017-06-07 22:12:32 +10:00
|
|
|
}
|
2017-06-10 10:42:35 +10:00
|
|
|
void WM_manipulator_set_color_highlight(wmManipulator *mpr, const float color_hi[4])
|
2017-06-07 22:12:32 +10:00
|
|
|
{
|
2017-06-10 10:42:35 +10:00
|
|
|
copy_v4_v4(mpr->color_hi, color_hi);
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
2017-06-07 22:12:32 +10:00
|
|
|
|
|
|
|
|
|
2016-10-07 16:34:55 +02:00
|
|
|
/** \} */ // Manipulator Creation API
|
|
|
|
|
|
|
|
|
|
|
2017-06-06 17:07:26 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Manipulator Callback Assignment
|
|
|
|
|
*
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2017-06-10 10:42:35 +10:00
|
|
|
void WM_manipulator_set_fn_custom_modal(struct wmManipulator *mpr, wmManipulatorFnModal fn)
|
2017-06-06 17:07:26 +10:00
|
|
|
{
|
2017-06-10 10:42:35 +10:00
|
|
|
mpr->custom_modal = fn;
|
2017-06-06 17:07:26 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
|
2016-10-07 16:34:55 +02:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Remove \a manipulator from selection.
|
|
|
|
|
* Reallocates memory for selected manipulators so better not call for selecting multiple ones.
|
|
|
|
|
*
|
|
|
|
|
* \return if the selection has changed.
|
|
|
|
|
*/
|
2017-06-10 10:42:35 +10:00
|
|
|
bool wm_manipulator_deselect(wmManipulatorMap *mmap, wmManipulator *mpr)
|
2016-10-07 16:34:55 +02:00
|
|
|
{
|
2017-06-10 10:42:35 +10:00
|
|
|
if (!mmap->mmap_context.selected)
|
2016-10-07 16:34:55 +02:00
|
|
|
return false;
|
|
|
|
|
|
2017-06-10 10:42:35 +10:00
|
|
|
wmManipulator ***sel = &mmap->mmap_context.selected;
|
|
|
|
|
int *selected_len = &mmap->mmap_context.selected_len;
|
2016-10-07 16:34:55 +02:00
|
|
|
bool changed = false;
|
|
|
|
|
|
|
|
|
|
/* caller should check! */
|
2017-06-10 10:42:35 +10:00
|
|
|
BLI_assert(mpr->state & WM_MANIPULATOR_STATE_SELECT);
|
2016-10-07 16:34:55 +02:00
|
|
|
|
|
|
|
|
/* remove manipulator from selected_manipulators array */
|
2017-06-10 10:42:35 +10:00
|
|
|
for (int i = 0; i < (*selected_len); i++) {
|
|
|
|
|
if ((*sel)[i] == mpr) {
|
|
|
|
|
for (int j = i; j < ((*selected_len) - 1); j++) {
|
2016-10-07 16:34:55 +02:00
|
|
|
(*sel)[j] = (*sel)[j + 1];
|
|
|
|
|
}
|
|
|
|
|
changed = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* update array data */
|
2017-06-10 10:42:35 +10:00
|
|
|
if ((*selected_len) <= 1) {
|
|
|
|
|
wm_manipulatormap_selected_clear(mmap);
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2017-06-10 10:42:35 +10:00
|
|
|
*sel = MEM_reallocN(*sel, sizeof(**sel) * (*selected_len));
|
|
|
|
|
(*selected_len)--;
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
|
2017-06-10 10:42:35 +10:00
|
|
|
mpr->state &= ~WM_MANIPULATOR_STATE_SELECT;
|
2016-10-07 16:34:55 +02:00
|
|
|
return changed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add \a manipulator to selection.
|
|
|
|
|
* Reallocates memory for selected manipulators so better not call for selecting multiple ones.
|
|
|
|
|
*
|
|
|
|
|
* \return if the selection has changed.
|
|
|
|
|
*/
|
2017-06-10 10:42:35 +10:00
|
|
|
bool wm_manipulator_select(bContext *C, wmManipulatorMap *mmap, wmManipulator *mpr)
|
2016-10-07 16:34:55 +02:00
|
|
|
{
|
2017-06-10 10:42:35 +10:00
|
|
|
wmManipulator ***sel = &mmap->mmap_context.selected;
|
|
|
|
|
int *selected_len = &mmap->mmap_context.selected_len;
|
2016-10-07 16:34:55 +02:00
|
|
|
|
2017-06-10 10:42:35 +10:00
|
|
|
if (!mpr || (mpr->state & WM_MANIPULATOR_STATE_SELECT))
|
2016-10-07 16:34:55 +02:00
|
|
|
return false;
|
|
|
|
|
|
2017-06-10 10:42:35 +10:00
|
|
|
(*selected_len)++;
|
2016-10-07 16:34:55 +02:00
|
|
|
|
2017-06-10 10:42:35 +10:00
|
|
|
*sel = MEM_reallocN(*sel, sizeof(wmManipulator *) * (*selected_len));
|
|
|
|
|
(*sel)[(*selected_len) - 1] = mpr;
|
2016-10-07 16:34:55 +02:00
|
|
|
|
2017-06-10 10:42:35 +10:00
|
|
|
mpr->state |= WM_MANIPULATOR_STATE_SELECT;
|
|
|
|
|
if (mpr->type->select) {
|
|
|
|
|
mpr->type->select(C, mpr, SEL_SELECT);
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
2017-06-10 10:42:35 +10:00
|
|
|
wm_manipulatormap_highlight_set(mmap, C, mpr, mpr->highlight_part);
|
2016-10-07 16:34:55 +02:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-10 10:42:35 +10:00
|
|
|
void wm_manipulator_calculate_scale(wmManipulator *mpr, const bContext *C)
|
2016-10-07 16:34:55 +02:00
|
|
|
{
|
|
|
|
|
const RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
2017-06-19 18:22:04 +10:00
|
|
|
float scale = U.ui_scale;
|
2016-10-07 16:34:55 +02:00
|
|
|
|
2017-06-10 10:42:35 +10:00
|
|
|
if (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_SCALE_3D) {
|
2017-06-19 18:22:04 +10:00
|
|
|
scale *= U.manipulator_size;
|
2017-06-19 17:47:04 +10:00
|
|
|
if (rv3d) {
|
2017-06-19 18:22:04 +10:00
|
|
|
/* 'ED_view3d_pixel_size' includes 'U.pixelsize', remove it. */
|
2017-06-18 05:38:10 +10:00
|
|
|
if (mpr->type->matrix_world_get) {
|
|
|
|
|
float matrix_world[4][4];
|
2016-10-07 16:34:55 +02:00
|
|
|
|
2017-06-18 05:38:10 +10:00
|
|
|
mpr->type->matrix_world_get(mpr, matrix_world);
|
2017-06-19 18:22:04 +10:00
|
|
|
scale *= ED_view3d_pixel_size(rv3d, matrix_world[3]) / U.pixelsize;
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2017-06-19 18:22:04 +10:00
|
|
|
scale *= ED_view3d_pixel_size(rv3d, mpr->matrix[3]) / U.pixelsize;
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2017-06-19 18:22:04 +10:00
|
|
|
scale *= 0.02f;
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-10 10:42:35 +10:00
|
|
|
mpr->scale = scale * mpr->user_scale;
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
|
2017-06-10 10:42:35 +10:00
|
|
|
static void manipulator_update_prop_data(wmManipulator *mpr)
|
2016-10-07 16:34:55 +02:00
|
|
|
{
|
|
|
|
|
/* manipulator property might have been changed, so update manipulator */
|
2017-06-10 10:42:35 +10:00
|
|
|
if (mpr->type->property_update && !BLI_listbase_is_empty(&mpr->properties)) {
|
|
|
|
|
for (wmManipulatorProperty *mpr_prop = mpr->properties.first; mpr_prop; mpr_prop = mpr_prop->next) {
|
2017-06-15 20:48:24 +10:00
|
|
|
if (WM_manipulator_property_is_valid(mpr_prop)) {
|
2017-06-10 10:42:35 +10:00
|
|
|
mpr->type->property_update(mpr, mpr_prop);
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-10 10:42:35 +10:00
|
|
|
void wm_manipulator_update(wmManipulator *mpr, const bContext *C, const bool refresh_map)
|
2016-10-07 16:34:55 +02:00
|
|
|
{
|
|
|
|
|
if (refresh_map) {
|
2017-06-10 10:42:35 +10:00
|
|
|
manipulator_update_prop_data(mpr);
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
2017-06-10 10:42:35 +10:00
|
|
|
wm_manipulator_calculate_scale(mpr, C);
|
2016-10-07 16:34:55 +02:00
|
|
|
}
|
|
|
|
|
|
2017-06-10 10:42:35 +10:00
|
|
|
bool wm_manipulator_is_visible(wmManipulator *mpr)
|
2016-10-07 16:34:55 +02:00
|
|
|
{
|
2017-06-10 10:42:35 +10:00
|
|
|
if (mpr->flag & WM_MANIPULATOR_HIDDEN) {
|
2016-10-07 16:34:55 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
2017-06-10 10:42:35 +10:00
|
|
|
if ((mpr->state & WM_MANIPULATOR_STATE_ACTIVE) &&
|
|
|
|
|
!(mpr->flag & (WM_MANIPULATOR_DRAW_ACTIVE | WM_MANIPULATOR_DRAW_VALUE)))
|
2016-10-07 16:34:55 +02:00
|
|
|
{
|
|
|
|
|
/* don't draw while active (while dragging) */
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2017-06-10 10:42:35 +10:00
|
|
|
if ((mpr->flag & WM_MANIPULATOR_DRAW_HOVER) &&
|
|
|
|
|
!(mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) &&
|
|
|
|
|
!(mpr->state & WM_MANIPULATOR_STATE_SELECT)) /* still draw selected manipulators */
|
2016-10-07 16:34:55 +02:00
|
|
|
{
|
|
|
|
|
/* only draw on mouse hover */
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|