GPv3: Add "(De)select All" operator and keymap #108628

Merged
Falk David merged 4 commits from filedescriptor/blender:select-all-grease-pencil-v3 into main 2023-06-06 14:45:59 +02:00
9 changed files with 185 additions and 28 deletions
Showing only changes of commit 3fdc34b530 - Show all commits

View File

@ -4501,6 +4501,9 @@ def km_grease_pencil_edit(params):
{"items": items},
)
items.extend([
*_template_items_select_actions(params, "grease_pencil.select_all"),
])
return keymap

View File

@ -1987,36 +1987,43 @@ class VIEW3D_MT_select_edit_gpencil(Menu):
def draw(self, context):
layout = self.layout
filedescriptor marked this conversation as resolved Outdated

I would do:

def draw_legacy(self, context):
 (...)

def draw(self, context):
  if context.preferences.experimental.use_grease_pencil_version3:
    return self.draw_legacy(context)
I would do: ```Py def draw_legacy(self, context): (...) def draw(self, context): if context.preferences.experimental.use_grease_pencil_version3: return self.draw_legacy(context) ```
if context.preferences.experimental.use_grease_pencil_version3:
layout.operator("grease_pencil.select_all", text="All").action = 'SELECT'
layout.operator("grease_pencil.select_all", text="None").action = 'DESELECT'
layout.operator("grease_pencil.select_all", text="Invert").action = 'INVERT'
layout.operator("gpencil.select_all", text="All").action = 'SELECT'
layout.operator("gpencil.select_all", text="None").action = 'DESELECT'
layout.operator("gpencil.select_all", text="Invert").action = 'INVERT'
layout.separator()
else:
layout.operator("gpencil.select_all", text="All").action = 'SELECT'
layout.operator("gpencil.select_all", text="None").action = 'DESELECT'
layout.operator("gpencil.select_all", text="Invert").action = 'INVERT'
layout.separator()
layout.separator()
layout.operator("gpencil.select_box")
layout.operator("gpencil.select_circle")
layout.operator_menu_enum("gpencil.select_lasso", "mode")
layout.operator("gpencil.select_box")
layout.operator("gpencil.select_circle")
layout.operator_menu_enum("gpencil.select_lasso", "mode")
layout.separator()
layout.separator()
layout.operator("gpencil.select_linked", text="Linked")
layout.operator("gpencil.select_alternate")
layout.operator("gpencil.select_random")
layout.operator_menu_enum("gpencil.select_grouped", "type", text="Grouped")
layout.operator("gpencil.select_linked", text="Linked")
layout.operator("gpencil.select_alternate")
layout.operator("gpencil.select_random")
layout.operator_menu_enum("gpencil.select_grouped", "type", text="Grouped")
if context.mode == 'VERTEX_GPENCIL':
layout.operator("gpencil.select_vertex_color", text="Color Attribute")
if context.mode == 'VERTEX_GPENCIL':
layout.operator("gpencil.select_vertex_color", text="Color Attribute")
layout.separator()
layout.separator()
layout.operator("gpencil.select_first")
layout.operator("gpencil.select_last")
layout.operator("gpencil.select_first")
layout.operator("gpencil.select_last")
layout.separator()
layout.separator()
filedescriptor marked this conversation as resolved Outdated

This is an extra identation to the entire code, and more code that will need to change once we remove the experimental option. If instead you do a short return you isolate the legacy code a bit more:

if not context....version3:
  return self.draw_legacy(context)

Also, if you call self.draw_legacy, the self is already passed as argument. Is the patch as it is working? Because it feels like is calling draw_legacy with too many arguments (self, self, context).

This is an extra identation to the entire code, and more code that will need to change once we remove the experimental option. If instead you do a short return you isolate the legacy code a bit more: ``` if not context....version3: return self.draw_legacy(context) ``` Also, if you call self.draw_legacy, the self is already passed as argument. Is the patch as it is working? Because it feels like is calling draw_legacy with too many arguments (self, self, context).
layout.operator("gpencil.select_more")
layout.operator("gpencil.select_less")
layout.operator("gpencil.select_more")
layout.operator("gpencil.select_less")
class VIEW3D_MT_select_paint_mask(Menu):

View File

