2023-05-31 16:19:06 +02:00
|
|
|
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2019-08-22 13:45:31 +10:00
|
|
|
|
|
|
|
|
/** \file
|
|
|
|
|
* \ingroup edobj
|
|
|
|
|
*
|
|
|
|
|
* Use to transform object origins only.
|
|
|
|
|
*
|
|
|
|
|
* This is a small API to store & apply transformations to object data,
|
2022-09-16 18:13:19 +10:00
|
|
|
* where a transformation matrix can be continually applied on top of the original values
|
2019-08-22 13:45:31 +10:00
|
|
|
* so we don't lose precision over time.
|
|
|
|
|
*/
|
|
|
|
|
|
2023-03-02 23:14:33 +01:00
|
|
|
#include <cstdlib>
|
|
|
|
|
#include <cstring>
|
2019-08-22 13:45:31 +10:00
|
|
|
|
|
|
|
|
#include "DNA_armature_types.h"
|
2023-03-13 10:42:51 +01:00
|
|
|
#include "DNA_gpencil_legacy_types.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_lattice_types.h"
|
2019-08-22 13:45:31 +10:00
|
|
|
#include "DNA_mesh_types.h"
|
|
|
|
|
#include "DNA_meta_types.h"
|
|
|
|
|
#include "DNA_object_types.h"
|
2025-02-16 20:48:46 -05:00
|
|
|
#include "DNA_pointcloud_types.h"
|
2019-08-22 13:45:31 +10:00
|
|
|
|
|
|
|
|
#include "BLI_listbase.h"
|
Cleanup: reduce amount of math-related includes
Using ClangBuildAnalyzer on the whole Blender build, it was pointing
out that BLI_math.h is the heaviest "header hub" (i.e. non tiny file
that is included a lot).
However, there's very little (actually zero) source files in Blender
that need "all the math" (base, colors, vectors, matrices,
quaternions, intersection, interpolation, statistics, solvers and
time). A common use case is source files needing just vectors, or
just vectors & matrices, or just colors etc. Actually, 181 files
were including the whole math thing without needing it at all.
This change removes BLI_math.h completely, and instead in all the
places that need it, includes BLI_math_vector.h or BLI_math_color.h
and so on.
Change from that:
- BLI_math_color.h was included 1399 times -> now 408 (took 114.0sec
to parse -> now 36.3sec)
- BLI_simd.h 1403 -> 418 (109.7sec -> 34.9sec).
Full rebuild of Blender (Apple M1, Xcode, RelWithDebInfo) is not
affected much (342sec -> 334sec). Most of benefit would be when
someone's changing BLI_simd.h or BLI_math_color.h or similar files,
that now there's 3x fewer files result in a recompile.
Pull Request #110944
2023-08-09 11:39:20 +03:00
|
|
|
#include "BLI_math_matrix.h"
|
|
|
|
|
#include "BLI_math_rotation.h"
|
|
|
|
|
#include "BLI_math_vector.h"
|
2025-02-16 20:31:09 -05:00
|
|
|
#include "BLI_task.hh"
|
2019-08-22 13:45:31 +10:00
|
|
|
|
2023-11-16 11:41:55 +01:00
|
|
|
#include "BKE_armature.hh"
|
|
|
|
|
#include "BKE_curve.hh"
|
2025-05-17 10:38:01 +02:00
|
|
|
#include "BKE_curves_utils.hh"
|
2023-11-16 11:41:55 +01:00
|
|
|
#include "BKE_editmesh.hh"
|
2024-09-13 17:06:43 +02:00
|
|
|
#include "BKE_grease_pencil.hh"
|
2024-01-30 14:42:07 -05:00
|
|
|
#include "BKE_key.hh"
|
2023-11-16 11:41:55 +01:00
|
|
|
#include "BKE_lattice.hh"
|
2024-01-24 11:33:47 -05:00
|
|
|
#include "BKE_mball.hh"
|
2024-03-21 23:18:49 +01:00
|
|
|
#include "BKE_mesh_types.hh"
|
2019-08-22 13:45:31 +10:00
|
|
|
|
2023-12-05 23:01:12 +01:00
|
|
|
#include "bmesh.hh"
|
2019-11-21 21:03:03 +11:00
|
|
|
|
2023-09-22 03:18:17 +02:00
|
|
|
#include "DEG_depsgraph.hh"
|
2019-08-22 13:45:31 +10:00
|
|
|
|
2023-08-05 02:57:52 +02:00
|
|
|
#include "ED_armature.hh"
|
2025-01-29 09:57:36 +01:00
|
|
|
#include "ED_curves.hh"
|
2023-08-05 02:57:52 +02:00
|
|
|
#include "ED_mesh.hh"
|
|
|
|
|
#include "ED_object.hh"
|
2019-08-22 13:45:31 +10:00
|
|
|
|
2024-03-28 01:30:38 +01:00
|
|
|
namespace blender::ed::object {
|
|
|
|
|
|
2019-08-22 13:45:31 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Internal Transform Get/Apply
|
|
|
|
|
*
|
|
|
|
|
* Some object data types don't have utility functions to access their transformation data.
|
|
|
|
|
* Define these locally.
|
|
|
|
|
*
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
/* Armature */
|
|
|
|
|
|
|
|
|
|
struct ElemData_Armature {
|
|
|
|
|
float tail[3];
|
|
|
|
|
float head[3];
|
|
|
|
|
float roll;
|
|
|
|
|
float arm_tail[3];
|
|
|
|
|
float arm_head[3];
|
|
|
|
|
float arm_roll;
|
|
|
|
|
float rad_tail;
|
|
|
|
|
float rad_head;
|
|
|
|
|
float dist;
|
|
|
|
|
float xwidth;
|
|
|
|
|
float zwidth;
|
|
|
|
|
};
|
|
|
|
|
|
2023-03-02 23:14:33 +01:00
|
|
|
static ElemData_Armature *armature_coords_and_quats_get_recurse(const ListBase *bone_base,
|
|
|
|
|
ElemData_Armature *elem_array)
|
2019-08-22 13:45:31 +10:00
|
|
|
{
|
2023-03-02 23:14:33 +01:00
|
|
|
ElemData_Armature *elem = elem_array;
|
2020-04-03 19:15:01 +02:00
|
|
|
LISTBASE_FOREACH (const Bone *, bone, bone_base) {
|
2019-08-22 13:45:31 +10:00
|
|
|
|
|
|
|
|
#define COPY_PTR(member) memcpy(elem->member, bone->member, sizeof(bone->member))
|
|
|
|
|
#define COPY_VAL(member) memcpy(&elem->member, &bone->member, sizeof(bone->member))
|
|
|
|
|
COPY_PTR(head);
|
|
|
|
|
COPY_PTR(tail);
|
|
|
|
|
COPY_VAL(roll);
|
|
|
|
|
COPY_PTR(arm_head);
|
|
|
|
|
COPY_PTR(arm_tail);
|
|
|
|
|
COPY_VAL(arm_roll);
|
|
|
|
|
COPY_VAL(rad_tail);
|
|
|
|
|
COPY_VAL(rad_head);
|
|
|
|
|
COPY_VAL(dist);
|
|
|
|
|
COPY_VAL(xwidth);
|
|
|
|
|
COPY_VAL(zwidth);
|
|
|
|
|
#undef COPY_PTR
|
|
|
|
|
#undef COPY_VAL
|
|
|
|
|
|
|
|
|
|
elem = armature_coords_and_quats_get_recurse(&bone->childbase, elem + 1);
|
|
|
|
|
}
|
|
|
|
|
return elem;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
static void armature_coords_and_quats_get(const bArmature *arm,
|
|
|
|
|
MutableSpan<ElemData_Armature> elem_array)
|
2019-08-22 13:45:31 +10:00
|
|
|
{
|
2025-02-16 20:31:09 -05:00
|
|
|
armature_coords_and_quats_get_recurse(&arm->bonebase, elem_array.data());
|
2019-08-22 13:45:31 +10:00
|
|
|
}
|
|
|
|
|
|
2023-03-02 23:14:33 +01:00
|
|
|
static const ElemData_Armature *armature_coords_and_quats_apply_with_mat4_recurse(
|
2025-02-16 20:31:09 -05:00
|
|
|
ListBase *bone_base, const ElemData_Armature *elem_array, const float4x4 &transform)
|
2019-08-22 13:45:31 +10:00
|
|
|
{
|
2023-03-02 23:14:33 +01:00
|
|
|
const ElemData_Armature *elem = elem_array;
|
2020-04-03 19:15:01 +02:00
|
|
|
LISTBASE_FOREACH (Bone *, bone, bone_base) {
|
2019-08-22 13:45:31 +10:00
|
|
|
|
|
|
|
|
#define COPY_PTR(member) memcpy(bone->member, elem->member, sizeof(bone->member))
|
|
|
|
|
#define COPY_VAL(member) memcpy(&bone->member, &elem->member, sizeof(bone->member))
|
|
|
|
|
COPY_PTR(head);
|
|
|
|
|
COPY_PTR(tail);
|
|
|
|
|
COPY_VAL(roll);
|
|
|
|
|
COPY_PTR(arm_head);
|
|
|
|
|
COPY_PTR(arm_tail);
|
|
|
|
|
COPY_VAL(arm_roll);
|
|
|
|
|
COPY_VAL(rad_tail);
|
|
|
|
|
COPY_VAL(rad_head);
|
|
|
|
|
COPY_VAL(dist);
|
|
|
|
|
COPY_VAL(xwidth);
|
|
|
|
|
COPY_VAL(zwidth);
|
|
|
|
|
#undef COPY_PTR
|
|
|
|
|
#undef COPY_VAL
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
elem = armature_coords_and_quats_apply_with_mat4_recurse(
|
|
|
|
|
&bone->childbase, elem + 1, transform);
|
2019-08-22 13:45:31 +10:00
|
|
|
}
|
|
|
|
|
return elem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void armature_coords_and_quats_apply_with_mat4(bArmature *arm,
|
2025-02-16 20:31:09 -05:00
|
|
|
const Span<ElemData_Armature> elem_array,
|
|
|
|
|
const float4x4 &transform)
|
2019-08-22 13:45:31 +10:00
|
|
|
{
|
2025-02-16 20:31:09 -05:00
|
|
|
armature_coords_and_quats_apply_with_mat4_recurse(&arm->bonebase, elem_array.data(), transform);
|
|
|
|
|
BKE_armature_transform(arm, transform.ptr(), true);
|
2019-08-22 13:45:31 +10:00
|
|
|
}
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
static void armature_coords_and_quats_apply(bArmature *arm,
|
|
|
|
|
const Span<ElemData_Armature> elem_array)
|
2019-11-21 21:03:03 +11:00
|
|
|
{
|
|
|
|
|
/* Avoid code duplication by using a unit matrix. */
|
2025-02-16 20:31:09 -05:00
|
|
|
armature_coords_and_quats_apply_with_mat4(arm, elem_array, float4x4::identity());
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Edit Armature */
|
2025-02-16 20:31:09 -05:00
|
|
|
static void edit_armature_coords_and_quats_get(const bArmature *arm,
|
|
|
|
|
MutableSpan<ElemData_Armature> elem_array)
|
2019-11-21 21:03:03 +11:00
|
|
|
{
|
2025-02-16 20:31:09 -05:00
|
|
|
ElemData_Armature *elem = elem_array.data();
|
2023-03-02 23:14:33 +01:00
|
|
|
for (EditBone *ebone = static_cast<EditBone *>(arm->edbo->first); ebone;
|
|
|
|
|
ebone = ebone->next, elem++)
|
|
|
|
|
{
|
2019-11-21 21:03:03 +11:00
|
|
|
|
|
|
|
|
#define COPY_PTR(member) memcpy(elem->member, ebone->member, sizeof(ebone->member))
|
|
|
|
|
#define COPY_VAL(member) memcpy(&elem->member, &ebone->member, sizeof(ebone->member))
|
|
|
|
|
/* Unused for edit bones: arm_head, arm_tail, arm_roll */
|
|
|
|
|
COPY_PTR(head);
|
|
|
|
|
COPY_PTR(tail);
|
|
|
|
|
COPY_VAL(roll);
|
|
|
|
|
COPY_VAL(rad_tail);
|
|
|
|
|
COPY_VAL(rad_head);
|
|
|
|
|
COPY_VAL(dist);
|
|
|
|
|
COPY_VAL(xwidth);
|
|
|
|
|
COPY_VAL(zwidth);
|
|
|
|
|
#undef COPY_PTR
|
|
|
|
|
#undef COPY_VAL
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
static void edit_armature_coords_and_quats_apply_with_mat4(
|
|
|
|
|
bArmature *arm, const Span<ElemData_Armature> elem_array, const float4x4 &transform)
|
2019-11-21 21:03:03 +11:00
|
|
|
{
|
2025-02-16 20:31:09 -05:00
|
|
|
const ElemData_Armature *elem = elem_array.data();
|
2023-03-02 23:14:33 +01:00
|
|
|
for (EditBone *ebone = static_cast<EditBone *>(arm->edbo->first); ebone;
|
|
|
|
|
ebone = ebone->next, elem++)
|
|
|
|
|
{
|
2019-11-21 21:03:03 +11:00
|
|
|
|
|
|
|
|
#define COPY_PTR(member) memcpy(ebone->member, elem->member, sizeof(ebone->member))
|
|
|
|
|
#define COPY_VAL(member) memcpy(&ebone->member, &elem->member, sizeof(ebone->member))
|
|
|
|
|
/* Unused for edit bones: arm_head, arm_tail, arm_roll */
|
|
|
|
|
COPY_PTR(head);
|
|
|
|
|
COPY_PTR(tail);
|
|
|
|
|
COPY_VAL(roll);
|
|
|
|
|
COPY_VAL(rad_tail);
|
|
|
|
|
COPY_VAL(rad_head);
|
|
|
|
|
COPY_VAL(dist);
|
|
|
|
|
COPY_VAL(xwidth);
|
|
|
|
|
COPY_VAL(zwidth);
|
|
|
|
|
#undef COPY_PTR
|
|
|
|
|
#undef COPY_VAL
|
|
|
|
|
}
|
2025-02-16 20:31:09 -05:00
|
|
|
ED_armature_edit_transform(arm, transform.ptr(), true);
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void edit_armature_coords_and_quats_apply(bArmature *arm,
|
2025-02-16 20:31:09 -05:00
|
|
|
const Span<ElemData_Armature> elem_array)
|
2019-11-21 21:03:03 +11:00
|
|
|
{
|
|
|
|
|
/* Avoid code duplication by using a unit matrix. */
|
2025-02-16 20:31:09 -05:00
|
|
|
edit_armature_coords_and_quats_apply_with_mat4(arm, elem_array, float4x4::identity());
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
|
|
|
|
|
2019-08-22 13:45:31 +10:00
|
|
|
/* MetaBall */
|
|
|
|
|
|
|
|
|
|
struct ElemData_MetaBall {
|
|
|
|
|
float co[3];
|
|
|
|
|
float quat[4];
|
|
|
|
|
float exp[3];
|
|
|
|
|
float rad;
|
|
|
|
|
};
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
static void metaball_coords_and_quats_get(const MetaBall *mb,
|
|
|
|
|
MutableSpan<ElemData_MetaBall> elem_array)
|
2019-08-22 13:45:31 +10:00
|
|
|
{
|
2025-02-16 20:31:09 -05:00
|
|
|
ElemData_MetaBall *elem = elem_array.data();
|
2023-03-02 23:14:33 +01:00
|
|
|
for (const MetaElem *ml = static_cast<const MetaElem *>(mb->elems.first); ml;
|
|
|
|
|
ml = ml->next, elem++)
|
|
|
|
|
{
|
2019-08-22 13:45:31 +10:00
|
|
|
copy_v3_v3(elem->co, &ml->x);
|
|
|
|
|
copy_qt_qt(elem->quat, ml->quat);
|
|
|
|
|
copy_v3_v3(elem->exp, &ml->expx);
|
|
|
|
|
elem->rad = ml->rad;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void metaball_coords_and_quats_apply_with_mat4(MetaBall *mb,
|
2025-02-16 20:31:09 -05:00
|
|
|
const Span<ElemData_MetaBall> elem_array,
|
|
|
|
|
const float4x4 &transform)
|
2019-08-22 13:45:31 +10:00
|
|
|
{
|
2025-02-16 20:31:09 -05:00
|
|
|
const ElemData_MetaBall *elem = elem_array.data();
|
2023-03-02 23:14:33 +01:00
|
|
|
for (MetaElem *ml = static_cast<MetaElem *>(mb->elems.first); ml; ml = ml->next, elem++) {
|
2019-08-22 13:45:31 +10:00
|
|
|
copy_v3_v3(&ml->x, elem->co);
|
|
|
|
|
copy_qt_qt(ml->quat, elem->quat);
|
|
|
|
|
copy_v3_v3(&ml->expx, elem->exp);
|
|
|
|
|
ml->rad = elem->rad;
|
|
|
|
|
}
|
2025-02-16 20:31:09 -05:00
|
|
|
BKE_mball_transform(mb, transform.ptr(), true);
|
2019-08-22 13:45:31 +10:00
|
|
|
}
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
static void metaball_coords_and_quats_apply(MetaBall *mb, const Span<ElemData_MetaBall> elem_array)
|
2019-11-21 21:03:03 +11:00
|
|
|
{
|
|
|
|
|
/* Avoid code duplication by using a unit matrix. */
|
2025-02-16 20:31:09 -05:00
|
|
|
metaball_coords_and_quats_apply_with_mat4(mb, elem_array, float4x4::identity());
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
|
|
|
|
|
2019-08-22 13:45:31 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Public Object Data Storage API
|
|
|
|
|
*
|
|
|
|
|
* Used for interactively transforming object data.
|
|
|
|
|
*
|
|
|
|
|
* Store object data transformation in an opaque struct.
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
struct XFormObjectData_Mesh : public XFormObjectData {
|
2020-07-25 16:35:52 +10:00
|
|
|
/* Optional data for shape keys. */
|
2025-02-16 20:31:09 -05:00
|
|
|
Array<float3> key_data;
|
|
|
|
|
Array<float3> positions;
|
|
|
|
|
bool is_edit_mode = false;
|
|
|
|
|
virtual ~XFormObjectData_Mesh() = default;
|
2019-08-22 13:45:31 +10:00
|
|
|
};
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
struct XFormObjectData_Lattice : public XFormObjectData {
|
2020-07-25 16:35:52 +10:00
|
|
|
/* Optional data for shape keys. */
|
2025-02-16 20:31:09 -05:00
|
|
|
Array<float3> key_data;
|
|
|
|
|
Array<float3> positions;
|
|
|
|
|
bool is_edit_mode = false;
|
|
|
|
|
virtual ~XFormObjectData_Lattice() = default;
|
2019-08-22 13:45:31 +10:00
|
|
|
};
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
struct XFormObjectData_Curve : public XFormObjectData {
|
2020-07-25 16:35:52 +10:00
|
|
|
/* Optional data for shape keys. */
|
2025-02-16 20:31:09 -05:00
|
|
|
Array<float3> key_data;
|
|
|
|
|
Array<float3> positions;
|
|
|
|
|
bool is_edit_mode = false;
|
|
|
|
|
virtual ~XFormObjectData_Curve() = default;
|
2019-08-22 13:45:31 +10:00
|
|
|
};
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
struct XFormObjectData_Armature : public XFormObjectData {
|
|
|
|
|
Array<ElemData_Armature> elems;
|
|
|
|
|
bool is_edit_mode = false;
|
|
|
|
|
virtual ~XFormObjectData_Armature() = default;
|
2019-08-22 13:45:31 +10:00
|
|
|
};
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
struct XFormObjectData_MetaBall : public XFormObjectData {
|
|
|
|
|
Array<ElemData_MetaBall> elems;
|
|
|
|
|
bool is_edit_mode = false;
|
|
|
|
|
virtual ~XFormObjectData_MetaBall() = default;
|
2024-09-13 17:06:43 +02:00
|
|
|
};
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
struct XFormObjectData_GreasePencil : public XFormObjectData {
|
|
|
|
|
Array<float3> positions;
|
|
|
|
|
Array<float> radii;
|
|
|
|
|
virtual ~XFormObjectData_GreasePencil() = default;
|
2025-01-29 09:57:36 +01:00
|
|
|
};
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
struct XFormObjectData_Curves : public XFormObjectData {
|
|
|
|
|
Array<float3> positions;
|
|
|
|
|
Array<float> radii;
|
|
|
|
|
virtual ~XFormObjectData_Curves() = default;
|
2025-01-29 09:57:36 +01:00
|
|
|
};
|
|
|
|
|
|
2025-02-16 20:48:46 -05:00
|
|
|
struct XFormObjectData_PointCloud : public XFormObjectData {
|
|
|
|
|
Array<float3> positions;
|
|
|
|
|
Array<float> radii;
|
|
|
|
|
virtual ~XFormObjectData_PointCloud() = default;
|
|
|
|
|
};
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
static std::unique_ptr<XFormObjectData> data_xform_create_ex(ID *id, bool is_edit_mode)
|
2019-08-22 13:45:31 +10:00
|
|
|
{
|
2023-03-02 23:14:33 +01:00
|
|
|
if (id == nullptr) {
|
2025-02-16 20:31:09 -05:00
|
|
|
return {};
|
2020-01-27 11:46:01 +01:00
|
|
|
}
|
2020-07-25 16:35:52 +10:00
|
|
|
|
2019-08-22 13:45:31 +10:00
|
|
|
switch (GS(id->name)) {
|
|
|
|
|
case ID_ME: {
|
2023-12-08 16:40:06 -05:00
|
|
|
Mesh *mesh = (Mesh *)id;
|
|
|
|
|
Key *key = mesh->key;
|
2020-07-25 16:35:52 +10:00
|
|
|
const int key_index = -1;
|
|
|
|
|
|
2019-11-21 21:03:03 +11:00
|
|
|
if (is_edit_mode) {
|
2024-03-21 23:18:49 +01:00
|
|
|
BMesh *bm = mesh->runtime->edit_mesh->bm;
|
2020-07-25 16:35:52 +10:00
|
|
|
/* Always operate on all keys for the moment. */
|
|
|
|
|
// key_index = bm->shapenr - 1;
|
2025-02-16 20:31:09 -05:00
|
|
|
auto xod = std::make_unique<XFormObjectData_Mesh>();
|
|
|
|
|
xod->id = id;
|
|
|
|
|
xod->is_edit_mode = is_edit_mode;
|
|
|
|
|
xod->positions.reinitialize(bm->totvert);
|
2020-07-25 16:35:52 +10:00
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
BM_mesh_vert_coords_get(bm, xod->positions.as_mutable_span());
|
2020-07-25 16:35:52 +10:00
|
|
|
|
2023-03-02 23:14:33 +01:00
|
|
|
if (key != nullptr) {
|
2020-07-25 16:35:52 +10:00
|
|
|
const size_t key_size = BKE_keyblock_element_calc_size_from_shape(key, key_index);
|
|
|
|
|
if (key_size) {
|
2025-02-16 20:31:09 -05:00
|
|
|
xod->key_data.reinitialize(key_size);
|
|
|
|
|
BKE_keyblock_data_get_from_shape(key, xod->key_data, key_index);
|
2020-07-25 16:35:52 +10:00
|
|
|
}
|
|
|
|
|
}
|
2025-02-16 20:31:09 -05:00
|
|
|
return xod;
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
2020-07-25 16:35:52 +10:00
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
auto xod = std::make_unique<XFormObjectData_Mesh>();
|
|
|
|
|
xod->id = id;
|
|
|
|
|
xod->is_edit_mode = is_edit_mode;
|
|
|
|
|
xod->positions = mesh->vert_positions();
|
2020-07-25 16:35:52 +10:00
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
if (key != nullptr) {
|
|
|
|
|
const size_t key_size = BKE_keyblock_element_calc_size_from_shape(key, key_index);
|
|
|
|
|
if (key_size) {
|
|
|
|
|
xod->key_data.reinitialize(key_size);
|
|
|
|
|
BKE_keyblock_data_get_from_shape(key, xod->key_data, key_index);
|
2020-07-25 16:35:52 +10:00
|
|
|
}
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
2025-02-16 20:31:09 -05:00
|
|
|
return xod;
|
2019-08-22 13:45:31 +10:00
|
|
|
}
|
|
|
|
|
case ID_LT: {
|
2019-11-21 21:03:03 +11:00
|
|
|
Lattice *lt_orig = (Lattice *)id;
|
|
|
|
|
Lattice *lt = is_edit_mode ? lt_orig->editlatt->latt : lt_orig;
|
2023-03-02 23:14:33 +01:00
|
|
|
Key *key = lt->key;
|
2020-07-25 16:35:52 +10:00
|
|
|
const int key_index = -1;
|
|
|
|
|
|
|
|
|
|
if (is_edit_mode) {
|
|
|
|
|
/* Always operate on all keys for the moment. */
|
|
|
|
|
// key_index = lt_orig->editlatt->shapenr - 1;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
auto xod = std::make_unique<XFormObjectData_Lattice>();
|
|
|
|
|
xod->id = id;
|
|
|
|
|
xod->is_edit_mode = is_edit_mode;
|
|
|
|
|
xod->positions = BKE_lattice_vert_coords_alloc(lt);
|
2020-07-25 16:35:52 +10:00
|
|
|
|
2023-03-02 23:14:33 +01:00
|
|
|
if (key != nullptr) {
|
2020-07-25 16:35:52 +10:00
|
|
|
const size_t key_size = BKE_keyblock_element_calc_size_from_shape(key, key_index);
|
|
|
|
|
if (key_size) {
|
2025-02-16 20:31:09 -05:00
|
|
|
xod->key_data.reinitialize(key_size);
|
|
|
|
|
BKE_keyblock_data_get_from_shape(key, xod->key_data, key_index);
|
2020-07-25 16:35:52 +10:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
return xod;
|
2019-08-22 13:45:31 +10:00
|
|
|
}
|
2022-02-18 09:50:29 -06:00
|
|
|
case ID_CU_LEGACY: {
|
2019-08-22 13:45:31 +10:00
|
|
|
Curve *cu = (Curve *)id;
|
2023-03-02 23:14:33 +01:00
|
|
|
Key *key = cu->key;
|
2020-07-25 16:35:52 +10:00
|
|
|
|
2025-05-20 10:11:56 +00:00
|
|
|
if (cu->ob_type == OB_FONT) {
|
2019-08-22 13:45:31 +10:00
|
|
|
/* We could support translation. */
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-11-21 21:03:03 +11:00
|
|
|
|
2020-07-25 16:35:52 +10:00
|
|
|
const int key_index = -1;
|
2019-11-21 21:03:03 +11:00
|
|
|
ListBase *nurbs;
|
|
|
|
|
if (is_edit_mode) {
|
|
|
|
|
EditNurb *editnurb = cu->editnurb;
|
|
|
|
|
nurbs = &editnurb->nurbs;
|
2020-07-25 16:35:52 +10:00
|
|
|
/* Always operate on all keys for the moment. */
|
|
|
|
|
// key_index = editnurb->shapenr - 1;
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
nurbs = &cu->nurb;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
auto xod = std::make_unique<XFormObjectData_Curve>();
|
|
|
|
|
xod->id = id;
|
|
|
|
|
xod->is_edit_mode = is_edit_mode;
|
|
|
|
|
xod->positions = BKE_curve_nurbs_vert_coords_alloc(nurbs);
|
2020-07-25 16:35:52 +10:00
|
|
|
|
2023-03-02 23:14:33 +01:00
|
|
|
if (key != nullptr) {
|
2020-07-25 16:35:52 +10:00
|
|
|
const size_t key_size = BKE_keyblock_element_calc_size_from_shape(key, key_index);
|
|
|
|
|
if (key_size) {
|
2025-02-16 20:31:09 -05:00
|
|
|
xod->key_data.reinitialize(key_size);
|
|
|
|
|
BKE_keyblock_data_get_from_shape(key, xod->key_data, key_index);
|
2020-07-25 16:35:52 +10:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
return xod;
|
2019-08-22 13:45:31 +10:00
|
|
|
}
|
|
|
|
|
case ID_AR: {
|
|
|
|
|
bArmature *arm = (bArmature *)id;
|
2019-11-21 21:03:03 +11:00
|
|
|
if (is_edit_mode) {
|
2025-02-16 20:31:09 -05:00
|
|
|
auto xod = std::make_unique<XFormObjectData_Armature>();
|
|
|
|
|
xod->id = id;
|
|
|
|
|
xod->is_edit_mode = is_edit_mode;
|
|
|
|
|
xod->elems.reinitialize(BLI_listbase_count(arm->edbo));
|
|
|
|
|
edit_armature_coords_and_quats_get(arm, xod->elems);
|
|
|
|
|
return xod;
|
|
|
|
|
}
|
|
|
|
|
auto xod = std::make_unique<XFormObjectData_Armature>();
|
|
|
|
|
xod->id = id;
|
|
|
|
|
xod->is_edit_mode = is_edit_mode;
|
|
|
|
|
xod->elems.reinitialize(BKE_armature_bonelist_count(&arm->bonebase));
|
|
|
|
|
armature_coords_and_quats_get(arm, xod->elems);
|
|
|
|
|
return xod;
|
2019-08-22 13:45:31 +10:00
|
|
|
}
|
|
|
|
|
case ID_MB: {
|
2019-11-21 21:03:03 +11:00
|
|
|
/* Edit mode and object mode are shared. */
|
2019-08-22 13:45:31 +10:00
|
|
|
MetaBall *mb = (MetaBall *)id;
|
2025-02-16 20:31:09 -05:00
|
|
|
auto xod = std::make_unique<XFormObjectData_MetaBall>();
|
|
|
|
|
xod->id = id;
|
|
|
|
|
xod->is_edit_mode = is_edit_mode;
|
|
|
|
|
xod->elems.reinitialize(BLI_listbase_count(&mb->elems));
|
|
|
|
|
metaball_coords_and_quats_get(mb, xod->elems);
|
|
|
|
|
return xod;
|
2019-08-22 13:45:31 +10:00
|
|
|
}
|
2024-09-13 17:06:43 +02:00
|
|
|
case ID_GP: {
|
|
|
|
|
GreasePencil *grease_pencil = (GreasePencil *)id;
|
|
|
|
|
const int elem_array_len = BKE_grease_pencil_stroke_point_count(*grease_pencil);
|
2025-02-16 20:31:09 -05:00
|
|
|
auto xod = std::make_unique<XFormObjectData_GreasePencil>();
|
|
|
|
|
xod->id = id;
|
2025-05-17 10:38:01 +02:00
|
|
|
if (!BKE_grease_pencil_has_curve_with_type(*grease_pencil, CURVE_TYPE_BEZIER)) {
|
|
|
|
|
xod->positions.reinitialize(elem_array_len);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
xod->positions.reinitialize(elem_array_len * 3);
|
|
|
|
|
}
|
2025-02-16 20:31:09 -05:00
|
|
|
xod->radii.reinitialize(elem_array_len);
|
|
|
|
|
BKE_grease_pencil_point_coords_get(*grease_pencil, xod->positions, xod->radii);
|
|
|
|
|
return xod;
|
2024-09-13 17:06:43 +02:00
|
|
|
}
|
2025-01-29 09:57:36 +01:00
|
|
|
case ID_CV: {
|
|
|
|
|
Curves *curves_id = reinterpret_cast<Curves *>(id);
|
|
|
|
|
const bke::CurvesGeometry &curves = curves_id->geometry.wrap();
|
2025-05-17 10:38:01 +02:00
|
|
|
auto xod = std::make_unique<XFormObjectData_Curves>();
|
2025-02-16 20:31:09 -05:00
|
|
|
xod->id = id;
|
2025-05-17 10:38:01 +02:00
|
|
|
|
|
|
|
|
if (!curves.has_curve_with_type(CURVE_TYPE_BEZIER)) {
|
|
|
|
|
xod->positions = curves.positions();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
xod->positions = bke::curves::bezier::retrieve_all_positions(curves,
|
|
|
|
|
curves.curves_range());
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
xod->radii.reinitialize(curves.points_num());
|
|
|
|
|
curves.radius().materialize(xod->radii);
|
|
|
|
|
return xod;
|
2025-01-29 09:57:36 +01:00
|
|
|
}
|
2025-02-16 20:48:46 -05:00
|
|
|
case ID_PT: {
|
|
|
|
|
PointCloud *pointcloud = reinterpret_cast<PointCloud *>(id);
|
|
|
|
|
auto xod = std::make_unique<XFormObjectData_PointCloud>();
|
|
|
|
|
xod->id = id;
|
|
|
|
|
xod->positions = pointcloud->positions();
|
|
|
|
|
xod->radii.reinitialize(pointcloud->totpoint);
|
|
|
|
|
pointcloud->radius().materialize(xod->radii);
|
|
|
|
|
return xod;
|
|
|
|
|
}
|
2019-08-22 13:45:31 +10:00
|
|
|
default: {
|
2025-02-16 20:31:09 -05:00
|
|
|
return {};
|
2019-08-22 13:45:31 +10:00
|
|
|
}
|
|
|
|
|
}
|
2025-02-16 20:31:09 -05:00
|
|
|
return {};
|
2019-08-22 13:45:31 +10:00
|
|
|
}
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
std::unique_ptr<XFormObjectData> data_xform_create(ID *id)
|
2019-11-21 21:03:03 +11:00
|
|
|
{
|
2024-03-28 01:30:38 +01:00
|
|
|
return data_xform_create_ex(id, false);
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
std::unique_ptr<XFormObjectData> data_xform_create_from_edit_mode(ID *id)
|
2019-11-21 21:03:03 +11:00
|
|
|
{
|
2024-03-28 01:30:38 +01:00
|
|
|
return data_xform_create_ex(id, true);
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
static void copy_transformed_positions(const Span<float3> src,
|
|
|
|
|
const float4x4 &transform,
|
|
|
|
|
MutableSpan<float3> dst)
|
2019-08-22 13:45:31 +10:00
|
|
|
{
|
2025-02-16 20:31:09 -05:00
|
|
|
threading::parallel_for(src.index_range(), 1024, [&](const IndexRange range) {
|
|
|
|
|
for (const int i : range) {
|
|
|
|
|
dst[i] = math::transform_point(transform, src[i]);
|
2020-07-25 16:35:52 +10:00
|
|
|
}
|
2025-02-16 20:31:09 -05:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void copy_transformed_radii(const Span<float> src,
|
|
|
|
|
const float4x4 &transform,
|
|
|
|
|
MutableSpan<float> dst)
|
|
|
|
|
{
|
|
|
|
|
const float scale = mat4_to_scale(transform.ptr());
|
|
|
|
|
threading::parallel_for(src.index_range(), 1024, [&](const IndexRange range) {
|
|
|
|
|
for (const int i : range) {
|
|
|
|
|
dst[i] = src[i] * scale;
|
2020-07-25 16:35:52 +10:00
|
|
|
}
|
2025-02-16 20:31:09 -05:00
|
|
|
});
|
2019-08-22 13:45:31 +10:00
|
|
|
}
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
void data_xform_by_mat4(XFormObjectData &xod_base, const float4x4 &transform)
|
2019-08-22 13:45:31 +10:00
|
|
|
{
|
2025-02-16 20:31:09 -05:00
|
|
|
switch (GS(xod_base.id->name)) {
|
2019-08-22 13:45:31 +10:00
|
|
|
case ID_ME: {
|
2025-02-16 20:31:09 -05:00
|
|
|
Mesh *mesh = (Mesh *)xod_base.id;
|
2020-07-25 16:35:52 +10:00
|
|
|
|
2023-12-08 16:40:06 -05:00
|
|
|
Key *key = mesh->key;
|
2020-07-25 16:35:52 +10:00
|
|
|
const int key_index = -1;
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
const auto &xod = reinterpret_cast<XFormObjectData_Mesh &>(xod_base);
|
|
|
|
|
if (xod.is_edit_mode) {
|
2024-03-21 23:18:49 +01:00
|
|
|
BMesh *bm = mesh->runtime->edit_mesh->bm;
|
2025-02-16 20:31:09 -05:00
|
|
|
BM_mesh_vert_coords_apply_with_mat4(bm, xod.positions, transform);
|
2020-07-25 16:35:52 +10:00
|
|
|
/* Always operate on all keys for the moment. */
|
|
|
|
|
// key_index = bm->shapenr - 1;
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
|
|
|
|
else {
|
2025-02-16 20:31:09 -05:00
|
|
|
copy_transformed_positions(xod.positions, transform, mesh->vert_positions_for_write());
|
2023-12-12 15:38:42 -05:00
|
|
|
mesh->tag_positions_changed();
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
2020-07-25 16:35:52 +10:00
|
|
|
|
2023-03-02 23:14:33 +01:00
|
|
|
if (key != nullptr) {
|
2025-02-16 20:31:09 -05:00
|
|
|
BKE_keyblock_data_set_with_mat4(key, key_index, xod.key_data, transform);
|
2020-07-25 16:35:52 +10:00
|
|
|
}
|
|
|
|
|
|
2019-08-22 13:45:31 +10:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ID_LT: {
|
2025-02-16 20:31:09 -05:00
|
|
|
const auto &xod = reinterpret_cast<XFormObjectData_Lattice &>(xod_base);
|
|
|
|
|
Lattice *lt_orig = (Lattice *)xod_base.id;
|
|
|
|
|
Lattice *lt = xod.is_edit_mode ? lt_orig->editlatt->latt : lt_orig;
|
2020-07-25 16:35:52 +10:00
|
|
|
|
2023-03-02 23:14:33 +01:00
|
|
|
Key *key = lt->key;
|
2020-07-25 16:35:52 +10:00
|
|
|
const int key_index = -1;
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
BKE_lattice_vert_coords_apply_with_mat4(lt, xod.positions, transform);
|
|
|
|
|
if (xod.is_edit_mode) {
|
2020-07-25 16:35:52 +10:00
|
|
|
/* Always operate on all keys for the moment. */
|
|
|
|
|
// key_index = lt_orig->editlatt->shapenr - 1;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
if ((key != nullptr) && !xod.key_data.is_empty()) {
|
|
|
|
|
BKE_keyblock_data_set_with_mat4(key, key_index, xod.key_data, transform);
|
2020-07-25 16:35:52 +10:00
|
|
|
}
|
|
|
|
|
|
2019-08-22 13:45:31 +10:00
|
|
|
break;
|
|
|
|
|
}
|
2022-02-18 09:50:29 -06:00
|
|
|
case ID_CU_LEGACY: {
|
2025-02-16 20:31:09 -05:00
|
|
|
const auto &xod = reinterpret_cast<XFormObjectData_Curve &>(xod_base);
|
|
|
|
|
BLI_assert(xod.is_edit_mode == false); /* Not used currently. */
|
|
|
|
|
Curve *cu = (Curve *)xod_base.id;
|
2020-07-25 16:35:52 +10:00
|
|
|
|
2023-03-02 23:14:33 +01:00
|
|
|
Key *key = cu->key;
|
2020-07-25 16:35:52 +10:00
|
|
|
const int key_index = -1;
|
2023-03-02 23:14:33 +01:00
|
|
|
ListBase *nurb = nullptr;
|
2020-07-25 16:35:52 +10:00
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
if (xod.is_edit_mode) {
|
2019-11-21 21:03:03 +11:00
|
|
|
EditNurb *editnurb = cu->editnurb;
|
2020-07-25 16:35:52 +10:00
|
|
|
nurb = &editnurb->nurbs;
|
2021-04-01 10:41:12 -03:00
|
|
|
BKE_curve_nurbs_vert_coords_apply_with_mat4(
|
2025-02-16 20:31:09 -05:00
|
|
|
&editnurb->nurbs, xod.positions, transform, CU_IS_2D(cu));
|
2020-07-25 16:35:52 +10:00
|
|
|
/* Always operate on all keys for the moment. */
|
|
|
|
|
// key_index = editnurb->shapenr - 1;
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
|
|
|
|
else {
|
2020-07-25 16:35:52 +10:00
|
|
|
nurb = &cu->nurb;
|
2025-02-16 20:31:09 -05:00
|
|
|
BKE_curve_nurbs_vert_coords_apply_with_mat4(
|
|
|
|
|
&cu->nurb, xod.positions, transform, CU_IS_2D(cu));
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
2020-07-25 16:35:52 +10:00
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
if ((key != nullptr) && !xod.key_data.is_empty()) {
|
|
|
|
|
BKE_keyblock_curve_data_set_with_mat4(
|
|
|
|
|
key, nurb, key_index, xod.key_data.data(), transform);
|
2020-07-25 16:35:52 +10:00
|
|
|
}
|
|
|
|
|
|
2019-08-22 13:45:31 +10:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ID_AR: {
|
2025-02-16 20:31:09 -05:00
|
|
|
const auto &xod = reinterpret_cast<XFormObjectData_Armature &>(xod_base);
|
|
|
|
|
BLI_assert(xod.is_edit_mode == false); /* Not used currently. */
|
|
|
|
|
bArmature *arm = (bArmature *)xod_base.id;
|
|
|
|
|
if (xod.is_edit_mode) {
|
|
|
|
|
edit_armature_coords_and_quats_apply_with_mat4(arm, xod.elems, transform);
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
|
|
|
|
else {
|
2025-02-16 20:31:09 -05:00
|
|
|
armature_coords_and_quats_apply_with_mat4(arm, xod.elems, transform);
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
2019-08-22 13:45:31 +10:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ID_MB: {
|
2025-01-04 16:26:39 +11:00
|
|
|
/* Meta-balls are a special case, edit-mode and object mode data is shared. */
|
2025-02-16 20:31:09 -05:00
|
|
|
MetaBall *mb = (MetaBall *)xod_base.id;
|
|
|
|
|
const auto &xod = reinterpret_cast<XFormObjectData_MetaBall &>(xod_base);
|
|
|
|
|
metaball_coords_and_quats_apply_with_mat4(mb, xod.elems, transform);
|
2019-08-22 13:45:31 +10:00
|
|
|
break;
|
|
|
|
|
}
|
2024-09-13 17:06:43 +02:00
|
|
|
case ID_GP: {
|
2025-02-16 20:31:09 -05:00
|
|
|
GreasePencil *grease_pencil = (GreasePencil *)xod_base.id;
|
|
|
|
|
const auto &xod = reinterpret_cast<XFormObjectData_GreasePencil &>(xod_base);
|
2024-09-13 17:06:43 +02:00
|
|
|
BKE_grease_pencil_point_coords_apply_with_mat4(
|
2025-02-16 20:31:09 -05:00
|
|
|
*grease_pencil, xod.positions, xod.radii, transform);
|
2024-09-13 17:06:43 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2025-01-29 09:57:36 +01:00
|
|
|
case ID_CV: {
|
2025-02-16 20:31:09 -05:00
|
|
|
Curves *curves_id = reinterpret_cast<Curves *>(xod_base.id);
|
2025-01-29 09:57:36 +01:00
|
|
|
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
|
2025-02-16 20:31:09 -05:00
|
|
|
const auto &xod = reinterpret_cast<const XFormObjectData_Curves &>(xod_base);
|
2025-05-17 10:38:01 +02:00
|
|
|
if (!curves.has_curve_with_type(CURVE_TYPE_BEZIER)) {
|
|
|
|
|
copy_transformed_positions(xod.positions, transform, curves.positions_for_write());
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
Array<float3> transformed_positions(xod.positions.size());
|
|
|
|
|
copy_transformed_positions(xod.positions, transform, transformed_positions);
|
|
|
|
|
bke::curves::bezier::write_all_positions(
|
|
|
|
|
curves, curves.curves_range(), transformed_positions);
|
|
|
|
|
}
|
2025-02-16 20:31:09 -05:00
|
|
|
copy_transformed_radii(xod.radii, transform, curves.radius_for_write());
|
2025-01-29 09:57:36 +01:00
|
|
|
break;
|
|
|
|
|
}
|
2025-02-16 20:48:46 -05:00
|
|
|
case ID_PT: {
|
|
|
|
|
PointCloud *pointcloud = reinterpret_cast<PointCloud *>(xod_base.id);
|
|
|
|
|
const auto &xod = reinterpret_cast<const XFormObjectData_PointCloud &>(xod_base);
|
|
|
|
|
copy_transformed_positions(xod.positions, transform, pointcloud->positions_for_write());
|
|
|
|
|
copy_transformed_radii(xod.radii, transform, pointcloud->radius_for_write());
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-08-22 13:45:31 +10:00
|
|
|
default: {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
void data_xform_restore(XFormObjectData &xod_base)
|
2019-11-21 21:03:03 +11:00
|
|
|
{
|
2025-02-16 20:31:09 -05:00
|
|
|
switch (GS(xod_base.id->name)) {
|
2019-11-21 21:03:03 +11:00
|
|
|
case ID_ME: {
|
2025-02-16 20:31:09 -05:00
|
|
|
Mesh *mesh = (Mesh *)xod_base.id;
|
2020-07-25 16:35:52 +10:00
|
|
|
|
2023-12-08 16:40:06 -05:00
|
|
|
Key *key = mesh->key;
|
2020-07-25 16:35:52 +10:00
|
|
|
const int key_index = -1;
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
const auto &xod = reinterpret_cast<XFormObjectData_Mesh &>(xod_base);
|
|
|
|
|
if (xod.is_edit_mode) {
|
2024-03-21 23:18:49 +01:00
|
|
|
BMesh *bm = mesh->runtime->edit_mesh->bm;
|
2025-02-16 20:31:09 -05:00
|
|
|
BM_mesh_vert_coords_apply(bm, xod.positions);
|
2020-07-25 16:35:52 +10:00
|
|
|
/* Always operate on all keys for the moment. */
|
|
|
|
|
// key_index = bm->shapenr - 1;
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
|
|
|
|
else {
|
2025-02-16 20:31:09 -05:00
|
|
|
mesh->vert_positions_for_write().copy_from(xod.positions);
|
2023-12-12 15:38:42 -05:00
|
|
|
mesh->tag_positions_changed();
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
2020-07-25 16:35:52 +10:00
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
if ((key != nullptr) && !xod.key_data.is_empty()) {
|
|
|
|
|
BKE_keyblock_data_set(key, key_index, xod.key_data.data());
|
2020-07-25 16:35:52 +10:00
|
|
|
}
|
|
|
|
|
|
2019-11-21 21:03:03 +11:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ID_LT: {
|
2025-02-16 20:31:09 -05:00
|
|
|
const auto &xod = reinterpret_cast<XFormObjectData_Lattice &>(xod_base);
|
|
|
|
|
Lattice *lt_orig = (Lattice *)xod_base.id;
|
|
|
|
|
Lattice *lt = xod.is_edit_mode ? lt_orig->editlatt->latt : lt_orig;
|
2020-07-25 16:35:52 +10:00
|
|
|
|
2023-03-02 23:14:33 +01:00
|
|
|
Key *key = lt->key;
|
2020-07-25 16:35:52 +10:00
|
|
|
const int key_index = -1;
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
BKE_lattice_vert_coords_apply(lt, xod.positions);
|
|
|
|
|
if (xod.is_edit_mode) {
|
2020-07-25 16:35:52 +10:00
|
|
|
/* Always operate on all keys for the moment. */
|
|
|
|
|
// key_index = lt_orig->editlatt->shapenr - 1;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
if ((key != nullptr) && !xod.key_data.is_empty()) {
|
|
|
|
|
BKE_keyblock_data_set(key, key_index, xod.key_data.data());
|
2020-07-25 16:35:52 +10:00
|
|
|
}
|
|
|
|
|
|
2019-11-21 21:03:03 +11:00
|
|
|
break;
|
|
|
|
|
}
|
2022-02-18 09:50:29 -06:00
|
|
|
case ID_CU_LEGACY: {
|
2025-02-16 20:31:09 -05:00
|
|
|
Curve *cu = (Curve *)xod_base.id;
|
2020-07-25 16:35:52 +10:00
|
|
|
|
2023-03-02 23:14:33 +01:00
|
|
|
Key *key = cu->key;
|
2020-07-25 16:35:52 +10:00
|
|
|
const int key_index = -1;
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
const auto &xod = reinterpret_cast<XFormObjectData_Curve &>(xod_base);
|
|
|
|
|
if (xod.is_edit_mode) {
|
2019-11-21 21:03:03 +11:00
|
|
|
EditNurb *editnurb = cu->editnurb;
|
2025-02-16 20:31:09 -05:00
|
|
|
BKE_curve_nurbs_vert_coords_apply(&editnurb->nurbs, xod.positions, CU_IS_2D(cu));
|
2020-07-25 16:35:52 +10:00
|
|
|
/* Always operate on all keys for the moment. */
|
|
|
|
|
// key_index = editnurb->shapenr - 1;
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
|
|
|
|
else {
|
2025-02-16 20:31:09 -05:00
|
|
|
BKE_curve_nurbs_vert_coords_apply(&cu->nurb, xod.positions, CU_IS_2D(cu));
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
2020-07-25 16:35:52 +10:00
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
if ((key != nullptr) && !xod.key_data.is_empty()) {
|
|
|
|
|
BKE_keyblock_data_set(key, key_index, xod.key_data.data());
|
2020-07-25 16:35:52 +10:00
|
|
|
}
|
|
|
|
|
|
2019-11-21 21:03:03 +11:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ID_AR: {
|
2025-02-16 20:31:09 -05:00
|
|
|
bArmature *arm = (bArmature *)xod_base.id;
|
|
|
|
|
const auto &xod = reinterpret_cast<XFormObjectData_Armature &>(xod_base);
|
|
|
|
|
if (xod.is_edit_mode) {
|
|
|
|
|
edit_armature_coords_and_quats_apply(arm, xod.elems);
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
|
|
|
|
else {
|
2025-02-16 20:31:09 -05:00
|
|
|
armature_coords_and_quats_apply(arm, xod.elems);
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ID_MB: {
|
2025-01-04 16:26:39 +11:00
|
|
|
/* Meta-balls are a special case, edit-mode and object mode data is shared. */
|
2025-02-16 20:31:09 -05:00
|
|
|
MetaBall *mb = (MetaBall *)xod_base.id;
|
|
|
|
|
const auto &xod = reinterpret_cast<XFormObjectData_MetaBall &>(xod_base);
|
|
|
|
|
metaball_coords_and_quats_apply(mb, xod.elems);
|
2020-07-21 12:11:56 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2024-09-13 17:06:43 +02:00
|
|
|
case ID_GP: {
|
2025-02-16 20:31:09 -05:00
|
|
|
GreasePencil *grease_pencil = (GreasePencil *)xod_base.id;
|
|
|
|
|
const auto &xod = reinterpret_cast<XFormObjectData_GreasePencil &>(xod_base);
|
|
|
|
|
BKE_grease_pencil_point_coords_apply(*grease_pencil, xod.positions, xod.radii);
|
2024-09-13 17:06:43 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2025-01-29 09:57:36 +01:00
|
|
|
case ID_CV: {
|
2025-02-16 20:31:09 -05:00
|
|
|
Curves *curves_id = reinterpret_cast<Curves *>(xod_base.id);
|
2025-01-29 09:57:36 +01:00
|
|
|
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
|
2025-02-16 20:31:09 -05:00
|
|
|
const auto &xod = reinterpret_cast<const XFormObjectData_Curves &>(xod_base);
|
2025-05-17 10:38:01 +02:00
|
|
|
if (!curves.has_curve_with_type(CURVE_TYPE_BEZIER)) {
|
|
|
|
|
curves.positions_for_write().copy_from(xod.positions);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
bke::curves::bezier::write_all_positions(curves, curves.curves_range(), xod.positions);
|
|
|
|
|
}
|
2025-02-16 20:31:09 -05:00
|
|
|
curves.radius_for_write().copy_from(xod.radii);
|
2025-01-29 09:57:36 +01:00
|
|
|
break;
|
|
|
|
|
}
|
2025-02-16 20:48:46 -05:00
|
|
|
case ID_PT: {
|
|
|
|
|
PointCloud *pointcloud = reinterpret_cast<PointCloud *>(xod_base.id);
|
|
|
|
|
const auto &xod = reinterpret_cast<const XFormObjectData_PointCloud &>(xod_base);
|
|
|
|
|
pointcloud->positions_for_write().copy_from(xod.positions);
|
|
|
|
|
pointcloud->radius_for_write().copy_from(xod.radii);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-11-21 21:03:03 +11:00
|
|
|
default: {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-16 20:31:09 -05:00
|
|
|
void data_xform_tag_update(XFormObjectData &xod_base)
|
2019-11-21 21:03:03 +11:00
|
|
|
{
|
2025-02-16 20:31:09 -05:00
|
|
|
switch (GS(xod_base.id->name)) {
|
2019-11-21 21:03:03 +11:00
|
|
|
case ID_ME: {
|
2025-02-16 20:31:09 -05:00
|
|
|
Mesh *mesh = (Mesh *)xod_base.id;
|
|
|
|
|
const auto &xod = reinterpret_cast<XFormObjectData_Mesh &>(xod_base);
|
|
|
|
|
if (xod.is_edit_mode) {
|
2023-03-02 23:14:33 +01:00
|
|
|
EDBMUpdate_Params params{};
|
2023-12-14 12:08:21 +11:00
|
|
|
params.calc_looptris = true;
|
2023-03-02 23:14:33 +01:00
|
|
|
params.calc_normals = true;
|
|
|
|
|
params.is_destructive = false;
|
2023-12-08 16:40:06 -05:00
|
|
|
EDBM_update(mesh, ¶ms);
|
2019-11-21 21:03:03 +11:00
|
|
|
}
|
2023-12-08 16:40:06 -05:00
|
|
|
DEG_id_tag_update(&mesh->id, ID_RECALC_GEOMETRY);
|
2019-11-21 21:03:03 +11:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ID_LT: {
|
|
|
|
|
/* Generic update. */
|
2025-02-16 20:31:09 -05:00
|
|
|
Lattice *lt = (Lattice *)xod_base.id;
|
2019-11-21 21:03:03 +11:00
|
|
|
DEG_id_tag_update(<->id, ID_RECALC_GEOMETRY);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-02-18 09:50:29 -06:00
|
|
|
case ID_CU_LEGACY: {
|
2019-11-21 21:03:03 +11:00
|
|
|
/* Generic update. */
|
2025-02-16 20:31:09 -05:00
|
|
|
Curve *cu = (Curve *)xod_base.id;
|
2019-11-21 21:03:03 +11:00
|
|
|
DEG_id_tag_update(&cu->id, ID_RECALC_GEOMETRY);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ID_AR: {
|
|
|
|
|
/* Generic update. */
|
2025-02-16 20:31:09 -05:00
|
|
|
bArmature *arm = (bArmature *)xod_base.id;
|
2019-11-21 21:03:03 +11:00
|
|
|
/* XXX, zero is needed, no other flags properly update this. */
|
|
|
|
|
DEG_id_tag_update(&arm->id, 0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ID_MB: {
|
|
|
|
|
/* Generic update. */
|
2025-02-16 20:31:09 -05:00
|
|
|
MetaBall *mb = (MetaBall *)xod_base.id;
|
2024-02-19 15:54:08 +01:00
|
|
|
DEG_id_tag_update(&mb->id, ID_RECALC_GEOMETRY | ID_RECALC_SYNC_TO_EVAL);
|
2019-11-21 21:03:03 +11:00
|
|
|
break;
|
|
|
|
|
}
|
2023-03-08 12:35:58 +01:00
|
|
|
case ID_GD_LEGACY: {
|
2020-07-21 12:11:56 +02:00
|
|
|
/* Generic update. */
|
2025-02-16 20:31:09 -05:00
|
|
|
bGPdata *gpd = (bGPdata *)xod_base.id;
|
2024-02-19 15:54:08 +01:00
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_SYNC_TO_EVAL);
|
2020-07-21 12:11:56 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2024-09-13 17:06:43 +02:00
|
|
|
case ID_GP: {
|
|
|
|
|
/* Generic update. */
|
2025-02-16 20:31:09 -05:00
|
|
|
GreasePencil *grease_pencil = (GreasePencil *)xod_base.id;
|
2024-09-13 17:06:43 +02:00
|
|
|
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY | ID_RECALC_SYNC_TO_EVAL);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2025-01-29 09:57:36 +01:00
|
|
|
case ID_CV: {
|
2025-02-16 20:31:09 -05:00
|
|
|
Curves *curves_id = reinterpret_cast<Curves *>(xod_base.id);
|
2025-01-29 09:57:36 +01:00
|
|
|
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
|
|
|
|
|
curves.tag_positions_changed();
|
2025-02-16 20:48:46 -05:00
|
|
|
curves.tag_radii_changed();
|
2025-01-29 09:57:36 +01:00
|
|
|
DEG_id_tag_update(&curves_id->id, ID_RECALC_GEOMETRY | ID_RECALC_SYNC_TO_EVAL);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2025-02-16 20:48:46 -05:00
|
|
|
case ID_PT: {
|
|
|
|
|
PointCloud *pointcloud = reinterpret_cast<PointCloud *>(xod_base.id);
|
|
|
|
|
pointcloud->tag_positions_changed();
|
|
|
|
|
pointcloud->tag_radii_changed();
|
|
|
|
|
DEG_id_tag_update(&pointcloud->id, ID_RECALC_GEOMETRY | ID_RECALC_SYNC_TO_EVAL);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-11-21 21:03:03 +11:00
|
|
|
default: {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-22 13:45:31 +10:00
|
|
|
/** \} */
|
2024-03-28 01:30:38 +01:00
|
|
|
|
|
|
|
|
} // namespace blender::ed::object
|