WIP: Snapping Redesign: Defaults | Navigation | Drawing | Removals #109062

Draft
Germano Cavalcante wants to merge 29 commits from mano-wii/blender:snap_defaults into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
31 changed files with 640 additions and 566 deletions
Showing only changes of commit beb28713ac - Show all commits

View File

@ -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

View File

@ -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);
}
}

View File

@ -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.

View File

@ -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) {

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;
};

View File

@ -8,6 +8,7 @@
#pragma once
#include "BKE_attribute.h"
#include "BLI_utildefines.h"
#include "DNA_scene_types.h"

View File

@ -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"

View File

@ -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();

View File

@ -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;
}

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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)) {

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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))
{

View File

@ -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,

View File

@ -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++,

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}