@ -1053,16 +1053,35 @@ void GreasePencil::remove_drawing(const int index_to_remove)
shrink_array<GreasePencilDrawingBase *>(&this->drawing_array, &this->drawing_array_num, 1);
}
void GreasePencil::foreach_visible_drawing(
int frame, blender::FunctionRef<void(GreasePencilDrawing &)> function)
enum ForeachDrawingMode {
VISIBLE,
EDITABLE,
};
static void foreach_drawing_ex(GreasePencil &grease_pencil,
int frame,
ForeachDrawingMode mode,
blender::FunctionRef<void(GreasePencilDrawing &)> function)
{
using namespace blender::bke::greasepencil;
blender::Span<GreasePencilDrawingBase *> drawings = this->drawings();
for (const Layer *layer : this->layers()) {
if (!layer->is_visible()) {
continue;
blender::Span<GreasePencilDrawingBase *> drawings = grease_pencil.drawings();
for (const Layer *layer : grease_pencil.layers()) {
switch (mode) {
case VISIBLE: {
if (!layer->is_visible()) {
continue;
}
break;
}
case EDITABLE: {
if (!layer->is_visible() || layer->is_locked()) {
continue;
}
break;
}
}
int index = layer->drawing_index_at(frame);
if (index == -1) {
continue;
@ -1078,6 +1097,18 @@ void GreasePencil::foreach_visible_drawing(
}
}
void GreasePencil::foreach_visible_drawing(
int frame, blender::FunctionRef<void(GreasePencilDrawing &)> function)
{
foreach_drawing_ex(*this, frame, VISIBLE, function);
}
void GreasePencil::foreach_editable_drawing(
int frame, blender::FunctionRef<void(GreasePencilDrawing &)> function)
{
foreach_drawing_ex(*this, frame, EDITABLE, function);
}
bool GreasePencil::bounds_min_max(float3 &min, float3 &max) const
{
bool found = false;

View File

@ -326,8 +326,9 @@ static void grease_pencil_geom_batch_ensure(GreasePencil &grease_pencil, int cfr
"radius", ATTR_DOMAIN_POINT, 1.0f);
const VArray<float> opacities = *attributes.lookup_or_default<float>(
"opacity", ATTR_DOMAIN_POINT, 1.0f);
/* Assumes that if the ".selection" attribute does not exist, all points are selected. */
const VArray<float> selection_float = *attributes.lookup_or_default<float>(
".selection", ATTR_DOMAIN_POINT, false);
".selection", ATTR_DOMAIN_POINT, true);
const VArray<int8_t> start_caps = *attributes.lookup_or_default<int8_t>(
"start_cap", ATTR_DOMAIN_CURVE, 0);
const VArray<int8_t> end_caps = *attributes.lookup_or_default<int8_t>(

View File

@ -21,6 +21,7 @@ set(INC_SYS
set(SRC
intern/grease_pencil_add.cc
intern/grease_pencil_ops.cc
)
set(LIB

View File

@ -0,0 +1,96 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2023 Blender Foundation. */
/** \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 "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](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 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);
}
void ED_keymap_grease_pencil(wmKeyConfig *keyconf)
{
using namespace blender::ed::greasepencil;
keymap_grease_pencil_editing(keyconf);
}

View File

@ -7,13 +7,24 @@
#pragma once
struct bContext;
struct Main;
struct Object;
struct wmKeyConfig;
#ifdef __cplusplus
extern "C" {
#endif
/* -------------------------------------------------------------------- */
/** \name C Wrappers
* \{ */
void ED_operatortypes_grease_pencil(void);
void ED_keymap_grease_pencil(struct wmKeyConfig *keyconf);
#ifdef __cplusplus
}
#endif
@ -22,6 +33,8 @@ extern "C" {
namespace blender::ed::greasepencil {
bool editable_grease_pencil_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);
void create_suzanne(Main &bmain, Object &object, float4x4 matrix, const int frame_number);

View File

@ -35,6 +35,7 @@
#include "ED_geometry.h"
#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"
@ -93,8 +94,9 @@ void ED_spacetypes_init(void)
ED_operatortypes_anim();
ED_operatortypes_animchannels();
ED_operatortypes_asset();
ED_operatortypes_grease_pencil_draw();
ED_operatortypes_gpencil_legacy();
ED_operatortypes_grease_pencil_draw();
ED_operatortypes_grease_pencil();
ED_operatortypes_object();
ED_operatortypes_lattice();
ED_operatortypes_mesh();
@ -184,6 +186,7 @@ void ED_spacetypes_keymap(wmKeyConfig *keyconf)
ED_keymap_anim(keyconf);
ED_keymap_animchannels(keyconf);
ED_keymap_gpencil_legacy(keyconf);
ED_keymap_grease_pencil(keyconf);
ED_keymap_object(keyconf);
ED_keymap_lattice(keyconf);
ED_keymap_mesh(keyconf);

View File

@ -454,6 +454,8 @@ typedef struct GreasePencil {
void foreach_visible_drawing(int frame,
blender::FunctionRef<void(GreasePencilDrawing &)> function);
void foreach_editable_drawing(int frame,
blender::FunctionRef<void(GreasePencilDrawing &)> function);
bool bounds_min_max(blender::float3 &min, blender::float3 &max) const;