WIP: Snapping Redesign: Defaults | Navigation | Drawing | Removals #109062
|
@ -748,6 +748,14 @@ class VIEW3D_HT_header(Header):
|
|||
).domain = 'CURVE'
|
||||
|
||||
# Grease Pencil
|
||||
if obj and obj.type == 'GREASEPENCIL':
|
||||
# Select mode for Editing
|
||||
if object_mode == 'EDIT':
|
||||
row = layout.row(align=True)
|
||||
row.prop_enum(tool_settings, "gpencil_selectmode_edit", text="", value='POINT')
|
||||
row.prop_enum(tool_settings, "gpencil_selectmode_edit", text="", value='STROKE')
|
||||
|
||||
# Grease Pencil (legacy)
|
||||
if obj and obj.type == 'GPENCIL' and context.gpencil_data:
|
||||
gpd = context.gpencil_data
|
||||
|
||||
|
@ -2016,6 +2024,7 @@ class VIEW3D_MT_select_edit_gpencil(Menu):
|
|||
def draw(self, context):
|
||||
if not context.preferences.experimental.use_grease_pencil_version3:
|
||||
self.draw_legacy(context)
|
||||
return
|
||||
|
||||
layout = self.layout
|
||||
|
||||
|
|
|
@ -3653,9 +3653,6 @@ void ntreeLocalMerge(Main *bmain, bNodeTree *localtree, bNodeTree *ntree)
|
|||
if (ntree->typeinfo->local_merge) {
|
||||
ntree->typeinfo->local_merge(bmain, localtree, ntree);
|
||||
}
|
||||
|
||||
ntreeFreeTree(localtree);
|
||||
MEM_freeN(localtree);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -204,6 +204,8 @@ void BLO_blendfiledata_free(BlendFileData *bfd);
|
|||
typedef struct BLODataBlockInfo {
|
||||
char name[64]; /* MAX_NAME */
|
||||
struct AssetMetaData *asset_data;
|
||||
/** Ownership over #asset_data above can be "stolen out" of this struct, for more permanent
|
||||
* storage. In that case, set this to false to avoid double freeing of the stolen data. */
|
||||
bool free_asset_data;
|
||||
/**
|
||||
* Optimization: Tag data-blocks for which we know there is no preview.
|
||||
|
|
|
@ -79,7 +79,12 @@ bke::GSpanAttributeWriter ensure_selection_attribute(bke::CurvesGeometry &curves
|
|||
{
|
||||
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
|
||||
if (attributes.contains(".selection")) {
|
||||
return attributes.lookup_for_write_span(".selection");
|
||||
bke::GSpanAttributeWriter selection_attr = attributes.lookup_for_write_span(".selection");
|
||||
/* Check domain type. */
|
||||
if (selection_attr.domain == selection_domain) {
|
||||
return selection_attr;
|
||||
}
|
||||
attributes.remove(".selection");
|
||||
}
|
||||
const int domain_size = attributes.domain_size(selection_domain);
|
||||
switch (create_type) {
|
||||
|
|
|
@ -347,72 +347,19 @@ static bool *gpencil_vgroup_bone_deformed_map_get(Object *ob, const int defbase_
|
|||
* for points in vertex groups deformed by bones.
|
||||
* The logic is copied from `editors/sculpt_paint/paint_vertex.cc`. */
|
||||
|
||||
/**
|
||||
* Normalize weights of a stroke point deformed by bones.
|
||||
*/
|
||||
static void do_weight_paint_normalize_all(MDeformVert *dvert,
|
||||
const int defbase_tot,
|
||||
const bool *vgroup_bone_deformed)
|
||||
{
|
||||
float sum = 0.0f, fac;
|
||||
uint tot = 0;
|
||||
MDeformWeight *dw;
|
||||
|
||||
dw = dvert->dw;
|
||||
for (int i = dvert->totweight; i != 0; i--, dw++) {
|
||||
if (dw->def_nr < defbase_tot && vgroup_bone_deformed[dw->def_nr]) {
|
||||
tot++;
|
||||
sum += dw->weight;
|
||||
}
|
||||
}
|
||||
|
||||
if ((tot == 0) || (sum == 1.0f)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sum != 0.0f) {
|
||||
fac = 1.0f / sum;
|
||||
|
||||
dw = dvert->dw;
|
||||
for (int i = dvert->totweight; i != 0; i--, dw++) {
|
||||
if (dw->def_nr < defbase_tot && vgroup_bone_deformed[dw->def_nr]) {
|
||||
dw->weight *= fac;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
fac = 1.0f / tot;
|
||||
|
||||
dw = dvert->dw;
|
||||
for (int i = dvert->totweight; i != 0; i--, dw++) {
|
||||
if (dw->def_nr < defbase_tot && vgroup_bone_deformed[dw->def_nr]) {
|
||||
dw->weight = fac;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A version of #do_weight_paint_normalize_all that only changes unlocked weights.
|
||||
*/
|
||||
static bool do_weight_paint_normalize_all_unlocked(MDeformVert *dvert,
|
||||
const int defbase_tot,
|
||||
const bool *vgroup_bone_deformed,
|
||||
const bool *vgroup_locked,
|
||||
const bool lock_active_vgroup,
|
||||
const int active_vgroup)
|
||||
static bool do_weight_paint_normalize(MDeformVert *dvert,
|
||||
const int defbase_tot,
|
||||
const bool *vgroup_bone_deformed,
|
||||
const bool *vgroup_locked,
|
||||
const bool lock_active_vgroup,
|
||||
const int active_vgroup)
|
||||
{
|
||||
float sum = 0.0f, fac;
|
||||
float sum_unlock = 0.0f;
|
||||
float sum_lock = 0.0f;
|
||||
uint tot = 0;
|
||||
uint lock_tot = 0, unlock_tot = 0;
|
||||
MDeformWeight *dw;
|
||||
|
||||
if (vgroup_locked == NULL) {
|
||||
do_weight_paint_normalize_all(dvert, defbase_tot, vgroup_bone_deformed);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dvert->totweight <= 1) {
|
||||
return true;
|
||||
}
|
||||
|
@ -424,10 +371,11 @@ static bool do_weight_paint_normalize_all_unlocked(MDeformVert *dvert,
|
|||
sum += dw->weight;
|
||||
|
||||
if (vgroup_locked[dw->def_nr] || (lock_active_vgroup && active_vgroup == dw->def_nr)) {
|
||||
lock_tot++;
|
||||
sum_lock += dw->weight;
|
||||
}
|
||||
else {
|
||||
tot++;
|
||||
unlock_tot++;
|
||||
sum_unlock += dw->weight;
|
||||
}
|
||||
}
|
||||
|
@ -437,8 +385,10 @@ static bool do_weight_paint_normalize_all_unlocked(MDeformVert *dvert,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (tot == 0) {
|
||||
return false;
|
||||
if (unlock_tot == 0) {
|
||||
/* There are no unlocked vertex groups to normalize. We don't need
|
||||
* a second pass when there is only one locked group (the active group). */
|
||||
return (lock_tot == 1);
|
||||
}
|
||||
|
||||
if (sum_lock >= 1.0f - VERTEX_WEIGHT_LOCK_EPSILON) {
|
||||
|
@ -446,7 +396,6 @@ static bool do_weight_paint_normalize_all_unlocked(MDeformVert *dvert,
|
|||
* zero out what we can and return false. */
|
||||
dw = dvert->dw;
|
||||
for (int i = dvert->totweight; i != 0; i--, dw++) {
|
||||
*dw = dvert->dw[i];
|
||||
if (dw->def_nr < defbase_tot && vgroup_bone_deformed[dw->def_nr]) {
|
||||
if ((vgroup_locked[dw->def_nr] == false) &&
|
||||
!(lock_active_vgroup && active_vgroup == dw->def_nr)) {
|
||||
|
@ -473,7 +422,7 @@ static bool do_weight_paint_normalize_all_unlocked(MDeformVert *dvert,
|
|||
}
|
||||
}
|
||||
else {
|
||||
fac = (1.0f - sum_lock) / tot;
|
||||
fac = (1.0f - sum_lock) / unlock_tot;
|
||||
CLAMP(fac, 0.0f, 1.0f);
|
||||
|
||||
dw = dvert->dw;
|
||||
|
@ -492,18 +441,18 @@ static bool do_weight_paint_normalize_all_unlocked(MDeformVert *dvert,
|
|||
}
|
||||
|
||||
/**
|
||||
* A version of #do_weight_paint_normalize_all that only changes unlocked weights
|
||||
* A version of #do_weight_paint_normalize that only changes unlocked weights
|
||||
* and does a second pass without the active vertex group locked when the first pass fails.
|
||||
*/
|
||||
static void do_weight_paint_normalize_all_try(MDeformVert *dvert, tGP_BrushWeightpaintData *gso)
|
||||
static void do_weight_paint_normalize_try(MDeformVert *dvert, tGP_BrushWeightpaintData *gso)
|
||||
{
|
||||
/* First pass with both active and explicitly locked vertex groups restricted from change. */
|
||||
bool succes = do_weight_paint_normalize_all_unlocked(
|
||||
bool succes = do_weight_paint_normalize(
|
||||
dvert, gso->vgroup_tot, gso->vgroup_bone_deformed, gso->vgroup_locked, true, gso->vrgroup);
|
||||
|
||||
if (!succes) {
|
||||
/* Second pass with active vertex group unlocked. */
|
||||
do_weight_paint_normalize_all_unlocked(
|
||||
do_weight_paint_normalize(
|
||||
dvert, gso->vgroup_tot, gso->vgroup_bone_deformed, gso->vgroup_locked, false, -1);
|
||||
}
|
||||
}
|
||||
|
@ -585,7 +534,7 @@ static bool brush_draw_apply(tGP_BrushWeightpaintData *gso,
|
|||
|
||||
/* Perform auto-normalize. */
|
||||
if (gso->auto_normalize) {
|
||||
do_weight_paint_normalize_all_try(dvert, gso);
|
||||
do_weight_paint_normalize_try(dvert, gso);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -615,7 +564,7 @@ static bool brush_average_apply(tGP_BrushWeightpaintData *gso,
|
|||
|
||||
/* Perform auto-normalize. */
|
||||
if (gso->auto_normalize) {
|
||||
do_weight_paint_normalize_all_try(dvert, gso);
|
||||
do_weight_paint_normalize_try(dvert, gso);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -667,7 +616,7 @@ static bool brush_blur_apply(tGP_BrushWeightpaintData *gso,
|
|||
|
||||
/* Perform auto-normalize. */
|
||||
if (gso->auto_normalize) {
|
||||
do_weight_paint_normalize_all_try(dvert, gso);
|
||||
do_weight_paint_normalize_try(dvert, gso);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -749,7 +698,7 @@ static bool brush_smear_apply(tGP_BrushWeightpaintData *gso,
|
|||
|
||||
/* Perform auto-normalize. */
|
||||
if (gso->auto_normalize) {
|
||||
do_weight_paint_normalize_all_try(dvert, gso);
|
||||
do_weight_paint_normalize_try(dvert, gso);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -23,7 +23,9 @@ set(INC_SYS
|
|||
|
||||
set(SRC
|
||||
intern/grease_pencil_add.cc
|
||||
intern/grease_pencil_edit.cc
|
||||
intern/grease_pencil_ops.cc
|
||||
intern/grease_pencil_select.cc
|
||||
)
|
||||
|
||||
set(LIB
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup edgreasepencil
|
||||
*/
|
||||
|
||||
#include "BKE_context.h"
|
||||
|
||||
#include "ED_grease_pencil.h"
|
||||
#include "ED_screen.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
|
||||
namespace blender::ed::greasepencil {
|
||||
|
||||
bool editable_grease_pencil_poll(bContext *C)
|
||||
{
|
||||
Object *object = CTX_data_active_object(C);
|
||||
if (object == nullptr || object->type != OB_GREASE_PENCIL) {
|
||||
return false;
|
||||
}
|
||||
if (!ED_operator_object_active_editable_ex(C, object)) {
|
||||
return false;
|
||||
}
|
||||
if ((object->mode & OB_MODE_EDIT) == 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool editable_grease_pencil_point_selection_poll(bContext *C)
|
||||
{
|
||||
if (!editable_grease_pencil_poll(C)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Allowed: point and segment selection mode, not allowed: stroke selection mode. */
|
||||
ToolSettings *ts = CTX_data_tool_settings(C);
|
||||
return (ts->gpencil_selectmode_edit != GP_SELECTMODE_STROKE);
|
||||
}
|
||||
|
||||
static void keymap_grease_pencil_editing(wmKeyConfig *keyconf)
|
||||
{
|
||||
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Edit Mode", 0, 0);
|
||||
keymap->poll = editable_grease_pencil_poll;
|
||||
}
|
||||
|
||||
} // namespace blender::ed::greasepencil
|
||||
|
||||
void ED_keymap_grease_pencil(wmKeyConfig *keyconf)
|
||||
{
|
||||
using namespace blender::ed::greasepencil;
|
||||
keymap_grease_pencil_editing(keyconf);
|
||||
}
|
|
@ -6,284 +6,10 @@
|
|||
* \ingroup edgreasepencil
|
||||
*/
|
||||
|
||||
#include "BLI_vector_set.hh"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_grease_pencil.hh"
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
||||
#include "ED_curves.h"
|
||||
#include "ED_grease_pencil.h"
|
||||
#include "ED_screen.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
#include "RNA_enum_types.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
|
||||
namespace blender::ed::greasepencil {
|
||||
|
||||
bool editable_grease_pencil_poll(bContext *C)
|
||||
{
|
||||
Object *object = CTX_data_active_object(C);
|
||||
if (object == nullptr || object->type != OB_GREASE_PENCIL) {
|
||||
return false;
|
||||
}
|
||||
if (!ED_operator_object_active_editable_ex(C, object)) {
|
||||
return false;
|
||||
}
|
||||
if ((object->mode & OB_MODE_EDIT) == 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int select_all_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
int action = RNA_enum_get(op->ptr, "action");
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *object = CTX_data_active_object(C);
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
|
||||
|
||||
grease_pencil.foreach_editable_drawing(
|
||||
scene->r.cfra, [action](int /*drawing_index*/, GreasePencilDrawing &drawing) {
|
||||
/* TODO: Support different selection domains. */
|
||||
blender::ed::curves::select_all(drawing.geometry.wrap(), ATTR_DOMAIN_POINT, action);
|
||||
});
|
||||
|
||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
||||
* attribute for now. */
|
||||
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void GREASE_PENCIL_OT_select_all(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "(De)select All Strokes";
|
||||
ot->idname = "GREASE_PENCIL_OT_select_all";
|
||||
ot->description = "(De)select all visible strokes";
|
||||
|
||||
ot->exec = select_all_exec;
|
||||
ot->poll = editable_grease_pencil_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
WM_operator_properties_select_all(ot);
|
||||
}
|
||||
|
||||
static int select_more_exec(bContext *C, wmOperator * /*op*/)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *object = CTX_data_active_object(C);
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
|
||||
|
||||
grease_pencil.foreach_editable_drawing(
|
||||
scene->r.cfra, [](int /*drawing_index*/, GreasePencilDrawing &drawing) {
|
||||
/* TODO: Support different selection domains. */
|
||||
blender::ed::curves::select_adjacent(drawing.geometry.wrap(), false);
|
||||
});
|
||||
|
||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
||||
* attribute for now. */
|
||||
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void GREASE_PENCIL_OT_select_more(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Select More";
|
||||
ot->idname = "GREASE_PENCIL_OT_select_more";
|
||||
ot->description = "Grow the selection by one point";
|
||||
|
||||
ot->exec = select_more_exec;
|
||||
ot->poll = editable_grease_pencil_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
static int select_less_exec(bContext *C, wmOperator * /*op*/)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *object = CTX_data_active_object(C);
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
|
||||
|
||||
grease_pencil.foreach_editable_drawing(
|
||||
scene->r.cfra, [](int /*drawing_index*/, GreasePencilDrawing &drawing) {
|
||||
/* TODO: Support different selection domains. */
|
||||
blender::ed::curves::select_adjacent(drawing.geometry.wrap(), true);
|
||||
});
|
||||
|
||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
||||
* attribute for now. */
|
||||
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void GREASE_PENCIL_OT_select_less(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Select Less";
|
||||
ot->idname = "GREASE_PENCIL_OT_select_less";
|
||||
ot->description = "Shrink the selection by one point";
|
||||
|
||||
ot->exec = select_less_exec;
|
||||
ot->poll = editable_grease_pencil_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
static int select_linked_exec(bContext *C, wmOperator * /*op*/)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *object = CTX_data_active_object(C);
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
|
||||
|
||||
grease_pencil.foreach_editable_drawing(
|
||||
scene->r.cfra, [](int /*drawing_index*/, GreasePencilDrawing &drawing) {
|
||||
/* TODO: Support different selection domains. */
|
||||
blender::ed::curves::select_linked(drawing.geometry.wrap());
|
||||
});
|
||||
|
||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
||||
* attribute for now. */
|
||||
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void GREASE_PENCIL_OT_select_linked(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Select Linked";
|
||||
ot->idname = "GREASE_PENCIL_OT_select_linked";
|
||||
ot->description = "Select all points in curves with any point selection";
|
||||
|
||||
ot->exec = select_linked_exec;
|
||||
ot->poll = editable_grease_pencil_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
static int select_random_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
const float ratio = RNA_float_get(op->ptr, "ratio");
|
||||
const int seed = WM_operator_properties_select_random_seed_increment_get(op);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *object = CTX_data_active_object(C);
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
|
||||
|
||||
grease_pencil.foreach_editable_drawing(
|
||||
scene->r.cfra, [&](int drawing_index, GreasePencilDrawing &drawing) {
|
||||
// TODO: Support different selection domains.
|
||||
blender::ed::curves::select_random(drawing.geometry.wrap(),
|
||||
ATTR_DOMAIN_POINT,
|
||||
blender::get_default_hash_2<int>(seed, drawing_index),
|
||||
ratio);
|
||||
});
|
||||
|
||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
||||
* attribute for now. */
|
||||
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void GREASE_PENCIL_OT_select_random(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Select Random";
|
||||
ot->idname = "GREASE_PENCIL_OT_select_random";
|
||||
ot->description = "Selects random points from the current strokes selection";
|
||||
|
||||
ot->exec = select_random_exec;
|
||||
ot->poll = editable_grease_pencil_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
WM_operator_properties_select_random(ot);
|
||||
}
|
||||
|
||||
static int select_ends_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
const int amount_start = RNA_int_get(op->ptr, "amount_start");
|
||||
const int amount_end = RNA_int_get(op->ptr, "amount_end");
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *object = CTX_data_active_object(C);
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
|
||||
|
||||
grease_pencil.foreach_editable_drawing(
|
||||
scene->r.cfra, [&](int /*drawing_index*/, GreasePencilDrawing &drawing) {
|
||||
blender::ed::curves::select_ends(drawing.geometry.wrap(), amount_start, amount_end);
|
||||
});
|
||||
|
||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
||||
* attribute for now. */
|
||||
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void GREASE_PENCIL_OT_select_ends(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Select Ends";
|
||||
ot->idname = "GREASE_PENCIL_OT_select_ends";
|
||||
ot->description = "Select end points of strokes";
|
||||
|
||||
ot->exec = select_ends_exec;
|
||||
ot->poll = editable_grease_pencil_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
RNA_def_int(ot->srna,
|
||||
"amount_start",
|
||||
0,
|
||||
0,
|
||||
INT32_MAX,
|
||||
"Amount Start",
|
||||
"Number of points to select from the start",
|
||||
0,
|
||||
INT32_MAX);
|
||||
RNA_def_int(ot->srna,
|
||||
"amount_end",
|
||||
1,
|
||||
0,
|
||||
INT32_MAX,
|
||||
"Amount End",
|
||||
"Number of points to select from the end",
|
||||
0,
|
||||
INT32_MAX);
|
||||
}
|
||||
|
||||
static void keymap_grease_pencil_editing(wmKeyConfig *keyconf)
|
||||
{
|
||||
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Edit Mode", 0, 0);
|
||||
keymap->poll = editable_grease_pencil_poll;
|
||||
}
|
||||
|
||||
} // namespace blender::ed::greasepencil
|
||||
void ED_operatortypes_grease_pencil(void)
|
||||
{
|
||||
using namespace blender::ed::greasepencil;
|
||||
WM_operatortype_append(GREASE_PENCIL_OT_select_all);
|
||||
WM_operatortype_append(GREASE_PENCIL_OT_select_more);
|
||||
WM_operatortype_append(GREASE_PENCIL_OT_select_less);
|
||||
WM_operatortype_append(GREASE_PENCIL_OT_select_linked);
|
||||
WM_operatortype_append(GREASE_PENCIL_OT_select_random);
|
||||
WM_operatortype_append(GREASE_PENCIL_OT_select_ends);
|
||||
}
|
||||
|
||||
void ED_keymap_grease_pencil(wmKeyConfig *keyconf)
|
||||
{
|
||||
using namespace blender::ed::greasepencil;
|
||||
keymap_grease_pencil_editing(keyconf);
|
||||
ED_operatortypes_grease_pencil_select();
|
||||
ED_operatortypes_grease_pencil_draw();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,279 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup edgreasepencil
|
||||
*/
|
||||
|
||||
#include "BLI_vector_set.hh"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_grease_pencil.hh"
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
||||
#include "ED_curves.h"
|
||||
#include "ED_grease_pencil.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_view3d.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
#include "RNA_enum_types.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
|
||||
namespace blender::ed::greasepencil {
|
||||
|
||||
static int select_all_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
int action = RNA_enum_get(op->ptr, "action");
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *object = CTX_data_active_object(C);
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
|
||||
eAttrDomain selection_domain = ED_grease_pencil_selection_domain_get(C);
|
||||
|
||||
grease_pencil.foreach_editable_drawing(
|
||||
scene->r.cfra, [&](int /*drawing_index*/, GreasePencilDrawing &drawing) {
|
||||
blender::ed::curves::select_all(drawing.geometry.wrap(), selection_domain, action);
|
||||
});
|
||||
|
||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
||||
* attribute for now. */
|
||||
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void GREASE_PENCIL_OT_select_all(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "(De)select All Strokes";
|
||||
ot->idname = "GREASE_PENCIL_OT_select_all";
|
||||
ot->description = "(De)select all visible strokes";
|
||||
|
||||
ot->exec = select_all_exec;
|
||||
ot->poll = editable_grease_pencil_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
WM_operator_properties_select_all(ot);
|
||||
}
|
||||
|
||||
static int select_more_exec(bContext *C, wmOperator * /*op*/)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *object = CTX_data_active_object(C);
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
|
||||
|
||||
grease_pencil.foreach_editable_drawing(
|
||||
scene->r.cfra, [](int /*drawing_index*/, GreasePencilDrawing &drawing) {
|
||||
blender::ed::curves::select_adjacent(drawing.geometry.wrap(), false);
|
||||
});
|
||||
|
||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
||||
* attribute for now. */
|
||||
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void GREASE_PENCIL_OT_select_more(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Select More";
|
||||
ot->idname = "GREASE_PENCIL_OT_select_more";
|
||||
ot->description = "Grow the selection by one point";
|
||||
|
||||
ot->exec = select_more_exec;
|
||||
ot->poll = editable_grease_pencil_point_selection_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
static int select_less_exec(bContext *C, wmOperator * /*op*/)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *object = CTX_data_active_object(C);
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
|
||||
|
||||
grease_pencil.foreach_editable_drawing(
|
||||
scene->r.cfra, [](int /*drawing_index*/, GreasePencilDrawing &drawing) {
|
||||
blender::ed::curves::select_adjacent(drawing.geometry.wrap(), true);
|
||||
});
|
||||
|
||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
||||
* attribute for now. */
|
||||
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void GREASE_PENCIL_OT_select_less(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Select Less";
|
||||
ot->idname = "GREASE_PENCIL_OT_select_less";
|
||||
ot->description = "Shrink the selection by one point";
|
||||
|
||||
ot->exec = select_less_exec;
|
||||
ot->poll = editable_grease_pencil_point_selection_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
static int select_linked_exec(bContext *C, wmOperator * /*op*/)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *object = CTX_data_active_object(C);
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
|
||||
|
||||
grease_pencil.foreach_editable_drawing(
|
||||
scene->r.cfra, [](int /*drawing_index*/, GreasePencilDrawing &drawing) {
|
||||
blender::ed::curves::select_linked(drawing.geometry.wrap());
|
||||
});
|
||||
|
||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
||||
* attribute for now. */
|
||||
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void GREASE_PENCIL_OT_select_linked(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Select Linked";
|
||||
ot->idname = "GREASE_PENCIL_OT_select_linked";
|
||||
ot->description = "Select all points in curves with any point selection";
|
||||
|
||||
ot->exec = select_linked_exec;
|
||||
ot->poll = editable_grease_pencil_point_selection_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
static int select_random_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
const float ratio = RNA_float_get(op->ptr, "ratio");
|
||||
const int seed = WM_operator_properties_select_random_seed_increment_get(op);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *object = CTX_data_active_object(C);
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
|
||||
eAttrDomain selection_domain = ED_grease_pencil_selection_domain_get(C);
|
||||
|
||||
grease_pencil.foreach_editable_drawing(
|
||||
scene->r.cfra, [&](int drawing_index, GreasePencilDrawing &drawing) {
|
||||
blender::ed::curves::select_random(drawing.geometry.wrap(),
|
||||
selection_domain,
|
||||
blender::get_default_hash_2<int>(seed, drawing_index),
|
||||
ratio);
|
||||
});
|
||||
|
||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
||||
* attribute for now. */
|
||||
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void GREASE_PENCIL_OT_select_random(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Select Random";
|
||||
ot->idname = "GREASE_PENCIL_OT_select_random";
|
||||
ot->description = "Selects random points from the current strokes selection";
|
||||
|
||||
ot->exec = select_random_exec;
|
||||
ot->poll = editable_grease_pencil_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
WM_operator_properties_select_random(ot);
|
||||
}
|
||||
|
||||
static int select_ends_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
const int amount_start = RNA_int_get(op->ptr, "amount_start");
|
||||
const int amount_end = RNA_int_get(op->ptr, "amount_end");
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *object = CTX_data_active_object(C);
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
|
||||
|
||||
grease_pencil.foreach_editable_drawing(
|
||||
scene->r.cfra, [&](int /*drawing_index*/, GreasePencilDrawing &drawing) {
|
||||
blender::ed::curves::select_ends(drawing.geometry.wrap(), amount_start, amount_end);
|
||||
});
|
||||
|
||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
||||
* attribute for now. */
|
||||
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void GREASE_PENCIL_OT_select_ends(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Select Ends";
|
||||
ot->idname = "GREASE_PENCIL_OT_select_ends";
|
||||
ot->description = "Select end points of strokes";
|
||||
|
||||
ot->exec = select_ends_exec;
|
||||
ot->poll = editable_grease_pencil_point_selection_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
RNA_def_int(ot->srna,
|
||||
"amount_start",
|
||||
0,
|
||||
0,
|
||||
INT32_MAX,
|
||||
"Amount Start",
|
||||
"Number of points to select from the start",
|
||||
0,
|
||||
INT32_MAX);
|
||||
RNA_def_int(ot->srna,
|
||||
"amount_end",
|
||||
1,
|
||||
0,
|
||||
INT32_MAX,
|
||||
"Amount End",
|
||||
"Number of points to select from the end",
|
||||
0,
|
||||
INT32_MAX);
|
||||
}
|
||||
|
||||
} // namespace blender::ed::greasepencil
|
||||
|
||||
eAttrDomain ED_grease_pencil_selection_domain_get(bContext *C)
|
||||
{
|
||||
ToolSettings *ts = CTX_data_tool_settings(C);
|
||||
|
||||
switch (ts->gpencil_selectmode_edit) {
|
||||
case GP_SELECTMODE_POINT:
|
||||
return ATTR_DOMAIN_POINT;
|
||||
break;
|
||||
case GP_SELECTMODE_STROKE:
|
||||
return ATTR_DOMAIN_CURVE;
|
||||
break;
|
||||
case GP_SELECTMODE_SEGMENT:
|
||||
return ATTR_DOMAIN_POINT;
|
||||
break;
|
||||
}
|
||||
return ATTR_DOMAIN_POINT;
|
||||
}
|
||||
|
||||
void ED_operatortypes_grease_pencil_select(void)
|
||||
{
|
||||
using namespace blender::ed::greasepencil;
|
||||
WM_operatortype_append(GREASE_PENCIL_OT_select_all);
|
||||
WM_operatortype_append(GREASE_PENCIL_OT_select_more);
|
||||
WM_operatortype_append(GREASE_PENCIL_OT_select_less);
|
||||
WM_operatortype_append(GREASE_PENCIL_OT_select_linked);
|
||||
WM_operatortype_append(GREASE_PENCIL_OT_select_random);
|
||||
WM_operatortype_append(GREASE_PENCIL_OT_select_ends);
|
||||
}
|
|
@ -130,10 +130,13 @@ void ED_file_indexer_entries_clear(FileIndexerEntries *indexer_entries);
|
|||
* Adds all entries from the given `datablock_infos` to the `indexer_entries`.
|
||||
* The datablock_infos must only contain data for a single IDType. The specific IDType must be
|
||||
* passed in the `idcode` parameter.
|
||||
*
|
||||
* \note This can "steal" data contained in \a datablock_infos, to avoid expensive copies, which is
|
||||
* supported by the #BLODataBlockInfo type.
|
||||
*/
|
||||
void ED_file_indexer_entries_extend_from_datablock_infos(
|
||||
FileIndexerEntries *indexer_entries,
|
||||
const LinkNode * /*BLODataBlockInfo*/ datablock_infos,
|
||||
struct LinkNode * /*BLODataBlockInfo*/ datablock_infos,
|
||||
int idcode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "BKE_attribute.h"
|
||||
|
||||
struct bContext;
|
||||
|
||||
struct Main;
|
||||
|
@ -24,7 +26,13 @@ extern "C" {
|
|||
* \{ */
|
||||
|
||||
void ED_operatortypes_grease_pencil(void);
|
||||
void ED_operatortypes_grease_pencil_draw(void);
|
||||
void ED_operatortypes_grease_pencil_select(void);
|
||||
void ED_keymap_grease_pencil(struct wmKeyConfig *keyconf);
|
||||
/**
|
||||
* Get the selection mode for Grease Pencil selection operators: point, stroke, segment.
|
||||
*/
|
||||
eAttrDomain ED_grease_pencil_selection_domain_get(struct bContext *C);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -32,9 +40,12 @@ void ED_keymap_grease_pencil(struct wmKeyConfig *keyconf);
|
|||
|
||||
#ifdef __cplusplus
|
||||
|
||||
# include "BLI_math_matrix_types.hh"
|
||||
|
||||
namespace blender::ed::greasepencil {
|
||||
|
||||
bool editable_grease_pencil_poll(bContext *C);
|
||||
bool editable_grease_pencil_point_selection_poll(bContext *C);
|
||||
|
||||
void create_blank(Main &bmain, Object &object, int frame_number);
|
||||
void create_stroke(Main &bmain, Object &object, float4x4 matrix, int frame_number);
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup editors
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void ED_operatortypes_grease_pencil_draw(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -41,11 +41,6 @@ struct SnapObjectHitDepth {
|
|||
|
||||
float depth;
|
||||
float co[3];
|
||||
float no[3];
|
||||
int index;
|
||||
|
||||
struct Object *ob_eval;
|
||||
float obmat[4][4];
|
||||
|
||||
/* needed to tell which ray-cast this was part of,
|
||||
* the same object may be part of many ray-casts when dupli's are used. */
|
||||
|
@ -58,12 +53,12 @@ struct SnapObjectParams {
|
|||
eSnapTargetOP snap_target_select;
|
||||
/* Geometry for snapping in edit mode. */
|
||||
eSnapEditType edit_mode_type;
|
||||
/* Break nearest face snapping into steps to improve transformations across U-shaped targets. */
|
||||
short face_nearest_steps;
|
||||
/* snap to the closest element, use when using more than one snap type */
|
||||
bool use_occlusion_test : 1;
|
||||
/* exclude back facing geometry from snapping */
|
||||
bool use_backface_culling : 1;
|
||||
/* Break nearest face snapping into steps to improve transformations across U-shaped targets. */
|
||||
short face_nearest_steps;
|
||||
/* Enable to force nearest face snapping to snap to target the source was initially near. */
|
||||
bool keep_on_same_target : 1;
|
||||
};
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "BKE_attribute.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "DNA_brush_types.h"
|
||||
#include "DNA_grease_pencil_types.h"
|
||||
|
||||
#include "ED_grease_pencil_draw.h"
|
||||
#include "ED_grease_pencil.h"
|
||||
#include "ED_object.h"
|
||||
#include "ED_screen.h"
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#include "ED_gizmo_library.h"
|
||||
#include "ED_gpencil_legacy.h"
|
||||
#include "ED_grease_pencil.h"
|
||||
#include "ED_grease_pencil_draw.h"
|
||||
#include "ED_lattice.h"
|
||||
#include "ED_markers.h"
|
||||
#include "ED_mask.h"
|
||||
|
@ -95,7 +94,6 @@ void ED_spacetypes_init()
|
|||
ED_operatortypes_animchannels();
|
||||
ED_operatortypes_asset();
|
||||
ED_operatortypes_gpencil_legacy();
|
||||
ED_operatortypes_grease_pencil_draw();
|
||||
ED_operatortypes_grease_pencil();
|
||||
ED_operatortypes_object();
|
||||
ED_operatortypes_lattice();
|
||||
|
|
|
@ -42,12 +42,14 @@ constexpr FileIndexerType default_indexer()
|
|||
}
|
||||
|
||||
static FileIndexerEntry *file_indexer_entry_create_from_datablock_info(
|
||||
const BLODataBlockInfo *datablock_info, const int idcode)
|
||||
BLODataBlockInfo *datablock_info, const int idcode)
|
||||
{
|
||||
FileIndexerEntry *entry = static_cast<FileIndexerEntry *>(
|
||||
MEM_mallocN(sizeof(FileIndexerEntry), __func__));
|
||||
entry->datablock_info = *datablock_info;
|
||||
entry->idcode = idcode;
|
||||
/* Shallow copy data-block info and mark original as having its asset data ownership stolen. */
|
||||
entry->datablock_info = *datablock_info;
|
||||
datablock_info->free_asset_data = false;
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
@ -57,11 +59,11 @@ extern "C" {
|
|||
|
||||
void ED_file_indexer_entries_extend_from_datablock_infos(
|
||||
FileIndexerEntries *indexer_entries,
|
||||
const LinkNode * /*BLODataBlockInfo*/ datablock_infos,
|
||||
LinkNode * /*BLODataBlockInfo*/ datablock_infos,
|
||||
const int idcode)
|
||||
{
|
||||
for (const LinkNode *ln = datablock_infos; ln; ln = ln->next) {
|
||||
const BLODataBlockInfo *datablock_info = static_cast<const BLODataBlockInfo *>(ln->link);
|
||||
for (LinkNode *ln = datablock_infos; ln; ln = ln->next) {
|
||||
BLODataBlockInfo *datablock_info = static_cast<BLODataBlockInfo *>(ln->link);
|
||||
FileIndexerEntry *file_indexer_entry =
|
||||
blender::ed::file::indexer::file_indexer_entry_create_from_datablock_info(datablock_info,
|
||||
idcode);
|
||||
|
@ -69,16 +71,14 @@ void ED_file_indexer_entries_extend_from_datablock_infos(
|
|||
}
|
||||
}
|
||||
|
||||
static void ED_file_indexer_entry_free(void *indexer_entry_ptr)
|
||||
{
|
||||
FileIndexerEntry *indexer_entry = static_cast<FileIndexerEntry *>(indexer_entry_ptr);
|
||||
BLO_datablock_info_free(&indexer_entry->datablock_info);
|
||||
MEM_freeN(indexer_entry);
|
||||
}
|
||||
|
||||
void ED_file_indexer_entries_clear(FileIndexerEntries *indexer_entries)
|
||||
{
|
||||
BLI_linklist_free(indexer_entries->entries, ED_file_indexer_entry_free);
|
||||
BLI_linklist_free(indexer_entries->entries, [](void *indexer_entry_ptr) {
|
||||
FileIndexerEntry *indexer_entry = static_cast<FileIndexerEntry *>(indexer_entry_ptr);
|
||||
BLO_datablock_info_free(&indexer_entry->datablock_info);
|
||||
MEM_freeN(indexer_entry);
|
||||
});
|
||||
|
||||
indexer_entries->entries = nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -3299,7 +3299,8 @@ static std::optional<int> filelist_readjob_list_lib(FileListReadJob *job_params,
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
const bool group_came_from_path = group != nullptr;
|
||||
/* The root path contains an ID group (e.g. "Materials" or "Objects"). */
|
||||
const bool has_group = group != nullptr;
|
||||
|
||||
/* Try read from indexer_runtime. */
|
||||
/* Indexing returns all entries in a blend file. We should ignore the index when listing a group
|
||||
|
@ -3309,7 +3310,7 @@ static std::optional<int> filelist_readjob_list_lib(FileListReadJob *job_params,
|
|||
*
|
||||
* Adding support for partial reading/updating indexes would increase the complexity.
|
||||
*/
|
||||
const bool use_indexer = !group_came_from_path;
|
||||
const bool use_indexer = !has_group;
|
||||
FileIndexerEntries indexer_entries = {nullptr};
|
||||
if (use_indexer) {
|
||||
int read_from_index = 0;
|
||||
|
@ -3344,7 +3345,8 @@ static std::optional<int> filelist_readjob_list_lib(FileListReadJob *job_params,
|
|||
|
||||
int group_len = 0;
|
||||
int datablock_len = 0;
|
||||
if (group_came_from_path) {
|
||||
/* Read only the datablocks from this group. */
|
||||
if (has_group) {
|
||||
const int idcode = groupname_to_code(group);
|
||||
LinkNode *datablock_infos = BLO_blendhandle_get_datablock_info(
|
||||
libfiledata, idcode, options & LIST_LIB_ASSETS_ONLY, &datablock_len);
|
||||
|
@ -3352,6 +3354,7 @@ static std::optional<int> filelist_readjob_list_lib(FileListReadJob *job_params,
|
|||
job_params, entries, datablock_infos, false, idcode, group);
|
||||
BLO_datablock_info_linklist_free(datablock_infos);
|
||||
}
|
||||
/* Read all datablocks from all groups. */
|
||||
else {
|
||||
LinkNode *groups = BLO_blendhandle_get_linkable_groups(libfiledata);
|
||||
group_len = BLI_linklist_count(groups);
|
||||
|
|
|
@ -97,10 +97,11 @@ struct CompoJob {
|
|||
bNodeTree *localtree;
|
||||
/* Render instance. */
|
||||
Render *re;
|
||||
/* Jon system integration. */
|
||||
/* Job system integration. */
|
||||
const bool *stop;
|
||||
bool *do_update;
|
||||
float *progress;
|
||||
bool cancelled;
|
||||
};
|
||||
|
||||
float node_socket_calculate_height(const bNodeSocket &socket)
|
||||
|
@ -209,7 +210,13 @@ static void compo_freejob(void *cjv)
|
|||
CompoJob *cj = (CompoJob *)cjv;
|
||||
|
||||
if (cj->localtree) {
|
||||
bke::ntreeLocalMerge(cj->bmain, cj->localtree, cj->ntree);
|
||||
/* Merge back node previews, only for completed jobs. */
|
||||
if (!cj->cancelled) {
|
||||
bke::ntreeLocalMerge(cj->bmain, cj->localtree, cj->ntree);
|
||||
}
|
||||
|
||||
bke::ntreeFreeTree(cj->localtree);
|
||||
MEM_freeN(cj->localtree);
|
||||
}
|
||||
if (cj->compositor_depsgraph != nullptr) {
|
||||
DEG_graph_free(cj->compositor_depsgraph);
|
||||
|
@ -315,6 +322,7 @@ static void compo_canceljob(void *cjv)
|
|||
Main *bmain = cj->bmain;
|
||||
Scene *scene = cj->scene;
|
||||
BKE_callback_exec_id(bmain, &scene->id, BKE_CB_EVT_COMPOSITE_CANCEL);
|
||||
cj->cancelled = true;
|
||||
}
|
||||
|
||||
static void compo_completejob(void *cjv)
|
||||
|
|
|
@ -57,6 +57,7 @@ set(SRC
|
|||
tree/tree_element_driver.cc
|
||||
tree/tree_element_gpencil_layer.cc
|
||||
tree/tree_element_id.cc
|
||||
tree/tree_element_id_armature.cc
|
||||
tree/tree_element_id_collection.cc
|
||||
tree/tree_element_id_curve.cc
|
||||
tree/tree_element_id_gpencil_legacy.cc
|
||||
|
@ -84,6 +85,7 @@ set(SRC
|
|||
tree/tree_element_driver.hh
|
||||
tree/tree_element_gpencil_layer.hh
|
||||
tree/tree_element_id.hh
|
||||
tree/tree_element_id_armature.hh
|
||||
tree/tree_element_id_collection.hh
|
||||
tree/tree_element_id_curve.hh
|
||||
tree/tree_element_id_gpencil_legacy.hh
|
||||
|
|
|
@ -218,25 +218,6 @@ bool outliner_requires_rebuild_on_select_or_active_change(const SpaceOutliner *s
|
|||
return exclude_flags & (SO_FILTER_OB_STATE_SELECTED | SO_FILTER_OB_STATE_ACTIVE);
|
||||
}
|
||||
|
||||
/* special handling of hierarchical non-lib data */
|
||||
static void outliner_add_bone(SpaceOutliner *space_outliner,
|
||||
ListBase *lb,
|
||||
ID *id,
|
||||
Bone *curBone,
|
||||
TreeElement *parent,
|
||||
int *a)
|
||||
{
|
||||
TreeElement *te = outliner_add_element(space_outliner, lb, id, parent, TSE_BONE, *a);
|
||||
|
||||
(*a)++;
|
||||
te->name = curBone->name;
|
||||
te->directdata = curBone;
|
||||
|
||||
LISTBASE_FOREACH (Bone *, child_bone, &curBone->childbase) {
|
||||
outliner_add_bone(space_outliner, &te->subtree, id, child_bone, te, a);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_FREESTYLE
|
||||
static void outliner_add_line_styles(SpaceOutliner *space_outliner,
|
||||
ListBase *lb,
|
||||
|
@ -558,6 +539,7 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
|
|||
case ID_LS:
|
||||
case ID_GD_LEGACY:
|
||||
case ID_GR:
|
||||
case ID_AR:
|
||||
BLI_assert_msg(0, "ID type expected to be expanded through new tree-element design");
|
||||
break;
|
||||
case ID_OB: {
|
||||
|
@ -626,55 +608,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
|
|||
/* bAction *act = (bAction *)id; */
|
||||
break;
|
||||
}
|
||||
case ID_AR: {
|
||||
bArmature *arm = (bArmature *)id;
|
||||
|
||||
if (outliner_animdata_test(arm->adt)) {
|
||||
outliner_add_element(space_outliner, &te->subtree, arm, te, TSE_ANIM_DATA, 0);
|
||||
}
|
||||
|
||||
if (arm->edbo) {
|
||||
int a = 0;
|
||||
LISTBASE_FOREACH_INDEX (EditBone *, ebone, arm->edbo, a) {
|
||||
TreeElement *ten = outliner_add_element(
|
||||
space_outliner, &te->subtree, id, te, TSE_EBONE, a);
|
||||
ten->directdata = ebone;
|
||||
ten->name = ebone->name;
|
||||
ebone->temp.p = ten;
|
||||
}
|
||||
/* make hierarchy */
|
||||
TreeElement *ten = arm->edbo->first ?
|
||||
static_cast<TreeElement *>(((EditBone *)arm->edbo->first)->temp.p) :
|
||||
nullptr;
|
||||
while (ten) {
|
||||
TreeElement *nten = ten->next, *par;
|
||||
EditBone *ebone = (EditBone *)ten->directdata;
|
||||
if (ebone->parent) {
|
||||
BLI_remlink(&te->subtree, ten);
|
||||
par = static_cast<TreeElement *>(ebone->parent->temp.p);
|
||||
BLI_addtail(&par->subtree, ten);
|
||||
ten->parent = par;
|
||||
}
|
||||
ten = nten;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* do not extend Armature when we have posemode */
|
||||
tselem = TREESTORE(te->parent);
|
||||
if (TSE_IS_REAL_ID(tselem) && GS(tselem->id->name) == ID_OB &&
|
||||
((Object *)tselem->id)->mode & OB_MODE_POSE)
|
||||
{
|
||||
/* pass */
|
||||
}
|
||||
else {
|
||||
int a = 0;
|
||||
LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) {
|
||||
outliner_add_bone(space_outliner, &te->subtree, id, bone, te, &a);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ID_CV: {
|
||||
Curves *curves = (Curves *)id;
|
||||
if (outliner_animdata_test(curves->adt)) {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "../outliner_intern.hh"
|
||||
#include "common.hh"
|
||||
#include "tree_element_id_armature.hh"
|
||||
#include "tree_element_id_collection.hh"
|
||||
#include "tree_element_id_curve.hh"
|
||||
#include "tree_element_id_gpencil_legacy.hh"
|
||||
|
@ -60,6 +61,8 @@ std::unique_ptr<TreeElementID> TreeElementID::createFromID(TreeElement &legacy_t
|
|||
return std::make_unique<TreeElementIDGPLegacy>(legacy_te, (bGPdata &)id);
|
||||
case ID_GR:
|
||||
return std::make_unique<TreeElementIDCollection>(legacy_te, (Collection &)id);
|
||||
case ID_AR:
|
||||
return std::make_unique<TreeElementIDArmature>(legacy_te, (bArmature &)id);
|
||||
case ID_OB:
|
||||
case ID_MA:
|
||||
case ID_LT:
|
||||
|
@ -85,7 +88,6 @@ std::unique_ptr<TreeElementID> TreeElementID::createFromID(TreeElement &legacy_t
|
|||
case ID_VF:
|
||||
case ID_TXT:
|
||||
case ID_SO:
|
||||
case ID_AR:
|
||||
case ID_AC:
|
||||
case ID_PAL:
|
||||
case ID_PC:
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spoutliner
|
||||
*/
|
||||
|
||||
#include "DNA_ID.h"
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_listBase.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_outliner_types.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
#include "BKE_armature.h"
|
||||
|
||||
#include "../outliner_intern.hh"
|
||||
|
||||
#include "tree_element_id_armature.hh"
|
||||
|
||||
namespace blender::ed::outliner {
|
||||
|
||||
TreeElementIDArmature::TreeElementIDArmature(TreeElement &legacy_te, bArmature &arm)
|
||||
: TreeElementID(legacy_te, arm.id), arm_(arm)
|
||||
{
|
||||
}
|
||||
|
||||
void TreeElementIDArmature::expand(SpaceOutliner &space_outliner) const
|
||||
{
|
||||
expand_animation_data(space_outliner, arm_.adt);
|
||||
|
||||
if (arm_.edbo) {
|
||||
expandEditBones(space_outliner);
|
||||
}
|
||||
else {
|
||||
/* do not extend Armature when we have posemode */
|
||||
TreeStoreElem *tselem = TREESTORE(legacy_te_.parent);
|
||||
if (TSE_IS_REAL_ID(tselem) && GS(tselem->id->name) == ID_OB &&
|
||||
((Object *)tselem->id)->mode & OB_MODE_POSE)
|
||||
{
|
||||
/* pass */
|
||||
}
|
||||
else {
|
||||
expandBones(space_outliner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TreeElementIDArmature::isExpandValid() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void TreeElementIDArmature::expandEditBones(SpaceOutliner &space_outiner) const
|
||||
{
|
||||
int a = 0;
|
||||
LISTBASE_FOREACH_INDEX (EditBone *, ebone, arm_.edbo, a) {
|
||||
TreeElement *ten = outliner_add_element(
|
||||
&space_outiner, &legacy_te_.subtree, &arm_.id, &legacy_te_, TSE_EBONE, a);
|
||||
ten->directdata = ebone;
|
||||
ten->name = ebone->name;
|
||||
ebone->temp.p = ten;
|
||||
}
|
||||
/* make hierarchy */
|
||||
TreeElement *ten = arm_.edbo->first ?
|
||||
static_cast<TreeElement *>(((EditBone *)arm_.edbo->first)->temp.p) :
|
||||
nullptr;
|
||||
while (ten) {
|
||||
TreeElement *nten = ten->next, *par;
|
||||
EditBone *ebone = (EditBone *)ten->directdata;
|
||||
if (ebone->parent) {
|
||||
BLI_remlink(&legacy_te_.subtree, ten);
|
||||
par = static_cast<TreeElement *>(ebone->parent->temp.p);
|
||||
BLI_addtail(&par->subtree, ten);
|
||||
ten->parent = par;
|
||||
}
|
||||
ten = nten;
|
||||
}
|
||||
}
|
||||
|
||||
/* special handling of hierarchical non-lib data */
|
||||
static void outliner_add_bone(SpaceOutliner *space_outliner,
|
||||
ListBase *lb,
|
||||
ID *id,
|
||||
Bone *curBone,
|
||||
TreeElement *parent,
|
||||
int *a)
|
||||
{
|
||||
TreeElement *te = outliner_add_element(space_outliner, lb, id, parent, TSE_BONE, *a);
|
||||
|
||||
(*a)++;
|
||||
te->name = curBone->name;
|
||||
te->directdata = curBone;
|
||||
|
||||
LISTBASE_FOREACH (Bone *, child_bone, &curBone->childbase) {
|
||||
outliner_add_bone(space_outliner, &te->subtree, id, child_bone, te, a);
|
||||
}
|
||||
}
|
||||
|
||||
void TreeElementIDArmature::expandBones(SpaceOutliner &space_outliner) const
|
||||
{
|
||||
int a = 0;
|
||||
LISTBASE_FOREACH (Bone *, bone, &arm_.bonebase) {
|
||||
outliner_add_bone(&space_outliner, &legacy_te_.subtree, &arm_.id, bone, &legacy_te_, &a);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::ed::outliner
|
|
@ -0,0 +1,33 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spoutliner
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tree_element_id.hh"
|
||||
|
||||
struct Bone;
|
||||
struct EditBone;
|
||||
struct bArmature;
|
||||
|
||||
namespace blender::ed::outliner {
|
||||
|
||||
class TreeElementIDArmature final : public TreeElementID {
|
||||
bArmature &arm_;
|
||||
|
||||
public:
|
||||
TreeElementIDArmature(TreeElement &legacy_te, bArmature &arm);
|
||||
|
||||
void expand(SpaceOutliner &) const override;
|
||||
bool isExpandValid() const override;
|
||||
|
||||
private:
|
||||
void expandEditBones(SpaceOutliner &) const;
|
||||
void expandBones(SpaceOutliner &) const;
|
||||
};
|
||||
|
||||
} // namespace blender::ed::outliner
|
|
@ -75,6 +75,7 @@
|
|||
#include "ED_curve.h"
|
||||
#include "ED_curves.h"
|
||||
#include "ED_gpencil_legacy.h"
|
||||
#include "ED_grease_pencil.h"
|
||||
#include "ED_lattice.h"
|
||||
#include "ED_mball.h"
|
||||
#include "ED_mesh.h"
|
||||
|
@ -1182,6 +1183,9 @@ static bool do_lasso_select_grease_pencil(ViewContext *vc,
|
|||
const_cast<Object *>(vc->obedit));
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(vc->obedit->data);
|
||||
|
||||
/* Get selection domain from tool settings. */
|
||||
const eAttrDomain selection_domain = ED_grease_pencil_selection_domain_get(vc->C);
|
||||
|
||||
bool changed = false;
|
||||
grease_pencil.foreach_editable_drawing(
|
||||
vc->scene->r.cfra, [&](int drawing_index, GreasePencilDrawing &drawing) {
|
||||
|
@ -1189,12 +1193,11 @@ static bool do_lasso_select_grease_pencil(ViewContext *vc,
|
|||
bke::crazyspace::get_evaluated_grease_pencil_drawing_deformation(
|
||||
ob_eval, *vc->obedit, drawing_index);
|
||||
|
||||
/* TODO: Support different selection domains. */
|
||||
changed = ed::curves::select_lasso(
|
||||
*vc,
|
||||
drawing.geometry.wrap(),
|
||||
deformation.positions,
|
||||
ATTR_DOMAIN_POINT,
|
||||
selection_domain,
|
||||
Span<int2>(reinterpret_cast<const int2 *>(mcoords), mcoords_len),
|
||||
sel_op);
|
||||
});
|
||||
|
@ -3170,8 +3173,8 @@ static bool ed_grease_pencil_select_pick(bContext *C,
|
|||
drawing_indices.append(drawing_index);
|
||||
});
|
||||
|
||||
/* TODO: Support different selection domains. */
|
||||
const eAttrDomain selection_domain = ATTR_DOMAIN_POINT;
|
||||
/* Get selection domain from tool settings. */
|
||||
const eAttrDomain selection_domain = ED_grease_pencil_selection_domain_get(C);
|
||||
|
||||
const ClosestGreasePencilDrawing closest = threading::parallel_reduce(
|
||||
drawings.index_range(),
|
||||
|
@ -3215,17 +3218,18 @@ static bool ed_grease_pencil_select_pick(bContext *C,
|
|||
selection.finish();
|
||||
|
||||
deselected = true;
|
||||
|
||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a
|
||||
* generic attribute for now. */
|
||||
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!closest.drawing) {
|
||||
if (deselected) {
|
||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a
|
||||
* generic attribute for now. */
|
||||
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
|
||||
}
|
||||
return deselected;
|
||||
}
|
||||
|
||||
|
@ -3237,10 +3241,8 @@ static bool ed_grease_pencil_select_pick(bContext *C,
|
|||
|
||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a
|
||||
* generic attribute for now. */
|
||||
if (!deselected) {
|
||||
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
|
||||
}
|
||||
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -4187,6 +4189,9 @@ static bool do_grease_pencil_box_select(ViewContext *vc, const rcti *rect, const
|
|||
const_cast<Object *>(vc->obedit));
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(vc->obedit->data);
|
||||
|
||||
/* Get selection domain from tool settings. */
|
||||
const eAttrDomain selection_domain = ED_grease_pencil_selection_domain_get(vc->C);
|
||||
|
||||
bool changed = false;
|
||||
grease_pencil.foreach_editable_drawing(
|
||||
scene->r.cfra, [&](int drawing_index, GreasePencilDrawing &drawing) {
|
||||
|
@ -4194,7 +4199,7 @@ static bool do_grease_pencil_box_select(ViewContext *vc, const rcti *rect, const
|
|||
bke::crazyspace::get_evaluated_grease_pencil_drawing_deformation(
|
||||
ob_eval, *vc->obedit, drawing_index);
|
||||
changed |= ed::curves::select_box(
|
||||
*vc, drawing.geometry.wrap(), deformation.positions, ATTR_DOMAIN_POINT, *rect, sel_op);
|
||||
*vc, drawing.geometry.wrap(), deformation.positions, selection_domain, *rect, sel_op);
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
|
|
|
@ -215,23 +215,12 @@ static eSnapMode iter_snap_objects(SnapObjectContext *sctx, IterSnapObjsCallback
|
|||
/* Store all ray-hits
|
||||
* Support for storing all depths, not just the first (ray-cast 'all'). */
|
||||
|
||||
static SnapObjectHitDepth *hit_depth_create(const float depth,
|
||||
const float co[3],
|
||||
const float no[3],
|
||||
int index,
|
||||
Object *ob_eval,
|
||||
const float obmat[4][4],
|
||||
uint ob_uuid)
|
||||
static SnapObjectHitDepth *hit_depth_create(const float depth, const float co[3], uint ob_uuid)
|
||||
{
|
||||
SnapObjectHitDepth *hit = MEM_new<SnapObjectHitDepth>(__func__);
|
||||
|
||||
hit->depth = depth;
|
||||
copy_v3_v3(hit->co, co);
|
||||
copy_v3_v3(hit->no, no);
|
||||
hit->index = index;
|
||||
|
||||
hit->ob_eval = ob_eval;
|
||||
copy_m4_m4(hit->obmat, (float(*)[4])obmat);
|
||||
hit->ob_uuid = ob_uuid;
|
||||
|
||||
return hit;
|
||||
|
@ -259,20 +248,14 @@ void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRay
|
|||
data->raycast_callback(data->bvhdata, index, ray, hit);
|
||||
if (hit->index != -1) {
|
||||
/* Get all values in world-space. */
|
||||
float location[3], normal[3];
|
||||
float location[3];
|
||||
float depth;
|
||||
|
||||
/* World-space location. */
|
||||
mul_v3_m4v3(location, (float(*)[4])data->obmat, hit->co);
|
||||
depth = (hit->dist + data->len_diff) / data->local_scale;
|
||||
|
||||
/* World-space normal. */
|
||||
copy_v3_v3(normal, hit->no);
|
||||
mul_m3_v3((float(*)[3])data->timat, normal);
|
||||
normalize_v3(normal);
|
||||
|
||||
SnapObjectHitDepth *hit_item = hit_depth_create(
|
||||
depth, location, normal, hit->index, data->ob_eval, data->obmat, data->ob_uuid);
|
||||
SnapObjectHitDepth *hit_item = hit_depth_create(depth, location, data->ob_uuid);
|
||||
BLI_addtail(data->hit_list, hit_item);
|
||||
}
|
||||
}
|
||||
|
@ -1732,7 +1715,7 @@ eSnapMode ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx,
|
|||
mval,
|
||||
init_co,
|
||||
prev_co,
|
||||
square_f(*dist_px),
|
||||
dist_px ? square_f(*dist_px) : FLT_MAX,
|
||||
nullptr,
|
||||
use_occlusion_test))
|
||||
{
|
||||
|
|
|
@ -10,44 +10,7 @@
|
|||
|
||||
#define MAX_CLIPPLANE_LEN 3
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Internal Data Types
|
||||
* \{ */
|
||||
|
||||
/** #SnapObjectContext.editmesh_caches */
|
||||
struct SnapData_EditMesh {
|
||||
/* Verts, Edges. */
|
||||
BVHTree *bvhtree[2];
|
||||
bool cached[2];
|
||||
|
||||
/* BVH tree from #BMEditMesh.looptris. */
|
||||
BVHTreeFromEditMesh treedata_editmesh;
|
||||
|
||||
blender::bke::MeshRuntime *mesh_runtime;
|
||||
float min[3], max[3];
|
||||
|
||||
void clear()
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(this->bvhtree); i++) {
|
||||
if (!this->cached[i]) {
|
||||
BLI_bvhtree_free(this->bvhtree[i]);
|
||||
}
|
||||
this->bvhtree[i] = nullptr;
|
||||
}
|
||||
free_bvhtree_from_editmesh(&this->treedata_editmesh);
|
||||
}
|
||||
|
||||
~SnapData_EditMesh()
|
||||
{
|
||||
this->clear();
|
||||
}
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
MEM_CXX_CLASS_ALLOC_FUNCS("SnapData_EditMesh")
|
||||
#endif
|
||||
};
|
||||
|
||||
/** \} */
|
||||
struct SnapData_EditMesh;
|
||||
|
||||
struct SnapObjectContext {
|
||||
struct Scene *scene;
|
||||
|
@ -123,17 +86,14 @@ struct RayCastAll_Data {
|
|||
BVHTree_RayCastCallback raycast_callback;
|
||||
|
||||
const float (*obmat)[4];
|
||||
const float (*timat)[3];
|
||||
|
||||
float len_diff;
|
||||
float local_scale;
|
||||
|
||||
Object *ob_eval;
|
||||
uint ob_uuid;
|
||||
|
||||
/* output data */
|
||||
ListBase *hit_list;
|
||||
bool retval;
|
||||
};
|
||||
|
||||
struct Nearest2dUserData;
|
||||
|
@ -222,6 +182,29 @@ bool nearest_world_tree(SnapObjectContext *sctx,
|
|||
|
||||
/* transform_snap_object_editmesh.cc */
|
||||
|
||||
struct SnapData_EditMesh {
|
||||
/* Verts, Edges. */
|
||||
BVHTree *bvhtree[2];
|
||||
bool cached[2];
|
||||
|
||||
/* BVH tree from #BMEditMesh.looptris. */
|
||||
BVHTreeFromEditMesh treedata_editmesh;
|
||||
|
||||
blender::bke::MeshRuntime *mesh_runtime;
|
||||
float min[3], max[3];
|
||||
|
||||
void clear();
|
||||
|
||||
~SnapData_EditMesh()
|
||||
{
|
||||
this->clear();
|
||||
}
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
MEM_CXX_CLASS_ALLOC_FUNCS("SnapData_EditMesh")
|
||||
#endif
|
||||
};
|
||||
|
||||
eSnapMode snap_object_editmesh(SnapObjectContext *sctx,
|
||||
Object *ob_eval,
|
||||
ID *id,
|
||||
|
|
|
@ -25,6 +25,17 @@
|
|||
/** \name Snap Object Data
|
||||
* \{ */
|
||||
|
||||
void SnapData_EditMesh::clear()
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(this->bvhtree); i++) {
|
||||
if (!this->cached[i]) {
|
||||
BLI_bvhtree_free(this->bvhtree[i]);
|
||||
}
|
||||
this->bvhtree[i] = nullptr;
|
||||
}
|
||||
free_bvhtree_from_editmesh(&this->treedata_editmesh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the minimum and maximum coordinates of the box that encompasses this mesh.
|
||||
*/
|
||||
|
@ -257,7 +268,6 @@ static void editmesh_looptri_raycast_backface_culling_cb(void *userdata,
|
|||
|
||||
static bool raycastEditMesh(SnapData_EditMesh *sod,
|
||||
SnapObjectContext *sctx,
|
||||
Object *ob_eval,
|
||||
BMEditMesh *em,
|
||||
const float obmat[4][4],
|
||||
const uint ob_index,
|
||||
|
@ -316,23 +326,18 @@ static bool raycastEditMesh(SnapData_EditMesh *sod,
|
|||
return retval;
|
||||
}
|
||||
|
||||
float timat[3][3]; /* transpose inverse matrix for normals */
|
||||
transpose_m3_m4(timat, imat);
|
||||
|
||||
if (r_hit_list) {
|
||||
RayCastAll_Data data;
|
||||
|
||||
data.bvhdata = treedata;
|
||||
data.raycast_callback = treedata->raycast_callback;
|
||||
data.obmat = obmat;
|
||||
data.timat = timat;
|
||||
data.len_diff = len_diff;
|
||||
data.local_scale = local_scale;
|
||||
data.ob_eval = ob_eval;
|
||||
data.ob_uuid = ob_index;
|
||||
data.hit_list = r_hit_list;
|
||||
data.retval = retval;
|
||||
|
||||
void *hit_last_prev = data.hit_list->last;
|
||||
BLI_bvhtree_ray_cast_all(treedata->tree,
|
||||
ray_start_local,
|
||||
ray_normal_local,
|
||||
|
@ -341,7 +346,7 @@ static bool raycastEditMesh(SnapData_EditMesh *sod,
|
|||
raycast_all_cb,
|
||||
&data);
|
||||
|
||||
retval = data.retval;
|
||||
retval = hit_last_prev != data.hit_list->last;
|
||||
}
|
||||
else {
|
||||
BVHTreeRayHit hit{};
|
||||
|
@ -369,7 +374,7 @@ static bool raycastEditMesh(SnapData_EditMesh *sod,
|
|||
|
||||
if (r_no) {
|
||||
copy_v3_v3(r_no, hit.no);
|
||||
mul_m3_v3(timat, r_no);
|
||||
mul_transposed_mat3_m4_v3(imat, r_no);
|
||||
normalize_v3(r_no);
|
||||
}
|
||||
|
||||
|
@ -759,7 +764,6 @@ eSnapMode snap_object_editmesh(SnapObjectContext *sctx,
|
|||
if (snap_mode_used & SCE_SNAP_MODE_FACE) {
|
||||
if (raycastEditMesh(sod,
|
||||
sctx,
|
||||
ob_eval,
|
||||
em,
|
||||
obmat,
|
||||
sctx->runtime.object_index++,
|
||||
|
|
|
@ -156,9 +156,6 @@ static bool raycastMesh(SnapObjectContext *sctx,
|
|||
return retval;
|
||||
}
|
||||
|
||||
float timat[3][3]; /* transpose inverse matrix for normals */
|
||||
transpose_m3_m4(timat, imat);
|
||||
|
||||
BLI_assert(treedata.raycast_callback != nullptr);
|
||||
if (r_hit_list) {
|
||||
RayCastAll_Data data;
|
||||
|
@ -166,18 +163,16 @@ static bool raycastMesh(SnapObjectContext *sctx,
|
|||
data.bvhdata = &treedata;
|
||||
data.raycast_callback = treedata.raycast_callback;
|
||||
data.obmat = obmat;
|
||||
data.timat = timat;
|
||||
data.len_diff = len_diff;
|
||||
data.local_scale = local_scale;
|
||||
data.ob_eval = ob_eval;
|
||||
data.ob_uuid = ob_index;
|
||||
data.hit_list = r_hit_list;
|
||||
data.retval = retval;
|
||||
|
||||
void *hit_last_prev = data.hit_list->last;
|
||||
BLI_bvhtree_ray_cast_all(
|
||||
treedata.tree, ray_start_local, ray_normal_local, 0.0f, *ray_depth, raycast_all_cb, &data);
|
||||
|
||||
retval = data.retval;
|
||||
retval = hit_last_prev != data.hit_list->last;
|
||||
}
|
||||
else {
|
||||
BVHTreeRayHit hit{};
|
||||
|
@ -205,7 +200,7 @@ static bool raycastMesh(SnapObjectContext *sctx,
|
|||
|
||||
if (r_no) {
|
||||
copy_v3_v3(r_no, hit.no);
|
||||
mul_m3_v3(timat, r_no);
|
||||
mul_transposed_mat3_m4_v3(imat, r_no);
|
||||
normalize_v3(r_no);
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,6 @@ set(SRC
|
|||
../include/ED_gizmo_utils.h
|
||||
../include/ED_gpencil_legacy.h
|
||||
../include/ED_grease_pencil.h
|
||||
../include/ED_grease_pencil_draw.h
|
||||
../include/ED_image.h
|
||||
../include/ED_info.h
|
||||
../include/ED_keyframes_draw.h
|
||||
|
|
|
@ -596,7 +596,7 @@ static void rna_MeshPolygon_use_smooth_set(PointerRNA *ptr, bool value)
|
|||
bool *sharp_faces = (bool *)CustomData_get_layer_named_for_write(
|
||||
&mesh->pdata, CD_PROP_BOOL, "sharp_face", mesh->totpoly);
|
||||
if (!sharp_faces) {
|
||||
if (!value) {
|
||||
if (value) {
|
||||
/* Skip adding layer if the value is the same as the default. */
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue