GPv3: Initial sculpt mode #119338
|
@ -1894,7 +1894,12 @@ bool BKE_object_has_mode_data(const Object *ob, eObjectMode object_mode)
|
|||
}
|
||||
}
|
||||
else if (object_mode & OB_MODE_SCULPT) {
|
||||
if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_SCULPT)) {
|
||||
if (ob->type == OB_MESH) {
|
||||
if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_SCULPT)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (ob->type == OB_GREASE_PENCIL) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -2373,7 +2378,8 @@ static void copy_object_pose(Object *obn, const Object *ob, const int flag)
|
|||
|
||||
/* XXX Remapping object pointing onto itself should be handled by generic
|
||||
* BKE_library_remap stuff, but...
|
||||
* the flush_constraint_targets callback am not sure about, so will delay that for now. */
|
||||
* the flush_constraint_targets callback am not sure about, so will delay that for now.
|
||||
*/
|
||||
LISTBASE_FOREACH (bConstraint *, con, &chan->constraints) {
|
||||
ListBase targets = {nullptr, nullptr};
|
||||
|
||||
|
@ -2565,8 +2571,8 @@ Object *BKE_object_duplicate(Main *bmain,
|
|||
copy_flags |= LIB_ID_COPY_RIGID_BODY_NO_COLLECTION_HANDLING;
|
||||
}
|
||||
if (is_root_id) {
|
||||
/* In case root duplicated ID is linked, assume we want to get a local copy of it and duplicate
|
||||
* all expected linked data. */
|
||||
/* In case root duplicated ID is linked, assume we want to get a local copy of it and
|
||||
* duplicate all expected linked data. */
|
||||
if (ID_IS_LINKED(ob)) {
|
||||
dupflag |= USER_DUP_LINKED_ID;
|
||||
}
|
||||
|
@ -2693,7 +2699,8 @@ Object *BKE_object_duplicate(Main *bmain,
|
|||
BKE_libblock_relink_to_newid(bmain, &obn->id, 0);
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* Call to `BKE_libblock_relink_to_newid` above is supposed to have cleared all those flags. */
|
||||
/* Call to `BKE_libblock_relink_to_newid` above is supposed to have cleared all those flags.
|
||||
*/
|
||||
ID *id_iter;
|
||||
FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
|
||||
BLI_assert((id_iter->tag & LIB_TAG_NEW) == 0);
|
||||
|
@ -2792,7 +2799,8 @@ void BKE_object_rot_to_mat3(const Object *ob, float mat[3][3], bool use_drot)
|
|||
* with the rotation matrix to yield the appropriate rotation
|
||||
*/
|
||||
|
||||
/* Rotations may either be quaternions, eulers (with various rotation orders), or axis-angle. */
|
||||
/* Rotations may either be quaternions, eulers (with various rotation orders), or axis-angle.
|
||||
*/
|
||||
if (ob->rotmode > 0) {
|
||||
/* Euler rotations
|
||||
* (will cause gimbal lock, but this can be alleviated a bit with rotation orders). */
|
||||
|
@ -3175,7 +3183,8 @@ static void give_parvert(Object *par, int nr, float vec[3])
|
|||
ListBase *nurb;
|
||||
|
||||
/* It is possible that a cycle in the dependency graph was resolved in a way that caused this
|
||||
* object to be evaluated before its dependencies. In this case the curve cache may be null. */
|
||||
* object to be evaluated before its dependencies. In this case the curve cache may be null.
|
||||
*/
|
||||
if (par->runtime->curve_cache && par->runtime->curve_cache->deformed_nurbs.first != nullptr) {
|
||||
nurb = &par->runtime->curve_cache->deformed_nurbs;
|
||||
}
|
||||
|
@ -3418,10 +3427,10 @@ blender::float4x4 BKE_object_calc_parent(Depsgraph *depsgraph, Scene *scene, Obj
|
|||
workob.par3 = ob->par3;
|
||||
|
||||
/* The effects of constraints should NOT be included in the parent-inverse matrix. Constraints
|
||||
* are supposed to be applied after the object's local loc/rot/scale. If the (inverted) effect of
|
||||
* constraints would be included in the parent inverse matrix, these would be applied before the
|
||||
* object's local loc/rot/scale instead of after. For example, a "Copy Rotation" constraint would
|
||||
* rotate the object's local translation as well. See #82156. */
|
||||
* are supposed to be applied after the object's local loc/rot/scale. If the (inverted) effect
|
||||
* of constraints would be included in the parent inverse matrix, these would be applied before
|
||||
* the object's local loc/rot/scale instead of after. For example, a "Copy Rotation" constraint
|
||||
* would rotate the object's local translation as well. See #82156. */
|
||||
|
||||
STRNCPY(workob.parsubstr, ob->parsubstr);
|
||||
|
||||
|
@ -4289,10 +4298,10 @@ static int pc_cmp(const void *a, const void *b)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: Review the usages of this function, currently with copy-on-eval it will be called for orig
|
||||
* object and then again for evaluated copies of it, think this is bad since there is no guarantee
|
||||
* that we get the same stack index in both cases? Order is important since this index is used for
|
||||
* filenames on disk. */
|
||||
/* TODO: Review the usages of this function, currently with copy-on-eval it will be called for
|
||||
* orig object and then again for evaluated copies of it, think this is bad since there is no
|
||||
* guarantee that we get the same stack index in both cases? Order is important since this index
|
||||
* is used for filenames on disk. */
|
||||
int BKE_object_insert_ptcache(Object *ob)
|
||||
{
|
||||
LinkData *link = nullptr;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
* actual mode switching logic is per-object type.
|
||||
*/
|
||||
|
||||
#include "DNA_object_enums.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
|
@ -142,7 +143,9 @@ bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode)
|
|||
}
|
||||
break;
|
||||
case OB_GREASE_PENCIL:
|
||||
if (mode & (OB_MODE_EDIT | OB_MODE_PAINT_GREASE_PENCIL | OB_MODE_WEIGHT_PAINT)) {
|
||||
if (mode &
|
||||
(OB_MODE_EDIT | OB_MODE_PAINT_GREASE_PENCIL | OB_MODE_WEIGHT_PAINT | OB_MODE_SCULPT))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
@ -264,7 +267,13 @@ static bool ed_object_mode_generic_exit_ex(
|
|||
}
|
||||
}
|
||||
else if (ob->mode & OB_MODE_SCULPT) {
|
||||
if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_SCULPT)) {
|
||||
if (ob->type == OB_MESH && ob->sculpt && (ob->sculpt->mode_type == OB_MODE_SCULPT)) {
|
||||
if (only_test) {
|
||||
return true;
|
||||
}
|
||||
ED_object_sculptmode_exit_ex(bmain, depsgraph, scene, ob);
|
||||
}
|
||||
if (ob->type == OB_GREASE_PENCIL) {
|
||||
if (only_test) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -232,7 +232,7 @@ ModifierData *ED_object_modifier_add(
|
|||
/* set totlvl from existing MDISPS layer if object already had it */
|
||||
multiresModifier_set_levels_from_disps((MultiresModifierData *)new_md, ob);
|
||||
|
||||
if (ob->mode & OB_MODE_SCULPT) {
|
||||
if ((ob->type == OB_MESH) && (ob->mode & OB_MODE_SCULPT)) {
|
||||
/* ensure that grid paint mask layer is created */
|
||||
BKE_sculpt_mask_layers_ensure(nullptr, nullptr, ob, (MultiresModifierData *)new_md);
|
||||
}
|
||||
|
@ -1150,8 +1150,8 @@ bool ED_object_modifier_apply(Main *bmain,
|
|||
BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
|
||||
return false;
|
||||
}
|
||||
if ((ob->mode & OB_MODE_SCULPT) && find_multires_modifier_before(scene, md) &&
|
||||
(BKE_modifier_is_same_topology(md) == false))
|
||||
if ((ob->type == OB_MESH) && (ob->mode & OB_MODE_SCULPT) &&
|
||||
find_multires_modifier_before(scene, md) && (BKE_modifier_is_same_topology(md) == false))
|
||||
{
|
||||
BKE_report(reports,
|
||||
RPT_ERROR,
|
||||
|
@ -1722,8 +1722,8 @@ static bool modifier_apply_poll(bContext *C)
|
|||
return false;
|
||||
}
|
||||
if (md != nullptr) {
|
||||
if ((ob->mode & OB_MODE_SCULPT) && find_multires_modifier_before(scene, md) &&
|
||||
(BKE_modifier_is_same_topology(md) == false))
|
||||
if ((ob->type == OB_MESH) && (ob->mode & OB_MODE_SCULPT) &&
|
||||
find_multires_modifier_before(scene, md) && (BKE_modifier_is_same_topology(md) == false))
|
||||
{
|
||||
CTX_wm_operator_poll_msg_set(
|
||||
C, "Constructive modifier cannot be applied to multi-res data in sculpt mode");
|
||||
|
@ -2306,7 +2306,7 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op)
|
|||
DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, object);
|
||||
|
||||
if (object->mode & OB_MODE_SCULPT) {
|
||||
if (object->type == OB_MESH && object->mode & OB_MODE_SCULPT) {
|
||||
/* ensure that grid paint mask layer is created */
|
||||
BKE_sculpt_mask_layers_ensure(
|
||||
CTX_data_ensure_evaluated_depsgraph(C), CTX_data_main(C), object, mmd);
|
||||
|
|
|
@ -3956,7 +3956,7 @@ static void do_symmetrical_brush_actions(Sculpt *sd,
|
|||
bool SCULPT_mode_poll(bContext *C)
|
||||
{
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
return ob && ob->mode & OB_MODE_SCULPT;
|
||||
return ob && ob->type == OB_MESH && ob->mode & OB_MODE_SCULPT;
|
||||
}
|
||||
|
||||
bool SCULPT_mode_poll_view3d(bContext *C)
|
||||
|
|
|
@ -279,6 +279,8 @@ namespace blender::ed::sculpt_paint {
|
|||
|
||||
static void sculpt_init_session(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
|
||||
{
|
||||
BLI_assert(ob->type == OB_MESH);
|
||||
|
||||
/* Create persistent sculpt mode data. */
|
||||
BKE_sculpt_toolsettings_data_ensure(scene);
|
||||
|
||||
|
@ -352,13 +354,10 @@ void ED_object_sculptmode_enter_ex(Main *bmain,
|
|||
{
|
||||
using namespace blender::ed::sculpt_paint;
|
||||
const int mode_flag = OB_MODE_SCULPT;
|
||||
Mesh *mesh = BKE_mesh_from_object(ob);
|
||||
|
||||
/* Enter sculpt mode. */
|
||||
ob->mode |= mode_flag;
|
||||
|
||||
sculpt_init_session(bmain, depsgraph, scene, ob);
|
||||
|
||||
if (!(fabsf(ob->scale[0] - ob->scale[1]) < 1e-4f && fabsf(ob->scale[1] - ob->scale[2]) < 1e-4f))
|
||||
{
|
||||
BKE_report(
|
||||
|
@ -373,62 +372,71 @@ void ED_object_sculptmode_enter_ex(Main *bmain,
|
|||
|
||||
ED_paint_cursor_start(paint, SCULPT_mode_poll_view3d);
|
||||
|
||||
/* Check dynamic-topology flag; re-enter dynamic-topology mode when changing modes,
|
||||
* As long as no data was added that is not supported. */
|
||||
if (mesh->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
|
||||
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
|
||||
if (ob->type == OB_MESH) {
|
||||
Mesh *mesh = BKE_mesh_from_object(ob);
|
||||
|
||||
const char *message_unsupported = nullptr;
|
||||
if (mesh->corners_num != mesh->faces_num * 3) {
|
||||
message_unsupported = RPT_("non-triangle face");
|
||||
}
|
||||
else if (mmd != nullptr) {
|
||||
message_unsupported = RPT_("multi-res modifier");
|
||||
}
|
||||
else {
|
||||
dyntopo::WarnFlag flag = dyntopo::check_attribute_warning(scene, ob);
|
||||
if (flag == 0) {
|
||||
/* pass */
|
||||
sculpt_init_session(bmain, depsgraph, scene, ob);
|
||||
|
||||
/* Check dynamic-topology flag; re-enter dynamic-topology mode when changing modes,
|
||||
* As long as no data was added that is not supported. */
|
||||
if (mesh->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
|
||||
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
|
||||
|
||||
const char *message_unsupported = nullptr;
|
||||
if (mesh->corners_num != mesh->faces_num * 3) {
|
||||
message_unsupported = RPT_("non-triangle face");
|
||||
}
|
||||
else if (flag & dyntopo::VDATA) {
|
||||
message_unsupported = RPT_("vertex data");
|
||||
}
|
||||
else if (flag & dyntopo::EDATA) {
|
||||
message_unsupported = RPT_("edge data");
|
||||
}
|
||||
else if (flag & dyntopo::LDATA) {
|
||||
message_unsupported = RPT_("face data");
|
||||
}
|
||||
else if (flag & dyntopo::MODIFIER) {
|
||||
message_unsupported = RPT_("constructive modifier");
|
||||
else if (mmd != nullptr) {
|
||||
message_unsupported = RPT_("multi-res modifier");
|
||||
}
|
||||
else {
|
||||
BLI_assert(0);
|
||||
dyntopo::WarnFlag flag = dyntopo::check_attribute_warning(scene, ob);
|
||||
if (flag == 0) {
|
||||
/* pass */
|
||||
}
|
||||
else if (flag & dyntopo::VDATA) {
|
||||
message_unsupported = RPT_("vertex data");
|
||||
}
|
||||
else if (flag & dyntopo::EDATA) {
|
||||
message_unsupported = RPT_("edge data");
|
||||
}
|
||||
else if (flag & dyntopo::LDATA) {
|
||||
message_unsupported = RPT_("face data");
|
||||
}
|
||||
else if (flag & dyntopo::MODIFIER) {
|
||||
message_unsupported = RPT_("constructive modifier");
|
||||
}
|
||||
else {
|
||||
BLI_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
if ((message_unsupported == nullptr) || force_dyntopo) {
|
||||
/* Needed because we may be entering this mode before the undo system loads. */
|
||||
wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
|
||||
bool has_undo = wm->undo_stack != nullptr;
|
||||
/* Undo push is needed to prevent memory leak. */
|
||||
if (has_undo) {
|
||||
undo::push_begin_ex(ob, "Dynamic topology enable");
|
||||
}
|
||||
dyntopo::enable_ex(bmain, depsgraph, ob);
|
||||
if (has_undo) {
|
||||
undo::push_node(ob, nullptr, undo::Type::DyntopoBegin);
|
||||
undo::push_end(ob);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BKE_reportf(
|
||||
reports, RPT_WARNING, "Dynamic Topology found: %s, disabled", message_unsupported);
|
||||
mesh->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY;
|
||||
}
|
||||
}
|
||||
|
||||
if ((message_unsupported == nullptr) || force_dyntopo) {
|
||||
/* Needed because we may be entering this mode before the undo system loads. */
|
||||
wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
|
||||
bool has_undo = wm->undo_stack != nullptr;
|
||||
/* Undo push is needed to prevent memory leak. */
|
||||
if (has_undo) {
|
||||
undo::push_begin_ex(ob, "Dynamic topology enable");
|
||||
}
|
||||
dyntopo::enable_ex(bmain, depsgraph, ob);
|
||||
if (has_undo) {
|
||||
undo::push_node(ob, nullptr, undo::Type::DyntopoBegin);
|
||||
undo::push_end(ob);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BKE_reportf(
|
||||
reports, RPT_WARNING, "Dynamic Topology found: %s, disabled", message_unsupported);
|
||||
mesh->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY;
|
||||
}
|
||||
ensure_valid_pivot(ob, scene);
|
||||
}
|
||||
if (ob->type == OB_GREASE_PENCIL) {
|
||||
/* TODO set up grease pencil sculpt */
|
||||
}
|
||||
|
||||
ensure_valid_pivot(ob, scene);
|
||||
|
||||
/* Flush object mode. */
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_SYNC_TO_EVAL);
|
||||
|
@ -448,37 +456,42 @@ void ED_object_sculptmode_exit_ex(Main *bmain, Depsgraph *depsgraph, Scene *scen
|
|||
{
|
||||
using namespace blender::ed::sculpt_paint;
|
||||
const int mode_flag = OB_MODE_SCULPT;
|
||||
Mesh *mesh = BKE_mesh_from_object(ob);
|
||||
|
||||
multires_flush_sculpt_updates(ob);
|
||||
if (ob->type == OB_MESH) {
|
||||
Mesh *mesh = BKE_mesh_from_object(ob);
|
||||
|
||||
/* Not needed for now. */
|
||||
multires_flush_sculpt_updates(ob);
|
||||
|
||||
/* Not needed for now. */
|
||||
#if 0
|
||||
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
|
||||
const int flush_recalc = ed_object_sculptmode_flush_recalc_flag(scene, ob, mmd);
|
||||
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
|
||||
const int flush_recalc = ed_object_sculptmode_flush_recalc_flag(scene, ob, mmd);
|
||||
#endif
|
||||
|
||||
/* Always for now, so leaving sculpt mode always ensures scene is in
|
||||
* a consistent state. */
|
||||
if (true || /* flush_recalc || */ (ob->sculpt && ob->sculpt->bm)) {
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
||||
/* Always for now, so leaving sculpt mode always ensures scene is in
|
||||
* a consistent state. */
|
||||
if (true || /* flush_recalc || */ (ob->sculpt && ob->sculpt->bm)) {
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
||||
}
|
||||
|
||||
if (mesh->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
|
||||
/* Dynamic topology must be disabled before exiting sculpt
|
||||
* mode to ensure the undo stack stays in a consistent
|
||||
* state. */
|
||||
dyntopo::disable_with_undo(bmain, depsgraph, scene, ob);
|
||||
|
||||
/* Store so we know to re-enable when entering sculpt mode. */
|
||||
mesh->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
|
||||
}
|
||||
|
||||
BKE_sculptsession_free(ob);
|
||||
}
|
||||
|
||||
if (mesh->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
|
||||
/* Dynamic topology must be disabled before exiting sculpt
|
||||
* mode to ensure the undo stack stays in a consistent
|
||||
* state. */
|
||||
dyntopo::disable_with_undo(bmain, depsgraph, scene, ob);
|
||||
|
||||
/* Store so we know to re-enable when entering sculpt mode. */
|
||||
mesh->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
|
||||
if (ob->type == OB_GREASE_PENCIL) {
|
||||
}
|
||||
|
||||
/* Leave sculpt mode. */
|
||||
ob->mode &= ~mode_flag;
|
||||
|
||||
BKE_sculptsession_free(ob);
|
||||
|
||||
paint_cursor_delete_textures();
|
||||
|
||||
/* Never leave derived meshes behind. */
|
||||
|
@ -529,7 +542,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
|
|||
ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, false, op->reports);
|
||||
BKE_paint_toolslots_brush_validate(bmain, &ts->sculpt->paint);
|
||||
|
||||
if (ob->mode & mode_flag) {
|
||||
if ((ob->type == OB_MESH) && (ob->mode & mode_flag)) {
|
||||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
/* Dyntopo adds its own undo step. */
|
||||
if ((mesh->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) == 0) {
|
||||
|
@ -944,8 +957,8 @@ static int sculpt_mask_by_color_invoke(bContext *C, wmOperator *op, const wmEven
|
|||
BKE_sculpt_update_object_for_edit(depsgraph, ob, false);
|
||||
SCULPT_vertex_random_access_ensure(ss);
|
||||
|
||||
/* Tools that are not brushes do not have the brush gizmo to update the vertex as the mouse move,
|
||||
* so it needs to be updated here. */
|
||||
/* Tools that are not brushes do not have the brush gizmo to update the vertex as the mouse
|
||||
* move, so it needs to be updated here. */
|
||||
SculptCursorGeometryInfo sgi;
|
||||
const float mval_fl[2] = {float(event->mval[0]), float(event->mval[1])};
|
||||
SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_armature_types.h"
|
||||
|
@ -357,31 +358,36 @@ static void stats_object_pose(const Object *ob, SceneStats *stats)
|
|||
static bool stats_is_object_dynamic_topology_sculpt(const Object *ob)
|
||||
{
|
||||
BLI_assert(ob->mode & OB_MODE_SCULPT);
|
||||
return (ob->sculpt && ob->sculpt->bm);
|
||||
return (ob->type == OB_MESH && ob->sculpt && ob->sculpt->bm);
|
||||
}
|
||||
|
||||
static void stats_object_sculpt(const Object *ob, SceneStats *stats)
|
||||
{
|
||||
BLI_assert(ob->mode & OB_MODE_SCULPT);
|
||||
if (ob->type == OB_MESH) {
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
SculptSession *ss = ob->sculpt;
|
||||
if (ss == nullptr || ss->pbvh == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ss == nullptr || ss->pbvh == nullptr) {
|
||||
return;
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
case PBVH_FACES:
|
||||
stats->totvertsculpt = ss->totvert;
|
||||
stats->totfacesculpt = ss->totfaces;
|
||||
break;
|
||||
case PBVH_BMESH:
|
||||
stats->totvertsculpt = ob->sculpt->bm->totvert;
|
||||
stats->tottri = ob->sculpt->bm->totface;
|
||||
break;
|
||||
case PBVH_GRIDS:
|
||||
stats->totvertsculpt = BKE_pbvh_get_grid_num_verts(ss->pbvh);
|
||||
stats->totfacesculpt = BKE_pbvh_get_grid_num_faces(ss->pbvh);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
case PBVH_FACES:
|
||||
stats->totvertsculpt = ss->totvert;
|
||||
stats->totfacesculpt = ss->totfaces;
|
||||
break;
|
||||
case PBVH_BMESH:
|
||||
stats->totvertsculpt = ob->sculpt->bm->totvert;
|
||||
stats->tottri = ob->sculpt->bm->totface;
|
||||
break;
|
||||
case PBVH_GRIDS:
|
||||
stats->totvertsculpt = BKE_pbvh_get_grid_num_verts(ss->pbvh);
|
||||
stats->totfacesculpt = BKE_pbvh_get_grid_num_faces(ss->pbvh);
|
||||
break;
|
||||
if (ob->type == OB_GREASE_PENCIL) {
|
||||
/* TODO. */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -891,7 +891,7 @@ static TransConvertTypeInfo *convert_type_get(const TransInfo *t, Object **r_obj
|
|||
return &TransConvertType_Cursor3D;
|
||||
}
|
||||
if (!(t->options & CTX_PAINT_CURVE) && (t->spacetype == SPACE_VIEW3D) && ob &&
|
||||
(ob->mode == OB_MODE_SCULPT) && ob->sculpt)
|
||||
(ob->type == OB_MESH) && (ob->mode == OB_MODE_SCULPT) && ob->sculpt)
|
||||
{
|
||||
return &TransConvertType_Sculpt;
|
||||
}
|
||||
|
|
|
@ -886,8 +886,10 @@ static int gizmo_3d_foreach_selected(const bContext *C,
|
|||
}
|
||||
else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
|
||||
if (ob->mode & OB_MODE_SCULPT) {
|
||||
totsel = 1;
|
||||
run_coord_with_matrix(ob->sculpt->pivot_pos, false, ob->object_to_world().ptr());
|
||||
if (ob->sculpt) {
|
||||
totsel = 1;
|
||||
run_coord_with_matrix(ob->sculpt->pivot_pos, false, ob->object_to_world().ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) {
|
||||
|
|
Loading…
Reference in New Issue