2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2009-04-20 10:20:18 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2009-04-20 10:20:18 +00:00
|
|
|
*
|
2019-02-01 17:20:05 +01:00
|
|
|
* The Original Code is Copyright (C) 2008, Blender Foundation
|
2009-04-20 10:20:18 +00:00
|
|
|
* This is a new part of Blender
|
2015-04-02 16:29:33 +13:00
|
|
|
* Operators for editing Grease Pencil strokes
|
2009-04-20 10:20:18 +00:00
|
|
|
*/
|
2011-02-27 20:29:51 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
* \ingroup edgpencil
|
2019-02-06 15:52:04 +11:00
|
|
|
*/
|
2014-12-26 20:00:52 +01:00
|
|
|
|
2020-03-19 09:33:03 +01:00
|
|
|
#include <math.h>
|
|
|
|
#include <stddef.h>
|
2009-04-20 10:20:18 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2020-03-19 09:33:03 +01:00
|
|
|
#include <string.h>
|
2009-04-20 10:20:18 +00:00
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#include "BLI_blenlib.h"
|
2017-06-07 19:07:21 +12:00
|
|
|
#include "BLI_ghash.h"
|
2019-01-11 19:15:23 +01:00
|
|
|
#include "BLI_lasso_2d.h"
|
2017-06-07 19:07:21 +12:00
|
|
|
#include "BLI_math.h"
|
|
|
|
#include "BLI_string.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2009-04-20 10:20:18 +00:00
|
|
|
|
2015-08-16 17:32:01 +10:00
|
|
|
#include "BLT_translation.h"
|
2013-03-26 14:33:53 +00:00
|
|
|
|
2020-09-03 14:59:34 +02:00
|
|
|
#include "DNA_gpencil_modifier_types.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_gpencil_types.h"
|
2020-12-15 10:47:58 +11:00
|
|
|
#include "DNA_material_types.h"
|
2018-07-31 10:22:19 +02:00
|
|
|
#include "DNA_meshdata_types.h"
|
2015-12-13 21:03:13 +13:00
|
|
|
#include "DNA_object_types.h"
|
2009-04-20 10:20:18 +00:00
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
#include "DNA_screen_types.h"
|
|
|
|
#include "DNA_space_types.h"
|
|
|
|
#include "DNA_view3d_types.h"
|
|
|
|
|
2018-11-07 18:00:24 +01:00
|
|
|
#include "BKE_brush.h"
|
2009-04-20 10:20:18 +00:00
|
|
|
#include "BKE_context.h"
|
2018-07-31 10:22:19 +02:00
|
|
|
#include "BKE_global.h"
|
2009-04-20 10:20:18 +00:00
|
|
|
#include "BKE_gpencil.h"
|
2020-11-13 21:43:00 +01:00
|
|
|
#include "BKE_gpencil_curve.h"
|
2020-03-19 11:35:17 +01:00
|
|
|
#include "BKE_gpencil_geom.h"
|
2020-09-03 14:59:34 +02:00
|
|
|
#include "BKE_layer.h"
|
2020-02-10 12:58:59 +01:00
|
|
|
#include "BKE_lib_id.h"
|
2020-09-03 14:59:34 +02:00
|
|
|
#include "BKE_library.h"
|
2018-11-07 18:00:24 +01:00
|
|
|
#include "BKE_main.h"
|
2018-07-31 10:22:19 +02:00
|
|
|
#include "BKE_material.h"
|
|
|
|
#include "BKE_object.h"
|
2018-11-07 18:00:24 +01:00
|
|
|
#include "BKE_paint.h"
|
2009-08-29 06:50:32 +00:00
|
|
|
#include "BKE_report.h"
|
2019-08-19 21:01:18 +02:00
|
|
|
#include "BKE_scene.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_workspace.h"
|
2009-04-20 10:20:18 +00:00
|
|
|
|
"Dynamic Sketch" patch, which adds timing data to GP strokes, by storing an inittime in each stroke (value returned by PIL_check_seconds_timer() func), and then a delta time for each of its points, relative to that inittime.
These timing data can then be used during conversion to Curve objects, to create a path animation (i.e. an Evaluation Time F-Curve) exactly reproducing the drawing movements.
Aside from this "main feature", the patch brings several fixes/enhancements:
* Stroke smoothing/simplifying will no more move the start/end points of a stroke (this was rather annoying sometimes!).
* Also optimized smoothing code (even though not really noticeable on a modern computer, it now uses less memory and runs faster).
* When converting to curve, you now have the following new possibilities:
** Normalize the weight values (currently, they will get "stroke width * 0.1", i.e. would range by default from 0.0 to 0.3...).
** Scale the radius values to your liking (again, currently they are set from stroke width times 0.1)!
** Link all strokes into a single curve, using zero-radius sections (this is mandatory to use the dynamic feature!).
Here is a small demo video: http://youtu.be/VwWEXrnQAFI
Will update user manual later today.
2012-11-11 14:48:58 +00:00
|
|
|
#include "UI_interface.h"
|
2015-12-13 21:03:13 +13:00
|
|
|
#include "UI_resources.h"
|
2009-04-20 10:20:18 +00:00
|
|
|
|
|
|
|
#include "WM_api.h"
|
2018-09-07 13:35:47 +10:00
|
|
|
#include "WM_message.h"
|
|
|
|
#include "WM_toolsystem.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "WM_types.h"
|
2009-04-20 10:20:18 +00:00
|
|
|
|
2009-08-28 12:41:45 +00:00
|
|
|
#include "RNA_access.h"
|
2009-08-31 01:58:11 +00:00
|
|
|
#include "RNA_define.h"
|
2015-12-13 21:03:13 +13:00
|
|
|
#include "RNA_enum_types.h"
|
2009-08-28 12:41:45 +00:00
|
|
|
|
2009-04-20 10:20:18 +00:00
|
|
|
#include "UI_view2d.h"
|
|
|
|
|
2020-09-03 14:59:34 +02:00
|
|
|
#include "ED_armature.h"
|
2011-02-14 17:55:27 +00:00
|
|
|
#include "ED_gpencil.h"
|
2015-12-13 21:03:13 +13:00
|
|
|
#include "ED_object.h"
|
2020-05-01 20:06:38 -06:00
|
|
|
#include "ED_outliner.h"
|
2016-08-29 03:03:09 +12:00
|
|
|
#include "ED_screen.h"
|
2019-01-11 19:15:23 +01:00
|
|
|
#include "ED_select_utils.h"
|
2016-09-07 09:54:50 +02:00
|
|
|
#include "ED_space_api.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "ED_transform_snap_object_context.h"
|
|
|
|
#include "ED_view3d.h"
|
2009-04-20 10:20:18 +00:00
|
|
|
|
2017-08-16 12:45:11 +10:00
|
|
|
#include "DEG_depsgraph.h"
|
2018-07-31 10:22:19 +02:00
|
|
|
#include "DEG_depsgraph_build.h"
|
|
|
|
#include "DEG_depsgraph_query.h"
|
2017-08-16 12:45:11 +10:00
|
|
|
|
2009-04-20 10:20:18 +00:00
|
|
|
#include "gpencil_intern.h"
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Stroke Edit Mode Management
|
|
|
|
* \{ */
|
2018-09-20 11:56:41 +02:00
|
|
|
|
|
|
|
/* poll callback for all stroke editing operators */
|
2020-06-29 15:28:38 +02:00
|
|
|
static bool gpencil_stroke_edit_poll(bContext *C)
|
2018-09-20 11:56:41 +02:00
|
|
|
{
|
|
|
|
/* edit only supported with grease pencil objects */
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
|
|
|
|
return false;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-09-20 11:56:41 +02:00
|
|
|
/* NOTE: this is a bit slower, but is the most accurate... */
|
|
|
|
return CTX_DATA_COUNT(C, editable_gpencil_strokes) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* poll callback to verify edit mode in 3D view only */
|
2020-06-29 15:28:38 +02:00
|
|
|
static bool gpencil_strokes_edit3d_poll(bContext *C)
|
2018-09-20 11:56:41 +02:00
|
|
|
{
|
|
|
|
/* edit only supported with grease pencil objects */
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
|
|
|
|
return false;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-09-20 11:56:41 +02:00
|
|
|
/* 2 Requirements:
|
|
|
|
* - 1) Editable GP data
|
|
|
|
* - 2) 3D View only
|
|
|
|
*/
|
2020-06-29 15:28:38 +02:00
|
|
|
return (gpencil_stroke_edit_poll(C) && ED_operator_view3d_active(C));
|
2018-09-20 11:56:41 +02:00
|
|
|
}
|
|
|
|
|
2018-07-02 11:47:00 +02:00
|
|
|
static bool gpencil_editmode_toggle_poll(bContext *C)
|
2015-12-13 21:03:13 +13:00
|
|
|
{
|
2018-09-04 17:16:14 +02:00
|
|
|
/* edit only supported with grease pencil objects */
|
2018-07-31 10:22:19 +02:00
|
|
|
Object *ob = CTX_data_active_object(C);
|
2018-09-04 17:16:14 +02:00
|
|
|
if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
|
|
|
|
return false;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-09-04 17:16:14 +02:00
|
|
|
/* if using gpencil object, use this gpd */
|
|
|
|
if (ob->type == OB_GPENCIL) {
|
2018-07-31 10:22:19 +02:00
|
|
|
return ob->data != NULL;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
return ED_gpencil_data_get_active(C) != NULL;
|
|
|
|
}
|
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
static bool gpencil_stroke_not_in_curve_edit_mode(bContext *C)
|
|
|
|
{
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
bGPdata *gpd = (bGPdata *)ob->data;
|
|
|
|
bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
|
|
|
|
|
|
|
|
return (gpl != NULL && !GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd));
|
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Toggle Edit Mode Operator
|
|
|
|
* \{ */
|
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
static int gpencil_editmode_toggle_exec(bContext *C, wmOperator *op)
|
2015-12-13 21:03:13 +13:00
|
|
|
{
|
2018-07-31 10:22:19 +02:00
|
|
|
const int back = RNA_boolean_get(op->ptr, "back");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-09-07 13:35:47 +10:00
|
|
|
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
2018-07-31 10:22:19 +02:00
|
|
|
bool is_object = false;
|
|
|
|
short mode;
|
|
|
|
/* if using a gpencil object, use this datablock */
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
if ((ob) && (ob->type == OB_GPENCIL)) {
|
|
|
|
gpd = ob->data;
|
|
|
|
is_object = true;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
if (gpd == NULL) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "No active GP data");
|
2015-12-13 21:03:13 +13:00
|
|
|
return OPERATOR_CANCELLED;
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* Just toggle editmode flag... */
|
|
|
|
gpd->flag ^= GP_DATA_STROKE_EDITMODE;
|
2016-11-19 22:41:37 +01:00
|
|
|
/* recalculate parent matrix */
|
|
|
|
if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
|
2019-07-25 16:36:22 +02:00
|
|
|
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
2018-07-31 10:22:19 +02:00
|
|
|
ED_gpencil_reset_layers_parent(depsgraph, ob, gpd);
|
|
|
|
}
|
|
|
|
/* set mode */
|
|
|
|
if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
|
2018-12-14 16:45:57 +01:00
|
|
|
mode = OB_MODE_EDIT_GPENCIL;
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
mode = OB_MODE_OBJECT;
|
2016-11-19 22:41:37 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
if (is_object) {
|
|
|
|
/* try to back previous mode */
|
|
|
|
if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_EDITMODE) == 0) && (back == 1)) {
|
|
|
|
mode = ob->restore_mode;
|
|
|
|
}
|
|
|
|
ob->restore_mode = ob->mode;
|
|
|
|
ob->mode = mode;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* Recalculate editcurves for strokes where the geometry/vertex colors have changed */
|
|
|
|
if (GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)) {
|
|
|
|
GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc)
|
|
|
|
{
|
|
|
|
if (gpc->flag & GP_CURVE_NEEDS_STROKE_UPDATE) {
|
|
|
|
BKE_gpencil_stroke_editcurve_update(gpd, gpl, gps);
|
|
|
|
/* Update the selection from the stroke to the curve. */
|
2021-02-19 17:18:12 +01:00
|
|
|
BKE_gpencil_editcurve_stroke_sync_selection(gpd, gps, gps->editcurve);
|
2020-11-13 21:43:00 +01:00
|
|
|
|
|
|
|
gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
|
|
|
|
BKE_gpencil_stroke_geometry_update(gpd, gps);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
GP_EDITABLE_CURVES_END(gps_iter);
|
|
|
|
}
|
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* setup other modes */
|
|
|
|
ED_gpencil_setup_modes(C, gpd, mode);
|
|
|
|
/* set cache as dirty */
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-01-25 10:10:21 -02:00
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_GPENCIL_EDITMODE, NULL);
|
2015-12-13 21:03:13 +13:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-09-07 13:35:47 +10:00
|
|
|
if (is_object) {
|
|
|
|
WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
|
|
|
|
}
|
|
|
|
if (G.background == false) {
|
|
|
|
WM_toolsystem_update_from_context_view3d(C);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_editmode_toggle(wmOperatorType *ot)
|
|
|
|
{
|
2018-07-31 10:22:19 +02:00
|
|
|
PropertyRNA *prop;
|
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Strokes Edit Mode Toggle";
|
|
|
|
ot->idname = "GPENCIL_OT_editmode_toggle";
|
|
|
|
ot->description = "Enter/Exit edit mode for Grease Pencil strokes";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* callbacks */
|
|
|
|
ot->exec = gpencil_editmode_toggle_exec;
|
|
|
|
ot->poll = gpencil_editmode_toggle_poll;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
|
2018-07-31 10:22:19 +02:00
|
|
|
|
|
|
|
/* properties */
|
|
|
|
prop = RNA_def_boolean(
|
|
|
|
ot->srna, "back", 0, "Return to Previous Mode", "Return to previous mode");
|
|
|
|
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Toggle Select Mode Operator
|
|
|
|
* \{ */
|
|
|
|
|
2018-09-20 11:56:41 +02:00
|
|
|
/* set select mode */
|
2019-08-17 16:18:09 +02:00
|
|
|
static bool gpencil_selectmode_toggle_poll(bContext *C)
|
|
|
|
{
|
|
|
|
/* edit only supported with grease pencil objects */
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
if ((ob == NULL) || (ob->type != OB_GPENCIL) || (ob->mode != OB_MODE_EDIT_GPENCIL)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ED_operator_view3d_active(C);
|
|
|
|
}
|
|
|
|
|
2018-09-20 11:56:41 +02:00
|
|
|
static int gpencil_selectmode_toggle_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
ToolSettings *ts = CTX_data_tool_settings(C);
|
2019-09-17 13:07:29 +02:00
|
|
|
Object *ob = CTX_data_active_object(C);
|
2018-09-20 11:56:41 +02:00
|
|
|
const int mode = RNA_int_get(op->ptr, "mode");
|
2019-09-17 13:07:29 +02:00
|
|
|
bool changed = false;
|
|
|
|
|
|
|
|
if (ts->gpencil_selectmode_edit == mode) {
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
2018-09-20 11:56:41 +02:00
|
|
|
|
|
|
|
/* Just set mode */
|
2019-08-17 16:18:09 +02:00
|
|
|
ts->gpencil_selectmode_edit = mode;
|
2018-09-20 11:56:41 +02:00
|
|
|
|
2019-09-17 13:07:29 +02:00
|
|
|
/* If the mode is Stroke, extend selection. */
|
2019-09-23 12:55:16 +02:00
|
|
|
if ((ob) && (ts->gpencil_selectmode_edit == GP_SELECTMODE_STROKE)) {
|
2019-09-17 13:07:29 +02:00
|
|
|
bGPdata *gpd = (bGPdata *)ob->data;
|
|
|
|
/* Extend selection to all points in all selected strokes. */
|
|
|
|
CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
|
|
|
|
if ((gps->flag & GP_STROKE_SELECT) && (gps->totpoints > 1)) {
|
|
|
|
changed = true;
|
|
|
|
bGPDspoint *pt;
|
|
|
|
for (int i = 0; i < gps->totpoints; i++) {
|
|
|
|
pt = &gps->points[i];
|
|
|
|
pt->flag |= GP_SPOINT_SELECT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
|
|
|
if (changed) {
|
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
|
2018-09-20 11:56:41 +02:00
|
|
|
WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
|
2018-09-20 11:56:41 +02:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_selectmode_toggle(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Select Mode Toggle";
|
|
|
|
ot->idname = "GPENCIL_OT_selectmode_toggle";
|
|
|
|
ot->description = "Set selection mode for Grease Pencil strokes";
|
|
|
|
|
|
|
|
/* callbacks */
|
|
|
|
ot->exec = gpencil_selectmode_toggle_exec;
|
2019-08-17 16:18:09 +02:00
|
|
|
ot->poll = gpencil_selectmode_toggle_poll;
|
2018-09-20 11:56:41 +02:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
|
|
|
|
|
|
|
|
/* properties */
|
2020-12-24 11:07:32 -06:00
|
|
|
prop = RNA_def_int(ot->srna, "mode", 0, 0, 2, "Select Mode", "Select mode", 0, 2);
|
2018-09-20 11:56:41 +02:00
|
|
|
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Toggle Stroke Paint Mode Operator
|
|
|
|
* \{ */
|
2018-07-31 10:22:19 +02:00
|
|
|
|
|
|
|
static bool gpencil_paintmode_toggle_poll(bContext *C)
|
|
|
|
{
|
|
|
|
/* if using gpencil object, use this gpd */
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
if ((ob) && (ob->type == OB_GPENCIL)) {
|
|
|
|
return ob->data != NULL;
|
|
|
|
}
|
|
|
|
return ED_gpencil_data_get_active(C) != NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int gpencil_paintmode_toggle_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
const bool back = RNA_boolean_get(op->ptr, "back");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-09-07 13:35:47 +10:00
|
|
|
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
|
2018-11-03 16:52:06 +11:00
|
|
|
Main *bmain = CTX_data_main(C);
|
2018-07-31 10:22:19 +02:00
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
|
|
|
ToolSettings *ts = CTX_data_tool_settings(C);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
bool is_object = false;
|
|
|
|
short mode;
|
|
|
|
/* if using a gpencil object, use this datablock */
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
if ((ob) && (ob->type == OB_GPENCIL)) {
|
|
|
|
gpd = ob->data;
|
|
|
|
is_object = true;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:19:45 +10:00
|
|
|
if (gpd == NULL) {
|
2018-07-31 10:22:19 +02:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* Just toggle paintmode flag... */
|
|
|
|
gpd->flag ^= GP_DATA_STROKE_PAINTMODE;
|
|
|
|
/* set mode */
|
|
|
|
if (gpd->flag & GP_DATA_STROKE_PAINTMODE) {
|
2018-12-14 16:45:57 +01:00
|
|
|
mode = OB_MODE_PAINT_GPENCIL;
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
mode = OB_MODE_OBJECT;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
if (is_object) {
|
|
|
|
/* try to back previous mode */
|
|
|
|
if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0) && (back == 1)) {
|
|
|
|
mode = ob->restore_mode;
|
|
|
|
}
|
|
|
|
ob->restore_mode = ob->mode;
|
|
|
|
ob->mode = mode;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-12-14 16:45:57 +01:00
|
|
|
if (mode == OB_MODE_PAINT_GPENCIL) {
|
2020-05-24 10:22:03 +02:00
|
|
|
/* Be sure we have brushes and Paint settings.
|
2020-05-30 17:31:54 +02:00
|
|
|
* Need Draw and Vertex (used for Tint). */
|
2018-11-05 15:31:25 +11:00
|
|
|
BKE_paint_ensure(ts, (Paint **)&ts->gp_paint);
|
2020-05-24 10:22:03 +02:00
|
|
|
BKE_paint_ensure(ts, (Paint **)&ts->gp_vertexpaint);
|
|
|
|
|
|
|
|
BKE_brush_gpencil_paint_presets(bmain, ts, false);
|
|
|
|
|
|
|
|
/* Ensure Palette by default. */
|
|
|
|
BKE_gpencil_palette_ensure(bmain, CTX_data_scene(C));
|
|
|
|
|
2018-11-05 15:31:25 +11:00
|
|
|
Paint *paint = &ts->gp_paint->paint;
|
2018-11-03 16:52:06 +11:00
|
|
|
/* if not exist, create a new one */
|
2019-05-06 20:34:24 +02:00
|
|
|
if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
|
2020-05-15 16:43:50 +02:00
|
|
|
BKE_brush_gpencil_paint_presets(bmain, ts, true);
|
2018-11-03 16:52:06 +11:00
|
|
|
}
|
2018-11-05 16:18:43 +11:00
|
|
|
BKE_paint_toolslots_brush_validate(bmain, &ts->gp_paint->paint);
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* setup other modes */
|
|
|
|
ED_gpencil_setup_modes(C, gpd, mode);
|
|
|
|
/* set cache as dirty */
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, NULL);
|
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-09-07 13:35:47 +10:00
|
|
|
if (is_object) {
|
|
|
|
WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
|
|
|
|
}
|
|
|
|
if (G.background == false) {
|
|
|
|
WM_toolsystem_update_from_context_view3d(C);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_paintmode_toggle(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Strokes Paint Mode Toggle";
|
|
|
|
ot->idname = "GPENCIL_OT_paintmode_toggle";
|
|
|
|
ot->description = "Enter/Exit paint mode for Grease Pencil strokes";
|
|
|
|
|
|
|
|
/* callbacks */
|
|
|
|
ot->exec = gpencil_paintmode_toggle_exec;
|
|
|
|
ot->poll = gpencil_paintmode_toggle_poll;
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
|
|
|
|
|
|
|
|
/* properties */
|
|
|
|
prop = RNA_def_boolean(
|
|
|
|
ot->srna, "back", 0, "Return to Previous Mode", "Return to previous mode");
|
|
|
|
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Toggle Stroke Sculpt Mode Operator
|
|
|
|
* \{ */
|
2018-07-31 10:22:19 +02:00
|
|
|
|
|
|
|
static bool gpencil_sculptmode_toggle_poll(bContext *C)
|
|
|
|
{
|
|
|
|
/* if using gpencil object, use this gpd */
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
if ((ob) && (ob->type == OB_GPENCIL)) {
|
|
|
|
return ob->data != NULL;
|
|
|
|
}
|
|
|
|
return ED_gpencil_data_get_active(C) != NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int gpencil_sculptmode_toggle_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2020-03-09 16:27:24 +01:00
|
|
|
Main *bmain = CTX_data_main(C);
|
|
|
|
ToolSettings *ts = CTX_data_tool_settings(C);
|
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
const bool back = RNA_boolean_get(op->ptr, "back");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-09-07 13:35:47 +10:00
|
|
|
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
|
2018-07-31 10:22:19 +02:00
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
|
|
|
bool is_object = false;
|
|
|
|
short mode;
|
|
|
|
/* if using a gpencil object, use this datablock */
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
if ((ob) && (ob->type == OB_GPENCIL)) {
|
|
|
|
gpd = ob->data;
|
|
|
|
is_object = true;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:19:45 +10:00
|
|
|
if (gpd == NULL) {
|
2018-07-31 10:22:19 +02:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* Just toggle sculptmode flag... */
|
|
|
|
gpd->flag ^= GP_DATA_STROKE_SCULPTMODE;
|
|
|
|
/* set mode */
|
|
|
|
if (gpd->flag & GP_DATA_STROKE_SCULPTMODE) {
|
2018-12-14 16:45:57 +01:00
|
|
|
mode = OB_MODE_SCULPT_GPENCIL;
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
mode = OB_MODE_OBJECT;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
if (is_object) {
|
|
|
|
/* try to back previous mode */
|
|
|
|
if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_SCULPTMODE) == 0) && (back == 1)) {
|
|
|
|
mode = ob->restore_mode;
|
|
|
|
}
|
|
|
|
ob->restore_mode = ob->mode;
|
|
|
|
ob->mode = mode;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
if (mode == OB_MODE_SCULPT_GPENCIL) {
|
2020-05-30 17:31:54 +02:00
|
|
|
/* Be sure we have brushes. */
|
2020-03-09 16:27:24 +01:00
|
|
|
BKE_paint_ensure(ts, (Paint **)&ts->gp_sculptpaint);
|
2020-05-24 10:22:03 +02:00
|
|
|
|
2020-05-30 17:31:54 +02:00
|
|
|
const bool reset_mode = (ts->gp_sculptpaint->paint.brush == NULL);
|
|
|
|
BKE_brush_gpencil_sculpt_presets(bmain, ts, reset_mode);
|
|
|
|
|
|
|
|
BKE_paint_toolslots_brush_validate(bmain, &ts->gp_sculptpaint->paint);
|
2020-03-09 16:27:24 +01:00
|
|
|
}
|
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* setup other modes */
|
|
|
|
ED_gpencil_setup_modes(C, gpd, mode);
|
|
|
|
/* set cache as dirty */
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, NULL);
|
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-09-07 13:35:47 +10:00
|
|
|
if (is_object) {
|
|
|
|
WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
|
|
|
|
}
|
|
|
|
if (G.background == false) {
|
|
|
|
WM_toolsystem_update_from_context_view3d(C);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Toggle Weight Paint Mode Operator
|
|
|
|
* \{ */
|
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
void GPENCIL_OT_sculptmode_toggle(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Strokes Sculpt Mode Toggle";
|
|
|
|
ot->idname = "GPENCIL_OT_sculptmode_toggle";
|
|
|
|
ot->description = "Enter/Exit sculpt mode for Grease Pencil strokes";
|
|
|
|
|
|
|
|
/* callbacks */
|
|
|
|
ot->exec = gpencil_sculptmode_toggle_exec;
|
|
|
|
ot->poll = gpencil_sculptmode_toggle_poll;
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
|
|
|
|
|
|
|
|
/* properties */
|
|
|
|
prop = RNA_def_boolean(
|
|
|
|
ot->srna, "back", 0, "Return to Previous Mode", "Return to previous mode");
|
|
|
|
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Stroke Weight Paint Mode Management */
|
|
|
|
|
|
|
|
static bool gpencil_weightmode_toggle_poll(bContext *C)
|
|
|
|
{
|
|
|
|
/* if using gpencil object, use this gpd */
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
if ((ob) && (ob->type == OB_GPENCIL)) {
|
|
|
|
return ob->data != NULL;
|
|
|
|
}
|
|
|
|
return ED_gpencil_data_get_active(C) != NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int gpencil_weightmode_toggle_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2020-03-09 16:27:24 +01:00
|
|
|
Main *bmain = CTX_data_main(C);
|
|
|
|
ToolSettings *ts = CTX_data_tool_settings(C);
|
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
const bool back = RNA_boolean_get(op->ptr, "back");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-09-07 13:35:47 +10:00
|
|
|
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
|
2018-07-31 10:22:19 +02:00
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
|
|
|
bool is_object = false;
|
|
|
|
short mode;
|
|
|
|
/* if using a gpencil object, use this datablock */
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
if ((ob) && (ob->type == OB_GPENCIL)) {
|
|
|
|
gpd = ob->data;
|
|
|
|
is_object = true;
|
|
|
|
}
|
2020-09-03 14:59:34 +02:00
|
|
|
const int mode_flag = OB_MODE_WEIGHT_GPENCIL;
|
|
|
|
const bool is_mode_set = (ob->mode & mode_flag) != 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:19:45 +10:00
|
|
|
if (gpd == NULL) {
|
2018-07-31 10:22:19 +02:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* Just toggle weightmode flag... */
|
|
|
|
gpd->flag ^= GP_DATA_STROKE_WEIGHTMODE;
|
|
|
|
/* set mode */
|
|
|
|
if (gpd->flag & GP_DATA_STROKE_WEIGHTMODE) {
|
2018-12-14 16:45:57 +01:00
|
|
|
mode = OB_MODE_WEIGHT_GPENCIL;
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
mode = OB_MODE_OBJECT;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
if (is_object) {
|
|
|
|
/* try to back previous mode */
|
|
|
|
if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && (back == 1)) {
|
|
|
|
mode = ob->restore_mode;
|
|
|
|
}
|
|
|
|
ob->restore_mode = ob->mode;
|
|
|
|
ob->mode = mode;
|
2020-09-03 14:59:34 +02:00
|
|
|
|
|
|
|
/* Prepare armature posemode. */
|
|
|
|
ED_object_posemode_set_for_weight_paint(C, bmain, ob, is_mode_set);
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
if (mode == OB_MODE_WEIGHT_GPENCIL) {
|
2020-05-30 17:31:54 +02:00
|
|
|
/* Be sure we have brushes. */
|
2020-03-09 16:27:24 +01:00
|
|
|
BKE_paint_ensure(ts, (Paint **)&ts->gp_weightpaint);
|
2020-05-24 10:22:03 +02:00
|
|
|
|
2020-05-30 17:31:54 +02:00
|
|
|
const bool reset_mode = (ts->gp_weightpaint->paint.brush == NULL);
|
|
|
|
BKE_brush_gpencil_weight_presets(bmain, ts, reset_mode);
|
|
|
|
|
|
|
|
BKE_paint_toolslots_brush_validate(bmain, &ts->gp_weightpaint->paint);
|
2020-03-09 16:27:24 +01:00
|
|
|
}
|
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* setup other modes */
|
|
|
|
ED_gpencil_setup_modes(C, gpd, mode);
|
|
|
|
/* set cache as dirty */
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, NULL);
|
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-09-07 13:35:47 +10:00
|
|
|
if (is_object) {
|
|
|
|
WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
|
|
|
|
}
|
|
|
|
if (G.background == false) {
|
|
|
|
WM_toolsystem_update_from_context_view3d(C);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_weightmode_toggle(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Strokes Weight Mode Toggle";
|
|
|
|
ot->idname = "GPENCIL_OT_weightmode_toggle";
|
|
|
|
ot->description = "Enter/Exit weight paint mode for Grease Pencil strokes";
|
|
|
|
|
|
|
|
/* callbacks */
|
|
|
|
ot->exec = gpencil_weightmode_toggle_exec;
|
|
|
|
ot->poll = gpencil_weightmode_toggle_poll;
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
|
|
|
|
|
|
|
|
/* properties */
|
|
|
|
prop = RNA_def_boolean(
|
|
|
|
ot->srna, "back", 0, "Return to Previous Mode", "Return to previous mode");
|
|
|
|
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
2015-12-13 21:03:13 +13:00
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Toggle Vertex Paint Mode Operator
|
|
|
|
* \{ */
|
2020-03-09 16:27:24 +01:00
|
|
|
|
|
|
|
static bool gpencil_vertexmode_toggle_poll(bContext *C)
|
|
|
|
{
|
|
|
|
/* if using gpencil object, use this gpd */
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
if ((ob) && (ob->type == OB_GPENCIL)) {
|
|
|
|
return ob->data != NULL;
|
|
|
|
}
|
|
|
|
return ED_gpencil_data_get_active(C) != NULL;
|
|
|
|
}
|
|
|
|
static int gpencil_vertexmode_toggle_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
const bool back = RNA_boolean_get(op->ptr, "back");
|
|
|
|
|
|
|
|
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
|
|
|
|
Main *bmain = CTX_data_main(C);
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
|
|
|
ToolSettings *ts = CTX_data_tool_settings(C);
|
|
|
|
|
|
|
|
bool is_object = false;
|
|
|
|
short mode;
|
|
|
|
/* if using a gpencil object, use this datablock */
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
if ((ob) && (ob->type == OB_GPENCIL)) {
|
|
|
|
gpd = ob->data;
|
|
|
|
is_object = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gpd == NULL) {
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Just toggle paintmode flag... */
|
|
|
|
gpd->flag ^= GP_DATA_STROKE_VERTEXMODE;
|
|
|
|
/* set mode */
|
|
|
|
if (gpd->flag & GP_DATA_STROKE_VERTEXMODE) {
|
|
|
|
mode = OB_MODE_VERTEX_GPENCIL;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
mode = OB_MODE_OBJECT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_object) {
|
|
|
|
/* try to back previous mode */
|
|
|
|
if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_VERTEXMODE) == 0) && (back == 1)) {
|
|
|
|
mode = ob->restore_mode;
|
|
|
|
}
|
|
|
|
ob->restore_mode = ob->mode;
|
|
|
|
ob->mode = mode;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mode == OB_MODE_VERTEX_GPENCIL) {
|
2020-05-30 17:31:54 +02:00
|
|
|
/* Be sure we have brushes. */
|
2020-03-09 16:27:24 +01:00
|
|
|
BKE_paint_ensure(ts, (Paint **)&ts->gp_vertexpaint);
|
2020-05-24 10:22:03 +02:00
|
|
|
|
2020-05-30 17:31:54 +02:00
|
|
|
const bool reset_mode = (ts->gp_vertexpaint->paint.brush == NULL);
|
|
|
|
BKE_brush_gpencil_vertex_presets(bmain, ts, reset_mode);
|
|
|
|
|
|
|
|
BKE_paint_toolslots_brush_validate(bmain, &ts->gp_vertexpaint->paint);
|
2020-05-24 10:22:03 +02:00
|
|
|
|
|
|
|
/* Ensure Palette by default. */
|
|
|
|
BKE_gpencil_palette_ensure(bmain, CTX_data_scene(C));
|
2020-03-09 16:27:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* setup other modes */
|
|
|
|
ED_gpencil_setup_modes(C, gpd, mode);
|
|
|
|
/* set cache as dirty */
|
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
|
|
|
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, NULL);
|
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
|
|
|
|
|
|
|
|
if (is_object) {
|
|
|
|
WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
|
|
|
|
}
|
|
|
|
if (G.background == false) {
|
|
|
|
WM_toolsystem_update_from_context_view3d(C);
|
|
|
|
}
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_vertexmode_toggle(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Strokes Vertex Mode Toggle";
|
|
|
|
ot->idname = "GPENCIL_OT_vertexmode_toggle";
|
|
|
|
ot->description = "Enter/Exit vertex paint mode for Grease Pencil strokes";
|
|
|
|
|
|
|
|
/* callbacks */
|
|
|
|
ot->exec = gpencil_vertexmode_toggle_exec;
|
|
|
|
ot->poll = gpencil_vertexmode_toggle_poll;
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
|
|
|
|
|
|
|
|
/* properties */
|
|
|
|
prop = RNA_def_boolean(
|
|
|
|
ot->srna, "back", 0, "Return to Previous Mode", "Return to previous mode");
|
|
|
|
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Stroke Hide Selection Toggle Operator
|
|
|
|
* \{ */
|
2016-08-03 23:31:48 +02:00
|
|
|
|
|
|
|
static int gpencil_hideselect_toggle_exec(bContext *C, wmOperator *UNUSED(op))
|
|
|
|
{
|
2018-07-31 10:22:19 +02:00
|
|
|
View3D *v3d = CTX_wm_view3d(C);
|
2019-04-22 09:19:45 +10:00
|
|
|
if (v3d == NULL) {
|
2016-08-03 23:31:48 +02:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-03 23:31:48 +02:00
|
|
|
/* Just toggle alpha... */
|
2018-07-31 10:22:19 +02:00
|
|
|
if (v3d->vertex_opacity > 0.0f) {
|
|
|
|
v3d->vertex_opacity = 0.0f;
|
2016-08-03 23:31:48 +02:00
|
|
|
}
|
|
|
|
else {
|
2018-07-31 10:22:19 +02:00
|
|
|
v3d->vertex_opacity = 1.0f;
|
2016-08-03 23:31:48 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-01-25 10:10:21 -02:00
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_GPENCIL_EDITMODE, NULL);
|
2016-08-03 23:31:48 +02:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-03 23:31:48 +02:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_selection_opacity_toggle(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
2019-03-19 17:07:59 -03:00
|
|
|
ot->name = "Hide Selected";
|
2016-08-03 23:31:48 +02:00
|
|
|
ot->idname = "GPENCIL_OT_selection_opacity_toggle";
|
|
|
|
ot->description = "Hide/Unhide selected points for Grease Pencil strokes setting alpha factor";
|
|
|
|
|
|
|
|
/* callbacks */
|
|
|
|
ot->exec = gpencil_hideselect_toggle_exec;
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->poll = gpencil_stroke_edit_poll;
|
2016-08-03 23:31:48 +02:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
|
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Duplicate Selected Strokes Operator
|
|
|
|
* \{ */
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
|
|
|
|
/* Make copies of selected point segments in a selected stroke */
|
2020-11-13 21:43:00 +01:00
|
|
|
static void gpencil_duplicate_points(bGPdata *gpd,
|
|
|
|
const bGPDstroke *gps,
|
2020-06-29 15:28:38 +02:00
|
|
|
ListBase *new_strokes,
|
|
|
|
const char *layername)
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
{
|
|
|
|
bGPDspoint *pt;
|
|
|
|
int i;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
int start_idx = -1;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
/* Step through the original stroke's points:
|
|
|
|
* - We accumulate selected points (from start_idx to current index)
|
|
|
|
* and then convert that to a new stroke
|
|
|
|
*/
|
|
|
|
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
|
|
|
/* searching for start, are waiting for end? */
|
|
|
|
if (start_idx == -1) {
|
|
|
|
/* is this the first selected point for a new island? */
|
|
|
|
if (pt->flag & GP_SPOINT_SELECT) {
|
|
|
|
start_idx = i;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
size_t len = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-12-26 20:00:52 +01:00
|
|
|
/* is this the end of current island yet?
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
* 1) Point i-1 was the last one that was selected
|
|
|
|
* 2) Point i is the last in the array
|
|
|
|
*/
|
|
|
|
if ((pt->flag & GP_SPOINT_SELECT) == 0) {
|
|
|
|
len = i - start_idx;
|
|
|
|
}
|
|
|
|
else if (i == gps->totpoints - 1) {
|
|
|
|
len = i - start_idx + 1;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
/* make copies of the relevant data */
|
|
|
|
if (len) {
|
|
|
|
bGPDstroke *gpsd;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
/* make a stupid copy first of the entire stroke (to get the flags too) */
|
2020-11-13 21:43:00 +01:00
|
|
|
gpsd = BKE_gpencil_stroke_duplicate((bGPDstroke *)gps, false, true);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-15 23:24:20 +11:00
|
|
|
/* saves original layer name */
|
|
|
|
BLI_strncpy(gpsd->runtime.tmp_layerinfo, layername, sizeof(gpsd->runtime.tmp_layerinfo));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
/* now, make a new points array, and copy of the relevant parts */
|
2020-03-05 07:54:52 +11:00
|
|
|
gpsd->points = MEM_mallocN(sizeof(bGPDspoint) * len, "gps stroke points copy");
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
memcpy(gpsd->points, gps->points + start_idx, sizeof(bGPDspoint) * len);
|
|
|
|
gpsd->totpoints = len;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
if (gps->dvert != NULL) {
|
2020-03-05 07:54:52 +11:00
|
|
|
gpsd->dvert = MEM_mallocN(sizeof(MDeformVert) * len, "gps stroke weights copy");
|
2018-07-31 10:22:19 +02:00
|
|
|
memcpy(gpsd->dvert, gps->dvert + start_idx, sizeof(MDeformVert) * len);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* Copy weights */
|
|
|
|
int e = start_idx;
|
|
|
|
for (int j = 0; j < gpsd->totpoints; j++) {
|
|
|
|
MDeformVert *dvert_dst = &gps->dvert[e];
|
|
|
|
MDeformVert *dvert_src = &gps->dvert[j];
|
|
|
|
dvert_dst->dw = MEM_dupallocN(dvert_src->dw);
|
|
|
|
e++;
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
BKE_gpencil_stroke_geometry_update(gpd, gpsd);
|
2020-03-09 16:27:24 +01:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
/* add to temp buffer */
|
|
|
|
gpsd->next = gpsd->prev = NULL;
|
2020-03-09 16:27:24 +01:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
BLI_addtail(new_strokes, gpsd);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
/* cleanup + reset for next */
|
|
|
|
start_idx = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_duplicate_exec(bContext *C, wmOperator *op)
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
{
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
2020-11-13 21:43:00 +01:00
|
|
|
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
if (gpd == NULL) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
if (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "Operator not supported in multiframe edition");
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
bool changed = false;
|
|
|
|
if (is_curve_edit) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "Not implemented!");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* for each visible (and editable) layer's selected strokes,
|
|
|
|
* copy the strokes into a temporary buffer, then append
|
|
|
|
* once all done
|
|
|
|
*/
|
|
|
|
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
|
|
|
|
ListBase new_strokes = {NULL, NULL};
|
|
|
|
bGPDframe *gpf = gpl->actframe;
|
|
|
|
bGPDstroke *gps;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (gpf == NULL) {
|
2015-01-19 16:38:32 +13:00
|
|
|
continue;
|
2016-08-03 23:31:48 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* make copies of selected strokes, and deselect these once we're done */
|
|
|
|
for (gps = gpf->strokes.first; gps; gps = gps->next) {
|
|
|
|
/* skip strokes that are invalid for current view */
|
|
|
|
if (ED_gpencil_stroke_can_use(C, gps) == false) {
|
|
|
|
continue;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (gps->flag & GP_STROKE_SELECT) {
|
|
|
|
if (gps->totpoints == 1) {
|
|
|
|
/* Special Case: If there's just a single point in this stroke... */
|
|
|
|
bGPDstroke *gpsd;
|
2020-03-09 16:27:24 +01:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* make direct copies of the stroke and its points */
|
|
|
|
gpsd = BKE_gpencil_stroke_duplicate(gps, true, true);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
BLI_strncpy(
|
|
|
|
gpsd->runtime.tmp_layerinfo, gpl->info, sizeof(gpsd->runtime.tmp_layerinfo));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* Initialize triangle information. */
|
|
|
|
BKE_gpencil_stroke_geometry_update(gpd, gpsd);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* add to temp buffer */
|
|
|
|
gpsd->next = gpsd->prev = NULL;
|
|
|
|
BLI_addtail(&new_strokes, gpsd);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* delegate to a helper, as there's too much to fit in here (for copying subsets)... */
|
|
|
|
gpencil_duplicate_points(gpd, gps, &new_strokes, gpl->info);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* deselect original stroke, or else the originals get moved too
|
|
|
|
* (when using the copy + move macro)
|
|
|
|
*/
|
|
|
|
bGPDspoint *pt;
|
|
|
|
int i;
|
|
|
|
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
|
|
|
pt->flag &= ~GP_SPOINT_SELECT;
|
|
|
|
}
|
|
|
|
gps->flag &= ~GP_STROKE_SELECT;
|
2021-02-20 10:16:51 +01:00
|
|
|
BKE_gpencil_stroke_select_index_reset(gps);
|
2020-11-13 21:43:00 +01:00
|
|
|
|
|
|
|
changed = true;
|
2019-12-05 13:44:37 +01:00
|
|
|
}
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* add all new strokes in temp buffer to the frame (preventing double-copies) */
|
|
|
|
BLI_movelisttolist(&gpf->strokes, &new_strokes);
|
|
|
|
BLI_assert(new_strokes.first == NULL);
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (changed) {
|
|
|
|
/* updates */
|
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_duplicate(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Duplicate Strokes";
|
|
|
|
ot->idname = "GPENCIL_OT_duplicate";
|
|
|
|
ot->description = "Duplicate the selected Grease Pencil strokes";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
/* callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_duplicate_exec;
|
|
|
|
ot->poll = gpencil_stroke_edit_poll;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Extrude Selected Strokes Operator
|
|
|
|
* \{ */
|
2019-03-04 19:31:36 +01:00
|
|
|
|
|
|
|
/* helper to copy a point to temp area */
|
2020-06-29 15:28:38 +02:00
|
|
|
static void gpencil_copy_move_point(bGPDstroke *gps,
|
|
|
|
bGPDspoint *temp_points,
|
|
|
|
MDeformVert *temp_dverts,
|
|
|
|
int from_idx,
|
|
|
|
int to_idx,
|
|
|
|
const bool copy)
|
2019-03-04 19:31:36 +01:00
|
|
|
{
|
|
|
|
bGPDspoint *pt = &temp_points[from_idx];
|
|
|
|
bGPDspoint *pt_final = &gps->points[to_idx];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
copy_v3_v3(&pt_final->x, &pt->x);
|
|
|
|
pt_final->pressure = pt->pressure;
|
|
|
|
pt_final->strength = pt->strength;
|
|
|
|
pt_final->time = pt->time;
|
|
|
|
pt_final->flag = pt->flag;
|
|
|
|
pt_final->uv_fac = pt->uv_fac;
|
|
|
|
pt_final->uv_rot = pt->uv_rot;
|
2020-03-09 16:27:24 +01:00
|
|
|
copy_v4_v4(pt_final->vert_color, pt->vert_color);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
if (gps->dvert != NULL) {
|
|
|
|
MDeformVert *dvert = &temp_dverts[from_idx];
|
|
|
|
MDeformVert *dvert_final = &gps->dvert[to_idx];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
dvert_final->totweight = dvert->totweight;
|
2019-04-01 16:47:01 +02:00
|
|
|
/* if copy, duplicate memory, otherwise move only the pointer */
|
|
|
|
if (copy) {
|
|
|
|
dvert_final->dw = MEM_dupallocN(dvert->dw);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
dvert_final->dw = dvert->dw;
|
|
|
|
}
|
2019-03-04 19:31:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
static void gpencil_add_move_points(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps)
|
2019-03-04 19:31:36 +01:00
|
|
|
{
|
|
|
|
bGPDspoint *temp_points = NULL;
|
|
|
|
MDeformVert *temp_dverts = NULL;
|
|
|
|
bGPDspoint *pt = NULL;
|
|
|
|
const bGPDspoint *pt_start = &gps->points[0];
|
|
|
|
const bGPDspoint *pt_last = &gps->points[gps->totpoints - 1];
|
|
|
|
const bool do_first = (pt_start->flag & GP_SPOINT_SELECT);
|
|
|
|
const bool do_last = ((pt_last->flag & GP_SPOINT_SELECT) && (pt_start != pt_last));
|
|
|
|
const bool do_stroke = (do_first || do_last);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-01 15:33:09 +02:00
|
|
|
/* review points in the middle of stroke to create new strokes */
|
2019-03-04 19:31:36 +01:00
|
|
|
for (int i = 0; i < gps->totpoints; i++) {
|
|
|
|
/* skip first and last point */
|
2020-11-06 12:30:59 +11:00
|
|
|
if (ELEM(i, 0, gps->totpoints - 1)) {
|
2019-03-04 19:31:36 +01:00
|
|
|
continue;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
pt = &gps->points[i];
|
|
|
|
if (pt->flag == GP_SPOINT_SELECT) {
|
|
|
|
/* duplicate original stroke data */
|
2020-11-13 21:43:00 +01:00
|
|
|
bGPDstroke *gps_new = BKE_gpencil_stroke_duplicate(gps, false, true);
|
2019-03-04 19:31:36 +01:00
|
|
|
gps_new->prev = gps_new->next = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
/* add new points array */
|
|
|
|
gps_new->totpoints = 1;
|
|
|
|
gps_new->points = MEM_callocN(sizeof(bGPDspoint), __func__);
|
|
|
|
gps_new->dvert = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
if (gps->dvert != NULL) {
|
|
|
|
gps_new->dvert = MEM_callocN(sizeof(MDeformVert), __func__);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
BLI_insertlinkafter(&gpf->strokes, gps, gps_new);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
/* copy selected point data to new stroke */
|
2020-06-29 15:28:38 +02:00
|
|
|
gpencil_copy_move_point(gps_new, gps->points, gps->dvert, i, 0, true);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
/* Calc geometry data. */
|
2020-11-13 21:43:00 +01:00
|
|
|
BKE_gpencil_stroke_geometry_update(gpd, gps);
|
|
|
|
BKE_gpencil_stroke_geometry_update(gpd, gps_new);
|
2020-03-09 16:27:24 +01:00
|
|
|
|
2021-02-14 20:58:04 +11:00
|
|
|
/* Deselect original point. */
|
2019-03-04 19:31:36 +01:00
|
|
|
pt->flag &= ~GP_SPOINT_SELECT;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
/* review first and last point to reuse same stroke */
|
|
|
|
int i2 = 0;
|
|
|
|
int totnewpoints, oldtotpoints;
|
|
|
|
/* if first or last, reuse stroke and resize */
|
|
|
|
if ((do_first) || (do_last)) {
|
|
|
|
totnewpoints = gps->totpoints;
|
|
|
|
if (do_first) {
|
|
|
|
totnewpoints++;
|
|
|
|
}
|
|
|
|
if (do_last) {
|
|
|
|
totnewpoints++;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
/* duplicate points in a temp area */
|
|
|
|
temp_points = MEM_dupallocN(gps->points);
|
|
|
|
oldtotpoints = gps->totpoints;
|
|
|
|
if (gps->dvert != NULL) {
|
|
|
|
temp_dverts = MEM_dupallocN(gps->dvert);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
/* if first point, need move all one position */
|
|
|
|
if (do_first) {
|
|
|
|
i2 = 1;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
/* resize the points arrays */
|
|
|
|
gps->totpoints = totnewpoints;
|
|
|
|
gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
|
|
|
|
if (gps->dvert != NULL) {
|
|
|
|
gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
/* move points to new position */
|
|
|
|
for (int i = 0; i < oldtotpoints; i++) {
|
2020-06-29 15:28:38 +02:00
|
|
|
gpencil_copy_move_point(gps, temp_points, temp_dverts, i, i2, false);
|
2019-03-04 19:31:36 +01:00
|
|
|
i2++;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-07 15:38:41 +10:00
|
|
|
/* If first point, add new point at the beginning. */
|
2019-03-04 19:31:36 +01:00
|
|
|
if (do_first) {
|
2020-06-29 15:28:38 +02:00
|
|
|
gpencil_copy_move_point(gps, temp_points, temp_dverts, 0, 0, true);
|
2019-03-04 19:31:36 +01:00
|
|
|
/* deselect old */
|
|
|
|
pt = &gps->points[1];
|
|
|
|
pt->flag &= ~GP_SPOINT_SELECT;
|
|
|
|
/* select new */
|
|
|
|
pt = &gps->points[0];
|
|
|
|
pt->flag |= GP_SPOINT_SELECT;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
/* if last point, add new point at the end */
|
|
|
|
if (do_last) {
|
2020-06-29 15:28:38 +02:00
|
|
|
gpencil_copy_move_point(
|
|
|
|
gps, temp_points, temp_dverts, oldtotpoints - 1, gps->totpoints - 1, true);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
/* deselect old */
|
|
|
|
pt = &gps->points[gps->totpoints - 2];
|
|
|
|
pt->flag &= ~GP_SPOINT_SELECT;
|
|
|
|
/* select new */
|
|
|
|
pt = &gps->points[gps->totpoints - 1];
|
|
|
|
pt->flag |= GP_SPOINT_SELECT;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-07-29 11:19:35 +02:00
|
|
|
/* Flip stroke if it was only one point to consider extrude point as last point. */
|
|
|
|
if (gps->totpoints == 2) {
|
2020-11-18 21:30:43 +01:00
|
|
|
BKE_gpencil_stroke_flip(gps);
|
2020-07-29 11:19:35 +02:00
|
|
|
}
|
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
/* Calc geometry data. */
|
2020-11-13 21:43:00 +01:00
|
|
|
BKE_gpencil_stroke_geometry_update(gpd, gps);
|
2020-03-09 16:27:24 +01:00
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
MEM_SAFE_FREE(temp_points);
|
|
|
|
MEM_SAFE_FREE(temp_dverts);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
/* if the stroke is not reused, deselect */
|
|
|
|
if (!do_stroke) {
|
|
|
|
gps->flag &= ~GP_STROKE_SELECT;
|
2021-02-20 10:16:51 +01:00
|
|
|
BKE_gpencil_stroke_select_index_reset(gps);
|
2019-03-04 19:31:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
static void gpencil_curve_extrude_points(bGPdata *gpd,
|
|
|
|
bGPDframe *gpf,
|
|
|
|
bGPDstroke *gps,
|
|
|
|
bGPDcurve *gpc)
|
|
|
|
{
|
|
|
|
const int old_num_points = gpc->tot_curve_points;
|
|
|
|
const bool first_select = gpc->curve_points[0].flag & GP_CURVE_POINT_SELECT;
|
|
|
|
bool last_select = gpc->curve_points[old_num_points - 1].flag & GP_CURVE_POINT_SELECT;
|
|
|
|
|
|
|
|
/* iterate over middle points */
|
|
|
|
for (int i = 1; i < gpc->tot_curve_points - 1; i++) {
|
|
|
|
bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
|
|
|
|
|
|
|
|
/* Create new stroke if selected point */
|
|
|
|
if (gpc_pt->flag & GP_CURVE_POINT_SELECT) {
|
|
|
|
bGPDstroke *gps_new = BKE_gpencil_stroke_duplicate(gps, false, false);
|
|
|
|
gps_new->points = NULL;
|
|
|
|
gps_new->flag &= ~GP_STROKE_CYCLIC;
|
|
|
|
gps_new->prev = gps_new->next = NULL;
|
|
|
|
|
|
|
|
gps_new->editcurve = BKE_gpencil_stroke_editcurve_new(2);
|
|
|
|
bGPDcurve *new_gpc = gps_new->editcurve;
|
|
|
|
for (int j = 0; j < new_gpc->tot_curve_points; j++) {
|
|
|
|
bGPDcurve_point *gpc_pt_new = &new_gpc->curve_points[j];
|
|
|
|
memcpy(gpc_pt_new, gpc_pt, sizeof(bGPDcurve_point));
|
|
|
|
gpc_pt_new->flag &= ~GP_CURVE_POINT_SELECT;
|
|
|
|
BEZT_DESEL_ALL(&gpc_pt_new->bezt);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* select last point */
|
|
|
|
bGPDcurve_point *gpc_pt_last = &new_gpc->curve_points[1];
|
|
|
|
gpc_pt_last->flag |= GP_CURVE_POINT_SELECT;
|
|
|
|
BEZT_SEL_IDX(&gpc_pt_last->bezt, 1);
|
|
|
|
gps_new->editcurve->flag |= GP_CURVE_SELECT;
|
|
|
|
|
|
|
|
BLI_insertlinkafter(&gpf->strokes, gps, gps_new);
|
|
|
|
|
|
|
|
gps_new->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
|
|
|
|
BKE_gpencil_stroke_geometry_update(gpd, gps_new);
|
|
|
|
|
|
|
|
gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
|
|
|
|
BEZT_DESEL_ALL(&gpc_pt->bezt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-14 20:58:04 +11:00
|
|
|
/* Edge-case for single curve point. */
|
2020-11-13 21:43:00 +01:00
|
|
|
if (gpc->tot_curve_points == 1) {
|
|
|
|
last_select = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (first_select || last_select) {
|
|
|
|
int new_num_points = old_num_points;
|
|
|
|
|
|
|
|
if (first_select) {
|
|
|
|
new_num_points++;
|
|
|
|
}
|
|
|
|
if (last_select) {
|
|
|
|
new_num_points++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Grow the array */
|
|
|
|
gpc->tot_curve_points = new_num_points;
|
|
|
|
gpc->curve_points = MEM_recallocN(gpc->curve_points, sizeof(bGPDcurve_point) * new_num_points);
|
|
|
|
|
|
|
|
if (first_select) {
|
|
|
|
/* shift points by one */
|
|
|
|
memmove(
|
|
|
|
&gpc->curve_points[1], &gpc->curve_points[0], sizeof(bGPDcurve_point) * old_num_points);
|
|
|
|
|
|
|
|
bGPDcurve_point *old_first = &gpc->curve_points[1];
|
|
|
|
|
|
|
|
old_first->flag &= ~GP_CURVE_POINT_SELECT;
|
|
|
|
BEZT_DESEL_ALL(&old_first->bezt);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (last_select) {
|
|
|
|
bGPDcurve_point *old_last = &gpc->curve_points[gpc->tot_curve_points - 2];
|
|
|
|
bGPDcurve_point *new_last = &gpc->curve_points[gpc->tot_curve_points - 1];
|
|
|
|
memcpy(new_last, old_last, sizeof(bGPDcurve_point));
|
|
|
|
|
|
|
|
old_last->flag &= ~GP_CURVE_POINT_SELECT;
|
|
|
|
BEZT_DESEL_ALL(&old_last->bezt);
|
|
|
|
}
|
|
|
|
|
|
|
|
gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
|
|
|
|
BKE_gpencil_stroke_geometry_update(gpd, gps);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_extrude_exec(bContext *C, wmOperator *op)
|
2019-03-04 19:31:36 +01:00
|
|
|
{
|
|
|
|
Object *obact = CTX_data_active_object(C);
|
|
|
|
bGPdata *gpd = (bGPdata *)obact->data;
|
2020-11-13 21:43:00 +01:00
|
|
|
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
2019-03-04 19:31:36 +01:00
|
|
|
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
|
|
|
|
bGPDstroke *gps = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
if (gpd == NULL) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
bool changed = false;
|
2019-03-04 19:31:36 +01:00
|
|
|
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
|
2019-06-07 11:46:11 +02:00
|
|
|
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
|
|
|
|
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
|
2019-04-22 09:19:45 +10:00
|
|
|
if (gpf == NULL) {
|
2019-03-04 19:31:36 +01:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
for (gps = gpf->strokes.first; gps; gps = gps->next) {
|
|
|
|
/* skip strokes that are invalid for current view */
|
2019-04-22 09:19:45 +10:00
|
|
|
if (ED_gpencil_stroke_can_use(C, gps) == false) {
|
2019-03-04 19:31:36 +01:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (is_curve_edit) {
|
|
|
|
if (gps->editcurve == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
bGPDcurve *gpc = gps->editcurve;
|
|
|
|
if (gpc->flag & GP_CURVE_SELECT) {
|
|
|
|
gpencil_curve_extrude_points(gpd, gpf, gps, gpc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (gps->flag & GP_STROKE_SELECT) {
|
|
|
|
gpencil_add_move_points(gpd, gpf, gps);
|
|
|
|
}
|
2019-03-04 19:31:36 +01:00
|
|
|
}
|
2020-11-13 21:43:00 +01:00
|
|
|
|
|
|
|
changed = true;
|
2019-03-04 19:31:36 +01:00
|
|
|
}
|
2021-02-14 20:58:04 +11:00
|
|
|
/* If not multi-edit, exit loop. */
|
2019-03-04 19:31:36 +01:00
|
|
|
if (!is_multiedit) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (changed) {
|
|
|
|
/* updates */
|
|
|
|
DEG_id_tag_update(&gpd->id,
|
|
|
|
ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
|
|
|
|
DEG_id_tag_update(&obact->id, ID_RECALC_COPY_ON_WRITE);
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-04 19:31:36 +01:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_extrude(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Extrude Stroke Points";
|
|
|
|
ot->idname = "GPENCIL_OT_extrude";
|
|
|
|
ot->description = "Extrude the selected Grease Pencil points";
|
|
|
|
|
|
|
|
/* callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_extrude_exec;
|
|
|
|
ot->poll = gpencil_stroke_edit_poll;
|
2019-03-04 19:31:36 +01:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Copy/Paste Strokes Utilities
|
|
|
|
*
|
|
|
|
* Grease Pencil stroke data copy/paste buffer:
|
2015-01-01 12:36:01 +13:00
|
|
|
* - The copy operation collects all segments of selected strokes,
|
|
|
|
* dumping "ready to be copied" copies of the strokes into the buffer.
|
|
|
|
* - The paste operation makes a copy of those elements, and adds them
|
|
|
|
* to the active layer. This effectively flattens down the strokes
|
|
|
|
* from several different layers into a single layer.
|
2020-05-06 12:45:04 +10:00
|
|
|
* \{ */
|
2015-01-01 12:36:01 +13:00
|
|
|
|
2021-02-14 20:58:04 +11:00
|
|
|
/**
|
|
|
|
* list of #bGPDstroke instances
|
|
|
|
*
|
|
|
|
* \note is exposed within the editors/gpencil module so that other tools can use it too.
|
|
|
|
*/
|
2020-06-29 12:49:30 +02:00
|
|
|
ListBase gpencil_strokes_copypastebuf = {NULL, NULL};
|
2015-01-01 12:36:01 +13:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* Hash for hanging on to all the colors used by strokes in the buffer
|
2017-06-08 02:42:04 +12:00
|
|
|
*
|
2019-06-12 09:04:10 +10:00
|
|
|
* This is needed to prevent dangling and unsafe pointers when pasting across data-blocks,
|
2017-06-08 02:42:04 +12:00
|
|
|
* or after a color used by a stroke in the buffer gets deleted (via user action or undo).
|
|
|
|
*/
|
2020-06-29 15:28:38 +02:00
|
|
|
static GHash *gpencil_strokes_copypastebuf_colors = NULL;
|
2017-06-08 02:42:04 +12:00
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static GHash *gpencil_strokes_copypastebuf_colors_material_to_name_create(Main *bmain)
|
2018-08-23 08:40:05 +02:00
|
|
|
{
|
|
|
|
GHash *ma_to_name = BLI_ghash_ptr_new(__func__);
|
|
|
|
|
2019-03-08 09:29:17 +11:00
|
|
|
for (Material *ma = bmain->materials.first; ma != NULL; ma = ma->id.next) {
|
2018-08-23 08:40:05 +02:00
|
|
|
char *name = BKE_id_to_unique_string_key(&ma->id);
|
|
|
|
BLI_ghash_insert(ma_to_name, ma, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ma_to_name;
|
|
|
|
}
|
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static void gpencil_strokes_copypastebuf_colors_material_to_name_free(GHash *ma_to_name)
|
2018-08-23 08:40:05 +02:00
|
|
|
{
|
|
|
|
BLI_ghash_free(ma_to_name, NULL, MEM_freeN);
|
|
|
|
}
|
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static GHash *gpencil_strokes_copypastebuf_colors_name_to_material_create(Main *bmain)
|
2018-08-23 08:40:05 +02:00
|
|
|
{
|
|
|
|
GHash *name_to_ma = BLI_ghash_str_new(__func__);
|
|
|
|
|
2019-03-08 09:29:17 +11:00
|
|
|
for (Material *ma = bmain->materials.first; ma != NULL; ma = ma->id.next) {
|
2018-08-23 08:40:05 +02:00
|
|
|
char *name = BKE_id_to_unique_string_key(&ma->id);
|
|
|
|
BLI_ghash_insert(name_to_ma, name, ma);
|
|
|
|
}
|
|
|
|
|
|
|
|
return name_to_ma;
|
|
|
|
}
|
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static void gpencil_strokes_copypastebuf_colors_name_to_material_free(GHash *name_to_ma)
|
2018-08-23 08:40:05 +02:00
|
|
|
{
|
|
|
|
BLI_ghash_free(name_to_ma, MEM_freeN, NULL);
|
|
|
|
}
|
|
|
|
|
2015-01-01 12:36:01 +13:00
|
|
|
/* Free copy/paste buffer data */
|
|
|
|
void ED_gpencil_strokes_copybuf_free(void)
|
|
|
|
{
|
|
|
|
bGPDstroke *gps, *gpsn;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* Free the colors buffer
|
|
|
|
* NOTE: This is done before the strokes so that the ptrs are still safe
|
2017-06-08 02:42:04 +12:00
|
|
|
*/
|
2020-06-29 15:28:38 +02:00
|
|
|
if (gpencil_strokes_copypastebuf_colors) {
|
|
|
|
BLI_ghash_free(gpencil_strokes_copypastebuf_colors, NULL, MEM_freeN);
|
|
|
|
gpencil_strokes_copypastebuf_colors = NULL;
|
2017-06-08 02:42:04 +12:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-06-08 02:42:04 +12:00
|
|
|
/* Free the stroke buffer */
|
2020-06-29 12:49:30 +02:00
|
|
|
for (gps = gpencil_strokes_copypastebuf.first; gps; gps = gpsn) {
|
2015-01-01 12:36:01 +13:00
|
|
|
gpsn = gps->next;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
if (gps->points) {
|
|
|
|
MEM_freeN(gps->points);
|
|
|
|
}
|
|
|
|
if (gps->dvert) {
|
|
|
|
BKE_gpencil_free_stroke_weights(gps);
|
|
|
|
MEM_freeN(gps->dvert);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
MEM_SAFE_FREE(gps->triangles);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-06-29 12:49:30 +02:00
|
|
|
BLI_freelinkN(&gpencil_strokes_copypastebuf, gps);
|
2015-01-01 12:36:01 +13:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-06-29 12:49:30 +02:00
|
|
|
gpencil_strokes_copypastebuf.first = gpencil_strokes_copypastebuf.last = NULL;
|
2015-01-01 12:36:01 +13:00
|
|
|
}
|
|
|
|
|
2019-04-29 14:14:14 +10:00
|
|
|
/**
|
|
|
|
* Ensure that destination datablock has all the colors the pasted strokes need.
|
2017-06-08 03:07:57 +12:00
|
|
|
* Helper function for copy-pasting strokes
|
|
|
|
*/
|
2020-06-29 12:49:30 +02:00
|
|
|
GHash *gpencil_copybuf_validate_colormap(bContext *C)
|
2017-06-08 03:07:57 +12:00
|
|
|
{
|
2018-07-31 10:22:19 +02:00
|
|
|
Main *bmain = CTX_data_main(C);
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
2018-08-23 08:40:05 +02:00
|
|
|
GHash *new_colors = BLI_ghash_int_new("GPencil Paste Dst Colors");
|
2017-06-08 03:07:57 +12:00
|
|
|
GHashIterator gh_iter;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* For each color, check if exist and add if not */
|
2020-06-29 15:28:38 +02:00
|
|
|
GHash *name_to_ma = gpencil_strokes_copypastebuf_colors_name_to_material_create(bmain);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
GHASH_ITER (gh_iter, gpencil_strokes_copypastebuf_colors) {
|
2018-07-31 10:22:19 +02:00
|
|
|
int *key = BLI_ghashIterator_getKey(&gh_iter);
|
2018-08-23 08:40:05 +02:00
|
|
|
char *ma_name = BLI_ghashIterator_getValue(&gh_iter);
|
|
|
|
Material *ma = BLI_ghash_lookup(name_to_ma, ma_name);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2019-04-09 09:22:46 +02:00
|
|
|
BKE_gpencil_object_material_ensure(bmain, ob, ma);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2017-06-08 03:07:57 +12:00
|
|
|
/* Store this mapping (for use later when pasting) */
|
2018-12-19 22:56:29 +01:00
|
|
|
if (!BLI_ghash_haskey(new_colors, POINTER_FROM_INT(*key))) {
|
|
|
|
BLI_ghash_insert(new_colors, POINTER_FROM_INT(*key), ma);
|
|
|
|
}
|
2017-06-08 03:07:57 +12:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
gpencil_strokes_copypastebuf_colors_name_to_material_free(name_to_ma);
|
2018-08-23 08:40:05 +02:00
|
|
|
|
2017-06-08 03:07:57 +12:00
|
|
|
return new_colors;
|
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Copy Selected Strokes Operator
|
|
|
|
* \{ */
|
2015-01-01 12:36:01 +13:00
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_strokes_copy_exec(bContext *C, wmOperator *op)
|
2015-01-01 12:36:01 +13:00
|
|
|
{
|
2018-08-23 08:40:05 +02:00
|
|
|
Main *bmain = CTX_data_main(C);
|
2018-07-31 10:22:19 +02:00
|
|
|
Object *ob = CTX_data_active_object(C);
|
2015-01-01 12:36:01 +13:00
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
2020-11-13 21:43:00 +01:00
|
|
|
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-01-01 12:36:01 +13:00
|
|
|
if (gpd == NULL) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
if (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "Operator not supported in multiframe edition");
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-01-01 12:36:01 +13:00
|
|
|
/* clear the buffer first */
|
|
|
|
ED_gpencil_strokes_copybuf_free();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (is_curve_edit) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "Not implemented!");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* for each visible (and editable) layer's selected strokes,
|
|
|
|
* copy the strokes into a temporary buffer, then append
|
|
|
|
* once all done
|
|
|
|
*/
|
|
|
|
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
|
|
|
|
bGPDframe *gpf = gpl->actframe;
|
|
|
|
bGPDstroke *gps;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (gpf == NULL) {
|
2015-01-19 16:38:32 +13:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* make copies of selected strokes, and deselect these once we're done */
|
|
|
|
for (gps = gpf->strokes.first; gps; gps = gps->next) {
|
|
|
|
/* skip strokes that are invalid for current view */
|
|
|
|
if (ED_gpencil_stroke_can_use(C, gps) == false) {
|
|
|
|
continue;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (gps->flag & GP_STROKE_SELECT) {
|
|
|
|
if (gps->totpoints == 1) {
|
|
|
|
/* Special Case: If there's just a single point in this stroke... */
|
|
|
|
bGPDstroke *gpsd;
|
|
|
|
|
|
|
|
/* make direct copies of the stroke and its points */
|
|
|
|
gpsd = BKE_gpencil_stroke_duplicate(gps, false, true);
|
|
|
|
|
|
|
|
/* saves original layer name */
|
|
|
|
BLI_strncpy(
|
|
|
|
gpsd->runtime.tmp_layerinfo, gpl->info, sizeof(gpsd->runtime.tmp_layerinfo));
|
|
|
|
gpsd->points = MEM_dupallocN(gps->points);
|
|
|
|
if (gps->dvert != NULL) {
|
|
|
|
gpsd->dvert = MEM_dupallocN(gps->dvert);
|
|
|
|
BKE_gpencil_stroke_weights_duplicate(gps, gpsd);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* Calc geometry data. */
|
|
|
|
BKE_gpencil_stroke_geometry_update(gpd, gpsd);
|
|
|
|
|
|
|
|
/* add to temp buffer */
|
|
|
|
gpsd->next = gpsd->prev = NULL;
|
|
|
|
BLI_addtail(&gpencil_strokes_copypastebuf, gpsd);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* delegate to a helper, as there's too much to fit in here (for copying subsets)... */
|
|
|
|
gpencil_duplicate_points(gpd, gps, &gpencil_strokes_copypastebuf, gpl->info);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2015-01-01 12:36:01 +13:00
|
|
|
}
|
|
|
|
}
|
2020-11-13 21:43:00 +01:00
|
|
|
CTX_DATA_END;
|
2015-01-01 12:36:01 +13:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* Build up hash of material colors used in these strokes */
|
2020-06-29 12:49:30 +02:00
|
|
|
if (gpencil_strokes_copypastebuf.first) {
|
2020-06-29 15:28:38 +02:00
|
|
|
gpencil_strokes_copypastebuf_colors = BLI_ghash_int_new("GPencil CopyBuf Colors");
|
|
|
|
GHash *ma_to_name = gpencil_strokes_copypastebuf_colors_material_to_name_create(bmain);
|
2020-06-29 12:49:30 +02:00
|
|
|
LISTBASE_FOREACH (bGPDstroke *, gps, &gpencil_strokes_copypastebuf) {
|
2017-06-08 02:42:04 +12:00
|
|
|
if (ED_gpencil_stroke_can_use(C, gps)) {
|
2020-02-05 11:23:58 +01:00
|
|
|
Material *ma = BKE_object_material_get(ob, gps->mat_nr + 1);
|
2019-08-30 14:19:07 +02:00
|
|
|
/* Avoid default material. */
|
|
|
|
if (ma == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-08-23 08:40:05 +02:00
|
|
|
char **ma_name_val;
|
|
|
|
if (!BLI_ghash_ensure_p(
|
2020-06-29 15:28:38 +02:00
|
|
|
gpencil_strokes_copypastebuf_colors, &gps->mat_nr, (void ***)&ma_name_val)) {
|
2018-08-23 08:40:05 +02:00
|
|
|
char *ma_name = BLI_ghash_lookup(ma_to_name, ma);
|
|
|
|
*ma_name_val = MEM_dupallocN(ma_name);
|
2017-06-08 02:42:04 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-06-29 15:28:38 +02:00
|
|
|
gpencil_strokes_copypastebuf_colors_material_to_name_free(ma_to_name);
|
2017-06-08 02:42:04 +12:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-06-07 19:07:57 +12:00
|
|
|
/* updates (to ensure operator buttons are refreshed, when used via hotkeys) */
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL); /* XXX? */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-06-07 19:07:57 +12:00
|
|
|
/* done */
|
2015-01-01 12:36:01 +13:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
2014-12-31 14:20:44 +13:00
|
|
|
|
2015-01-01 12:36:01 +13:00
|
|
|
void GPENCIL_OT_copy(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Copy Strokes";
|
|
|
|
ot->idname = "GPENCIL_OT_copy";
|
|
|
|
ot->description = "Copy selected Grease Pencil points and strokes";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2015-01-01 12:36:01 +13:00
|
|
|
/* callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_strokes_copy_exec;
|
|
|
|
ot->poll = gpencil_stroke_edit_poll;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2015-01-01 12:36:01 +13:00
|
|
|
/* flags */
|
2019-05-01 11:09:22 +10:00
|
|
|
// ot->flag = OPTYPE_REGISTER;
|
2015-01-01 12:36:01 +13:00
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Paste Selected Strokes Operator
|
|
|
|
* \{ */
|
2015-01-01 12:36:01 +13:00
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static bool gpencil_strokes_paste_poll(bContext *C)
|
2016-05-09 19:41:48 +12:00
|
|
|
{
|
2020-04-03 13:25:03 +02:00
|
|
|
ScrArea *area = CTX_wm_area(C);
|
|
|
|
if (!((area != NULL) && (area->spacetype == SPACE_VIEW3D))) {
|
2020-03-09 16:27:24 +01:00
|
|
|
return false;
|
|
|
|
}
|
2016-08-29 16:27:23 +12:00
|
|
|
/* 1) Must have GP datablock to paste to
|
|
|
|
* - We don't need to have an active layer though, as that can easily get added
|
2019-04-22 00:18:34 +10:00
|
|
|
* - If the active layer is locked, we can't paste there,
|
|
|
|
* but that should prompt a warning instead.
|
|
|
|
* 2) Copy buffer must at least have something (though it may be the wrong sort...).
|
2016-05-09 19:41:48 +12:00
|
|
|
*/
|
2016-08-29 16:27:23 +12:00
|
|
|
return (ED_gpencil_data_get_active(C) != NULL) &&
|
2020-06-29 12:49:30 +02:00
|
|
|
(!BLI_listbase_is_empty(&gpencil_strokes_copypastebuf));
|
2016-05-09 19:41:48 +12:00
|
|
|
}
|
|
|
|
|
2016-08-29 16:39:27 +12:00
|
|
|
typedef enum eGP_PasteMode {
|
2019-08-26 15:46:00 +02:00
|
|
|
GP_COPY_BY_LAYER = -1,
|
|
|
|
GP_COPY_TO_ACTIVE = 1,
|
2016-08-29 16:39:27 +12:00
|
|
|
} eGP_PasteMode;
|
2016-08-03 23:31:48 +02:00
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_strokes_paste_exec(bContext *C, wmOperator *op)
|
2015-01-01 12:36:01 +13:00
|
|
|
{
|
2018-07-31 10:22:19 +02:00
|
|
|
Object *ob = CTX_data_active_object(C);
|
2020-03-09 16:27:24 +01:00
|
|
|
bGPdata *gpd = (bGPdata *)ob->data;
|
2020-11-13 21:43:00 +01:00
|
|
|
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
2020-03-09 16:27:24 +01:00
|
|
|
bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); /* only use active for copy merge */
|
2019-07-26 14:13:53 +02:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2015-01-01 12:36:01 +13:00
|
|
|
bGPDframe *gpf;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-29 16:39:27 +12:00
|
|
|
eGP_PasteMode type = RNA_enum_get(op->ptr, "type");
|
2020-03-09 16:27:24 +01:00
|
|
|
const bool on_back = RNA_boolean_get(op->ptr, "paste_back");
|
2017-06-08 03:07:57 +12:00
|
|
|
GHash *new_colors;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
/* Check for various error conditions. */
|
|
|
|
if (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) {
|
2018-07-31 10:22:19 +02:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "Operator not supported in multiframe edition");
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2020-07-03 14:38:26 +02:00
|
|
|
|
|
|
|
if (BLI_listbase_is_empty(&gpencil_strokes_copypastebuf)) {
|
2015-01-01 12:36:01 +13:00
|
|
|
BKE_report(op->reports,
|
|
|
|
RPT_ERROR,
|
|
|
|
"No strokes to paste, select and copy some points before trying again");
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2020-07-03 14:38:26 +02:00
|
|
|
|
|
|
|
if (gpl == NULL) {
|
2015-01-01 12:36:01 +13:00
|
|
|
/* no active layer - let's just create one */
|
2016-08-04 15:03:18 +02:00
|
|
|
gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
|
2015-01-01 12:36:01 +13:00
|
|
|
}
|
2020-03-09 16:27:24 +01:00
|
|
|
else if ((BKE_gpencil_layer_is_editable(gpl) == false) && (type == GP_COPY_TO_ACTIVE)) {
|
2015-01-01 12:36:01 +13:00
|
|
|
BKE_report(
|
|
|
|
op->reports, RPT_ERROR, "Can not paste strokes when active layer is hidden or locked");
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2015-02-18 12:08:07 +13:00
|
|
|
else {
|
|
|
|
/* Check that some of the strokes in the buffer can be used */
|
|
|
|
bGPDstroke *gps;
|
|
|
|
bool ok = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-06-29 12:49:30 +02:00
|
|
|
for (gps = gpencil_strokes_copypastebuf.first; gps; gps = gps->next) {
|
2015-02-18 12:08:07 +13:00
|
|
|
if (ED_gpencil_stroke_can_use(C, gps)) {
|
|
|
|
ok = true;
|
|
|
|
break;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
2015-02-18 12:08:07 +13:00
|
|
|
if (ok == false) {
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
2015-01-01 12:36:01 +13:00
|
|
|
/* Deselect all strokes first */
|
|
|
|
CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
|
|
|
|
bGPDspoint *pt;
|
|
|
|
int i;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-01-01 12:36:01 +13:00
|
|
|
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
|
|
|
pt->flag &= ~GP_SPOINT_SELECT;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-01-01 12:36:01 +13:00
|
|
|
gps->flag &= ~GP_STROKE_SELECT;
|
2021-02-20 10:16:51 +01:00
|
|
|
BKE_gpencil_stroke_select_index_reset(gps);
|
2015-01-01 12:36:01 +13:00
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-06-07 19:07:21 +12:00
|
|
|
/* Ensure that all the necessary colors exist */
|
2020-06-29 12:49:30 +02:00
|
|
|
new_colors = gpencil_copybuf_validate_colormap(C);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (is_curve_edit) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "Not implemented!");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* Copy over the strokes from the buffer (and adjust the colors) */
|
|
|
|
bGPDstroke *gps_init = (!on_back) ? gpencil_strokes_copypastebuf.first :
|
|
|
|
gpencil_strokes_copypastebuf.last;
|
|
|
|
for (bGPDstroke *gps = gps_init; gps; gps = (!on_back) ? gps->next : gps->prev) {
|
|
|
|
if (ED_gpencil_stroke_can_use(C, gps)) {
|
|
|
|
/* Need to verify if layer exists */
|
|
|
|
if (type != GP_COPY_TO_ACTIVE) {
|
|
|
|
gpl = BLI_findstring(
|
|
|
|
&gpd->layers, gps->runtime.tmp_layerinfo, offsetof(bGPDlayer, info));
|
|
|
|
if (gpl == NULL) {
|
|
|
|
/* no layer - use active (only if layer deleted before paste) */
|
|
|
|
gpl = BKE_gpencil_layer_active_get(gpd);
|
|
|
|
}
|
2015-02-18 12:08:07 +13:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* Ensure we have a frame to draw into
|
|
|
|
* NOTE: Since this is an op which creates strokes,
|
|
|
|
* we are obliged to add a new frame if one
|
|
|
|
* doesn't exist already
|
|
|
|
*/
|
|
|
|
gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_NEW);
|
|
|
|
if (gpf) {
|
|
|
|
/* Create new stroke */
|
|
|
|
bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps, true, true);
|
|
|
|
new_stroke->runtime.tmp_layerinfo[0] = '\0';
|
|
|
|
new_stroke->next = new_stroke->prev = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* Calc geometry data. */
|
|
|
|
BKE_gpencil_stroke_geometry_update(gpd, new_stroke);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (on_back) {
|
|
|
|
BLI_addhead(&gpf->strokes, new_stroke);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BLI_addtail(&gpf->strokes, new_stroke);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* Remap material */
|
|
|
|
Material *ma = BLI_ghash_lookup(new_colors, POINTER_FROM_INT(new_stroke->mat_nr));
|
|
|
|
new_stroke->mat_nr = BKE_gpencil_object_material_index_get(ob, ma);
|
|
|
|
CLAMP_MIN(new_stroke->mat_nr, 0);
|
|
|
|
}
|
2016-08-29 16:39:27 +12:00
|
|
|
}
|
2015-01-01 12:36:01 +13:00
|
|
|
}
|
2016-08-29 16:39:27 +12:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-06-08 02:42:04 +12:00
|
|
|
/* free temp data */
|
|
|
|
BLI_ghash_free(new_colors, NULL, NULL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-01-01 12:36:01 +13:00
|
|
|
/* updates */
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
2015-01-01 12:36:01 +13:00
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-01-01 12:36:01 +13:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_paste(wmOperatorType *ot)
|
|
|
|
{
|
2020-03-09 16:27:24 +01:00
|
|
|
PropertyRNA *prop;
|
|
|
|
|
2017-10-18 15:07:26 +11:00
|
|
|
static const EnumPropertyItem copy_type[] = {
|
2019-08-26 15:46:00 +02:00
|
|
|
{GP_COPY_TO_ACTIVE, "ACTIVE", 0, "Paste to Active", ""},
|
|
|
|
{GP_COPY_BY_LAYER, "LAYER", 0, "Paste by Layer", ""},
|
2019-02-03 14:01:45 +11:00
|
|
|
{0, NULL, 0, NULL, NULL},
|
2016-08-03 23:31:48 +02:00
|
|
|
};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-01-01 12:36:01 +13:00
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Paste Strokes";
|
|
|
|
ot->idname = "GPENCIL_OT_paste";
|
2019-08-26 15:46:00 +02:00
|
|
|
ot->description = "Paste previously copied strokes to active layer or to original layer";
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-01-01 12:36:01 +13:00
|
|
|
/* callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_strokes_paste_exec;
|
|
|
|
ot->poll = gpencil_strokes_paste_poll;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-01-01 12:36:01 +13:00
|
|
|
/* flags */
|
2019-07-25 16:36:22 +02:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-29 16:39:27 +12:00
|
|
|
/* properties */
|
2019-08-26 15:46:00 +02:00
|
|
|
ot->prop = RNA_def_enum(ot->srna, "type", copy_type, GP_COPY_TO_ACTIVE, "Type", "");
|
2020-03-09 16:27:24 +01:00
|
|
|
|
|
|
|
prop = RNA_def_boolean(
|
|
|
|
ot->srna, "paste_back", 0, "Paste on Back", "Add pasted strokes behind all strokes");
|
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
2015-01-01 12:36:01 +13:00
|
|
|
}
|
2014-12-31 14:20:44 +13:00
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Move To Layer Operator
|
|
|
|
* \{ */
|
2015-12-13 21:03:13 +13:00
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_move_to_layer_exec(bContext *C, wmOperator *op)
|
2015-12-13 21:03:13 +13:00
|
|
|
{
|
2020-02-17 10:49:27 +01:00
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
bGPdata *gpd = (bGPdata *)ob->data;
|
2019-07-26 14:13:53 +02:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2015-12-13 21:03:13 +13:00
|
|
|
bGPDlayer *target_layer = NULL;
|
|
|
|
ListBase strokes = {NULL, NULL};
|
2019-08-30 13:00:21 +02:00
|
|
|
int layer_num = RNA_int_get(op->ptr, "layer");
|
2019-02-12 18:14:36 +01:00
|
|
|
const bool use_autolock = (bool)(gpd->flag & GP_DATA_AUTOLOCK_LAYERS);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
if (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "Operator not supported in multiframe edition");
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-12 18:14:36 +01:00
|
|
|
/* if autolock enabled, disabled now */
|
|
|
|
if (use_autolock) {
|
|
|
|
gpd->flag &= ~GP_DATA_AUTOLOCK_LAYERS;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-30 13:00:21 +02:00
|
|
|
/* Try to get layer */
|
2020-03-31 18:54:41 +02:00
|
|
|
if (layer_num > -1) {
|
|
|
|
target_layer = BLI_findlink(&gpd->layers, layer_num);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* Create a new layer. */
|
|
|
|
target_layer = BKE_gpencil_layer_addnew(gpd, "GP_Layer", true);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-30 13:00:21 +02:00
|
|
|
if (target_layer == NULL) {
|
|
|
|
/* back autolock status */
|
|
|
|
if (use_autolock) {
|
|
|
|
gpd->flag |= GP_DATA_AUTOLOCK_LAYERS;
|
2015-12-13 21:03:13 +13:00
|
|
|
}
|
2019-08-30 13:00:21 +02:00
|
|
|
BKE_reportf(op->reports, RPT_ERROR, "There is no layer number %d", layer_num);
|
|
|
|
return OPERATOR_CANCELLED;
|
2015-12-13 21:03:13 +13:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* Extract all strokes to move to this layer
|
|
|
|
* NOTE: We need to do this in a two-pass system to avoid conflicts with strokes
|
|
|
|
* getting repeatedly moved
|
|
|
|
*/
|
|
|
|
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
|
|
|
|
bGPDframe *gpf = gpl->actframe;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* skip if no frame with strokes, or if this is the layer we're moving strokes to */
|
2019-04-22 09:19:45 +10:00
|
|
|
if ((gpl == target_layer) || (gpf == NULL)) {
|
2015-12-13 21:03:13 +13:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* make copies of selected strokes, and deselect these once we're done */
|
2020-03-09 16:27:24 +01:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* skip strokes that are invalid for current view */
|
2019-04-22 09:19:45 +10:00
|
|
|
if (ED_gpencil_stroke_can_use(C, gps) == false) {
|
2015-12-13 21:03:13 +13:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2020-02-17 10:49:27 +01:00
|
|
|
|
|
|
|
/* Check if the color is editable. */
|
2021-01-16 16:44:49 +01:00
|
|
|
if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) {
|
2020-02-17 10:49:27 +01:00
|
|
|
continue;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* TODO: Don't just move entire strokes - instead, only copy the selected portions... */
|
|
|
|
if (gps->flag & GP_STROKE_SELECT) {
|
|
|
|
BLI_remlink(&gpf->strokes, gps);
|
|
|
|
BLI_addtail(&strokes, gps);
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-12 18:14:36 +01:00
|
|
|
/* if new layer and autolock, lock old layer */
|
|
|
|
if ((layer_num == -1) && (use_autolock)) {
|
|
|
|
gpl->flag |= GP_LAYER_LOCKED;
|
|
|
|
}
|
2015-12-13 21:03:13 +13:00
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* Paste them all in one go */
|
|
|
|
if (strokes.first) {
|
2020-03-09 16:27:24 +01:00
|
|
|
bGPDframe *gpf = BKE_gpencil_layer_frame_get(target_layer, CFRA, GP_GETFRAME_ADD_NEW);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
BLI_movelisttolist(&gpf->strokes, &strokes);
|
|
|
|
BLI_assert((strokes.first == strokes.last) && (strokes.first == NULL));
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-12 18:14:36 +01:00
|
|
|
/* back autolock status */
|
|
|
|
if (use_autolock) {
|
|
|
|
gpd->flag |= GP_DATA_AUTOLOCK_LAYERS;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* updates */
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
2015-12-13 21:03:13 +13:00
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_move_to_layer(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Move Strokes to Layer";
|
|
|
|
ot->idname = "GPENCIL_OT_move_to_layer";
|
|
|
|
ot->description =
|
|
|
|
"Move selected strokes to another layer"; /* XXX: allow moving individual points too? */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_move_to_layer_exec;
|
|
|
|
ot->poll = gpencil_stroke_edit_poll; /* XXX? */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-30 13:00:21 +02:00
|
|
|
/* GPencil layer to use. */
|
2020-03-31 18:54:41 +02:00
|
|
|
ot->prop = RNA_def_int(
|
|
|
|
ot->srna, "layer", 0, -1, INT_MAX, "Grease Pencil Layer", "", -1, INT_MAX);
|
2019-11-01 14:30:55 +01:00
|
|
|
RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
2015-12-13 21:03:13 +13:00
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Add Blank Frame Operator
|
|
|
|
* \{ */
|
2017-01-19 02:11:51 +13:00
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_blank_frame_add_exec(bContext *C, wmOperator *op)
|
2017-01-19 02:11:51 +13:00
|
|
|
{
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
2019-07-26 14:13:53 +02:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2019-07-29 17:07:24 +02:00
|
|
|
int cfra = CFRA;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
bGPDlayer *active_gpl = BKE_gpencil_layer_active_get(gpd);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-01-19 13:04:56 +01:00
|
|
|
const bool all_layers = RNA_boolean_get(op->ptr, "all_layers");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-01 12:47:59 +10:00
|
|
|
/* Initialize data-block and an active layer if nothing exists yet. */
|
2017-01-18 15:56:04 +01:00
|
|
|
if (ELEM(NULL, gpd, active_gpl)) {
|
2019-04-22 00:18:34 +10:00
|
|
|
/* Let's just be lazy, and call the "Add New Layer" operator,
|
|
|
|
* which sets everything up as required. */
|
2017-01-19 02:11:51 +13:00
|
|
|
WM_operator_name_call(C, "GPENCIL_OT_layer_add", WM_OP_EXEC_DEFAULT, NULL);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-06-04 09:31:30 +02:00
|
|
|
/* Go through each layer, adding a frame after the active one
|
2017-01-19 02:11:51 +13:00
|
|
|
* and/or shunting all the others out of the way
|
|
|
|
*/
|
|
|
|
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
|
2017-01-19 13:04:56 +01:00
|
|
|
if ((all_layers == false) && (gpl != active_gpl)) {
|
|
|
|
continue;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-01-19 02:11:51 +13:00
|
|
|
/* 1) Check for an existing frame on the current frame */
|
2020-03-09 16:27:24 +01:00
|
|
|
bGPDframe *gpf = BKE_gpencil_layer_frame_find(gpl, cfra);
|
2017-01-19 02:11:51 +13:00
|
|
|
if (gpf) {
|
|
|
|
/* Shunt all frames after (and including) the existing one later by 1-frame */
|
|
|
|
for (; gpf; gpf = gpf->next) {
|
|
|
|
gpf->framenum += 1;
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-01-19 02:11:51 +13:00
|
|
|
/* 2) Now add a new frame, with nothing in it */
|
2020-03-09 16:27:24 +01:00
|
|
|
gpl->actframe = BKE_gpencil_layer_frame_get(gpl, cfra, GP_GETFRAME_ADD_NEW);
|
2017-01-19 02:11:51 +13:00
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-01-19 02:11:51 +13:00
|
|
|
/* notifiers */
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
2017-01-19 02:11:51 +13:00
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-01-19 02:11:51 +13:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_blank_frame_add(wmOperatorType *ot)
|
|
|
|
{
|
2019-12-06 16:30:21 +01:00
|
|
|
PropertyRNA *prop;
|
|
|
|
|
2017-01-19 02:11:51 +13:00
|
|
|
/* identifiers */
|
2017-05-29 10:51:20 +02:00
|
|
|
ot->name = "Insert Blank Frame";
|
2017-01-19 02:11:51 +13:00
|
|
|
ot->idname = "GPENCIL_OT_blank_frame_add";
|
2017-06-16 12:50:24 +02:00
|
|
|
ot->description =
|
|
|
|
"Insert a blank frame on the current frame "
|
2018-08-30 11:06:44 +02:00
|
|
|
"(all subsequently existing frames, if any, are shifted right by one frame)";
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-01-19 02:11:51 +13:00
|
|
|
/* callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_blank_frame_add_exec;
|
2020-06-29 12:49:30 +02:00
|
|
|
ot->poll = gpencil_add_poll;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-01-19 02:11:51 +13:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2019-12-06 16:30:21 +01:00
|
|
|
|
|
|
|
/* properties */
|
|
|
|
prop = RNA_def_boolean(ot->srna,
|
|
|
|
"all_layers",
|
|
|
|
false,
|
|
|
|
"All Layers",
|
|
|
|
"Create blank frame in all layers, not only active");
|
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
2017-01-19 02:11:51 +13:00
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Delete Active Frame Operator
|
|
|
|
* \{ */
|
2009-08-31 01:58:11 +00:00
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static bool gpencil_actframe_delete_poll(bContext *C)
|
2009-08-31 01:58:11 +00:00
|
|
|
{
|
2014-06-14 02:54:17 +10:00
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
2020-03-09 16:27:24 +01:00
|
|
|
bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-08-31 01:58:11 +00:00
|
|
|
/* only if there's an active layer with an active frame */
|
|
|
|
return (gpl && gpl->actframe);
|
|
|
|
}
|
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static bool annotation_actframe_delete_poll(bContext *C)
|
2020-01-07 11:29:42 +01:00
|
|
|
{
|
|
|
|
bGPdata *gpd = ED_annotation_data_get_active(C);
|
2020-03-09 16:27:24 +01:00
|
|
|
bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
|
2020-01-07 11:29:42 +01:00
|
|
|
|
|
|
|
/* only if there's an active layer with an active frame */
|
|
|
|
return (gpl && gpl->actframe);
|
|
|
|
}
|
|
|
|
|
2009-08-31 01:58:11 +00:00
|
|
|
/* delete active frame - wrapper around API calls */
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_actframe_delete_exec(bContext *C, wmOperator *op)
|
2009-08-31 01:58:11 +00:00
|
|
|
{
|
2020-01-07 11:44:51 +01:00
|
|
|
const bool is_annotation = STREQ(op->idname, "GPENCIL_OT_annotation_active_frame_delete");
|
2020-01-07 11:29:42 +01:00
|
|
|
|
|
|
|
bGPdata *gpd = (!is_annotation) ? ED_gpencil_data_get_active(C) :
|
|
|
|
ED_annotation_data_get_active(C);
|
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
|
2018-07-31 10:22:19 +02:00
|
|
|
|
2019-07-26 14:13:53 +02:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2018-07-31 10:22:19 +02:00
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-08-31 01:58:11 +00:00
|
|
|
/* if there's no existing Grease-Pencil data there, add some */
|
|
|
|
if (gpd == NULL) {
|
2012-10-26 17:32:50 +00:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "No grease pencil data");
|
2009-08-31 01:58:11 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2012-03-25 22:35:18 +00:00
|
|
|
if (ELEM(NULL, gpl, gpf)) {
|
2009-08-31 01:58:11 +00:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "No active frame to delete");
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-08-31 01:58:11 +00:00
|
|
|
/* delete it... */
|
2020-03-09 16:27:24 +01:00
|
|
|
BKE_gpencil_layer_frame_delete(gpl, gpf);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-08-31 01:58:11 +00:00
|
|
|
/* notifiers */
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
2012-10-05 19:51:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-08-31 01:58:11 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2012-04-29 17:11:40 +00:00
|
|
|
void GPENCIL_OT_active_frame_delete(wmOperatorType *ot)
|
2009-08-31 01:58:11 +00:00
|
|
|
{
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Delete Active Frame";
|
|
|
|
ot->idname = "GPENCIL_OT_active_frame_delete";
|
2016-06-18 12:58:26 +12:00
|
|
|
ot->description = "Delete the active frame for the active Grease Pencil Layer";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-05-08 18:29:02 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-08-31 01:58:11 +00:00
|
|
|
/* callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_actframe_delete_exec;
|
|
|
|
ot->poll = gpencil_actframe_delete_poll;
|
2009-08-31 01:58:11 +00:00
|
|
|
}
|
|
|
|
|
2020-01-07 11:29:42 +01:00
|
|
|
void GPENCIL_OT_annotation_active_frame_delete(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Delete Active Frame";
|
|
|
|
ot->idname = "GPENCIL_OT_annotation_active_frame_delete";
|
|
|
|
ot->description = "Delete the active frame for the active Annotation Layer";
|
|
|
|
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
|
|
|
|
/* callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_actframe_delete_exec;
|
|
|
|
ot->poll = annotation_actframe_delete_poll;
|
2020-01-07 11:29:42 +01:00
|
|
|
}
|
2020-05-06 12:45:04 +10:00
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Delete All Active Frames
|
|
|
|
* \{ */
|
2016-06-18 12:58:26 +12:00
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static bool gpencil_actframe_delete_all_poll(bContext *C)
|
2016-06-18 12:58:26 +12:00
|
|
|
{
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2016-06-18 12:58:26 +12:00
|
|
|
/* 1) There must be grease pencil data
|
|
|
|
* 2) Hopefully some of the layers have stuff we can use
|
|
|
|
*/
|
|
|
|
return (gpd && gpd->layers.first);
|
|
|
|
}
|
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_actframe_delete_all_exec(bContext *C, wmOperator *op)
|
2016-06-18 12:58:26 +12:00
|
|
|
{
|
2018-07-31 10:22:19 +02:00
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
2019-07-26 14:13:53 +02:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-06-18 12:58:26 +12:00
|
|
|
bool success = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-06-18 12:58:26 +12:00
|
|
|
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
|
|
|
|
/* try to get the "active" frame - but only if it actually occurs on this frame */
|
2020-03-09 16:27:24 +01:00
|
|
|
bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:19:45 +10:00
|
|
|
if (gpf == NULL) {
|
2016-06-18 12:58:26 +12:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-06-18 12:58:26 +12:00
|
|
|
/* delete it... */
|
2020-03-09 16:27:24 +01:00
|
|
|
BKE_gpencil_layer_frame_delete(gpl, gpf);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-06-18 12:58:26 +12:00
|
|
|
/* we successfully modified something */
|
|
|
|
success = true;
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-06-18 12:58:26 +12:00
|
|
|
/* updates */
|
|
|
|
if (success) {
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
2018-06-04 09:31:30 +02:00
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
2016-06-18 12:58:26 +12:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
2020-07-03 14:38:26 +02:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "No active frame(s) to delete");
|
|
|
|
return OPERATOR_CANCELLED;
|
2016-06-18 12:58:26 +12:00
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_active_frames_delete_all(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Delete All Active Frames";
|
|
|
|
ot->idname = "GPENCIL_OT_active_frames_delete_all";
|
|
|
|
ot->description = "Delete the active frame(s) of all editable Grease Pencil layers";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2016-06-18 12:58:26 +12:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2016-06-18 12:58:26 +12:00
|
|
|
/* callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_actframe_delete_all_exec;
|
|
|
|
ot->poll = gpencil_actframe_delete_all_poll;
|
2016-06-18 12:58:26 +12:00
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Delete/Dissolve Utilities
|
|
|
|
* \{ */
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
|
|
|
|
typedef enum eGP_DeleteMode {
|
|
|
|
/* delete selected stroke points */
|
|
|
|
GP_DELETEOP_POINTS = 0,
|
|
|
|
/* delete selected strokes */
|
|
|
|
GP_DELETEOP_STROKES = 1,
|
|
|
|
/* delete active frame */
|
|
|
|
GP_DELETEOP_FRAME = 2,
|
|
|
|
} eGP_DeleteMode;
|
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
typedef enum eGP_DissolveMode {
|
|
|
|
/* dissolve all selected points */
|
|
|
|
GP_DISSOLVE_POINTS = 0,
|
|
|
|
/* dissolve between selected points */
|
|
|
|
GP_DISSOLVE_BETWEEN = 1,
|
|
|
|
/* dissolve unselected points */
|
|
|
|
GP_DISSOLVE_UNSELECT = 2,
|
|
|
|
} eGP_DissolveMode;
|
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
/* Delete selected strokes */
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_delete_selected_strokes(bContext *C)
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
{
|
2018-07-31 10:22:19 +02:00
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
2018-09-25 20:23:55 +02:00
|
|
|
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
bool changed = false;
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
|
2019-06-07 11:46:11 +02:00
|
|
|
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
|
|
|
|
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:19:45 +10:00
|
|
|
if (gpf == NULL) {
|
2018-07-31 10:22:19 +02:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* simply delete strokes which are selected */
|
2020-03-09 16:27:24 +01:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* skip strokes that are invalid for current view */
|
2019-04-22 09:19:45 +10:00
|
|
|
if (ED_gpencil_stroke_can_use(C, gps) == false) {
|
2018-07-31 10:22:19 +02:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* free stroke if selected */
|
|
|
|
if (gps->flag & GP_STROKE_SELECT) {
|
2020-11-13 21:43:00 +01:00
|
|
|
BLI_remlink(&gpf->strokes, gps);
|
2018-07-31 10:22:19 +02:00
|
|
|
/* free stroke memory arrays, then stroke itself */
|
2020-11-13 21:43:00 +01:00
|
|
|
BKE_gpencil_free_stroke(gps);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
}
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
if (changed) {
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
2020-07-03 14:38:26 +02:00
|
|
|
return OPERATOR_CANCELLED;
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
}
|
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* ----------------------------------- */
|
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
static bool gpencil_dissolve_selected_curve_points(bContext *C,
|
|
|
|
bGPdata *gpd,
|
|
|
|
eGP_DissolveMode mode)
|
|
|
|
{
|
|
|
|
bool changed = false;
|
|
|
|
GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc)
|
|
|
|
{
|
|
|
|
if (gpc->flag & GP_CURVE_SELECT) {
|
|
|
|
int first = 0, last = 0;
|
|
|
|
int num_points_remaining = gpc->tot_curve_points;
|
|
|
|
|
|
|
|
switch (mode) {
|
|
|
|
case GP_DISSOLVE_POINTS:
|
|
|
|
for (int i = 0; i < gpc->tot_curve_points; i++) {
|
|
|
|
bGPDcurve_point *cpt = &gpc->curve_points[i];
|
|
|
|
if (cpt->flag & GP_CURVE_POINT_SELECT) {
|
|
|
|
num_points_remaining--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GP_DISSOLVE_BETWEEN:
|
|
|
|
first = -1;
|
|
|
|
for (int i = 0; i < gpc->tot_curve_points; i++) {
|
|
|
|
bGPDcurve_point *cpt = &gpc->curve_points[i];
|
|
|
|
if (cpt->flag & GP_CURVE_POINT_SELECT) {
|
|
|
|
if (first < 0) {
|
|
|
|
first = i;
|
|
|
|
}
|
|
|
|
last = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = first + 1; i < last; i++) {
|
|
|
|
bGPDcurve_point *cpt = &gpc->curve_points[i];
|
|
|
|
if ((cpt->flag & GP_CURVE_POINT_SELECT) == 0) {
|
|
|
|
num_points_remaining--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GP_DISSOLVE_UNSELECT:
|
|
|
|
for (int i = 0; i < gpc->tot_curve_points; i++) {
|
|
|
|
bGPDcurve_point *cpt = &gpc->curve_points[i];
|
|
|
|
if ((cpt->flag & GP_CURVE_POINT_SELECT) == 0) {
|
|
|
|
num_points_remaining--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (num_points_remaining < 1) {
|
|
|
|
/* Delete stroke */
|
|
|
|
BLI_remlink(&gpf_->strokes, gps);
|
|
|
|
BKE_gpencil_free_stroke(gps);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bGPDcurve_point *new_points = MEM_callocN(sizeof(bGPDcurve_point) * num_points_remaining,
|
|
|
|
__func__);
|
|
|
|
|
|
|
|
int idx = 0;
|
|
|
|
switch (mode) {
|
|
|
|
case GP_DISSOLVE_POINTS:
|
|
|
|
for (int i = 0; i < gpc->tot_curve_points; i++) {
|
|
|
|
bGPDcurve_point *cpt = &gpc->curve_points[i];
|
|
|
|
bGPDcurve_point *new_cpt = &new_points[idx];
|
|
|
|
if ((cpt->flag & GP_CURVE_POINT_SELECT) == 0) {
|
|
|
|
*new_cpt = *cpt;
|
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GP_DISSOLVE_BETWEEN:
|
|
|
|
for (int i = 0; i < first; i++) {
|
|
|
|
bGPDcurve_point *cpt = &gpc->curve_points[i];
|
|
|
|
bGPDcurve_point *new_cpt = &new_points[idx];
|
|
|
|
|
|
|
|
*new_cpt = *cpt;
|
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = first; i < last; i++) {
|
|
|
|
bGPDcurve_point *cpt = &gpc->curve_points[i];
|
|
|
|
bGPDcurve_point *new_cpt = &new_points[idx];
|
|
|
|
if (cpt->flag & GP_CURVE_POINT_SELECT) {
|
|
|
|
*new_cpt = *cpt;
|
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = last; i < gpc->tot_curve_points; i++) {
|
|
|
|
bGPDcurve_point *cpt = &gpc->curve_points[i];
|
|
|
|
bGPDcurve_point *new_cpt = &new_points[idx];
|
|
|
|
|
|
|
|
*new_cpt = *cpt;
|
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GP_DISSOLVE_UNSELECT:
|
|
|
|
for (int i = 0; i < gpc->tot_curve_points; i++) {
|
|
|
|
bGPDcurve_point *cpt = &gpc->curve_points[i];
|
|
|
|
bGPDcurve_point *new_cpt = &new_points[idx];
|
|
|
|
if (cpt->flag & GP_CURVE_POINT_SELECT) {
|
|
|
|
*new_cpt = *cpt;
|
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gpc->curve_points != NULL) {
|
|
|
|
MEM_freeN(gpc->curve_points);
|
|
|
|
}
|
|
|
|
|
|
|
|
gpc->curve_points = new_points;
|
|
|
|
gpc->tot_curve_points = num_points_remaining;
|
|
|
|
|
|
|
|
BKE_gpencil_editcurve_recalculate_handles(gps);
|
|
|
|
gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
|
|
|
|
BKE_gpencil_stroke_geometry_update(gpd, gps);
|
|
|
|
}
|
|
|
|
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
GP_EDITABLE_CURVES_END(gps_iter);
|
|
|
|
|
|
|
|
return changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool gpencil_dissolve_selected_stroke_points(bContext *C,
|
|
|
|
bGPdata *gpd,
|
|
|
|
eGP_DissolveMode mode)
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
{
|
|
|
|
bool changed = false;
|
2018-07-31 10:22:19 +02:00
|
|
|
int first = 0;
|
|
|
|
int last = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-02 11:26:38 +02:00
|
|
|
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
|
|
|
|
/* the stroke must have at least one point selected for any operator */
|
|
|
|
if (gps->flag & GP_STROKE_SELECT) {
|
|
|
|
bGPDspoint *pt;
|
|
|
|
MDeformVert *dvert = NULL;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
int tot = gps->totpoints; /* number of points in new buffer */
|
|
|
|
|
|
|
|
/* first pass: count points to remove */
|
|
|
|
switch (mode) {
|
|
|
|
case GP_DISSOLVE_POINTS:
|
|
|
|
/* Count how many points are selected (i.e. how many to remove) */
|
|
|
|
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
|
|
|
if (pt->flag & GP_SPOINT_SELECT) {
|
|
|
|
/* selected point - one of the points to remove */
|
|
|
|
tot--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GP_DISSOLVE_BETWEEN:
|
|
|
|
/* need to find first and last point selected */
|
|
|
|
first = -1;
|
|
|
|
last = 0;
|
|
|
|
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
|
|
|
if (pt->flag & GP_SPOINT_SELECT) {
|
|
|
|
if (first < 0) {
|
|
|
|
first = i;
|
|
|
|
}
|
|
|
|
last = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* count unselected points in the range */
|
|
|
|
for (i = first, pt = gps->points + first; i < last; i++, pt++) {
|
|
|
|
if ((pt->flag & GP_SPOINT_SELECT) == 0) {
|
|
|
|
tot--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GP_DISSOLVE_UNSELECT:
|
|
|
|
/* count number of unselected points */
|
|
|
|
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
|
|
|
if ((pt->flag & GP_SPOINT_SELECT) == 0) {
|
|
|
|
tot--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-02 11:26:38 +02:00
|
|
|
/* if no points are left, we simply delete the entire stroke */
|
|
|
|
if (tot <= 0) {
|
|
|
|
/* remove the entire stroke */
|
2020-11-13 21:43:00 +01:00
|
|
|
BLI_remlink(&gpf_->strokes, gps);
|
|
|
|
BKE_gpencil_free_stroke(gps);
|
2019-08-02 11:26:38 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* just copy all points to keep into a smaller buffer */
|
|
|
|
bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * tot,
|
|
|
|
"new gp stroke points copy");
|
|
|
|
bGPDspoint *npt = new_points;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-02 11:26:38 +02:00
|
|
|
MDeformVert *new_dvert = NULL;
|
|
|
|
MDeformVert *ndvert = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-02 11:26:38 +02:00
|
|
|
if (gps->dvert != NULL) {
|
|
|
|
new_dvert = MEM_callocN(sizeof(MDeformVert) * tot, "new gp stroke weights copy");
|
|
|
|
ndvert = new_dvert;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-02 11:26:38 +02:00
|
|
|
switch (mode) {
|
|
|
|
case GP_DISSOLVE_POINTS:
|
|
|
|
(gps->dvert != NULL) ? dvert = gps->dvert : NULL;
|
|
|
|
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
|
|
|
if ((pt->flag & GP_SPOINT_SELECT) == 0) {
|
|
|
|
*npt = *pt;
|
|
|
|
npt++;
|
|
|
|
|
|
|
|
if (gps->dvert != NULL) {
|
|
|
|
*ndvert = *dvert;
|
|
|
|
ndvert->dw = MEM_dupallocN(dvert->dw);
|
|
|
|
ndvert++;
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
2019-08-02 11:26:38 +02:00
|
|
|
}
|
|
|
|
if (gps->dvert != NULL) {
|
|
|
|
dvert++;
|
|
|
|
}
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
2019-08-02 11:26:38 +02:00
|
|
|
break;
|
|
|
|
case GP_DISSOLVE_BETWEEN:
|
|
|
|
/* copy first segment */
|
|
|
|
(gps->dvert != NULL) ? dvert = gps->dvert : NULL;
|
|
|
|
for (i = 0, pt = gps->points; i < first; i++, pt++) {
|
|
|
|
*npt = *pt;
|
|
|
|
npt++;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-02 11:26:38 +02:00
|
|
|
if (gps->dvert != NULL) {
|
|
|
|
*ndvert = *dvert;
|
|
|
|
ndvert->dw = MEM_dupallocN(dvert->dw);
|
|
|
|
ndvert++;
|
|
|
|
dvert++;
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
2019-08-02 11:26:38 +02:00
|
|
|
}
|
|
|
|
/* copy segment (selected points) */
|
|
|
|
(gps->dvert != NULL) ? dvert = gps->dvert + first : NULL;
|
|
|
|
for (i = first, pt = gps->points + first; i < last; i++, pt++) {
|
|
|
|
if (pt->flag & GP_SPOINT_SELECT) {
|
|
|
|
*npt = *pt;
|
|
|
|
npt++;
|
|
|
|
|
|
|
|
if (gps->dvert != NULL) {
|
|
|
|
*ndvert = *dvert;
|
|
|
|
ndvert->dw = MEM_dupallocN(dvert->dw);
|
|
|
|
ndvert++;
|
|
|
|
}
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
2019-08-02 11:26:38 +02:00
|
|
|
if (gps->dvert != NULL) {
|
|
|
|
dvert++;
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
|
|
|
}
|
2019-08-02 11:26:38 +02:00
|
|
|
/* copy last segment */
|
|
|
|
(gps->dvert != NULL) ? dvert = gps->dvert + last : NULL;
|
|
|
|
for (i = last, pt = gps->points + last; i < gps->totpoints; i++, pt++) {
|
|
|
|
*npt = *pt;
|
|
|
|
npt++;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
if (gps->dvert != NULL) {
|
2019-08-02 11:26:38 +02:00
|
|
|
*ndvert = *dvert;
|
|
|
|
ndvert->dw = MEM_dupallocN(dvert->dw);
|
|
|
|
ndvert++;
|
|
|
|
dvert++;
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
2019-08-02 11:26:38 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-02 11:26:38 +02:00
|
|
|
break;
|
|
|
|
case GP_DISSOLVE_UNSELECT:
|
|
|
|
/* copy any selected point */
|
|
|
|
(gps->dvert != NULL) ? dvert = gps->dvert : NULL;
|
|
|
|
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
|
|
|
if (pt->flag & GP_SPOINT_SELECT) {
|
|
|
|
*npt = *pt;
|
|
|
|
npt++;
|
|
|
|
|
|
|
|
if (gps->dvert != NULL) {
|
|
|
|
*ndvert = *dvert;
|
|
|
|
ndvert->dw = MEM_dupallocN(dvert->dw);
|
|
|
|
ndvert++;
|
|
|
|
}
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
2019-08-02 11:26:38 +02:00
|
|
|
if (gps->dvert != NULL) {
|
|
|
|
dvert++;
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
2019-08-02 11:26:38 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-02 11:26:38 +02:00
|
|
|
/* free the old buffer */
|
|
|
|
if (gps->points) {
|
|
|
|
MEM_freeN(gps->points);
|
|
|
|
}
|
|
|
|
if (gps->dvert) {
|
|
|
|
BKE_gpencil_free_stroke_weights(gps);
|
|
|
|
MEM_freeN(gps->dvert);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-02 11:26:38 +02:00
|
|
|
/* save the new buffer */
|
|
|
|
gps->points = new_points;
|
|
|
|
gps->dvert = new_dvert;
|
|
|
|
gps->totpoints = tot;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
/* Calc geometry data. */
|
2020-11-13 21:43:00 +01:00
|
|
|
BKE_gpencil_stroke_geometry_update(gpd, gps);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-02 11:26:38 +02:00
|
|
|
/* deselect the stroke, since none of its selected points will still be selected */
|
|
|
|
gps->flag &= ~GP_STROKE_SELECT;
|
2021-02-20 10:16:51 +01:00
|
|
|
BKE_gpencil_stroke_select_index_reset(gps);
|
2019-08-02 11:26:38 +02:00
|
|
|
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
|
|
|
pt->flag &= ~GP_SPOINT_SELECT;
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
}
|
2019-08-02 11:26:38 +02:00
|
|
|
|
|
|
|
changed = true;
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
}
|
|
|
|
}
|
2019-08-02 11:26:38 +02:00
|
|
|
GP_EDITABLE_STROKES_END(gpstroke_iter);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
return changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Delete selected points but keep the stroke */
|
|
|
|
static int gpencil_dissolve_selected_points(bContext *C, eGP_DissolveMode mode)
|
|
|
|
{
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
bGPdata *gpd = (bGPdata *)ob->data;
|
|
|
|
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
|
|
|
bool changed = false;
|
|
|
|
|
|
|
|
if (is_curve_edit) {
|
|
|
|
changed = gpencil_dissolve_selected_curve_points(C, gpd, mode);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
changed = gpencil_dissolve_selected_stroke_points(C, gpd, mode);
|
|
|
|
}
|
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
if (changed) {
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
2020-07-03 14:38:26 +02:00
|
|
|
return OPERATOR_CANCELLED;
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
}
|
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* ----------------------------------- */
|
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* Split selected strokes into segments, splitting on selected points */
|
|
|
|
static int gpencil_delete_selected_points(bContext *C)
|
|
|
|
{
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
|
|
|
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
|
|
|
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
|
|
|
|
bool changed = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
|
2019-06-07 11:46:11 +02:00
|
|
|
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
|
|
|
|
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:19:45 +10:00
|
|
|
if (gpf == NULL) {
|
2018-07-31 10:22:19 +02:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* simply delete strokes which are selected */
|
2020-03-09 16:27:24 +01:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* skip strokes that are invalid for current view */
|
2019-04-22 09:19:45 +10:00
|
|
|
if (ED_gpencil_stroke_can_use(C, gps) == false) {
|
2018-07-31 10:22:19 +02:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2018-07-31 10:22:19 +02:00
|
|
|
/* check if the color is editable */
|
2021-01-16 16:44:49 +01:00
|
|
|
if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) {
|
2018-07-31 10:22:19 +02:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
if (gps->flag & GP_STROKE_SELECT) {
|
|
|
|
/* deselect old stroke, since it will be used as template for the new strokes */
|
|
|
|
gps->flag &= ~GP_STROKE_SELECT;
|
2021-02-20 10:16:51 +01:00
|
|
|
BKE_gpencil_stroke_select_index_reset(gps);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (is_curve_edit) {
|
|
|
|
bGPDcurve *gpc = gps->editcurve;
|
2020-11-18 21:30:43 +01:00
|
|
|
BKE_gpencil_curve_delete_tagged_points(
|
2020-11-13 21:43:00 +01:00
|
|
|
gpd, gpf, gps, gps->next, gpc, GP_CURVE_POINT_SELECT);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* delete unwanted points by splitting stroke into several smaller ones */
|
2020-11-18 21:30:43 +01:00
|
|
|
BKE_gpencil_stroke_delete_tagged_points(
|
2020-11-13 21:43:00 +01:00
|
|
|
gpd, gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
changed = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
if (changed) {
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
2020-07-03 14:38:26 +02:00
|
|
|
return OPERATOR_CANCELLED;
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
}
|
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* simple wrapper to external call */
|
2020-06-29 12:49:30 +02:00
|
|
|
int gpencil_delete_selected_point_wrap(bContext *C)
|
2018-07-31 10:22:19 +02:00
|
|
|
{
|
2020-06-29 15:28:38 +02:00
|
|
|
return gpencil_delete_selected_points(C);
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Delete Operator
|
|
|
|
* \{ */
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_delete_exec(bContext *C, wmOperator *op)
|
2014-12-26 20:00:52 +01:00
|
|
|
{
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
eGP_DeleteMode mode = RNA_enum_get(op->ptr, "type");
|
|
|
|
int result = OPERATOR_CANCELLED;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
switch (mode) {
|
|
|
|
case GP_DELETEOP_STROKES: /* selected strokes */
|
2020-06-29 15:28:38 +02:00
|
|
|
result = gpencil_delete_selected_strokes(C);
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
break;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
case GP_DELETEOP_POINTS: /* selected points (breaks the stroke into segments) */
|
2020-06-29 15:28:38 +02:00
|
|
|
result = gpencil_delete_selected_points(C);
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
break;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
case GP_DELETEOP_FRAME: /* active frame */
|
2020-06-29 15:28:38 +02:00
|
|
|
result = gpencil_actframe_delete_exec(C, op);
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
break;
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_delete(wmOperatorType *ot)
|
|
|
|
{
|
2017-10-18 15:07:26 +11:00
|
|
|
static const EnumPropertyItem prop_gpencil_delete_types[] = {
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
{GP_DELETEOP_POINTS,
|
|
|
|
"POINTS",
|
|
|
|
0,
|
|
|
|
"Points",
|
|
|
|
"Delete selected points and split strokes into segments"},
|
|
|
|
{GP_DELETEOP_STROKES, "STROKES", 0, "Strokes", "Delete selected strokes"},
|
|
|
|
{GP_DELETEOP_FRAME, "FRAME", 0, "Frame", "Delete active frame"},
|
2019-02-03 14:01:45 +11:00
|
|
|
{0, NULL, 0, NULL, NULL},
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
/* identifiers */
|
2016-08-03 23:31:48 +02:00
|
|
|
ot->name = "Delete";
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
ot->idname = "GPENCIL_OT_delete";
|
|
|
|
ot->description = "Delete selected Grease Pencil strokes, vertices, or frames";
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
/* callbacks */
|
|
|
|
ot->invoke = WM_menu_invoke;
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_delete_exec;
|
|
|
|
ot->poll = gpencil_stroke_edit_poll;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
/* props */
|
|
|
|
ot->prop = RNA_def_enum(ot->srna,
|
|
|
|
"type",
|
|
|
|
prop_gpencil_delete_types,
|
|
|
|
0,
|
|
|
|
"Type",
|
|
|
|
"Method used for deleting Grease Pencil data");
|
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Dissolve Operator
|
|
|
|
* \{ */
|
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_dissolve_exec(bContext *C, wmOperator *op)
|
2015-07-05 14:34:17 +10:00
|
|
|
{
|
2018-07-31 10:22:19 +02:00
|
|
|
eGP_DissolveMode mode = RNA_enum_get(op->ptr, "type");
|
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
return gpencil_dissolve_selected_points(C, mode);
|
2015-07-05 14:34:17 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_dissolve(wmOperatorType *ot)
|
|
|
|
{
|
2018-07-31 10:22:19 +02:00
|
|
|
static EnumPropertyItem prop_gpencil_dissolve_types[] = {
|
2018-11-10 09:24:23 +11:00
|
|
|
{GP_DISSOLVE_POINTS, "POINTS", 0, "Dissolve", "Dissolve selected points"},
|
|
|
|
{GP_DISSOLVE_BETWEEN,
|
|
|
|
"BETWEEN",
|
|
|
|
0,
|
|
|
|
"Dissolve Between",
|
|
|
|
"Dissolve points between selected points"},
|
|
|
|
{GP_DISSOLVE_UNSELECT, "UNSELECT", 0, "Dissolve Unselect", "Dissolve all unselected points"},
|
2019-02-03 14:01:45 +11:00
|
|
|
{0, NULL, 0, NULL, NULL},
|
2018-07-31 10:22:19 +02:00
|
|
|
};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-07-05 14:34:17 +10:00
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Dissolve";
|
|
|
|
ot->idname = "GPENCIL_OT_dissolve";
|
|
|
|
ot->description = "Delete selected points without splitting strokes";
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-07-05 14:34:17 +10:00
|
|
|
/* callbacks */
|
2018-07-31 10:22:19 +02:00
|
|
|
ot->invoke = WM_menu_invoke;
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_dissolve_exec;
|
|
|
|
ot->poll = gpencil_stroke_edit_poll;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-07-05 14:34:17 +10:00
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* props */
|
2018-12-23 21:58:59 +01:00
|
|
|
ot->prop = RNA_def_enum(ot->srna,
|
|
|
|
"type",
|
|
|
|
prop_gpencil_dissolve_types,
|
|
|
|
0,
|
|
|
|
"Type",
|
2020-12-24 11:07:32 -06:00
|
|
|
"Method used for dissolving stroke points");
|
2015-07-05 14:34:17 +10:00
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Snapping Selection to Grid Operator
|
|
|
|
* \{ */
|
2015-12-13 21:03:13 +13:00
|
|
|
|
|
|
|
/* Poll callback for snap operators */
|
|
|
|
/* NOTE: For now, we only allow these in the 3D view, as other editors do not
|
|
|
|
* define a cursor or gridstep which can be used
|
|
|
|
*/
|
2020-06-29 15:28:38 +02:00
|
|
|
static bool gpencil_snap_poll(bContext *C)
|
2015-12-13 21:03:13 +13:00
|
|
|
{
|
2020-04-03 13:25:03 +02:00
|
|
|
ScrArea *area = CTX_wm_area(C);
|
2020-03-17 17:09:20 +01:00
|
|
|
Object *ob = CTX_data_active_object(C);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-03-17 17:09:20 +01:00
|
|
|
return (ob != NULL) && (ob->type == OB_GPENCIL) &&
|
2020-04-03 13:25:03 +02:00
|
|
|
((area != NULL) && (area->spacetype == SPACE_VIEW3D));
|
2015-12-13 21:03:13 +13:00
|
|
|
}
|
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_snap_to_grid(bContext *C, wmOperator *UNUSED(op))
|
2015-12-13 21:03:13 +13:00
|
|
|
{
|
2016-08-26 19:54:16 +12:00
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
2020-11-02 16:13:51 -03:00
|
|
|
ARegion *region = CTX_wm_region(C);
|
2018-08-27 11:40:48 -03:00
|
|
|
View3D *v3d = CTX_wm_view3d(C);
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
2019-07-25 16:36:22 +02:00
|
|
|
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
2018-07-31 10:22:19 +02:00
|
|
|
Object *obact = CTX_data_active_object(C);
|
2020-11-02 16:13:51 -03:00
|
|
|
const float gridf = ED_view3d_grid_view_scale(scene, v3d, region, NULL);
|
2020-11-13 21:43:00 +01:00
|
|
|
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
bool changed = false;
|
2020-03-09 16:27:24 +01:00
|
|
|
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
2016-08-03 23:31:48 +02:00
|
|
|
/* only editable and visible layers are considered */
|
2020-03-09 16:27:24 +01:00
|
|
|
if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
|
2016-08-26 19:54:16 +12:00
|
|
|
bGPDframe *gpf = gpl->actframe;
|
|
|
|
float diff_mat[4][4];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* calculate difference matrix object */
|
2021-01-16 15:33:38 +01:00
|
|
|
BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
2016-08-03 23:31:48 +02:00
|
|
|
/* skip strokes that are invalid for current view */
|
2019-04-22 09:19:45 +10:00
|
|
|
if (ED_gpencil_stroke_can_use(C, gps) == false) {
|
2016-08-03 23:31:48 +02:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2016-08-03 23:31:48 +02:00
|
|
|
/* check if the color is editable */
|
2021-01-16 16:44:49 +01:00
|
|
|
if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) {
|
2016-08-03 23:31:48 +02:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (is_curve_edit) {
|
|
|
|
if (gps->editcurve == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
float inv_diff_mat[4][4];
|
|
|
|
invert_m4_m4_safe(inv_diff_mat, diff_mat);
|
|
|
|
|
|
|
|
bGPDcurve *gpc = gps->editcurve;
|
|
|
|
for (int i = 0; i < gpc->tot_curve_points; i++) {
|
|
|
|
bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
|
|
|
|
BezTriple *bezt = &gpc_pt->bezt;
|
|
|
|
if (gpc_pt->flag & GP_CURVE_POINT_SELECT) {
|
|
|
|
float tmp0[3], tmp1[3], tmp2[3], offset[3];
|
|
|
|
mul_v3_m4v3(tmp0, diff_mat, bezt->vec[0]);
|
|
|
|
mul_v3_m4v3(tmp1, diff_mat, bezt->vec[1]);
|
|
|
|
mul_v3_m4v3(tmp2, diff_mat, bezt->vec[2]);
|
|
|
|
|
|
|
|
/* calculate the offset vector */
|
|
|
|
offset[0] = gridf * floorf(0.5f + tmp1[0] / gridf) - tmp1[0];
|
|
|
|
offset[1] = gridf * floorf(0.5f + tmp1[1] / gridf) - tmp1[1];
|
|
|
|
offset[2] = gridf * floorf(0.5f + tmp1[2] / gridf) - tmp1[2];
|
|
|
|
|
|
|
|
/* shift bezTriple */
|
|
|
|
add_v3_v3(bezt->vec[0], offset);
|
|
|
|
add_v3_v3(bezt->vec[1], offset);
|
|
|
|
add_v3_v3(bezt->vec[2], offset);
|
|
|
|
|
|
|
|
mul_v3_m4v3(tmp0, inv_diff_mat, bezt->vec[0]);
|
|
|
|
mul_v3_m4v3(tmp1, inv_diff_mat, bezt->vec[1]);
|
|
|
|
mul_v3_m4v3(tmp2, inv_diff_mat, bezt->vec[2]);
|
|
|
|
copy_v3_v3(bezt->vec[0], tmp0);
|
|
|
|
copy_v3_v3(bezt->vec[1], tmp1);
|
|
|
|
copy_v3_v3(bezt->vec[2], tmp2);
|
|
|
|
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (changed) {
|
|
|
|
BKE_gpencil_editcurve_recalculate_handles(gps);
|
|
|
|
gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
|
|
|
|
BKE_gpencil_stroke_geometry_update(gpd, gps);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* TODO: if entire stroke is selected, offset entire stroke by same amount? */
|
|
|
|
for (int i = 0; i < gps->totpoints; i++) {
|
|
|
|
bGPDspoint *pt = &gps->points[i];
|
|
|
|
/* only if point is selected */
|
|
|
|
if (pt->flag & GP_SPOINT_SELECT) {
|
|
|
|
/* apply parent transformations */
|
|
|
|
float fpt[3];
|
|
|
|
mul_v3_m4v3(fpt, diff_mat, &pt->x);
|
|
|
|
|
|
|
|
fpt[0] = gridf * floorf(0.5f + fpt[0] / gridf);
|
|
|
|
fpt[1] = gridf * floorf(0.5f + fpt[1] / gridf);
|
|
|
|
fpt[2] = gridf * floorf(0.5f + fpt[2] / gridf);
|
|
|
|
|
|
|
|
/* return data */
|
|
|
|
copy_v3_v3(&pt->x, fpt);
|
|
|
|
gpencil_apply_parent_point(depsgraph, obact, gpl, pt);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
changed = true;
|
|
|
|
}
|
2016-08-03 23:31:48 +02:00
|
|
|
}
|
|
|
|
}
|
2015-12-13 21:03:13 +13:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (changed) {
|
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
|
|
|
DEG_id_tag_update(&obact->id, ID_RECALC_COPY_ON_WRITE);
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
|
|
|
}
|
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_snap_to_grid(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Snap Selection to Grid";
|
|
|
|
ot->idname = "GPENCIL_OT_snap_to_grid";
|
|
|
|
ot->description = "Snap selected points to the nearest grid points";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_snap_to_grid;
|
|
|
|
ot->poll = gpencil_snap_poll;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Snapping Selection to Cursor Operator
|
|
|
|
* \{ */
|
2015-12-13 21:03:13 +13:00
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_snap_to_cursor(bContext *C, wmOperator *op)
|
2015-12-13 21:03:13 +13:00
|
|
|
{
|
2016-08-26 19:54:16 +12:00
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
2020-11-13 21:43:00 +01:00
|
|
|
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
2015-12-13 21:03:13 +13:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2019-07-25 16:36:22 +02:00
|
|
|
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
2018-10-12 10:35:49 +11:00
|
|
|
Object *obact = CTX_data_active_object(C);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-12 10:35:49 +11:00
|
|
|
const bool use_offset = RNA_boolean_get(op->ptr, "use_offset");
|
2018-11-26 13:49:17 +11:00
|
|
|
const float *cursor_global = scene->cursor.location;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
bool changed = false;
|
|
|
|
if (is_curve_edit) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "Not implemented!");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
|
|
|
/* only editable and visible layers are considered */
|
|
|
|
if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
|
|
|
|
bGPDframe *gpf = gpl->actframe;
|
|
|
|
float diff_mat[4][4];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* calculate difference matrix */
|
2021-01-16 15:33:38 +01:00
|
|
|
BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
|
|
|
bGPDspoint *pt;
|
|
|
|
int i;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* skip strokes that are invalid for current view */
|
|
|
|
if (ED_gpencil_stroke_can_use(C, gps) == false) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* check if the color is editable */
|
2021-01-16 16:44:49 +01:00
|
|
|
if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) {
|
2020-11-13 21:43:00 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* only continue if this stroke is selected (editable doesn't guarantee this)... */
|
|
|
|
if ((gps->flag & GP_STROKE_SELECT) == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (use_offset) {
|
|
|
|
float offset[3];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* compute offset from first point of stroke to cursor */
|
|
|
|
/* TODO: Allow using midpoint instead? */
|
|
|
|
sub_v3_v3v3(offset, cursor_global, &gps->points->x);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* apply offset to all points in the stroke */
|
|
|
|
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
|
|
|
add_v3_v3(&pt->x, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
changed = true;
|
2016-08-03 23:31:48 +02:00
|
|
|
}
|
2020-11-13 21:43:00 +01:00
|
|
|
else {
|
|
|
|
/* affect each selected point */
|
|
|
|
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
|
|
|
if (pt->flag & GP_SPOINT_SELECT) {
|
|
|
|
copy_v3_v3(&pt->x, cursor_global);
|
|
|
|
gpencil_apply_parent_point(depsgraph, obact, gpl, pt);
|
|
|
|
|
|
|
|
changed = true;
|
|
|
|
}
|
2016-08-03 23:31:48 +02:00
|
|
|
}
|
2015-12-13 21:03:13 +13:00
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2015-12-13 21:03:13 +13:00
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (changed) {
|
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
|
|
|
DEG_id_tag_update(&obact->id, ID_RECALC_COPY_ON_WRITE);
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
|
|
|
}
|
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_snap_to_cursor(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Snap Selection to Cursor";
|
|
|
|
ot->idname = "GPENCIL_OT_snap_to_cursor";
|
|
|
|
ot->description = "Snap selected points/strokes to the cursor";
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_snap_to_cursor;
|
|
|
|
ot->poll = gpencil_snap_poll;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* props */
|
2019-03-15 08:53:22 +11:00
|
|
|
ot->prop = RNA_def_boolean(ot->srna,
|
|
|
|
"use_offset",
|
|
|
|
true,
|
|
|
|
"With Offset",
|
|
|
|
"Offset the entire stroke instead of selected points only");
|
2015-12-13 21:03:13 +13:00
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Snapping Cursor to Selection Operator
|
|
|
|
* \{ */
|
2015-12-13 21:03:13 +13:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
static bool gpencil_stroke_points_centroid(Depsgraph *depsgraph,
|
|
|
|
bContext *C,
|
|
|
|
Object *obact,
|
|
|
|
bGPdata *gpd,
|
|
|
|
float r_centroid[3],
|
|
|
|
float r_min[3],
|
|
|
|
float r_max[3],
|
|
|
|
size_t *count)
|
2015-12-13 21:03:13 +13:00
|
|
|
{
|
2020-11-13 21:43:00 +01:00
|
|
|
bool changed = false;
|
2015-12-13 21:03:13 +13:00
|
|
|
/* calculate midpoints from selected points */
|
2020-03-09 16:27:24 +01:00
|
|
|
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
2016-08-03 23:31:48 +02:00
|
|
|
/* only editable and visible layers are considered */
|
2020-03-09 16:27:24 +01:00
|
|
|
if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
|
2016-08-26 19:54:16 +12:00
|
|
|
bGPDframe *gpf = gpl->actframe;
|
|
|
|
float diff_mat[4][4];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* calculate difference matrix */
|
2021-01-16 15:33:38 +01:00
|
|
|
BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
2016-08-26 19:54:16 +12:00
|
|
|
bGPDspoint *pt;
|
|
|
|
int i;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-03 23:31:48 +02:00
|
|
|
/* skip strokes that are invalid for current view */
|
2019-04-22 09:19:45 +10:00
|
|
|
if (ED_gpencil_stroke_can_use(C, gps) == false) {
|
2016-08-03 23:31:48 +02:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2016-08-03 23:31:48 +02:00
|
|
|
/* check if the color is editable */
|
2021-01-16 16:44:49 +01:00
|
|
|
if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) {
|
2016-08-03 23:31:48 +02:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2016-08-03 23:31:48 +02:00
|
|
|
/* only continue if this stroke is selected (editable doesn't guarantee this)... */
|
2019-04-22 09:19:45 +10:00
|
|
|
if ((gps->flag & GP_STROKE_SELECT) == 0) {
|
2016-08-03 23:31:48 +02:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-03 23:31:48 +02:00
|
|
|
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
|
|
|
if (pt->flag & GP_SPOINT_SELECT) {
|
2018-07-31 10:22:19 +02:00
|
|
|
/* apply parent transformations */
|
|
|
|
float fpt[3];
|
|
|
|
mul_v3_m4v3(fpt, diff_mat, &pt->x);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
add_v3_v3(r_centroid, fpt);
|
|
|
|
minmax_v3v3_v3(r_min, r_max, fpt);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
(*count)++;
|
2016-08-03 23:31:48 +02:00
|
|
|
}
|
2015-12-13 21:03:13 +13:00
|
|
|
}
|
2020-11-13 21:43:00 +01:00
|
|
|
|
|
|
|
changed = true;
|
2015-12-13 21:03:13 +13:00
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
return changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int gpencil_snap_cursor_to_sel(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
|
|
|
Object *obact = CTX_data_active_object(C);
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
|
|
|
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
|
|
|
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
|
|
|
|
float *cursor = scene->cursor.location;
|
|
|
|
float centroid[3] = {0.0f};
|
|
|
|
float min[3], max[3];
|
|
|
|
size_t count = 0;
|
|
|
|
|
|
|
|
INIT_MINMAX(min, max);
|
|
|
|
|
|
|
|
bool changed = false;
|
|
|
|
if (is_curve_edit) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "Not implemented!");
|
2015-12-13 21:03:13 +13:00
|
|
|
}
|
2020-11-13 21:43:00 +01:00
|
|
|
else {
|
|
|
|
changed = gpencil_stroke_points_centroid(depsgraph, C, obact, gpd, centroid, min, max, &count);
|
2020-06-23 18:31:10 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (changed) {
|
|
|
|
if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_BOUNDS) {
|
|
|
|
mid_v3_v3v3(cursor, min, max);
|
|
|
|
}
|
|
|
|
else { /* #V3D_AROUND_CENTER_MEDIAN. */
|
|
|
|
zero_v3(cursor);
|
|
|
|
if (count) {
|
|
|
|
mul_v3_fl(centroid, 1.0f / (float)count);
|
|
|
|
copy_v3_v3(cursor, centroid);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
|
2021-03-11 17:30:39 +01:00
|
|
|
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
2020-11-13 21:43:00 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_snap_cursor_to_selected(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Snap Cursor to Selected Points";
|
|
|
|
ot->idname = "GPENCIL_OT_snap_cursor_to_selected";
|
|
|
|
ot->description = "Snap cursor to center of selected points";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_snap_cursor_to_sel;
|
|
|
|
ot->poll = gpencil_snap_poll;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2015-12-13 21:03:13 +13:00
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Apply Layer Thickness Change to Strokes Operator
|
|
|
|
* \{ */
|
2016-08-26 16:25:39 +12:00
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_stroke_apply_thickness_exec(bContext *C, wmOperator *UNUSED(op))
|
2016-08-26 16:25:39 +12:00
|
|
|
{
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
2020-03-09 16:27:24 +01:00
|
|
|
bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
/* sanity checks */
|
2019-04-22 09:19:45 +10:00
|
|
|
if (ELEM(NULL, gpd, gpl, gpl->frames.first)) {
|
2016-08-26 16:25:39 +12:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
/* loop all strokes */
|
2020-03-09 16:27:24 +01:00
|
|
|
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
|
|
|
|
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
2016-08-26 16:25:39 +12:00
|
|
|
/* Apply thickness */
|
2018-07-31 10:22:19 +02:00
|
|
|
if ((gps->thickness == 0) && (gpl->line_change == 0)) {
|
|
|
|
gps->thickness = gpl->thickness;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
gps->thickness = gps->thickness + gpl->line_change;
|
|
|
|
}
|
2016-08-26 16:25:39 +12:00
|
|
|
}
|
|
|
|
}
|
2020-11-13 21:43:00 +01:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
/* clear value */
|
|
|
|
gpl->thickness = 0.0f;
|
2018-07-31 10:22:19 +02:00
|
|
|
gpl->line_change = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
/* notifiers */
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
2016-08-26 16:25:39 +12:00
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_stroke_apply_thickness(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Apply Stroke Thickness";
|
|
|
|
ot->idname = "GPENCIL_OT_stroke_apply_thickness";
|
|
|
|
ot->description = "Apply the thickness change of the layer to its strokes";
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
/* api callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_stroke_apply_thickness_exec;
|
2020-06-29 12:49:30 +02:00
|
|
|
ot->poll = gpencil_active_layer_poll;
|
2016-08-26 16:25:39 +12:00
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Stroke Toggle Cyclic Operator
|
|
|
|
* \{ */
|
2016-08-26 16:25:39 +12:00
|
|
|
|
|
|
|
enum {
|
|
|
|
GP_STROKE_CYCLIC_CLOSE = 1,
|
|
|
|
GP_STROKE_CYCLIC_OPEN = 2,
|
2019-01-15 23:57:49 +11:00
|
|
|
GP_STROKE_CYCLIC_TOGGLE = 3,
|
2016-08-26 16:25:39 +12:00
|
|
|
};
|
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_stroke_cyclical_set_exec(bContext *C, wmOperator *op)
|
2016-08-26 16:25:39 +12:00
|
|
|
{
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
2018-07-31 10:22:19 +02:00
|
|
|
Object *ob = CTX_data_active_object(C);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
const int type = RNA_enum_get(op->ptr, "type");
|
2019-06-30 21:03:24 +02:00
|
|
|
const bool geometry = RNA_boolean_get(op->ptr, "geometry");
|
|
|
|
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
|
2020-11-13 21:43:00 +01:00
|
|
|
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
2019-06-30 21:03:24 +02:00
|
|
|
bGPDstroke *gps = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
/* sanity checks */
|
2019-04-22 09:19:45 +10:00
|
|
|
if (ELEM(NULL, gpd)) {
|
2016-08-26 16:25:39 +12:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
bool changed = false;
|
2016-08-26 16:25:39 +12:00
|
|
|
/* loop all selected strokes */
|
|
|
|
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
|
2019-06-30 21:03:24 +02:00
|
|
|
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-06-30 21:03:24 +02:00
|
|
|
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
|
|
|
|
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
|
|
|
|
if (gpf == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-06-30 21:03:24 +02:00
|
|
|
for (gps = gpf->strokes.first; gps; gps = gps->next) {
|
2020-02-05 11:23:58 +01:00
|
|
|
MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
|
2019-06-30 21:03:24 +02:00
|
|
|
/* skip strokes that are not selected or invalid for current view */
|
|
|
|
if (((gps->flag & GP_STROKE_SELECT) == 0) ||
|
|
|
|
ED_gpencil_stroke_can_use(C, gps) == false) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* skip hidden or locked colors */
|
2020-03-09 16:27:24 +01:00
|
|
|
if (!gp_style || (gp_style->flag & GP_MATERIAL_HIDE) ||
|
|
|
|
(gp_style->flag & GP_MATERIAL_LOCKED)) {
|
2019-06-30 21:03:24 +02:00
|
|
|
continue;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
bool before = (bool)(gps->flag & GP_STROKE_CYCLIC);
|
2019-06-30 21:03:24 +02:00
|
|
|
switch (type) {
|
|
|
|
case GP_STROKE_CYCLIC_CLOSE:
|
|
|
|
/* Close all (enable) */
|
|
|
|
gps->flag |= GP_STROKE_CYCLIC;
|
|
|
|
break;
|
|
|
|
case GP_STROKE_CYCLIC_OPEN:
|
|
|
|
/* Open all (disable) */
|
|
|
|
gps->flag &= ~GP_STROKE_CYCLIC;
|
|
|
|
break;
|
|
|
|
case GP_STROKE_CYCLIC_TOGGLE:
|
|
|
|
/* Just toggle flag... */
|
|
|
|
gps->flag ^= GP_STROKE_CYCLIC;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
BLI_assert(0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (before != (gps->flag & GP_STROKE_CYCLIC)) {
|
|
|
|
/* Create new geometry. */
|
|
|
|
if (is_curve_edit) {
|
|
|
|
BKE_gpencil_editcurve_recalculate_handles(gps);
|
|
|
|
gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
|
|
|
|
BKE_gpencil_stroke_geometry_update(gpd, gps);
|
|
|
|
}
|
|
|
|
else if ((gps->flag & GP_STROKE_CYCLIC) && geometry) {
|
|
|
|
BKE_gpencil_stroke_close(gps);
|
|
|
|
BKE_gpencil_stroke_geometry_update(gpd, gps);
|
|
|
|
}
|
|
|
|
|
|
|
|
changed = true;
|
2019-06-30 21:03:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if not multiedit, exit loop*/
|
|
|
|
if (!is_multiedit) {
|
2016-08-26 16:25:39 +12:00
|
|
|
break;
|
2019-06-30 21:03:24 +02:00
|
|
|
}
|
2016-08-26 16:25:39 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (changed) {
|
|
|
|
/* notifiers */
|
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
static bool gpencil_cyclical_set_curve_edit_poll_property(const bContext *C,
|
|
|
|
wmOperator *UNUSED(op),
|
|
|
|
const PropertyRNA *prop)
|
|
|
|
{
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
|
|
|
if (gpd != NULL && GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)) {
|
|
|
|
const char *prop_id = RNA_property_identifier(prop);
|
|
|
|
/* Only show type in curve edit mode */
|
|
|
|
if (!STREQ(prop_id, "type")) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
/**
|
|
|
|
* Similar to #CURVE_OT_cyclic_toggle or #MASK_OT_cyclic_toggle, but with
|
|
|
|
* option to force opened/closed strokes instead of just toggle behavior.
|
|
|
|
*/
|
|
|
|
void GPENCIL_OT_stroke_cyclical_set(wmOperatorType *ot)
|
|
|
|
{
|
2019-06-30 21:03:24 +02:00
|
|
|
PropertyRNA *prop;
|
|
|
|
|
2017-10-18 15:07:26 +11:00
|
|
|
static const EnumPropertyItem cyclic_type[] = {
|
2020-10-24 11:42:17 -07:00
|
|
|
{GP_STROKE_CYCLIC_CLOSE, "CLOSE", 0, "Close All", ""},
|
|
|
|
{GP_STROKE_CYCLIC_OPEN, "OPEN", 0, "Open All", ""},
|
2016-08-26 16:25:39 +12:00
|
|
|
{GP_STROKE_CYCLIC_TOGGLE, "TOGGLE", 0, "Toggle", ""},
|
2019-02-03 14:01:45 +11:00
|
|
|
{0, NULL, 0, NULL, NULL},
|
2016-08-26 16:25:39 +12:00
|
|
|
};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Set Cyclical State";
|
|
|
|
ot->idname = "GPENCIL_OT_stroke_cyclical_set";
|
|
|
|
ot->description = "Close or open the selected stroke adding an edge from last to first point";
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
/* api callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_stroke_cyclical_set_exec;
|
2020-06-29 12:49:30 +02:00
|
|
|
ot->poll = gpencil_active_layer_poll;
|
2020-11-13 21:43:00 +01:00
|
|
|
ot->poll_property = gpencil_cyclical_set_curve_edit_poll_property;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 19:54:16 +12:00
|
|
|
/* properties */
|
2016-08-26 16:25:39 +12:00
|
|
|
ot->prop = RNA_def_enum(ot->srna, "type", cyclic_type, GP_STROKE_CYCLIC_TOGGLE, "Type", "");
|
2019-06-30 21:03:24 +02:00
|
|
|
prop = RNA_def_boolean(
|
|
|
|
ot->srna, "geometry", false, "Create Geometry", "Create new geometry for closing stroke");
|
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
2016-08-26 16:25:39 +12:00
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Stroke Toggle Flat Caps Operator
|
|
|
|
* \{ */
|
2019-01-11 19:15:23 +01:00
|
|
|
|
|
|
|
enum {
|
|
|
|
GP_STROKE_CAPS_TOGGLE_BOTH = 0,
|
|
|
|
GP_STROKE_CAPS_TOGGLE_START = 1,
|
|
|
|
GP_STROKE_CAPS_TOGGLE_END = 2,
|
2019-01-15 23:57:49 +11:00
|
|
|
GP_STROKE_CAPS_TOGGLE_DEFAULT = 3,
|
2019-01-11 19:15:23 +01:00
|
|
|
};
|
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_stroke_caps_set_exec(bContext *C, wmOperator *op)
|
2019-01-11 19:15:23 +01:00
|
|
|
{
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
const int type = RNA_enum_get(op->ptr, "type");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
/* sanity checks */
|
2019-04-22 09:19:45 +10:00
|
|
|
if (ELEM(NULL, gpd)) {
|
2019-01-11 19:15:23 +01:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
bool changed = false;
|
2019-01-11 19:15:23 +01:00
|
|
|
/* loop all selected strokes */
|
|
|
|
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
|
2019-04-22 09:19:45 +10:00
|
|
|
if (gpl->actframe == NULL) {
|
2019-01-11 19:15:23 +01:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
|
2020-02-05 11:23:58 +01:00
|
|
|
MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
/* skip strokes that are not selected or invalid for current view */
|
2019-01-15 08:47:04 +11:00
|
|
|
if (((gps->flag & GP_STROKE_SELECT) == 0) || (ED_gpencil_stroke_can_use(C, gps) == false)) {
|
2019-01-11 19:15:23 +01:00
|
|
|
continue;
|
2019-01-15 08:47:04 +11:00
|
|
|
}
|
2019-01-11 19:15:23 +01:00
|
|
|
/* skip hidden or locked colors */
|
2020-03-09 16:27:24 +01:00
|
|
|
if (!gp_style || (gp_style->flag & GP_MATERIAL_HIDE) ||
|
|
|
|
(gp_style->flag & GP_MATERIAL_LOCKED)) {
|
2019-01-11 19:15:23 +01:00
|
|
|
continue;
|
2019-01-15 08:47:04 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
short prev_first = gps->caps[0];
|
|
|
|
short prev_last = gps->caps[1];
|
|
|
|
|
2020-11-06 12:30:59 +11:00
|
|
|
if (ELEM(type, GP_STROKE_CAPS_TOGGLE_BOTH, GP_STROKE_CAPS_TOGGLE_START)) {
|
2019-01-11 19:15:23 +01:00
|
|
|
++gps->caps[0];
|
|
|
|
if (gps->caps[0] >= GP_STROKE_CAP_MAX) {
|
|
|
|
gps->caps[0] = GP_STROKE_CAP_ROUND;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-01-11 19:15:23 +01:00
|
|
|
}
|
2020-11-06 12:30:59 +11:00
|
|
|
if (ELEM(type, GP_STROKE_CAPS_TOGGLE_BOTH, GP_STROKE_CAPS_TOGGLE_END)) {
|
2019-01-11 19:15:23 +01:00
|
|
|
++gps->caps[1];
|
|
|
|
if (gps->caps[1] >= GP_STROKE_CAP_MAX) {
|
|
|
|
gps->caps[1] = GP_STROKE_CAP_ROUND;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-01-11 19:15:23 +01:00
|
|
|
}
|
|
|
|
if (type == GP_STROKE_CAPS_TOGGLE_DEFAULT) {
|
|
|
|
gps->caps[0] = GP_STROKE_CAP_ROUND;
|
|
|
|
gps->caps[1] = GP_STROKE_CAP_ROUND;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2020-11-13 21:43:00 +01:00
|
|
|
|
|
|
|
if (prev_first != gps->caps[0] || prev_last != gps->caps[1]) {
|
|
|
|
changed = true;
|
|
|
|
}
|
2019-01-11 19:15:23 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (changed) {
|
|
|
|
/* notifiers */
|
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Change Stroke caps mode Rounded or Flat
|
|
|
|
*/
|
|
|
|
void GPENCIL_OT_stroke_caps_set(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
static const EnumPropertyItem toggle_type[] = {
|
|
|
|
{GP_STROKE_CAPS_TOGGLE_BOTH, "TOGGLE", 0, "Both", ""},
|
|
|
|
{GP_STROKE_CAPS_TOGGLE_START, "START", 0, "Start", ""},
|
|
|
|
{GP_STROKE_CAPS_TOGGLE_END, "END", 0, "End", ""},
|
|
|
|
{GP_STROKE_CAPS_TOGGLE_DEFAULT, "TOGGLE", 0, "Default", "Set as default rounded"},
|
2019-02-03 14:01:45 +11:00
|
|
|
{0, NULL, 0, NULL, NULL},
|
2019-01-11 19:15:23 +01:00
|
|
|
};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Set Caps Mode";
|
|
|
|
ot->idname = "GPENCIL_OT_stroke_caps_set";
|
2020-12-24 11:07:32 -06:00
|
|
|
ot->description = "Change stroke caps mode (rounded or flat)";
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
/* api callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_stroke_caps_set_exec;
|
2020-06-29 12:49:30 +02:00
|
|
|
ot->poll = gpencil_active_layer_poll;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
/* properties */
|
|
|
|
ot->prop = RNA_def_enum(ot->srna, "type", toggle_type, GP_STROKE_CAPS_TOGGLE_BOTH, "Type", "");
|
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Stroke Join Operator
|
|
|
|
* \{ */
|
2016-08-26 16:25:39 +12:00
|
|
|
|
2020-10-29 20:05:49 +01:00
|
|
|
typedef struct tJoinStrokes {
|
|
|
|
bGPDframe *gpf;
|
|
|
|
bGPDstroke *gps;
|
|
|
|
bool used;
|
|
|
|
} tJoinStrokes;
|
|
|
|
|
|
|
|
static int gpencil_get_nearest_stroke_index(tJoinStrokes *strokes_list,
|
|
|
|
const bGPDstroke *gps,
|
|
|
|
const int totstrokes)
|
|
|
|
{
|
|
|
|
int index = -1;
|
|
|
|
float min_dist = FLT_MAX;
|
|
|
|
float dist, start_a[3], end_a[3], start_b[3], end_b[3];
|
|
|
|
|
|
|
|
bGPDspoint *pt = &gps->points[0];
|
|
|
|
copy_v3_v3(start_a, &pt->x);
|
|
|
|
|
|
|
|
pt = &gps->points[gps->totpoints - 1];
|
|
|
|
copy_v3_v3(end_a, &pt->x);
|
|
|
|
|
|
|
|
for (int i = 0; i < totstrokes; i++) {
|
|
|
|
tJoinStrokes *elem = &strokes_list[i];
|
|
|
|
if (elem->used) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
pt = &elem->gps->points[0];
|
|
|
|
copy_v3_v3(start_b, &pt->x);
|
|
|
|
|
|
|
|
pt = &elem->gps->points[elem->gps->totpoints - 1];
|
|
|
|
copy_v3_v3(end_b, &pt->x);
|
|
|
|
|
|
|
|
dist = len_squared_v3v3(start_a, start_b);
|
|
|
|
if (dist < min_dist) {
|
|
|
|
min_dist = dist;
|
|
|
|
index = i;
|
|
|
|
}
|
|
|
|
dist = len_squared_v3v3(start_a, end_b);
|
|
|
|
if (dist < min_dist) {
|
|
|
|
min_dist = dist;
|
|
|
|
index = i;
|
|
|
|
}
|
|
|
|
dist = len_squared_v3v3(end_a, start_b);
|
|
|
|
if (dist < min_dist) {
|
|
|
|
min_dist = dist;
|
|
|
|
index = i;
|
|
|
|
}
|
|
|
|
dist = len_squared_v3v3(end_a, end_b);
|
|
|
|
if (dist < min_dist) {
|
|
|
|
min_dist = dist;
|
|
|
|
index = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_stroke_join_exec(bContext *C, wmOperator *op)
|
2016-08-26 16:25:39 +12:00
|
|
|
{
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
2020-03-09 16:27:24 +01:00
|
|
|
bGPDlayer *activegpl = BKE_gpencil_layer_active_get(gpd);
|
2018-07-31 10:22:19 +02:00
|
|
|
Object *ob = CTX_data_active_object(C);
|
2020-10-31 09:37:10 +01:00
|
|
|
/* Limit the number of strokes to join. It makes no sense to allow an very high number of strokes
|
|
|
|
* for CPU time and because to have a stroke with thousands of points is unpractical, so limit
|
|
|
|
* this number avoid to joining a full frame scene in one single stroke. */
|
|
|
|
const int max_join_strokes = 128;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
const int type = RNA_enum_get(op->ptr, "type");
|
|
|
|
const bool leave_gaps = RNA_boolean_get(op->ptr, "leave_gaps");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
/* sanity checks */
|
2019-04-22 09:19:45 +10:00
|
|
|
if (ELEM(NULL, gpd)) {
|
2016-08-26 16:25:39 +12:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
|
|
|
if (is_curve_edit) {
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2019-04-22 09:19:45 +10:00
|
|
|
if (activegpl->flag & GP_LAYER_LOCKED) {
|
2016-08-26 16:25:39 +12:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
BLI_assert(ELEM(type, GP_STROKE_JOIN, GP_STROKE_JOINCOPY));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-10-29 20:05:49 +01:00
|
|
|
int tot_strokes = 0;
|
|
|
|
/** Alloc memory */
|
|
|
|
tJoinStrokes *strokes_list = MEM_malloc_arrayN(sizeof(tJoinStrokes), max_join_strokes, __func__);
|
2020-10-29 23:32:19 +01:00
|
|
|
tJoinStrokes *elem = NULL;
|
2020-10-29 20:05:49 +01:00
|
|
|
/* Read all selected strokes to create a list. */
|
2016-08-26 16:25:39 +12:00
|
|
|
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
|
|
|
|
bGPDframe *gpf = gpl->actframe;
|
2019-04-22 09:19:45 +10:00
|
|
|
if (gpf == NULL) {
|
2016-09-21 17:02:17 +12:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-10-29 20:05:49 +01:00
|
|
|
/* Add all stroke selected of the frame. */
|
|
|
|
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
2016-08-26 16:25:39 +12:00
|
|
|
if (gps->flag & GP_STROKE_SELECT) {
|
|
|
|
/* skip strokes that are invalid for current view */
|
|
|
|
if (ED_gpencil_stroke_can_use(C, gps) == false) {
|
|
|
|
continue;
|
|
|
|
}
|
2020-10-29 20:05:49 +01:00
|
|
|
/* check if the color is editable. */
|
2021-01-16 16:44:49 +01:00
|
|
|
if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) {
|
2016-08-26 16:25:39 +12:00
|
|
|
continue;
|
|
|
|
}
|
2020-10-29 23:32:19 +01:00
|
|
|
elem = &strokes_list[tot_strokes];
|
2020-10-29 20:05:49 +01:00
|
|
|
elem->gpf = gpf;
|
|
|
|
elem->gps = gps;
|
|
|
|
elem->used = false;
|
|
|
|
|
|
|
|
tot_strokes++;
|
|
|
|
/* Limit the number of strokes. */
|
|
|
|
if (tot_strokes == max_join_strokes) {
|
|
|
|
BKE_reportf(op->reports,
|
|
|
|
RPT_WARNING,
|
2020-12-07 10:57:08 +01:00
|
|
|
"Too many strokes selected, only joined first %d strokes",
|
2020-10-29 20:05:49 +01:00
|
|
|
max_join_strokes);
|
|
|
|
break;
|
2016-08-26 16:25:39 +12:00
|
|
|
}
|
2020-10-29 20:05:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-10-29 20:05:49 +01:00
|
|
|
/* Nothing to join. */
|
|
|
|
if (tot_strokes < 2) {
|
|
|
|
MEM_SAFE_FREE(strokes_list);
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-10-29 20:05:49 +01:00
|
|
|
/* Take first stroke. */
|
2020-10-29 23:32:19 +01:00
|
|
|
elem = &strokes_list[0];
|
2020-10-29 20:05:49 +01:00
|
|
|
elem->used = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-10-29 20:05:49 +01:00
|
|
|
/* Create a new stroke. */
|
2020-11-13 21:43:00 +01:00
|
|
|
bGPDstroke *gps_new = BKE_gpencil_stroke_duplicate(elem->gps, true, true);
|
2020-10-29 20:05:49 +01:00
|
|
|
gps_new->flag &= ~GP_STROKE_CYCLIC;
|
|
|
|
BLI_insertlinkbefore(&elem->gpf->strokes, elem->gps, gps_new);
|
2020-03-09 16:27:24 +01:00
|
|
|
|
2020-10-29 20:05:49 +01:00
|
|
|
/* Join all strokes until the list is completed. */
|
|
|
|
while (true) {
|
|
|
|
int i = gpencil_get_nearest_stroke_index(strokes_list, gps_new, tot_strokes);
|
|
|
|
if (i < 0) {
|
|
|
|
break;
|
2016-08-26 16:25:39 +12:00
|
|
|
}
|
2020-10-29 23:32:19 +01:00
|
|
|
elem = &strokes_list[i];
|
2020-10-29 20:05:49 +01:00
|
|
|
/* Join new_stroke and stroke B. */
|
2020-11-18 21:30:43 +01:00
|
|
|
BKE_gpencil_stroke_join(gps_new, elem->gps, leave_gaps, true);
|
2020-10-29 20:05:49 +01:00
|
|
|
elem->used = true;
|
2016-08-26 16:25:39 +12:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-10-29 20:05:49 +01:00
|
|
|
/* Calc geometry data for new stroke. */
|
2020-11-13 21:43:00 +01:00
|
|
|
BKE_gpencil_stroke_geometry_update(gpd, gps_new);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-10-29 20:05:49 +01:00
|
|
|
/* If join only, delete old strokes. */
|
|
|
|
if (type == GP_STROKE_JOIN) {
|
|
|
|
for (int i = 0; i < tot_strokes; i++) {
|
2020-10-29 23:32:19 +01:00
|
|
|
elem = &strokes_list[i];
|
2020-10-29 20:05:49 +01:00
|
|
|
BLI_remlink(&elem->gpf->strokes, elem->gps);
|
|
|
|
BKE_gpencil_free_stroke(elem->gps);
|
2016-08-26 16:25:39 +12:00
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-10-29 20:05:49 +01:00
|
|
|
/* Free memory. */
|
|
|
|
MEM_SAFE_FREE(strokes_list);
|
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
/* notifiers */
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
2016-08-26 16:25:39 +12:00
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_stroke_join(wmOperatorType *ot)
|
|
|
|
{
|
2017-10-18 15:07:26 +11:00
|
|
|
static const EnumPropertyItem join_type[] = {
|
2016-08-26 16:25:39 +12:00
|
|
|
{GP_STROKE_JOIN, "JOIN", 0, "Join", ""},
|
|
|
|
{GP_STROKE_JOINCOPY, "JOINCOPY", 0, "Join and Copy", ""},
|
2019-02-03 14:01:45 +11:00
|
|
|
{0, NULL, 0, NULL, NULL},
|
2016-08-26 16:25:39 +12:00
|
|
|
};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Join Strokes";
|
|
|
|
ot->idname = "GPENCIL_OT_stroke_join";
|
|
|
|
ot->description = "Join selected strokes (optionally as new stroke)";
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
/* api callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_stroke_join_exec;
|
2020-06-29 12:49:30 +02:00
|
|
|
ot->poll = gpencil_active_layer_poll;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 19:54:16 +12:00
|
|
|
/* properties */
|
2016-08-26 16:25:39 +12:00
|
|
|
ot->prop = RNA_def_enum(ot->srna, "type", join_type, GP_STROKE_JOIN, "Type", "");
|
|
|
|
RNA_def_boolean(ot->srna,
|
|
|
|
"leave_gaps",
|
|
|
|
false,
|
|
|
|
"Leave Gaps",
|
|
|
|
"Leave gaps between joined strokes instead of linking them");
|
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Stroke Flip Operator
|
|
|
|
* \{ */
|
2016-08-26 16:25:39 +12:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
static int gpencil_stroke_flip_exec(bContext *C, wmOperator *op)
|
2016-08-26 16:25:39 +12:00
|
|
|
{
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
2018-07-31 10:22:19 +02:00
|
|
|
Object *ob = CTX_data_active_object(C);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
/* sanity checks */
|
2019-04-22 09:19:45 +10:00
|
|
|
if (ELEM(NULL, gpd)) {
|
2016-08-26 16:25:39 +12:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
|
|
|
bool changed = false;
|
2016-08-26 16:25:39 +12:00
|
|
|
/* read all selected strokes */
|
|
|
|
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
|
|
|
|
bGPDframe *gpf = gpl->actframe;
|
2019-04-22 09:19:45 +10:00
|
|
|
if (gpf == NULL) {
|
2016-08-26 19:54:16 +12:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
2016-08-26 16:25:39 +12:00
|
|
|
if (gps->flag & GP_STROKE_SELECT) {
|
|
|
|
/* skip strokes that are invalid for current view */
|
|
|
|
if (ED_gpencil_stroke_can_use(C, gps) == false) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* check if the color is editable */
|
2021-01-16 16:44:49 +01:00
|
|
|
if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) {
|
2016-08-26 16:25:39 +12:00
|
|
|
continue;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (is_curve_edit) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "Not implemented!");
|
|
|
|
}
|
|
|
|
else {
|
2020-11-18 21:30:43 +01:00
|
|
|
/* Flip stroke. */
|
|
|
|
BKE_gpencil_stroke_flip(gps);
|
2020-11-13 21:43:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
changed = true;
|
2016-08-26 16:25:39 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (changed) {
|
|
|
|
/* notifiers */
|
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_stroke_flip(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Flip Stroke";
|
|
|
|
ot->idname = "GPENCIL_OT_stroke_flip";
|
|
|
|
ot->description = "Change direction of the points of the selected strokes";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
/* api callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_stroke_flip_exec;
|
2020-06-29 12:49:30 +02:00
|
|
|
ot->poll = gpencil_active_layer_poll;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2016-08-26 16:25:39 +12:00
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
}
|
2015-12-13 21:03:13 +13:00
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Stroke Re-project Operator
|
|
|
|
* \{ */
|
2016-08-29 03:03:09 +12:00
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_strokes_reproject_exec(bContext *C, wmOperator *op)
|
2016-08-29 03:03:09 +12:00
|
|
|
{
|
2018-07-31 10:22:19 +02:00
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
2016-08-29 03:03:09 +12:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2019-07-25 16:36:22 +02:00
|
|
|
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
2020-03-06 16:56:42 +01:00
|
|
|
ARegion *region = CTX_wm_region(C);
|
2019-08-19 21:01:18 +02:00
|
|
|
int oldframe = (int)DEG_get_ctime(depsgraph);
|
2020-06-09 15:41:26 +02:00
|
|
|
const eGP_ReprojectModes mode = RNA_enum_get(op->ptr, "type");
|
|
|
|
const bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
|
2020-11-13 21:43:00 +01:00
|
|
|
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-06-09 15:41:26 +02:00
|
|
|
/* Init snap context for geometry projection. */
|
2020-11-13 21:43:00 +01:00
|
|
|
SnapObjectContext *sctx = NULL;
|
2020-06-09 15:41:26 +02:00
|
|
|
sctx = ED_transform_snap_object_context_create_view3d(scene, 0, region, CTX_wm_view3d(C));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
bool changed = false;
|
|
|
|
/* Init space conversion stuff. */
|
|
|
|
GP_SpaceConversion gsc = {NULL};
|
|
|
|
gpencil_point_conversion_init(C, &gsc);
|
2019-08-19 21:01:18 +02:00
|
|
|
int cfra_prv = INT_MIN;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-29 03:03:09 +12:00
|
|
|
/* Go through each editable + selected stroke, adjusting each of its points one by one... */
|
2018-11-13 15:02:32 +11:00
|
|
|
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
|
2020-11-13 21:43:00 +01:00
|
|
|
bool curve_select = false;
|
|
|
|
if (is_curve_edit && gps->editcurve != NULL) {
|
|
|
|
curve_select = gps->editcurve->flag & GP_CURVE_SELECT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gps->flag & GP_STROKE_SELECT || curve_select) {
|
2019-08-19 21:01:18 +02:00
|
|
|
|
|
|
|
/* update frame to get the new location of objects */
|
|
|
|
if ((mode == GP_REPROJECT_SURFACE) && (cfra_prv != gpf_->framenum)) {
|
|
|
|
cfra_prv = gpf_->framenum;
|
|
|
|
CFRA = gpf_->framenum;
|
2020-08-18 15:45:58 +02:00
|
|
|
BKE_scene_graph_update_for_newframe(depsgraph);
|
2019-08-19 21:01:18 +02:00
|
|
|
}
|
|
|
|
|
2020-06-09 15:41:26 +02:00
|
|
|
ED_gpencil_stroke_reproject(depsgraph, &gsc, sctx, gpl, gpf_, gps, mode, keep_original);
|
2020-11-13 21:43:00 +01:00
|
|
|
|
|
|
|
if (is_curve_edit && gps->editcurve != NULL) {
|
|
|
|
BKE_gpencil_stroke_editcurve_update(gpd, gpl, gps);
|
|
|
|
/* Update the selection from the stroke to the curve. */
|
2021-02-19 17:18:12 +01:00
|
|
|
BKE_gpencil_editcurve_stroke_sync_selection(gpd, gps, gps->editcurve);
|
2020-11-13 21:43:00 +01:00
|
|
|
|
|
|
|
gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
|
|
|
|
BKE_gpencil_stroke_geometry_update(gpd, gps);
|
|
|
|
}
|
|
|
|
|
|
|
|
changed = true;
|
2016-08-29 03:03:09 +12:00
|
|
|
}
|
|
|
|
}
|
2018-11-13 15:02:32 +11:00
|
|
|
GP_EDITABLE_STROKES_END(gpstroke_iter);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-19 21:01:18 +02:00
|
|
|
/* return frame state and DB to original state */
|
|
|
|
CFRA = oldframe;
|
2020-08-18 15:45:58 +02:00
|
|
|
BKE_scene_graph_update_for_newframe(depsgraph);
|
2019-08-19 21:01:18 +02:00
|
|
|
|
|
|
|
if (sctx != NULL) {
|
|
|
|
ED_transform_snap_object_context_destroy(sctx);
|
|
|
|
}
|
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (changed) {
|
|
|
|
/* update changed data */
|
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
|
|
|
}
|
|
|
|
|
2016-08-29 03:03:09 +12:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_reproject(wmOperatorType *ot)
|
|
|
|
{
|
2017-10-18 15:07:26 +11:00
|
|
|
static const EnumPropertyItem reproject_type[] = {
|
2018-11-20 16:29:33 +01:00
|
|
|
{GP_REPROJECT_FRONT, "FRONT", 0, "Front", "Reproject the strokes using the X-Z plane"},
|
|
|
|
{GP_REPROJECT_SIDE, "SIDE", 0, "Side", "Reproject the strokes using the Y-Z plane"},
|
|
|
|
{GP_REPROJECT_TOP, "TOP", 0, "Top", "Reproject the strokes using the X-Y plane"},
|
|
|
|
{GP_REPROJECT_VIEW,
|
|
|
|
"VIEW",
|
|
|
|
0,
|
|
|
|
"View",
|
2017-01-19 03:20:44 +13:00
|
|
|
"Reproject the strokes to end up on the same plane, as if drawn from the current viewpoint "
|
|
|
|
"using 'Cursor' Stroke Placement"},
|
|
|
|
{GP_REPROJECT_SURFACE,
|
|
|
|
"SURFACE",
|
|
|
|
0,
|
|
|
|
"Surface",
|
|
|
|
"Reproject the strokes on to the scene geometry, as if drawn using 'Surface' placement"},
|
2019-03-17 19:47:31 +01:00
|
|
|
{GP_REPROJECT_CURSOR,
|
|
|
|
"CURSOR",
|
|
|
|
0,
|
|
|
|
"Cursor",
|
2019-08-01 13:53:25 +10:00
|
|
|
"Reproject the strokes using the orientation of 3D cursor"},
|
2019-02-03 14:01:45 +11:00
|
|
|
{0, NULL, 0, NULL, NULL},
|
2017-01-19 03:20:44 +13:00
|
|
|
};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-29 03:03:09 +12:00
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Reproject Strokes";
|
|
|
|
ot->idname = "GPENCIL_OT_reproject";
|
2017-01-19 03:20:44 +13:00
|
|
|
ot->description =
|
|
|
|
"Reproject the selected strokes from the current viewpoint as if they had been newly drawn "
|
2018-08-30 11:06:44 +02:00
|
|
|
"(e.g. to fix problems from accidental 3D cursor movement or accidental viewport changes, "
|
|
|
|
"or for matching deforming geometry)";
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-29 03:03:09 +12:00
|
|
|
/* callbacks */
|
2017-01-19 03:20:44 +13:00
|
|
|
ot->invoke = WM_menu_invoke;
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_strokes_reproject_exec;
|
|
|
|
ot->poll = gpencil_strokes_edit3d_poll;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-08-29 03:03:09 +12:00
|
|
|
/* flags */
|
2019-07-25 16:36:22 +02:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-01-19 03:20:44 +13:00
|
|
|
/* properties */
|
2018-11-20 16:29:33 +01:00
|
|
|
ot->prop = RNA_def_enum(
|
|
|
|
ot->srna, "type", reproject_type, GP_REPROJECT_VIEW, "Projection Type", "");
|
2020-06-09 15:41:26 +02:00
|
|
|
|
|
|
|
RNA_def_boolean(
|
|
|
|
ot->srna,
|
|
|
|
"keep_original",
|
|
|
|
0,
|
|
|
|
"Keep Original",
|
|
|
|
"Keep original strokes and create a copy before reprojecting instead of reproject them");
|
2016-08-29 03:03:09 +12:00
|
|
|
}
|
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_recalc_geometry_exec(bContext *C, wmOperator *UNUSED(op))
|
2020-03-09 16:27:24 +01:00
|
|
|
{
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
bGPdata *gpd = (bGPdata *)ob->data;
|
|
|
|
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
|
|
|
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
|
|
|
|
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
2020-11-13 21:43:00 +01:00
|
|
|
BKE_gpencil_stroke_geometry_update(gpd, gps);
|
2020-03-09 16:27:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-11-13 21:43:00 +01:00
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
/* update changed data */
|
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_recalc_geometry(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Recalculate internal geometry";
|
|
|
|
ot->idname = "GPENCIL_OT_recalc_geometry";
|
|
|
|
ot->description = "Update all internal geometry data";
|
|
|
|
|
|
|
|
/* callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_recalc_geometry_exec;
|
2020-06-29 12:49:30 +02:00
|
|
|
ot->poll = gpencil_active_layer_poll;
|
2020-03-09 16:27:24 +01:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Stroke Subdivide Operator
|
|
|
|
* \{ */
|
|
|
|
|
2018-12-13 23:30:29 +01:00
|
|
|
/* helper to smooth */
|
2020-06-29 15:28:38 +02:00
|
|
|
static void gpencil_smooth_stroke(bContext *C, wmOperator *op)
|
2018-12-13 23:30:29 +01:00
|
|
|
{
|
|
|
|
const int repeat = RNA_int_get(op->ptr, "repeat");
|
|
|
|
float factor = RNA_float_get(op->ptr, "factor");
|
|
|
|
const bool only_selected = RNA_boolean_get(op->ptr, "only_selected");
|
|
|
|
const bool smooth_position = RNA_boolean_get(op->ptr, "smooth_position");
|
|
|
|
const bool smooth_thickness = RNA_boolean_get(op->ptr, "smooth_thickness");
|
|
|
|
const bool smooth_strength = RNA_boolean_get(op->ptr, "smooth_strength");
|
|
|
|
const bool smooth_uv = RNA_boolean_get(op->ptr, "smooth_uv");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-12-13 23:30:29 +01:00
|
|
|
if (factor == 0.0f) {
|
|
|
|
return;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-12-13 23:30:29 +01:00
|
|
|
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
|
|
|
|
if (gps->flag & GP_STROKE_SELECT) {
|
|
|
|
for (int r = 0; r < repeat; r++) {
|
|
|
|
for (int i = 0; i < gps->totpoints; i++) {
|
|
|
|
bGPDspoint *pt = &gps->points[i];
|
|
|
|
if ((only_selected) && ((pt->flag & GP_SPOINT_SELECT) == 0)) {
|
|
|
|
continue;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-12-13 23:30:29 +01:00
|
|
|
/* perform smoothing */
|
|
|
|
if (smooth_position) {
|
2020-03-09 16:27:24 +01:00
|
|
|
BKE_gpencil_stroke_smooth(gps, i, factor);
|
2018-12-13 23:30:29 +01:00
|
|
|
}
|
|
|
|
if (smooth_strength) {
|
2020-03-09 16:27:24 +01:00
|
|
|
BKE_gpencil_stroke_smooth_strength(gps, i, factor);
|
2018-12-13 23:30:29 +01:00
|
|
|
}
|
|
|
|
if (smooth_thickness) {
|
|
|
|
/* thickness need to repeat process several times */
|
2021-03-31 14:18:41 +02:00
|
|
|
for (int r2 = 0; r2 < 20; r2++) {
|
2020-03-09 16:27:24 +01:00
|
|
|
BKE_gpencil_stroke_smooth_thickness(gps, i, factor);
|
2018-12-13 23:30:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (smooth_uv) {
|
2020-03-09 16:27:24 +01:00
|
|
|
BKE_gpencil_stroke_smooth_uv(gps, i, factor);
|
2018-12-13 23:30:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
GP_EDITABLE_STROKES_END(gpstroke_iter);
|
|
|
|
}
|
2017-01-18 00:48:15 +13:00
|
|
|
|
2016-09-15 13:29:26 +02:00
|
|
|
/* helper: Count how many points need to be inserted */
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_count_subdivision_cuts(bGPDstroke *gps)
|
2016-09-15 13:29:26 +02:00
|
|
|
{
|
|
|
|
bGPDspoint *pt;
|
|
|
|
int i;
|
|
|
|
int totnewpoints = 0;
|
|
|
|
for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) {
|
|
|
|
if (pt->flag & GP_SPOINT_SELECT) {
|
2017-04-01 12:09:17 +11:00
|
|
|
if (i + 1 < gps->totpoints) {
|
2016-09-15 13:29:26 +02:00
|
|
|
if (gps->points[i + 1].flag & GP_SPOINT_SELECT) {
|
2018-07-31 10:22:19 +02:00
|
|
|
totnewpoints++;
|
2017-04-01 12:09:17 +11:00
|
|
|
}
|
2016-09-15 13:29:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-04-06 17:30:13 +02:00
|
|
|
if ((gps->flag & GP_STROKE_CYCLIC) && (gps->points[0].flag & GP_SPOINT_SELECT) &&
|
|
|
|
(gps->points[gps->totpoints - 1].flag & GP_SPOINT_SELECT)) {
|
|
|
|
totnewpoints++;
|
|
|
|
}
|
|
|
|
|
2016-09-15 13:29:26 +02:00
|
|
|
return totnewpoints;
|
|
|
|
}
|
2018-07-31 10:22:19 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
static void gpencil_stroke_subdivide(bGPDstroke *gps, const int cuts)
|
2016-09-15 13:29:26 +02:00
|
|
|
{
|
2018-08-30 13:45:12 +02:00
|
|
|
bGPDspoint *temp_points;
|
|
|
|
int totnewpoints, oldtotpoints;
|
|
|
|
int i2;
|
2020-11-13 21:43:00 +01:00
|
|
|
/* loop as many times as cuts */
|
|
|
|
for (int s = 0; s < cuts; s++) {
|
|
|
|
totnewpoints = gpencil_count_subdivision_cuts(gps);
|
|
|
|
if (totnewpoints == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* duplicate points in a temp area */
|
|
|
|
temp_points = MEM_dupallocN(gps->points);
|
|
|
|
oldtotpoints = gps->totpoints;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
MDeformVert *temp_dverts = NULL;
|
|
|
|
MDeformVert *dvert_final = NULL;
|
|
|
|
MDeformVert *dvert = NULL;
|
|
|
|
MDeformVert *dvert_next = NULL;
|
|
|
|
if (gps->dvert != NULL) {
|
|
|
|
temp_dverts = MEM_dupallocN(gps->dvert);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* resize the points arrays */
|
|
|
|
gps->totpoints += totnewpoints;
|
|
|
|
gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
|
|
|
|
if (gps->dvert != NULL) {
|
|
|
|
gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* loop and interpolate */
|
|
|
|
i2 = 0;
|
|
|
|
for (int i = 0; i < oldtotpoints; i++) {
|
|
|
|
bGPDspoint *pt = &temp_points[i];
|
|
|
|
bGPDspoint *pt_final = &gps->points[i2];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* copy current point */
|
|
|
|
copy_v3_v3(&pt_final->x, &pt->x);
|
|
|
|
pt_final->pressure = pt->pressure;
|
|
|
|
pt_final->strength = pt->strength;
|
|
|
|
pt_final->time = pt->time;
|
|
|
|
pt_final->flag = pt->flag;
|
|
|
|
copy_v4_v4(pt_final->vert_color, pt->vert_color);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (gps->dvert != NULL) {
|
|
|
|
dvert = &temp_dverts[i];
|
|
|
|
dvert_final = &gps->dvert[i2];
|
|
|
|
dvert_final->totweight = dvert->totweight;
|
|
|
|
dvert_final->dw = dvert->dw;
|
|
|
|
}
|
|
|
|
i2++;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* if next point is selected add a half way point */
|
|
|
|
if (pt->flag & GP_SPOINT_SELECT) {
|
|
|
|
if (i + 1 < oldtotpoints) {
|
|
|
|
if (temp_points[i + 1].flag & GP_SPOINT_SELECT) {
|
|
|
|
pt_final = &gps->points[i2];
|
|
|
|
if (gps->dvert != NULL) {
|
|
|
|
dvert_final = &gps->dvert[i2];
|
|
|
|
}
|
|
|
|
/* Interpolate all values */
|
|
|
|
bGPDspoint *next = &temp_points[i + 1];
|
|
|
|
interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
|
|
|
|
pt_final->pressure = interpf(pt->pressure, next->pressure, 0.5f);
|
|
|
|
pt_final->strength = interpf(pt->strength, next->strength, 0.5f);
|
|
|
|
CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
|
|
|
|
interp_v4_v4v4(pt_final->vert_color, pt->vert_color, next->vert_color, 0.5f);
|
|
|
|
pt_final->time = interpf(pt->time, next->time, 0.5f);
|
|
|
|
pt_final->flag |= GP_SPOINT_SELECT;
|
|
|
|
|
|
|
|
/* interpolate weights */
|
|
|
|
if (gps->dvert != NULL) {
|
|
|
|
dvert = &temp_dverts[i];
|
|
|
|
dvert_next = &temp_dverts[i + 1];
|
|
|
|
dvert_final = &gps->dvert[i2];
|
|
|
|
|
|
|
|
dvert_final->totweight = dvert->totweight;
|
|
|
|
dvert_final->dw = MEM_dupallocN(dvert->dw);
|
|
|
|
|
|
|
|
/* interpolate weight values */
|
|
|
|
for (int d = 0; d < dvert->totweight; d++) {
|
|
|
|
MDeformWeight *dw_a = &dvert->dw[d];
|
|
|
|
if (dvert_next->totweight > d) {
|
|
|
|
MDeformWeight *dw_b = &dvert_next->dw[d];
|
|
|
|
MDeformWeight *dw_final = &dvert_final->dw[d];
|
|
|
|
dw_final->weight = interpf(dw_a->weight, dw_b->weight, 0.5f);
|
|
|
|
}
|
2018-08-30 13:45:12 +02:00
|
|
|
}
|
|
|
|
}
|
2020-11-13 21:43:00 +01:00
|
|
|
|
|
|
|
i2++;
|
2018-08-30 13:45:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-11-13 21:43:00 +01:00
|
|
|
}
|
2021-04-06 17:30:13 +02:00
|
|
|
|
|
|
|
/* Subdivide between last and first point. */
|
|
|
|
if (gps->flag & GP_STROKE_CYCLIC) {
|
|
|
|
bGPDspoint *pt = &temp_points[oldtotpoints - 1];
|
|
|
|
bGPDspoint *next = &temp_points[0];
|
|
|
|
if ((pt->flag & GP_SPOINT_SELECT) && (next->flag & GP_SPOINT_SELECT)) {
|
|
|
|
bGPDspoint *pt_final = &gps->points[i2];
|
|
|
|
if (gps->dvert != NULL) {
|
|
|
|
dvert_final = &gps->dvert[i2];
|
|
|
|
}
|
|
|
|
/* Interpolate all values */
|
|
|
|
interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
|
|
|
|
pt_final->pressure = interpf(pt->pressure, next->pressure, 0.5f);
|
|
|
|
pt_final->strength = interpf(pt->strength, next->strength, 0.5f);
|
|
|
|
CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
|
|
|
|
interp_v4_v4v4(pt_final->vert_color, pt->vert_color, next->vert_color, 0.5f);
|
|
|
|
pt_final->time = interpf(pt->time, next->time, 0.5f);
|
|
|
|
pt_final->flag |= GP_SPOINT_SELECT;
|
|
|
|
|
|
|
|
/* interpolate weights */
|
|
|
|
if (gps->dvert != NULL) {
|
|
|
|
dvert = &temp_dverts[oldtotpoints - 1];
|
|
|
|
dvert_next = &temp_dverts[0];
|
|
|
|
dvert_final = &gps->dvert[i2];
|
|
|
|
|
|
|
|
dvert_final->totweight = dvert->totweight;
|
|
|
|
dvert_final->dw = MEM_dupallocN(dvert->dw);
|
|
|
|
|
|
|
|
/* interpolate weight values */
|
|
|
|
for (int d = 0; d < dvert->totweight; d++) {
|
|
|
|
MDeformWeight *dw_a = &dvert->dw[d];
|
|
|
|
if (dvert_next->totweight > d) {
|
|
|
|
MDeformWeight *dw_b = &dvert_next->dw[d];
|
|
|
|
MDeformWeight *dw_final = &dvert_final->dw[d];
|
|
|
|
dw_final->weight = interpf(dw_a->weight, dw_b->weight, 0.5f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* free temp memory */
|
|
|
|
MEM_SAFE_FREE(temp_points);
|
|
|
|
MEM_SAFE_FREE(temp_dverts);
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
static int gpencil_stroke_subdivide_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
|
|
|
const int cuts = RNA_int_get(op->ptr, "number_cuts");
|
|
|
|
|
|
|
|
/* sanity checks */
|
|
|
|
if (ELEM(NULL, gpd)) {
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
|
|
|
|
|
|
|
bool changed = false;
|
|
|
|
if (is_curve_edit) {
|
|
|
|
GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc)
|
|
|
|
{
|
|
|
|
if (gpc->flag & GP_CURVE_SELECT) {
|
|
|
|
BKE_gpencil_editcurve_subdivide(gps, cuts);
|
|
|
|
BKE_gpencil_editcurve_recalculate_handles(gps);
|
|
|
|
gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
|
|
|
|
BKE_gpencil_stroke_geometry_update(gpd, gps);
|
|
|
|
changed = true;
|
|
|
|
}
|
2016-09-15 13:29:26 +02:00
|
|
|
}
|
2020-11-13 21:43:00 +01:00
|
|
|
GP_EDITABLE_CURVES_END(gps_iter);
|
2016-09-15 13:29:26 +02:00
|
|
|
}
|
2020-11-13 21:43:00 +01:00
|
|
|
else {
|
|
|
|
/* Go through each editable + selected stroke */
|
|
|
|
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
|
|
|
|
if (gps->flag & GP_STROKE_SELECT) {
|
|
|
|
gpencil_stroke_subdivide(gps, cuts);
|
|
|
|
/* Calc geometry data. */
|
|
|
|
BKE_gpencil_stroke_geometry_update(gpd, gps);
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
GP_EDITABLE_STROKES_END(gpstroke_iter);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (changed) {
|
|
|
|
/* smooth stroke */
|
|
|
|
gpencil_smooth_stroke(C, op);
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (changed) {
|
|
|
|
/* notifiers */
|
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-09-15 13:29:26 +02:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
static bool gpencil_subdivide_curve_edit_poll_property(const bContext *C,
|
|
|
|
wmOperator *UNUSED(op),
|
|
|
|
const PropertyRNA *prop)
|
|
|
|
{
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
|
|
|
if (gpd != NULL && GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)) {
|
|
|
|
const char *prop_id = RNA_property_identifier(prop);
|
|
|
|
/* Only show number_cuts in curve edit mode */
|
|
|
|
if (!STREQ(prop_id, "number_cuts")) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-09-15 13:29:26 +02:00
|
|
|
void GPENCIL_OT_stroke_subdivide(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-09-15 13:29:26 +02:00
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Subdivide Stroke";
|
|
|
|
ot->idname = "GPENCIL_OT_stroke_subdivide";
|
|
|
|
ot->description =
|
|
|
|
"Subdivide between continuous selected points of the stroke adding a point half way between "
|
|
|
|
"them";
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-09-15 13:29:26 +02:00
|
|
|
/* api callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_stroke_subdivide_exec;
|
2020-06-29 12:49:30 +02:00
|
|
|
ot->poll = gpencil_active_layer_poll;
|
2020-11-13 21:43:00 +01:00
|
|
|
ot->poll_property = gpencil_subdivide_curve_edit_poll_property;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-09-15 13:29:26 +02:00
|
|
|
/* flags */
|
2018-07-31 10:22:19 +02:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-09-15 13:29:26 +02:00
|
|
|
/* properties */
|
|
|
|
prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 10, "Number of Cuts", "", 1, 5);
|
|
|
|
/* avoid re-using last var because it can cause _very_ high value and annoy users */
|
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-12-13 23:30:29 +01:00
|
|
|
/* Smooth parameters */
|
|
|
|
RNA_def_float(ot->srna, "factor", 0.0f, 0.0f, 2.0f, "Smooth", "", 0.0f, 2.0f);
|
|
|
|
prop = RNA_def_int(ot->srna, "repeat", 1, 1, 10, "Repeat", "", 1, 5);
|
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
2019-03-15 08:53:22 +11:00
|
|
|
RNA_def_boolean(ot->srna,
|
|
|
|
"only_selected",
|
|
|
|
true,
|
|
|
|
"Selected Points",
|
|
|
|
"Smooth only selected points in the stroke");
|
2018-12-13 23:30:29 +01:00
|
|
|
RNA_def_boolean(ot->srna, "smooth_position", true, "Position", "");
|
|
|
|
RNA_def_boolean(ot->srna, "smooth_thickness", true, "Thickness", "");
|
|
|
|
RNA_def_boolean(ot->srna, "smooth_strength", false, "Strength", "");
|
|
|
|
RNA_def_boolean(ot->srna, "smooth_uv", false, "UV", "");
|
2016-09-15 13:29:26 +02:00
|
|
|
}
|
2018-07-31 10:22:19 +02:00
|
|
|
|
|
|
|
/* ** simplify stroke *** */
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_stroke_simplify_exec(bContext *C, wmOperator *op)
|
2018-07-31 10:22:19 +02:00
|
|
|
{
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
|
|
|
float factor = RNA_float_get(op->ptr, "factor");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* sanity checks */
|
2019-04-22 09:19:45 +10:00
|
|
|
if (ELEM(NULL, gpd)) {
|
2018-07-31 10:22:19 +02:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
|
|
|
|
|
|
|
bool changed = false;
|
|
|
|
if (is_curve_edit) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "Not implemented!");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* Go through each editable + selected stroke */
|
|
|
|
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
|
|
|
|
if (gps->flag & GP_STROKE_SELECT) {
|
|
|
|
/* simplify stroke using Ramer-Douglas-Peucker algorithm */
|
|
|
|
BKE_gpencil_stroke_simplify_adaptive(gpd, gps, factor);
|
|
|
|
changed = true;
|
|
|
|
}
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
2020-11-13 21:43:00 +01:00
|
|
|
GP_EDITABLE_STROKES_END(gpstroke_iter);
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (changed) {
|
|
|
|
/* notifiers */
|
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_stroke_simplify(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Simplify Stroke";
|
|
|
|
ot->idname = "GPENCIL_OT_stroke_simplify";
|
|
|
|
ot->description = "Simplify selected stroked reducing number of points";
|
|
|
|
|
|
|
|
/* api callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_stroke_simplify_exec;
|
2020-06-29 12:49:30 +02:00
|
|
|
ot->poll = gpencil_active_layer_poll;
|
2018-07-31 10:22:19 +02:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
|
|
|
|
/* properties */
|
|
|
|
prop = RNA_def_float(ot->srna, "factor", 0.0f, 0.0f, 100.0f, "Factor", "", 0.0f, 100.0f);
|
|
|
|
/* avoid re-using last var */
|
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
|
|
|
}
|
|
|
|
|
2018-09-27 15:49:59 +02:00
|
|
|
/* ** simplify stroke using fixed algorithm *** */
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_stroke_simplify_fixed_exec(bContext *C, wmOperator *op)
|
2018-07-31 10:22:19 +02:00
|
|
|
{
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
|
|
|
int steps = RNA_int_get(op->ptr, "step");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* sanity checks */
|
2019-04-22 09:19:45 +10:00
|
|
|
if (ELEM(NULL, gpd)) {
|
2018-07-31 10:22:19 +02:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
|
|
|
|
|
|
|
bool changed = false;
|
|
|
|
if (is_curve_edit) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "Not implemented!");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* Go through each editable + selected stroke */
|
|
|
|
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
|
|
|
|
if (gps->flag & GP_STROKE_SELECT) {
|
|
|
|
changed |= true;
|
|
|
|
for (int i = 0; i < steps; i++) {
|
|
|
|
BKE_gpencil_stroke_simplify_fixed(gpd, gps);
|
|
|
|
}
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
|
|
|
}
|
2020-11-13 21:43:00 +01:00
|
|
|
GP_EDITABLE_STROKES_END(gpstroke_iter);
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
if (changed) {
|
|
|
|
/* notifiers */
|
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_stroke_simplify_fixed(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Simplify Fixed Stroke";
|
|
|
|
ot->idname = "GPENCIL_OT_stroke_simplify_fixed";
|
|
|
|
ot->description = "Simplify selected stroked reducing number of points using fixed algorithm";
|
|
|
|
|
|
|
|
/* api callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_stroke_simplify_fixed_exec;
|
2020-06-29 12:49:30 +02:00
|
|
|
ot->poll = gpencil_active_layer_poll;
|
2018-07-31 10:22:19 +02:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
|
|
|
|
/* properties */
|
|
|
|
prop = RNA_def_int(ot->srna, "step", 1, 1, 100, "Steps", "Number of simplify steps", 1, 10);
|
|
|
|
|
|
|
|
/* avoid re-using last var */
|
2018-12-13 19:49:13 +01:00
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
|
|
|
|
2019-08-08 16:12:13 +02:00
|
|
|
/* ** Resample stroke *** */
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_stroke_sample_exec(bContext *C, wmOperator *op)
|
2019-08-08 16:12:13 +02:00
|
|
|
{
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
|
|
|
const float length = RNA_float_get(op->ptr, "length");
|
|
|
|
|
|
|
|
/* sanity checks */
|
|
|
|
if (ELEM(NULL, gpd)) {
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Go through each editable + selected stroke */
|
|
|
|
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
|
|
|
|
if (gps->flag & GP_STROKE_SELECT) {
|
2020-11-13 21:43:00 +01:00
|
|
|
BKE_gpencil_stroke_sample(gpd, gps, length, true);
|
2019-08-08 16:12:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
GP_EDITABLE_STROKES_END(gpstroke_iter);
|
|
|
|
|
|
|
|
/* notifiers */
|
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_stroke_sample(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Sample Stroke";
|
|
|
|
ot->idname = "GPENCIL_OT_stroke_sample";
|
|
|
|
ot->description = "Sample stroke points to predefined segment length";
|
|
|
|
|
|
|
|
/* api callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_stroke_sample_exec;
|
2020-11-13 21:43:00 +01:00
|
|
|
ot->poll = gpencil_stroke_not_in_curve_edit_mode;
|
2019-08-08 16:12:13 +02:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
|
|
|
|
/* properties */
|
|
|
|
prop = RNA_def_float(ot->srna, "length", 0.1f, 0.0f, 100.0f, "Length", "", 0.0f, 100.0f);
|
|
|
|
/* avoid re-using last var */
|
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Stroke Trim Operator
|
|
|
|
* \{ */
|
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
static int gpencil_stroke_trim_exec(bContext *C, wmOperator *op)
|
2019-02-26 16:04:27 +00:00
|
|
|
{
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-26 16:04:27 +00:00
|
|
|
/* sanity checks */
|
2019-04-22 09:19:45 +10:00
|
|
|
if (ELEM(NULL, gpd)) {
|
2019-02-26 16:04:27 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-26 16:04:27 +00:00
|
|
|
/* Go through each editable + selected stroke */
|
|
|
|
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
|
2020-11-13 21:43:00 +01:00
|
|
|
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-26 16:04:27 +00:00
|
|
|
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
|
2019-06-07 11:46:11 +02:00
|
|
|
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-26 16:04:27 +00:00
|
|
|
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
|
|
|
|
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:19:45 +10:00
|
|
|
if (gpf == NULL) {
|
2019-02-26 16:04:27 +00:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-26 16:04:27 +00:00
|
|
|
/* skip strokes that are invalid for current view */
|
2019-04-22 09:19:45 +10:00
|
|
|
if (ED_gpencil_stroke_can_use(C, gps) == false) {
|
2019-02-26 16:04:27 +00:00
|
|
|
continue;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-26 16:04:27 +00:00
|
|
|
if (gps->flag & GP_STROKE_SELECT) {
|
2020-11-13 21:43:00 +01:00
|
|
|
if (is_curve_edit) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "Not implemented!");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BKE_gpencil_stroke_trim(gpd, gps);
|
|
|
|
}
|
2019-02-26 16:04:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* if not multiedit, exit loop*/
|
|
|
|
if (!is_multiedit) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-26 16:04:27 +00:00
|
|
|
/* notifiers */
|
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-26 16:04:27 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_stroke_trim(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Trim Stroke";
|
|
|
|
ot->idname = "GPENCIL_OT_stroke_trim";
|
|
|
|
ot->description = "Trim selected stroke to first loop or intersection";
|
|
|
|
|
|
|
|
/* api callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_stroke_trim_exec;
|
2020-06-29 12:49:30 +02:00
|
|
|
ot->poll = gpencil_active_layer_poll;
|
2019-02-26 16:04:27 +00:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Stroke Separate Operator
|
|
|
|
* \{ */
|
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
typedef enum eGP_SeparateModes {
|
|
|
|
/* Points */
|
|
|
|
GP_SEPARATE_POINT = 0,
|
|
|
|
/* Selected Strokes */
|
|
|
|
GP_SEPARATE_STROKE,
|
|
|
|
/* Current Layer */
|
|
|
|
GP_SEPARATE_LAYER,
|
|
|
|
} eGP_SeparateModes;
|
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op)
|
2018-07-31 10:22:19 +02:00
|
|
|
{
|
|
|
|
Base *base_new;
|
|
|
|
Main *bmain = CTX_data_main(C);
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
2020-03-09 16:27:24 +01:00
|
|
|
Base *base_prev = CTX_data_active_base(C);
|
2018-07-31 10:22:19 +02:00
|
|
|
bGPdata *gpd_src = ED_gpencil_data_get_active(C);
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
Object *ob_dst = NULL;
|
|
|
|
bGPdata *gpd_dst = NULL;
|
|
|
|
bGPDlayer *gpl_dst = NULL;
|
|
|
|
bGPDframe *gpf_dst = NULL;
|
|
|
|
bGPDspoint *pt;
|
|
|
|
Material *ma = NULL;
|
|
|
|
int i, idx;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
eGP_SeparateModes mode = RNA_enum_get(op->ptr, "mode");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-05-14 13:21:10 +02:00
|
|
|
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_src);
|
|
|
|
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd_src);
|
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* sanity checks */
|
|
|
|
if (ELEM(NULL, gpd_src)) {
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-10-20 14:16:47 +11:00
|
|
|
if ((mode == GP_SEPARATE_LAYER) && (BLI_listbase_is_single(&gpd_src->layers))) {
|
2019-01-18 10:52:38 +01:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "Cannot separate an object with one layer only");
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-05-14 13:21:10 +02:00
|
|
|
/* Cancel if nothing selected. */
|
|
|
|
if (ELEM(mode, GP_SEPARATE_POINT, GP_SEPARATE_STROKE)) {
|
|
|
|
bool has_selected = false;
|
|
|
|
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
|
|
|
|
if (ED_gpencil_layer_has_selected_stroke(gpl, is_multiedit)) {
|
|
|
|
has_selected = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
|
|
|
|
|
|
|
if (!has_selected) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "Nothing selected");
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-10-23 12:28:32 +02:00
|
|
|
/* Create a new object. */
|
|
|
|
/* Take into account user preferences for duplicating actions. */
|
2020-06-16 17:14:50 +02:00
|
|
|
const eDupli_ID_Flags dupflag = (U.dupflag & USER_DUP_ACT);
|
2019-10-23 12:28:32 +02:00
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
base_new = ED_object_add_duplicate(bmain, scene, view_layer, base_prev, dupflag);
|
2018-07-31 10:22:19 +02:00
|
|
|
ob_dst = base_new->object;
|
2018-11-12 10:08:49 +01:00
|
|
|
ob_dst->mode = OB_MODE_OBJECT;
|
2020-08-01 12:47:59 +10:00
|
|
|
/* Duplication will increment #bGPdata user-count, but since we create a new grease-pencil
|
|
|
|
* data-block for ob_dst (which gets its own user automatically),
|
|
|
|
* we have to decrement the user-count again. */
|
2018-11-11 14:31:23 +01:00
|
|
|
gpd_dst = BKE_gpencil_data_addnew(bmain, gpd_src->id.name + 2);
|
2020-07-29 12:53:49 +02:00
|
|
|
id_us_min(ob_dst->data);
|
2018-07-31 10:22:19 +02:00
|
|
|
ob_dst->data = (bGPdata *)gpd_dst;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-01 12:47:59 +10:00
|
|
|
/* Loop old data-block and separate parts. */
|
2020-11-06 12:30:59 +11:00
|
|
|
if (ELEM(mode, GP_SEPARATE_POINT, GP_SEPARATE_STROKE)) {
|
2018-07-31 10:22:19 +02:00
|
|
|
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
|
|
|
|
gpl_dst = NULL;
|
2019-06-07 11:46:11 +02:00
|
|
|
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
|
|
|
|
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
if (gpf == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
gpf_dst = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* skip strokes that are invalid for current view */
|
|
|
|
if (ED_gpencil_stroke_can_use(C, gps) == false) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* check if the color is editable */
|
2021-01-16 16:44:49 +01:00
|
|
|
if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) {
|
2018-07-31 10:22:19 +02:00
|
|
|
continue;
|
|
|
|
}
|
2020-03-29 16:33:51 +11:00
|
|
|
/* Separate selected strokes. */
|
2018-07-31 10:22:19 +02:00
|
|
|
if (gps->flag & GP_STROKE_SELECT) {
|
|
|
|
/* add layer if not created before */
|
|
|
|
if (gpl_dst == NULL) {
|
|
|
|
gpl_dst = BKE_gpencil_layer_addnew(gpd_dst, gpl->info, false);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* add frame if not created before */
|
|
|
|
if (gpf_dst == NULL) {
|
2020-03-09 16:27:24 +01:00
|
|
|
gpf_dst = BKE_gpencil_layer_frame_get(gpl_dst, gpf->framenum, GP_GETFRAME_ADD_NEW);
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* add duplicate materials */
|
2019-08-14 23:29:46 +10:00
|
|
|
|
|
|
|
/* XXX same material can be in multiple slots. */
|
2020-02-05 11:23:58 +01:00
|
|
|
ma = BKE_gpencil_material(ob, gps->mat_nr + 1);
|
2019-08-14 23:29:46 +10:00
|
|
|
|
2019-04-09 09:22:46 +02:00
|
|
|
idx = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* selected points mode */
|
|
|
|
if (mode == GP_SEPARATE_POINT) {
|
2020-11-13 21:43:00 +01:00
|
|
|
if (is_curve_edit) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "Not implemented!");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* make copy of source stroke */
|
|
|
|
bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps, true, true);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* Reassign material. */
|
|
|
|
gps_dst->mat_nr = idx;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* link to destination frame */
|
|
|
|
BLI_addtail(&gpf_dst->strokes, gps_dst);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* Invert selection status of all points in destination stroke */
|
|
|
|
for (i = 0, pt = gps_dst->points; i < gps_dst->totpoints; i++, pt++) {
|
|
|
|
pt->flag ^= GP_SPOINT_SELECT;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* delete selected points from destination stroke */
|
2020-11-18 21:30:43 +01:00
|
|
|
BKE_gpencil_stroke_delete_tagged_points(
|
2020-11-13 21:43:00 +01:00
|
|
|
gpd_dst, gpf_dst, gps_dst, NULL, GP_SPOINT_SELECT, false, 0);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* delete selected points from origin stroke */
|
2020-11-18 21:30:43 +01:00
|
|
|
BKE_gpencil_stroke_delete_tagged_points(
|
2020-11-13 21:43:00 +01:00
|
|
|
gpd_src, gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0);
|
|
|
|
}
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
|
|
|
/* selected strokes mode */
|
|
|
|
else if (mode == GP_SEPARATE_STROKE) {
|
|
|
|
/* deselect old stroke */
|
|
|
|
gps->flag &= ~GP_STROKE_SELECT;
|
2021-02-20 10:16:51 +01:00
|
|
|
BKE_gpencil_stroke_select_index_reset(gps);
|
2018-07-31 10:22:19 +02:00
|
|
|
/* unlink from source frame */
|
|
|
|
BLI_remlink(&gpf->strokes, gps);
|
|
|
|
gps->prev = gps->next = NULL;
|
|
|
|
/* relink to destination frame */
|
|
|
|
BLI_addtail(&gpf_dst->strokes, gps);
|
2019-06-12 09:04:10 +10:00
|
|
|
/* Reassign material. */
|
2019-03-25 17:02:42 +01:00
|
|
|
gps->mat_nr = idx;
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* if not multiedit, exit loop*/
|
|
|
|
if (!is_multiedit) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
|
|
|
}
|
|
|
|
else if (mode == GP_SEPARATE_LAYER) {
|
|
|
|
bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
|
|
|
|
if (gpl) {
|
|
|
|
/* try to set a new active layer in source datablock */
|
|
|
|
if (gpl->prev) {
|
2020-03-09 16:27:24 +01:00
|
|
|
BKE_gpencil_layer_active_set(gpd_src, gpl->prev);
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
|
|
|
else if (gpl->next) {
|
2020-03-09 16:27:24 +01:00
|
|
|
BKE_gpencil_layer_active_set(gpd_src, gpl->next);
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
|
|
|
/* unlink from source datablock */
|
|
|
|
BLI_remlink(&gpd_src->layers, gpl);
|
|
|
|
gpl->prev = gpl->next = NULL;
|
|
|
|
/* relink to destination datablock */
|
|
|
|
BLI_addtail(&gpd_dst->layers, gpl);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-18 10:52:38 +01:00
|
|
|
/* add duplicate materials */
|
2020-03-09 16:27:24 +01:00
|
|
|
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
|
|
|
|
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
2019-01-18 10:52:38 +01:00
|
|
|
/* skip strokes that are invalid for current view */
|
|
|
|
if (ED_gpencil_stroke_can_use(C, gps) == false) {
|
|
|
|
continue;
|
|
|
|
}
|
2020-02-05 11:23:58 +01:00
|
|
|
ma = BKE_gpencil_material(ob, gps->mat_nr + 1);
|
2019-04-09 09:22:46 +02:00
|
|
|
gps->mat_nr = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma);
|
2019-01-18 10:52:38 +01:00
|
|
|
}
|
|
|
|
}
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-02-18 11:11:22 +01:00
|
|
|
/* Ensure destination object has one active layer. */
|
|
|
|
if (gpd_dst->layers.first != NULL) {
|
2020-03-09 16:27:24 +01:00
|
|
|
if (BKE_gpencil_layer_active_get(gpd_dst) == NULL) {
|
|
|
|
BKE_gpencil_layer_active_set(gpd_dst, gpd_dst->layers.first);
|
2020-02-18 11:11:22 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-26 17:22:37 +02:00
|
|
|
/* Remove unused slots. */
|
|
|
|
int actcol = ob_dst->actcol;
|
|
|
|
for (int slot = 1; slot <= ob_dst->totcol; slot++) {
|
|
|
|
while (slot <= ob_dst->totcol && !BKE_object_material_slot_used(ob_dst->data, slot)) {
|
|
|
|
ob_dst->actcol = slot;
|
|
|
|
BKE_object_material_slot_remove(bmain, ob_dst);
|
|
|
|
if (actcol >= slot) {
|
|
|
|
actcol--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ob_dst->actcol = actcol;
|
|
|
|
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&gpd_src->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
|
|
|
DEG_id_tag_update(&gpd_dst->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
DEG_relations_tag_update(bmain);
|
|
|
|
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
2020-04-02 16:52:43 +02:00
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, NULL);
|
2020-05-01 20:06:38 -06:00
|
|
|
ED_outliner_select_sync_from_object_tag(C);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_stroke_separate(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
static const EnumPropertyItem separate_type[] = {
|
2018-08-30 01:36:52 +10:00
|
|
|
{GP_SEPARATE_POINT, "POINT", 0, "Selected Points", "Separate the selected points"},
|
|
|
|
{GP_SEPARATE_STROKE, "STROKE", 0, "Selected Strokes", "Separate the selected strokes"},
|
|
|
|
{GP_SEPARATE_LAYER, "LAYER", 0, "Active Layer", "Separate the strokes of the current layer"},
|
2019-02-03 14:01:45 +11:00
|
|
|
{0, NULL, 0, NULL, NULL},
|
2018-07-31 10:22:19 +02:00
|
|
|
};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Separate Strokes";
|
|
|
|
ot->idname = "GPENCIL_OT_stroke_separate";
|
|
|
|
ot->description = "Separate the selected strokes or layer in a new grease pencil object";
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* callbacks */
|
|
|
|
ot->invoke = WM_menu_invoke;
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_stroke_separate_exec;
|
|
|
|
ot->poll = gpencil_strokes_edit3d_poll;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* properties */
|
|
|
|
ot->prop = RNA_def_enum(ot->srna, "mode", separate_type, GP_SEPARATE_POINT, "Mode", "");
|
|
|
|
}
|
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Stroke Split Operator
|
|
|
|
* \{ */
|
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
static int gpencil_stroke_split_exec(bContext *C, wmOperator *op)
|
2018-07-31 10:22:19 +02:00
|
|
|
{
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
|
|
|
bGPDspoint *pt;
|
|
|
|
int i;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* sanity checks */
|
|
|
|
if (ELEM(NULL, gpd)) {
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2018-09-25 20:23:55 +02:00
|
|
|
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
|
2020-11-13 21:43:00 +01:00
|
|
|
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* loop strokes and split parts */
|
|
|
|
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
|
2019-06-07 11:46:11 +02:00
|
|
|
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
|
|
|
|
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
if (gpf == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* skip strokes that are invalid for current view */
|
|
|
|
if (ED_gpencil_stroke_can_use(C, gps) == false) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* check if the color is editable */
|
2021-01-16 16:44:49 +01:00
|
|
|
if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) {
|
2018-07-31 10:22:19 +02:00
|
|
|
continue;
|
|
|
|
}
|
2020-03-29 16:33:51 +11:00
|
|
|
/* Split selected strokes. */
|
2018-07-31 10:22:19 +02:00
|
|
|
if (gps->flag & GP_STROKE_SELECT) {
|
2020-11-13 21:43:00 +01:00
|
|
|
if (is_curve_edit) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "Not implemented!");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* make copy of source stroke */
|
|
|
|
bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps, true, true);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* link to same frame */
|
|
|
|
BLI_addtail(&gpf->strokes, gps_dst);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* invert selection status of all points in destination stroke */
|
|
|
|
for (i = 0, pt = gps_dst->points; i < gps_dst->totpoints; i++, pt++) {
|
|
|
|
pt->flag ^= GP_SPOINT_SELECT;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* delete selected points from destination stroke */
|
2020-11-18 21:30:43 +01:00
|
|
|
BKE_gpencil_stroke_delete_tagged_points(
|
2020-11-13 21:43:00 +01:00
|
|
|
gpd, gpf, gps_dst, NULL, GP_SPOINT_SELECT, true, 0);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
/* delete selected points from origin stroke */
|
2020-11-18 21:30:43 +01:00
|
|
|
BKE_gpencil_stroke_delete_tagged_points(
|
2020-11-13 21:43:00 +01:00
|
|
|
gpd, gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0);
|
|
|
|
}
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* select again tagged points */
|
2020-03-09 16:27:24 +01:00
|
|
|
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
2018-07-31 10:22:19 +02:00
|
|
|
bGPDspoint *ptn = gps->points;
|
|
|
|
for (int i2 = 0; i2 < gps->totpoints; i2++, ptn++) {
|
|
|
|
if (ptn->flag & GP_SPOINT_TAG) {
|
|
|
|
ptn->flag |= GP_SPOINT_SELECT;
|
|
|
|
ptn->flag &= ~GP_SPOINT_TAG;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
/* if not multiedit, exit loop*/
|
|
|
|
if (!is_multiedit) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_stroke_split(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Split Strokes";
|
|
|
|
ot->idname = "GPENCIL_OT_stroke_split";
|
|
|
|
ot->description = "Split selected points as new stroke on same frame";
|
|
|
|
|
|
|
|
/* callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_stroke_split_exec;
|
|
|
|
ot->poll = gpencil_strokes_edit3d_poll;
|
2018-07-31 10:22:19 +02:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
}
|
2018-12-13 19:49:13 +01:00
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Stroke Smooth Operator
|
|
|
|
* \{ */
|
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_stroke_smooth_exec(bContext *C, wmOperator *op)
|
2018-12-13 19:49:13 +01:00
|
|
|
{
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
|
|
|
|
|
|
|
/* sanity checks */
|
2019-04-22 09:19:45 +10:00
|
|
|
if (ELEM(NULL, gpd)) {
|
2018-12-13 19:49:13 +01:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2018-12-13 19:49:13 +01:00
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
gpencil_smooth_stroke(C, op);
|
2018-12-13 19:49:13 +01:00
|
|
|
|
|
|
|
/* notifiers */
|
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_stroke_smooth(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-12-13 19:49:13 +01:00
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Smooth Stroke";
|
|
|
|
ot->idname = "GPENCIL_OT_stroke_smooth";
|
|
|
|
ot->description = "Smooth selected strokes";
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-12-13 19:49:13 +01:00
|
|
|
/* api callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_stroke_smooth_exec;
|
2020-11-13 21:43:00 +01:00
|
|
|
ot->poll = gpencil_stroke_not_in_curve_edit_mode;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-12-13 19:49:13 +01:00
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-12-13 19:49:13 +01:00
|
|
|
/* properties */
|
2019-08-15 17:49:55 +02:00
|
|
|
prop = RNA_def_int(ot->srna, "repeat", 1, 1, 50, "Repeat", "", 1, 20);
|
2018-12-13 19:49:13 +01:00
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-12-13 19:49:13 +01:00
|
|
|
RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 2.0f, "Factor", "", 0.0f, 2.0f);
|
2019-03-15 08:53:22 +11:00
|
|
|
RNA_def_boolean(ot->srna,
|
|
|
|
"only_selected",
|
|
|
|
true,
|
|
|
|
"Selected Points",
|
|
|
|
"Smooth only selected points in the stroke");
|
2018-12-13 19:49:13 +01:00
|
|
|
RNA_def_boolean(ot->srna, "smooth_position", true, "Position", "");
|
|
|
|
RNA_def_boolean(ot->srna, "smooth_thickness", true, "Thickness", "");
|
|
|
|
RNA_def_boolean(ot->srna, "smooth_strength", false, "Strength", "");
|
|
|
|
RNA_def_boolean(ot->srna, "smooth_uv", false, "UV", "");
|
|
|
|
}
|
2019-01-11 19:15:23 +01:00
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Stroke Cutter Operator
|
|
|
|
* \{ */
|
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
/* smart stroke cutter for trimming stroke ends */
|
|
|
|
struct GP_SelectLassoUserData {
|
|
|
|
rcti rect;
|
2020-05-04 19:50:06 +10:00
|
|
|
const int (*mcoords)[2];
|
|
|
|
int mcoords_len;
|
2019-01-11 19:15:23 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
static bool gpencil_test_lasso(bGPDstroke *gps,
|
|
|
|
bGPDspoint *pt,
|
|
|
|
const GP_SpaceConversion *gsc,
|
|
|
|
const float diff_mat[4][4],
|
|
|
|
void *user_data)
|
|
|
|
{
|
|
|
|
const struct GP_SelectLassoUserData *data = user_data;
|
|
|
|
bGPDspoint pt2;
|
|
|
|
int x0, y0;
|
2020-06-29 12:49:30 +02:00
|
|
|
gpencil_point_to_parent_space(pt, diff_mat, &pt2);
|
|
|
|
gpencil_point_to_xy(gsc, gps, &pt2, &x0, &y0);
|
2019-01-11 19:15:23 +01:00
|
|
|
/* test if in lasso */
|
|
|
|
return ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(&data->rect, x0, y0) &&
|
2020-05-04 19:50:06 +10:00
|
|
|
BLI_lasso_is_point_inside(data->mcoords, data->mcoords_len, x0, y0, INT_MAX));
|
2019-01-11 19:15:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
typedef bool (*GPencilTestFn)(bGPDstroke *gps,
|
|
|
|
bGPDspoint *pt,
|
|
|
|
const GP_SpaceConversion *gsc,
|
|
|
|
const float diff_mat[4][4],
|
|
|
|
void *user_data);
|
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
static void gpencil_cutter_dissolve(bGPdata *gpd,
|
|
|
|
bGPDlayer *hit_layer,
|
2020-10-22 17:35:48 +02:00
|
|
|
bGPDstroke *hit_stroke,
|
|
|
|
const bool flat_caps)
|
2019-01-11 19:15:23 +01:00
|
|
|
{
|
|
|
|
bGPDspoint *pt = NULL;
|
|
|
|
bGPDspoint *pt1 = NULL;
|
|
|
|
int i;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
bGPDstroke *gpsn = hit_stroke->next;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
int totselect = 0;
|
|
|
|
for (i = 0, pt = hit_stroke->points; i < hit_stroke->totpoints; i++, pt++) {
|
|
|
|
if (pt->flag & GP_SPOINT_SELECT) {
|
|
|
|
totselect++;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
/* if all points selected delete or only 2 points and 1 selected */
|
2019-01-14 11:42:28 +11:00
|
|
|
if (((totselect == 1) && (hit_stroke->totpoints == 2)) || (hit_stroke->totpoints == totselect)) {
|
2019-01-11 19:15:23 +01:00
|
|
|
BLI_remlink(&hit_layer->actframe->strokes, hit_stroke);
|
|
|
|
BKE_gpencil_free_stroke(hit_stroke);
|
|
|
|
hit_stroke = NULL;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
/* if very small distance delete */
|
|
|
|
if ((hit_stroke) && (hit_stroke->totpoints == 2)) {
|
|
|
|
pt = &hit_stroke->points[0];
|
|
|
|
pt1 = &hit_stroke->points[1];
|
|
|
|
if (len_v3v3(&pt->x, &pt1->x) < 0.001f) {
|
|
|
|
BLI_remlink(&hit_layer->actframe->strokes, hit_stroke);
|
|
|
|
BKE_gpencil_free_stroke(hit_stroke);
|
|
|
|
hit_stroke = NULL;
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
if (hit_stroke) {
|
|
|
|
/* tag and dissolve (untag new points) */
|
|
|
|
for (i = 0, pt = hit_stroke->points; i < hit_stroke->totpoints; i++, pt++) {
|
|
|
|
if (pt->flag & GP_SPOINT_SELECT) {
|
|
|
|
pt->flag &= ~GP_SPOINT_SELECT;
|
|
|
|
pt->flag |= GP_SPOINT_TAG;
|
|
|
|
}
|
|
|
|
else if (pt->flag & GP_SPOINT_TAG) {
|
|
|
|
pt->flag &= ~GP_SPOINT_TAG;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2020-10-22 17:35:48 +02:00
|
|
|
/* If flat caps mode check extremes. */
|
|
|
|
if (flat_caps) {
|
|
|
|
if (hit_stroke->points[0].flag & GP_SPOINT_TAG) {
|
|
|
|
hit_stroke->caps[0] = GP_STROKE_CAP_FLAT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hit_stroke->points[hit_stroke->totpoints - 1].flag & GP_SPOINT_TAG) {
|
|
|
|
hit_stroke->caps[1] = GP_STROKE_CAP_FLAT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-18 21:30:43 +01:00
|
|
|
BKE_gpencil_stroke_delete_tagged_points(
|
2020-11-13 21:43:00 +01:00
|
|
|
gpd, hit_layer->actframe, hit_stroke, gpsn, GP_SPOINT_TAG, false, 1);
|
2019-01-11 19:15:23 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int gpencil_cutter_lasso_select(bContext *C,
|
|
|
|
wmOperator *op,
|
|
|
|
GPencilTestFn is_inside_fn,
|
|
|
|
void *user_data)
|
|
|
|
{
|
2021-02-08 16:28:42 +01:00
|
|
|
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
|
|
|
Object *obact = CTX_data_active_object(C);
|
2019-01-11 19:15:23 +01:00
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
2020-04-03 13:25:03 +02:00
|
|
|
ScrArea *area = CTX_wm_area(C);
|
2019-01-11 19:15:23 +01:00
|
|
|
ToolSettings *ts = CTX_data_tool_settings(C);
|
|
|
|
const float scale = ts->gp_sculpt.isect_threshold;
|
2020-10-22 17:35:48 +02:00
|
|
|
const bool flat_caps = RNA_boolean_get(op->ptr, "flat_caps");
|
2021-02-08 16:28:42 +01:00
|
|
|
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
bGPDspoint *pt;
|
|
|
|
GP_SpaceConversion gsc = {NULL};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
bool changed = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
/* sanity checks */
|
2020-04-03 13:25:03 +02:00
|
|
|
if (area == NULL) {
|
2019-01-11 19:15:23 +01:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "No active area");
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
/* init space conversion stuff */
|
2020-06-29 12:49:30 +02:00
|
|
|
gpencil_point_conversion_init(C, &gsc);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-03-30 19:43:45 +02:00
|
|
|
/* Deselect all strokes. */
|
|
|
|
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
|
|
|
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
|
|
|
|
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
|
|
|
|
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
|
|
|
if (gps->flag & GP_STROKE_SELECT) {
|
|
|
|
int i;
|
|
|
|
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
|
|
|
pt->flag &= ~GP_SPOINT_SELECT;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-03-30 19:43:45 +02:00
|
|
|
gps->flag &= ~GP_STROKE_SELECT;
|
|
|
|
BKE_gpencil_stroke_select_index_reset(gps);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* if not multiedit, exit loop. */
|
|
|
|
if (!is_multiedit) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-01-11 19:15:23 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-02-08 16:28:42 +01:00
|
|
|
/* Select points */
|
|
|
|
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
|
|
|
if ((gpl->flag & GP_LAYER_LOCKED) || ((gpl->flag & GP_LAYER_HIDE))) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
float diff_mat[4][4];
|
|
|
|
BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat);
|
|
|
|
|
|
|
|
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
|
|
|
|
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
|
|
|
|
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
|
|
|
|
if (gpf == NULL) {
|
|
|
|
continue;
|
2019-01-11 19:15:23 +01:00
|
|
|
}
|
2021-02-08 16:28:42 +01:00
|
|
|
|
|
|
|
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
|
|
|
if (ED_gpencil_stroke_can_use(C, gps) == false) {
|
|
|
|
continue;
|
|
|
|
} /* check if the color is editable */
|
|
|
|
if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
int tot_inside = 0;
|
|
|
|
const int oldtot = gps->totpoints;
|
|
|
|
for (int i = 0; i < gps->totpoints; i++) {
|
|
|
|
pt = &gps->points[i];
|
|
|
|
if ((pt->flag & GP_SPOINT_SELECT) || (pt->flag & GP_SPOINT_TAG)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* convert point coords to screen-space */
|
|
|
|
const bool is_inside = is_inside_fn(gps, pt, &gsc, diff_mat, user_data);
|
|
|
|
if (is_inside) {
|
|
|
|
tot_inside++;
|
|
|
|
changed = true;
|
|
|
|
pt->flag |= GP_SPOINT_SELECT;
|
|
|
|
gps->flag |= GP_STROKE_SELECT;
|
2021-02-20 10:16:51 +01:00
|
|
|
BKE_gpencil_stroke_select_index_set(gpd, gps);
|
2021-02-08 16:28:42 +01:00
|
|
|
float r_hita[3], r_hitb[3];
|
|
|
|
if (gps->totpoints > 1) {
|
|
|
|
ED_gpencil_select_stroke_segment(
|
|
|
|
gpd, gpl, gps, pt, true, true, scale, r_hita, r_hitb);
|
|
|
|
}
|
|
|
|
/* avoid infinite loops */
|
|
|
|
if (gps->totpoints > oldtot) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* if mark all points inside lasso set to remove all stroke */
|
|
|
|
if ((tot_inside == oldtot) || ((tot_inside == 1) && (oldtot == 2))) {
|
|
|
|
for (int i = 0; i < gps->totpoints; i++) {
|
|
|
|
pt = &gps->points[i];
|
|
|
|
pt->flag |= GP_SPOINT_SELECT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* if not multiedit, exit loop. */
|
|
|
|
if (!is_multiedit) {
|
2019-01-11 19:15:23 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-02-08 16:28:42 +01:00
|
|
|
/* Dissolve selected points. */
|
2020-03-09 16:27:24 +01:00
|
|
|
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
2021-02-08 16:28:42 +01:00
|
|
|
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
|
|
|
|
bGPDframe *gpf_act = gpl->actframe;
|
|
|
|
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
|
|
|
|
gpl->actframe = gpf;
|
|
|
|
LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
|
|
|
|
if (gps->flag & GP_STROKE_SELECT) {
|
|
|
|
gpencil_cutter_dissolve(gpd, gpl, gps, flat_caps);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* if not multiedit, exit loop. */
|
|
|
|
if (!is_multiedit) {
|
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-01-11 19:15:23 +01:00
|
|
|
}
|
2021-02-08 16:28:42 +01:00
|
|
|
gpl->actframe = gpf_act;
|
2019-01-11 19:15:23 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
/* updates */
|
|
|
|
if (changed) {
|
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
|
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool gpencil_cutter_poll(bContext *C)
|
|
|
|
{
|
|
|
|
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
|
|
|
|
|
|
|
if (GPENCIL_PAINT_MODE(gpd)) {
|
2019-04-22 09:19:45 +10:00
|
|
|
if (gpd->layers.first) {
|
2019-01-11 19:15:23 +01:00
|
|
|
return true;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-01-11 19:15:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int gpencil_cutter_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2020-04-03 13:25:03 +02:00
|
|
|
ScrArea *area = CTX_wm_area(C);
|
2019-01-11 19:15:23 +01:00
|
|
|
/* sanity checks */
|
2020-04-03 13:25:03 +02:00
|
|
|
if (area == NULL) {
|
2019-01-11 19:15:23 +01:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "No active area");
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct GP_SelectLassoUserData data = {0};
|
2020-05-04 19:50:06 +10:00
|
|
|
data.mcoords = WM_gesture_lasso_path_to_array(C, op, &data.mcoords_len);
|
2019-01-11 19:15:23 +01:00
|
|
|
|
|
|
|
/* Sanity check. */
|
2020-05-04 19:50:06 +10:00
|
|
|
if (data.mcoords == NULL) {
|
2019-01-11 19:15:23 +01:00
|
|
|
return OPERATOR_PASS_THROUGH;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Compute boundbox of lasso (for faster testing later). */
|
2020-05-04 19:50:06 +10:00
|
|
|
BLI_lasso_boundbox(&data.rect, data.mcoords, data.mcoords_len);
|
2019-01-11 19:15:23 +01:00
|
|
|
|
|
|
|
gpencil_cutter_lasso_select(C, op, gpencil_test_lasso, &data);
|
|
|
|
|
2020-05-04 19:50:06 +10:00
|
|
|
MEM_freeN((void *)data.mcoords);
|
2019-01-11 19:15:23 +01:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_stroke_cutter(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Stroke Cutter";
|
|
|
|
ot->description = "Select section and cut";
|
|
|
|
ot->idname = "GPENCIL_OT_stroke_cutter";
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
/* callbacks */
|
|
|
|
ot->invoke = WM_gesture_lasso_invoke;
|
|
|
|
ot->modal = WM_gesture_lasso_modal;
|
|
|
|
ot->exec = gpencil_cutter_exec;
|
|
|
|
ot->poll = gpencil_cutter_poll;
|
|
|
|
ot->cancel = WM_gesture_lasso_cancel;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
/* flag */
|
2019-07-25 16:36:22 +02:00
|
|
|
ot->flag = OPTYPE_UNDO;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-11 19:15:23 +01:00
|
|
|
/* properties */
|
|
|
|
WM_operator_properties_gesture_lasso(ot);
|
2020-10-22 17:35:48 +02:00
|
|
|
|
|
|
|
RNA_def_boolean(ot->srna, "flat_caps", 0, "Flat Caps", "");
|
2019-01-11 19:15:23 +01:00
|
|
|
}
|
2019-06-28 13:54:09 +02:00
|
|
|
|
|
|
|
bool ED_object_gpencil_exit(struct Main *bmain, Object *ob)
|
|
|
|
{
|
|
|
|
bool ok = false;
|
|
|
|
if (ob) {
|
|
|
|
bGPdata *gpd = (bGPdata *)ob->data;
|
|
|
|
|
|
|
|
gpd->flag &= ~(GP_DATA_STROKE_PAINTMODE | GP_DATA_STROKE_EDITMODE | GP_DATA_STROKE_SCULPTMODE |
|
2020-03-09 16:27:24 +01:00
|
|
|
GP_DATA_STROKE_WEIGHTMODE | GP_DATA_STROKE_VERTEXMODE);
|
2019-06-28 13:54:09 +02:00
|
|
|
|
|
|
|
ob->restore_mode = ob->mode;
|
|
|
|
ob->mode &= ~(OB_MODE_PAINT_GPENCIL | OB_MODE_EDIT_GPENCIL | OB_MODE_SCULPT_GPENCIL |
|
2020-03-09 16:27:24 +01:00
|
|
|
OB_MODE_WEIGHT_GPENCIL | OB_MODE_VERTEX_GPENCIL);
|
2019-06-28 13:54:09 +02:00
|
|
|
|
|
|
|
/* Inform all CoW versions that we changed the mode. */
|
|
|
|
DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_COPY_ON_WRITE);
|
|
|
|
ok = true;
|
|
|
|
}
|
|
|
|
return ok;
|
|
|
|
}
|
2019-08-08 10:23:05 +02:00
|
|
|
|
2020-05-06 12:45:04 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Merge By Distance Operator
|
|
|
|
* \{ */
|
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static bool gpencil_merge_by_distance_poll(bContext *C)
|
2019-08-08 10:23:05 +02:00
|
|
|
{
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
2019-08-10 10:20:30 +02:00
|
|
|
if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
|
2019-08-08 10:23:05 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
bGPdata *gpd = (bGPdata *)ob->data;
|
|
|
|
if (gpd == NULL) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
|
2019-08-08 10:23:05 +02:00
|
|
|
|
|
|
|
return ((gpl != NULL) && (ob->mode == OB_MODE_EDIT_GPENCIL));
|
|
|
|
}
|
|
|
|
|
2020-06-29 15:28:38 +02:00
|
|
|
static int gpencil_merge_by_distance_exec(bContext *C, wmOperator *op)
|
2019-08-08 10:23:05 +02:00
|
|
|
{
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
bGPdata *gpd = (bGPdata *)ob->data;
|
|
|
|
const float threshold = RNA_float_get(op->ptr, "threshold");
|
|
|
|
const bool unselected = RNA_boolean_get(op->ptr, "use_unselected");
|
|
|
|
|
|
|
|
/* sanity checks */
|
|
|
|
if (ELEM(NULL, gpd)) {
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2020-11-13 21:43:00 +01:00
|
|
|
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
|
|
|
|
|
|
|
if (is_curve_edit) {
|
|
|
|
/* TODO: merge curve points by distance */
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* Go through each editable selected stroke */
|
|
|
|
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
|
|
|
|
if (gps->flag & GP_STROKE_SELECT) {
|
|
|
|
BKE_gpencil_stroke_merge_distance(gpd, gpf_, gps, threshold, unselected);
|
|
|
|
}
|
2019-08-08 10:23:05 +02:00
|
|
|
}
|
2020-11-13 21:43:00 +01:00
|
|
|
GP_EDITABLE_STROKES_END(gpstroke_iter);
|
2019-08-08 10:23:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* notifiers */
|
|
|
|
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPENCIL_OT_stroke_merge_by_distance(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Merge by Distance";
|
|
|
|
ot->idname = "GPENCIL_OT_stroke_merge_by_distance";
|
|
|
|
ot->description = "Merge points by distance";
|
|
|
|
|
|
|
|
/* api callbacks */
|
2020-06-29 15:28:38 +02:00
|
|
|
ot->exec = gpencil_merge_by_distance_exec;
|
|
|
|
ot->poll = gpencil_merge_by_distance_poll;
|
2019-08-08 10:23:05 +02:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
|
|
|
|
/* properties */
|
|
|
|
prop = RNA_def_float(ot->srna, "threshold", 0.001f, 0.0f, 100.0f, "Threshold", "", 0.0f, 100.0f);
|
|
|
|
/* avoid re-using last var */
|
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
|
|
|
|
|
|
|
prop = RNA_def_boolean(
|
|
|
|
ot->srna, "use_unselected", 0, "Unselected", "Use whole stroke, not only selected points");
|
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
|
|
|
}
|
2020-11-25 17:04:22 +01:00
|
|
|
/** \} */
|