GPv3: Initial Layer Tree UI #109197
|
@ -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.
|
||||
|
|
|
@ -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,8 +23,10 @@ set(INC_SYS
|
|||
|
||||
set(SRC
|
||||
intern/grease_pencil_add.cc
|
||||
intern/grease_pencil_edit.cc
|
||||
intern/grease_pencil_layers.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,312 +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 "ED_view3d.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;
|
||||
}
|
||||
|
||||
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 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);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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(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,6 +26,8 @@ extern "C" {
|
|||
* \{ */
|
||||
|
||||
void ED_operatortypes_grease_pencil(void);
|
||||
void ED_operatortypes_grease_pencil_draw(void);
|
||||
void ED_operatortypes_grease_pencil_select(void);
|
||||
void ED_operatortypes_grease_pencil_layers(void);
|
||||
void ED_keymap_grease_pencil(struct wmKeyConfig *keyconf);
|
||||
/**
|
||||
|
|
|
@ -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
|
|
@ -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_grease_pencil_layers();
|
||||
ED_operatortypes_object();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue