GPv3: Remove unused legacy editor functions for GPv2

Removes all unused functions in ED_gpencil_legacy.hh

Pull Request: https://projects.blender.org/blender/blender/pulls/128597
This commit is contained in:
Lukas Tönne
2024-10-07 18:21:28 +02:00
parent 68c665ffa1
commit a57206dd59
54 changed files with 26 additions and 10051 deletions

View File

@@ -1205,8 +1205,6 @@ context_type_map = {
"edit_object": [("Object", False)], "edit_object": [("Object", False)],
"edit_text": [("Text", False)], "edit_text": [("Text", False)],
"editable_bones": [("EditBone", True)], "editable_bones": [("EditBone", True)],
"editable_gpencil_layers": [("GPencilLayer", True)],
"editable_gpencil_strokes": [("GPencilStroke", True)],
"editable_objects": [("Object", True)], "editable_objects": [("Object", True)],
"editable_fcurves": [("FCurve", True)], "editable_fcurves": [("FCurve", True)],
"fluid": [("FluidSimulationModifier", False)], "fluid": [("FluidSimulationModifier", False)],

View File

@@ -103,18 +103,6 @@ class VIEW3D_HT_tool_header(Header):
# if tool.use_brushes: # if tool.use_brushes:
# layout.popover_group(context=".paint_common", **popover_kw) # layout.popover_group(context=".paint_common", **popover_kw)
pass pass
elif tool_mode == 'PAINT_GPENCIL':
if is_valid_context:
brush = context.tool_settings.gpencil_paint.brush
if brush:
if brush.gpencil_tool != 'ERASE':
if brush.gpencil_tool != 'TINT':
layout.popover("VIEW3D_PT_tools_grease_pencil_brush_advanced")
if brush.gpencil_tool not in {'FILL', 'TINT'}:
layout.popover("VIEW3D_PT_tools_grease_pencil_brush_stroke")
layout.popover("VIEW3D_PT_tools_grease_pencil_paint_appearance")
elif tool_mode == 'PAINT_GREASE_PENCIL': elif tool_mode == 'PAINT_GREASE_PENCIL':
if is_valid_context: if is_valid_context:
brush = context.tool_settings.gpencil_paint.brush brush = context.tool_settings.gpencil_paint.brush
@@ -126,14 +114,6 @@ class VIEW3D_HT_tool_header(Header):
if brush.gpencil_tool not in {'FILL', 'TINT'}: if brush.gpencil_tool not in {'FILL', 'TINT'}:
layout.popover("VIEW3D_PT_tools_grease_pencil_v3_brush_stroke") layout.popover("VIEW3D_PT_tools_grease_pencil_v3_brush_stroke")
layout.popover("VIEW3D_PT_tools_grease_pencil_paint_appearance") layout.popover("VIEW3D_PT_tools_grease_pencil_paint_appearance")
elif tool_mode == 'SCULPT_GPENCIL':
if is_valid_context:
brush = context.tool_settings.gpencil_sculpt_paint.brush
if brush:
tool = brush.gpencil_sculpt_tool
if tool in {'SMOOTH', 'RANDOMIZE'}:
layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_brush_popover")
layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_appearance")
elif tool_mode == 'SCULPT_GREASE_PENCIL': elif tool_mode == 'SCULPT_GREASE_PENCIL':
if is_valid_context: if is_valid_context:
brush = context.tool_settings.gpencil_sculpt_paint.brush brush = context.tool_settings.gpencil_sculpt_paint.brush

View File

@@ -1588,21 +1588,6 @@ class GreasePencilPaintPanel:
bl_context = ".greasepencil_paint" bl_context = ".greasepencil_paint"
bl_category = "Tool" bl_category = "Tool"
@classmethod
def poll(cls, context):
if context.space_data.type in {'VIEW_3D', 'PROPERTIES'}:
if context.gpencil_data is None:
return False
# Hide for tools not using brushes.
if tool_use_brush(context) is False:
return False
gpd = context.gpencil_data
return bool(gpd.is_stroke_paint_mode)
else:
return True
class VIEW3D_PT_tools_grease_pencil_brush_select(Panel, View3DPanel, GreasePencilPaintPanel, BrushSelectPanel): class VIEW3D_PT_tools_grease_pencil_brush_select(Panel, View3DPanel, GreasePencilPaintPanel, BrushSelectPanel):
bl_label = "Brush Asset" bl_label = "Brush Asset"
@@ -1981,17 +1966,6 @@ class GreasePencilSculptPanel:
bl_context = ".greasepencil_sculpt" bl_context = ".greasepencil_sculpt"
bl_category = "Tool" bl_category = "Tool"
@classmethod
def poll(cls, context):
if context.space_data.type in {'VIEW_3D', 'PROPERTIES'}:
if context.gpencil_data is None:
return False
gpd = context.gpencil_data
return bool(gpd.is_stroke_sculpt_mode)
else:
return True
class VIEW3D_PT_tools_grease_pencil_sculpt_select(Panel, View3DPanel, GreasePencilSculptPanel, BrushSelectPanel): class VIEW3D_PT_tools_grease_pencil_sculpt_select(Panel, View3DPanel, GreasePencilSculptPanel, BrushSelectPanel):
bl_label = "Brush Asset" bl_label = "Brush Asset"
@@ -2068,20 +2042,6 @@ class GreasePencilWeightPanel:
bl_context = ".greasepencil_weight" bl_context = ".greasepencil_weight"
bl_category = "Tool" bl_category = "Tool"
@classmethod
def poll(cls, context):
if context.space_data.type in {'VIEW_3D', 'PROPERTIES'}:
if context.object and context.object.type == 'GREASEPENCIL' and context.mode == 'WEIGHT_GREASE_PENCIL':
return True
if context.gpencil_data is None:
return False
gpd = context.gpencil_data
return bool(gpd.is_stroke_weight_mode)
else:
return True
class VIEW3D_PT_tools_grease_pencil_weight_paint_select(View3DPanel, Panel, GreasePencilWeightPanel, BrushSelectPanel): class VIEW3D_PT_tools_grease_pencil_weight_paint_select(View3DPanel, Panel, GreasePencilWeightPanel, BrushSelectPanel):
bl_label = "Brush Asset" bl_label = "Brush Asset"
@@ -2148,17 +2108,6 @@ class GreasePencilVertexPanel:
bl_context = ".greasepencil_vertex" bl_context = ".greasepencil_vertex"
bl_category = "Tool" bl_category = "Tool"
@classmethod
def poll(cls, context):
if context.space_data.type in {'VIEW_3D', 'PROPERTIES'}:
if context.gpencil_data is None:
return False
gpd = context.gpencil_data
return bool(gpd.is_stroke_vertex_mode)
else:
return True
class VIEW3D_PT_tools_grease_pencil_vertex_paint_select(View3DPanel, Panel, GreasePencilVertexPanel, BrushSelectPanel): class VIEW3D_PT_tools_grease_pencil_vertex_paint_select(View3DPanel, Panel, GreasePencilVertexPanel, BrushSelectPanel):
bl_label = "Brush Asset" bl_label = "Brush Asset"

View File

@@ -426,13 +426,6 @@ bool CTX_data_selected_pose_bones_from_active_object(const bContext *C,
blender::Vector<PointerRNA> *list); blender::Vector<PointerRNA> *list);
bool CTX_data_visible_pose_bones(const bContext *C, blender::Vector<PointerRNA> *list); bool CTX_data_visible_pose_bones(const bContext *C, blender::Vector<PointerRNA> *list);
bGPdata *CTX_data_gpencil_data(const bContext *C);
bGPDlayer *CTX_data_active_gpencil_layer(const bContext *C);
bGPDframe *CTX_data_active_gpencil_frame(const bContext *C);
bool CTX_data_visible_gpencil_layers(const bContext *C, blender::Vector<PointerRNA> *list);
bool CTX_data_editable_gpencil_layers(const bContext *C, blender::Vector<PointerRNA> *list);
bool CTX_data_editable_gpencil_strokes(const bContext *C, blender::Vector<PointerRNA> *list);
const AssetLibraryReference *CTX_wm_asset_library_ref(const bContext *C); const AssetLibraryReference *CTX_wm_asset_library_ref(const bContext *C);
class blender::asset_system::AssetRepresentation *CTX_wm_asset(const bContext *C); class blender::asset_system::AssetRepresentation *CTX_wm_asset(const bContext *C);

View File

@@ -1496,36 +1496,6 @@ bool CTX_data_visible_pose_bones(const bContext *C, blender::Vector<PointerRNA>
return ctx_data_collection_get(C, "visible_pose_bones", list); return ctx_data_collection_get(C, "visible_pose_bones", list);
} }
bGPdata *CTX_data_gpencil_data(const bContext *C)
{
return static_cast<bGPdata *>(ctx_data_pointer_get(C, "gpencil_data"));
}
bGPDlayer *CTX_data_active_gpencil_layer(const bContext *C)
{
return static_cast<bGPDlayer *>(ctx_data_pointer_get(C, "active_gpencil_layer"));
}
bGPDframe *CTX_data_active_gpencil_frame(const bContext *C)
{
return static_cast<bGPDframe *>(ctx_data_pointer_get(C, "active_gpencil_frame"));
}
bool CTX_data_visible_gpencil_layers(const bContext *C, blender::Vector<PointerRNA> *list)
{
return ctx_data_collection_get(C, "visible_gpencil_layers", list);
}
bool CTX_data_editable_gpencil_layers(const bContext *C, blender::Vector<PointerRNA> *list)
{
return ctx_data_collection_get(C, "editable_gpencil_layers", list);
}
bool CTX_data_editable_gpencil_strokes(const bContext *C, blender::Vector<PointerRNA> *list)
{
return ctx_data_collection_get(C, "editable_gpencil_strokes", list);
}
const AssetLibraryReference *CTX_wm_asset_library_ref(const bContext *C) const AssetLibraryReference *CTX_wm_asset_library_ref(const bContext *C)
{ {
return static_cast<AssetLibraryReference *>(ctx_data_pointer_get(C, "asset_library_reference")); return static_cast<AssetLibraryReference *>(ctx_data_pointer_get(C, "asset_library_reference"));

View File

@@ -21,13 +21,7 @@ set(INC_SYS
set(SRC set(SRC
annotate_draw.cc annotate_draw.cc
annotate_paint.cc annotate_paint.cc
drawgpencil.cc
editaction_gpencil.cc editaction_gpencil.cc
gpencil_add_blank.cc
gpencil_add_lineart.cc
gpencil_add_monkey.cc
gpencil_add_stroke.cc
gpencil_armature.cc
gpencil_data.cc gpencil_data.cc
gpencil_edit.cc gpencil_edit.cc
gpencil_ops.cc gpencil_ops.cc

View File

@@ -2519,7 +2519,8 @@ static int annotation_draw_modal(bContext *C, wmOperator *op, const wmEvent *eve
* - Since this operator is non-modal, we can just call it here, and keep going... * - Since this operator is non-modal, we can just call it here, and keep going...
* - This operator is especially useful when animating * - This operator is especially useful when animating
*/ */
WM_operator_name_call(C, "GPENCIL_OT_blank_frame_add", WM_OP_EXEC_DEFAULT, nullptr, event); WM_operator_name_call(
C, "GPENCIL_OT_layer_annotation_add", WM_OP_EXEC_DEFAULT, nullptr, event);
estate = OPERATOR_RUNNING_MODAL; estate = OPERATOR_RUNNING_MODAL;
} }
else { else {

View File

@@ -1,393 +0,0 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edgpencil
*/
#include <cfloat>
#include <cmath>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "MEM_guardedalloc.h"
#include "BLI_sys_types.h"
#include "BLI_math_matrix.h"
#include "BLI_utildefines.h"
#include "DNA_brush_types.h"
#include "DNA_gpencil_legacy_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_userdef_types.h"
#include "DNA_view3d_types.h"
#include "BKE_gpencil_legacy.h"
#include "BKE_material.h"
#include "GPU_batch.hh"
#include "GPU_immediate.hh"
#include "GPU_matrix.hh"
#include "GPU_shader_shared.hh"
#include "GPU_state.hh"
#include "GPU_uniform_buffer.hh"
#include "ED_gpencil_legacy.hh"
#include "gpencil_intern.hh"
/* ************************************************** */
/* GREASE PENCIL DRAWING */
/* ----- General Defines ------ */
/* flags for sflag */
enum eDrawStrokeFlags {
/** don't draw status info */
GP_DRAWDATA_NOSTATUS = (1 << 0),
/** only draw 3d-strokes */
GP_DRAWDATA_ONLY3D = (1 << 1),
/** only draw 'canvas' strokes */
GP_DRAWDATA_ONLYV2D = (1 << 2),
/** only draw 'image' strokes */
GP_DRAWDATA_ONLYI2D = (1 << 3),
/** special hack for drawing strokes in Image Editor (weird coordinates) */
GP_DRAWDATA_IEDITHACK = (1 << 4),
/** Don't draw XRAY in 3D view (which is default). */
GP_DRAWDATA_NO_XRAY = (1 << 5),
/** No onion-skins should be drawn (for animation playback). */
GP_DRAWDATA_NO_ONIONS = (1 << 6),
/** draw strokes as "volumetric" circular billboards */
GP_DRAWDATA_VOLUMETRIC = (1 << 7),
/** fill insides/bounded-regions of strokes */
GP_DRAWDATA_FILL = (1 << 8),
};
/* thickness above which we should use special drawing */
#if 0
# define GP_DRAWTHICKNESS_SPECIAL 3
#endif
/* conversion utility (float --> normalized unsigned byte) */
#define F2UB(x) uchar(255.0f * x)
/* ----- Tool Buffer Drawing ------ */
/* helper functions to set color of buffer point */
static void gpencil_set_point_varying_color(const bGPDspoint *pt,
const float ink[4],
uint attr_id,
bool fix_strength)
{
float alpha = ink[3] * pt->strength;
if ((fix_strength) && (alpha >= 0.1f)) {
alpha = 1.0f;
}
CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
immAttr4ub(attr_id, F2UB(ink[0]), F2UB(ink[1]), F2UB(ink[2]), F2UB(alpha));
}
/* ----------- Volumetric Strokes --------------- */
/* draw a 3D stroke in "volumetric" style */
static void gpencil_draw_stroke_volumetric_3d(const bGPDspoint *points,
int totpoints,
short thickness,
const float ink[4])
{
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
uint size = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
uint color = GPU_vertformat_attr_add(
format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
GPU_program_point_size(true);
immBegin(GPU_PRIM_POINTS, totpoints);
const bGPDspoint *pt = points;
for (int i = 0; i < totpoints && pt; i++, pt++) {
gpencil_set_point_varying_color(pt, ink, color, false);
/* TODO: scale based on view transform */
immAttr1f(size, pt->pressure * thickness);
/* we can adjust size in vertex shader based on view/projection! */
immVertex3fv(pos, &pt->x);
}
immEnd();
immUnbindProgram();
GPU_program_point_size(false);
}
/* ----- Existing Strokes Drawing (3D and Point) ------ */
/* draw a given stroke in 3d (i.e. in 3d-space) */
static void gpencil_draw_stroke_3d(tGPDdraw *tgpw,
short thickness,
const float ink[4],
bool cyclic)
{
bGPDspoint *points = tgpw->gps->points;
int totpoints = tgpw->gps->totpoints;
const float viewport[2] = {float(tgpw->winx), float(tgpw->winy)};
const float min_thickness = 0.05f;
float fpt[3];
/* if cyclic needs more vertex */
int cyclic_add = (cyclic) ? 1 : 0;
GPUVertFormat *format = immVertexFormat();
struct {
uint pos, color, thickness;
} attr_id{};
attr_id.pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
attr_id.color = GPU_vertformat_attr_add(
format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
attr_id.thickness = GPU_vertformat_attr_add(
format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_GPENCIL_STROKE);
float obj_scale = tgpw->ob ?
(tgpw->ob->scale[0] + tgpw->ob->scale[1] + tgpw->ob->scale[2]) / 3.0f :
1.0f;
GPencilStrokeData gpencil_stroke_data;
copy_v2_v2(gpencil_stroke_data.viewport, viewport);
gpencil_stroke_data.pixsize = tgpw->rv3d->pixsize;
gpencil_stroke_data.objscale = obj_scale;
int keep_size = int((tgpw->gpd) && (tgpw->gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS));
gpencil_stroke_data.keep_size = keep_size;
gpencil_stroke_data.pixfactor = tgpw->gpd->pixfactor;
/* X-ray mode always to 3D space to avoid wrong Z-depth calculation (#60051). */
gpencil_stroke_data.xraymode = GP_XRAY_3DSPACE;
gpencil_stroke_data.caps_start = tgpw->gps->caps[0];
gpencil_stroke_data.caps_end = tgpw->gps->caps[1];
gpencil_stroke_data.fill_stroke = tgpw->is_fill_stroke;
GPUUniformBuf *ubo = GPU_uniformbuf_create_ex(
sizeof(GPencilStrokeData), &gpencil_stroke_data, __func__);
immBindUniformBuf("gpencil_stroke_data", ubo);
/* draw stroke curve */
immBeginAtMost(GPU_PRIM_LINE_STRIP_ADJ, totpoints + cyclic_add + 2);
const bGPDspoint *pt = points;
for (int i = 0; i < totpoints; i++, pt++) {
/* first point for adjacency (not drawn) */
if (i == 0) {
gpencil_set_point_varying_color(points, ink, attr_id.color, bool(tgpw->is_fill_stroke));
if ((cyclic) && (totpoints > 2)) {
immAttr1f(attr_id.thickness,
max_ff((points + totpoints - 1)->pressure * thickness, min_thickness));
mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + totpoints - 1)->x);
}
else {
immAttr1f(attr_id.thickness, max_ff((points + 1)->pressure * thickness, min_thickness));
mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + 1)->x);
}
immVertex3fv(attr_id.pos, fpt);
}
/* set point */
gpencil_set_point_varying_color(pt, ink, attr_id.color, bool(tgpw->is_fill_stroke));
immAttr1f(attr_id.thickness, max_ff(pt->pressure * thickness, min_thickness));
mul_v3_m4v3(fpt, tgpw->diff_mat, &pt->x);
immVertex3fv(attr_id.pos, fpt);
}
if (cyclic && totpoints > 2) {
/* draw line to first point to complete the cycle */
immAttr1f(attr_id.thickness, max_ff(points->pressure * thickness, 1.0f));
mul_v3_m4v3(fpt, tgpw->diff_mat, &points->x);
immVertex3fv(attr_id.pos, fpt);
/* now add adjacency point (not drawn) */
immAttr1f(attr_id.thickness, max_ff((points + 1)->pressure * thickness, 1.0f));
mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + 1)->x);
immVertex3fv(attr_id.pos, fpt);
}
/* last adjacency point (not drawn) */
else {
gpencil_set_point_varying_color(
points + totpoints - 2, ink, attr_id.color, bool(tgpw->is_fill_stroke));
immAttr1f(attr_id.thickness, max_ff((points + totpoints - 2)->pressure * thickness, 1.0f));
mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + totpoints - 2)->x);
immVertex3fv(attr_id.pos, fpt);
}
immEnd();
immUnbindProgram();
GPU_uniformbuf_free(ubo);
}
/* ----- Strokes Drawing ------ */
/* Helper for doing all the checks on whether a stroke can be drawn */
static bool gpencil_can_draw_stroke(const bGPDstroke *gps, const int dflag)
{
/* skip stroke if it isn't in the right display space for this drawing context */
/* 1) 3D Strokes */
if ((dflag & GP_DRAWDATA_ONLY3D) && !(gps->flag & GP_STROKE_3DSPACE)) {
return false;
}
if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE)) {
return false;
}
/* 2) Screen Space 2D Strokes */
if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE)) {
return false;
}
if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE)) {
return false;
}
/* 3) Image Space (2D) */
if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE)) {
return false;
}
if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE)) {
return false;
}
/* skip stroke if it doesn't have any valid data */
if ((gps->points == nullptr) || (gps->totpoints < 1)) {
return false;
}
/* stroke can be drawn */
return true;
}
/* draw a set of strokes */
static void gpencil_draw_strokes(tGPDdraw *tgpw)
{
float tcolor[4];
short sthickness;
float ink[4];
const bool is_unique = (tgpw->gps != nullptr);
const bool use_mat = (tgpw->gpd->mat != nullptr);
GPU_program_point_size(true);
/* Do not write to depth (avoid self-occlusion). */
bool prev_depth_mask = GPU_depth_mask_get();
GPU_depth_mask(false);
bGPDstroke *gps_init = static_cast<bGPDstroke *>((tgpw->gps) ? tgpw->gps :
tgpw->t_gpf->strokes.first);
for (bGPDstroke *gps = gps_init; gps; gps = gps->next) {
/* check if stroke can be drawn */
if (gpencil_can_draw_stroke(gps, tgpw->dflag) == false) {
continue;
}
/* check if the color is visible */
Material *ma = (use_mat) ? tgpw->gpd->mat[gps->mat_nr] : BKE_material_default_gpencil();
MaterialGPencilStyle *gp_style = (ma) ? ma->gp_style : nullptr;
if ((gp_style == nullptr) || (gp_style->flag & GP_MATERIAL_HIDE) ||
/* If onion and ghost flag do not draw. */
(tgpw->onion && (gp_style->flag & GP_MATERIAL_HIDE_ONIONSKIN)))
{
continue;
}
/* if disable fill, the colors with fill must be omitted too except fill boundary strokes */
if ((tgpw->disable_fill == 1) && (gp_style->fill_rgba[3] > 0.0f) &&
((gps->flag & GP_STROKE_NOFILL) == 0) && (gp_style->flag & GP_MATERIAL_FILL_SHOW))
{
continue;
}
/* calculate thickness */
sthickness = gps->thickness + tgpw->lthick;
if (tgpw->is_fill_stroke) {
sthickness = short(max_ii(1, sthickness / 2));
}
if (sthickness <= 0) {
continue;
}
/* check which stroke-drawer to use */
if (tgpw->dflag & GP_DRAWDATA_ONLY3D) {
const int no_xray = (tgpw->dflag & GP_DRAWDATA_NO_XRAY);
if (no_xray) {
GPU_depth_test(GPU_DEPTH_LESS_EQUAL);
/* first arg is normally rv3d->dist, but this isn't
* available here and seems to work quite well without */
GPU_polygon_offset(1.0f, 1.0f);
}
/* 3D Stroke */
/* set color using material tint color and opacity */
if (!tgpw->onion) {
interp_v3_v3v3(tcolor, gp_style->stroke_rgba, tgpw->tintcolor, tgpw->tintcolor[3]);
tcolor[3] = gp_style->stroke_rgba[3] * tgpw->opacity;
copy_v4_v4(ink, tcolor);
}
else {
if (tgpw->custonion) {
copy_v4_v4(ink, tgpw->tintcolor);
}
else {
ARRAY_SET_ITEMS(tcolor, UNPACK3(gp_style->stroke_rgba), tgpw->opacity);
copy_v4_v4(ink, tcolor);
}
}
/* if used for fill, set opacity to 1 */
if (tgpw->is_fill_stroke) {
if (ink[3] >= GPENCIL_ALPHA_OPACITY_THRESH) {
ink[3] = 1.0f;
}
}
if (gp_style->mode == GP_MATERIAL_MODE_DOT) {
/* volumetric stroke drawing */
if (tgpw->disable_fill != 1) {
gpencil_draw_stroke_volumetric_3d(gps->points, gps->totpoints, sthickness, ink);
}
}
else {
/* 3D Lines - OpenGL primitives-based */
if (gps->totpoints > 1) {
tgpw->gps = gps;
gpencil_draw_stroke_3d(tgpw, sthickness, ink, gps->flag & GP_STROKE_CYCLIC);
}
}
if (no_xray) {
GPU_depth_test(GPU_DEPTH_NONE);
GPU_polygon_offset(0.0f, 0.0f);
}
}
/* if only one stroke, exit from loop */
if (is_unique) {
break;
}
}
GPU_depth_mask(prev_depth_mask);
GPU_program_point_size(false);
}
/* ----- General Drawing ------ */
void ED_gpencil_draw_fill(tGPDdraw *tgpw)
{
gpencil_draw_strokes(tgpw);
}

View File

@@ -1,85 +0,0 @@
/* SPDX-FileCopyrightText: 2017 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edgpencil
*/
#include "BLI_math_color.h"
#include "BLI_math_vector.h"
#include "BLI_utildefines.h"
#include "DNA_gpencil_legacy_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_context.hh"
#include "BKE_gpencil_legacy.h"
#include "BLT_translation.hh"
#include "DEG_depsgraph.hh"
#include "ED_gpencil_legacy.hh"
/* Definition of the most important info from a color */
struct ColorTemplate {
const char *name;
float line[4];
float fill[4];
};
/* Add color an ensure duplications (matched by name) */
static int gpencil_stroke_material(Main *bmain, Object *ob, const ColorTemplate *pct)
{
int index;
Material *ma = BKE_gpencil_object_material_ensure_by_name(bmain, ob, DATA_(pct->name), &index);
copy_v4_v4(ma->gp_style->stroke_rgba, pct->line);
srgb_to_linearrgb_v4(ma->gp_style->stroke_rgba, ma->gp_style->stroke_rgba);
copy_v4_v4(ma->gp_style->fill_rgba, pct->fill);
srgb_to_linearrgb_v4(ma->gp_style->fill_rgba, ma->gp_style->fill_rgba);
return index;
}
/* ***************************************************************** */
/* Stroke Geometry */
/* ***************************************************************** */
/* Color Data */
static const ColorTemplate gp_stroke_material_black = {
N_("Black"),
{0.0f, 0.0f, 0.0f, 1.0f},
{0.0f, 0.0f, 0.0f, 0.0f},
};
/* ***************************************************************** */
/* Blank API */
void ED_gpencil_create_blank(bContext *C, Object *ob, float[4][4] /*mat*/)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
bGPdata *gpd = (bGPdata *)ob->data;
/* create colors */
int color_black = gpencil_stroke_material(bmain, ob, &gp_stroke_material_black);
/* set first color as active and in brushes */
ob->actcol = color_black + 1;
/* layers */
bGPDlayer *layer = BKE_gpencil_layer_addnew(gpd, "GP_Layer", true, false);
/* frames */
BKE_gpencil_frame_addnew(layer, scene->r.cfra);
/* update depsgraph */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
}

View File

@@ -1,89 +0,0 @@
/* SPDX-FileCopyrightText: 2017 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edgpencil
*/
#include "BLI_utildefines.h"
#include "DNA_gpencil_legacy_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "BKE_context.hh"
#include "BKE_gpencil_legacy.h"
#include "BLI_math_color.h"
#include "BLI_math_vector.h"
#include "BLT_translation.hh"
#include "DEG_depsgraph.hh"
#include "ED_gpencil_legacy.hh"
/* Definition of the most important info from a color */
struct ColorTemplate {
const char *name;
float line[4];
float fill[4];
};
/* Add color an ensure duplications (matched by name) */
static int gpencil_lineart_material(Main *bmain,
Object *ob,
const ColorTemplate *pct,
const bool fill)
{
int index;
Material *ma = BKE_gpencil_object_material_ensure_by_name(bmain, ob, DATA_(pct->name), &index);
copy_v4_v4(ma->gp_style->stroke_rgba, pct->line);
srgb_to_linearrgb_v4(ma->gp_style->stroke_rgba, ma->gp_style->stroke_rgba);
copy_v4_v4(ma->gp_style->fill_rgba, pct->fill);
srgb_to_linearrgb_v4(ma->gp_style->fill_rgba, ma->gp_style->fill_rgba);
if (fill) {
ma->gp_style->flag |= GP_MATERIAL_FILL_SHOW;
}
return index;
}
/* ***************************************************************** */
/* Color Data */
static const ColorTemplate gp_stroke_material_black = {
N_("Black"),
{0.0f, 0.0f, 0.0f, 1.0f},
{0.0f, 0.0f, 0.0f, 0.0f},
};
/* ***************************************************************** */
/* LineArt API */
void ED_gpencil_create_lineart(bContext *C, Object *ob)
{
Main *bmain = CTX_data_main(C);
bGPdata *gpd = (bGPdata *)ob->data;
/* create colors */
int color_black = gpencil_lineart_material(bmain, ob, &gp_stroke_material_black, false);
/* set first color as active and in brushes */
ob->actcol = color_black + 1;
/* layers */
bGPDlayer *lines = BKE_gpencil_layer_addnew(gpd, "Lines", true, false);
/* frames */
BKE_gpencil_frame_addnew(lines, 0);
/* update depsgraph */
/* To trigger modifier update, this is still needed although we don't have any strokes. */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
}

View File

@@ -1,973 +0,0 @@
/* SPDX-FileCopyrightText: 2017 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edgpencil
*/
#include "BLI_math_color.h"
#include "BLI_math_matrix.h"
#include "BLI_math_vector.h"
#include "BLI_utildefines.h"
#include "DNA_gpencil_legacy_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_context.hh"
#include "BKE_gpencil_geom_legacy.h"
#include "BKE_gpencil_legacy.h"
#include "BLT_translation.hh"
#include "DEG_depsgraph.hh"
#include "ED_gpencil_legacy.hh"
void ED_gpencil_stroke_init_data(bGPDstroke *gps,
const float *array,
const int totpoints,
const float mat[4][4])
{
for (int i = 0; i < totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
const int x = GP_PRIM_DATABUF_SIZE * i;
pt->x = array[x];
pt->y = array[x + 1];
pt->z = array[x + 2];
mul_m4_v3(mat, &pt->x);
pt->pressure = array[x + 3];
pt->strength = array[x + 4];
}
}
/* Definition of the most important info from a color */
struct ColorTemplate {
const char *name;
float line[4];
float fill[4];
};
/* Add color an ensure duplications (matched by name) */
static int gpencil_monkey_color(
Main *bmain, Object *ob, const ColorTemplate *pct, bool stroke, bool fill)
{
int index;
Material *ma = BKE_gpencil_object_material_ensure_by_name(bmain, ob, DATA_(pct->name), &index);
copy_v4_v4(ma->gp_style->stroke_rgba, pct->line);
srgb_to_linearrgb_v4(ma->gp_style->stroke_rgba, ma->gp_style->stroke_rgba);
copy_v4_v4(ma->gp_style->fill_rgba, pct->fill);
srgb_to_linearrgb_v4(ma->gp_style->fill_rgba, ma->gp_style->fill_rgba);
if (!stroke) {
ma->gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
}
if (!fill) {
ma->gp_style->flag &= ~GP_MATERIAL_FILL_SHOW;
}
else {
ma->gp_style->flag |= GP_MATERIAL_FILL_SHOW;
}
return index;
}
/* ***************************************************************** */
/* Monkey Geometry */
static const float data0[270 * GP_PRIM_DATABUF_SIZE] = {
-0.4911f, 0.0f, -0.1781f, 0.267f, 0.362f, -0.5168f, 0.0f, -0.1806f, 0.31f, 0.407f,
-0.5361f, 0.0f, -0.1817f, 0.38f, 0.439f, -0.5618f, 0.0f, -0.1829f, 0.433f, 0.458f,
-0.5892f, 0.0f, -0.1827f, 0.471f, 0.5f, -0.6193f, 0.0f, -0.1814f, 0.496f, 0.516f,
-0.6499f, 0.0f, -0.1782f, 0.511f, 0.519f, -0.6808f, 0.0f, -0.1729f, 0.521f, 0.53f,
-0.7107f, 0.0f, -0.1651f, 0.527f, 0.533f, -0.7404f, 0.0f, -0.1555f, 0.531f, 0.534f,
-0.7698f, 0.0f, -0.1447f, 0.534f, 0.535f, -0.7993f, 0.0f, -0.1332f, 0.535f, 0.535f,
-0.8289f, 0.0f, -0.1209f, 0.536f, 0.537f, -0.8586f, 0.0f, -0.109f, 0.536f, 0.537f,
-0.8871f, 0.0f, -0.0973f, 0.536f, 0.537f, -0.9125f, 0.0f, -0.0838f, 0.535f, 0.535f,
-0.9353f, 0.0f, -0.0688f, 0.534f, 0.534f, -0.9561f, 0.0f, -0.0525f, 0.534f, 0.534f,
-0.9752f, 0.0f, -0.0346f, 0.533f, 0.534f, -0.9944f, 0.0f, -0.016f, 0.533f, 0.534f,
-1.0148f, 0.0f, 0.0028f, 0.532f, 0.532f, -1.0348f, 0.0f, 0.0215f, 0.531f, 0.531f,
-1.05f, 0.0f, 0.0407f, 0.531f, 0.531f, -1.0639f, 0.0f, 0.0613f, 0.532f, 0.532f,
-1.0752f, 0.0f, 0.0838f, 0.535f, 0.535f, -1.0848f, 0.0f, 0.1082f, 0.54f, 0.54f,
-1.0936f, 0.0f, 0.1346f, 0.542f, 0.542f, -1.1024f, 0.0f, 0.1639f, 0.543f, 0.543f,
-1.1102f, 0.0f, 0.1953f, 0.543f, 0.543f, -1.1128f, 0.0f, 0.2277f, 0.546f, 0.546f,
-1.1091f, 0.0f, 0.2579f, 0.549f, 0.549f, -1.1023f, 0.0f, 0.2849f, 0.549f, 0.549f,
-1.0934f, 0.0f, 0.3086f, 0.549f, 0.549f, -1.0831f, 0.0f, 0.3285f, 0.549f, 0.549f,
-1.0724f, 0.0f, 0.3451f, 0.551f, 0.551f, -1.0607f, 0.0f, 0.3594f, 0.553f, 0.553f,
-1.0474f, 0.0f, 0.3713f, 0.554f, 0.554f, -1.031f, 0.0f, 0.3804f, 0.554f, 0.554f,
-1.0108f, 0.0f, 0.3874f, 0.555f, 0.555f, -0.9862f, 0.0f, 0.3922f, 0.556f, 0.556f,
-0.9568f, 0.0f, 0.3941f, 0.557f, 0.557f, -0.9243f, 0.0f, 0.3934f, 0.557f, 0.557f,
-0.8897f, 0.0f, 0.3861f, 0.557f, 0.557f, -0.8556f, 0.0f, 0.3754f, 0.557f, 0.557f,
-0.8237f, 0.0f, 0.3608f, 0.558f, 0.557f, -0.7982f, 0.0f, 0.344f, 0.558f, 0.558f,
-0.7786f, 0.0f, 0.329f, 0.557f, 0.559f, -0.7633f, 0.0f, 0.3183f, 0.556f, 0.559f,
-0.7498f, 0.0f, 0.3135f, 0.554f, 0.559f, -0.7374f, 0.0f, 0.3134f, 0.552f, 0.548f,
-0.7261f, 0.0f, 0.3179f, 0.551f, 0.546f, -0.7146f, 0.0f, 0.3262f, 0.55f, 0.547f,
-0.703f, 0.0f, 0.3395f, 0.549f, 0.547f, -0.692f, 0.0f, 0.3576f, 0.549f, 0.548f,
-0.6831f, 0.0f, 0.3806f, 0.549f, 0.548f, -0.6748f, 0.0f, 0.4052f, 0.55f, 0.549f,
-0.6648f, 0.0f, 0.4305f, 0.552f, 0.548f, -0.6527f, 0.0f, 0.4549f, 0.556f, 0.549f,
-0.6375f, 0.0f, 0.4783f, 0.563f, 0.549f, -0.6195f, 0.0f, 0.5021f, 0.572f, 0.558f,
-0.5985f, 0.0f, 0.5256f, 0.582f, 0.587f, -0.5775f, 0.0f, 0.5488f, 0.591f, 0.595f,
-0.556f, 0.0f, 0.5715f, 0.597f, 0.598f, -0.5339f, 0.0f, 0.593f, 0.602f, 0.603f,
-0.5119f, 0.0f, 0.613f, 0.605f, 0.606f, -0.4905f, 0.0f, 0.6312f, 0.607f, 0.607f,
-0.4697f, 0.0f, 0.6474f, 0.609f, 0.607f, -0.4499f, 0.0f, 0.6613f, 0.612f, 0.611f,
-0.4306f, 0.0f, 0.6734f, 0.616f, 0.615f, -0.4116f, 0.0f, 0.6845f, 0.619f, 0.621f,
-0.3918f, 0.0f, 0.6954f, 0.623f, 0.623f, -0.3709f, 0.0f, 0.7059f, 0.626f, 0.626f,
-0.3486f, 0.0f, 0.7157f, 0.63f, 0.63f, -0.3251f, 0.0f, 0.7249f, 0.637f, 0.632f,
-0.3006f, 0.0f, 0.7333f, 0.646f, 0.644f, -0.2755f, 0.0f, 0.7414f, 0.654f, 0.657f,
-0.25f, 0.0f, 0.7489f, 0.659f, 0.661f, -0.2242f, 0.0f, 0.7562f, 0.664f, 0.664f,
-0.1979f, 0.0f, 0.7631f, 0.667f, 0.668f, -0.171f, 0.0f, 0.7695f, 0.671f, 0.671f,
-0.1434f, 0.0f, 0.7752f, 0.674f, 0.674f, -0.1151f, 0.0f, 0.7801f, 0.677f, 0.678f,
-0.0861f, 0.0f, 0.7841f, 0.678f, 0.68f, -0.0563f, 0.0f, 0.7869f, 0.68f, 0.68f,
-0.026f, 0.0f, 0.7889f, 0.68f, 0.68f, 0.0049f, 0.0f, 0.7899f, 0.681f, 0.681f,
0.0362f, 0.0f, 0.7898f, 0.682f, 0.681f, 0.0679f, 0.0f, 0.7881f, 0.683f, 0.683f,
0.0996f, 0.0f, 0.7853f, 0.685f, 0.683f, 0.1313f, 0.0f, 0.7812f, 0.687f, 0.685f,
0.1632f, 0.0f, 0.7756f, 0.69f, 0.686f, 0.1953f, 0.0f, 0.7687f, 0.693f, 0.694f,
0.2277f, 0.0f, 0.7608f, 0.697f, 0.697f, 0.2606f, 0.0f, 0.7513f, 0.7f, 0.7f,
0.2934f, 0.0f, 0.7404f, 0.704f, 0.704f, 0.3258f, 0.0f, 0.7276f, 0.707f, 0.71f,
0.357f, 0.0f, 0.7135f, 0.709f, 0.711f, 0.387f, 0.0f, 0.6983f, 0.711f, 0.713f,
0.4157f, 0.0f, 0.6819f, 0.712f, 0.714f, 0.444f, 0.0f, 0.6645f, 0.714f, 0.714f,
0.4719f, 0.0f, 0.6459f, 0.715f, 0.715f, 0.4994f, 0.0f, 0.6261f, 0.715f, 0.716f,
0.526f, 0.0f, 0.6046f, 0.716f, 0.716f, 0.552f, 0.0f, 0.5816f, 0.717f, 0.717f,
0.577f, 0.0f, 0.5575f, 0.718f, 0.717f, 0.6008f, 0.0f, 0.5328f, 0.718f, 0.718f,
0.6231f, 0.0f, 0.5077f, 0.718f, 0.718f, 0.6423f, 0.0f, 0.4829f, 0.719f, 0.718f,
0.658f, 0.0f, 0.4617f, 0.719f, 0.719f, 0.6713f, 0.0f, 0.4432f, 0.719f, 0.719f,
0.6828f, 0.0f, 0.4266f, 0.719f, 0.719f, 0.6928f, 0.0f, 0.4118f, 0.719f, 0.719f,
0.7016f, 0.0f, 0.3987f, 0.718f, 0.717f, 0.7094f, 0.0f, 0.3871f, 0.717f, 0.717f,
0.7165f, 0.0f, 0.3769f, 0.717f, 0.717f, 0.7233f, 0.0f, 0.3679f, 0.718f, 0.718f,
0.7301f, 0.0f, 0.3598f, 0.717f, 0.719f, 0.7373f, 0.0f, 0.3524f, 0.715f, 0.719f,
0.7454f, 0.0f, 0.3458f, 0.713f, 0.709f, 0.7545f, 0.0f, 0.3398f, 0.718f, 0.704f,
0.7651f, 0.0f, 0.3351f, 0.732f, 0.705f, 0.777f, 0.0f, 0.3317f, 0.753f, 0.713f,
0.7909f, 0.0f, 0.3311f, 0.774f, 0.813f, 0.8068f, 0.0f, 0.334f, 0.791f, 0.815f,
0.8246f, 0.0f, 0.3398f, 0.802f, 0.815f, 0.8438f, 0.0f, 0.3486f, 0.809f, 0.816f,
0.8651f, 0.0f, 0.3575f, 0.812f, 0.816f, 0.8893f, 0.0f, 0.3665f, 0.814f, 0.816f,
0.9166f, 0.0f, 0.374f, 0.814f, 0.817f, 0.9459f, 0.0f, 0.3791f, 0.812f, 0.817f,
0.9751f, 0.0f, 0.3811f, 0.81f, 0.815f, 1.0029f, 0.0f, 0.38f, 0.806f, 0.807f,
1.0288f, 0.0f, 0.3754f, 0.8f, 0.801f, 1.052f, 0.0f, 0.3673f, 0.794f, 0.8f,
1.0722f, 0.0f, 0.3556f, 0.788f, 0.781f, 1.0888f, 0.0f, 0.3403f, 0.783f, 0.78f,
1.1027f, 0.0f, 0.322f, 0.781f, 0.778f, 1.1133f, 0.0f, 0.301f, 0.779f, 0.777f,
1.1215f, 0.0f, 0.278f, 0.778f, 0.777f, 1.1269f, 0.0f, 0.2534f, 0.777f, 0.777f,
1.1296f, 0.0f, 0.2284f, 0.777f, 0.778f, 1.1292f, 0.0f, 0.2031f, 0.776f, 0.776f,
1.1254f, 0.0f, 0.1778f, 0.775f, 0.776f, 1.1178f, 0.0f, 0.153f, 0.774f, 0.774f,
1.1076f, 0.0f, 0.1299f, 0.774f, 0.772f, 1.0955f, 0.0f, 0.1079f, 0.773f, 0.773f,
1.0817f, 0.0f, 0.087f, 0.772f, 0.773f, 1.0668f, 0.0f, 0.0677f, 0.771f, 0.772f,
1.0508f, 0.0f, 0.0491f, 0.77f, 0.772f, 1.0339f, 0.0f, 0.0313f, 0.768f, 0.766f,
1.0157f, 0.0f, 0.0144f, 0.767f, 0.765f, 0.9969f, 0.0f, -0.0015f, 0.766f, 0.765f,
0.9784f, 0.0f, -0.017f, 0.765f, 0.766f, 0.96f, 0.0f, -0.0321f, 0.764f, 0.765f,
0.9413f, 0.0f, -0.0468f, 0.761f, 0.765f, 0.9216f, 0.0f, -0.0611f, 0.756f, 0.761f,
0.9009f, 0.0f, -0.0751f, 0.751f, 0.751f, 0.8787f, 0.0f, -0.0893f, 0.745f, 0.744f,
0.8556f, 0.0f, -0.1027f, 0.739f, 0.738f, 0.8312f, 0.0f, -0.1152f, 0.733f, 0.731f,
0.8058f, 0.0f, -0.1268f, 0.728f, 0.727f, 0.7788f, 0.0f, -0.1372f, 0.723f, 0.723f,
0.7505f, 0.0f, -0.1467f, 0.718f, 0.717f, 0.7214f, 0.0f, -0.1549f, 0.713f, 0.708f,
0.6929f, 0.0f, -0.1617f, 0.709f, 0.706f, 0.6652f, 0.0f, -0.1665f, 0.704f, 0.705f,
0.6388f, 0.0f, -0.1691f, 0.7f, 0.704f, 0.6131f, 0.0f, -0.1701f, 0.695f, 0.698f,
0.5883f, 0.0f, -0.1699f, 0.691f, 0.691f, 0.5644f, 0.0f, -0.1691f, 0.686f, 0.685f,
0.5416f, 0.0f, -0.1683f, 0.681f, 0.683f, 0.5195f, 0.0f, -0.168f, 0.676f, 0.676f,
0.4975f, 0.0f, -0.1687f, 0.671f, 0.67f, 0.4754f, 0.0f, -0.1705f, 0.666f, 0.663f,
0.4527f, 0.0f, -0.1741f, 0.663f, 0.66f, 0.4293f, 0.0f, -0.1797f, 0.661f, 0.659f,
0.4054f, 0.0f, -0.1881f, 0.66f, 0.659f, 0.3813f, 0.0f, -0.1992f, 0.659f, 0.657f,
0.3585f, 0.0f, -0.212f, 0.658f, 0.659f, 0.3368f, 0.0f, -0.2266f, 0.658f, 0.659f,
0.3174f, 0.0f, -0.2426f, 0.658f, 0.659f, 0.2996f, 0.0f, -0.2594f, 0.657f, 0.657f,
0.284f, 0.0f, -0.2768f, 0.656f, 0.658f, 0.2702f, 0.0f, -0.2946f, 0.653f, 0.657f,
0.2585f, 0.0f, -0.3127f, 0.646f, 0.656f, 0.25f, 0.0f, -0.3308f, 0.637f, 0.642f,
0.2447f, 0.0f, -0.3489f, 0.628f, 0.609f, 0.2418f, 0.0f, -0.3672f, 0.62f, 0.608f,
0.2412f, 0.0f, -0.386f, 0.614f, 0.607f, 0.2425f, 0.0f, -0.4051f, 0.61f, 0.606f,
0.2456f, 0.0f, -0.4246f, 0.608f, 0.604f, 0.2509f, 0.0f, -0.4447f, 0.607f, 0.606f,
0.2576f, 0.0f, -0.4652f, 0.606f, 0.607f, 0.2666f, 0.0f, -0.4867f, 0.605f, 0.607f,
0.2766f, 0.0f, -0.5091f, 0.603f, 0.607f, 0.2871f, 0.0f, -0.5326f, 0.598f, 0.606f,
0.2973f, 0.0f, -0.5569f, 0.591f, 0.602f, 0.306f, 0.0f, -0.5826f, 0.583f, 0.585f,
0.3131f, 0.0f, -0.61f, 0.574f, 0.576f, 0.3197f, 0.0f, -0.6384f, 0.564f, 0.564f,
0.326f, 0.0f, -0.6681f, 0.555f, 0.549f, 0.3315f, 0.0f, -0.6984f, 0.547f, 0.543f,
0.336f, 0.0f, -0.7291f, 0.541f, 0.541f, 0.3391f, 0.0f, -0.7593f, 0.536f, 0.538f,
0.3399f, 0.0f, -0.7884f, 0.532f, 0.528f, 0.3382f, 0.0f, -0.8158f, 0.529f, 0.528f,
0.334f, 0.0f, -0.8417f, 0.525f, 0.529f, 0.3273f, 0.0f, -0.8657f, 0.521f, 0.528f,
0.3185f, 0.0f, -0.8881f, 0.516f, 0.515f, 0.3073f, 0.0f, -0.9088f, 0.51f, 0.514f,
0.2941f, 0.0f, -0.9278f, 0.505f, 0.507f, 0.2786f, 0.0f, -0.9449f, 0.499f, 0.494f,
0.261f, 0.0f, -0.96f, 0.495f, 0.49f, 0.2413f, 0.0f, -0.9733f, 0.493f, 0.491f,
0.2193f, 0.0f, -0.9845f, 0.491f, 0.489f, 0.1953f, 0.0f, -0.9935f, 0.491f, 0.491f,
0.1693f, 0.0f, -1.0004f, 0.491f, 0.492f, 0.1421f, 0.0f, -1.0051f, 0.492f, 0.492f,
0.1136f, 0.0f, -1.0072f, 0.492f, 0.492f, 0.0842f, 0.0f, -1.0073f, 0.492f, 0.492f,
0.0548f, 0.0f, -1.0059f, 0.493f, 0.494f, 0.0258f, 0.0f, -1.0037f, 0.493f, 0.494f,
-0.0027f, 0.0f, -1.0003f, 0.493f, 0.493f, -0.0309f, 0.0f, -0.9959f, 0.492f, 0.492f,
-0.0584f, 0.0f, -0.9904f, 0.491f, 0.492f, -0.0858f, 0.0f, -0.9848f, 0.491f, 0.491f,
-0.1127f, 0.0f, -0.9783f, 0.49f, 0.49f, -0.1386f, 0.0f, -0.9703f, 0.49f, 0.49f,
-0.1649f, 0.0f, -0.9604f, 0.489f, 0.489f, -0.191f, 0.0f, -0.9479f, 0.489f, 0.489f,
-0.2165f, 0.0f, -0.9345f, 0.489f, 0.49f, -0.2414f, 0.0f, -0.9205f, 0.489f, 0.489f,
-0.2654f, 0.0f, -0.9055f, 0.489f, 0.489f, -0.2877f, 0.0f, -0.8898f, 0.49f, 0.49f,
-0.3076f, 0.0f, -0.8723f, 0.49f, 0.489f, -0.324f, 0.0f, -0.8532f, 0.491f, 0.489f,
-0.3367f, 0.0f, -0.8316f, 0.492f, 0.489f, -0.3451f, 0.0f, -0.8077f, 0.494f, 0.488f,
-0.3505f, 0.0f, -0.7829f, 0.497f, 0.49f, -0.3531f, 0.0f, -0.7584f, 0.501f, 0.497f,
-0.3528f, 0.0f, -0.7349f, 0.505f, 0.504f, -0.3503f, 0.0f, -0.7115f, 0.51f, 0.51f,
-0.346f, 0.0f, -0.688f, 0.515f, 0.515f, -0.3411f, 0.0f, -0.6643f, 0.52f, 0.522f,
-0.3361f, 0.0f, -0.6403f, 0.525f, 0.528f, -0.3304f, 0.0f, -0.6164f, 0.53f, 0.532f,
-0.3244f, 0.0f, -0.5925f, 0.535f, 0.535f, -0.318f, 0.0f, -0.5687f, 0.539f, 0.54f,
-0.3124f, 0.0f, -0.5441f, 0.542f, 0.545f, -0.3051f, 0.0f, -0.5191f, 0.546f, 0.549f,
-0.2959f, 0.0f, -0.4917f, 0.548f, 0.549f, -0.2882f, 0.0f, -0.4639f, 0.55f, 0.552f,
-0.2814f, 0.0f, -0.4363f, 0.551f, 0.552f, -0.2759f, 0.0f, -0.4084f, 0.552f, 0.553f,
-0.2707f, 0.0f, -0.3827f, 0.553f, 0.553f, -0.2703f, 0.0f, -0.3586f, 0.554f, 0.553f,
-0.2772f, 0.0f, -0.3375f, 0.554f, 0.554f, -0.2871f, 0.0f, -0.3178f, 0.555f, 0.555f,
-0.2995f, 0.0f, -0.2996f, 0.556f, 0.555f, -0.3145f, 0.0f, -0.283f, 0.556f, 0.557f,
-0.332f, 0.0f, -0.2672f, 0.557f, 0.557f, -0.3488f, 0.0f, -0.2531f, 0.558f, 0.558f,
-0.3639f, 0.0f, -0.2407f, 0.558f, 0.558f, -0.3778f, 0.0f, -0.2292f, 0.558f, 0.558f,
-0.3909f, 0.0f, -0.2191f, 0.559f, 0.559f, -0.4032f, 0.0f, -0.2102f, 0.559f, 0.558f,
-0.4146f, 0.0f, -0.2027f, 0.559f, 0.559f, -0.426f, 0.0f, -0.1968f, 0.558f, 0.558f,
-0.4348f, 0.0f, -0.1931f, 0.558f, 0.558f, -0.4479f, 0.0f, -0.1886f, 0.555f, 0.559f,
};
static const float data1[33 * GP_PRIM_DATABUF_SIZE] = {
0.5292f, 0.0f, 0.1742f, 0.1f, 1.0f, 0.5291f, 0.0f, 0.1621f, 0.2199f, 1.0f,
0.5274f, 0.0f, 0.1386f, 0.4615f, 1.0f, 0.5239f, 0.0f, 0.116f, 0.6019f, 1.0f,
0.5185f, 0.0f, 0.0945f, 0.6981f, 1.0f, 0.5115f, 0.0f, 0.0741f, 0.7689f, 1.0f,
0.503f, 0.0f, 0.0548f, 0.8236f, 1.0f, 0.4931f, 0.0f, 0.0368f, 0.866f, 1.0f,
0.482f, 0.0f, 0.02f, 0.9003f, 1.0f, 0.4697f, 0.0f, 0.0046f, 0.9272f, 1.0f,
0.4565f, 0.0f, -0.0094f, 0.9485f, 1.0f, 0.4424f, 0.0f, -0.0219f, 0.9653f, 1.0f,
0.4275f, 0.0f, -0.033f, 0.9781f, 1.0f, 0.4121f, 0.0f, -0.0424f, 0.9876f, 1.0f,
0.3961f, 0.0f, -0.0501f, 0.9942f, 1.0f, 0.3799f, 0.0f, -0.0562f, 0.9983f, 1.0f,
0.3634f, 0.0f, -0.0605f, 0.9997f, 1.0f, 0.3468f, 0.0f, -0.0629f, 0.999f, 1.0f,
0.3303f, 0.0f, -0.0634f, 0.9963f, 1.0f, 0.3139f, 0.0f, -0.062f, 0.9912f, 1.0f,
0.2979f, 0.0f, -0.0585f, 0.9834f, 1.0f, 0.2823f, 0.0f, -0.0529f, 0.9724f, 1.0f,
0.2672f, 0.0f, -0.0452f, 0.9576f, 1.0f, 0.2529f, 0.0f, -0.0352f, 0.9385f, 1.0f,
0.2393f, 0.0f, -0.023f, 0.9143f, 1.0f, 0.2267f, 0.0f, -0.0085f, 0.8841f, 1.0f,
0.2153f, 0.0f, 0.0085f, 0.8461f, 1.0f, 0.205f, 0.0f, 0.0279f, 0.7979f, 1.0f,
0.196f, 0.0f, 0.0499f, 0.7359f, 1.0f, 0.1886f, 0.0f, 0.0745f, 0.6541f, 1.0f,
0.1827f, 0.0f, 0.1017f, 0.5396f, 1.0f, 0.1786f, 0.0f, 0.1316f, 0.36f, 1.0f,
0.1763f, 0.0f, 0.1643f, 0.1f, 1.0f,
};
static const float data2[18 * GP_PRIM_DATABUF_SIZE] = {
-0.0844f, 0.0f, -0.301f, 0.1f, 1.0f, -0.0825f, 0.0f, -0.3034f, 0.2199f, 1.0f,
-0.0751f, 0.0f, -0.3128f, 0.6019f, 1.0f, -0.0677f, 0.0f, -0.3216f, 0.7689f, 1.0f,
-0.06f, 0.0f, -0.3298f, 0.866f, 1.0f, -0.0522f, 0.0f, -0.3372f, 0.9272f, 1.0f,
-0.044f, 0.0f, -0.3437f, 0.9653f, 1.0f, -0.0354f, 0.0f, -0.3491f, 0.9876f, 1.0f,
-0.0264f, 0.0f, -0.3535f, 0.9983f, 1.0f, -0.0168f, 0.0f, -0.3566f, 0.999f, 1.0f,
-0.0065f, 0.0f, -0.3583f, 0.9912f, 1.0f, 0.0045f, 0.0f, -0.3585f, 0.9724f, 1.0f,
0.0163f, 0.0f, -0.3571f, 0.9385f, 1.0f, 0.029f, 0.0f, -0.354f, 0.8841f, 1.0f,
0.0427f, 0.0f, -0.3491f, 0.7979f, 1.0f, 0.0574f, 0.0f, -0.3421f, 0.6541f, 1.0f,
0.0732f, 0.0f, -0.3331f, 0.36f, 1.0f, 0.0816f, 0.0f, -0.3278f, 0.1f, 1.0f,
};
static const float data3[64 * GP_PRIM_DATABUF_SIZE] = {
-0.6551f, 0.0f, 0.4448f, 0.1f, 1.0f, -0.6353f, 0.0f, 0.4689f, 0.2199f, 1.0f,
-0.6211f, 0.0f, 0.4845f, 0.36f, 1.0f, -0.6033f, 0.0f, 0.5034f, 0.4615f, 1.0f,
-0.5856f, 0.0f, 0.5211f, 0.5396f, 1.0f, -0.5672f, 0.0f, 0.5387f, 0.6019f, 1.0f,
-0.5485f, 0.0f, 0.5555f, 0.6541f, 1.0f, -0.5295f, 0.0f, 0.5718f, 0.6981f, 1.0f,
-0.5103f, 0.0f, 0.5875f, 0.7359f, 1.0f, -0.4909f, 0.0f, 0.6028f, 0.7689f, 1.0f,
-0.4712f, 0.0f, 0.6174f, 0.7979f, 1.0f, -0.4512f, 0.0f, 0.6313f, 0.8236f, 1.0f,
-0.4307f, 0.0f, 0.6444f, 0.8461f, 1.0f, -0.4099f, 0.0f, 0.6568f, 0.866f, 1.0f,
-0.3884f, 0.0f, 0.6684f, 0.8841f, 1.0f, -0.3665f, 0.0f, 0.6793f, 0.9003f, 1.0f,
-0.3439f, 0.0f, 0.6893f, 0.9143f, 1.0f, -0.3207f, 0.0f, 0.6984f, 0.9272f, 1.0f,
-0.2971f, 0.0f, 0.7069f, 0.9385f, 1.0f, -0.2731f, 0.0f, 0.7148f, 0.9485f, 1.0f,
-0.249f, 0.0f, 0.7222f, 0.9576f, 1.0f, -0.2247f, 0.0f, 0.7292f, 0.9653f, 1.0f,
-0.2003f, 0.0f, 0.7356f, 0.9724f, 1.0f, -0.1759f, 0.0f, 0.7416f, 0.9781f, 1.0f,
-0.1515f, 0.0f, 0.7471f, 0.9834f, 1.0f, -0.1272f, 0.0f, 0.7518f, 0.9876f, 1.0f,
-0.1028f, 0.0f, 0.7556f, 0.9912f, 1.0f, -0.0785f, 0.0f, 0.7586f, 0.9942f, 1.0f,
-0.0543f, 0.0f, 0.7607f, 0.9963f, 1.0f, -0.0302f, 0.0f, 0.7621f, 0.9983f, 1.0f,
-0.0062f, 0.0f, 0.7627f, 0.999f, 1.0f, 0.0177f, 0.0f, 0.7625f, 0.9997f, 1.0f,
0.0415f, 0.0f, 0.7616f, 0.9997f, 1.0f, 0.0652f, 0.0f, 0.7602f, 0.999f, 1.0f,
0.0887f, 0.0f, 0.7583f, 0.9983f, 1.0f, 0.1122f, 0.0f, 0.7559f, 0.9963f, 1.0f,
0.1355f, 0.0f, 0.7529f, 0.9942f, 1.0f, 0.1585f, 0.0f, 0.7493f, 0.9912f, 1.0f,
0.1814f, 0.0f, 0.7451f, 0.9876f, 1.0f, 0.2041f, 0.0f, 0.7404f, 0.9834f, 1.0f,
0.2266f, 0.0f, 0.7352f, 0.9781f, 1.0f, 0.2488f, 0.0f, 0.729f, 0.9724f, 1.0f,
0.2706f, 0.0f, 0.7216f, 0.9653f, 1.0f, 0.2921f, 0.0f, 0.7131f, 0.9576f, 1.0f,
0.3135f, 0.0f, 0.7041f, 0.9485f, 1.0f, 0.3348f, 0.0f, 0.6945f, 0.9385f, 1.0f,
0.3559f, 0.0f, 0.6845f, 0.9272f, 1.0f, 0.3769f, 0.0f, 0.6739f, 0.9143f, 1.0f,
0.3978f, 0.0f, 0.6628f, 0.9003f, 1.0f, 0.4185f, 0.0f, 0.651f, 0.8841f, 1.0f,
0.439f, 0.0f, 0.6383f, 0.866f, 1.0f, 0.4594f, 0.0f, 0.6249f, 0.8461f, 1.0f,
0.4795f, 0.0f, 0.6106f, 0.8236f, 1.0f, 0.4995f, 0.0f, 0.5956f, 0.7979f, 1.0f,
0.5193f, 0.0f, 0.5801f, 0.7689f, 1.0f, 0.539f, 0.0f, 0.5642f, 0.7359f, 1.0f,
0.5586f, 0.0f, 0.5479f, 0.6981f, 1.0f, 0.578f, 0.0f, 0.5312f, 0.6541f, 1.0f,
0.597f, 0.0f, 0.5141f, 0.6019f, 1.0f, 0.6153f, 0.0f, 0.4966f, 0.5396f, 1.0f,
0.6324f, 0.0f, 0.4797f, 0.4615f, 1.0f, 0.6498f, 0.0f, 0.462f, 0.36f, 1.0f,
0.6638f, 0.0f, 0.4477f, 0.2199f, 1.0f, 0.6843f, 0.0f, 0.4263f, 0.1f, 1.0f,
};
static const float data4[33 * GP_PRIM_DATABUF_SIZE] = {
-0.7765f, 0.0f, 0.3255f, 0.1f, 1.0f, -0.7908f, 0.0f, 0.3335f, 0.2199f, 1.0f,
-0.8048f, 0.0f, 0.3402f, 0.4615f, 1.0f, -0.8225f, 0.0f, 0.3467f, 0.6019f, 1.0f,
-0.8426f, 0.0f, 0.3529f, 0.6981f, 1.0f, -0.8651f, 0.0f, 0.3587f, 0.7689f, 1.0f,
-0.8878f, 0.0f, 0.3633f, 0.8236f, 1.0f, -0.9105f, 0.0f, 0.367f, 0.866f, 1.0f,
-0.9323f, 0.0f, 0.3693f, 0.9003f, 1.0f, -0.9529f, 0.0f, 0.3701f, 0.9272f, 1.0f,
-0.972f, 0.0f, 0.3695f, 0.9485f, 1.0f, -0.9896f, 0.0f, 0.3675f, 0.9653f, 1.0f,
-1.0057f, 0.0f, 0.364f, 0.9781f, 1.0f, -1.0203f, 0.0f, 0.3592f, 0.9876f, 1.0f,
-1.0333f, 0.0f, 0.3528f, 0.9942f, 1.0f, -1.0447f, 0.0f, 0.3452f, 0.9983f, 1.0f,
-1.0546f, 0.0f, 0.3362f, 0.9997f, 1.0f, -1.0633f, 0.0f, 0.3261f, 0.999f, 1.0f,
-1.0708f, 0.0f, 0.315f, 0.9963f, 1.0f, -1.0767f, 0.0f, 0.3027f, 0.9912f, 1.0f,
-1.0818f, 0.0f, 0.2894f, 0.9834f, 1.0f, -1.0861f, 0.0f, 0.2752f, 0.9724f, 1.0f,
-1.0897f, 0.0f, 0.2604f, 0.9576f, 1.0f, -1.0922f, 0.0f, 0.2446f, 0.9385f, 1.0f,
-1.0938f, 0.0f, 0.2277f, 0.9143f, 1.0f, -1.0944f, 0.0f, 0.2098f, 0.8841f, 1.0f,
-1.0939f, 0.0f, 0.191f, 0.8461f, 1.0f, -1.0924f, 0.0f, 0.1714f, 0.7979f, 1.0f,
-1.0897f, 0.0f, 0.1511f, 0.7359f, 1.0f, -1.0855f, 0.0f, 0.1303f, 0.6541f, 1.0f,
-1.0798f, 0.0f, 0.1095f, 0.5396f, 1.0f, -1.0723f, 0.0f, 0.089f, 0.36f, 1.0f,
-1.0642f, 0.0f, 0.0702f, 0.1f, 1.0f,
};
static const float data5[64 * GP_PRIM_DATABUF_SIZE] = {
0.8135f, 0.0f, 0.3341f, 0.1f, 1.0f, 0.8191f, 0.0f, 0.3376f, 0.2199f, 1.0f,
0.8246f, 0.0f, 0.3408f, 0.36f, 1.0f, 0.8304f, 0.0f, 0.3438f, 0.4615f, 1.0f,
0.8368f, 0.0f, 0.3465f, 0.5396f, 1.0f, 0.843f, 0.0f, 0.3491f, 0.6019f, 1.0f,
0.8494f, 0.0f, 0.3515f, 0.6541f, 1.0f, 0.8558f, 0.0f, 0.3536f, 0.6981f, 1.0f,
0.8623f, 0.0f, 0.3557f, 0.7359f, 1.0f, 0.8688f, 0.0f, 0.3575f, 0.7689f, 1.0f,
0.8752f, 0.0f, 0.3593f, 0.7979f, 1.0f, 0.8813f, 0.0f, 0.3609f, 0.8236f, 1.0f,
0.8872f, 0.0f, 0.3625f, 0.8461f, 1.0f, 0.8929f, 0.0f, 0.364f, 0.866f, 1.0f,
0.8984f, 0.0f, 0.3653f, 0.8841f, 1.0f, 0.9039f, 0.0f, 0.3665f, 0.9003f, 1.0f,
0.9093f, 0.0f, 0.3675f, 0.9143f, 1.0f, 0.9146f, 0.0f, 0.3684f, 0.9272f, 1.0f,
0.9199f, 0.0f, 0.3692f, 0.9385f, 1.0f, 0.9253f, 0.0f, 0.3698f, 0.9485f, 1.0f,
0.9305f, 0.0f, 0.3703f, 0.9576f, 1.0f, 0.9358f, 0.0f, 0.3706f, 0.9653f, 1.0f,
0.941f, 0.0f, 0.3709f, 0.9724f, 1.0f, 0.9462f, 0.0f, 0.371f, 0.9781f, 1.0f,
0.9514f, 0.0f, 0.371f, 0.9834f, 1.0f, 0.9566f, 0.0f, 0.3708f, 0.9876f, 1.0f,
0.9617f, 0.0f, 0.3706f, 0.9912f, 1.0f, 0.9668f, 0.0f, 0.3702f, 0.9942f, 1.0f,
0.9718f, 0.0f, 0.3697f, 0.9963f, 1.0f, 0.9768f, 0.0f, 0.3692f, 0.9983f, 1.0f,
0.9818f, 0.0f, 0.3685f, 0.999f, 1.0f, 0.9867f, 0.0f, 0.3677f, 0.9997f, 1.0f,
0.9916f, 0.0f, 0.3667f, 0.9997f, 1.0f, 0.9964f, 0.0f, 0.3657f, 0.999f, 1.0f,
1.0012f, 0.0f, 0.3646f, 0.9983f, 1.0f, 1.006f, 0.0f, 0.3634f, 0.9963f, 1.0f,
1.0107f, 0.0f, 0.3621f, 0.9942f, 1.0f, 1.0154f, 0.0f, 0.3607f, 0.9912f, 1.0f,
1.02f, 0.0f, 0.3593f, 0.9876f, 1.0f, 1.0245f, 0.0f, 0.3577f, 0.9834f, 1.0f,
1.029f, 0.0f, 0.3561f, 0.9781f, 1.0f, 1.0335f, 0.0f, 0.3543f, 0.9724f, 1.0f,
1.0379f, 0.0f, 0.3525f, 0.9653f, 1.0f, 1.0422f, 0.0f, 0.3507f, 0.9576f, 1.0f,
1.0465f, 0.0f, 0.3487f, 0.9485f, 1.0f, 1.0507f, 0.0f, 0.3468f, 0.9385f, 1.0f,
1.0549f, 0.0f, 0.3447f, 0.9272f, 1.0f, 1.0591f, 0.0f, 0.3427f, 0.9143f, 1.0f,
1.0633f, 0.0f, 0.3404f, 0.9003f, 1.0f, 1.0675f, 0.0f, 0.338f, 0.8841f, 1.0f,
1.0717f, 0.0f, 0.3351f, 0.866f, 1.0f, 1.0761f, 0.0f, 0.3318f, 0.8461f, 1.0f,
1.0805f, 0.0f, 0.3279f, 0.8236f, 1.0f, 1.0849f, 0.0f, 0.3235f, 0.7979f, 1.0f,
1.0893f, 0.0f, 0.3186f, 0.7689f, 1.0f, 1.0936f, 0.0f, 0.3134f, 0.7359f, 1.0f,
1.0979f, 0.0f, 0.3076f, 0.6981f, 1.0f, 1.102f, 0.0f, 0.3017f, 0.6541f, 1.0f,
1.106f, 0.0f, 0.2953f, 0.6019f, 1.0f, 1.1097f, 0.0f, 0.289f, 0.5396f, 1.0f,
1.1132f, 0.0f, 0.2826f, 0.4615f, 1.0f, 1.1164f, 0.0f, 0.2766f, 0.36f, 1.0f,
1.1193f, 0.0f, 0.2708f, 0.2199f, 1.0f, 1.1221f, 0.0f, 0.2652f, 0.1f, 1.0f,
};
static const float data6[33 * GP_PRIM_DATABUF_SIZE] = {
-0.2677f, 0.0f, -0.3496f, 0.1f, 1.0f, -0.2658f, 0.0f, -0.3919f, 0.2199f, 1.0f,
-0.2657f, 0.0f, -0.4295f, 0.4615f, 1.0f, -0.2691f, 0.0f, -0.4621f, 0.6019f, 1.0f,
-0.275f, 0.0f, -0.4949f, 0.6981f, 1.0f, -0.2828f, 0.0f, -0.527f, 0.7689f, 1.0f,
-0.2911f, 0.0f, -0.5578f, 0.8236f, 1.0f, -0.2971f, 0.0f, -0.5884f, 0.866f, 1.0f,
-0.303f, 0.0f, -0.6181f, 0.9003f, 1.0f, -0.3089f, 0.0f, -0.6467f, 0.9272f, 1.0f,
-0.3148f, 0.0f, -0.6738f, 0.9485f, 1.0f, -0.3196f, 0.0f, -0.7f, 0.9653f, 1.0f,
-0.323f, 0.0f, -0.7253f, 0.9781f, 1.0f, -0.3234f, 0.0f, -0.7496f, 0.9876f, 1.0f,
-0.3219f, 0.0f, -0.7728f, 0.9942f, 1.0f, -0.3184f, 0.0f, -0.7949f, 0.9983f, 1.0f,
-0.3103f, 0.0f, -0.8138f, 0.9997f, 1.0f, -0.3004f, 0.0f, -0.8307f, 0.999f, 1.0f,
-0.2892f, 0.0f, -0.8464f, 0.9963f, 1.0f, -0.2766f, 0.0f, -0.8611f, 0.9912f, 1.0f,
-0.2618f, 0.0f, -0.8735f, 0.9834f, 1.0f, -0.2469f, 0.0f, -0.8853f, 0.9724f, 1.0f,
-0.2315f, 0.0f, -0.8964f, 0.9576f, 1.0f, -0.2158f, 0.0f, -0.9068f, 0.9385f, 1.0f,
-0.1997f, 0.0f, -0.9167f, 0.9143f, 1.0f, -0.1833f, 0.0f, -0.9262f, 0.8841f, 1.0f,
-0.1663f, 0.0f, -0.9355f, 0.8461f, 1.0f, -0.1481f, 0.0f, -0.9445f, 0.7979f, 1.0f,
-0.1282f, 0.0f, -0.9534f, 0.7359f, 1.0f, -0.1077f, 0.0f, -0.9625f, 0.6541f, 1.0f,
-0.0854f, 0.0f, -0.9718f, 0.5396f, 1.0f, -0.0616f, 0.0f, -0.9813f, 0.36f, 1.0f,
-0.0248f, 0.0f, -0.992f, 0.1f, 1.0f,
};
static const float data7[18 * GP_PRIM_DATABUF_SIZE] = {
-0.0618f, 0.0f, -0.1922f, 0.1f, 1.0f, -0.0703f, 0.0f, -0.2021f, 0.2199f, 1.0f,
-0.0758f, 0.0f, -0.2103f, 0.6019f, 1.0f, -0.0803f, 0.0f, -0.2206f, 0.7689f, 1.0f,
-0.083f, 0.0f, -0.2307f, 0.866f, 1.0f, -0.0851f, 0.0f, -0.2405f, 0.9272f, 1.0f,
-0.0865f, 0.0f, -0.2499f, 0.9653f, 1.0f, -0.0872f, 0.0f, -0.2588f, 0.9876f, 1.0f,
-0.0869f, 0.0f, -0.2673f, 0.9983f, 1.0f, -0.0858f, 0.0f, -0.2754f, 0.999f, 1.0f,
-0.0831f, 0.0f, -0.2829f, 0.9912f, 1.0f, -0.0791f, 0.0f, -0.2898f, 0.9724f, 1.0f,
-0.074f, 0.0f, -0.2966f, 0.9385f, 1.0f, -0.0674f, 0.0f, -0.303f, 0.8841f, 1.0f,
-0.0591f, 0.0f, -0.3084f, 0.7979f, 1.0f, -0.0465f, 0.0f, -0.3134f, 0.6541f, 1.0f,
-0.0331f, 0.0f, -0.3165f, 0.36f, 1.0f, -0.015f, 0.0f, -0.318f, 0.1f, 1.0f,
};
static const float data8[49 * GP_PRIM_DATABUF_SIZE] = {
0.5311f, 0.0f, 0.1661f, 1.0f, 1.0f, 0.5307f, 0.0f, 0.1794f, 1.0f, 1.0f,
0.5277f, 0.0f, 0.2057f, 1.0f, 1.0f, 0.5218f, 0.0f, 0.2314f, 1.0f, 1.0f,
0.513f, 0.0f, 0.256f, 1.0f, 1.0f, 0.5014f, 0.0f, 0.279f, 1.0f, 1.0f,
0.4874f, 0.0f, 0.3001f, 1.0f, 1.0f, 0.4711f, 0.0f, 0.3189f, 1.0f, 1.0f,
0.4529f, 0.0f, 0.3351f, 1.0f, 1.0f, 0.4329f, 0.0f, 0.3483f, 1.0f, 1.0f,
0.4117f, 0.0f, 0.3585f, 1.0f, 1.0f, 0.3894f, 0.0f, 0.3654f, 1.0f, 1.0f,
0.3666f, 0.0f, 0.3689f, 1.0f, 1.0f, 0.3435f, 0.0f, 0.3689f, 1.0f, 1.0f,
0.3207f, 0.0f, 0.3654f, 1.0f, 1.0f, 0.2985f, 0.0f, 0.3585f, 1.0f, 1.0f,
0.2772f, 0.0f, 0.3483f, 1.0f, 1.0f, 0.2573f, 0.0f, 0.3351f, 1.0f, 1.0f,
0.239f, 0.0f, 0.3189f, 1.0f, 1.0f, 0.2227f, 0.0f, 0.3001f, 1.0f, 1.0f,
0.2087f, 0.0f, 0.279f, 1.0f, 1.0f, 0.1972f, 0.0f, 0.256f, 1.0f, 1.0f,
0.1884f, 0.0f, 0.2314f, 1.0f, 1.0f, 0.1824f, 0.0f, 0.2057f, 1.0f, 1.0f,
0.1794f, 0.0f, 0.1794f, 1.0f, 1.0f, 0.1794f, 0.0f, 0.1528f, 1.0f, 1.0f,
0.1824f, 0.0f, 0.1264f, 1.0f, 1.0f, 0.1884f, 0.0f, 0.1007f, 1.0f, 1.0f,
0.1972f, 0.0f, 0.0762f, 1.0f, 1.0f, 0.2087f, 0.0f, 0.0531f, 1.0f, 1.0f,
0.2227f, 0.0f, 0.032f, 1.0f, 1.0f, 0.239f, 0.0f, 0.0132f, 1.0f, 1.0f,
0.2573f, 0.0f, -0.0029f, 1.0f, 1.0f, 0.2772f, 0.0f, -0.0162f, 1.0f, 1.0f,
0.2985f, 0.0f, -0.0264f, 1.0f, 1.0f, 0.3207f, 0.0f, -0.0333f, 1.0f, 1.0f,
0.3435f, 0.0f, -0.0368f, 1.0f, 1.0f, 0.3666f, 0.0f, -0.0368f, 1.0f, 1.0f,
0.3894f, 0.0f, -0.0333f, 1.0f, 1.0f, 0.4117f, 0.0f, -0.0264f, 1.0f, 1.0f,
0.4329f, 0.0f, -0.0162f, 1.0f, 1.0f, 0.4529f, 0.0f, -0.0029f, 1.0f, 1.0f,
0.4711f, 0.0f, 0.0132f, 1.0f, 1.0f, 0.4874f, 0.0f, 0.032f, 1.0f, 1.0f,
0.5014f, 0.0f, 0.0531f, 1.0f, 1.0f, 0.513f, 0.0f, 0.0762f, 1.0f, 1.0f,
0.5218f, 0.0f, 0.1007f, 1.0f, 1.0f, 0.5277f, 0.0f, 0.1264f, 1.0f, 1.0f,
0.5307f, 0.0f, 0.1528f, 1.0f, 1.0f,
};
static const float data9[33 * GP_PRIM_DATABUF_SIZE] = {
-0.5271f, 0.0f, 0.1742f, 0.1f, 1.0f, -0.527f, 0.0f, 0.1621f, 0.2199f, 1.0f,
-0.5253f, 0.0f, 0.1386f, 0.4615f, 1.0f, -0.5217f, 0.0f, 0.116f, 0.6019f, 1.0f,
-0.5164f, 0.0f, 0.0945f, 0.6981f, 1.0f, -0.5094f, 0.0f, 0.0741f, 0.7689f, 1.0f,
-0.5009f, 0.0f, 0.0548f, 0.8236f, 1.0f, -0.491f, 0.0f, 0.0368f, 0.866f, 1.0f,
-0.4799f, 0.0f, 0.02f, 0.9003f, 1.0f, -0.4676f, 0.0f, 0.0046f, 0.9272f, 1.0f,
-0.4544f, 0.0f, -0.0094f, 0.9485f, 1.0f, -0.4402f, 0.0f, -0.0219f, 0.9653f, 1.0f,
-0.4254f, 0.0f, -0.033f, 0.9781f, 1.0f, -0.4099f, 0.0f, -0.0424f, 0.9876f, 1.0f,
-0.394f, 0.0f, -0.0501f, 0.9942f, 1.0f, -0.3777f, 0.0f, -0.0562f, 0.9983f, 1.0f,
-0.3612f, 0.0f, -0.0605f, 0.9997f, 1.0f, -0.3447f, 0.0f, -0.0629f, 0.999f, 1.0f,
-0.3281f, 0.0f, -0.0634f, 0.9963f, 1.0f, -0.3118f, 0.0f, -0.062f, 0.9912f, 1.0f,
-0.2957f, 0.0f, -0.0585f, 0.9834f, 1.0f, -0.2801f, 0.0f, -0.0529f, 0.9724f, 1.0f,
-0.2651f, 0.0f, -0.0452f, 0.9576f, 1.0f, -0.2507f, 0.0f, -0.0352f, 0.9385f, 1.0f,
-0.2372f, 0.0f, -0.023f, 0.9143f, 1.0f, -0.2246f, 0.0f, -0.0085f, 0.8841f, 1.0f,
-0.2131f, 0.0f, 0.0085f, 0.8461f, 1.0f, -0.2028f, 0.0f, 0.0279f, 0.7979f, 1.0f,
-0.1939f, 0.0f, 0.0499f, 0.7359f, 1.0f, -0.1864f, 0.0f, 0.0745f, 0.6541f, 1.0f,
-0.1806f, 0.0f, 0.1017f, 0.5396f, 1.0f, -0.1765f, 0.0f, 0.1316f, 0.36f, 1.0f,
-0.1742f, 0.0f, 0.1643f, 0.1f, 1.0f,
};
static const float data10[49 * GP_PRIM_DATABUF_SIZE] = {
-0.174f, 0.0f, 0.1661f, 1.0f, 1.0f, -0.1744f, 0.0f, 0.1794f, 1.0f, 1.0f,
-0.1774f, 0.0f, 0.2057f, 1.0f, 1.0f, -0.1833f, 0.0f, 0.2314f, 1.0f, 1.0f,
-0.1922f, 0.0f, 0.256f, 1.0f, 1.0f, -0.2037f, 0.0f, 0.279f, 1.0f, 1.0f,
-0.2177f, 0.0f, 0.3001f, 1.0f, 1.0f, -0.234f, 0.0f, 0.3189f, 1.0f, 1.0f,
-0.2522f, 0.0f, 0.3351f, 1.0f, 1.0f, -0.2722f, 0.0f, 0.3483f, 1.0f, 1.0f,
-0.2935f, 0.0f, 0.3585f, 1.0f, 1.0f, -0.3157f, 0.0f, 0.3654f, 1.0f, 1.0f,
-0.3385f, 0.0f, 0.3689f, 1.0f, 1.0f, -0.3616f, 0.0f, 0.3689f, 1.0f, 1.0f,
-0.3844f, 0.0f, 0.3654f, 1.0f, 1.0f, -0.4066f, 0.0f, 0.3585f, 1.0f, 1.0f,
-0.4279f, 0.0f, 0.3483f, 1.0f, 1.0f, -0.4479f, 0.0f, 0.3351f, 1.0f, 1.0f,
-0.4661f, 0.0f, 0.3189f, 1.0f, 1.0f, -0.4824f, 0.0f, 0.3001f, 1.0f, 1.0f,
-0.4964f, 0.0f, 0.279f, 1.0f, 1.0f, -0.508f, 0.0f, 0.256f, 1.0f, 1.0f,
-0.5168f, 0.0f, 0.2314f, 1.0f, 1.0f, -0.5227f, 0.0f, 0.2057f, 1.0f, 1.0f,
-0.5257f, 0.0f, 0.1794f, 1.0f, 1.0f, -0.5257f, 0.0f, 0.1528f, 1.0f, 1.0f,
-0.5227f, 0.0f, 0.1264f, 1.0f, 1.0f, -0.5168f, 0.0f, 0.1007f, 1.0f, 1.0f,
-0.508f, 0.0f, 0.0762f, 1.0f, 1.0f, -0.4964f, 0.0f, 0.0531f, 1.0f, 1.0f,
-0.4824f, 0.0f, 0.032f, 1.0f, 1.0f, -0.4661f, 0.0f, 0.0132f, 1.0f, 1.0f,
-0.4479f, 0.0f, -0.0029f, 1.0f, 1.0f, -0.4279f, 0.0f, -0.0162f, 1.0f, 1.0f,
-0.4066f, 0.0f, -0.0264f, 1.0f, 1.0f, -0.3844f, 0.0f, -0.0333f, 1.0f, 1.0f,
-0.3616f, 0.0f, -0.0368f, 1.0f, 1.0f, -0.3385f, 0.0f, -0.0368f, 1.0f, 1.0f,
-0.3157f, 0.0f, -0.0333f, 1.0f, 1.0f, -0.2935f, 0.0f, -0.0264f, 1.0f, 1.0f,
-0.2722f, 0.0f, -0.0162f, 1.0f, 1.0f, -0.2522f, 0.0f, -0.0029f, 1.0f, 1.0f,
-0.234f, 0.0f, 0.0132f, 1.0f, 1.0f, -0.2177f, 0.0f, 0.032f, 1.0f, 1.0f,
-0.2037f, 0.0f, 0.0531f, 1.0f, 1.0f, -0.1922f, 0.0f, 0.0762f, 1.0f, 1.0f,
-0.1833f, 0.0f, 0.1007f, 1.0f, 1.0f, -0.1774f, 0.0f, 0.1264f, 1.0f, 1.0f,
-0.1744f, 0.0f, 0.1528f, 1.0f, 1.0f,
};
static const float data11[18 * GP_PRIM_DATABUF_SIZE] = {
0.963f, 0.0f, 0.1753f, 0.1f, 1.0f, 0.9555f, 0.0f, 0.1761f, 0.2199f, 1.0f,
0.9367f, 0.0f, 0.1758f, 0.6019f, 1.0f, 0.9202f, 0.0f, 0.1741f, 0.7689f, 1.0f,
0.9036f, 0.0f, 0.1714f, 0.866f, 1.0f, 0.8885f, 0.0f, 0.1668f, 0.9272f, 1.0f,
0.8746f, 0.0f, 0.1607f, 0.9653f, 1.0f, 0.8621f, 0.0f, 0.1531f, 0.9876f, 1.0f,
0.8503f, 0.0f, 0.1447f, 0.9983f, 1.0f, 0.8389f, 0.0f, 0.1352f, 0.999f, 1.0f,
0.8279f, 0.0f, 0.1244f, 0.9912f, 1.0f, 0.8174f, 0.0f, 0.1125f, 0.9724f, 1.0f,
0.8079f, 0.0f, 0.099f, 0.9385f, 1.0f, 0.7999f, 0.0f, 0.0839f, 0.8841f, 1.0f,
0.7935f, 0.0f, 0.0669f, 0.7979f, 1.0f, 0.7892f, 0.0f, 0.0488f, 0.6541f, 1.0f,
0.787f, 0.0f, 0.0305f, 0.36f, 1.0f, 0.7847f, 0.0f, 0.0139f, 0.1f, 1.0f,
};
static const float data12[18 * GP_PRIM_DATABUF_SIZE] = {
-1.0227f, 0.0f, 0.1753f, 0.1f, 1.0f, -1.0153f, 0.0f, 0.1761f, 0.2199f, 1.0f,
-0.9964f, 0.0f, 0.1758f, 0.6019f, 1.0f, -0.9799f, 0.0f, 0.1741f, 0.7689f, 1.0f,
-0.9634f, 0.0f, 0.1714f, 0.866f, 1.0f, -0.9483f, 0.0f, 0.1668f, 0.9272f, 1.0f,
-0.9344f, 0.0f, 0.1607f, 0.9653f, 1.0f, -0.9219f, 0.0f, 0.1531f, 0.9876f, 1.0f,
-0.9101f, 0.0f, 0.1447f, 0.9983f, 1.0f, -0.8986f, 0.0f, 0.1352f, 0.999f, 1.0f,
-0.8876f, 0.0f, 0.1244f, 0.9912f, 1.0f, -0.8772f, 0.0f, 0.1125f, 0.9724f, 1.0f,
-0.8677f, 0.0f, 0.099f, 0.9385f, 1.0f, -0.8597f, 0.0f, 0.0839f, 0.8841f, 1.0f,
-0.8533f, 0.0f, 0.0669f, 0.7979f, 1.0f, -0.849f, 0.0f, 0.0488f, 0.6541f, 1.0f,
-0.8467f, 0.0f, 0.0305f, 0.36f, 1.0f, -0.8444f, 0.0f, 0.0139f, 0.1f, 1.0f,
};
static const float data13[33 * GP_PRIM_DATABUF_SIZE] = {
-0.6794f, 0.0f, 0.3908f, 0.1f, 1.0f, -0.6711f, 0.0f, 0.4112f, 0.2199f, 1.0f,
-0.6513f, 0.0f, 0.4509f, 0.4615f, 1.0f, -0.6276f, 0.0f, 0.489f, 0.6019f, 1.0f,
-0.6001f, 0.0f, 0.5253f, 0.6981f, 1.0f, -0.5692f, 0.0f, 0.5598f, 0.7689f, 1.0f,
-0.535f, 0.0f, 0.5924f, 0.8236f, 1.0f, -0.4979f, 0.0f, 0.6228f, 0.866f, 1.0f,
-0.4579f, 0.0f, 0.651f, 0.9003f, 1.0f, -0.4155f, 0.0f, 0.677f, 0.9272f, 1.0f,
-0.3707f, 0.0f, 0.7005f, 0.9485f, 1.0f, -0.3239f, 0.0f, 0.7215f, 0.9653f, 1.0f,
-0.2753f, 0.0f, 0.7399f, 0.9781f, 1.0f, -0.2251f, 0.0f, 0.7555f, 0.9876f, 1.0f,
-0.1736f, 0.0f, 0.7683f, 0.9942f, 1.0f, -0.121f, 0.0f, 0.778f, 0.9983f, 1.0f,
-0.0675f, 0.0f, 0.7847f, 0.9997f, 1.0f, -0.0134f, 0.0f, 0.7882f, 0.999f, 1.0f,
0.0411f, 0.0f, 0.7884f, 0.9963f, 1.0f, 0.0957f, 0.0f, 0.7851f, 0.9912f, 1.0f,
0.1503f, 0.0f, 0.7783f, 0.9834f, 1.0f, 0.2045f, 0.0f, 0.7678f, 0.9724f, 1.0f,
0.2581f, 0.0f, 0.7536f, 0.9576f, 1.0f, 0.311f, 0.0f, 0.7355f, 0.9385f, 1.0f,
0.3628f, 0.0f, 0.7134f, 0.9143f, 1.0f, 0.4133f, 0.0f, 0.6873f, 0.8841f, 1.0f,
0.4622f, 0.0f, 0.6569f, 0.8461f, 1.0f, 0.5095f, 0.0f, 0.6221f, 0.7979f, 1.0f,
0.5547f, 0.0f, 0.583f, 0.7359f, 1.0f, 0.5977f, 0.0f, 0.5393f, 0.6541f, 1.0f,
0.6382f, 0.0f, 0.4909f, 0.5396f, 1.0f, 0.676f, 0.0f, 0.4377f, 0.36f, 1.0f,
0.7109f, 0.0f, 0.3797f, 0.1f, 1.0f,
};
static const float data14[33 * GP_PRIM_DATABUF_SIZE] = {
-0.7544f, 0.0f, 0.1799f, 0.1f, 1.0f, -0.7495f, 0.0f, 0.162f, 0.2199f, 1.0f,
-0.7392f, 0.0f, 0.1283f, 0.4615f, 1.0f, -0.7281f, 0.0f, 0.0975f, 0.6019f, 1.0f,
-0.7161f, 0.0f, 0.0693f, 0.6981f, 1.0f, -0.7033f, 0.0f, 0.0435f, 0.7689f, 1.0f,
-0.6898f, 0.0f, 0.02f, 0.8236f, 1.0f, -0.6757f, 0.0f, -0.0014f, 0.866f, 1.0f,
-0.6609f, 0.0f, -0.0208f, 0.9003f, 1.0f, -0.6455f, 0.0f, -0.0386f, 0.9272f, 1.0f,
-0.6297f, 0.0f, -0.0547f, 0.9485f, 1.0f, -0.6133f, 0.0f, -0.0695f, 0.9653f, 1.0f,
-0.5966f, 0.0f, -0.083f, 0.9781f, 1.0f, -0.5795f, 0.0f, -0.0955f, 0.9876f, 1.0f,
-0.5621f, 0.0f, -0.1071f, 0.9942f, 1.0f, -0.5444f, 0.0f, -0.118f, 0.9983f, 1.0f,
-0.5265f, 0.0f, -0.1284f, 0.9997f, 1.0f, -0.5084f, 0.0f, -0.1384f, 0.999f, 1.0f,
-0.4902f, 0.0f, -0.1483f, 0.9963f, 1.0f, -0.4719f, 0.0f, -0.1582f, 0.9912f, 1.0f,
-0.4537f, 0.0f, -0.1682f, 0.9834f, 1.0f, -0.4355f, 0.0f, -0.1787f, 0.9724f, 1.0f,
-0.4173f, 0.0f, -0.1896f, 0.9576f, 1.0f, -0.3993f, 0.0f, -0.2013f, 0.9385f, 1.0f,
-0.3815f, 0.0f, -0.2138f, 0.9143f, 1.0f, -0.364f, 0.0f, -0.2274f, 0.8841f, 1.0f,
-0.3467f, 0.0f, -0.2422f, 0.8461f, 1.0f, -0.3298f, 0.0f, -0.2584f, 0.7979f, 1.0f,
-0.3133f, 0.0f, -0.2762f, 0.7359f, 1.0f, -0.2972f, 0.0f, -0.2958f, 0.6541f, 1.0f,
-0.2816f, 0.0f, -0.3173f, 0.5396f, 1.0f, -0.2665f, 0.0f, -0.3409f, 0.36f, 1.0f,
-0.2521f, 0.0f, -0.3668f, 0.1f, 1.0f,
};
static const float data15[65 * GP_PRIM_DATABUF_SIZE] = {
-0.2854f, 0.0f, -0.4528f, 0.1f, 1.0f, -0.2866f, 0.0f, -0.4623f, 0.1288f, 1.0f,
-0.2899f, 0.0f, -0.4814f, 0.2962f, 1.0f, -0.2943f, 0.0f, -0.5008f, 0.4147f, 1.0f,
-0.2995f, 0.0f, -0.5203f, 0.5028f, 1.0f, -0.3054f, 0.0f, -0.54f, 0.5723f, 1.0f,
-0.3117f, 0.0f, -0.5598f, 0.6291f, 1.0f, -0.3182f, 0.0f, -0.5797f, 0.6768f, 1.0f,
-0.3249f, 0.0f, -0.5996f, 0.7177f, 1.0f, -0.3314f, 0.0f, -0.6196f, 0.753f, 1.0f,
-0.3376f, 0.0f, -0.6395f, 0.7838f, 1.0f, -0.3432f, 0.0f, -0.6594f, 0.8109f, 1.0f,
-0.3482f, 0.0f, -0.6792f, 0.8349f, 1.0f, -0.3523f, 0.0f, -0.6989f, 0.8564f, 1.0f,
-0.3552f, 0.0f, -0.7185f, 0.8756f, 1.0f, -0.3569f, 0.0f, -0.7379f, 0.8922f, 1.0f,
-0.357f, 0.0f, -0.7571f, 0.9074f, 1.0f, -0.3555f, 0.0f, -0.7761f, 0.9211f, 1.0f,
-0.3522f, 0.0f, -0.7948f, 0.9329f, 1.0f, -0.3467f, 0.0f, -0.8132f, 0.944f, 1.0f,
-0.339f, 0.0f, -0.8313f, 0.9531f, 1.0f, -0.3289f, 0.0f, -0.849f, 0.9617f, 1.0f,
-0.316f, 0.0f, -0.8663f, 0.9688f, 1.0f, -0.3004f, 0.0f, -0.8831f, 0.9755f, 1.0f,
-0.2817f, 0.0f, -0.8996f, 0.9808f, 1.0f, -0.2598f, 0.0f, -0.9155f, 0.9858f, 1.0f,
-0.2344f, 0.0f, -0.9309f, 0.9894f, 1.0f, -0.2051f, 0.0f, -0.9457f, 0.993f, 1.0f,
-0.1716f, 0.0f, -0.9599f, 0.9952f, 1.0f, -0.1341f, 0.0f, -0.9733f, 0.9973f, 1.0f,
-0.0928f, 0.0f, -0.9857f, 0.9987f, 1.0f, -0.05f, 0.0f, -0.9962f, 0.9993f, 1.0f,
-0.0087f, 0.0f, -1.0041f, 1.0f, 1.0f, 0.0287f, 0.0f, -1.0087f, 0.9993f, 1.0f,
0.062f, 0.0f, -1.0104f, 0.9987f, 1.0f, 0.0924f, 0.0f, -1.0102f, 0.9973f, 1.0f,
0.1205f, 0.0f, -1.0086f, 0.9952f, 1.0f, 0.1465f, 0.0f, -1.0057f, 0.993f, 1.0f,
0.1706f, 0.0f, -1.0017f, 0.9894f, 1.0f, 0.1928f, 0.0f, -0.9964f, 0.9858f, 1.0f,
0.2132f, 0.0f, -0.99f, 0.9808f, 1.0f, 0.2318f, 0.0f, -0.9824f, 0.9755f, 1.0f,
0.2487f, 0.0f, -0.9738f, 0.9688f, 1.0f, 0.2641f, 0.0f, -0.9641f, 0.9617f, 1.0f,
0.2778f, 0.0f, -0.9533f, 0.9531f, 1.0f, 0.2901f, 0.0f, -0.9415f, 0.944f, 1.0f,
0.3009f, 0.0f, -0.9287f, 0.9329f, 1.0f, 0.3103f, 0.0f, -0.9148f, 0.9211f, 1.0f,
0.3183f, 0.0f, -0.8999f, 0.9074f, 1.0f, 0.325f, 0.0f, -0.8841f, 0.8922f, 1.0f,
0.3304f, 0.0f, -0.8672f, 0.8756f, 1.0f, 0.3345f, 0.0f, -0.8493f, 0.8564f, 1.0f,
0.3374f, 0.0f, -0.8305f, 0.8349f, 1.0f, 0.3391f, 0.0f, -0.8107f, 0.8109f, 1.0f,
0.3397f, 0.0f, -0.7899f, 0.7838f, 1.0f, 0.3392f, 0.0f, -0.7682f, 0.753f, 1.0f,
0.3377f, 0.0f, -0.7456f, 0.7177f, 1.0f, 0.3352f, 0.0f, -0.7221f, 0.6768f, 1.0f,
0.3317f, 0.0f, -0.6976f, 0.6291f, 1.0f, 0.3273f, 0.0f, -0.6722f, 0.5723f, 1.0f,
0.322f, 0.0f, -0.646f, 0.5028f, 1.0f, 0.316f, 0.0f, -0.6188f, 0.4147f, 1.0f,
0.3091f, 0.0f, -0.5908f, 0.2962f, 1.0f, 0.3015f, 0.0f, -0.5619f, 0.1288f, 1.0f,
0.2974f, 0.0f, -0.5472f, 0.1f, 1.0f,
};
static const float data16[34 * GP_PRIM_DATABUF_SIZE] = {
-0.4408f, 0.0f, 0.5073f, 0.1f, 1.0f, -0.4312f, 0.0f, 0.5132f, 0.1288f, 1.0f,
-0.3945f, 0.0f, 0.5319f, 0.4147f, 1.0f, -0.3605f, 0.0f, 0.5438f, 0.5723f, 1.0f,
-0.3288f, 0.0f, 0.5496f, 0.6768f, 1.0f, -0.2992f, 0.0f, 0.5501f, 0.753f, 1.0f,
-0.2712f, 0.0f, 0.546f, 0.8109f, 1.0f, -0.2446f, 0.0f, 0.5381f, 0.8564f, 1.0f,
-0.2191f, 0.0f, 0.5272f, 0.8922f, 1.0f, -0.1943f, 0.0f, 0.5139f, 0.9211f, 1.0f,
-0.1699f, 0.0f, 0.4992f, 0.944f, 1.0f, -0.1456f, 0.0f, 0.4837f, 0.9617f, 1.0f,
-0.1211f, 0.0f, 0.4682f, 0.9755f, 1.0f, -0.096f, 0.0f, 0.4535f, 0.9858f, 1.0f,
-0.07f, 0.0f, 0.4404f, 0.993f, 1.0f, -0.0428f, 0.0f, 0.4301f, 0.9973f, 1.0f,
-0.016f, 0.0f, 0.4235f, 0.9993f, 1.0f, 0.0076f, 0.0f, 0.4216f, 0.9993f, 1.0f,
0.0283f, 0.0f, 0.4237f, 0.9973f, 1.0f, 0.0477f, 0.0f, 0.4291f, 0.993f, 1.0f,
0.067f, 0.0f, 0.4369f, 0.9858f, 1.0f, 0.0866f, 0.0f, 0.4465f, 0.9755f, 1.0f,
0.1068f, 0.0f, 0.4576f, 0.9617f, 1.0f, 0.1278f, 0.0f, 0.4695f, 0.944f, 1.0f,
0.1498f, 0.0f, 0.4819f, 0.9211f, 1.0f, 0.173f, 0.0f, 0.4941f, 0.8922f, 1.0f,
0.1977f, 0.0f, 0.5056f, 0.8564f, 1.0f, 0.2241f, 0.0f, 0.5159f, 0.8109f, 1.0f,
0.2523f, 0.0f, 0.5244f, 0.753f, 1.0f, 0.2825f, 0.0f, 0.5307f, 0.6768f, 1.0f,
0.315f, 0.0f, 0.5342f, 0.5723f, 1.0f, 0.3499f, 0.0f, 0.5345f, 0.4147f, 1.0f,
0.3875f, 0.0f, 0.5311f, 0.1288f, 1.0f, 0.3973f, 0.0f, 0.5295f, 0.1f, 1.0f,
};
static const float data17[33 * GP_PRIM_DATABUF_SIZE] = {
0.724f, 0.0f, 0.1799f, 0.1f, 1.0f, 0.7192f, 0.0f, 0.162f, 0.2199f, 1.0f,
0.7089f, 0.0f, 0.1283f, 0.4615f, 1.0f, 0.6977f, 0.0f, 0.0975f, 0.6019f, 1.0f,
0.6858f, 0.0f, 0.0693f, 0.6981f, 1.0f, 0.673f, 0.0f, 0.0435f, 0.7689f, 1.0f,
0.6595f, 0.0f, 0.02f, 0.8236f, 1.0f, 0.6453f, 0.0f, -0.0014f, 0.866f, 1.0f,
0.6306f, 0.0f, -0.0208f, 0.9003f, 1.0f, 0.6152f, 0.0f, -0.0386f, 0.9272f, 1.0f,
0.5994f, 0.0f, -0.0547f, 0.9485f, 1.0f, 0.583f, 0.0f, -0.0695f, 0.9653f, 1.0f,
0.5663f, 0.0f, -0.083f, 0.9781f, 1.0f, 0.5492f, 0.0f, -0.0955f, 0.9876f, 1.0f,
0.5317f, 0.0f, -0.1071f, 0.9942f, 1.0f, 0.514f, 0.0f, -0.118f, 0.9983f, 1.0f,
0.4961f, 0.0f, -0.1284f, 0.9997f, 1.0f, 0.4781f, 0.0f, -0.1384f, 0.999f, 1.0f,
0.4599f, 0.0f, -0.1483f, 0.9963f, 1.0f, 0.4416f, 0.0f, -0.1582f, 0.9912f, 1.0f,
0.4234f, 0.0f, -0.1682f, 0.9834f, 1.0f, 0.4051f, 0.0f, -0.1787f, 0.9724f, 1.0f,
0.387f, 0.0f, -0.1896f, 0.9576f, 1.0f, 0.369f, 0.0f, -0.2013f, 0.9385f, 1.0f,
0.3512f, 0.0f, -0.2138f, 0.9143f, 1.0f, 0.3337f, 0.0f, -0.2274f, 0.8841f, 1.0f,
0.3164f, 0.0f, -0.2422f, 0.8461f, 1.0f, 0.2995f, 0.0f, -0.2584f, 0.7979f, 1.0f,
0.2829f, 0.0f, -0.2762f, 0.7359f, 1.0f, 0.2669f, 0.0f, -0.2958f, 0.6541f, 1.0f,
0.2513f, 0.0f, -0.3173f, 0.5396f, 1.0f, 0.2362f, 0.0f, -0.3409f, 0.36f, 1.0f,
0.2218f, 0.0f, -0.3668f, 0.1f, 1.0f,
};
static const float data18[33 * GP_PRIM_DATABUF_SIZE] = {
-0.1119f, 0.0f, -0.7868f, 0.1f, 1.0f, -0.1087f, 0.0f, -0.7905f, 0.2199f, 1.0f,
-0.1022f, 0.0f, -0.7974f, 0.4615f, 1.0f, -0.0955f, 0.0f, -0.8038f, 0.6019f, 1.0f,
-0.0886f, 0.0f, -0.8097f, 0.6981f, 1.0f, -0.0816f, 0.0f, -0.8152f, 0.7689f, 1.0f,
-0.0744f, 0.0f, -0.8201f, 0.8236f, 1.0f, -0.0671f, 0.0f, -0.8246f, 0.866f, 1.0f,
-0.0597f, 0.0f, -0.8286f, 0.9003f, 1.0f, -0.0522f, 0.0f, -0.8321f, 0.9272f, 1.0f,
-0.0446f, 0.0f, -0.8351f, 0.9485f, 1.0f, -0.0369f, 0.0f, -0.8376f, 0.9653f, 1.0f,
-0.0292f, 0.0f, -0.8397f, 0.9781f, 1.0f, -0.0214f, 0.0f, -0.8413f, 0.9876f, 1.0f,
-0.0136f, 0.0f, -0.8424f, 0.9942f, 1.0f, -0.0057f, 0.0f, -0.843f, 0.9983f, 1.0f,
0.0022f, 0.0f, -0.8431f, 0.9997f, 1.0f, 0.01f, 0.0f, -0.8428f, 0.999f, 1.0f,
0.0178f, 0.0f, -0.8419f, 0.9963f, 1.0f, 0.0257f, 0.0f, -0.8407f, 0.9912f, 1.0f,
0.0334f, 0.0f, -0.8389f, 0.9834f, 1.0f, 0.0411f, 0.0f, -0.8366f, 0.9724f, 1.0f,
0.0488f, 0.0f, -0.8339f, 0.9576f, 1.0f, 0.0564f, 0.0f, -0.8308f, 0.9385f, 1.0f,
0.0638f, 0.0f, -0.8271f, 0.9143f, 1.0f, 0.0712f, 0.0f, -0.823f, 0.8841f, 1.0f,
0.0785f, 0.0f, -0.8184f, 0.8461f, 1.0f, 0.0856f, 0.0f, -0.8134f, 0.7979f, 1.0f,
0.0925f, 0.0f, -0.8079f, 0.7359f, 1.0f, 0.0994f, 0.0f, -0.8019f, 0.6541f, 1.0f,
0.106f, 0.0f, -0.7954f, 0.5396f, 1.0f, 0.1125f, 0.0f, -0.7885f, 0.36f, 1.0f,
0.1187f, 0.0f, -0.7812f, 0.1f, 1.0f,
};
static const float data19[34 * GP_PRIM_DATABUF_SIZE] = {
-0.1119f, 0.0f, -0.2655f, 0.1f, 1.0f, -0.1101f, 0.0f, -0.2605f, 0.1288f, 1.0f,
-0.1032f, 0.0f, -0.2424f, 0.4147f, 1.0f, -0.0965f, 0.0f, -0.2276f, 0.5723f, 1.0f,
-0.0901f, 0.0f, -0.2158f, 0.6768f, 1.0f, -0.0837f, 0.0f, -0.2069f, 0.753f, 1.0f,
-0.0775f, 0.0f, -0.2006f, 0.8109f, 1.0f, -0.0712f, 0.0f, -0.1967f, 0.8564f, 1.0f,
-0.065f, 0.0f, -0.1949f, 0.8922f, 1.0f, -0.0587f, 0.0f, -0.195f, 0.9211f, 1.0f,
-0.0522f, 0.0f, -0.1968f, 0.944f, 1.0f, -0.0455f, 0.0f, -0.2001f, 0.9617f, 1.0f,
-0.0386f, 0.0f, -0.2046f, 0.9755f, 1.0f, -0.0315f, 0.0f, -0.21f, 0.9858f, 1.0f,
-0.0239f, 0.0f, -0.2163f, 0.993f, 1.0f, -0.016f, 0.0f, -0.223f, 0.9973f, 1.0f,
-0.0075f, 0.0f, -0.2301f, 0.9993f, 1.0f, -0.0002f, 0.0f, -0.2342f, 0.9993f, 1.0f,
0.0054f, 0.0f, -0.234f, 0.9973f, 1.0f, 0.0106f, 0.0f, -0.2324f, 0.993f, 1.0f,
0.0155f, 0.0f, -0.2297f, 0.9858f, 1.0f, 0.0202f, 0.0f, -0.2261f, 0.9755f, 1.0f,
0.0249f, 0.0f, -0.2219f, 0.9617f, 1.0f, 0.0296f, 0.0f, -0.2174f, 0.944f, 1.0f,
0.0344f, 0.0f, -0.2128f, 0.9211f, 1.0f, 0.0394f, 0.0f, -0.2084f, 0.8922f, 1.0f,
0.0448f, 0.0f, -0.2044f, 0.8564f, 1.0f, 0.0506f, 0.0f, -0.2012f, 0.8109f, 1.0f,
0.057f, 0.0f, -0.1988f, 0.753f, 1.0f, 0.064f, 0.0f, -0.1977f, 0.6768f, 1.0f,
0.0717f, 0.0f, -0.198f, 0.5723f, 1.0f, 0.0804f, 0.0f, -0.2001f, 0.4147f, 1.0f,
0.0899f, 0.0f, -0.2042f, 0.1288f, 1.0f, 0.0925f, 0.0f, -0.2055f, 0.1f, 1.0f,
};
static const float data20[33 * GP_PRIM_DATABUF_SIZE] = {
0.7993f, 0.0f, 0.3242f, 0.1f, 1.0f, 0.8169f, 0.0f, 0.3354f, 0.2199f, 1.0f,
0.8512f, 0.0f, 0.3542f, 0.4615f, 1.0f, 0.884f, 0.0f, 0.3686f, 0.6019f, 1.0f,
0.9153f, 0.0f, 0.3787f, 0.6981f, 1.0f, 0.945f, 0.0f, 0.3848f, 0.7689f, 1.0f,
0.9729f, 0.0f, 0.3871f, 0.8236f, 1.0f, 0.9989f, 0.0f, 0.3857f, 0.866f, 1.0f,
1.0229f, 0.0f, 0.3811f, 0.9003f, 1.0f, 1.0447f, 0.0f, 0.3732f, 0.9272f, 1.0f,
1.0643f, 0.0f, 0.3624f, 0.9485f, 1.0f, 1.0814f, 0.0f, 0.349f, 0.9653f, 1.0f,
1.096f, 0.0f, 0.333f, 0.9781f, 1.0f, 1.108f, 0.0f, 0.3147f, 0.9876f, 1.0f,
1.1172f, 0.0f, 0.2944f, 0.9942f, 1.0f, 1.1235f, 0.0f, 0.2723f, 0.9983f, 1.0f,
1.1267f, 0.0f, 0.2485f, 0.9997f, 1.0f, 1.1269f, 0.0f, 0.2233f, 0.999f, 1.0f,
1.1237f, 0.0f, 0.197f, 0.9963f, 1.0f, 1.1172f, 0.0f, 0.1697f, 0.9912f, 1.0f,
1.1071f, 0.0f, 0.1417f, 0.9834f, 1.0f, 1.0934f, 0.0f, 0.1131f, 0.9724f, 1.0f,
1.0759f, 0.0f, 0.0842f, 0.9576f, 1.0f, 1.0545f, 0.0f, 0.0553f, 0.9385f, 1.0f,
1.0291f, 0.0f, 0.0265f, 0.9143f, 1.0f, 0.9995f, 0.0f, -0.0019f, 0.8841f, 1.0f,
0.9657f, 0.0f, -0.0298f, 0.8461f, 1.0f, 0.9275f, 0.0f, -0.0569f, 0.7979f, 1.0f,
0.8847f, 0.0f, -0.0829f, 0.7359f, 1.0f, 0.8373f, 0.0f, -0.1077f, 0.6541f, 1.0f,
0.7852f, 0.0f, -0.1311f, 0.5396f, 1.0f, 0.7281f, 0.0f, -0.1528f, 0.36f, 1.0f,
0.6661f, 0.0f, -0.1725f, 0.1f, 1.0f,
};
static const float data21[64 * GP_PRIM_DATABUF_SIZE] = {
-0.7428f, 0.0f, 0.2977f, 0.1f, 1.0f, -0.7608f, 0.0f, 0.3138f, 0.2199f, 1.0f,
-0.7786f, 0.0f, 0.3284f, 0.36f, 1.0f, -0.7962f, 0.0f, 0.3414f, 0.4615f, 1.0f,
-0.8135f, 0.0f, 0.3531f, 0.5396f, 1.0f, -0.8306f, 0.0f, 0.3633f, 0.6019f, 1.0f,
-0.8473f, 0.0f, 0.3722f, 0.6541f, 1.0f, -0.8637f, 0.0f, 0.3798f, 0.6981f, 1.0f,
-0.8798f, 0.0f, 0.386f, 0.7359f, 1.0f, -0.8956f, 0.0f, 0.3911f, 0.7689f, 1.0f,
-0.9109f, 0.0f, 0.3949f, 0.7979f, 1.0f, -0.9259f, 0.0f, 0.3975f, 0.8236f, 1.0f,
-0.9405f, 0.0f, 0.3989f, 0.8461f, 1.0f, -0.9546f, 0.0f, 0.3993f, 0.866f, 1.0f,
-0.9682f, 0.0f, 0.3986f, 0.8841f, 1.0f, -0.9814f, 0.0f, 0.3969f, 0.9003f, 1.0f,
-0.994f, 0.0f, 0.3941f, 0.9143f, 1.0f, -1.0062f, 0.0f, 0.3904f, 0.9272f, 1.0f,
-1.0178f, 0.0f, 0.3858f, 0.9385f, 1.0f, -1.0288f, 0.0f, 0.3803f, 0.9485f, 1.0f,
-1.0393f, 0.0f, 0.3739f, 0.9576f, 1.0f, -1.0492f, 0.0f, 0.3668f, 0.9653f, 1.0f,
-1.0584f, 0.0f, 0.3588f, 0.9724f, 1.0f, -1.067f, 0.0f, 0.3501f, 0.9781f, 1.0f,
-1.075f, 0.0f, 0.3407f, 0.9834f, 1.0f, -1.0822f, 0.0f, 0.3307f, 0.9876f, 1.0f,
-1.0888f, 0.0f, 0.32f, 0.9912f, 1.0f, -1.0946f, 0.0f, 0.3087f, 0.9942f, 1.0f,
-1.0997f, 0.0f, 0.2969f, 0.9963f, 1.0f, -1.104f, 0.0f, 0.2845f, 0.9983f, 1.0f,
-1.1075f, 0.0f, 0.2717f, 0.999f, 1.0f, -1.1103f, 0.0f, 0.2584f, 0.9997f, 1.0f,
-1.1122f, 0.0f, 0.2447f, 0.9997f, 1.0f, -1.1132f, 0.0f, 0.2306f, 0.999f, 1.0f,
-1.1134f, 0.0f, 0.2162f, 0.9983f, 1.0f, -1.1128f, 0.0f, 0.2015f, 0.9963f, 1.0f,
-1.1112f, 0.0f, 0.1865f, 0.9942f, 1.0f, -1.1086f, 0.0f, 0.1713f, 0.9912f, 1.0f,
-1.1052f, 0.0f, 0.1559f, 0.9876f, 1.0f, -1.1007f, 0.0f, 0.1404f, 0.9834f, 1.0f,
-1.0953f, 0.0f, 0.1247f, 0.9781f, 1.0f, -1.0889f, 0.0f, 0.109f, 0.9724f, 1.0f,
-1.0814f, 0.0f, 0.0932f, 0.9653f, 1.0f, -1.0729f, 0.0f, 0.0774f, 0.9576f, 1.0f,
-1.0633f, 0.0f, 0.0617f, 0.9485f, 1.0f, -1.0527f, 0.0f, 0.046f, 0.9385f, 1.0f,
-1.0409f, 0.0f, 0.0304f, 0.9272f, 1.0f, -1.028f, 0.0f, 0.015f, 0.9143f, 1.0f,
-1.0139f, 0.0f, -0.0003f, 0.9003f, 1.0f, -0.9987f, 0.0f, -0.0154f, 0.8841f, 1.0f,
-0.9823f, 0.0f, -0.0302f, 0.866f, 1.0f, -0.9646f, 0.0f, -0.0447f, 0.8461f, 1.0f,
-0.9458f, 0.0f, -0.0589f, 0.8236f, 1.0f, -0.9257f, 0.0f, -0.0727f, 0.7979f, 1.0f,
-0.9043f, 0.0f, -0.0862f, 0.7689f, 1.0f, -0.8816f, 0.0f, -0.0992f, 0.7359f, 1.0f,
-0.8576f, 0.0f, -0.1117f, 0.6981f, 1.0f, -0.8323f, 0.0f, -0.1237f, 0.6541f, 1.0f,
-0.8056f, 0.0f, -0.1352f, 0.6019f, 1.0f, -0.7775f, 0.0f, -0.1461f, 0.5396f, 1.0f,
-0.7481f, 0.0f, -0.1564f, 0.4615f, 1.0f, -0.7172f, 0.0f, -0.166f, 0.36f, 1.0f,
-0.6849f, 0.0f, -0.175f, 0.2199f, 1.0f, -0.6512f, 0.0f, -0.1832f, 0.1f, 1.0f,
};
static const float data22[26 * GP_PRIM_DATABUF_SIZE] = {
0.2721f, 0.0f, 0.2084f, 1.0f, 1.0f, 0.2721f, 0.0f, 0.2112f, 1.0f, 1.0f,
0.2739f, 0.0f, 0.2223f, 1.0f, 1.0f, 0.2778f, 0.0f, 0.2324f, 1.0f, 1.0f,
0.2836f, 0.0f, 0.2409f, 1.0f, 1.0f, 0.291f, 0.0f, 0.2471f, 1.0f, 1.0f,
0.2994f, 0.0f, 0.2507f, 1.0f, 1.0f, 0.3082f, 0.0f, 0.2515f, 1.0f, 1.0f,
0.3169f, 0.0f, 0.2493f, 1.0f, 1.0f, 0.3248f, 0.0f, 0.2443f, 1.0f, 1.0f,
0.3315f, 0.0f, 0.2369f, 1.0f, 1.0f, 0.3364f, 0.0f, 0.2275f, 1.0f, 1.0f,
0.3392f, 0.0f, 0.2168f, 1.0f, 1.0f, 0.3398f, 0.0f, 0.2056f, 1.0f, 1.0f,
0.3381f, 0.0f, 0.1945f, 1.0f, 1.0f, 0.3342f, 0.0f, 0.1844f, 1.0f, 1.0f,
0.3283f, 0.0f, 0.176f, 1.0f, 1.0f, 0.321f, 0.0f, 0.1697f, 1.0f, 1.0f,
0.3126f, 0.0f, 0.1661f, 1.0f, 1.0f, 0.3038f, 0.0f, 0.1653f, 1.0f, 1.0f,
0.2951f, 0.0f, 0.1675f, 1.0f, 1.0f, 0.2871f, 0.0f, 0.1725f, 1.0f, 1.0f,
0.2805f, 0.0f, 0.1799f, 1.0f, 1.0f, 0.2756f, 0.0f, 0.1893f, 1.0f, 1.0f,
0.2727f, 0.0f, 0.2f, 1.0f, 1.0f, 0.2721f, 0.0f, 0.2056f, 1.0f, 1.0f,
};
static const float data23[26 * GP_PRIM_DATABUF_SIZE] = {
-0.3545f, 0.0f, 0.2084f, 1.0f, 1.0f, -0.3544f, 0.0f, 0.2112f, 1.0f, 1.0f,
-0.3527f, 0.0f, 0.2223f, 1.0f, 1.0f, -0.3488f, 0.0f, 0.2324f, 1.0f, 1.0f,
-0.343f, 0.0f, 0.2409f, 1.0f, 1.0f, -0.3356f, 0.0f, 0.2471f, 1.0f, 1.0f,
-0.3272f, 0.0f, 0.2507f, 1.0f, 1.0f, -0.3184f, 0.0f, 0.2515f, 1.0f, 1.0f,
-0.3097f, 0.0f, 0.2493f, 1.0f, 1.0f, -0.3018f, 0.0f, 0.2443f, 1.0f, 1.0f,
-0.2951f, 0.0f, 0.2369f, 1.0f, 1.0f, -0.2902f, 0.0f, 0.2275f, 1.0f, 1.0f,
-0.2874f, 0.0f, 0.2168f, 1.0f, 1.0f, -0.2868f, 0.0f, 0.2056f, 1.0f, 1.0f,
-0.2885f, 0.0f, 0.1945f, 1.0f, 1.0f, -0.2924f, 0.0f, 0.1844f, 1.0f, 1.0f,
-0.2983f, 0.0f, 0.176f, 1.0f, 1.0f, -0.3056f, 0.0f, 0.1697f, 1.0f, 1.0f,
-0.314f, 0.0f, 0.1661f, 1.0f, 1.0f, -0.3228f, 0.0f, 0.1653f, 1.0f, 1.0f,
-0.3315f, 0.0f, 0.1675f, 1.0f, 1.0f, -0.3394f, 0.0f, 0.1725f, 1.0f, 1.0f,
-0.3461f, 0.0f, 0.1799f, 1.0f, 1.0f, -0.351f, 0.0f, 0.1893f, 1.0f, 1.0f,
-0.3539f, 0.0f, 0.2f, 1.0f, 1.0f, -0.3544f, 0.0f, 0.2056f, 1.0f, 1.0f,
};
static const float data24[33 * GP_PRIM_DATABUF_SIZE] = {
0.1904f, 0.0f, 0.0983f, 0.1f, 1.0f, 0.1997f, 0.0f, 0.0774f, 0.2199f, 1.0f,
0.2234f, 0.0f, 0.0407f, 0.4615f, 1.0f, 0.2477f, 0.0f, 0.0158f, 0.6019f, 1.0f,
0.2767f, 0.0f, -0.0047f, 0.6981f, 1.0f, 0.3061f, 0.0f, -0.0179f, 0.7689f, 1.0f,
0.3346f, 0.0f, -0.0247f, 0.8236f, 1.0f, 0.362f, 0.0f, -0.0262f, 0.866f, 1.0f,
0.3881f, 0.0f, -0.0231f, 0.9003f, 1.0f, 0.4128f, 0.0f, -0.0159f, 0.9272f, 1.0f,
0.436f, 0.0f, -0.0049f, 0.9485f, 1.0f, 0.4577f, 0.0f, 0.0099f, 0.9653f, 1.0f,
0.4778f, 0.0f, 0.0289f, 0.9781f, 1.0f, 0.4959f, 0.0f, 0.0524f, 0.9876f, 1.0f,
0.5114f, 0.0f, 0.0806f, 0.9942f, 1.0f, 0.5229f, 0.0f, 0.1134f, 0.9983f, 1.0f,
0.5291f, 0.0f, 0.1498f, 0.9997f, 1.0f, 0.5289f, 0.0f, 0.1884f, 0.999f, 1.0f,
0.5219f, 0.0f, 0.2267f, 0.9963f, 1.0f, 0.5087f, 0.0f, 0.2616f, 0.9912f, 1.0f,
0.4907f, 0.0f, 0.2916f, 0.9834f, 1.0f, 0.4697f, 0.0f, 0.3159f, 0.9724f, 1.0f,
0.4465f, 0.0f, 0.3349f, 0.9576f, 1.0f, 0.422f, 0.0f, 0.3489f, 0.9385f, 1.0f,
0.3964f, 0.0f, 0.3582f, 0.9143f, 1.0f, 0.3705f, 0.0f, 0.3628f, 0.8841f, 1.0f,
0.3436f, 0.0f, 0.363f, 0.8461f, 1.0f, 0.3166f, 0.0f, 0.3586f, 0.7979f, 1.0f,
0.2897f, 0.0f, 0.3491f, 0.7359f, 1.0f, 0.2635f, 0.0f, 0.3344f, 0.6541f, 1.0f,
0.2382f, 0.0f, 0.3137f, 0.5396f, 1.0f, 0.2162f, 0.0f, 0.2882f, 0.36f, 1.0f,
0.1949f, 0.0f, 0.2516f, 0.1f, 1.0f,
};
static const float data25[18 * GP_PRIM_DATABUF_SIZE] = {
-1.0361f, 0.0f, 0.1745f, 0.1f, 1.0f, -1.0319f, 0.0f, 0.177f, 0.2199f, 1.0f,
-1.0153f, 0.0f, 0.1852f, 0.6019f, 1.0f, -0.999f, 0.0f, 0.1907f, 0.7689f, 1.0f,
-0.983f, 0.0f, 0.1936f, 0.866f, 1.0f, -0.9673f, 0.0f, 0.1941f, 0.9272f, 1.0f,
-0.9522f, 0.0f, 0.1923f, 0.9653f, 1.0f, -0.9376f, 0.0f, 0.1885f, 0.9876f, 1.0f,
-0.9236f, 0.0f, 0.1827f, 0.9983f, 1.0f, -0.9103f, 0.0f, 0.1752f, 0.999f, 1.0f,
-0.8978f, 0.0f, 0.1662f, 0.9912f, 1.0f, -0.8862f, 0.0f, 0.1558f, 0.9724f, 1.0f,
-0.8756f, 0.0f, 0.1441f, 0.9385f, 1.0f, -0.866f, 0.0f, 0.1314f, 0.8841f, 1.0f,
-0.8575f, 0.0f, 0.1179f, 0.7979f, 1.0f, -0.8501f, 0.0f, 0.1036f, 0.6541f, 1.0f,
-0.8441f, 0.0f, 0.0889f, 0.36f, 1.0f, -0.8416f, 0.0f, 0.0813f, 0.1f, 1.0f,
};
static const float data26[18 * GP_PRIM_DATABUF_SIZE] = {
0.9747f, 0.0f, 0.1745f, 0.1f, 1.0f, 0.9706f, 0.0f, 0.177f, 0.2199f, 1.0f,
0.954f, 0.0f, 0.1852f, 0.6019f, 1.0f, 0.9377f, 0.0f, 0.1907f, 0.7689f, 1.0f,
0.9216f, 0.0f, 0.1936f, 0.866f, 1.0f, 0.906f, 0.0f, 0.1941f, 0.9272f, 1.0f,
0.8908f, 0.0f, 0.1923f, 0.9653f, 1.0f, 0.8762f, 0.0f, 0.1885f, 0.9876f, 1.0f,
0.8622f, 0.0f, 0.1827f, 0.9983f, 1.0f, 0.849f, 0.0f, 0.1752f, 0.999f, 1.0f,
0.8365f, 0.0f, 0.1662f, 0.9912f, 1.0f, 0.8249f, 0.0f, 0.1558f, 0.9724f, 1.0f,
0.8143f, 0.0f, 0.1441f, 0.9385f, 1.0f, 0.8046f, 0.0f, 0.1314f, 0.8841f, 1.0f,
0.7961f, 0.0f, 0.1179f, 0.7979f, 1.0f, 0.7888f, 0.0f, 0.1036f, 0.6541f, 1.0f,
0.7828f, 0.0f, 0.0889f, 0.36f, 1.0f, 0.7802f, 0.0f, 0.0813f, 0.1f, 1.0f,
};
static const float data27[33 * GP_PRIM_DATABUF_SIZE] = {
-0.186f, 0.0f, 0.0983f, 0.1f, 1.0f, -0.1954f, 0.0f, 0.0774f, 0.2199f, 1.0f,
-0.2191f, 0.0f, 0.0407f, 0.4615f, 1.0f, -0.2434f, 0.0f, 0.0158f, 0.6019f, 1.0f,
-0.2723f, 0.0f, -0.0047f, 0.6981f, 1.0f, -0.3017f, 0.0f, -0.0179f, 0.7689f, 1.0f,
-0.3302f, 0.0f, -0.0247f, 0.8236f, 1.0f, -0.3576f, 0.0f, -0.0262f, 0.866f, 1.0f,
-0.3837f, 0.0f, -0.0231f, 0.9003f, 1.0f, -0.4085f, 0.0f, -0.0159f, 0.9272f, 1.0f,
-0.4317f, 0.0f, -0.0049f, 0.9485f, 1.0f, -0.4533f, 0.0f, 0.0099f, 0.9653f, 1.0f,
-0.4734f, 0.0f, 0.0289f, 0.9781f, 1.0f, -0.4916f, 0.0f, 0.0524f, 0.9876f, 1.0f,
-0.507f, 0.0f, 0.0806f, 0.9942f, 1.0f, -0.5185f, 0.0f, 0.1134f, 0.9983f, 1.0f,
-0.5247f, 0.0f, 0.1498f, 0.9997f, 1.0f, -0.5246f, 0.0f, 0.1884f, 0.999f, 1.0f,
-0.5175f, 0.0f, 0.2267f, 0.9963f, 1.0f, -0.5043f, 0.0f, 0.2616f, 0.9912f, 1.0f,
-0.4864f, 0.0f, 0.2916f, 0.9834f, 1.0f, -0.4653f, 0.0f, 0.3159f, 0.9724f, 1.0f,
-0.4422f, 0.0f, 0.3349f, 0.9576f, 1.0f, -0.4177f, 0.0f, 0.3489f, 0.9385f, 1.0f,
-0.3921f, 0.0f, 0.3582f, 0.9143f, 1.0f, -0.3661f, 0.0f, 0.3628f, 0.8841f, 1.0f,
-0.3392f, 0.0f, 0.363f, 0.8461f, 1.0f, -0.3123f, 0.0f, 0.3586f, 0.7979f, 1.0f,
-0.2853f, 0.0f, 0.3491f, 0.7359f, 1.0f, -0.2591f, 0.0f, 0.3344f, 0.6541f, 1.0f,
-0.2339f, 0.0f, 0.3137f, 0.5396f, 1.0f, -0.2118f, 0.0f, 0.2882f, 0.36f, 1.0f,
-0.1906f, 0.0f, 0.2516f, 0.1f, 1.0f,
};
/* ***************************************************************** */
/* Monkey Color Data */
static const ColorTemplate gp_monkey_pct_black = {
N_("Black"),
{0.0f, 0.0f, 0.0f, 1.0f},
{0.0f, 0.0f, 0.0f, 0.0f},
};
static const ColorTemplate gp_monkey_pct_skin = {
N_("Skin"),
{0.733f, 0.569f, 0.361f, 1.0f},
{0.745f, 0.502f, 0.278f, 1.0f},
};
static const ColorTemplate gp_monkey_pct_skin_light = {
N_("Skin_Light"),
{0.914f, 0.827f, 0.635f, 1.0f},
{0.913f, 0.828f, 0.637f, 0.0f},
};
static const ColorTemplate gp_monkey_pct_skin_shadow = {
N_("Skin_Shadow"),
{0.322f, 0.29f, 0.224f, 0.5f},
{0.32f, 0.29f, 0.223f, 0.3f},
};
static const ColorTemplate gp_monkey_pct_eyes = {
N_("Eyes"),
{0.553f, 0.39f, 0.266f, 0.0f},
{0.847f, 0.723f, 0.599f, 1.0f},
};
static const ColorTemplate gp_monkey_pct_pupils = {
N_("Pupils"),
{0.0f, 0.0f, 0.0f, 0.0f},
{0.0f, 0.0f, 0.0f, 1.0f},
};
/* ***************************************************************** */
/* Monkey API */
void ED_gpencil_create_monkey(bContext *C, Object *ob, float mat[4][4])
{
/* Original model created by Matias Mendiola. */
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
bGPdata *gpd = (bGPdata *)ob->data;
bGPDstroke *gps;
/* create colors */
int color_Black = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_black, true, false);
int color_Skin = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_skin, false, true);
int color_Skin_Light = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_skin_light, true, false);
int color_Skin_Shadow = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_skin_shadow, true, false);
int color_Eyes = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_eyes, false, true);
int color_Pupils = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_pupils, false, true);
/* set first color as active */
ob->actcol = color_Black + 1;
/* layers */
/* NOTE: For now, we just add new layers, to make it easier to separate out old/new instances */
bGPDlayer *Fills = BKE_gpencil_layer_addnew(gpd, "Fills", false, false);
bGPDlayer *Lines = BKE_gpencil_layer_addnew(gpd, "Lines", true, false);
/* frames */
/* NOTE: No need to check for existing, as this will take care of it for us */
bGPDframe *frameFills = BKE_gpencil_frame_addnew(Fills, scene->r.cfra);
bGPDframe *frameLines = BKE_gpencil_frame_addnew(Lines, scene->r.cfra);
/* generate strokes */
gps = BKE_gpencil_stroke_add(frameFills, color_Skin, 270, 75, false);
ED_gpencil_stroke_init_data(gps, data0, 270, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 33, 60, false);
ED_gpencil_stroke_init_data(gps, data1, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 60, false);
ED_gpencil_stroke_init_data(gps, data2, 18, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 64, 60, false);
ED_gpencil_stroke_init_data(gps, data3, 64, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 33, 60, false);
ED_gpencil_stroke_init_data(gps, data4, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 64, 60, false);
ED_gpencil_stroke_init_data(gps, data5, 64, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 33, 60, false);
ED_gpencil_stroke_init_data(gps, data6, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 18, 40, false);
ED_gpencil_stroke_init_data(gps, data7, 18, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Eyes, 49, 60, false);
ED_gpencil_stroke_init_data(gps, data8, 49, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 33, 60, false);
ED_gpencil_stroke_init_data(gps, data9, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Eyes, 49, 60, false);
ED_gpencil_stroke_init_data(gps, data10, 49, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 40, false);
ED_gpencil_stroke_init_data(gps, data11, 18, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 40, false);
ED_gpencil_stroke_init_data(gps, data12, 18, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
ED_gpencil_stroke_init_data(gps, data13, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
ED_gpencil_stroke_init_data(gps, data14, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 65, 60, false);
ED_gpencil_stroke_init_data(gps, data15, 65, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 34, 60, false);
ED_gpencil_stroke_init_data(gps, data16, 34, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
ED_gpencil_stroke_init_data(gps, data17, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 40, false);
ED_gpencil_stroke_init_data(gps, data18, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 34, 40, false);
ED_gpencil_stroke_init_data(gps, data19, 34, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
ED_gpencil_stroke_init_data(gps, data20, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 64, 60, false);
ED_gpencil_stroke_init_data(gps, data21, 64, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Pupils, 26, 60, false);
ED_gpencil_stroke_init_data(gps, data22, 26, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Pupils, 26, 60, false);
ED_gpencil_stroke_init_data(gps, data23, 26, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
ED_gpencil_stroke_init_data(gps, data24, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 18, 40, false);
ED_gpencil_stroke_init_data(gps, data25, 18, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 18, 40, false);
ED_gpencil_stroke_init_data(gps, data26, 18, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
ED_gpencil_stroke_init_data(gps, data27, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
/* update depsgraph */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
}
/* ***************************************************************** */

View File

@@ -1,230 +0,0 @@
/* SPDX-FileCopyrightText: 2017 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edgpencil
*/
#include "BLI_math_color.h"
#include "BLI_math_vector.h"
#include "BLI_utildefines.h"
#include "DNA_gpencil_legacy_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_context.hh"
#include "BKE_gpencil_geom_legacy.h"
#include "BKE_gpencil_legacy.h"
#include "BLT_translation.hh"
#include "DEG_depsgraph.hh"
#include "ED_gpencil_legacy.hh"
/* Definition of the most important info from a color */
struct ColorTemplate {
const char *name;
float line[4];
float fill[4];
};
/* Add color an ensure duplications (matched by name) */
static int gpencil_stroke_material(Main *bmain,
Object *ob,
const ColorTemplate *pct,
const bool fill)
{
int index;
Material *ma = BKE_gpencil_object_material_ensure_by_name(bmain, ob, DATA_(pct->name), &index);
copy_v4_v4(ma->gp_style->stroke_rgba, pct->line);
srgb_to_linearrgb_v4(ma->gp_style->stroke_rgba, ma->gp_style->stroke_rgba);
copy_v4_v4(ma->gp_style->fill_rgba, pct->fill);
srgb_to_linearrgb_v4(ma->gp_style->fill_rgba, ma->gp_style->fill_rgba);
if (fill) {
ma->gp_style->flag |= GP_MATERIAL_FILL_SHOW;
}
return index;
}
/* ***************************************************************** */
/* Stroke Geometry */
static const float data0[175 * GP_PRIM_DATABUF_SIZE] = {
-1.281f, 0.0f, -0.315f, 0.038f, 1.0f, -1.269f, 0.0f, -0.302f, 0.069f, 1.0f,
-1.261f, 0.0f, -0.293f, 0.089f, 1.0f, -1.251f, 0.0f, -0.282f, 0.112f, 1.0f,
-1.241f, 0.0f, -0.271f, 0.134f, 1.0f, -1.23f, 0.0f, -0.259f, 0.155f, 1.0f,
-1.219f, 0.0f, -0.247f, 0.175f, 1.0f, -1.208f, 0.0f, -0.234f, 0.194f, 1.0f,
-1.196f, 0.0f, -0.221f, 0.211f, 1.0f, -1.184f, 0.0f, -0.208f, 0.227f, 1.0f,
-1.172f, 0.0f, -0.194f, 0.242f, 1.0f, -1.159f, 0.0f, -0.18f, 0.256f, 1.0f,
-1.147f, 0.0f, -0.165f, 0.268f, 1.0f, -1.134f, 0.0f, -0.151f, 0.28f, 1.0f,
-1.121f, 0.0f, -0.136f, 0.29f, 1.0f, -1.108f, 0.0f, -0.121f, 0.299f, 1.0f,
-1.094f, 0.0f, -0.106f, 0.307f, 1.0f, -1.08f, 0.0f, -0.091f, 0.315f, 1.0f,
-1.066f, 0.0f, -0.076f, 0.322f, 1.0f, -1.052f, 0.0f, -0.061f, 0.329f, 1.0f,
-1.037f, 0.0f, -0.047f, 0.335f, 1.0f, -1.022f, 0.0f, -0.032f, 0.341f, 1.0f,
-1.007f, 0.0f, -0.017f, 0.346f, 1.0f, -0.991f, 0.0f, -0.003f, 0.351f, 1.0f,
-0.975f, 0.0f, 0.012f, 0.355f, 1.0f, -0.959f, 0.0f, 0.027f, 0.36f, 1.0f,
-0.942f, 0.0f, 0.041f, 0.364f, 1.0f, -0.926f, 0.0f, 0.056f, 0.368f, 1.0f,
-0.909f, 0.0f, 0.071f, 0.371f, 1.0f, -0.893f, 0.0f, 0.086f, 0.373f, 1.0f,
-0.876f, 0.0f, 0.1f, 0.376f, 1.0f, -0.859f, 0.0f, 0.115f, 0.377f, 1.0f,
-0.842f, 0.0f, 0.129f, 0.378f, 1.0f, -0.824f, 0.0f, 0.144f, 0.379f, 1.0f,
-0.807f, 0.0f, 0.158f, 0.379f, 1.0f, -0.79f, 0.0f, 0.172f, 0.379f, 1.0f,
-0.773f, 0.0f, 0.186f, 0.38f, 1.0f, -0.755f, 0.0f, 0.199f, 0.38f, 1.0f,
-0.738f, 0.0f, 0.212f, 0.381f, 1.0f, -0.721f, 0.0f, 0.224f, 0.382f, 1.0f,
-0.703f, 0.0f, 0.236f, 0.384f, 1.0f, -0.686f, 0.0f, 0.248f, 0.386f, 1.0f,
-0.67f, 0.0f, 0.26f, 0.388f, 1.0f, -0.653f, 0.0f, 0.27f, 0.39f, 1.0f,
-0.637f, 0.0f, 0.28f, 0.393f, 1.0f, -0.621f, 0.0f, 0.29f, 0.396f, 1.0f,
-0.605f, 0.0f, 0.298f, 0.399f, 1.0f, -0.589f, 0.0f, 0.306f, 0.403f, 1.0f,
-0.574f, 0.0f, 0.313f, 0.407f, 1.0f, -0.559f, 0.0f, 0.319f, 0.411f, 1.0f,
-0.544f, 0.0f, 0.325f, 0.415f, 1.0f, -0.53f, 0.0f, 0.331f, 0.42f, 1.0f,
-0.516f, 0.0f, 0.336f, 0.425f, 1.0f, -0.503f, 0.0f, 0.34f, 0.431f, 1.0f,
-0.489f, 0.0f, 0.344f, 0.437f, 1.0f, -0.477f, 0.0f, 0.347f, 0.443f, 1.0f,
-0.464f, 0.0f, 0.35f, 0.45f, 1.0f, -0.452f, 0.0f, 0.352f, 0.457f, 1.0f,
-0.44f, 0.0f, 0.354f, 0.464f, 1.0f, -0.429f, 0.0f, 0.355f, 0.471f, 1.0f,
-0.418f, 0.0f, 0.355f, 0.479f, 1.0f, -0.407f, 0.0f, 0.355f, 0.487f, 1.0f,
-0.397f, 0.0f, 0.354f, 0.495f, 1.0f, -0.387f, 0.0f, 0.353f, 0.503f, 1.0f,
-0.378f, 0.0f, 0.351f, 0.512f, 1.0f, -0.368f, 0.0f, 0.348f, 0.52f, 1.0f,
-0.36f, 0.0f, 0.344f, 0.528f, 1.0f, -0.351f, 0.0f, 0.34f, 0.537f, 1.0f,
-0.344f, 0.0f, 0.336f, 0.545f, 1.0f, -0.336f, 0.0f, 0.33f, 0.553f, 1.0f,
-0.329f, 0.0f, 0.324f, 0.562f, 1.0f, -0.322f, 0.0f, 0.318f, 0.57f, 1.0f,
-0.316f, 0.0f, 0.31f, 0.579f, 1.0f, -0.311f, 0.0f, 0.303f, 0.588f, 1.0f,
-0.306f, 0.0f, 0.294f, 0.597f, 1.0f, -0.301f, 0.0f, 0.285f, 0.606f, 1.0f,
-0.297f, 0.0f, 0.275f, 0.615f, 1.0f, -0.293f, 0.0f, 0.264f, 0.625f, 1.0f,
-0.29f, 0.0f, 0.253f, 0.635f, 1.0f, -0.288f, 0.0f, 0.241f, 0.644f, 1.0f,
-0.286f, 0.0f, 0.229f, 0.654f, 1.0f, -0.285f, 0.0f, 0.216f, 0.664f, 1.0f,
-0.284f, 0.0f, 0.202f, 0.675f, 1.0f, -0.283f, 0.0f, 0.188f, 0.685f, 1.0f,
-0.283f, 0.0f, 0.173f, 0.696f, 1.0f, -0.284f, 0.0f, 0.158f, 0.707f, 1.0f,
-0.285f, 0.0f, 0.142f, 0.718f, 1.0f, -0.286f, 0.0f, 0.125f, 0.729f, 1.0f,
-0.288f, 0.0f, 0.108f, 0.74f, 1.0f, -0.29f, 0.0f, 0.091f, 0.751f, 1.0f,
-0.293f, 0.0f, 0.073f, 0.761f, 1.0f, -0.295f, 0.0f, 0.054f, 0.772f, 1.0f,
-0.298f, 0.0f, 0.035f, 0.782f, 1.0f, -0.302f, 0.0f, 0.016f, 0.793f, 1.0f,
-0.305f, 0.0f, -0.004f, 0.804f, 1.0f, -0.309f, 0.0f, -0.024f, 0.815f, 1.0f,
-0.313f, 0.0f, -0.044f, 0.828f, 1.0f, -0.317f, 0.0f, -0.065f, 0.843f, 1.0f,
-0.321f, 0.0f, -0.085f, 0.86f, 1.0f, -0.326f, 0.0f, -0.106f, 0.879f, 1.0f,
-0.33f, 0.0f, -0.127f, 0.897f, 1.0f, -0.335f, 0.0f, -0.148f, 0.915f, 1.0f,
-0.339f, 0.0f, -0.168f, 0.932f, 1.0f, -0.344f, 0.0f, -0.189f, 0.947f, 1.0f,
-0.348f, 0.0f, -0.21f, 0.962f, 1.0f, -0.353f, 0.0f, -0.23f, 0.974f, 1.0f,
-0.357f, 0.0f, -0.25f, 0.985f, 1.0f, -0.361f, 0.0f, -0.27f, 0.995f, 1.0f,
-0.365f, 0.0f, -0.29f, 1.004f, 1.0f, -0.369f, 0.0f, -0.309f, 1.011f, 1.0f,
-0.372f, 0.0f, -0.328f, 1.018f, 1.0f, -0.375f, 0.0f, -0.347f, 1.024f, 1.0f,
-0.377f, 0.0f, -0.365f, 1.029f, 1.0f, -0.379f, 0.0f, -0.383f, 1.033f, 1.0f,
-0.38f, 0.0f, -0.4f, 1.036f, 1.0f, -0.38f, 0.0f, -0.417f, 1.037f, 1.0f,
-0.38f, 0.0f, -0.434f, 1.037f, 1.0f, -0.379f, 0.0f, -0.449f, 1.035f, 1.0f,
-0.377f, 0.0f, -0.464f, 1.032f, 1.0f, -0.374f, 0.0f, -0.478f, 1.029f, 1.0f,
-0.371f, 0.0f, -0.491f, 1.026f, 1.0f, -0.366f, 0.0f, -0.503f, 1.023f, 1.0f,
-0.361f, 0.0f, -0.513f, 1.021f, 1.0f, -0.354f, 0.0f, -0.523f, 1.019f, 1.0f,
-0.347f, 0.0f, -0.531f, 1.017f, 1.0f, -0.339f, 0.0f, -0.538f, 1.016f, 1.0f,
-0.33f, 0.0f, -0.543f, 1.016f, 1.0f, -0.32f, 0.0f, -0.547f, 1.016f, 1.0f,
-0.31f, 0.0f, -0.549f, 1.016f, 1.0f, -0.298f, 0.0f, -0.55f, 1.017f, 1.0f,
-0.286f, 0.0f, -0.55f, 1.017f, 1.0f, -0.274f, 0.0f, -0.548f, 1.018f, 1.0f,
-0.261f, 0.0f, -0.544f, 1.017f, 1.0f, -0.247f, 0.0f, -0.539f, 1.017f, 1.0f,
-0.232f, 0.0f, -0.533f, 1.016f, 1.0f, -0.218f, 0.0f, -0.525f, 1.015f, 1.0f,
-0.202f, 0.0f, -0.515f, 1.013f, 1.0f, -0.186f, 0.0f, -0.503f, 1.009f, 1.0f,
-0.169f, 0.0f, -0.49f, 1.005f, 1.0f, -0.151f, 0.0f, -0.475f, 0.998f, 1.0f,
-0.132f, 0.0f, -0.458f, 0.99f, 1.0f, -0.112f, 0.0f, -0.44f, 0.98f, 1.0f,
-0.091f, 0.0f, -0.42f, 0.968f, 1.0f, -0.069f, 0.0f, -0.398f, 0.955f, 1.0f,
-0.045f, 0.0f, -0.375f, 0.939f, 1.0f, -0.021f, 0.0f, -0.35f, 0.923f, 1.0f,
0.005f, 0.0f, -0.324f, 0.908f, 1.0f, 0.031f, 0.0f, -0.297f, 0.895f, 1.0f,
0.06f, 0.0f, -0.268f, 0.882f, 1.0f, 0.089f, 0.0f, -0.238f, 0.87f, 1.0f,
0.12f, 0.0f, -0.207f, 0.858f, 1.0f, 0.153f, 0.0f, -0.175f, 0.844f, 1.0f,
0.187f, 0.0f, -0.14f, 0.828f, 1.0f, 0.224f, 0.0f, -0.104f, 0.81f, 1.0f,
0.262f, 0.0f, -0.067f, 0.79f, 1.0f, 0.302f, 0.0f, -0.027f, 0.769f, 1.0f,
0.344f, 0.0f, 0.014f, 0.747f, 1.0f, 0.388f, 0.0f, 0.056f, 0.724f, 1.0f,
0.434f, 0.0f, 0.1f, 0.7f, 1.0f, 0.483f, 0.0f, 0.145f, 0.676f, 1.0f,
0.533f, 0.0f, 0.191f, 0.651f, 1.0f, 0.585f, 0.0f, 0.238f, 0.625f, 1.0f,
0.637f, 0.0f, 0.284f, 0.599f, 1.0f, 0.69f, 0.0f, 0.33f, 0.573f, 1.0f,
0.746f, 0.0f, 0.376f, 0.546f, 1.0f, 0.802f, 0.0f, 0.421f, 0.516f, 1.0f,
0.859f, 0.0f, 0.464f, 0.483f, 1.0f, 0.915f, 0.0f, 0.506f, 0.446f, 1.0f,
0.97f, 0.0f, 0.545f, 0.407f, 1.0f, 1.023f, 0.0f, 0.581f, 0.365f, 1.0f,
1.075f, 0.0f, 0.614f, 0.322f, 1.0f, 1.122f, 0.0f, 0.643f, 0.28f, 1.0f,
1.169f, 0.0f, 0.671f, 0.236f, 1.0f, 1.207f, 0.0f, 0.693f, 0.202f, 1.0f,
1.264f, 0.0f, 0.725f, 0.155f, 1.0f,
};
/* ***************************************************************** */
/* Color Data */
static const ColorTemplate gp_stroke_material_black = {
N_("Black"),
{0.0f, 0.0f, 0.0f, 1.0f},
{0.0f, 0.0f, 0.0f, 0.0f},
};
static const ColorTemplate gp_stroke_material_white = {
N_("White"),
{1.0f, 1.0f, 1.0f, 1.0f},
{0.0f, 0.0f, 0.0f, 0.0f},
};
static const ColorTemplate gp_stroke_material_red = {
N_("Red"),
{1.0f, 0.0f, 0.0f, 1.0f},
{0.0f, 0.0f, 0.0f, 0.0f},
};
static const ColorTemplate gp_stroke_material_green = {
N_("Green"),
{0.0f, 1.0f, 0.0f, 1.0f},
{0.0f, 0.0f, 0.0f, 0.0f},
};
static const ColorTemplate gp_stroke_material_blue = {
N_("Blue"),
{0.0f, 0.0f, 1.0f, 1.0f},
{0.0f, 0.0f, 0.0f, 0.0f},
};
static const ColorTemplate gp_stroke_material_grey = {
N_("Grey"),
{0.358f, 0.358f, 0.358f, 1.0f},
{0.5f, 0.5f, 0.5f, 1.0f},
};
/* ***************************************************************** */
/* Stroke API */
void ED_gpencil_create_stroke(bContext *C, Object *ob, float mat[4][4])
{
/* Original design created by Daniel M. Lara and Matias Mendiola. */
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
bGPdata *gpd = (bGPdata *)ob->data;
bGPDstroke *gps;
/* create colors */
int color_black = gpencil_stroke_material(bmain, ob, &gp_stroke_material_black, false);
gpencil_stroke_material(bmain, ob, &gp_stroke_material_white, false);
gpencil_stroke_material(bmain, ob, &gp_stroke_material_red, false);
gpencil_stroke_material(bmain, ob, &gp_stroke_material_green, false);
gpencil_stroke_material(bmain, ob, &gp_stroke_material_blue, false);
gpencil_stroke_material(bmain, ob, &gp_stroke_material_grey, true);
/* set first color as active and in brushes */
ob->actcol = color_black + 1;
/* layers */
bGPDlayer *colors = BKE_gpencil_layer_addnew(gpd, "Colors", false, false);
bGPDlayer *lines = BKE_gpencil_layer_addnew(gpd, "Lines", true, false);
/* frames */
bGPDframe *frame_color = BKE_gpencil_frame_addnew(colors, scene->r.cfra);
bGPDframe *frame_lines = BKE_gpencil_frame_addnew(lines, scene->r.cfra);
UNUSED_VARS(frame_color);
/* generate stroke */
gps = BKE_gpencil_stroke_add(frame_lines, color_black, 175, 75, false);
ED_gpencil_stroke_init_data(gps, data0, 175, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
/* update depsgraph */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
}

View File

@@ -1,501 +0,0 @@
/* SPDX-FileCopyrightText: 2018 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edgpencil
*
* Operators for dealing with armatures and GP data-blocks.
*/
#include <cmath>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "MEM_guardedalloc.h"
#include "BLI_math_geom.h"
#include "BLI_math_matrix.h"
#include "BLI_math_vector.h"
#include "BLI_utildefines.h"
#include "DNA_armature_types.h"
#include "DNA_gpencil_legacy_types.h"
#include "DNA_meshdata_types.h"
#include "BKE_action.hh"
#include "BKE_armature.hh"
#include "BKE_context.hh"
#include "BKE_deform.hh"
#include "BKE_gpencil_legacy.h"
#include "BKE_layer.hh"
#include "BKE_object_deform.h"
#include "BKE_report.hh"
#include "WM_api.hh"
#include "WM_types.hh"
#include "RNA_access.hh"
#include "RNA_define.hh"
#include "RNA_enum_types.hh"
#include "ED_gpencil_legacy.hh"
#include "ED_mesh.hh"
#include "ED_object.hh"
#include "ED_object_vgroup.hh"
#include "ANIM_bone_collections.hh"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_query.hh"
#include "gpencil_intern.hh"
enum {
GP_ARMATURE_NAME = 0,
GP_ARMATURE_AUTO = 1,
};
#define DEFAULT_RATIO 0.10f
#define DEFAULT_DECAY 0.8f
static int gpencil_bone_looper(Object *ob,
Bone *bone,
void *data,
int (*bone_func)(Object *, Bone *, void *))
{
/* We want to apply the function bone_func to every bone
* in an armature -- feed bone_looper the first bone and
* a pointer to the bone_func and watch it go! The int count
* can be useful for counting bones with a certain property
* (e.g. skinnable)
*/
int count = 0;
if (bone) {
/* only do bone_func if the bone is non null */
count += bone_func(ob, bone, data);
/* try to execute bone_func for the first child */
count += gpencil_bone_looper(ob, static_cast<Bone *>(bone->childbase.first), data, bone_func);
/* try to execute bone_func for the next bone at this
* depth of the recursion.
*/
count += gpencil_bone_looper(ob, bone->next, data, bone_func);
}
return count;
}
static int gpencil_bone_skinnable_cb(Object * /*ob*/, Bone *bone, void *datap)
{
/* Bones that are deforming
* are regarded to be "skinnable" and are eligible for
* auto-skinning.
*
* This function performs 2 functions:
*
* a) It returns 1 if the bone is skinnable.
* If we loop over all bones with this
* function, we can count the number of
* skinnable bones.
* b) If the pointer data is non null,
* it is treated like a handle to a
* bone pointer -- the bone pointer
* is set to point at this bone, and
* the pointer the handle points to
* is incremented to point to the
* next member of an array of pointers
* to bones. This way we can loop using
* this function to construct an array of
* pointers to bones that point to all
* skinnable bones.
*/
Bone ***hbone;
int a, segments;
struct Data {
Object *armob;
void *list;
int heat;
} *data = static_cast<Data *>(datap);
if (!(bone->flag & BONE_HIDDEN_P)) {
if (!(bone->flag & BONE_NO_DEFORM)) {
if (data->heat && data->armob->pose &&
BKE_pose_channel_find_name(data->armob->pose, bone->name))
{
segments = bone->segments;
}
else {
segments = 1;
}
if (data->list != nullptr) {
hbone = (Bone ***)&data->list;
for (a = 0; a < segments; a++) {
**hbone = bone;
(*hbone)++;
}
}
return segments;
}
}
return 0;
}
static int vgroup_add_unique_bone_cb(Object *ob, Bone *bone, void * /*ptr*/)
{
/* This group creates a vertex group to ob that has the
* same name as bone (provided the bone is skinnable).
* If such a vertex group already exist the routine exits.
*/
if (!(bone->flag & BONE_NO_DEFORM)) {
if (!BKE_object_defgroup_find_name(ob, bone->name)) {
BKE_object_defgroup_add_name(ob, bone->name);
return 1;
}
}
return 0;
}
static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
{
/* Bones that are deforming
* are regarded to be "skinnable" and are eligible for
* auto-skinning.
*
* This function performs 2 functions:
*
* a) If the bone is skinnable, it creates
* a vertex group for ob that has
* the name of the skinnable bone
* (if one doesn't exist already).
* b) If the pointer data is non null,
* it is treated like a handle to a
* bDeformGroup pointer -- the
* bDeformGroup pointer is set to point
* to the deform group with the bone's
* name, and the pointer the handle
* points to is incremented to point to the
* next member of an array of pointers
* to bDeformGroups. This way we can loop using
* this function to construct an array of
* pointers to bDeformGroups, all with names
* of skinnable bones.
*/
bDeformGroup ***hgroup, *defgroup = nullptr;
int a, segments;
struct Data {
Object *armob;
void *list;
int heat;
} *data = static_cast<Data *>(datap);
bArmature *arm = static_cast<bArmature *>(data->armob->data);
if (!(bone->flag & BONE_HIDDEN_P)) {
if (!(bone->flag & BONE_NO_DEFORM)) {
if (data->heat && data->armob->pose &&
BKE_pose_channel_find_name(data->armob->pose, bone->name))
{
segments = bone->segments;
}
else {
segments = 1;
}
if (ANIM_bone_in_visible_collection(arm, bone)) {
if (!(defgroup = BKE_object_defgroup_find_name(ob, bone->name))) {
defgroup = BKE_object_defgroup_add_name(ob, bone->name);
}
else if (defgroup->flag & DG_LOCK_WEIGHT) {
/* In case vgroup already exists and is locked, do not modify it here. See #43814. */
defgroup = nullptr;
}
}
if (data->list != nullptr) {
hgroup = (bDeformGroup ***)&data->list;
for (a = 0; a < segments; a++) {
**hgroup = defgroup;
(*hgroup)++;
}
}
return segments;
}
}
return 0;
}
/* get weight value depending of distance and decay value */
static float get_weight(float dist, float decay_rad, float dif_rad)
{
float weight = 1.0f;
if (dist < decay_rad) {
weight = 1.0f;
}
else {
weight = interpf(0.0f, 0.9f, (dist - decay_rad) / dif_rad);
}
return weight;
}
/* This functions implements the automatic computation of vertex group weights */
static void gpencil_add_verts_to_dgroups(
const bContext *C, Object *ob, Object *ob_arm, const float ratio, const float decay)
{
bArmature *arm = static_cast<bArmature *>(ob_arm->data);
Bone **bonelist, *bone;
bDeformGroup **dgrouplist;
bPoseChannel *pchan;
bGPdata *gpd = (bGPdata *)ob->data;
const bool is_multiedit = bool(GPENCIL_MULTIEDIT_SESSIONS_ON(gpd));
Mat4 bbone_array[MAX_BBONE_SUBDIV], *bbone = nullptr;
float(*root)[3], (*tip)[3], (*verts)[3];
float *radsqr;
bool *selected;
float weight;
int numbones, i, j, segments = 0;
struct {
Object *armob;
void *list;
int heat;
} looper_data;
looper_data.armob = ob_arm;
looper_data.heat = true;
looper_data.list = nullptr;
/* count the number of skinnable bones */
numbones = gpencil_bone_looper(
ob, static_cast<Bone *>(arm->bonebase.first), &looper_data, gpencil_bone_skinnable_cb);
if (numbones == 0) {
return;
}
/* create an array of pointer to bones that are skinnable
* and fill it with all of the skinnable bones */
bonelist = static_cast<Bone **>(MEM_callocN(numbones * sizeof(Bone *), "bonelist"));
looper_data.list = bonelist;
gpencil_bone_looper(
ob, static_cast<Bone *>(arm->bonebase.first), &looper_data, gpencil_bone_skinnable_cb);
/* create an array of pointers to the deform groups that
* correspond to the skinnable bones (creating them
* as necessary. */
dgrouplist = static_cast<bDeformGroup **>(
MEM_callocN(numbones * sizeof(bDeformGroup *), "dgrouplist"));
looper_data.list = dgrouplist;
gpencil_bone_looper(
ob, static_cast<Bone *>(arm->bonebase.first), &looper_data, dgroup_skinnable_cb);
/* create an array of root and tip positions transformed into
* global coords */
root = static_cast<float(*)[3]>(MEM_callocN(sizeof(float[3]) * numbones, "root"));
tip = static_cast<float(*)[3]>(MEM_callocN(sizeof(float[3]) * numbones, "tip"));
selected = static_cast<bool *>(MEM_callocN(sizeof(bool) * numbones, "selected"));
radsqr = static_cast<float *>(MEM_callocN(sizeof(float) * numbones, "radsqr"));
for (j = 0; j < numbones; j++) {
bone = bonelist[j];
/* handle bbone */
if (segments == 0) {
segments = 1;
bbone = nullptr;
if ((ob_arm->pose) && (pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name))) {
if (bone->segments > 1) {
segments = bone->segments;
BKE_pchan_bbone_spline_setup(pchan, true, false, bbone_array);
bbone = bbone_array;
}
}
}
segments--;
/* compute root and tip */
if (bbone) {
mul_v3_m4v3(root[j], bone->arm_mat, bbone[segments].mat[3]);
if ((segments + 1) < bone->segments) {
mul_v3_m4v3(tip[j], bone->arm_mat, bbone[segments + 1].mat[3]);
}
else {
copy_v3_v3(tip[j], bone->arm_tail);
}
}
else {
copy_v3_v3(root[j], bone->arm_head);
copy_v3_v3(tip[j], bone->arm_tail);
}
mul_m4_v3(ob_arm->object_to_world().ptr(), root[j]);
mul_m4_v3(ob_arm->object_to_world().ptr(), tip[j]);
selected[j] = true;
/* calculate radius squared */
radsqr[j] = len_squared_v3v3(root[j], tip[j]) * ratio;
}
/* loop all strokes */
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
bGPDframe *init_gpf = static_cast<bGPDframe *>((is_multiedit) ? gpl->frames.first :
gpl->actframe);
bGPDspoint *pt = nullptr;
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
if (gpf == nullptr) {
continue;
}
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
}
BKE_gpencil_dvert_ensure(gps);
/* create verts array */
verts = static_cast<float(*)[3]>(MEM_callocN(gps->totpoints * sizeof(*verts), __func__));
/* transform stroke points to global space */
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
copy_v3_v3(verts[i], &pt->x);
mul_m4_v3(ob->object_to_world().ptr(), verts[i]);
}
/* loop groups and assign weight */
for (j = 0; j < numbones; j++) {
int def_nr = BLI_findindex(&gpd->vertex_group_names, dgrouplist[j]);
if (def_nr < 0) {
continue;
}
float decay_rad = radsqr[j] - (radsqr[j] * decay);
float dif_rad = radsqr[j] - decay_rad;
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
MDeformVert *dvert = &gps->dvert[i];
float dist = dist_squared_to_line_segment_v3(verts[i], root[j], tip[j]);
if (dist > radsqr[j]) {
/* if not in cylinder, check if inside extreme spheres */
weight = 0.0f;
dist = len_squared_v3v3(root[j], verts[i]);
if (dist < radsqr[j]) {
weight = get_weight(dist, decay_rad, dif_rad);
}
else {
dist = len_squared_v3v3(tip[j], verts[i]);
if (dist < radsqr[j]) {
weight = get_weight(dist, decay_rad, dif_rad);
}
}
}
else {
/* inside bone cylinder */
weight = get_weight(dist, decay_rad, dif_rad);
}
/* assign weight */
MDeformWeight *dw = BKE_defvert_ensure_index(dvert, def_nr);
if (dw) {
dw->weight = weight;
}
}
}
MEM_SAFE_FREE(verts);
}
}
/* If not multi-edit, exit loop. */
if (!is_multiedit) {
break;
}
}
}
/* free the memory allocated */
MEM_SAFE_FREE(bonelist);
MEM_SAFE_FREE(dgrouplist);
MEM_SAFE_FREE(root);
MEM_SAFE_FREE(tip);
MEM_SAFE_FREE(radsqr);
MEM_SAFE_FREE(selected);
}
static void gpencil_object_vgroup_calc_from_armature(const bContext *C,
Object *ob,
Object *ob_arm,
const int mode,
const float ratio,
const float decay)
{
/* Lets try to create some vertex groups
* based on the bones of the parent armature.
*/
bArmature *arm = static_cast<bArmature *>(ob_arm->data);
/* always create groups */
const int defbase_tot = BKE_object_defgroup_count(ob);
int defbase_add;
/* Traverse the bone list, trying to create empty vertex
* groups corresponding to the bone.
*/
defbase_add = gpencil_bone_looper(
ob, static_cast<Bone *>(arm->bonebase.first), nullptr, vgroup_add_unique_bone_cb);
if (defbase_add) {
/* It's possible there are DWeights outside the range of the current
* object's deform groups. In this case the new groups won't be empty */
blender::ed::object::vgroup_data_clamp_range(static_cast<ID *>(ob->data), defbase_tot);
}
if (mode == GP_ARMATURE_AUTO) {
/* Traverse the bone list, trying to fill vertex groups
* with the corresponding vertex weights for which the
* bone is closest.
*/
gpencil_add_verts_to_dgroups(C, ob, ob_arm, ratio, decay);
}
DEG_relations_tag_update(CTX_data_main(C));
}
bool ED_gpencil_add_armature(const bContext * /*C*/,
ReportList * /*reports*/,
Object * /*ob*/,
Object * /*ob_arm*/)
{
/* pass */
return true;
}
bool ED_gpencil_add_armature_weights(
const bContext *C, ReportList *reports, Object *ob, Object *ob_arm, int mode)
{
if (ob == nullptr) {
return false;
}
bool success = ED_gpencil_add_armature(C, reports, ob, ob_arm);
/* add weights */
if (success) {
gpencil_object_vgroup_calc_from_armature(C, ob, ob_arm, mode, DEFAULT_RATIO, DEFAULT_DECAY);
}
return success;
}

View File

@@ -399,278 +399,3 @@ void GPENCIL_OT_layer_annotation_move(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", ""); ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
} }
/****************************** Join ***********************************/
/**
* Callback to pass to #BKE_fcurves_main_cb()
* for RNA Paths attached to each F-Curve used in the #AnimData.
*/
static void gpencil_joined_fix_animdata_cb(
ID *id, FCurve *fcu, bGPdata *src_gpd, bGPdata *tar_gpd, GHash *names_map)
{
ID *src_id = &src_gpd->id;
ID *dst_id = &tar_gpd->id;
GHashIterator gh_iter;
/* Fix paths - If this is the target datablock, it will have some "dirty" paths */
if ((id == src_id) && fcu->rna_path && strstr(fcu->rna_path, "layers[")) {
GHASH_ITER (gh_iter, names_map) {
const char *old_name = static_cast<const char *>(BLI_ghashIterator_getKey(&gh_iter));
const char *new_name = static_cast<const char *>(BLI_ghashIterator_getValue(&gh_iter));
/* only remap if changed;
* this still means there will be some waste if there aren't many drivers/keys */
if (!STREQ(old_name, new_name) && strstr(fcu->rna_path, old_name)) {
fcu->rna_path = BKE_animsys_fix_rna_path_rename(
id, fcu->rna_path, "layers", old_name, new_name, 0, 0, false);
/* We don't want to apply a second remapping on this F-Curve now,
* so stop trying to fix names. */
break;
}
}
}
/* Fix driver targets */
if (fcu->driver) {
/* Fix driver references to invalid ID's */
LISTBASE_FOREACH (DriverVar *, dvar, &fcu->driver->variables) {
/* Only change the used targets, since the others will need fixing manually anyway. */
DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
/* Change the ID's used. */
if (dtar->id == src_id) {
dtar->id = dst_id;
/* Also check on the sub-target.
* We duplicate the logic from #drivers_path_rename_fix() here, with our own
* little twists so that we know that it isn't going to clobber the wrong data
*/
if (dtar->rna_path && strstr(dtar->rna_path, "layers[")) {
GHASH_ITER (gh_iter, names_map) {
const char *old_name = static_cast<const char *>(BLI_ghashIterator_getKey(&gh_iter));
const char *new_name = static_cast<const char *>(
BLI_ghashIterator_getValue(&gh_iter));
/* Only remap if changed. */
if (!STREQ(old_name, new_name)) {
if ((dtar->rna_path) && strstr(dtar->rna_path, old_name)) {
/* Fix up path */
dtar->rna_path = BKE_animsys_fix_rna_path_rename(
id, dtar->rna_path, "layers", old_name, new_name, 0, 0, false);
break; /* no need to try any more names for layer path */
}
}
}
}
}
}
DRIVER_TARGETS_LOOPER_END;
}
}
}
int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Object *ob_active = CTX_data_active_object(C);
bool ok = false;
/* Ensure we're in right mode and that the active object is correct */
if (!ob_active || ob_active->type != OB_GPENCIL_LEGACY) {
return OPERATOR_CANCELLED;
}
bGPdata *gpd = (bGPdata *)ob_active->data;
if ((!gpd) || GPENCIL_ANY_MODE(gpd)) {
return OPERATOR_CANCELLED;
}
/* Ensure all rotations are applied before */
CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
if (ob_iter->type == OB_GPENCIL_LEGACY) {
if ((ob_iter->rot[0] != 0) || (ob_iter->rot[1] != 0) || (ob_iter->rot[2] != 0)) {
BKE_report(op->reports, RPT_ERROR, "Apply all rotations before join objects");
return OPERATOR_CANCELLED;
}
}
}
CTX_DATA_END;
CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
if (ob_iter == ob_active) {
ok = true;
break;
}
}
CTX_DATA_END;
/* that way the active object is always selected */
if (ok == false) {
BKE_report(op->reports, RPT_WARNING, "Active object is not a selected grease pencil");
return OPERATOR_CANCELLED;
}
bGPdata *gpd_dst = static_cast<bGPdata *>(ob_active->data);
Object *ob_dst = ob_active;
/* loop and join all data */
CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
if ((ob_iter->type == OB_GPENCIL_LEGACY) && (ob_iter != ob_active)) {
/* we assume that each datablock is not already used in active object */
if (ob_active->data != ob_iter->data) {
Object *ob_src = ob_iter;
bGPdata *gpd_src = static_cast<bGPdata *>(ob_iter->data);
/* copy vertex groups to the base one's */
int old_idx = 0;
LISTBASE_FOREACH (bDeformGroup *, dg, &gpd_src->vertex_group_names) {
bDeformGroup *vgroup = static_cast<bDeformGroup *>(MEM_dupallocN(dg));
int idx = BLI_listbase_count(&gpd_dst->vertex_group_names);
BKE_object_defgroup_unique_name(vgroup, ob_active);
BLI_addtail(&gpd_dst->vertex_group_names, vgroup);
/* update vertex groups in strokes in original data */
LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd->layers) {
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl_src->frames) {
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
MDeformVert *dvert;
int i;
if (gps->dvert == nullptr) {
continue;
}
for (i = 0, dvert = gps->dvert; i < gps->totpoints; i++, dvert++) {
if ((dvert->dw != nullptr) && (dvert->dw->def_nr == old_idx)) {
dvert->dw->def_nr = idx;
}
}
}
}
}
old_idx++;
}
if (!BLI_listbase_is_empty(&gpd_dst->vertex_group_names) &&
gpd_dst->vertex_group_active_index == 0)
{
gpd_dst->vertex_group_active_index = 1;
}
/* add missing materials reading source materials and checking in destination object */
short *totcol = BKE_object_material_len_p(ob_src);
for (short i = 0; i < *totcol; i++) {
Material *tmp_ma = BKE_gpencil_material(ob_src, i + 1);
BKE_gpencil_object_material_ensure(bmain, ob_dst, tmp_ma);
}
/* Duplicate #bGPDlayers. */
GHash *names_map = BLI_ghash_str_new("joined_gp_layers_map");
float imat[3][3], bmat[3][3];
float offset_global[3];
float offset_local[3];
sub_v3_v3v3(offset_global, ob_active->loc, ob_iter->object_to_world().location());
copy_m3_m4(bmat, ob_active->object_to_world().ptr());
/* Inverse transform for all selected curves in this object,
* See #object_join_exec for detailed comment on why the safe version is used. */
invert_m3_m3_safe_ortho(imat, bmat);
mul_m3_v3(imat, offset_global);
mul_v3_m3v3(offset_local, imat, offset_global);
LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd_src->layers) {
bGPDlayer *gpl_new = BKE_gpencil_layer_duplicate(gpl_src, true, true);
float diff_mat[4][4];
float inverse_diff_mat[4][4];
/* recalculate all stroke points */
BKE_gpencil_layer_transform_matrix_get(depsgraph, ob_iter, gpl_src, diff_mat);
invert_m4_m4_safe_ortho(inverse_diff_mat, diff_mat);
Material *ma_src = nullptr;
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl_new->frames) {
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* Reassign material. Look old material and try to find in destination. */
ma_src = BKE_gpencil_material(ob_src, gps->mat_nr + 1);
gps->mat_nr = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma_src);
bGPDspoint *pt;
int i;
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
float mpt[3];
mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x);
sub_v3_v3(mpt, offset_local);
mul_v3_m4v3(&pt->x, diff_mat, mpt);
}
}
}
/* be sure name is unique in new object */
BLI_uniquename(&gpd_dst->layers,
gpl_new,
DATA_("GP_Layer"),
'.',
offsetof(bGPDlayer, info),
sizeof(gpl_new->info));
BLI_ghash_insert(names_map, BLI_strdup(gpl_src->info), gpl_new->info);
/* add to destination datablock */
BLI_addtail(&gpd_dst->layers, gpl_new);
}
/* Fix all the animation data */
BKE_fcurves_main_cb(bmain, [&](ID *id, FCurve *fcu) {
gpencil_joined_fix_animdata_cb(id, fcu, gpd_src, gpd_dst, names_map);
});
BLI_ghash_free(names_map, MEM_freeN, nullptr);
/* Only copy over animdata now, after all the remapping has been done,
* so that we don't have to worry about ambiguities re which datablock
* a layer came from!
*/
if (ob_iter->adt) {
if (ob_active->adt == nullptr) {
/* no animdata, so just use a copy of the whole thing */
ob_active->adt = BKE_animdata_copy(bmain, ob_iter->adt, 0);
}
else {
/* merge in data - we'll fix the drivers manually */
BKE_animdata_merge_copy(
bmain, &ob_active->id, &ob_iter->id, ADT_MERGECOPY_KEEP_DST, false);
}
}
if (gpd_src->adt) {
if (gpd_dst->adt == nullptr) {
/* no animdata, so just use a copy of the whole thing */
gpd_dst->adt = BKE_animdata_copy(bmain, gpd_src->adt, 0);
}
else {
/* merge in data - we'll fix the drivers manually */
BKE_animdata_merge_copy(
bmain, &gpd_dst->id, &gpd_src->id, ADT_MERGECOPY_KEEP_DST, false);
}
}
DEG_id_tag_update(&gpd_src->id,
ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_SYNC_TO_EVAL);
}
/* Free the old object */
blender::ed::object::base_free_and_unlink(bmain, scene, ob_iter);
}
}
CTX_DATA_END;
DEG_id_tag_update(&gpd_dst->id,
ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_SYNC_TO_EVAL);
DEG_relations_tag_update(bmain); /* because we removed object(s) */
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
return OPERATOR_FINISHED;
}

View File

@@ -98,25 +98,6 @@ ListBase gpencil_strokes_copypastebuf = {nullptr, nullptr};
*/ */
static GHash *gpencil_strokes_copypastebuf_colors = nullptr; static GHash *gpencil_strokes_copypastebuf_colors = nullptr;
static GHash *gpencil_strokes_copypastebuf_colors_name_to_material_create(Main *bmain)
{
GHash *name_to_ma = BLI_ghash_str_new(__func__);
for (Material *ma = static_cast<Material *>(bmain->materials.first); ma != nullptr;
ma = static_cast<Material *>(ma->id.next))
{
char *name = BKE_id_to_unique_string_key(&ma->id);
BLI_ghash_insert(name_to_ma, name, ma);
}
return name_to_ma;
}
static void gpencil_strokes_copypastebuf_colors_name_to_material_free(GHash *name_to_ma)
{
BLI_ghash_free(name_to_ma, MEM_freeN, nullptr);
}
void ED_gpencil_strokes_copybuf_free() void ED_gpencil_strokes_copybuf_free()
{ {
bGPDstroke *gps, *gpsn; bGPDstroke *gps, *gpsn;
@@ -148,115 +129,6 @@ void ED_gpencil_strokes_copybuf_free()
gpencil_strokes_copypastebuf.first = gpencil_strokes_copypastebuf.last = nullptr; gpencil_strokes_copypastebuf.first = gpencil_strokes_copypastebuf.last = nullptr;
} }
GHash *gpencil_copybuf_validate_colormap(bContext *C)
{
Main *bmain = CTX_data_main(C);
Object *ob = CTX_data_active_object(C);
GHash *new_colors = BLI_ghash_int_new("GPencil Paste Dst Colors");
GHashIterator gh_iter;
/* For each color, check if exist and add if not */
GHash *name_to_ma = gpencil_strokes_copypastebuf_colors_name_to_material_create(bmain);
GHASH_ITER (gh_iter, gpencil_strokes_copypastebuf_colors) {
int *key = static_cast<int *>(BLI_ghashIterator_getKey(&gh_iter));
const char *ma_name = static_cast<const char *>(BLI_ghashIterator_getValue(&gh_iter));
Material *ma = static_cast<Material *>(BLI_ghash_lookup(name_to_ma, ma_name));
BKE_gpencil_object_material_ensure(bmain, ob, ma);
/* Store this mapping (for use later when pasting) */
if (!BLI_ghash_haskey(new_colors, POINTER_FROM_INT(*key))) {
BLI_ghash_insert(new_colors, POINTER_FROM_INT(*key), ma);
}
}
gpencil_strokes_copypastebuf_colors_name_to_material_free(name_to_ma);
return new_colors;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Add Blank Frame Operator
* \{ */
static int gpencil_blank_frame_add_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
Scene *scene = CTX_data_scene(C);
int cfra = scene->r.cfra;
bGPDlayer *active_gpl = BKE_gpencil_layer_active_get(gpd);
const bool all_layers = RNA_boolean_get(op->ptr, "all_layers");
/* Initialize data-block and an active layer if nothing exists yet. */
if (ELEM(nullptr, gpd, active_gpl)) {
/* Let's just be lazy, and call the "Add New Layer" operator,
* which sets everything up as required. */
WM_operator_name_call(
C, "GPENCIL_OT_layer_annotation_add", WM_OP_EXEC_DEFAULT, nullptr, nullptr);
}
/* Go through each layer, adding a frame after the active one
* and/or shunting all the others out of the way
*/
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
if ((all_layers == false) && (gpl != active_gpl)) {
continue;
}
/* 1) Check for an existing frame on the current frame */
bGPDframe *gpf = BKE_gpencil_layer_frame_find(gpl, cfra);
if (gpf) {
/* Shunt all frames after (and including) the existing one later by 1-frame */
for (; gpf; gpf = gpf->next) {
gpf->framenum += 1;
}
}
/* 2) Now add a new frame, with nothing in it */
gpl->actframe = BKE_gpencil_layer_frame_get(gpl, cfra, GP_GETFRAME_ADD_NEW);
}
CTX_DATA_END;
/* notifiers */
if (gpd != nullptr) {
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
}
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, nullptr);
return OPERATOR_FINISHED;
}
void GPENCIL_OT_blank_frame_add(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
ot->name = "Insert Blank Frame";
ot->idname = "GPENCIL_OT_blank_frame_add";
ot->description =
"Insert a blank frame on the current frame "
"(all subsequently existing frames, if any, are shifted right by one frame)";
/* callbacks */
ot->exec = gpencil_blank_frame_add_exec;
ot->poll = gpencil_add_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* 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);
}
/** \} */ /** \} */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
@@ -321,121 +193,3 @@ void GPENCIL_OT_annotation_active_frame_delete(wmOperatorType *ot)
} }
/** \} */ /** \} */
/* -------------------------------------------------------------------- */
/** \name Delete/Dissolve Utilities
* \{ */
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,
};
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,
};
/* ----------------------------------- */
/* 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;
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
bGPDframe *init_gpf = static_cast<bGPDframe *>((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 == nullptr) {
continue;
}
/* simply delete strokes which are selected */
LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
}
/* check if the color is editable */
if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) {
continue;
}
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;
BKE_gpencil_stroke_select_index_reset(gps);
if (is_curve_edit) {
bGPDcurve *gpc = gps->editcurve;
BKE_gpencil_curve_delete_tagged_points(
gpd, gpf, gps, gps->next, gpc, GP_CURVE_POINT_SELECT);
}
else {
/* delete unwanted points by splitting stroke into several smaller ones */
BKE_gpencil_stroke_delete_tagged_points(
gpd, gpf, gps, gps->next, GP_SPOINT_SELECT, false, false, 0);
}
changed = true;
}
}
}
}
}
CTX_DATA_END;
if (changed) {
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, nullptr);
return OPERATOR_FINISHED;
}
return OPERATOR_CANCELLED;
}
int gpencil_delete_selected_point_wrap(bContext *C)
{
return gpencil_delete_selected_points(C);
}
/** \} */
bool ED_object_gpencil_exit(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 |
GP_DATA_STROKE_WEIGHTMODE | GP_DATA_STROKE_VERTEXMODE);
ob->restore_mode = ob->mode;
ob->mode &= ~(OB_MODE_PAINT_GREASE_PENCIL | OB_MODE_EDIT_GPENCIL_LEGACY |
OB_MODE_SCULPT_GREASE_PENCIL | OB_MODE_WEIGHT_GREASE_PENCIL |
OB_MODE_VERTEX_GREASE_PENCIL);
/* Inform all evaluated versions that we changed the mode. */
DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_SYNC_TO_EVAL);
ok = true;
}
return ok;
}
/** \} */

View File

@@ -39,66 +39,6 @@ struct EnumPropertyItem;
struct PointerRNA; struct PointerRNA;
struct PropertyRNA; struct PropertyRNA;
/* ***************************************************** */
/* Modal Operator Geometry Preview
*
* Several modal operators (Fill, Interpolate, Primitive)
* need to run some drawing code to display previews, or
* to perform screen-space/image-based analysis routines.
* The following structs + function prototypes are used
* by these operators so that the operator code
* (in gpencil_<opname>.c) can communicate with the drawing
* code (in `drawgpencil.cc`).
*
* NOTE: All this is within the gpencil module, so nothing needs
* to be exported to other modules.
*/
/* Internal Operator-State Data ------------------------ */
/** Random settings by stroke */
struct GpRandomSettings {
/** Pressure used for evaluated curves. */
float pen_press;
float hsv[3];
float pressure;
float strength;
float uv;
};
/* Temporary draw data (no draw manager mode) */
struct tGPDdraw {
struct RegionView3D *rv3d; /* region to draw */
struct Depsgraph *depsgraph; /* depsgraph */
struct Object *ob; /* GP object */
struct bGPdata *gpd; /* current GP datablock */
struct bGPDlayer *gpl; /* layer */
struct bGPDframe *gpf; /* frame */
struct bGPDframe *t_gpf; /* temporal frame */
struct bGPDstroke *gps; /* stroke */
int disable_fill; /* disable fill */
int offsx; /* windows offset x */
int offsy; /* windows offset y */
int winx; /* windows width */
int winy; /* windows height */
int dflag; /* flags datablock */
short lthick; /* layer thickness */
float opacity; /* opacity */
float tintcolor[4]; /* tint color */
bool onion; /* onion flag */
bool custonion; /* use custom onion colors */
bool is_fill_stroke; /* use fill tool */
float diff_mat[4][4]; /* matrix */
};
/* Modal Operator Drawing Callbacks ------------------------ */
/**
* Wrapper to draw strokes for filling operator.
*/
void ED_gpencil_draw_fill(tGPDdraw *tgpw);
/* ***************************************************** */ /* ***************************************************** */
/* Internal API */ /* Internal API */
@@ -121,106 +61,6 @@ struct GP_SpaceConversion {
float mat[4][4]; /* transform matrix on the strokes (introduced in [b770964]) */ float mat[4][4]; /* transform matrix on the strokes (introduced in [b770964]) */
}; };
/* Temporary primitive operation data */
struct tGPDprimitive {
/** main database pointer */
Main *bmain;
Depsgraph *depsgraph;
/** window where painting originated */
wmWindow *win;
/** current scene from context */
Scene *scene;
/** current active gp object */
Object *ob;
/** current evaluated gp object */
Object *ob_eval;
/** area where painting originated */
ScrArea *area;
/** region where painting originated */
RegionView3D *rv3d;
/** view3d where painting originated */
View3D *v3d;
/** region where painting originated */
ARegion *region;
/** current GP datablock */
bGPdata *gpd;
/** current material */
Material *material;
/** current brush */
Brush *brush;
/** For operations that require occlusion testing. */
ViewDepths *depths;
/** Settings to pass to gp_points_to_xy(). */
GP_SpaceConversion gsc;
/** current frame number */
int cframe;
/** layer */
bGPDlayer *gpl;
/** frame */
bGPDframe *gpf;
/** type of primitive */
int type;
/** original type of primitive */
int orign_type;
/** type of primitive is a curve */
bool curve;
/** brush size */
int brush_size;
/** brush strength */
float brush_strength;
/** flip option */
short flip;
/** array of data-points for stroke */
tGPspoint *points;
/** number of edges allocated */
int point_count;
/** number of subdivisions. */
int subdiv;
/** stored number of polygon edges */
int tot_stored_edges;
/** number of polygon edges */
int tot_edges;
/** move distance */
float move[2];
/** initial box corner */
float origin[2];
/** first box corner */
float start[2];
/** last box corner */
float end[2];
/** midpoint box corner */
float midpoint[2];
/** first control point */
float cp1[2];
/** second control point */
float cp2[2];
/** flag to determine control point is selected */
int sel_cp;
/** flag to determine operations in progress */
int flag;
/** flag to determine operations previous mode */
int prev_flag;
/** recorded mouse-position */
float mval[2];
/** previous recorded mouse-position */
float mvalo[2];
/** lock to viewport axis */
int lock_axis;
RNG *rng;
/** numeric input */
NumInput num;
/** size in pixels for uv calculation */
float totpixlen;
/** Random settings by stroke */
GpRandomSettings random_settings;
};
/** /**
* Check whether a given stroke segment is inside a circular brush * Check whether a given stroke segment is inside a circular brush
* *
@@ -232,13 +72,6 @@ struct tGPDprimitive {
*/ */
bool gpencil_stroke_inside_circle(const float mval[2], int rad, int x0, int y0, int x1, int y1); bool gpencil_stroke_inside_circle(const float mval[2], int rad, int x0, int y0, int x1, int y1);
/**
* Init settings for stroke point space conversions
*
* \param r_gsc: [out] The space conversion settings struct, populated with necessary params
*/
void gpencil_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc);
/** /**
* Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screen-space (2D) * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screen-space (2D)
* *
@@ -254,120 +87,6 @@ void gpencil_point_to_xy(const GP_SpaceConversion *gsc,
int *r_x, int *r_x,
int *r_y); int *r_y);
/**
* Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screen-space (2D).
*
* Just like #gpencil_point_to_xy(), except the resulting coordinates are floats not ints.
* Use this version to solve "stair-step" artifacts which may arise when
* round-tripping the calculations.
*
* \param r_x: The screen-space x-coordinate of the point.
* \param r_y: The screen-space y-coordinate of the point.
*
* \warning This assumes that the caller has already checked
* whether the stroke in question can be drawn.
*/
void gpencil_point_to_xy_fl(const GP_SpaceConversion *gsc,
const bGPDstroke *gps,
const bGPDspoint *pt,
float *r_x,
float *r_y);
/**
* Convert point to world space
*
* \param pt: Original point
* \param diff_mat: Matrix with the transformation
* \param[out] r_pt: Pointer to new point after apply matrix
*/
void gpencil_point_to_world_space(const bGPDspoint *pt,
const float diff_mat[4][4],
bGPDspoint *r_pt);
/**
* Change points position relative to parent object
*/
/**
* Change position relative to parent object
*/
void gpencil_world_to_object_space(Depsgraph *depsgraph,
Object *obact,
bGPDlayer *gpl,
bGPDstroke *gps);
/**
* Change point position relative to parent object
*/
/**
* Change point position relative to parent object
*/
void gpencil_world_to_object_space_point(Depsgraph *depsgraph,
Object *obact,
bGPDlayer *gpl,
bGPDspoint *pt);
/**
* generic based on gpencil_point_to_xy_fl
*/
void gpencil_point_3d_to_xy(const GP_SpaceConversion *gsc,
short flag,
const float pt[3],
float xy[2]);
/**
* Project screen-space coordinates to 3D-space
*
* For use with editing tools where it is easier to perform the operations in 2D,
* and then later convert the transformed points back to 3D.
*
* \param screen_co: The screen-space 2D coordinates to convert to
* \param r_out: The resulting 3D coordinates of the input point
*
* \note We include this as a utility function, since the standard method
* involves quite a few steps, which are invariably always the same
* for all GPencil operations. So, it's nicer to just centralize these.
*
* \warning Assumes that it is getting called in a 3D view only.
*/
bool gpencil_point_xy_to_3d(const GP_SpaceConversion *gsc,
Scene *scene,
const float screen_co[2],
float r_out[3]);
/* helper to convert 2d to 3d */
/**
* Convert #tGPspoint (temporary 2D/screen-space point data used by GP modal operators)
* to 3D coordinates.
*
* \param point2D: The screen-space 2D point data to convert.
* \param depth: Depth array (via #ED_view3d_depth_read_cached()).
* \param r_out: The resulting 2D point data.
*/
void gpencil_stroke_convertcoords_tpoint(Scene *scene,
ARegion *region,
Object *ob,
const tGPspoint *point2D,
float *depth,
float r_out[3]);
/* Poll Callbacks ------------------------------------ */
/* `gpencil_utils.cc` */
/**
* Poll callback for adding data/layers - special.
*/
bool gpencil_add_poll(bContext *C);
/**
* Poll callback for checking if there is an active layer.
*/
bool gpencil_active_layer_poll(bContext *C);
/**
* Poll callback for checking if there is an active brush.
*/
bool gpencil_active_brush_poll(bContext *C);
bool gpencil_brush_create_presets_poll(bContext *C);
int ED_gpencil_new_layer_dialog(bContext *C, wmOperator *op);
/* Copy/Paste Buffer --------------------------------- */ /* Copy/Paste Buffer --------------------------------- */
/* `gpencil_edit.cc` */ /* `gpencil_edit.cc` */
@@ -378,52 +97,6 @@ int ED_gpencil_new_layer_dialog(bContext *C, wmOperator *op);
*/ */
extern ListBase gpencil_strokes_copypastebuf; extern ListBase gpencil_strokes_copypastebuf;
/* Build a map for converting between old color-names and destination-color-refs. */
/**
* Ensure that destination datablock has all the colors the pasted strokes need.
* Helper function for copy-pasting strokes
*/
GHash *gpencil_copybuf_validate_colormap(bContext *C);
/* Stroke Editing ------------------------------------ */
/**
* Simple wrapper to external call.
*/
int gpencil_delete_selected_point_wrap(bContext *C);
/**
* Subdivide a stroke once, by adding a point half way between each pair of existing points
* \param gpd: Datablock
* \param gps: Stroke data
* \param subdivide: Number of times to subdivide
*/
void gpencil_subdivide_stroke(bGPdata *gpd, bGPDstroke *gps, int subdivide);
/* Layers Enums -------------------------------------- */
/**
* Just existing layers.
*/
const EnumPropertyItem *ED_gpencil_layers_enum_itemf(bContext *C,
PointerRNA *ptr,
PropertyRNA *prop,
bool *r_free);
/**
* Existing + Option to add/use new layer.
*/
const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C,
PointerRNA *ptr,
PropertyRNA *prop,
bool *r_free);
/**
* Just existing Materials.
*/
const EnumPropertyItem *ED_gpencil_material_enum_itemf(bContext *C,
PointerRNA *ptr,
PropertyRNA *prop,
bool *r_free);
/* ***************************************************** */ /* ***************************************************** */
/* Operator Defines */ /* Operator Defines */
@@ -435,7 +108,6 @@ void GPENCIL_OT_data_unlink(wmOperatorType *ot);
void GPENCIL_OT_layer_annotation_add(wmOperatorType *ot); void GPENCIL_OT_layer_annotation_add(wmOperatorType *ot);
void GPENCIL_OT_layer_annotation_remove(wmOperatorType *ot); void GPENCIL_OT_layer_annotation_remove(wmOperatorType *ot);
void GPENCIL_OT_layer_annotation_move(wmOperatorType *ot); void GPENCIL_OT_layer_annotation_move(wmOperatorType *ot);
void GPENCIL_OT_blank_frame_add(wmOperatorType *ot);
void GPENCIL_OT_annotation_active_frame_delete(wmOperatorType *ot); void GPENCIL_OT_annotation_active_frame_delete(wmOperatorType *ot);
/* Paint Modes for operator */ /* Paint Modes for operator */
@@ -450,190 +122,8 @@ enum eGPencil_PaintModes {
/* chunk size for gp-session buffer (the total size is a multiple of this number) */ /* chunk size for gp-session buffer (the total size is a multiple of this number) */
#define GP_STROKE_BUFFER_CHUNK 2048 #define GP_STROKE_BUFFER_CHUNK 2048
/* buttons editing --- */
enum {
GP_STROKE_JOIN = -1,
GP_STROKE_JOINCOPY = 1,
};
enum {
GP_STROKE_BOX = -1,
GP_STROKE_LINE = 1,
GP_STROKE_CIRCLE = 2,
GP_STROKE_ARC = 3,
GP_STROKE_CURVE = 4,
GP_STROKE_POLYLINE = 5,
};
enum {
GP_MERGE_STROKE = -1,
GP_MERGE_POINT = 1,
};
/* undo stack ---------- */ /* undo stack ---------- */
void gpencil_undo_init(bGPdata *gpd); void gpencil_undo_init(bGPdata *gpd);
void gpencil_undo_push(bGPdata *gpd); void gpencil_undo_push(bGPdata *gpd);
void gpencil_undo_finish(); void gpencil_undo_finish();
/* ****************************************************** */
/* Stroke Iteration Utilities */
struct GP_EditableStrokes_Iter {
float diff_mat[4][4];
float inverse_diff_mat[4][4];
};
/**
* Iterate over all editable strokes in the current context,
* stopping on each usable layer + stroke pair (i.e. gpl and gps)
* to perform some operations on the stroke.
*
* \param gpl: The identifier to use for the layer of the stroke being processed.
* Choose a suitable value to avoid name clashes.
* \param gps: The identifier to use for current stroke being processed.
* Choose a suitable value to avoid name clashes.
*/
#define GP_EDITABLE_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) \
{ \
GP_EditableStrokes_Iter gpstroke_iter = {{{0}}}; \
Depsgraph *depsgraph_ = CTX_data_ensure_evaluated_depsgraph(C); \
Object *obact_ = CTX_data_active_object(C); \
bGPdata *gpd_ = CTX_data_gpencil_data(C); \
const bool is_multiedit_ = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_); \
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { \
bGPDframe *init_gpf_ = (is_multiedit_) ? (bGPDframe *)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_)) { \
BKE_gpencil_layer_transform_matrix_get( \
depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \
invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \
/* loop over strokes */ \
bGPDstroke *gpsn_; \
for (bGPDstroke *gps = (bGPDstroke *)gpf_->strokes.first; gps; gps = gpsn_) { \
gpsn_ = gps->next; \
/* skip strokes that are invalid for current view */ \
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; \
} \
/* ... Do Stuff With Strokes ... */
#define GP_EDITABLE_STROKES_END(gpstroke_iter) \
} \
} \
if (!is_multiedit_) { \
break; \
} \
} \
} \
CTX_DATA_END; \
} \
(void)0
/**
* Iterate over all editable edit-curves in the current context,
* stopping on each usable layer + stroke + curve pair (i.e. `gpl`, `gps` and `gpc`)
* to perform some operations on the curve.
*
* \param gpl: The identifier to use for the layer of the stroke being processed.
* Choose a suitable value to avoid name clashes.
* \param gps: The identifier to use for current stroke being processed.
* Choose a suitable value to avoid name clashes.
* \param gpc: The identifier to use for current editcurve being processed.
* Choose a suitable value to avoid name clashes.
*/
#define GP_EDITABLE_CURVES_BEGIN(gpstroke_iter, C, gpl, gps, gpc) \
{ \
GP_EditableStrokes_Iter gpstroke_iter = {{{0}}}; \
Depsgraph *depsgraph_ = CTX_data_ensure_evaluated_depsgraph(C); \
Object *obact_ = CTX_data_active_object(C); \
bGPdata *gpd_ = CTX_data_gpencil_data(C); \
const bool is_multiedit_ = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_); \
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { \
bGPDframe *init_gpf_ = (is_multiedit_) ? (bGPDframe *)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_)) { \
BKE_gpencil_layer_transform_matrix_get( \
depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \
invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \
/* loop over strokes */ \
bGPDstroke *gpsn_; \
for (bGPDstroke *gps = (bGPDstroke *)gpf_->strokes.first; gps; gps = gpsn_) { \
gpsn_ = gps->next; \
/* skip strokes that are invalid for current view */ \
if (ED_gpencil_stroke_can_use(C, gps) == false) \
continue; \
if (gps->editcurve == NULL) \
continue; \
bGPDcurve *gpc = gps->editcurve; \
/* ... Do Stuff With Strokes ... */
#define GP_EDITABLE_CURVES_END(gpstroke_iter) \
} \
} \
if (!is_multiedit_) { \
break; \
} \
} \
} \
CTX_DATA_END; \
} \
(void)0
/**
* Iterate over all editable strokes using evaluated data in the current context,
* stopping on each usable layer + stroke pair (i.e. gpl and gps)
* to perform some operations on the stroke.
*
* \param gpl: The identifier to use for the layer of the stroke being processed.
* Choose a suitable value to avoid name clashes.
* \param gps: The identifier to use for current stroke being processed.
* Choose a suitable value to avoid name clashes.
*/
#define GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) \
{ \
GP_EditableStrokes_Iter gpstroke_iter = {{{0}}}; \
Depsgraph *depsgraph_ = CTX_data_ensure_evaluated_depsgraph(C); \
Object *obact_ = CTX_data_active_object(C); \
Object *ob_eval_ = (Object *)DEG_get_evaluated_id(depsgraph_, &obact_->id); \
bGPdata *gpd_ = (bGPdata *)ob_eval_->data; \
const bool is_multiedit_ = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_); \
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_->layers) { \
if (BKE_gpencil_layer_is_editable(gpl)) { \
bGPDframe *init_gpf_ = (is_multiedit_) ? (bGPDframe *)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_)) { \
BKE_gpencil_layer_transform_matrix_get( \
depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \
/* Undo layer transform. */ \
mul_m4_m4m4(gpstroke_iter.diff_mat, gpstroke_iter.diff_mat, gpl->layer_invmat); \
/* loop over strokes */ \
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf_->strokes) { \
/* skip strokes that are invalid for current view */ \
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; \
} \
/* ... Do Stuff With Strokes ... */
#define GP_EVALUATED_STROKES_END(gpstroke_iter) \
} \
} \
if (!is_multiedit_) { \
break; \
} \
} \
} \
} \
} \
(void)0
/* ****************************************************** */

View File

@@ -46,7 +46,6 @@ void ED_operatortypes_gpencil_legacy()
WM_operatortype_append(GPENCIL_OT_layer_annotation_add); WM_operatortype_append(GPENCIL_OT_layer_annotation_add);
WM_operatortype_append(GPENCIL_OT_layer_annotation_remove); WM_operatortype_append(GPENCIL_OT_layer_annotation_remove);
WM_operatortype_append(GPENCIL_OT_layer_annotation_move); WM_operatortype_append(GPENCIL_OT_layer_annotation_move);
WM_operatortype_append(GPENCIL_OT_blank_frame_add);
WM_operatortype_append(GPENCIL_OT_annotation_active_frame_delete); WM_operatortype_append(GPENCIL_OT_annotation_active_frame_delete);
/* Editing (Time) --------------- */ /* Editing (Time) --------------- */

View File

@@ -229,12 +229,6 @@ bGPdata **ED_annotation_data_get_pointers(const bContext *C, PointerRNA *r_ptr)
} }
/* -------------------------------------------------------- */ /* -------------------------------------------------------- */
bGPdata *ED_gpencil_data_get_active_direct(ScrArea *area, Object *ob)
{
bGPdata **gpd_ptr = ED_gpencil_data_get_pointers_direct(area, ob, nullptr);
return (gpd_ptr) ? *(gpd_ptr) : nullptr;
}
bGPdata *ED_annotation_data_get_active_direct(ID *screen_id, ScrArea *area, Scene *scene) bGPdata *ED_annotation_data_get_active_direct(ID *screen_id, ScrArea *area, Scene *scene)
{ {
bGPdata **gpd_ptr = ED_annotation_data_get_pointers_direct(screen_id, area, scene, nullptr); bGPdata **gpd_ptr = ED_annotation_data_get_pointers_direct(screen_id, area, scene, nullptr);
@@ -256,17 +250,6 @@ bGPdata *ED_annotation_data_get_active(const bContext *C)
return (gpd_ptr) ? *(gpd_ptr) : nullptr; return (gpd_ptr) ? *(gpd_ptr) : nullptr;
} }
bGPdata *ED_gpencil_data_get_active_evaluated(const bContext *C)
{
ScrArea *area = CTX_wm_area(C);
const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Object *ob = CTX_data_active_object(C);
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
return ED_gpencil_data_get_active_direct(area, ob_eval);
}
/* -------------------------------------------------------- */ /* -------------------------------------------------------- */
bool ED_gpencil_data_owner_is_annotation(PointerRNA *owner_ptr) bool ED_gpencil_data_owner_is_annotation(PointerRNA *owner_ptr)
@@ -276,188 +259,6 @@ bool ED_gpencil_data_owner_is_annotation(PointerRNA *owner_ptr)
return ((owner_ptr) && (owner_ptr->type != &RNA_Object)); return ((owner_ptr) && (owner_ptr->type != &RNA_Object));
} }
/* ******************************************************** */
/* Keyframe Indicator Checks */
bool ED_gpencil_has_keyframe_v3d(Scene * /*scene*/, Object *ob, int cfra)
{
if (ob && ob->data && (ob->type == OB_GPENCIL_LEGACY)) {
bGPDlayer *gpl = BKE_gpencil_layer_active_get(static_cast<bGPdata *>(ob->data));
if (gpl) {
if (gpl->actframe) {
/* XXX: assumes that frame has been fetched already */
return (gpl->actframe->framenum == cfra);
}
/* XXX: disabled as could be too much of a penalty */
// return BKE_gpencil_layer_frame_find(gpl, cfra);
}
}
return false;
}
/* ******************************************************** */
/* Poll Callbacks */
bool gpencil_add_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
if (ob == nullptr) {
return false;
}
bGPdata *gpd = (bGPdata *)ob->data;
return (gpd != nullptr);
}
bool gpencil_active_layer_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
if ((ob == nullptr) || (ob->type != OB_GPENCIL_LEGACY)) {
return false;
}
bGPdata *gpd = (bGPdata *)ob->data;
bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
return (gpl != nullptr);
}
bool gpencil_active_brush_poll(bContext *C)
{
ToolSettings *ts = CTX_data_tool_settings(C);
Paint *paint = &ts->gp_paint->paint;
if (paint) {
return (BKE_paint_brush(paint) != nullptr);
}
return false;
}
/* ******************************************************** */
/* Dynamic Enums of GP Layers */
/* NOTE: These include an option to create a new layer and use that... */
const EnumPropertyItem *ED_gpencil_layers_enum_itemf(bContext *C,
PointerRNA * /*ptr*/,
PropertyRNA * /*prop*/,
bool *r_free)
{
bGPdata *gpd = CTX_data_gpencil_data(C);
bGPDlayer *gpl;
EnumPropertyItem *item = nullptr, item_tmp = {0};
int totitem = 0;
int i = 0;
if (ELEM(nullptr, C, gpd)) {
return rna_enum_dummy_DEFAULT_items;
}
/* Existing layers */
for (gpl = static_cast<bGPDlayer *>(gpd->layers.first); gpl; gpl = gpl->next, i++) {
item_tmp.identifier = gpl->info;
item_tmp.name = gpl->info;
item_tmp.value = i;
if (gpl->flag & GP_LAYER_ACTIVE) {
item_tmp.icon = ICON_GREASEPENCIL;
}
else {
item_tmp.icon = ICON_NONE;
}
RNA_enum_item_add(&item, &totitem, &item_tmp);
}
RNA_enum_item_end(&item, &totitem);
*r_free = true;
return item;
}
const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C,
PointerRNA * /*ptr*/,
PropertyRNA * /*prop*/,
bool *r_free)
{
bGPdata *gpd = CTX_data_gpencil_data(C);
bGPDlayer *gpl;
EnumPropertyItem *item = nullptr, item_tmp = {0};
int totitem = 0;
int i = 0;
if (ELEM(nullptr, C, gpd)) {
return rna_enum_dummy_DEFAULT_items;
}
/* Create new layer */
/* TODO: have some way of specifying that we don't want this? */
{
/* "New Layer" entry */
item_tmp.identifier = "__CREATE__";
item_tmp.name = "New Layer";
item_tmp.value = -1;
item_tmp.icon = ICON_ADD;
RNA_enum_item_add(&item, &totitem, &item_tmp);
/* separator */
RNA_enum_item_add_separator(&item, &totitem);
}
const int tot = BLI_listbase_count(&gpd->layers);
/* Existing layers */
for (gpl = static_cast<bGPDlayer *>(gpd->layers.last), i = 0; gpl; gpl = gpl->prev, i++) {
item_tmp.identifier = gpl->info;
item_tmp.name = gpl->info;
item_tmp.value = tot - i - 1;
if (gpl->flag & GP_LAYER_ACTIVE) {
item_tmp.icon = ICON_GREASEPENCIL;
}
else {
item_tmp.icon = ICON_NONE;
}
RNA_enum_item_add(&item, &totitem, &item_tmp);
}
RNA_enum_item_end(&item, &totitem);
*r_free = true;
return item;
}
const EnumPropertyItem *ED_gpencil_material_enum_itemf(bContext *C,
PointerRNA * /*ptr*/,
PropertyRNA * /*prop*/,
bool *r_free)
{
Object *ob = CTX_data_active_object(C);
EnumPropertyItem *item = nullptr, item_tmp = {0};
int totitem = 0;
int i = 0;
if (ELEM(nullptr, C, ob)) {
return rna_enum_dummy_DEFAULT_items;
}
/* Existing materials */
for (i = 1; i <= ob->totcol; i++) {
Material *ma = BKE_object_material_get(ob, i);
if (ma) {
item_tmp.identifier = ma->id.name + 2;
item_tmp.name = ma->id.name + 2;
item_tmp.value = i;
item_tmp.icon = ma->preview ? ma->preview->runtime->icon_id : ICON_NONE;
RNA_enum_item_add(&item, &totitem, &item_tmp);
}
}
RNA_enum_item_end(&item, &totitem);
*r_free = true;
return item;
}
/* ******************************************************** */ /* ******************************************************** */
/* Brush Tool Core */ /* Brush Tool Core */
@@ -475,39 +276,6 @@ bool gpencil_stroke_inside_circle(const float mval[2], int rad, int x0, int y0,
return false; return false;
} }
/* ******************************************************** */
/* Selection Validity Testing */
bool ED_gpencil_frame_has_selected_stroke(const bGPDframe *gpf)
{
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if (gps->flag & GP_STROKE_SELECT) {
return true;
}
}
return false;
}
bool ED_gpencil_layer_has_selected_stroke(const bGPDlayer *gpl, const bool is_multiedit)
{
bGPDframe *init_gpf = static_cast<bGPDframe *>((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 (ED_gpencil_frame_has_selected_stroke(gpf)) {
return true;
}
}
/* If not multi-edit, exit loop. */
if (!is_multiedit) {
break;
}
}
return false;
}
/* ******************************************************** */ /* ******************************************************** */
/* Stroke Validity Testing */ /* Stroke Validity Testing */
@@ -558,108 +326,9 @@ bool ED_gpencil_stroke_material_editable(Object *ob, const bGPDlayer *gpl, const
return true; return true;
} }
bool ED_gpencil_stroke_material_visible(Object *ob, const bGPDstroke *gps)
{
/* check if the color is editable */
MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
if (gp_style != nullptr) {
if (gp_style->flag & GP_MATERIAL_HIDE) {
return false;
}
}
return true;
}
/* ******************************************************** */ /* ******************************************************** */
/* Space Conversion */ /* Space Conversion */
void gpencil_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
{
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
/* zero out the storage (just in case) */
memset(r_gsc, 0, sizeof(GP_SpaceConversion));
unit_m4(r_gsc->mat);
/* store settings */
r_gsc->scene = CTX_data_scene(C);
r_gsc->ob = CTX_data_active_object(C);
r_gsc->area = area;
r_gsc->region = region;
r_gsc->v2d = &region->v2d;
/* init region-specific stuff */
if (area->spacetype == SPACE_VIEW3D) {
wmWindow *win = CTX_wm_window(C);
Scene *scene = CTX_data_scene(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
View3D *v3d = (View3D *)CTX_wm_space_data(C);
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
/* init 3d depth buffers */
view3d_operator_needs_opengl(C);
view3d_region_operator_needs_opengl(win, region);
ED_view3d_depth_override(depsgraph, region, v3d, nullptr, V3D_DEPTH_NO_GPENCIL, nullptr);
/* for camera view set the subrect */
if (rv3d->persp == RV3D_CAMOB) {
ED_view3d_calc_camera_border(
scene, depsgraph, region, v3d, rv3d, true, &r_gsc->subrect_data);
r_gsc->subrect = &r_gsc->subrect_data;
}
}
}
void gpencil_point_to_world_space(const bGPDspoint *pt,
const float diff_mat[4][4],
bGPDspoint *r_pt)
{
mul_v3_m4v3(&r_pt->x, diff_mat, &pt->x);
}
void gpencil_world_to_object_space(Depsgraph *depsgraph,
Object *obact,
bGPDlayer *gpl,
bGPDstroke *gps)
{
bGPDspoint *pt;
int i;
/* undo matrix */
float diff_mat[4][4];
float inverse_diff_mat[4][4];
BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat);
zero_axis_bias_m4(diff_mat);
invert_m4_m4(inverse_diff_mat, diff_mat);
for (i = 0; i < gps->totpoints; i++) {
pt = &gps->points[i];
mul_m4_v3(inverse_diff_mat, &pt->x);
}
}
void gpencil_world_to_object_space_point(Depsgraph *depsgraph,
Object *obact,
bGPDlayer *gpl,
bGPDspoint *pt)
{
/* undo matrix */
float diff_mat[4][4];
float inverse_diff_mat[4][4];
BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat);
zero_axis_bias_m4(diff_mat);
invert_m4_m4(inverse_diff_mat, diff_mat);
mul_m4_v3(inverse_diff_mat, &pt->x);
}
void gpencil_point_to_xy( void gpencil_point_to_xy(
const GP_SpaceConversion *gsc, const bGPDstroke *gps, const bGPDspoint *pt, int *r_x, int *r_y) const GP_SpaceConversion *gsc, const bGPDstroke *gps, const bGPDspoint *pt, int *r_x, int *r_y)
{ {
@@ -702,194 +371,6 @@ void gpencil_point_to_xy(
} }
} }
void gpencil_point_to_xy_fl(const GP_SpaceConversion *gsc,
const bGPDstroke *gps,
const bGPDspoint *pt,
float *r_x,
float *r_y)
{
const ARegion *region = gsc->region;
const View2D *v2d = gsc->v2d;
const rctf *subrect = gsc->subrect;
float xyval[2];
/* sanity checks */
BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->area->spacetype == SPACE_VIEW3D));
BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->area->spacetype != SPACE_VIEW3D));
if (gps->flag & GP_STROKE_3DSPACE) {
if (ED_view3d_project_float_global(region, &pt->x, xyval, V3D_PROJ_TEST_NOP) ==
V3D_PROJ_RET_OK)
{
*r_x = xyval[0];
*r_y = xyval[1];
}
else {
*r_x = 0.0f;
*r_y = 0.0f;
}
}
else if (gps->flag & GP_STROKE_2DSPACE) {
float vec[3] = {pt->x, pt->y, 0.0f};
int t_x, t_y;
mul_m4_v3(gsc->mat, vec);
UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], &t_x, &t_y);
if ((t_x == t_y) && (t_x == V2D_IS_CLIPPED)) {
/* XXX: Or should we just always use the values as-is? */
*r_x = 0.0f;
*r_y = 0.0f;
}
else {
*r_x = float(t_x);
*r_y = float(t_y);
}
}
else {
if (subrect == nullptr) {
/* normal 3D view (or view space) */
*r_x = (pt->x / 100.0f * region->winx);
*r_y = (pt->y / 100.0f * region->winy);
}
else {
/* camera view, use subrect */
*r_x = ((pt->x / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin;
*r_y = ((pt->y / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin;
}
}
}
void gpencil_point_3d_to_xy(const GP_SpaceConversion *gsc,
const short flag,
const float pt[3],
float xy[2])
{
const ARegion *region = gsc->region;
const View2D *v2d = gsc->v2d;
const rctf *subrect = gsc->subrect;
float xyval[2];
/* sanity checks */
BLI_assert(gsc->area->spacetype == SPACE_VIEW3D);
if (flag & GP_STROKE_3DSPACE) {
if (ED_view3d_project_float_global(region, pt, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
xy[0] = xyval[0];
xy[1] = xyval[1];
}
else {
xy[0] = 0.0f;
xy[1] = 0.0f;
}
}
else if (flag & GP_STROKE_2DSPACE) {
float vec[3] = {pt[0], pt[1], 0.0f};
int t_x, t_y;
mul_m4_v3(gsc->mat, vec);
UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], &t_x, &t_y);
if ((t_x == t_y) && (t_x == V2D_IS_CLIPPED)) {
/* XXX: Or should we just always use the values as-is? */
xy[0] = 0.0f;
xy[1] = 0.0f;
}
else {
xy[0] = float(t_x);
xy[1] = float(t_y);
}
}
else {
if (subrect == nullptr) {
/* normal 3D view (or view space) */
xy[0] = (pt[0] / 100.0f * region->winx);
xy[1] = (pt[1] / 100.0f * region->winy);
}
else {
/* camera view, use subrect */
xy[0] = ((pt[0] / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin;
xy[1] = ((pt[1] / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin;
}
}
}
bool gpencil_point_xy_to_3d(const GP_SpaceConversion *gsc,
Scene *scene,
const float screen_co[2],
float r_out[3])
{
const RegionView3D *rv3d = static_cast<const RegionView3D *>(gsc->region->regiondata);
float rvec[3];
ED_gpencil_drawing_reference_get(scene, gsc->ob, scene->toolsettings->gpencil_v3d_align, rvec);
float zfac = ED_view3d_calc_zfac(rv3d, rvec);
float mval_prj[2];
if (ED_view3d_project_float_global(gsc->region, rvec, mval_prj, V3D_PROJ_TEST_NOP) ==
V3D_PROJ_RET_OK)
{
float dvec[3];
float xy_delta[2];
sub_v2_v2v2(xy_delta, mval_prj, screen_co);
ED_view3d_win_to_delta(gsc->region, xy_delta, zfac, dvec);
sub_v3_v3v3(r_out, rvec, dvec);
return true;
}
zero_v3(r_out);
return false;
}
void gpencil_stroke_convertcoords_tpoint(Scene *scene,
ARegion *region,
Object *ob,
const tGPspoint *point2D,
float *depth,
float r_out[3])
{
ToolSettings *ts = scene->toolsettings;
if (depth && (*depth == DEPTH_INVALID)) {
depth = nullptr;
}
int mval_i[2];
round_v2i_v2fl(mval_i, point2D->m_xy);
if ((depth != nullptr) && ED_view3d_autodist_simple(region, mval_i, r_out, 0, depth)) {
/* projecting onto 3D-Geometry
* - nothing more needs to be done here, since view_autodist_simple() has already done it
*/
}
else {
float mval_prj[2];
float rvec[3];
/* Current method just converts each point in screen-coordinates to
* 3D-coordinates using the 3D-cursor as reference.
*/
ED_gpencil_drawing_reference_get(scene, ob, ts->gpencil_v3d_align, rvec);
const float zfac = ED_view3d_calc_zfac(static_cast<const RegionView3D *>(region->regiondata),
rvec);
if (ED_view3d_project_float_global(region, rvec, mval_prj, V3D_PROJ_TEST_NOP) ==
V3D_PROJ_RET_OK)
{
float dvec[3];
float xy_delta[2];
sub_v2_v2v2(xy_delta, mval_prj, point2D->m_xy);
ED_view3d_win_to_delta(region, xy_delta, zfac, dvec);
sub_v3_v3v3(r_out, rvec, dvec);
}
else {
zero_v3(r_out);
}
}
}
void ED_gpencil_drawing_reference_get(const Scene *scene, void ED_gpencil_drawing_reference_get(const Scene *scene,
const Object *ob, const Object *ob,
char align_flag, char align_flag,
@@ -923,1158 +404,6 @@ void ED_gpencil_drawing_reference_get(const Scene *scene,
} }
} }
void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke *gps)
{
Scene *scene = CTX_data_scene(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Object *ob = CTX_data_active_object(C);
GP_SpaceConversion gsc = {nullptr};
bGPDspoint *pt;
int i;
float diff_mat[4][4];
float inverse_diff_mat[4][4];
/* init space conversion stuff */
gpencil_point_conversion_init(C, &gsc);
BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat);
zero_axis_bias_m4(diff_mat);
invert_m4_m4(inverse_diff_mat, diff_mat);
/* Adjust each point */
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
float xy[2];
bGPDspoint pt2;
gpencil_point_to_world_space(pt, diff_mat, &pt2);
gpencil_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]);
/* Planar - All on same plane parallel to the viewplane */
gpencil_point_xy_to_3d(&gsc, scene, xy, &pt->x);
/* Unapply parent corrections */
mul_m4_v3(inverse_diff_mat, &pt->x);
}
}
void ED_gpencil_project_stroke_to_plane(const Scene *scene,
const Object *ob,
const RegionView3D *rv3d,
bGPDlayer *gpl,
bGPDstroke *gps,
const float origin[3],
const int axis)
{
const ToolSettings *ts = scene->toolsettings;
const View3DCursor *cursor = &scene->cursor;
float plane_normal[3];
float vn[3];
float ray[3];
float rpoint[3];
/* Recalculate layer transform matrix. */
loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale);
invert_m4_m4(gpl->layer_invmat, gpl->layer_mat);
/* normal vector for a plane locked to axis */
zero_v3(plane_normal);
if (axis < 0) {
/* if the axis is not locked, need a vector to the view direction
* in order to get the right size of the stroke.
*/
ED_view3d_global_to_vector(rv3d, origin, plane_normal);
}
else if (axis < 3) {
plane_normal[axis] = 1.0f;
/* if object, apply object rotation */
if (ob && (ob->type == OB_GPENCIL_LEGACY)) {
float mat[4][4];
copy_m4_m4(mat, ob->object_to_world().ptr());
/* move origin to cursor */
if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) {
if (gpl != nullptr) {
add_v3_v3(mat[3], gpl->location);
}
}
if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) {
copy_v3_v3(mat[3], cursor->location);
}
mul_mat3_m4_v3(mat, plane_normal);
}
if ((gpl != nullptr) && (ts->gp_sculpt.lock_axis != GP_LOCKAXIS_CURSOR)) {
mul_mat3_m4_v3(gpl->layer_mat, plane_normal);
}
}
else {
const float scale[3] = {1.0f, 1.0f, 1.0f};
plane_normal[2] = 1.0f;
float mat[4][4];
loc_eul_size_to_mat4(mat, cursor->location, cursor->rotation_euler, scale);
mul_mat3_m4_v3(mat, plane_normal);
}
/* Reproject the points in the plane */
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
/* get a vector from the point with the current view direction of the viewport */
ED_view3d_global_to_vector(rv3d, &pt->x, vn);
/* calculate line extreme point to create a ray that cross the plane */
mul_v3_fl(vn, -50.0f);
add_v3_v3v3(ray, &pt->x, vn);
/* if the line never intersect, the point is not changed */
if (isect_line_plane_v3(rpoint, &pt->x, ray, origin, plane_normal)) {
copy_v3_v3(&pt->x, rpoint);
}
}
}
void ED_gpencil_stroke_reproject(Depsgraph *depsgraph,
const GP_SpaceConversion *gsc,
SnapObjectContext *sctx,
bGPDlayer *gpl,
bGPDframe *gpf,
bGPDstroke *gps,
const eGP_ReprojectModes mode,
const bool keep_original,
const float offset)
{
ToolSettings *ts = gsc->scene->toolsettings;
ARegion *region = gsc->region;
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
/* Recalculate layer transform matrix. */
loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale);
invert_m4_m4(gpl->layer_invmat, gpl->layer_mat);
float diff_mat[4][4], inverse_diff_mat[4][4];
BKE_gpencil_layer_transform_matrix_get(depsgraph, gsc->ob, gpl, diff_mat);
zero_axis_bias_m4(diff_mat);
invert_m4_m4(inverse_diff_mat, diff_mat);
float origin[3];
if (mode != GP_REPROJECT_CURSOR) {
ED_gpencil_drawing_reference_get(gsc->scene, gsc->ob, ts->gpencil_v3d_align, origin);
}
else {
copy_v3_v3(origin, gsc->scene->cursor.location);
}
bGPDspoint *pt;
int i;
/* If keep original, do a copy. */
bGPDstroke *gps_active = gps;
/* if duplicate, deselect all points. */
if (keep_original) {
gps_active = BKE_gpencil_stroke_duplicate(gps, true, true);
gps_active->flag &= ~GP_STROKE_SELECT;
BKE_gpencil_stroke_select_index_reset(gps_active);
for (i = 0, pt = gps_active->points; i < gps_active->totpoints; i++, pt++) {
pt->flag &= ~GP_SPOINT_SELECT;
}
/* Add to frame. */
BLI_addtail(&gpf->strokes, gps_active);
}
/* Adjust each point */
for (i = 0, pt = gps_active->points; i < gps_active->totpoints; i++, pt++) {
float xy[2];
/* 3D to Screen-space */
/* NOTE: We can't use gpencil_point_to_xy() here because that uses ints for the screen-space
* coordinates, resulting in lost precision, which in turn causes stair-stepping
* artifacts in the final points. */
bGPDspoint pt2;
gpencil_point_to_world_space(pt, diff_mat, &pt2);
gpencil_point_to_xy_fl(gsc, gps_active, &pt2, &xy[0], &xy[1]);
/* Project stroke in one axis */
if (ELEM(mode, GP_REPROJECT_FRONT, GP_REPROJECT_SIDE, GP_REPROJECT_TOP, GP_REPROJECT_CURSOR)) {
int axis = 0;
switch (mode) {
case GP_REPROJECT_FRONT: {
axis = 1;
break;
}
case GP_REPROJECT_SIDE: {
axis = 0;
break;
}
case GP_REPROJECT_TOP: {
axis = 2;
break;
}
case GP_REPROJECT_CURSOR: {
axis = 3;
break;
}
default: {
axis = 1;
break;
}
}
ED_gpencil_project_point_to_plane(gsc->scene, gsc->ob, gpl, rv3d, origin, axis, &pt2);
copy_v3_v3(&pt->x, &pt2.x);
/* apply parent again */
gpencil_world_to_object_space_point(depsgraph, gsc->ob, gpl, pt);
}
/* Project screen-space back to 3D space (from current perspective)
* so that all points have been treated the same way. */
else if (mode == GP_REPROJECT_VIEW) {
/* Planar - All on same plane parallel to the view-plane. */
gpencil_point_xy_to_3d(gsc, gsc->scene, xy, &pt->x);
}
else {
/* Geometry - Snap to surfaces of visible geometry */
float ray_start[3];
float ray_normal[3];
/* magic value for initial depth copied from the default
* value of Python's Scene.ray_cast function
*/
float depth = 1.70141e+38f;
float location[3] = {0.0f, 0.0f, 0.0f};
float normal[3] = {0.0f, 0.0f, 0.0f};
BLI_assert(gps->flag & GP_STROKE_3DSPACE);
BLI_assert(gsc->area && gsc->area->spacetype == SPACE_VIEW3D);
const View3D *v3d = static_cast<const View3D *>(gsc->area->spacedata.first);
ED_view3d_win_to_ray_clipped(
depsgraph, region, v3d, xy, &ray_start[0], &ray_normal[0], true);
SnapObjectParams params{};
params.snap_target_select = SCE_SNAP_TARGET_ALL;
if (ED_transform_snap_object_project_ray(sctx,
depsgraph,
v3d,
&params,
&ray_start[0],
&ray_normal[0],
&depth,
&location[0],
&normal[0]))
{
/* Apply offset over surface. */
float normal_vector[3];
sub_v3_v3v3(normal_vector, ray_start, location);
normalize_v3(normal_vector);
mul_v3_fl(normal_vector, offset);
add_v3_v3v3(&pt->x, location, normal_vector);
}
else {
/* Default to planar */
gpencil_point_xy_to_3d(gsc, gsc->scene, xy, &pt->x);
}
}
/* Unapply parent corrections */
if (!ELEM(mode, GP_REPROJECT_FRONT, GP_REPROJECT_SIDE, GP_REPROJECT_TOP)) {
mul_m4_v3(inverse_diff_mat, &pt->x);
}
}
}
void ED_gpencil_project_point_to_plane(const Scene *scene,
const Object *ob,
bGPDlayer *gpl,
const RegionView3D *rv3d,
const float origin[3],
const int axis,
bGPDspoint *pt)
{
const ToolSettings *ts = scene->toolsettings;
const View3DCursor *cursor = &scene->cursor;
float plane_normal[3];
float vn[3];
float ray[3];
float rpoint[3];
/* normal vector for a plane locked to axis */
zero_v3(plane_normal);
if (axis < 0) {
/* if the axis is not locked, need a vector to the view direction
* in order to get the right size of the stroke.
*/
ED_view3d_global_to_vector(rv3d, origin, plane_normal);
}
else if (axis < 3) {
plane_normal[axis] = 1.0f;
/* if object, apply object rotation */
if (ob && (ob->type == OB_GPENCIL_LEGACY)) {
float mat[4][4];
copy_m4_m4(mat, ob->object_to_world().ptr());
if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) {
if (gpl != nullptr) {
add_v3_v3(mat[3], gpl->location);
}
}
/* move origin to cursor */
if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) {
copy_v3_v3(mat[3], cursor->location);
}
mul_mat3_m4_v3(mat, plane_normal);
/* Apply layer rotation (local transform). */
if ((gpl != nullptr) && (ts->gp_sculpt.lock_axis != GP_LOCKAXIS_CURSOR)) {
mul_mat3_m4_v3(gpl->layer_mat, plane_normal);
}
}
}
else {
const float scale[3] = {1.0f, 1.0f, 1.0f};
plane_normal[2] = 1.0f;
float mat[4][4];
loc_eul_size_to_mat4(mat, cursor->location, cursor->rotation_euler, scale);
/* move origin to object */
if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) {
copy_v3_v3(mat[3], ob->object_to_world().location());
}
mul_mat3_m4_v3(mat, plane_normal);
}
/* Reproject the points in the plane */
/* get a vector from the point with the current view direction of the viewport */
ED_view3d_global_to_vector(rv3d, &pt->x, vn);
/* calculate line extreme point to create a ray that cross the plane */
mul_v3_fl(vn, -50.0f);
add_v3_v3v3(ray, &pt->x, vn);
/* if the line never intersect, the point is not changed */
if (isect_line_plane_v3(rpoint, &pt->x, ray, origin, plane_normal)) {
copy_v3_v3(&pt->x, rpoint);
}
}
/* ******************************************************** */
/* Stroke Operations */
/* XXX: Check if these functions duplicate stuff in blenkernel,
* and/or whether we should just deduplicate. */
void gpencil_subdivide_stroke(bGPdata *gpd, bGPDstroke *gps, const int subdivide)
{
bGPDspoint *temp_points;
int totnewpoints, oldtotpoints;
int i2;
/* loop as many times as levels */
for (int s = 0; s < subdivide; s++) {
totnewpoints = gps->totpoints - 1;
/* duplicate points in a temp area */
temp_points = static_cast<bGPDspoint *>(MEM_dupallocN(gps->points));
oldtotpoints = gps->totpoints;
/* resize the points arrays */
gps->totpoints += totnewpoints;
gps->points = static_cast<bGPDspoint *>(
MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints));
if (gps->dvert != nullptr) {
gps->dvert = static_cast<MDeformVert *>(
MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints));
}
/* move points from last to first to new place */
i2 = gps->totpoints - 1;
for (int i = oldtotpoints - 1; i > 0; i--) {
bGPDspoint *pt = &temp_points[i];
bGPDspoint *pt_final = &gps->points[i2];
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;
copy_v4_v4(pt_final->vert_color, pt->vert_color);
if (gps->dvert != nullptr) {
MDeformVert *dvert = &gps->dvert[i];
MDeformVert *dvert_final = &gps->dvert[i2];
dvert_final->totweight = dvert->totweight;
dvert_final->dw = dvert->dw;
}
i2 -= 2;
}
/* interpolate mid points */
i2 = 1;
for (int i = 0; i < oldtotpoints - 1; i++) {
bGPDspoint *pt = &temp_points[i];
bGPDspoint *next = &temp_points[i + 1];
bGPDspoint *pt_final = &gps->points[i2];
/* add a half way point */
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);
pt_final->time = interpf(pt->time, next->time, 0.5f);
pt_final->uv_fac = interpf(pt->uv_fac, next->uv_fac, 0.5f);
pt_final->uv_rot = interpf(pt->uv_rot, next->uv_rot, 0.5f);
interp_v4_v4v4(pt_final->vert_color, pt->vert_color, next->vert_color, 0.5f);
if (gps->dvert != nullptr) {
MDeformVert *dvert_final = &gps->dvert[i2];
dvert_final->totweight = 0;
dvert_final->dw = nullptr;
}
i2 += 2;
}
MEM_SAFE_FREE(temp_points);
/* move points to smooth stroke */
/* duplicate points in a temp area with the new subdivide data */
temp_points = static_cast<bGPDspoint *>(MEM_dupallocN(gps->points));
/* extreme points are not changed */
for (int i = 0; i < gps->totpoints - 2; i++) {
bGPDspoint *pt = &temp_points[i];
bGPDspoint *next = &temp_points[i + 1];
bGPDspoint *pt_final = &gps->points[i + 1];
/* move point */
interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
}
/* free temp memory */
MEM_SAFE_FREE(temp_points);
}
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata *gpd)
{
bGPDspoint *pt;
int i;
float diff_mat[4][4];
float cur_mat[4][4];
float gpl_loc[3];
zero_v3(gpl_loc);
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl->parent != nullptr) {
/* calculate new matrix */
if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) {
invert_m4_m4(cur_mat, gpl->parent->object_to_world().ptr());
copy_v3_v3(gpl_loc, obact->object_to_world().location());
}
else if (gpl->partype == PARBONE) {
bPoseChannel *pchan = BKE_pose_channel_find_name(gpl->parent->pose, gpl->parsubstr);
if (pchan) {
float tmp_mat[4][4];
mul_m4_m4m4(tmp_mat, gpl->parent->object_to_world().ptr(), pchan->pose_mat);
invert_m4_m4(cur_mat, tmp_mat);
copy_v3_v3(gpl_loc, obact->object_to_world().location());
}
}
/* only redo if any change */
if (!equals_m4m4(gpl->inverse, cur_mat)) {
/* first apply current transformation to all strokes */
BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat);
/* undo local object */
sub_v3_v3(diff_mat[3], gpl_loc);
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
mul_m4_v3(diff_mat, &pt->x);
}
}
}
/* set new parent matrix */
copy_m4_m4(gpl->inverse, cur_mat);
}
}
}
}
/* ******************************************************** */
/* GP Object Stuff */
Object *ED_gpencil_add_object(bContext *C, const float loc[3], ushort local_view_bits)
{
const float rot[3] = {0.0f};
Object *ob = blender::ed::object::add_type(
C, OB_GPENCIL_LEGACY, nullptr, loc, rot, false, local_view_bits);
/* create default brushes and colors */
ED_gpencil_add_defaults(C, ob);
return ob;
}
void ED_gpencil_add_defaults(bContext *C, Object *ob)
{
Main *bmain = CTX_data_main(C);
ToolSettings *ts = CTX_data_tool_settings(C);
BKE_paint_ensure(bmain, ts, (Paint **)&ts->gp_paint);
/* ensure a color exists and is assigned to object */
BKE_gpencil_object_material_ensure_from_active_input_toolsettings(bmain, ob, ts);
/* Ensure multi-frame falloff curve. */
if (ts->gp_sculpt.cur_falloff == nullptr) {
ts->gp_sculpt.cur_falloff = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
CurveMapping *gp_falloff_curve = ts->gp_sculpt.cur_falloff;
BKE_curvemapping_init(gp_falloff_curve);
BKE_curvemap_reset(gp_falloff_curve->cm,
&gp_falloff_curve->clipr,
CURVE_PRESET_GAUSS,
CURVEMAP_SLOPE_POSITIVE);
}
}
/* ******************************************************** */
/* Vertex Groups */
void ED_gpencil_vgroup_assign(bContext *C, Object *ob, float weight)
{
bGPdata *gpd = (bGPdata *)ob->data;
const bool is_multiedit = bool(GPENCIL_MULTIEDIT_SESSIONS_ON(gpd));
const int def_nr = gpd->vertex_group_active_index - 1;
if (!BLI_findlink(&gpd->vertex_group_names, def_nr)) {
return;
}
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
bGPDframe *init_gpf = static_cast<bGPDframe *>((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 == nullptr) {
continue;
}
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
}
if (gps->flag & GP_STROKE_SELECT) {
/* verify the weight array is created */
BKE_gpencil_dvert_ensure(gps);
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
MDeformVert *dvert = &gps->dvert[i];
if (pt->flag & GP_SPOINT_SELECT) {
MDeformWeight *dw = BKE_defvert_ensure_index(dvert, def_nr);
if (dw) {
dw->weight = weight;
}
}
}
}
}
}
/* If not multi-edit, exit loop. */
if (!is_multiedit) {
break;
}
}
}
CTX_DATA_END;
}
void ED_gpencil_vgroup_remove(bContext *C, Object *ob)
{
bGPdata *gpd = (bGPdata *)ob->data;
const bool is_multiedit = bool(GPENCIL_MULTIEDIT_SESSIONS_ON(gpd));
const int def_nr = gpd->vertex_group_active_index - 1;
if (!BLI_findlink(&gpd->vertex_group_names, def_nr)) {
return;
}
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
bGPDframe *init_gpf = static_cast<bGPDframe *>((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 == nullptr) {
continue;
}
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
}
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
if (gps->dvert == nullptr) {
continue;
}
MDeformVert *dvert = &gps->dvert[i];
if ((pt->flag & GP_SPOINT_SELECT) && (dvert->totweight > 0)) {
MDeformWeight *dw = BKE_defvert_find_index(dvert, def_nr);
if (dw != nullptr) {
BKE_defvert_remove_group(dvert, dw);
}
}
}
}
}
/* If not multi-edit, exit loop. */
if (!is_multiedit) {
break;
}
}
}
CTX_DATA_END;
}
void ED_gpencil_vgroup_select(bContext *C, Object *ob)
{
bGPdata *gpd = (bGPdata *)ob->data;
const bool is_multiedit = bool(GPENCIL_MULTIEDIT_SESSIONS_ON(gpd));
const int def_nr = gpd->vertex_group_active_index - 1;
if (!BLI_findlink(&gpd->vertex_group_names, def_nr)) {
return;
}
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
bGPDframe *init_gpf = static_cast<bGPDframe *>((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 == nullptr) {
continue;
}
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
}
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
if (gps->dvert == nullptr) {
continue;
}
MDeformVert *dvert = &gps->dvert[i];
if (BKE_defvert_find_index(dvert, def_nr) != nullptr) {
pt->flag |= GP_SPOINT_SELECT;
gps->flag |= GP_STROKE_SELECT;
}
}
if (gps->flag & GP_STROKE_SELECT) {
BKE_gpencil_stroke_select_index_set(gpd, gps);
}
}
}
/* If not multi-edit, exit loop. */
if (!is_multiedit) {
break;
}
}
}
CTX_DATA_END;
}
void ED_gpencil_vgroup_deselect(bContext *C, Object *ob)
{
bGPdata *gpd = (bGPdata *)ob->data;
const bool is_multiedit = bool(GPENCIL_MULTIEDIT_SESSIONS_ON(gpd));
const int def_nr = gpd->vertex_group_active_index - 1;
if (!BLI_findlink(&gpd->vertex_group_names, def_nr)) {
return;
}
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
bGPDframe *init_gpf = static_cast<bGPDframe *>((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 == nullptr) {
continue;
}
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
}
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
if (gps->dvert == nullptr) {
continue;
}
MDeformVert *dvert = &gps->dvert[i];
if (BKE_defvert_find_index(dvert, def_nr) != nullptr) {
pt->flag &= ~GP_SPOINT_SELECT;
}
}
}
}
/* If not multi-edit, exit loop. */
if (!is_multiedit) {
break;
}
}
}
CTX_DATA_END;
}
/* ******************************************************** */
/* Cursor drawing */
/* check if cursor is in drawing region */
static bool gpencil_check_cursor_region(bContext *C, const int mval_i[2])
{
ARegion *region = CTX_wm_region(C);
ScrArea *area = CTX_wm_area(C);
Object *ob = CTX_data_active_object(C);
if ((ob == nullptr) || ((ob->mode & OB_MODE_ALL_PAINT_GPENCIL) == 0)) {
return false;
}
/* TODO: add more space-types. */
if (!ELEM(area->spacetype, SPACE_VIEW3D)) {
return false;
}
if ((region) && (region->regiontype != RGN_TYPE_WINDOW)) {
return false;
}
if (region) {
return BLI_rcti_isect_pt_v(&region->winrct, mval_i);
}
return false;
}
void ED_gpencil_brush_draw_eraser(Brush *brush, int x, int y)
{
short radius = short(brush->size);
GPUVertFormat *format = immVertexFormat();
const uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
GPU_line_smooth(true);
GPU_blend(GPU_BLEND_ALPHA);
immUniformColor4ub(255, 100, 100, 20);
imm_draw_circle_fill_2d(shdr_pos, x, y, radius, 40);
immUnbindProgram();
immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
GPU_viewport_size_get_f(viewport_size);
immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
immUniformColor4f(1.0f, 0.39f, 0.39f, 0.78f);
immUniform1i("colors_len", 0); /* "simple" mode */
immUniform1f("dash_width", 12.0f);
immUniform1f("udash_factor", 0.5f);
imm_draw_circle_wire_2d(shdr_pos,
x,
y,
radius,
/* XXX Dashed shader gives bad results with sets of small segments
* currently, temp hack around the issue. :( */
max_ii(8, radius / 2)); /* was fixed 40 */
immUnbindProgram();
GPU_blend(GPU_BLEND_NONE);
GPU_line_smooth(false);
}
bool ED_gpencil_brush_cursor_poll(bContext *C)
{
if (WM_toolsystem_active_tool_is_brush(C) && !WM_toolsystem_active_tool_has_custom_cursor(C)) {
return true;
}
return false;
}
float ED_gpencil_cursor_radius(bContext *C, int x, int y)
{
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
ARegion *region = CTX_wm_region(C);
Brush *brush = BKE_paint_brush(&scene->toolsettings->gp_paint->paint);
bGPdata *gpd = ED_gpencil_data_get_active(C);
/* Show brush size. */
tGPspoint point2D;
float p1[3];
float p2[3];
float distance;
float radius = 2.0f;
if (ELEM(nullptr, gpd, brush)) {
return radius;
}
/* Strokes in screen space or world space? */
if ((gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS) != 0) {
/* In screen space the cursor radius matches the brush size. */
radius = float(brush->size) * 0.5f;
}
else {
/* To calculate the brush size in world space, we have to establish the zoom level.
* For this we take two 2D screen coordinates with a fixed offset,
* convert them to 3D coordinates and measure the offset distance in 3D.
* A small distance means a high zoom level. */
point2D.m_xy[0] = float(x);
point2D.m_xy[1] = float(y);
gpencil_stroke_convertcoords_tpoint(scene, region, ob, &point2D, nullptr, p1);
point2D.m_xy[0] = float(x + 64);
gpencil_stroke_convertcoords_tpoint(scene, region, ob, &point2D, nullptr, p2);
/* Clip extreme zoom level (and avoid division by zero). */
distance = std::max(len_v3v3(p1, p2), 0.001f);
/* Handle layer thickness change. */
float brush_size = float(brush->size);
bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
if (gpl != nullptr) {
brush_size = std::max(1.0f, brush_size + gpl->line_change);
}
/* Convert the 3D offset distance to a brush radius. */
radius = (1 / distance) * 2.0f * gpd->pixfactor * (brush_size / 64);
}
return radius;
}
float ED_gpencil_radial_control_scale(bContext *C,
Brush *brush,
float initial_value,
const int mval[2])
{
float scale_fac = 1.0f;
if ((brush && brush->gpencil_settings) && (brush->ob_mode == OB_MODE_PAINT_GREASE_PENCIL) &&
(brush->gpencil_brush_type == GPAINT_BRUSH_TYPE_DRAW))
{
float cursor_radius = ED_gpencil_cursor_radius(C, mval[0], mval[1]);
scale_fac = max_ff(cursor_radius, 1.0f) / max_ff(initial_value, 1.0f);
}
return scale_fac;
}
/**
* Helper callback for drawing the cursor itself.
*/
static void gpencil_brush_cursor_draw(bContext *C, int x, int y, void *customdata)
{
Scene *scene = CTX_data_scene(C);
ToolSettings *ts = scene->toolsettings;
Object *ob = CTX_data_active_object(C);
ARegion *region = CTX_wm_region(C);
Paint *paint = BKE_paint_get_active_from_context(C);
bGPdata *gpd = ED_gpencil_data_get_active(C);
Brush *brush = nullptr;
Material *ma = nullptr;
MaterialGPencilStyle *gp_style = nullptr;
float *last_mouse_position = static_cast<float *>(customdata);
/* default radius and color */
float color[3] = {1.0f, 1.0f, 1.0f};
float darkcolor[3];
float radius = 3.0f;
const int mval_i[2] = {x, y};
/* Check if cursor is in drawing region and has valid data-block. */
if (!gpencil_check_cursor_region(C, mval_i) || (gpd == nullptr)) {
return;
}
/* for paint use paint brush size and color */
if (gpd->flag & GP_DATA_STROKE_PAINTMODE) {
brush = BKE_paint_brush(&scene->toolsettings->gp_paint->paint);
if ((brush == nullptr) || (brush->gpencil_settings == nullptr)) {
return;
}
/* while drawing hide */
if ((gpd->runtime.sbuffer_used > 0) &&
((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0))
{
return;
}
if ((paint->flags & PAINT_SHOW_BRUSH) == 0) {
return;
}
/* eraser has special shape and use a different shader program */
if (brush->gpencil_brush_type == GPAINT_BRUSH_TYPE_ERASE) {
ED_gpencil_brush_draw_eraser(brush, x, y);
return;
}
/* get current drawing color */
ma = BKE_gpencil_object_material_from_brush_get(ob, brush);
if (ma) {
gp_style = ma->gp_style;
/* Follow user settings for the size of the draw cursor:
* - Fixed size, or
* - Brush size (i.e. stroke thickness)
*/
if ((gp_style) && GPENCIL_PAINT_MODE(gpd) &&
((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) &&
(brush->gpencil_brush_type == GPAINT_BRUSH_TYPE_DRAW))
{
const bool is_vertex_stroke =
(GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush) &&
(brush->gpencil_settings->brush_draw_mode != GP_BRUSH_MODE_MATERIAL)) ||
(!GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush) &&
(brush->gpencil_settings->brush_draw_mode == GP_BRUSH_MODE_VERTEXCOLOR));
/* Strokes in screen space or world space? */
if ((gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS) != 0) {
/* In screen space the cursor radius matches the brush size. */
radius = float(brush->size) * 0.5f;
}
else {
radius = ED_gpencil_cursor_radius(C, x, y);
}
copy_v3_v3(color, is_vertex_stroke ? brush->rgb : gp_style->stroke_rgba);
}
else {
/* Only Tint tool must show big cursor. */
if (brush->gpencil_brush_type == GPAINT_BRUSH_TYPE_TINT) {
radius = brush->size;
copy_v3_v3(color, brush->rgb);
}
else {
radius = 5.0f;
copy_v3_v3(color, brush->add_col);
}
}
}
}
/* Sculpt use sculpt brush size */
if (GPENCIL_SCULPT_MODE(gpd)) {
brush = BKE_paint_brush(&scene->toolsettings->gp_sculptpaint->paint);
if ((brush == nullptr) || (brush->gpencil_settings == nullptr)) {
return;
}
if ((paint->flags & PAINT_SHOW_BRUSH) == 0) {
return;
}
radius = brush->size;
if (brush->gpencil_settings->sculpt_flag & (GP_SCULPT_FLAG_INVERT | GP_SCULPT_FLAG_TMP_INVERT))
{
copy_v3_v3(color, brush->sub_col);
}
else {
copy_v3_v3(color, brush->add_col);
}
}
/* Weight Paint */
if (GPENCIL_WEIGHT_MODE(gpd)) {
brush = BKE_paint_brush(&scene->toolsettings->gp_weightpaint->paint);
if ((brush == nullptr) || (brush->gpencil_settings == nullptr)) {
return;
}
if ((paint->flags & PAINT_SHOW_BRUSH) == 0) {
return;
}
radius = brush->size;
if (brush->gpencil_settings->sculpt_flag & (GP_SCULPT_FLAG_INVERT | GP_SCULPT_FLAG_TMP_INVERT))
{
copy_v3_v3(color, brush->sub_col);
}
else {
copy_v3_v3(color, brush->add_col);
}
}
/* For Vertex Paint use brush size. */
if (GPENCIL_VERTEX_MODE(gpd)) {
brush = BKE_paint_brush(&scene->toolsettings->gp_vertexpaint->paint);
if ((brush == nullptr) || (brush->gpencil_settings == nullptr)) {
return;
}
if ((paint->flags & PAINT_SHOW_BRUSH) == 0) {
return;
}
radius = brush->size;
copy_v3_v3(color, brush->rgb);
}
/* draw icon */
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
GPU_line_smooth(true);
GPU_blend(GPU_BLEND_ALPHA);
/* Inner Ring: Color from UI panel */
immUniformColor4f(color[0], color[1], color[2], 0.8f);
imm_draw_circle_wire_2d(pos, x, y, radius, 40);
/* Outer Ring: Dark color for contrast on light backgrounds (e.g. gray on white) */
mul_v3_v3fl(darkcolor, color, 0.40f);
immUniformColor4f(darkcolor[0], darkcolor[1], darkcolor[2], 0.8f);
imm_draw_circle_wire_2d(pos, x, y, radius + 1, 40);
GPU_blend(GPU_BLEND_NONE);
GPU_line_smooth(false);
/* Draw line for lazy mouse */
if ((last_mouse_position) && (brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP)) {
GPU_line_smooth(true);
GPU_blend(GPU_BLEND_ALPHA);
copy_v3_v3(color, brush->add_col);
immUniformColor4f(color[0], color[1], color[2], 0.8f);
immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, x, y);
immVertex2f(pos,
last_mouse_position[0] + region->winrct.xmin,
last_mouse_position[1] + region->winrct.ymin);
immEnd();
GPU_blend(GPU_BLEND_NONE);
GPU_line_smooth(false);
}
immUnbindProgram();
}
void ED_gpencil_toggle_brush_cursor(bContext *C, bool enable, void *customdata)
{
Scene *scene = CTX_data_scene(C);
GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt;
float *lastpost = static_cast<float *>(customdata);
if (gset->paintcursor && !enable) {
/* clear cursor */
WM_paint_cursor_end(static_cast<wmPaintCursor *>(gset->paintcursor));
gset->paintcursor = nullptr;
}
else if (enable) {
/* in some situations cursor could be duplicated, so it is better disable first if exist */
if (gset->paintcursor) {
/* clear cursor */
WM_paint_cursor_end(static_cast<wmPaintCursor *>(gset->paintcursor));
gset->paintcursor = nullptr;
}
/* enable cursor */
gset->paintcursor = WM_paint_cursor_activate(SPACE_TYPE_ANY,
RGN_TYPE_ANY,
ED_gpencil_brush_cursor_poll,
gpencil_brush_cursor_draw,
(lastpost) ? customdata : nullptr);
}
}
void ED_gpencil_setup_modes(bContext *C, bGPdata *gpd, int newmode)
{
if (!gpd) {
return;
}
switch (newmode) {
case OB_MODE_EDIT_GPENCIL_LEGACY:
gpd->flag |= GP_DATA_STROKE_EDITMODE;
gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
gpd->flag &= ~GP_DATA_STROKE_VERTEXMODE;
ED_gpencil_toggle_brush_cursor(C, false, nullptr);
break;
case OB_MODE_PAINT_GREASE_PENCIL:
gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
gpd->flag |= GP_DATA_STROKE_PAINTMODE;
gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
gpd->flag &= ~GP_DATA_STROKE_VERTEXMODE;
ED_gpencil_toggle_brush_cursor(C, true, nullptr);
break;
case OB_MODE_SCULPT_GREASE_PENCIL:
gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
gpd->flag |= GP_DATA_STROKE_SCULPTMODE;
gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
gpd->flag &= ~GP_DATA_STROKE_VERTEXMODE;
ED_gpencil_toggle_brush_cursor(C, true, nullptr);
break;
case OB_MODE_WEIGHT_GREASE_PENCIL:
gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
gpd->flag |= GP_DATA_STROKE_WEIGHTMODE;
gpd->flag &= ~GP_DATA_STROKE_VERTEXMODE;
ED_gpencil_toggle_brush_cursor(C, true, nullptr);
break;
case OB_MODE_VERTEX_GREASE_PENCIL:
gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
gpd->flag |= GP_DATA_STROKE_VERTEXMODE;
ED_gpencil_toggle_brush_cursor(C, true, nullptr);
break;
default:
gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
gpd->flag &= ~GP_DATA_STROKE_VERTEXMODE;
ED_gpencil_toggle_brush_cursor(C, false, nullptr);
break;
}
}
/** /**
* Helper to convert 2d to 3d for simple drawing buffer. * Helper to convert 2d to 3d for simple drawing buffer.
*/ */
@@ -2121,602 +450,6 @@ void ED_gpencil_tpoint_to_point(ARegion *region,
pt->uv_rot = tpt->uv_rot; pt->uv_rot = tpt->uv_rot;
} }
void ED_gpencil_update_color_uv(Main *bmain, Material *mat)
{
Material *gps_ma = nullptr;
/* Read all strokes. */
for (Object *ob = static_cast<Object *>(bmain->objects.first); ob;
ob = static_cast<Object *>(ob->id.next))
{
if (ob->type == OB_GPENCIL_LEGACY) {
bGPdata *gpd = static_cast<bGPdata *>(ob->data);
if (gpd == nullptr) {
continue;
}
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
if (BKE_gpencil_layer_is_editable(gpl)) {
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* check if it is editable */
if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) {
continue;
}
gps_ma = BKE_gpencil_material(ob, gps->mat_nr + 1);
/* update */
if ((gps_ma) && (gps_ma == mat)) {
BKE_gpencil_stroke_uv_update(gps);
}
}
}
}
}
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
}
}
}
static bool gpencil_check_collision(bGPDstroke *gps,
bGPDstroke **gps_array,
GHash *all_2d,
int totstrokes,
const float p2d_a1[2],
const float p2d_a2[2],
float r_hit[2])
{
bool hit = false;
/* check segment with all segments of all strokes */
for (int s = 0; s < totstrokes; s++) {
bGPDstroke *gps_iter = gps_array[s];
if (gps_iter->totpoints < 2) {
continue;
}
/* get stroke 2d version */
float(*points2d)[2] = static_cast<float(*)[2]>(BLI_ghash_lookup(all_2d, gps_iter));
for (int i2 = 0; i2 < gps_iter->totpoints - 1; i2++) {
float p2d_b1[2], p2d_b2[2];
copy_v2_v2(p2d_b1, points2d[i2]);
copy_v2_v2(p2d_b2, points2d[i2 + 1]);
/* don't self check */
if (gps == gps_iter) {
if (equals_v2v2(p2d_a1, p2d_b1) || equals_v2v2(p2d_a1, p2d_b2)) {
continue;
}
if (equals_v2v2(p2d_a2, p2d_b1) || equals_v2v2(p2d_a2, p2d_b2)) {
continue;
}
}
/* check collision */
int check = isect_seg_seg_v2_point(p2d_a1, p2d_a2, p2d_b1, p2d_b2, r_hit);
if (check > 0) {
hit = true;
break;
}
}
if (hit) {
break;
}
}
if (!hit) {
zero_v2(r_hit);
}
return hit;
}
static void gpencil_copy_points(
bGPDstroke *gps, bGPDspoint *pt, bGPDspoint *pt_final, int i, int i2)
{
/* don't copy same point */
if (i == i2) {
return;
}
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;
copy_v4_v4(pt_final->vert_color, pt->vert_color);
if (gps->dvert != nullptr) {
MDeformVert *dvert = &gps->dvert[i];
MDeformVert *dvert_final = &gps->dvert[i2];
MEM_SAFE_FREE(dvert_final->dw);
dvert_final->totweight = dvert->totweight;
if (dvert->dw == nullptr) {
dvert_final->dw = nullptr;
dvert_final->totweight = 0;
}
else {
dvert_final->dw = static_cast<MDeformWeight *>(MEM_dupallocN(dvert->dw));
}
}
}
static void gpencil_insert_point(bGPdata *gpd,
bGPDstroke *gps,
bGPDspoint *a_pt,
bGPDspoint *b_pt,
const float co_a[3],
const float co_b[3])
{
bGPDspoint *temp_points;
int totnewpoints, oldtotpoints;
totnewpoints = gps->totpoints;
if (a_pt) {
totnewpoints++;
}
if (b_pt) {
totnewpoints++;
}
/* duplicate points in a temp area */
temp_points = static_cast<bGPDspoint *>(MEM_dupallocN(gps->points));
oldtotpoints = gps->totpoints;
/* look index of base points because memory is changed when resize points array */
int a_idx = -1;
int b_idx = -1;
for (int i = 0; i < oldtotpoints; i++) {
bGPDspoint *pt = &gps->points[i];
if (pt == a_pt) {
a_idx = i;
}
if (pt == b_pt) {
b_idx = i;
}
}
/* resize the points arrays */
gps->totpoints = totnewpoints;
gps->points = static_cast<bGPDspoint *>(
MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints));
if (gps->dvert != nullptr) {
gps->dvert = static_cast<MDeformVert *>(
MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints));
}
/* copy all points */
int i2 = 0;
for (int i = 0; i < oldtotpoints; i++) {
bGPDspoint *pt = &temp_points[i];
bGPDspoint *pt_final = &gps->points[i2];
gpencil_copy_points(gps, pt, pt_final, i, i2);
/* create new point duplicating point and copy location */
if (ELEM(i, a_idx, b_idx)) {
i2++;
pt_final = &gps->points[i2];
gpencil_copy_points(gps, pt, pt_final, i, i2);
copy_v3_v3(&pt_final->x, (i == a_idx) ? co_a : co_b);
/* Un-select. */
pt_final->flag &= ~GP_SPOINT_SELECT;
/* tag to avoid more checking with this point */
pt_final->flag |= GP_SPOINT_TAG;
}
i2++;
}
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gpd, gps);
MEM_SAFE_FREE(temp_points);
}
static float gpencil_calc_factor(const float p2d_a1[2],
const float p2d_a2[2],
const float r_hit2d[2])
{
float dist1 = len_squared_v2v2(p2d_a1, p2d_a2);
float dist2 = len_squared_v2v2(p2d_a1, r_hit2d);
float f = dist1 > 0.0f ? dist2 / dist1 : 0.0f;
/* apply a correction factor */
float v1[2];
interp_v2_v2v2(v1, p2d_a1, p2d_a2, f);
float dist3 = len_squared_v2v2(p2d_a1, v1);
float f1 = dist1 > 0.0f ? dist3 / dist1 : 0.0f;
f = f + (f - f1);
return f;
}
int ED_gpencil_select_stroke_segment(bGPdata *gpd,
bGPDlayer *gpl,
bGPDstroke *gps,
bGPDspoint *pt,
bool select,
bool insert,
const float scale,
float r_hita[3],
float r_hitb[3])
{
if (gps->totpoints < 2) {
return 0;
}
const float min_factor = 0.0015f;
bGPDspoint *pta1 = nullptr;
bGPDspoint *pta2 = nullptr;
float f = 0.0f;
int i2 = 0;
bGPDlayer *gpl_orig = (gpl->runtime.gpl_orig) ? gpl->runtime.gpl_orig : gpl;
bGPDframe *gpf = gpl_orig->actframe;
if (gpf == nullptr) {
return 0;
}
int memsize = BLI_listbase_count(&gpf->strokes);
bGPDstroke **gps_array = static_cast<bGPDstroke **>(
MEM_callocN(sizeof(bGPDstroke *) * memsize, __func__));
/* save points */
bGPDspoint *oldpoints = static_cast<bGPDspoint *>(MEM_dupallocN(gps->points));
/* Save list of strokes to check */
int totstrokes = 0;
LISTBASE_FOREACH (bGPDstroke *, gps_iter, &gpf->strokes) {
if (gps_iter->totpoints < 2) {
continue;
}
gps_array[totstrokes] = gps_iter;
totstrokes++;
}
if (totstrokes == 0) {
return 0;
}
/* look for index of the current point */
int cur_idx = -1;
for (int i = 0; i < gps->totpoints; i++) {
pta1 = &gps->points[i];
if (pta1 == pt) {
cur_idx = i;
break;
}
}
if (cur_idx < 0) {
return 0;
}
/* Convert all gps points to 2d and save in a hash to avoid recalculation. */
int direction = 0;
float(*points2d)[2] = static_cast<float(*)[2]>(
MEM_mallocN(sizeof(*points2d) * gps->totpoints, "GP Stroke temp 2d points"));
BKE_gpencil_stroke_2d_flat_ref(
gps->points, gps->totpoints, gps->points, gps->totpoints, points2d, scale, &direction);
GHash *all_2d = BLI_ghash_ptr_new(__func__);
for (int s = 0; s < totstrokes; s++) {
bGPDstroke *gps_iter = gps_array[s];
float(*points2d_iter)[2] = static_cast<float(*)[2]>(
MEM_mallocN(sizeof(*points2d_iter) * gps_iter->totpoints, __func__));
/* the extremes of the stroke are scaled to improve collision detection
* for near lines */
BKE_gpencil_stroke_2d_flat_ref(gps->points,
gps->totpoints,
gps_iter->points,
gps_iter->totpoints,
points2d_iter,
scale,
&direction);
BLI_ghash_insert(all_2d, gps_iter, points2d_iter);
}
bool hit_a = false;
bool hit_b = false;
float p2d_a1[2] = {0.0f, 0.0f};
float p2d_a2[2] = {0.0f, 0.0f};
float r_hit2d[2];
bGPDspoint *hit_pointa = nullptr;
bGPDspoint *hit_pointb = nullptr;
/* analyze points before current */
if (cur_idx > 0) {
for (int i = cur_idx; i >= 0; i--) {
pta1 = &gps->points[i];
copy_v2_v2(p2d_a1, points2d[i]);
i2 = i - 1;
CLAMP_MIN(i2, 0);
pta2 = &gps->points[i2];
copy_v2_v2(p2d_a2, points2d[i2]);
hit_a = gpencil_check_collision(gps, gps_array, all_2d, totstrokes, p2d_a1, p2d_a2, r_hit2d);
if (select) {
pta1->flag |= GP_SPOINT_SELECT;
}
else {
pta1->flag &= ~GP_SPOINT_SELECT;
}
if (hit_a) {
f = gpencil_calc_factor(p2d_a1, p2d_a2, r_hit2d);
interp_v3_v3v3(r_hita, &pta1->x, &pta2->x, f);
if (f > min_factor) {
hit_pointa = pta2; /* first point is second (inverted loop) */
}
else {
pta1->flag &= ~GP_SPOINT_SELECT;
}
break;
}
}
}
/* analyze points after current */
for (int i = cur_idx; i < gps->totpoints; i++) {
pta1 = &gps->points[i];
copy_v2_v2(p2d_a1, points2d[i]);
i2 = i + 1;
CLAMP_MAX(i2, gps->totpoints - 1);
pta2 = &gps->points[i2];
copy_v2_v2(p2d_a2, points2d[i2]);
hit_b = gpencil_check_collision(gps, gps_array, all_2d, totstrokes, p2d_a1, p2d_a2, r_hit2d);
if (select) {
pta1->flag |= GP_SPOINT_SELECT;
}
else {
pta1->flag &= ~GP_SPOINT_SELECT;
}
if (hit_b) {
f = gpencil_calc_factor(p2d_a1, p2d_a2, r_hit2d);
interp_v3_v3v3(r_hitb, &pta1->x, &pta2->x, f);
if (f > min_factor) {
hit_pointb = pta1;
}
else {
pta1->flag &= ~GP_SPOINT_SELECT;
}
break;
}
}
/* insert new point in the collision points */
if (insert) {
gpencil_insert_point(gpd, gps, hit_pointa, hit_pointb, r_hita, r_hitb);
}
/* free memory */
if (all_2d) {
GHashIterator gh_iter;
GHASH_ITER (gh_iter, all_2d) {
float(*p2d)[2] = static_cast<float(*)[2]>(BLI_ghashIterator_getValue(&gh_iter));
MEM_SAFE_FREE(p2d);
}
BLI_ghash_free(all_2d, nullptr, nullptr);
}
/* if no hit, reset selection flag */
if ((!hit_a) && (!hit_b)) {
for (int i = 0; i < gps->totpoints; i++) {
pta1 = &gps->points[i];
pta2 = &oldpoints[i];
pta1->flag = pta2->flag;
}
}
MEM_SAFE_FREE(points2d);
MEM_SAFE_FREE(gps_array);
MEM_SAFE_FREE(oldpoints);
/* return type of hit */
if ((hit_a) && (hit_b)) {
return 3;
}
if (hit_a) {
return 1;
}
if (hit_b) {
return 2;
}
return 0;
}
void ED_gpencil_select_toggle_all(bContext *C, int action)
{
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = static_cast<bGPdata *>(ob->data);
/* for "toggle", test for existing selected strokes */
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
if (gps->flag & GP_STROKE_SELECT) {
action = SEL_DESELECT;
break; /* XXX: this only gets out of the inner loop. */
}
}
CTX_DATA_END;
}
/* if deselecting, we need to deselect strokes across all frames
* - Currently, an exception is only given for deselection
* Selecting and toggling should only affect what's visible,
* while deselecting helps clean up unintended/forgotten
* stuff on other frames
*/
if (action == SEL_DESELECT) {
/* deselect strokes across editable layers
* NOTE: we limit ourselves to editable layers, since once a layer is "locked/hidden
* nothing should be able to touch it
*/
/* Set selection index to 0. */
gpd->select_last_index = 0;
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
/* deselect all strokes on all frames */
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
bGPDspoint *pt;
int i;
/* only edit strokes that are valid in this view... */
if (ED_gpencil_stroke_can_use(C, gps)) {
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
pt->flag &= ~GP_SPOINT_SELECT;
}
gps->flag &= ~GP_STROKE_SELECT;
BKE_gpencil_stroke_select_index_reset(gps);
}
}
}
}
CTX_DATA_END;
}
else {
/* select or deselect all strokes */
CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
bGPDspoint *pt;
int i;
bool selected = false;
/* Change selection status of all points, then make the stroke match */
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
switch (action) {
case SEL_SELECT:
pt->flag |= GP_SPOINT_SELECT;
break;
#if 0
case SEL_DESELECT:
pt->flag &= ~GP_SPOINT_SELECT;
break;
#endif
case SEL_INVERT:
pt->flag ^= GP_SPOINT_SELECT;
break;
}
if (pt->flag & GP_SPOINT_SELECT) {
selected = true;
}
}
/* Change status of stroke */
if (selected) {
gps->flag |= GP_STROKE_SELECT;
BKE_gpencil_stroke_select_index_set(gpd, gps);
}
else {
gps->flag &= ~GP_STROKE_SELECT;
BKE_gpencil_stroke_select_index_reset(gps);
}
}
CTX_DATA_END;
}
}
void ED_gpencil_select_curve_toggle_all(bContext *C, int action)
{
/* if toggle, check if we need to select or deselect */
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc)
{
if (gpc->flag & GP_CURVE_SELECT) {
action = SEL_DESELECT;
}
}
GP_EDITABLE_CURVES_END(gps_iter);
}
if (action == SEL_DESELECT) {
/* Set selection index to 0. */
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = static_cast<bGPdata *>(ob->data);
gpd->select_last_index = 0;
GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc)
{
for (int i = 0; i < gpc->tot_curve_points; i++) {
bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
BezTriple *bezt = &gpc_pt->bezt;
gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
BEZT_DESEL_ALL(bezt);
}
gpc->flag &= ~GP_CURVE_SELECT;
gps->flag &= ~GP_STROKE_SELECT;
BKE_gpencil_stroke_select_index_reset(gps);
}
GP_EDITABLE_CURVES_END(gps_iter);
}
else {
GP_EDITABLE_STROKES_BEGIN (gps_iter, C, gpl, gps) {
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = static_cast<bGPdata *>(ob->data);
bool selected = false;
/* Make sure stroke has an editcurve */
if (gps->editcurve == nullptr) {
BKE_gpencil_stroke_editcurve_update(gpd, gpl, gps);
gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
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;
switch (action) {
case SEL_SELECT:
gpc_pt->flag |= GP_CURVE_POINT_SELECT;
BEZT_SEL_ALL(bezt);
break;
case SEL_INVERT:
gpc_pt->flag ^= GP_CURVE_POINT_SELECT;
if (gpc_pt->flag & GP_CURVE_POINT_SELECT) {
BEZT_SEL_ALL(bezt);
}
else {
BEZT_DESEL_ALL(bezt);
}
break;
default:
break;
}
if (gpc_pt->flag & GP_CURVE_POINT_SELECT) {
selected = true;
}
}
if (selected) {
gpc->flag |= GP_CURVE_SELECT;
gps->flag |= GP_STROKE_SELECT;
BKE_gpencil_stroke_select_index_set(gpd, gps);
}
else {
gpc->flag &= ~GP_CURVE_SELECT;
gps->flag &= ~GP_STROKE_SELECT;
BKE_gpencil_stroke_select_index_reset(gps);
}
}
GP_EDITABLE_STROKES_END(gps_iter);
}
}
tGPspoint *ED_gpencil_sbuffer_ensure(tGPspoint *buffer_array, tGPspoint *ED_gpencil_sbuffer_ensure(tGPspoint *buffer_array,
int *buffer_size, int *buffer_size,
int *buffer_used, int *buffer_used,
@@ -2755,680 +488,3 @@ tGPspoint *ED_gpencil_sbuffer_ensure(tGPspoint *buffer_array,
return buffer_array; return buffer_array;
} }
void ED_gpencil_sbuffer_update_eval(bGPdata *gpd, Object *ob_eval)
{
bGPdata *gpd_eval = (bGPdata *)ob_eval->data;
gpd_eval->runtime.sbuffer = gpd->runtime.sbuffer;
gpd_eval->runtime.sbuffer_sflag = gpd->runtime.sbuffer_sflag;
gpd_eval->runtime.sbuffer_used = gpd->runtime.sbuffer_used;
gpd_eval->runtime.sbuffer_size = gpd->runtime.sbuffer_size;
gpd_eval->runtime.tot_cp_points = gpd->runtime.tot_cp_points;
gpd_eval->runtime.cp_points = gpd->runtime.cp_points;
}
void ED_gpencil_tag_scene_gpencil(Scene *scene)
{
/* Mark all grease pencil data-blocks of the scene. */
FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) {
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection, ob) {
if (ob->type == OB_GPENCIL_LEGACY) {
bGPdata *gpd = (bGPdata *)ob->data;
gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
}
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
FOREACH_SCENE_COLLECTION_END;
DEG_id_tag_update(&scene->id, ID_RECALC_SYNC_TO_EVAL);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, nullptr);
}
void ED_gpencil_fill_vertex_color_set(ToolSettings *ts, Brush *brush, bGPDstroke *gps)
{
const bool is_vertex = (GPENCIL_USE_VERTEX_COLOR_FILL(ts, brush) &&
(brush->gpencil_settings->brush_draw_mode != GP_BRUSH_MODE_MATERIAL)) ||
(!GPENCIL_USE_VERTEX_COLOR_FILL(ts, brush) &&
(brush->gpencil_settings->brush_draw_mode == GP_BRUSH_MODE_VERTEXCOLOR));
if (is_vertex) {
copy_v3_v3(gps->vert_color_fill, brush->rgb);
gps->vert_color_fill[3] = brush->gpencil_settings->vertex_factor;
srgb_to_linearrgb_v4(gps->vert_color_fill, gps->vert_color_fill);
}
else {
zero_v4(gps->vert_color_fill);
}
}
void ED_gpencil_point_vertex_color_set(ToolSettings *ts,
Brush *brush,
bGPDspoint *pt,
tGPspoint *tpt)
{
const bool is_vertex = (GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush) &&
(brush->gpencil_settings->brush_draw_mode != GP_BRUSH_MODE_MATERIAL)) ||
(!GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush) &&
(brush->gpencil_settings->brush_draw_mode == GP_BRUSH_MODE_VERTEXCOLOR));
if (is_vertex) {
if (tpt == nullptr) {
copy_v3_v3(pt->vert_color, brush->rgb);
pt->vert_color[3] = brush->gpencil_settings->vertex_factor;
srgb_to_linearrgb_v4(pt->vert_color, pt->vert_color);
}
else {
copy_v3_v3(pt->vert_color, tpt->vert_color);
pt->vert_color[3] = brush->gpencil_settings->vertex_factor;
}
}
else {
zero_v4(pt->vert_color);
}
}
void ED_gpencil_init_random_settings(Brush *brush,
const int mval[2],
GpRandomSettings *random_settings)
{
int seed = (uint(ceil(BLI_time_now_seconds())) + 1) % 128;
/* Use mouse position to get randomness. */
int ix = mval[0] * seed;
int iy = mval[1] * seed;
int iz = ix + iy * seed;
zero_v3(random_settings->hsv);
BrushGpencilSettings *brush_settings = brush->gpencil_settings;
/* Random to Hue. */
if (brush_settings->random_hue > 0.0f) {
float rand = BLI_hash_int_01(BLI_hash_int_2d(ix, iy)) * 2.0f - 1.0f;
random_settings->hsv[0] = rand * brush_settings->random_hue * 0.5f;
}
/* Random to Saturation. */
if (brush_settings->random_saturation > 0.0f) {
float rand = BLI_hash_int_01(BLI_hash_int_2d(iy, ix)) * 2.0f - 1.0f;
random_settings->hsv[1] = rand * brush_settings->random_saturation;
}
/* Random to Value. */
if (brush_settings->random_value > 0.0f) {
float rand = BLI_hash_int_01(BLI_hash_int_2d(ix * iz, iy * iz)) * 2.0f - 1.0f;
random_settings->hsv[2] = rand * brush_settings->random_value;
}
/* Random to pressure. */
if (brush_settings->draw_random_press > 0.0f) {
random_settings->pressure = BLI_hash_int_01(BLI_hash_int_2d(ix + iz, iy + iz)) * 2.0f - 1.0f;
}
/* Random to color strength. */
if (brush_settings->draw_random_strength) {
random_settings->strength = BLI_hash_int_01(BLI_hash_int_2d(ix + iy, iy + iz + ix)) * 2.0f -
1.0f;
}
/* Random to uv texture rotation. */
if (brush_settings->uv_random > 0.0f) {
random_settings->uv = BLI_hash_int_01(BLI_hash_int_2d(iy + iz, ix * iz)) * 2.0f - 1.0f;
}
}
static void gpencil_sbuffer_vertex_color_random(
bGPdata *gpd, Brush *brush, tGPspoint *tpt, const float random_color[3], float pen_pressure)
{
BrushGpencilSettings *brush_settings = brush->gpencil_settings;
if (brush_settings->flag & GP_BRUSH_GROUP_RANDOM) {
int seed = (uint(ceil(BLI_time_now_seconds())) + 1) % 128;
int ix = int(tpt->m_xy[0] * seed);
int iy = int(tpt->m_xy[1] * seed);
int iz = ix + iy * seed;
blender::float3 hsv;
float factor_value[3];
zero_v3(factor_value);
/* Apply randomness to Hue. */
if (brush_settings->random_hue > 0.0f) {
if ((brush_settings->flag2 & GP_BRUSH_USE_HUE_AT_STROKE) == 0) {
float rand = BLI_hash_int_01(BLI_hash_int_2d(ix, gpd->runtime.sbuffer_used)) * 2.0f - 1.0f;
factor_value[0] = rand * brush_settings->random_hue * 0.5f;
}
else {
factor_value[0] = random_color[0];
}
/* Apply random curve. */
if (brush_settings->flag2 & GP_BRUSH_USE_HUE_RAND_PRESS) {
factor_value[0] *= BKE_curvemapping_evaluateF(
brush_settings->curve_rand_hue, 0, pen_pressure);
}
}
/* Apply randomness to Saturation. */
if (brush_settings->random_saturation > 0.0f) {
if ((brush_settings->flag2 & GP_BRUSH_USE_SAT_AT_STROKE) == 0) {
float rand = BLI_hash_int_01(BLI_hash_int_2d(iy, gpd->runtime.sbuffer_used)) * 2.0f - 1.0f;
factor_value[1] = rand * brush_settings->random_saturation;
}
else {
factor_value[1] = random_color[1];
}
/* Apply random curve. */
if (brush_settings->flag2 & GP_BRUSH_USE_SAT_RAND_PRESS) {
factor_value[1] *= BKE_curvemapping_evaluateF(
brush_settings->curve_rand_saturation, 0, pen_pressure);
}
}
/* Apply randomness to Value. */
if (brush_settings->random_value > 0.0f) {
if ((brush_settings->flag2 & GP_BRUSH_USE_VAL_AT_STROKE) == 0) {
float rand = BLI_hash_int_01(BLI_hash_int_2d(iz, gpd->runtime.sbuffer_used)) * 2.0f - 1.0f;
factor_value[2] = rand * brush_settings->random_value;
}
else {
factor_value[2] = random_color[2];
}
/* Apply random curve. */
if (brush_settings->flag2 & GP_BRUSH_USE_VAL_RAND_PRESS) {
factor_value[2] *= BKE_curvemapping_evaluateF(
brush_settings->curve_rand_value, 0, pen_pressure);
}
}
rgb_to_hsv_v(tpt->vert_color, hsv);
add_v3_v3(hsv, factor_value);
/* For Hue need to cover all range, but for Saturation and Value
* is not logic because the effect is too hard, so the value is just clamped. */
if (hsv[0] < 0.0f) {
hsv[0] += 1.0f;
}
else if (hsv[0] > 1.0f) {
hsv[0] -= 1.0f;
}
hsv = blender::math::clamp(hsv, 0.0f, 1.0f);
hsv_to_rgb_v(hsv, tpt->vert_color);
}
}
void ED_gpencil_sbuffer_vertex_color_set(Depsgraph *depsgraph,
Object *ob,
ToolSettings *ts,
Brush *brush,
Material *material,
float random_color[3],
float pen_pressure)
{
bGPdata *gpd = (bGPdata *)ob->data;
Object *ob_eval = (Object *)DEG_get_evaluated_id(depsgraph, &ob->id);
bGPdata *gpd_eval = (bGPdata *)ob_eval->data;
MaterialGPencilStyle *gp_style = material->gp_style;
const bool is_vertex_fill =
(GPENCIL_USE_VERTEX_COLOR_FILL(ts, brush) &&
(brush->gpencil_settings->brush_draw_mode != GP_BRUSH_MODE_MATERIAL)) ||
(!GPENCIL_USE_VERTEX_COLOR_FILL(ts, brush) &&
(brush->gpencil_settings->brush_draw_mode == GP_BRUSH_MODE_VERTEXCOLOR));
const bool is_vertex_stroke =
(GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush) &&
(brush->gpencil_settings->brush_draw_mode != GP_BRUSH_MODE_MATERIAL)) ||
(!GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush) &&
(brush->gpencil_settings->brush_draw_mode == GP_BRUSH_MODE_VERTEXCOLOR));
int idx = gpd->runtime.sbuffer_used;
tGPspoint *tpt = (tGPspoint *)gpd->runtime.sbuffer + idx;
float vertex_color[4];
copy_v3_v3(vertex_color, brush->rgb);
vertex_color[3] = brush->gpencil_settings->vertex_factor;
srgb_to_linearrgb_v4(vertex_color, vertex_color);
/* Copy fill vertex color. */
if (is_vertex_fill) {
copy_v4_v4(gpd->runtime.vert_color_fill, vertex_color);
}
else {
copy_v4_v4(gpd->runtime.vert_color_fill, gp_style->fill_rgba);
}
/* Copy stroke vertex color. */
if (is_vertex_stroke) {
copy_v4_v4(tpt->vert_color, vertex_color);
}
else {
copy_v4_v4(tpt->vert_color, gp_style->stroke_rgba);
}
/* Random Color. */
gpencil_sbuffer_vertex_color_random(gpd, brush, tpt, random_color, pen_pressure);
/* Copy to evaluate data because paint operators don't tag refresh until end for speedup
* painting. */
if (gpd_eval != nullptr) {
copy_v4_v4(gpd_eval->runtime.vert_color_fill, gpd->runtime.vert_color_fill);
gpd_eval->runtime.matid = gpd->runtime.matid;
gpd_eval->runtime.fill_opacity_fac = gpd->runtime.fill_opacity_fac;
}
}
void ED_gpencil_projected_2d_bound_box(const GP_SpaceConversion *gsc,
const bGPDstroke *gps,
const float diff_mat[4][4],
float r_min[2],
float r_max[2])
{
float bounds[8][2];
BoundBox bb;
BKE_boundbox_init_from_minmax(&bb, gps->boundbox_min, gps->boundbox_max);
/* Project 8 vertices in 2D. */
for (int i = 0; i < 8; i++) {
bGPDspoint pt_dummy, pt_dummy_ps;
copy_v3_v3(&pt_dummy.x, bb.vec[i]);
gpencil_point_to_world_space(&pt_dummy, diff_mat, &pt_dummy_ps);
gpencil_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &bounds[i][0], &bounds[i][1]);
}
/* Take extremes. */
INIT_MINMAX2(r_min, r_max);
for (int i = 0; i < 8; i++) {
minmax_v2v2_v2(r_min, r_max, bounds[i]);
}
/* Ensure the bounding box is oriented to axis. */
if (r_max[0] < r_min[0]) {
std::swap(r_min[0], r_max[0]);
}
if (r_max[1] < r_min[1]) {
std::swap(r_min[1], r_max[1]);
}
}
bool ED_gpencil_stroke_check_collision(const GP_SpaceConversion *gsc,
bGPDstroke *gps,
const float mval[2],
const int radius,
const float diff_mat[4][4])
{
const int offset = int(ceil(sqrt((radius * radius) * 2)));
float boundbox_min[2];
float boundbox_max[2];
/* Check we have something to use (only for old files). */
if (is_zero_v3(gps->boundbox_min)) {
BKE_gpencil_stroke_boundingbox_calc(gps);
}
ED_gpencil_projected_2d_bound_box(gsc, gps, diff_mat, boundbox_min, boundbox_max);
rcti rect_stroke = {
int(boundbox_min[0]), int(boundbox_max[0]), int(boundbox_min[1]), int(boundbox_max[1])};
/* For mouse, add a small offset to avoid false negative in corners. */
rcti rect_mouse = {
int(mval[0]) - offset, int(mval[0]) + offset, int(mval[1]) - offset, int(mval[1]) + offset};
/* Check collision between both rectangles. */
return BLI_rcti_isect(&rect_stroke, &rect_mouse, nullptr);
}
bool ED_gpencil_stroke_point_is_inside(const bGPDstroke *gps,
const GP_SpaceConversion *gsc,
const int mval[2],
const float diff_mat[4][4])
{
bool hit = false;
if (gps->totpoints == 0) {
return hit;
}
int len = gps->totpoints;
blender::Array<blender::int2> mcoords(len);
/* Convert stroke to 2D array of points. */
const bGPDspoint *pt;
int i;
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
bGPDspoint pt2;
gpencil_point_to_world_space(pt, diff_mat, &pt2);
gpencil_point_to_xy(gsc, gps, &pt2, &mcoords[i][0], &mcoords[i][1]);
}
/* Compute bound-box of lasso (for faster testing later). */
rcti rect;
BLI_lasso_boundbox(&rect, mcoords);
/* Test if point inside stroke. */
hit = (!ELEM(V2D_IS_CLIPPED, mval[0], mval[1]) && BLI_rcti_isect_pt(&rect, mval[0], mval[1]) &&
BLI_lasso_is_point_inside(mcoords, mval[0], mval[1], INT_MAX));
return hit;
}
void ED_gpencil_stroke_extremes_to2d(const GP_SpaceConversion *gsc,
const float diff_mat[4][4],
bGPDstroke *gps,
float r_ctrl1[2],
float r_ctrl2[2])
{
bGPDspoint pt_dummy_ps;
gpencil_point_to_world_space(&gps->points[0], diff_mat, &pt_dummy_ps);
gpencil_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &r_ctrl1[0], &r_ctrl1[1]);
gpencil_point_to_world_space(&gps->points[gps->totpoints - 1], diff_mat, &pt_dummy_ps);
gpencil_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &r_ctrl2[0], &r_ctrl2[1]);
}
bGPDstroke *ED_gpencil_stroke_nearest_to_ends(bContext *C,
const GP_SpaceConversion *gsc,
bGPDlayer *gpl,
bGPDframe *gpf,
bGPDstroke *gps,
const float ctrl1[2],
const float ctrl2[2],
const float radius,
int *r_index)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Object *ob = CTX_data_active_object(C);
bGPDstroke *gps_rtn = nullptr;
const float radius_sqr = radius * radius;
/* calculate difference matrix object */
float diff_mat[4][4];
BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat);
/* Calculate the extremes of the stroke in 2D. */
bGPDspoint pt_parent;
float pt2d_start[2], pt2d_end[2];
bGPDspoint *pt = &gps->points[0];
gpencil_point_to_world_space(pt, diff_mat, &pt_parent);
gpencil_point_to_xy_fl(gsc, gps, &pt_parent, &pt2d_start[0], &pt2d_start[1]);
pt = &gps->points[gps->totpoints - 1];
gpencil_point_to_world_space(pt, diff_mat, &pt_parent);
gpencil_point_to_xy_fl(gsc, gps, &pt_parent, &pt2d_end[0], &pt2d_end[1]);
/* Loop all strokes of the active frame. */
float dist_min = FLT_MAX;
LISTBASE_FOREACH (bGPDstroke *, gps_target, &gpf->strokes) {
/* Check if the color is editable. */
if ((gps_target == gps) || (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false)) {
continue;
}
/* Check that stroke is not closed. Closed strokes must not be included in the merge. */
if (gps_target->flag & GP_STROKE_CYCLIC) {
continue;
}
/* Check if one of the ends is inside target stroke bounding box. */
if (!ED_gpencil_stroke_check_collision(gsc, gps_target, pt2d_start, radius, diff_mat) &&
!ED_gpencil_stroke_check_collision(gsc, gps_target, pt2d_end, radius, diff_mat))
{
continue;
}
/* Check the distance of the ends with the ends of target stroke to avoid middle contact.
* All is done in 2D plane. */
float pt2d_target_start[2], pt2d_target_end[2];
pt = &gps_target->points[0];
gpencil_point_to_world_space(pt, diff_mat, &pt_parent);
gpencil_point_to_xy_fl(gsc, gps, &pt_parent, &pt2d_target_start[0], &pt2d_target_start[1]);
pt = &gps_target->points[gps_target->totpoints - 1];
gpencil_point_to_world_space(pt, diff_mat, &pt_parent);
gpencil_point_to_xy_fl(gsc, gps, &pt_parent, &pt2d_target_end[0], &pt2d_target_end[1]);
/* If the distance to the original stroke extremes is too big, the stroke must not be joined.
*/
if ((len_squared_v2v2(ctrl1, pt2d_target_start) > radius_sqr) &&
(len_squared_v2v2(ctrl1, pt2d_target_end) > radius_sqr) &&
(len_squared_v2v2(ctrl2, pt2d_target_start) > radius_sqr) &&
(len_squared_v2v2(ctrl2, pt2d_target_end) > radius_sqr))
{
continue;
}
if ((len_squared_v2v2(pt2d_start, pt2d_target_start) > radius_sqr) &&
(len_squared_v2v2(pt2d_start, pt2d_target_end) > radius_sqr) &&
(len_squared_v2v2(pt2d_end, pt2d_target_start) > radius_sqr) &&
(len_squared_v2v2(pt2d_end, pt2d_target_end) > radius_sqr))
{
continue;
}
/* Loop all points and check what is the nearest point. */
int i;
for (i = 0, pt = gps_target->points; i < gps_target->totpoints; i++, pt++) {
/* Convert point to 2D. */
float pt2d[2];
gpencil_point_to_world_space(pt, diff_mat, &pt_parent);
gpencil_point_to_xy_fl(gsc, gps, &pt_parent, &pt2d[0], &pt2d[1]);
/* Check with Start point. */
float dist = len_squared_v2v2(pt2d, pt2d_start);
if ((dist <= radius_sqr) && (dist < dist_min)) {
*r_index = i;
dist_min = dist;
gps_rtn = gps_target;
}
/* Check with End point. */
dist = len_squared_v2v2(pt2d, pt2d_end);
if ((dist <= radius_sqr) && (dist < dist_min)) {
*r_index = i;
dist_min = dist;
gps_rtn = gps_target;
}
}
}
return gps_rtn;
}
bGPDstroke *ED_gpencil_stroke_join_and_trim(
bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps, bGPDstroke *gps_dst, const int pt_index)
{
if ((gps->totpoints < 1) || (gps_dst->totpoints < 1)) {
return nullptr;
}
BLI_assert(pt_index >= 0 && pt_index < gps_dst->totpoints);
bGPDspoint *pt = nullptr;
/* Cannot be cyclic. */
gps->flag &= ~GP_STROKE_CYCLIC;
gps_dst->flag &= ~GP_STROKE_CYCLIC;
/* Trim stroke. */
bGPDstroke *gps_final = gps_dst;
if ((pt_index > 0) && (pt_index < gps_dst->totpoints - 2)) {
/* Untag any pending operation. */
gps_dst->flag &= ~GP_STROKE_TAG;
for (int i = 0; i < gps_dst->totpoints; i++) {
gps_dst->points[i].flag &= ~GP_SPOINT_TAG;
}
/* Delete points of the shorter extreme */
pt = &gps_dst->points[0];
float dist_to_start = BKE_gpencil_stroke_segment_length(gps_dst, 0, pt_index, true);
pt = &gps_dst->points[gps_dst->totpoints - 1];
float dist_to_end = BKE_gpencil_stroke_segment_length(
gps_dst, pt_index, gps_dst->totpoints - 1, true);
if (dist_to_start < dist_to_end) {
for (int i = 0; i < pt_index; i++) {
gps_dst->points[i].flag |= GP_SPOINT_TAG;
}
}
else {
for (int i = pt_index + 1; i < gps_dst->totpoints; i++) {
gps_dst->points[i].flag |= GP_SPOINT_TAG;
}
}
/* Remove tagged points to trim stroke. */
gps_final = BKE_gpencil_stroke_delete_tagged_points(
gpd, gpf, gps_dst, gps_dst->next, GP_SPOINT_TAG, false, false, 0);
}
/* Join both strokes. */
int totpoint = gps_final->totpoints;
BKE_gpencil_stroke_join(gps_final, gps, false, true, true, true);
/* Select the join points and merge if the distance is very small. */
pt = &gps_final->points[totpoint - 1];
pt->flag |= GP_SPOINT_SELECT;
pt = &gps_final->points[totpoint];
pt->flag |= GP_SPOINT_SELECT;
BKE_gpencil_stroke_merge_distance(gpd, gpf, gps_final, 0.01f, false);
/* Unselect all points. */
for (int i = 0; i < gps_final->totpoints; i++) {
gps_final->points[i].flag &= ~GP_SPOINT_SELECT;
}
/* Delete old stroke. */
BLI_remlink(&gpf->strokes, gps);
BKE_gpencil_free_stroke(gps);
return gps_final;
}
void ED_gpencil_stroke_close_by_distance(bGPDstroke *gps, const float threshold)
{
if (gps == nullptr) {
return;
}
bGPDspoint *pt_start = &gps->points[0];
bGPDspoint *pt_end = &gps->points[gps->totpoints - 1];
const float threshold_sqr = threshold * threshold;
float dist_to_close = len_squared_v3v3(&pt_start->x, &pt_end->x);
if (dist_to_close < threshold_sqr) {
gps->flag |= GP_STROKE_CYCLIC;
BKE_gpencil_stroke_close(gps);
}
}
void ED_gpencil_layer_merge(bGPdata *gpd,
bGPDlayer *gpl_src,
bGPDlayer *gpl_dst,
const bool reverse)
{
/* Collect frames of gpl_dst in hash table to avoid O(n^2) lookups. */
GHash *gh_frames_dst = BLI_ghash_int_new_ex(__func__, 64);
LISTBASE_FOREACH (bGPDframe *, gpf_dst, &gpl_dst->frames) {
BLI_ghash_insert(gh_frames_dst, POINTER_FROM_INT(gpf_dst->framenum), gpf_dst);
}
/* Read all frames from merge layer and add any missing in destination layer,
* copying all previous strokes to keep the image equals.
* Need to do it in a separated loop to avoid strokes accumulation. */
LISTBASE_FOREACH (bGPDframe *, gpf_src, &gpl_src->frames) {
/* Try to find frame in destination layer hash table. */
bGPDframe *gpf_dst = static_cast<bGPDframe *>(
BLI_ghash_lookup(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum)));
if (!gpf_dst) {
gpf_dst = BKE_gpencil_layer_frame_get(gpl_dst, gpf_src->framenum, GP_GETFRAME_ADD_COPY);
/* Use same frame type. */
gpf_dst->key_type = gpf_src->key_type;
BLI_ghash_insert(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum), gpf_dst);
}
/* Copy current source frame to further frames
* that are keyframes in destination layer and not in source layer
* to keep the image equals. */
if (gpf_dst->next && (!gpf_src->next || (gpf_dst->next->framenum < gpf_src->next->framenum))) {
gpf_dst = gpf_dst->next;
BKE_gpencil_layer_frame_get(gpl_src, gpf_dst->framenum, GP_GETFRAME_ADD_COPY);
}
}
/* Read all frames from merge layer and add strokes. */
LISTBASE_FOREACH (bGPDframe *, gpf_src, &gpl_src->frames) {
/* Try to find frame in destination layer hash table. */
bGPDframe *gpf_dst = static_cast<bGPDframe *>(
BLI_ghash_lookup(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum)));
/* Add to tail all strokes. */
if (gpf_dst) {
if (reverse) {
BLI_movelisttolist_reverse(&gpf_dst->strokes, &gpf_src->strokes);
}
else {
BLI_movelisttolist(&gpf_dst->strokes, &gpf_src->strokes);
}
}
}
/* Add Masks to destination layer. */
LISTBASE_FOREACH (bGPDlayer_Mask *, mask, &gpl_src->mask_layers) {
/* Don't add merged layers or missing layer names. */
if (!BKE_gpencil_layer_named_get(gpd, mask->name) || STREQ(mask->name, gpl_src->info) ||
STREQ(mask->name, gpl_dst->info))
{
continue;
}
if (!BKE_gpencil_layer_mask_named_get(gpl_dst, mask->name)) {
bGPDlayer_Mask *mask_new = static_cast<bGPDlayer_Mask *>(MEM_dupallocN(mask));
BLI_addtail(&gpl_dst->mask_layers, mask_new);
gpl_dst->act_mask++;
}
}
/* Set destination layer as active. */
BKE_gpencil_layer_active_set(gpd, gpl_dst);
/* Now delete merged layer. */
BKE_gpencil_layer_delete(gpd, gpl_src);
BLI_ghash_free(gh_frames_dst, nullptr, nullptr);
/* Reorder masking. */
if (gpl_dst->mask_layers.first) {
BKE_gpencil_layer_mask_sort(gpd, gpl_dst);
}
}
static void gpencil_layer_new_name_get(bGPdata *gpd, char *r_name, size_t name_maxncpy)
{
int index = 0;
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (strstr(gpl->info, "GP_Layer")) {
index++;
}
}
if (index == 0) {
BLI_strncpy(r_name, "GP_Layer", name_maxncpy);
return;
}
BLI_snprintf(r_name, name_maxncpy, "GP_Layer.%03d", index);
}
int ED_gpencil_new_layer_dialog(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
PropertyRNA *prop;
if (RNA_int_get(op->ptr, "layer") == -1) {
prop = RNA_struct_find_property(op->ptr, "new_layer_name");
if (!RNA_property_is_set(op->ptr, prop)) {
char name[MAX_NAME];
bGPdata *gpd = static_cast<bGPdata *>(ob->data);
gpencil_layer_new_name_get(gpd, name, sizeof(name));
RNA_property_string_set(op->ptr, prop, name);
return WM_operator_props_dialog_popup(C,
op,
200,
IFACE_("Add New Layer"),
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add"));
}
}
return 0;
}

View File

@@ -14,7 +14,6 @@ struct PointerRNA;
struct Brush; struct Brush;
struct GP_SpaceConversion; struct GP_SpaceConversion;
struct GpRandomSettings;
struct bGPDframe; struct bGPDframe;
struct bGPDlayer; struct bGPDlayer;
struct bGPDspoint; struct bGPDspoint;
@@ -43,30 +42,6 @@ struct bAnimContext;
struct wmKeyConfig; struct wmKeyConfig;
struct wmOperator; struct wmOperator;
#define GPENCIL_MINIMUM_JOIN_DIST 20.0f
/** Reproject stroke modes. */
enum eGP_ReprojectModes {
/* Axis */
GP_REPROJECT_FRONT = 0,
GP_REPROJECT_SIDE,
GP_REPROJECT_TOP,
/** On same plane, parallel to view-plane. */
GP_REPROJECT_VIEW,
/** Re-projected on to the scene geometry. */
GP_REPROJECT_SURFACE,
/** Re-projected on 3D cursor orientation. */
GP_REPROJECT_CURSOR,
/** Keep equals (used in some operators). */
GP_REPROJECT_KEEP,
};
/* Target object modes. */
enum eGP_TargetObjectMode {
GP_TARGET_OB_NEW = 0,
GP_TARGET_OB_SELECTED = 1,
};
/* ------------- Grease-Pencil Runtime Data ---------------- */ /* ------------- Grease-Pencil Runtime Data ---------------- */
/** /**
@@ -109,15 +84,6 @@ bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *r_ptr);
* Get the active Grease Pencil data-block * Get the active Grease Pencil data-block
*/ */
bGPdata *ED_gpencil_data_get_active(const bContext *C); bGPdata *ED_gpencil_data_get_active(const bContext *C);
/**
* Get the evaluated copy of the active Grease Pencil data-block (where applicable)
* - For the 3D View (i.e. "GP Objects"), this gives the evaluated copy of the GP data-block
* (i.e. a copy of the active GP data-block for the active object, where modifiers have been
* applied). This is needed to correctly work with "Copy-on-Write".
* - For all other editors (i.e. "GP Annotations"), this just gives the active data-block
* like for #ED_gpencil_data_get_active()
*/
bGPdata *ED_gpencil_data_get_active_evaluated(const bContext *C);
/** /**
* Context independent (i.e. each required part is passed in instead). * Context independent (i.e. each required part is passed in instead).
@@ -127,8 +93,6 @@ bGPdata *ED_gpencil_data_get_active_evaluated(const bContext *C);
* when context info is not available. * when context info is not available.
*/ */
bGPdata **ED_gpencil_data_get_pointers_direct(ScrArea *area, Object *ob, PointerRNA *r_ptr); bGPdata **ED_gpencil_data_get_pointers_direct(ScrArea *area, Object *ob, PointerRNA *r_ptr);
/* Get the active Grease Pencil data-block, when context is not available */
bGPdata *ED_gpencil_data_get_active_direct(ScrArea *area, Object *ob);
/** /**
* Get the active Grease Pencil data-block * Get the active Grease Pencil data-block
@@ -161,17 +125,6 @@ bGPdata *ED_annotation_data_get_active_direct(ID *screen_id, ScrArea *area, Scen
*/ */
bool ED_gpencil_data_owner_is_annotation(PointerRNA *owner_ptr); bool ED_gpencil_data_owner_is_annotation(PointerRNA *owner_ptr);
/* 3D View */
/**
* Check whether there's an active GP keyframe on the current frame.
*/
bool ED_gpencil_has_keyframe_v3d(Scene *scene, Object *ob, int cfra);
/* ----------- Stroke Editing Utilities ---------------- */
bool ED_gpencil_frame_has_selected_stroke(const bGPDframe *gpf);
bool ED_gpencil_layer_has_selected_stroke(const bGPDlayer *gpl, bool is_multiedit);
/** /**
* Check whether given stroke can be edited given the supplied context. * Check whether given stroke can be edited given the supplied context.
* TODO: do we need additional flags for screen-space vs data-space?. * TODO: do we need additional flags for screen-space vs data-space?.
@@ -181,8 +134,6 @@ bool ED_gpencil_stroke_can_use_direct(const ScrArea *area, const bGPDstroke *gps
bool ED_gpencil_stroke_can_use(const bContext *C, const bGPDstroke *gps); bool ED_gpencil_stroke_can_use(const bContext *C, const bGPDstroke *gps);
/** Check whether given stroke can be edited for the current color */ /** Check whether given stroke can be edited for the current color */
bool ED_gpencil_stroke_material_editable(Object *ob, const bGPDlayer *gpl, const bGPDstroke *gps); bool ED_gpencil_stroke_material_editable(Object *ob, const bGPDlayer *gpl, const bGPDstroke *gps);
/** Check whether given stroke is visible for the current material. */
bool ED_gpencil_stroke_material_visible(Object *ob, const bGPDstroke *gps);
/* ----------- Grease Pencil Operators ----------------- */ /* ----------- Grease Pencil Operators ----------------- */
@@ -192,8 +143,6 @@ void ED_operatortypes_gpencil_legacy();
/* ------------- Copy-Paste Buffers -------------------- */ /* ------------- Copy-Paste Buffers -------------------- */
/* Strokes copybuf */
/** /**
* Free copy/paste buffer data. * Free copy/paste buffer data.
*/ */
@@ -278,11 +227,6 @@ bool ED_gpencil_layer_frames_delete(bGPDlayer *gpl);
*/ */
void ED_gpencil_layer_frames_duplicate(bGPDlayer *gpl); void ED_gpencil_layer_frames_duplicate(bGPDlayer *gpl);
/**
* Merge two layers.
*/
void ED_gpencil_layer_merge(bGPdata *gpd, bGPDlayer *gpl_src, bGPDlayer *gpl_dst, bool reverse);
/** /**
* Set keyframe type for selected frames from given gp-layer * Set keyframe type for selected frames from given gp-layer
* *
@@ -323,98 +267,8 @@ int ED_gpencil_session_active();
*/ */
int ED_undo_gpencil_step(bContext *C, int step); /* eUndoStepDir. */ int ED_undo_gpencil_step(bContext *C, int step); /* eUndoStepDir. */
/* ------------ Grease-Pencil Armature ------------------ */
bool ED_gpencil_add_armature(const bContext *C, ReportList *reports, Object *ob, Object *ob_arm);
bool ED_gpencil_add_armature_weights(
const bContext *C, ReportList *reports, Object *ob, Object *ob_arm, int mode);
/* keep this aligned with gpencil_armature enum */
#define GP_PAR_ARMATURE_NAME 0
#define GP_PAR_ARMATURE_AUTO 1
/* ------------ Transformation Utilities ------------ */
/**
* Reset parent matrix for all layers.
*/
void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata *gpd);
/* Cursor utilities. */
/**
* Draw eraser cursor.
*/
void ED_gpencil_brush_draw_eraser(Brush *brush, int x, int y);
/* ----------- Add Primitive Utilities -------------- */ /* ----------- Add Primitive Utilities -------------- */
/** Number of values defining each point in the built-in data buffers for primitives. */
#define GP_PRIM_DATABUF_SIZE 5
/**
* Populate stroke with point data from data buffers.
* \param gps: Grease pencil stroke
* \param array: Flat array of point data values. Each entry has #GP_PRIM_DATABUF_SIZE values.
* \param totpoints: Total of points
* \param mat: 4x4 transform matrix to transform points into the right coordinate space.
*/
void ED_gpencil_stroke_init_data(bGPDstroke *gps,
const float *array,
int totpoints,
const float mat[4][4]);
/**
* Add a Simple empty object with one layer and one color.
*/
void ED_gpencil_create_blank(bContext *C, Object *ob, float mat[4][4]);
/**
* Add a 2D Suzanne.
*/
void ED_gpencil_create_monkey(bContext *C, Object *ob, float mat[4][4]);
/**
* Add a Simple stroke with colors.
*/
void ED_gpencil_create_stroke(bContext *C, Object *ob, float mat[4][4]);
/**
* Add a Simple LineArt setup.
*/
void ED_gpencil_create_lineart(bContext *C, Object *ob);
/* ------------ Object Utilities ------------ */
/**
* Helper function to create new #OB_GPENCIL_LEGACY Object.
*/
Object *ED_gpencil_add_object(bContext *C, const float loc[3], unsigned short local_view_bits);
/**
* Helper function to create default colors and drawing brushes.
*/
void ED_gpencil_add_defaults(bContext *C, Object *ob);
/**
* Set object modes.
*/
void ED_gpencil_setup_modes(bContext *C, bGPdata *gpd, int newmode);
bool ED_object_gpencil_exit(Main *bmain, Object *ob);
/**
* Reproject all points of the stroke to a plane locked to axis to avoid stroke offset
*/
void ED_gpencil_project_stroke_to_plane(const Scene *scene,
const Object *ob,
const RegionView3D *rv3d,
bGPDlayer *gpl,
bGPDstroke *gps,
const float origin[3],
int axis);
/**
* Reproject given point to a plane locked to axis to avoid stroke offset
* \param pt: Point to affect (used for input & output).
*/
void ED_gpencil_project_point_to_plane(const Scene *scene,
const Object *ob,
bGPDlayer *gpl,
const RegionView3D *rv3d,
const float origin[3],
int axis,
bGPDspoint *pt);
/** /**
* Get drawing reference point for conversion or projection of the stroke * Get drawing reference point for conversion or projection of the stroke
* \param r_vec: Reference point found * \param r_vec: Reference point found
@@ -423,51 +277,6 @@ void ED_gpencil_drawing_reference_get(const Scene *scene,
const Object *ob, const Object *ob,
char align_flag, char align_flag,
float r_vec[3]); float r_vec[3]);
void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke *gps);
/**
* Reproject selected strokes.
*/
void ED_gpencil_stroke_reproject(Depsgraph *depsgraph,
const GP_SpaceConversion *gsc,
SnapObjectContext *sctx,
bGPDlayer *gpl,
bGPDframe *gpf,
bGPDstroke *gps,
eGP_ReprojectModes mode,
bool keep_original,
const float offset);
/**
* Turn brush cursor in on/off.
*/
void ED_gpencil_toggle_brush_cursor(bContext *C, bool enable, void *customdata);
/* vertex groups */
/**
* Assign points to vertex group.
*/
void ED_gpencil_vgroup_assign(bContext *C, Object *ob, float weight);
/**
* Remove points from vertex group.
*/
void ED_gpencil_vgroup_remove(bContext *C, Object *ob);
/**
* Select points of vertex group.
*/
void ED_gpencil_vgroup_select(bContext *C, Object *ob);
/**
* Un-select points of vertex group.
*/
void ED_gpencil_vgroup_deselect(bContext *C, Object *ob);
/* join objects */
/**
* Join objects called from OBJECT_OT_join.
*/
int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op);
/* texture coordinate utilities */ /* texture coordinate utilities */
@@ -478,31 +287,6 @@ void ED_gpencil_tpoint_to_point(ARegion *region,
float origin[3], float origin[3],
const tGPspoint *tpt, const tGPspoint *tpt,
bGPDspoint *pt); bGPDspoint *pt);
/**
* Recalculate UV for any stroke using the material.
*/
void ED_gpencil_update_color_uv(Main *bmain, Material *mat);
/**
* Extend selection to stroke intersections:
* \return The result of selecting:
* 0 - No hit
* 1 - Hit in point A
* 2 - Hit in point B
* 3 - Hit in point A and B
*/
int ED_gpencil_select_stroke_segment(bGPdata *gpd,
bGPDlayer *gpl,
bGPDstroke *gps,
bGPDspoint *pt,
bool select,
bool insert,
float scale,
float r_hita[3],
float r_hitb[3]);
void ED_gpencil_select_toggle_all(bContext *C, int action);
void ED_gpencil_select_curve_toggle_all(bContext *C, int action);
/** /**
* Ensure the #tGPspoint buffer (while drawing stroke) * Ensure the #tGPspoint buffer (while drawing stroke)
@@ -512,96 +296,3 @@ tGPspoint *ED_gpencil_sbuffer_ensure(tGPspoint *buffer_array,
int *buffer_size, int *buffer_size,
int *buffer_used, int *buffer_used,
bool clear); bool clear);
void ED_gpencil_sbuffer_update_eval(bGPdata *gpd, Object *ob_eval);
/**
* Tag all scene grease pencil object to update.
*/
void ED_gpencil_tag_scene_gpencil(Scene *scene);
/* Vertex color set. */
void ED_gpencil_fill_vertex_color_set(ToolSettings *ts, Brush *brush, bGPDstroke *gps);
void ED_gpencil_point_vertex_color_set(ToolSettings *ts,
Brush *brush,
bGPDspoint *pt,
tGPspoint *tpt);
void ED_gpencil_sbuffer_vertex_color_set(Depsgraph *depsgraph,
Object *ob,
ToolSettings *ts,
Brush *brush,
Material *material,
float random_color[3],
float pen_pressure);
void ED_gpencil_init_random_settings(Brush *brush,
const int mval[2],
GpRandomSettings *random_settings);
/**
* Check if the stroke collides with brush.
*/
bool ED_gpencil_stroke_check_collision(const GP_SpaceConversion *gsc,
bGPDstroke *gps,
const float mval[2],
int radius,
const float diff_mat[4][4]);
/**
* Check if a point is inside of the stroke.
*
* \param gps: Stroke to check.
* \param gsc: Space conversion data.
* \param mval: Region relative cursor position.
* \param diff_mat: View matrix.
* \return True if the point is inside.
*/
bool ED_gpencil_stroke_point_is_inside(const bGPDstroke *gps,
const GP_SpaceConversion *gsc,
const int mval[2],
const float diff_mat[4][4]);
/**
* Get the bigger 2D bound box points.
*/
void ED_gpencil_projected_2d_bound_box(const GP_SpaceConversion *gsc,
const bGPDstroke *gps,
const float diff_mat[4][4],
float r_min[2],
float r_max[2]);
bGPDstroke *ED_gpencil_stroke_nearest_to_ends(bContext *C,
const GP_SpaceConversion *gsc,
bGPDlayer *gpl,
bGPDframe *gpf,
bGPDstroke *gps,
const float ctrl1[2],
const float ctrl2[2],
float radius,
int *r_index);
/**
* Get extremes of stroke in 2D using current view.
*/
void ED_gpencil_stroke_extremes_to2d(const GP_SpaceConversion *gsc,
const float diff_mat[4][4],
bGPDstroke *gps,
float r_ctrl1[2],
float r_ctrl2[2]);
/**
* Join two stroke using a contact point index and trimming the rest.
*/
bGPDstroke *ED_gpencil_stroke_join_and_trim(
bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps, bGPDstroke *gps_dst, int pt_index);
/**
* Close if the distance between extremes is below threshold.
*/
void ED_gpencil_stroke_close_by_distance(bGPDstroke *gps, float threshold);
/**
* Calculate the brush cursor size in world space.
*/
float ED_gpencil_cursor_radius(bContext *C, int x, int y);
bool ED_gpencil_brush_cursor_poll(bContext *C);
float ED_gpencil_radial_control_scale(bContext *C,
Brush *brush,
float initial_value,
const int mval[2]);

View File

@@ -30,9 +30,6 @@ set(SRC
io_cache.cc io_cache.cc
io_collada.cc io_collada.cc
io_drop_import_file.cc io_drop_import_file.cc
io_gpencil_legacy_export.cc
io_gpencil_legacy_import.cc
io_gpencil_legacy_utils.cc
io_grease_pencil.cc io_grease_pencil.cc
io_obj.cc io_obj.cc
io_ops.cc io_ops.cc
@@ -45,7 +42,6 @@ set(SRC
io_cache.hh io_cache.hh
io_collada.hh io_collada.hh
io_drop_import_file.hh io_drop_import_file.hh
io_gpencil_legacy.hh
io_grease_pencil.hh io_grease_pencil.hh
io_obj.hh io_obj.hh
io_ops.hh io_ops.hh
@@ -95,7 +91,6 @@ endif()
if(WITH_IO_GREASE_PENCIL) if(WITH_IO_GREASE_PENCIL)
list(APPEND LIB list(APPEND LIB
bf_io_gpencil_legacy
bf_io_grease_pencil bf_io_grease_pencil
) )
add_definitions(-DWITH_IO_GREASE_PENCIL) add_definitions(-DWITH_IO_GREASE_PENCIL)

View File

@@ -1,26 +0,0 @@
/* SPDX-FileCopyrightText: 2020 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editor/io
*/
#pragma once
struct ARegion;
struct View3D;
struct bContext;
struct wmOperatorType;
void WM_OT_gpencil_import_svg(wmOperatorType *ot);
#ifdef WITH_PUGIXML
void WM_OT_gpencil_export_svg(wmOperatorType *ot);
#endif
#ifdef WITH_HARU
void WM_OT_gpencil_export_pdf(wmOperatorType *ot);
#endif
ARegion *get_invoke_region(bContext *C);
View3D *get_invoke_view3d(bContext *C);

View File

@@ -1,394 +0,0 @@
/* SPDX-FileCopyrightText: 2020 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editor/io
*/
#ifdef WITH_IO_GREASE_PENCIL
# include "BLI_path_utils.hh"
# include "DNA_space_types.h"
# include "BKE_report.hh"
# include "BKE_screen.hh"
# include "BLT_translation.hh"
# include "ED_fileselect.hh"
# include "RNA_access.hh"
# include "RNA_define.hh"
# include "UI_interface.hh"
# include "UI_resources.hh"
# include "WM_api.hh"
# include "WM_types.hh"
# include "io_gpencil_legacy.hh"
# include "gpencil_io.h"
# if defined(WITH_PUGIXML) || defined(WITH_HARU)
/* Definition of enum elements to export. */
/* Common props for exporting. */
static void gpencil_export_common_props_definition(wmOperatorType *ot)
{
static const EnumPropertyItem select_items[] = {
{GP_EXPORT_ACTIVE, "ACTIVE", 0, "Active", "Include only the active object"},
{GP_EXPORT_SELECTED, "SELECTED", 0, "Selected", "Include selected objects"},
{GP_EXPORT_VISIBLE, "VISIBLE", 0, "Visible", "Include all visible objects"},
{0, nullptr, 0, nullptr, nullptr},
};
RNA_def_boolean(ot->srna, "use_fill", true, "Fill", "Export strokes with fill enabled");
RNA_def_enum(ot->srna,
"selected_object_type",
select_items,
GP_EXPORT_SELECTED,
"Object",
"Which objects to include in the export");
RNA_def_float(ot->srna,
"stroke_sample",
0.0f,
0.0f,
100.0f,
"Sampling",
"Precision of stroke sampling. Low values mean a more precise result, and zero "
"disables sampling",
0.0f,
100.0f);
RNA_def_boolean(ot->srna,
"use_normalized_thickness",
false,
"Normalize",
"Export strokes with constant thickness");
}
# endif
/* <-------- SVG single frame export. --------> */
# ifdef WITH_PUGIXML
static bool wm_gpencil_export_svg_common_check(bContext * /*C*/, wmOperator *op)
{
char filepath[FILE_MAX];
RNA_string_get(op->ptr, "filepath", filepath);
if (!BLI_path_extension_check(filepath, ".svg")) {
BLI_path_extension_ensure(filepath, FILE_MAX, ".svg");
RNA_string_set(op->ptr, "filepath", filepath);
return true;
}
return false;
}
static int wm_gpencil_export_svg_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
{
ED_fileselect_ensure_default_filepath(C, op, ".svg");
WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
}
static int wm_gpencil_export_svg_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) {
BKE_report(op->reports, RPT_ERROR, "No filepath given");
return OPERATOR_CANCELLED;
}
ARegion *region = get_invoke_region(C);
if (region == nullptr) {
BKE_report(op->reports, RPT_ERROR, "Unable to find valid 3D View area");
return OPERATOR_CANCELLED;
}
View3D *v3d = get_invoke_view3d(C);
char filepath[FILE_MAX];
RNA_string_get(op->ptr, "filepath", filepath);
const bool use_fill = RNA_boolean_get(op->ptr, "use_fill");
const bool use_norm_thickness = RNA_boolean_get(op->ptr, "use_normalized_thickness");
const eGpencilExportSelect select_mode = eGpencilExportSelect(
RNA_enum_get(op->ptr, "selected_object_type"));
const bool use_clip_camera = RNA_boolean_get(op->ptr, "use_clip_camera");
/* Set flags. */
int flag = 0;
SET_FLAG_FROM_TEST(flag, use_fill, GP_EXPORT_FILL);
SET_FLAG_FROM_TEST(flag, use_norm_thickness, GP_EXPORT_NORM_THICKNESS);
SET_FLAG_FROM_TEST(flag, use_clip_camera, GP_EXPORT_CLIP_CAMERA);
GpencilIOParams params{};
params.C = C;
params.region = region;
params.v3d = v3d;
params.ob = ob;
params.mode = GP_EXPORT_TO_SVG;
params.frame_start = scene->r.cfra;
params.frame_end = scene->r.cfra;
params.frame_cur = scene->r.cfra;
params.flag = flag;
params.scale = 1.0f;
params.select_mode = select_mode;
params.frame_mode = GP_EXPORT_FRAME_ACTIVE;
params.stroke_sample = RNA_float_get(op->ptr, "stroke_sample");
params.resolution = 1.0f;
/* Do export. */
WM_cursor_wait(true);
const bool done = gpencil_io_export(filepath, &params);
WM_cursor_wait(false);
if (!done) {
BKE_report(op->reports, RPT_WARNING, "Unable to export SVG");
}
return OPERATOR_FINISHED;
}
static void ui_gpencil_export_svg_settings(uiLayout *layout, PointerRNA *imfptr)
{
uiLayout *box, *row;
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
box = uiLayoutBox(layout);
row = uiLayoutRow(box, false);
uiItemL(row, IFACE_("Scene Options"), ICON_NONE);
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "selected_object_type", UI_ITEM_NONE, nullptr, ICON_NONE);
box = uiLayoutBox(layout);
row = uiLayoutRow(box, false);
uiItemL(row, IFACE_("Export Options"), ICON_NONE);
uiLayout *col = uiLayoutColumn(box, false);
uiItemR(col, imfptr, "stroke_sample", UI_ITEM_NONE, nullptr, ICON_NONE);
uiItemR(col, imfptr, "use_fill", UI_ITEM_NONE, nullptr, ICON_NONE);
uiItemR(col, imfptr, "use_normalized_thickness", UI_ITEM_NONE, nullptr, ICON_NONE);
uiItemR(col, imfptr, "use_clip_camera", UI_ITEM_NONE, nullptr, ICON_NONE);
}
static void wm_gpencil_export_svg_draw(bContext * /*C*/, wmOperator *op)
{
ui_gpencil_export_svg_settings(op->layout, op->ptr);
}
static bool wm_gpencil_export_svg_poll(bContext *C)
{
if ((CTX_wm_window(C) == nullptr) || (CTX_data_mode_enum(C) != CTX_MODE_OBJECT)) {
return false;
}
return true;
}
void WM_OT_gpencil_export_svg(wmOperatorType *ot)
{
ot->name = "Export to SVG";
ot->description = "Export grease pencil to SVG";
ot->idname = "WM_OT_gpencil_export_svg";
ot->invoke = wm_gpencil_export_svg_invoke;
ot->exec = wm_gpencil_export_svg_exec;
ot->poll = wm_gpencil_export_svg_poll;
ot->ui = wm_gpencil_export_svg_draw;
ot->check = wm_gpencil_export_svg_common_check;
WM_operator_properties_filesel(ot,
FILE_TYPE_FOLDER | FILE_TYPE_OBJECT_IO,
FILE_BLENDER,
FILE_SAVE,
WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS,
FILE_DEFAULTDISPLAY,
FILE_SORT_DEFAULT);
gpencil_export_common_props_definition(ot);
RNA_def_boolean(ot->srna,
"use_clip_camera",
false,
"Clip Camera",
"Clip drawings to camera size when export in camera view");
}
# endif
/* <-------- PDF single frame export. --------> */
# ifdef WITH_HARU
static bool wm_gpencil_export_pdf_common_check(bContext * /*C*/, wmOperator *op)
{
char filepath[FILE_MAX];
RNA_string_get(op->ptr, "filepath", filepath);
if (!BLI_path_extension_check(filepath, ".pdf")) {
BLI_path_extension_ensure(filepath, FILE_MAX, ".pdf");
RNA_string_set(op->ptr, "filepath", filepath);
return true;
}
return false;
}
static int wm_gpencil_export_pdf_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
{
ED_fileselect_ensure_default_filepath(C, op, ".pdf");
WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
}
static int wm_gpencil_export_pdf_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) {
BKE_report(op->reports, RPT_ERROR, "No filepath given");
return OPERATOR_CANCELLED;
}
ARegion *region = get_invoke_region(C);
if (region == nullptr) {
BKE_report(op->reports, RPT_ERROR, "Unable to find valid 3D View area");
return OPERATOR_CANCELLED;
}
View3D *v3d = get_invoke_view3d(C);
char filepath[FILE_MAX];
RNA_string_get(op->ptr, "filepath", filepath);
const bool use_fill = RNA_boolean_get(op->ptr, "use_fill");
const bool use_norm_thickness = RNA_boolean_get(op->ptr, "use_normalized_thickness");
const short select_mode = RNA_enum_get(op->ptr, "selected_object_type");
const short frame_mode = RNA_enum_get(op->ptr, "frame_mode");
/* Set flags. */
int flag = 0;
SET_FLAG_FROM_TEST(flag, use_fill, GP_EXPORT_FILL);
SET_FLAG_FROM_TEST(flag, use_norm_thickness, GP_EXPORT_NORM_THICKNESS);
GpencilIOParams params{};
params.C = C;
params.region = region;
params.v3d = v3d;
params.ob = ob;
params.mode = GP_EXPORT_TO_PDF;
params.frame_start = scene->r.sfra;
params.frame_end = scene->r.efra;
params.frame_cur = scene->r.cfra;
params.flag = flag;
params.scale = 1.0f;
params.select_mode = select_mode;
params.frame_mode = frame_mode;
params.stroke_sample = RNA_float_get(op->ptr, "stroke_sample");
params.resolution = 1.0f;
/* Do export. */
WM_cursor_wait(true);
const bool done = gpencil_io_export(filepath, &params);
WM_cursor_wait(false);
if (!done) {
BKE_report(op->reports, RPT_WARNING, "Unable to export PDF");
}
return OPERATOR_FINISHED;
}
static void ui_gpencil_export_pdf_settings(uiLayout *layout, PointerRNA *imfptr)
{
uiLayout *box, *row, *col, *sub;
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
box = uiLayoutBox(layout);
row = uiLayoutRow(box, false);
uiItemL(row, IFACE_("Scene Options"), ICON_NONE);
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "selected_object_type", UI_ITEM_NONE, nullptr, ICON_NONE);
box = uiLayoutBox(layout);
row = uiLayoutRow(box, false);
uiItemL(row, IFACE_("Export Options"), ICON_NONE);
col = uiLayoutColumn(box, false);
sub = uiLayoutColumn(col, true);
uiItemR(sub, imfptr, "frame_mode", UI_ITEM_NONE, IFACE_("Frame"), ICON_NONE);
uiLayoutSetPropSep(box, true);
sub = uiLayoutColumn(col, true);
uiItemR(sub, imfptr, "stroke_sample", UI_ITEM_NONE, nullptr, ICON_NONE);
uiItemR(sub, imfptr, "use_fill", UI_ITEM_NONE, nullptr, ICON_NONE);
uiItemR(sub, imfptr, "use_normalized_thickness", UI_ITEM_NONE, nullptr, ICON_NONE);
}
static void wm_gpencil_export_pdf_draw(bContext * /*C*/, wmOperator *op)
{
ui_gpencil_export_pdf_settings(op->layout, op->ptr);
}
static bool wm_gpencil_export_pdf_poll(bContext *C)
{
if ((CTX_wm_window(C) == nullptr) || (CTX_data_mode_enum(C) != CTX_MODE_OBJECT)) {
return false;
}
return true;
}
void WM_OT_gpencil_export_pdf(wmOperatorType *ot)
{
ot->name = "Export to PDF";
ot->description = "Export grease pencil to PDF";
ot->idname = "WM_OT_gpencil_export_pdf";
ot->invoke = wm_gpencil_export_pdf_invoke;
ot->exec = wm_gpencil_export_pdf_exec;
ot->poll = wm_gpencil_export_pdf_poll;
ot->ui = wm_gpencil_export_pdf_draw;
ot->check = wm_gpencil_export_pdf_common_check;
WM_operator_properties_filesel(ot,
FILE_TYPE_FOLDER | FILE_TYPE_OBJECT_IO,
FILE_BLENDER,
FILE_SAVE,
WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS,
FILE_DEFAULTDISPLAY,
FILE_SORT_DEFAULT);
static const EnumPropertyItem gpencil_export_frame_items[] = {
{GP_EXPORT_FRAME_ACTIVE, "ACTIVE", 0, "Active", "Include only active frame"},
{GP_EXPORT_FRAME_SELECTED, "SELECTED", 0, "Selected", "Include selected frames"},
{GP_EXPORT_FRAME_SCENE, "SCENE", 0, "Scene", "Include all scene frames"},
{0, nullptr, 0, nullptr, nullptr},
};
gpencil_export_common_props_definition(ot);
ot->prop = RNA_def_enum(ot->srna,
"frame_mode",
gpencil_export_frame_items,
GP_EXPORT_ACTIVE,
"Frames",
"Which frames to include in the export");
}
# endif /* WITH_HARU */
#endif /* WITH_IO_GREASE_PENCIL */

View File

@@ -1,175 +0,0 @@
/* SPDX-FileCopyrightText: 2020 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editor/io
*/
#ifdef WITH_IO_GREASE_PENCIL
# include "BLI_path_utils.hh"
# include "BLI_string.h"
# include "MEM_guardedalloc.h"
# include "DNA_space_types.h"
# include "BKE_context.hh"
# include "BKE_file_handler.hh"
# include "BKE_report.hh"
# include "RNA_access.hh"
# include "RNA_define.hh"
# include "UI_interface.hh"
# include "UI_resources.hh"
# include "WM_api.hh"
# include "WM_types.hh"
# include "io_gpencil_legacy.hh"
# include "io_utils.hh"
# include "gpencil_io.h"
/* <-------- SVG single frame import. --------> */
static bool wm_gpencil_import_svg_common_check(bContext * /*C*/, wmOperator *op)
{
char filepath[FILE_MAX];
RNA_string_get(op->ptr, "filepath", filepath);
if (!BLI_path_extension_check(filepath, ".svg")) {
BLI_path_extension_ensure(filepath, FILE_MAX, ".svg");
RNA_string_set(op->ptr, "filepath", filepath);
return true;
}
return false;
}
static int wm_gpencil_import_svg_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false) ||
!RNA_struct_find_property(op->ptr, "directory"))
{
BKE_report(op->reports, RPT_ERROR, "No filepath given");
return OPERATOR_CANCELLED;
}
ARegion *region = get_invoke_region(C);
if (region == nullptr) {
BKE_report(op->reports, RPT_ERROR, "Unable to find valid 3D View area");
return OPERATOR_CANCELLED;
}
View3D *v3d = get_invoke_view3d(C);
/* Set flags. */
int flag = 0;
const int resolution = RNA_int_get(op->ptr, "resolution");
const float scale = RNA_float_get(op->ptr, "scale");
GpencilIOParams params{};
params.C = C;
params.region = region;
params.v3d = v3d;
params.ob = nullptr;
params.mode = GP_IMPORT_FROM_SVG;
params.frame_start = scene->r.cfra;
params.frame_end = scene->r.cfra;
params.frame_cur = scene->r.cfra;
params.flag = flag;
params.scale = scale;
params.select_mode = 0;
params.frame_mode = 0;
params.stroke_sample = 0.0f;
params.resolution = resolution;
/* Loop all selected files to import them. All SVG imported shared the same import
* parameters, but they are created in separated grease pencil objects. */
const auto paths = blender::ed::io::paths_from_operator_properties(op->ptr);
for (const auto &path : paths) {
/* Do Import. */
WM_cursor_wait(true);
BLI_path_split_file_part(path.c_str(), params.filename, ARRAY_SIZE(params.filename));
const bool done = gpencil_io_import(path.c_str(), &params);
WM_cursor_wait(false);
if (!done) {
BKE_reportf(op->reports, RPT_WARNING, "Unable to import '%s'", path.c_str());
}
}
return OPERATOR_FINISHED;
}
static void ui_gpencil_import_svg_settings(uiLayout *layout, PointerRNA *imfptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
uiLayout *box = uiLayoutBox(layout);
uiLayout *col = uiLayoutColumn(box, false);
uiItemR(col, imfptr, "resolution", UI_ITEM_NONE, nullptr, ICON_NONE);
uiItemR(col, imfptr, "scale", UI_ITEM_NONE, nullptr, ICON_NONE);
}
static void wm_gpencil_import_svg_draw(bContext * /*C*/, wmOperator *op)
{
ui_gpencil_import_svg_settings(op->layout, op->ptr);
}
static bool wm_gpencil_import_svg_poll(bContext *C)
{
if ((CTX_wm_window(C) == nullptr) || (CTX_data_mode_enum(C) != CTX_MODE_OBJECT)) {
return false;
}
return true;
}
void WM_OT_gpencil_import_svg(wmOperatorType *ot)
{
ot->name = "Import SVG as Grease Pencil";
ot->description = "Import SVG into grease pencil";
ot->idname = "WM_OT_gpencil_import_svg";
ot->invoke = blender::ed::io::filesel_drop_import_invoke;
ot->exec = wm_gpencil_import_svg_exec;
ot->poll = wm_gpencil_import_svg_poll;
ot->ui = wm_gpencil_import_svg_draw;
ot->check = wm_gpencil_import_svg_common_check;
WM_operator_properties_filesel(ot,
FILE_TYPE_FOLDER | FILE_TYPE_OBJECT_IO,
FILE_BLENDER,
FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_SHOW_PROPS |
WM_FILESEL_DIRECTORY | WM_FILESEL_FILES,
FILE_DEFAULTDISPLAY,
FILE_SORT_DEFAULT);
RNA_def_int(ot->srna,
"resolution",
10,
1,
30,
"Resolution",
"Resolution of the generated strokes",
1,
20);
RNA_def_float(ot->srna,
"scale",
10.0f,
0.001f,
100.0f,
"Scale",
"Scale of the final strokes",
0.001f,
100.0f);
}
#endif /* WITH_IO_GREASE_PENCIL */

View File

@@ -1,53 +0,0 @@
/* SPDX-FileCopyrightText: 2020 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editor/io
*/
#ifdef WITH_IO_GREASE_PENCIL
# include "DNA_space_types.h"
# include "BKE_context.hh"
# include "BKE_screen.hh"
# include "WM_api.hh"
# include "io_gpencil_legacy.hh"
ARegion *get_invoke_region(bContext *C)
{
bScreen *screen = CTX_wm_screen(C);
if (screen == nullptr) {
return nullptr;
}
ScrArea *area = BKE_screen_find_big_area(screen, SPACE_VIEW3D, 0);
if (area == nullptr) {
return nullptr;
}
ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
return region;
}
View3D *get_invoke_view3d(bContext *C)
{
bScreen *screen = CTX_wm_screen(C);
if (screen == nullptr) {
return nullptr;
}
ScrArea *area = BKE_screen_find_big_area(screen, SPACE_VIEW3D, 0);
if (area == nullptr) {
return nullptr;
}
if (area != nullptr) {
return static_cast<View3D *>(area->spacedata.first);
}
return nullptr;
}
#endif /* WITH_IO_GREASE_PENCIL */

View File

@@ -24,7 +24,6 @@
#include "io_cache.hh" #include "io_cache.hh"
#include "io_drop_import_file.hh" #include "io_drop_import_file.hh"
#include "io_gpencil_legacy.hh"
#include "io_grease_pencil.hh" #include "io_grease_pencil.hh"
#include "io_obj.hh" #include "io_obj.hh"
#include "io_ply_ops.hh" #include "io_ply_ops.hh"
@@ -51,15 +50,12 @@ void ED_operatortypes_io()
#endif #endif
#ifdef WITH_IO_GREASE_PENCIL #ifdef WITH_IO_GREASE_PENCIL
WM_operatortype_append(WM_OT_gpencil_import_svg);
WM_operatortype_append(WM_OT_grease_pencil_import_svg); WM_operatortype_append(WM_OT_grease_pencil_import_svg);
ed::io::grease_pencil_file_handler_add(); ed::io::grease_pencil_file_handler_add();
# ifdef WITH_PUGIXML # ifdef WITH_PUGIXML
WM_operatortype_append(WM_OT_gpencil_export_svg);
WM_operatortype_append(WM_OT_grease_pencil_export_svg); WM_operatortype_append(WM_OT_grease_pencil_export_svg);
# endif # endif
# ifdef WITH_HARU # ifdef WITH_HARU
WM_operatortype_append(WM_OT_gpencil_export_pdf);
WM_operatortype_append(WM_OT_grease_pencil_export_pdf); WM_operatortype_append(WM_OT_grease_pencil_export_pdf);
# endif # endif
#endif #endif

View File

@@ -2895,19 +2895,12 @@ static int object_convert_exec(bContext *C, wmOperator *op)
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Scene *scene = CTX_data_scene(C); Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C); ViewLayer *view_layer = CTX_data_view_layer(C);
View3D *v3d = CTX_wm_view3d(C);
Base *basen = nullptr, *basact = nullptr; Base *basen = nullptr, *basact = nullptr;
Object *ob1, *obact = CTX_data_active_object(C); Object *ob1, *obact = CTX_data_active_object(C);
const short target = RNA_enum_get(op->ptr, "target"); const short target = RNA_enum_get(op->ptr, "target");
bool keep_original = RNA_boolean_get(op->ptr, "keep_original"); bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
const bool do_merge_customdata = RNA_boolean_get(op->ptr, "merge_customdata"); const bool do_merge_customdata = RNA_boolean_get(op->ptr, "merge_customdata");
const float angle = RNA_float_get(op->ptr, "angle");
const int thickness = RNA_int_get(op->ptr, "thickness");
const bool use_seams = RNA_boolean_get(op->ptr, "seams");
const bool use_faces = RNA_boolean_get(op->ptr, "faces");
const float offset = RNA_float_get(op->ptr, "offset");
int mballConverted = 0; int mballConverted = 0;
bool gpencilConverted = false; bool gpencilConverted = false;
bool gpencilCurveConverted = false; bool gpencilCurveConverted = false;
@@ -3024,53 +3017,6 @@ static int object_convert_exec(bContext *C, wmOperator *op)
} }
} }
} }
else if (ob->type == OB_MESH && target == OB_GPENCIL_LEGACY) {
ob->flag |= OB_DONE;
/* Create a new grease pencil object and copy transformations. */
ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uid : 0;
float loc[3], size[3], rot[3][3], eul[3];
float matrix[4][4];
mat4_to_loc_rot_size(loc, rot, size, ob->object_to_world().ptr());
mat3_to_eul(eul, rot);
Object *ob_gpencil = ED_gpencil_add_object(C, loc, local_view_bits);
copy_v3_v3(ob_gpencil->loc, loc);
copy_v3_v3(ob_gpencil->rot, eul);
copy_v3_v3(ob_gpencil->scale, size);
unit_m4(matrix);
/* Set object in 3D mode. */
bGPdata *gpd = (bGPdata *)ob_gpencil->data;
gpd->draw_mode = GP_DRAWMODE_3D;
gpencilConverted |= BKE_gpencil_convert_mesh(bmain,
depsgraph,
scene,
ob_gpencil,
ob,
angle,
thickness,
offset,
matrix,
0,
use_seams,
use_faces,
true);
/* Remove unused materials. */
int actcol = ob_gpencil->actcol;
for (int slot = 1; slot <= ob_gpencil->totcol; slot++) {
while (slot <= ob_gpencil->totcol && !BKE_object_material_slot_used(ob_gpencil, slot)) {
ob_gpencil->actcol = slot;
BKE_object_material_slot_remove(CTX_data_main(C), ob_gpencil);
if (actcol >= slot) {
actcol--;
}
}
}
ob_gpencil->actcol = actcol;
}
else if (target == OB_CURVES) { else if (target == OB_CURVES) {
ob->flag |= OB_DONE; ob->flag |= OB_DONE;
@@ -3419,16 +3365,6 @@ static int object_convert_exec(bContext *C, wmOperator *op)
/* Meshes doesn't use the "curve cache". */ /* Meshes doesn't use the "curve cache". */
BKE_object_free_curve_cache(newob); BKE_object_free_curve_cache(newob);
} }
else if (target == OB_GPENCIL_LEGACY) {
ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uid : 0;
Object *ob_gpencil = ED_gpencil_add_object(C, newob->loc, local_view_bits);
copy_v3_v3(ob_gpencil->rot, newob->rot);
copy_v3_v3(ob_gpencil->scale, newob->scale);
BKE_gpencil_convert_curve(bmain, scene, ob_gpencil, newob, false, 1.0f, 0.0f);
gpencilConverted = true;
gpencilCurveConverted = true;
basen = nullptr;
}
} }
else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) { else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
ob->flag |= OB_DONE; ob->flag |= OB_DONE;
@@ -3454,23 +3390,6 @@ static int object_convert_exec(bContext *C, wmOperator *op)
/* Meshes don't use the "curve cache". */ /* Meshes don't use the "curve cache". */
BKE_object_free_curve_cache(newob); BKE_object_free_curve_cache(newob);
} }
else if (target == OB_GPENCIL_LEGACY) {
if (ob->type != OB_CURVES_LEGACY) {
ob->flag &= ~OB_DONE;
BKE_report(op->reports, RPT_ERROR, "Convert Surfaces to Grease Pencil is not supported");
}
else {
/* Create a new grease pencil object and copy transformations.
* Nurbs Surface are not supported.
*/
ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uid : 0;
Object *ob_gpencil = ED_gpencil_add_object(C, ob->loc, local_view_bits);
copy_v3_v3(ob_gpencil->rot, ob->rot);
copy_v3_v3(ob_gpencil->scale, ob->scale);
BKE_gpencil_convert_curve(bmain, scene, ob_gpencil, ob, false, 1.0f, 0.0f);
gpencilConverted = true;
}
}
} }
else if (ob->type == OB_MBALL && target == OB_MESH) { else if (ob->type == OB_MBALL && target == OB_MESH) {
Object *baseob; Object *baseob;
@@ -4389,9 +4308,6 @@ static int object_join_exec(bContext *C, wmOperator *op)
else if (ob->type == OB_ARMATURE) { else if (ob->type == OB_ARMATURE) {
ret = ED_armature_join_objects_exec(C, op); ret = ED_armature_join_objects_exec(C, op);
} }
else if (ob->type == OB_GPENCIL_LEGACY) {
ret = ED_gpencil_join_objects_exec(C, op);
}
else if (ob->type == OB_GREASE_PENCIL) { else if (ob->type == OB_GREASE_PENCIL) {
ret = ED_grease_pencil_join_objects_exec(C, op); ret = ED_grease_pencil_join_objects_exec(C, op);
} }

View File

@@ -292,14 +292,6 @@ static bool ed_object_mode_generic_exit_ex(
} }
ED_object_particle_edit_mode_exit_ex(scene, ob); ED_object_particle_edit_mode_exit_ex(scene, ob);
} }
else if (ob->type == OB_GPENCIL_LEGACY) {
/* Accounted for above. */
BLI_assert((ob->mode & OB_MODE_OBJECT) == 0);
if (only_test) {
return true;
}
ED_object_gpencil_exit(bmain, ob);
}
else if (ob->type == OB_GREASE_PENCIL) { else if (ob->type == OB_GREASE_PENCIL) {
BLI_assert((ob->mode & OB_MODE_OBJECT) == 0); BLI_assert((ob->mode & OB_MODE_OBJECT) == 0);
if (only_test) { if (only_test) {

View File

@@ -735,23 +735,6 @@ bool parent_set(ReportList *reports,
invert_m4_m4(ob->parentinv, BKE_object_calc_parent(depsgraph, scene, ob).ptr()); invert_m4_m4(ob->parentinv, BKE_object_calc_parent(depsgraph, scene, ob).ptr());
} }
else if (is_armature_parent && (ob->type == OB_GPENCIL_LEGACY) && (par->type == OB_ARMATURE)) {
if (partype == PAR_ARMATURE) {
ED_gpencil_add_armature(C, reports, ob, par);
}
else if (partype == PAR_ARMATURE_NAME) {
ED_gpencil_add_armature_weights(C, reports, ob, par, GP_PAR_ARMATURE_NAME);
}
else if (ELEM(partype, PAR_ARMATURE_AUTO, PAR_ARMATURE_ENVELOPE)) {
WM_cursor_wait(true);
ED_gpencil_add_armature_weights(C, reports, ob, par, GP_PAR_ARMATURE_AUTO);
WM_cursor_wait(false);
}
/* get corrected inverse */
ob->partype = PAROBJECT;
invert_m4_m4(ob->parentinv, BKE_object_calc_parent(depsgraph, scene, ob).ptr());
}
else if (is_armature_parent && (ob->type == OB_GREASE_PENCIL) && (par->type == OB_ARMATURE)) { else if (is_armature_parent && (ob->type == OB_GREASE_PENCIL) && (par->type == OB_ARMATURE)) {
if (partype == PAR_ARMATURE_NAME) { if (partype == PAR_ARMATURE_NAME) {
ed::greasepencil::add_armature_vertex_groups(*ob, *par); ed::greasepencil::add_armature_vertex_groups(*ob, *par);

View File

@@ -96,15 +96,8 @@ const char *screen_context_dir[] = {
"selected_nla_strips", /* nla editor */ "selected_nla_strips", /* nla editor */
"selected_movieclip_tracks", "selected_movieclip_tracks",
/* Legacy Grease Pencil */ /* Legacy Grease Pencil */
"gpencil_data",
"gpencil_data_owner",
"annotation_data", "annotation_data",
"annotation_data_owner", "annotation_data_owner",
"visible_gpencil_layers",
"editable_gpencil_layers",
"editable_gpencil_strokes",
"active_gpencil_layer",
"active_gpencil_frame",
"active_annotation_layer", "active_annotation_layer",
/* Grease Pencil v3 */ /* Grease Pencil v3 */
"grease_pencil", "grease_pencil",
@@ -803,47 +796,7 @@ static eContextResult screen_ctx_selected_movieclip_tracks(const bContext *C,
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK; return CTX_RESULT_OK;
} }
static eContextResult screen_ctx_gpencil_data(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
ScrArea *area = CTX_wm_area(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
/* FIXME: for some reason, CTX_data_active_object(C) returns nullptr when called from these
* situations (as outlined above - see Campbell's #ifdefs).
* That causes the get_active function to fail when called from context.
* For that reason, we end up using an alternative where we pass everything in!
*/
bGPdata *gpd = ED_gpencil_data_get_active_direct(area, obact);
if (gpd) {
CTX_data_id_pointer_set(result, &gpd->id);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_gpencil_data_owner(const bContext *C, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
ScrArea *area = CTX_wm_area(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
/* Pointer to which data/datablock owns the reference to the Grease Pencil data being used
* (as gpencil_data). */
PointerRNA ptr;
bGPdata **gpd_ptr = ED_gpencil_data_get_pointers_direct(area, obact, &ptr);
if (gpd_ptr) {
CTX_data_pointer_set_ptr(result, &ptr);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_annotation_data(const bContext *C, bContextDataResult *result) static eContextResult screen_ctx_annotation_data(const bContext *C, bContextDataResult *result)
{ {
wmWindow *win = CTX_wm_window(C); wmWindow *win = CTX_wm_window(C);
@@ -876,27 +829,6 @@ static eContextResult screen_ctx_annotation_data_owner(const bContext *C,
} }
return CTX_RESULT_NO_DATA; return CTX_RESULT_NO_DATA;
} }
static eContextResult screen_ctx_active_gpencil_layer(const bContext *C,
bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
ScrArea *area = CTX_wm_area(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
bGPdata *gpd = ED_gpencil_data_get_active_direct(area, obact);
if (gpd) {
bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
if (gpl) {
CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl);
return CTX_RESULT_OK;
}
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_active_annotation_layer(const bContext *C, static eContextResult screen_ctx_active_annotation_layer(const bContext *C,
bContextDataResult *result) bContextDataResult *result)
{ {
@@ -916,119 +848,6 @@ static eContextResult screen_ctx_active_annotation_layer(const bContext *C,
} }
return CTX_RESULT_NO_DATA; return CTX_RESULT_NO_DATA;
} }
static eContextResult screen_ctx_active_gpencil_frame(const bContext *C,
bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
ScrArea *area = CTX_wm_area(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
bGPdata *gpd = ED_gpencil_data_get_active_direct(area, obact);
if (gpd) {
bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
if (gpl) {
CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl->actframe);
return CTX_RESULT_OK;
}
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_visible_gpencil_layers(const bContext *C,
bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
ScrArea *area = CTX_wm_area(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
bGPdata *gpd = ED_gpencil_data_get_active_direct(area, obact);
if (gpd) {
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if ((gpl->flag & GP_LAYER_HIDE) == 0) {
CTX_data_list_add(result, &gpd->id, &RNA_GPencilLayer, gpl);
}
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_editable_gpencil_layers(const bContext *C,
bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
ScrArea *area = CTX_wm_area(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
bGPdata *gpd = ED_gpencil_data_get_active_direct(area, obact);
if (gpd) {
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (BKE_gpencil_layer_is_editable(gpl)) {
CTX_data_list_add(result, &gpd->id, &RNA_GPencilLayer, gpl);
}
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_editable_gpencil_strokes(const bContext *C,
bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
ScrArea *area = CTX_wm_area(C);
const Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obact = BKE_view_layer_active_object_get(view_layer);
bGPdata *gpd = ED_gpencil_data_get_active_direct(area, obact);
const bool is_multiedit = bool(GPENCIL_MULTIEDIT_SESSIONS_ON(gpd));
if (gpd == nullptr) {
return CTX_RESULT_NO_DATA;
}
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe)) {
bGPDframe *gpf;
bGPDframe *init_gpf = gpl->actframe;
if (is_multiedit) {
init_gpf = static_cast<bGPDframe *>(gpl->frames.first);
}
for (gpf = init_gpf; gpf; gpf = gpf->next) {
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if (ED_gpencil_stroke_can_use_direct(area, gps)) {
/* check if the color is editable */
if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) {
continue;
}
CTX_data_list_add(result, &gpd->id, &RNA_GPencilStroke, gps);
}
}
}
/* If not multi-edit out of loop. */
if (!is_multiedit) {
break;
}
}
}
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
static eContextResult screen_ctx_grease_pencil_data(const bContext *C, bContextDataResult *result) static eContextResult screen_ctx_grease_pencil_data(const bContext *C, bContextDataResult *result)
{ {
wmWindow *win = CTX_wm_window(C); wmWindow *win = CTX_wm_window(C);
@@ -1377,16 +1196,9 @@ static void ensure_ed_screen_context_functions()
register_context_function("active_nla_strip", screen_ctx_active_nla_strip); register_context_function("active_nla_strip", screen_ctx_active_nla_strip);
register_context_function("selected_nla_strips", screen_ctx_selected_nla_strips); register_context_function("selected_nla_strips", screen_ctx_selected_nla_strips);
register_context_function("selected_movieclip_tracks", screen_ctx_selected_movieclip_tracks); register_context_function("selected_movieclip_tracks", screen_ctx_selected_movieclip_tracks);
register_context_function("gpencil_data", screen_ctx_gpencil_data);
register_context_function("gpencil_data_owner", screen_ctx_gpencil_data_owner);
register_context_function("annotation_data", screen_ctx_annotation_data); register_context_function("annotation_data", screen_ctx_annotation_data);
register_context_function("annotation_data_owner", screen_ctx_annotation_data_owner); register_context_function("annotation_data_owner", screen_ctx_annotation_data_owner);
register_context_function("active_gpencil_layer", screen_ctx_active_gpencil_layer);
register_context_function("active_annotation_layer", screen_ctx_active_annotation_layer); register_context_function("active_annotation_layer", screen_ctx_active_annotation_layer);
register_context_function("active_gpencil_frame", screen_ctx_active_gpencil_frame);
register_context_function("visible_gpencil_layers", screen_ctx_visible_gpencil_layers);
register_context_function("editable_gpencil_layers", screen_ctx_editable_gpencil_layers);
register_context_function("editable_gpencil_strokes", screen_ctx_editable_gpencil_strokes);
register_context_function("grease_pencil", screen_ctx_grease_pencil_data); register_context_function("grease_pencil", screen_ctx_grease_pencil_data);
register_context_function("active_operator", screen_ctx_active_operator); register_context_function("active_operator", screen_ctx_active_operator);
register_context_function("active_action", screen_ctx_active_action); register_context_function("active_action", screen_ctx_active_action);

View File

@@ -1396,15 +1396,6 @@ static void draw_selected_name(
if (id_frame_has_keyframe((ID *)ob, /* BKE_scene_ctime_get(scene) */ float(cfra))) { if (id_frame_has_keyframe((ID *)ob, /* BKE_scene_ctime_get(scene) */ float(cfra))) {
UI_FontThemeColor(font_id, TH_TIME_KEYFRAME); UI_FontThemeColor(font_id, TH_TIME_KEYFRAME);
} }
else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra)) {
UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME);
}
}
else {
/* no object */
if (ED_gpencil_has_keyframe_v3d(scene, nullptr, cfra)) {
UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME);
}
} }
if (markern) { if (markern) {

View File

@@ -150,14 +150,12 @@ void uiTemplateHeader3D_mode(uiLayout *layout, bContext *C)
BKE_view_layer_synced_ensure(scene, view_layer); BKE_view_layer_synced_ensure(scene, view_layer);
Object *ob = BKE_view_layer_active_object_get(view_layer); Object *ob = BKE_view_layer_active_object_get(view_layer);
Object *obedit = CTX_data_edit_object(C); Object *obedit = CTX_data_edit_object(C);
bGPdata *gpd = CTX_data_gpencil_data(C);
bool is_paint = (ob && !(gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE)) && bool is_paint = (ob && ELEM(ob->mode,
ELEM(ob->mode, OB_MODE_SCULPT,
OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT,
OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT,
OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT));
OB_MODE_TEXTURE_PAINT));
uiTemplateEditModeSelection(layout, C); uiTemplateEditModeSelection(layout, C);
if ((obedit == nullptr) && is_paint) { if ((obedit == nullptr) && is_paint) {

View File

@@ -309,12 +309,7 @@ static int viewselected_exec(bContext *C, wmOperator *op)
BKE_view_layer_synced_ensure(scene_eval, view_layer_eval); BKE_view_layer_synced_ensure(scene_eval, view_layer_eval);
Object *ob_eval = BKE_view_layer_active_object_get(view_layer_eval); Object *ob_eval = BKE_view_layer_active_object_get(view_layer_eval);
Object *obedit = CTX_data_edit_object(C); Object *obedit = CTX_data_edit_object(C);
const bGPdata *gpd_eval = ob_eval && (ob_eval->type == OB_GPENCIL_LEGACY) ? const bool is_face_map = (region->gizmo_map && WM_gizmomap_is_any_selected(region->gizmo_map));
static_cast<const bGPdata *>(ob_eval->data) :
nullptr;
const bool is_gp_edit = gpd_eval ? GPENCIL_ANY_MODE(gpd_eval) : false;
const bool is_face_map = ((is_gp_edit == false) && region->gizmo_map &&
WM_gizmomap_is_any_selected(region->gizmo_map));
float3 min, max; float3 min, max;
bool ok = false, ok_dist = true; bool ok = false, ok_dist = true;
const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions"); const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions");
@@ -349,38 +344,7 @@ static int viewselected_exec(bContext *C, wmOperator *op)
} }
} }
if (is_gp_edit) { if (is_face_map) {
CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
/* we're only interested in selected points here... */
if ((gps->flag & GP_STROKE_SELECT) && (gps->flag & GP_STROKE_3DSPACE)) {
ok |= BKE_gpencil_stroke_minmax(gps, true, min, max);
}
if (gps->editcurve != nullptr) {
for (int i = 0; i < gps->editcurve->tot_curve_points; i++) {
BezTriple *bezt = &gps->editcurve->curve_points[i].bezt;
if (bezt->f1 & SELECT) {
minmax_v3v3_v3(min, max, bezt->vec[0]);
ok = true;
}
if (bezt->f2 & SELECT) {
minmax_v3v3_v3(min, max, bezt->vec[1]);
ok = true;
}
if (bezt->f3 & SELECT) {
minmax_v3v3_v3(min, max, bezt->vec[2]);
ok = true;
}
}
}
}
CTX_DATA_END;
if ((ob_eval) && (ok)) {
mul_m4_v3(ob_eval->object_to_world().ptr(), min);
mul_m4_v3(ob_eval->object_to_world().ptr(), max);
}
}
else if (is_face_map) {
ok = WM_gizmomap_minmax(region->gizmo_map, true, true, min, max); ok = WM_gizmomap_minmax(region->gizmo_map, true, true, min, max);
} }
else if (obedit) { else if (obedit) {

View File

@@ -128,7 +128,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
ARegion *region = CTX_wm_region(C); ARegion *region = CTX_wm_region(C);
ScrArea *area = CTX_wm_area(C); ScrArea *area = CTX_wm_area(C);
bGPdata *gpd = CTX_data_gpencil_data(C);
PropertyRNA *prop; PropertyRNA *prop;
t->mbus = CTX_wm_message_bus(C); t->mbus = CTX_wm_message_bus(C);
@@ -219,11 +218,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
} }
} }
/* GPencil editing context. */
if (GPENCIL_EDIT_MODE(gpd)) {
t->options |= CTX_GPENCIL_STROKES;
}
/* Grease Pencil editing context. */ /* Grease Pencil editing context. */
if (t->obedit_type == OB_GREASE_PENCIL && object_mode == OB_MODE_EDIT && if (t->obedit_type == OB_GREASE_PENCIL && object_mode == OB_MODE_EDIT &&
(area->spacetype == SPACE_VIEW3D)) (area->spacetype == SPACE_VIEW3D))

View File

@@ -541,71 +541,11 @@ static int gizmo_3d_foreach_selected(const bContext *C,
Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C); Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C);
ViewLayer *view_layer = CTX_data_view_layer(C); ViewLayer *view_layer = CTX_data_view_layer(C);
View3D *v3d = static_cast<View3D *>(area->spacedata.first); View3D *v3d = static_cast<View3D *>(area->spacedata.first);
bGPdata *gpd = CTX_data_gpencil_data(C);
const bool is_gp_edit = GPENCIL_ANY_MODE(gpd);
const bool is_curve_edit = GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
int a, totsel = 0; int a, totsel = 0;
Object *ob = gizmo_3d_transform_space_object_get(scene, view_layer); Object *ob = gizmo_3d_transform_space_object_get(scene, view_layer);
if (is_gp_edit) { if (Object *obedit = OBEDIT_FROM_OBACT(ob)) {
float diff_mat[4][4];
const bool use_mat_local = true;
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* Only editable and visible layers are considered. */
if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != nullptr)) {
/* Calculate difference matrix. */
BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat);
LISTBASE_FOREACH (bGPDstroke *, gps, &gpl->actframe->strokes) {
/* Skip strokes that are invalid for current view. */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
}
if (is_curve_edit) {
if (gps->editcurve == nullptr) {
continue;
}
bGPDcurve *gpc = gps->editcurve;
if (gpc->flag & GP_CURVE_SELECT) {
for (uint32_t 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) {
for (uint32_t j = 0; j < 3; j++) {
if (BEZT_ISSEL_IDX(bezt, j)) {
run_coord_with_matrix(bezt->vec[j], use_mat_local, diff_mat);
totsel++;
}
}
}
}
}
}
else {
/* We're only interested in selected points here... */
if (gps->flag & GP_STROKE_SELECT) {
bGPDspoint *pt;
int i;
/* Change selection status of all points, then make the stroke match. */
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
if (pt->flag & GP_SPOINT_SELECT) {
run_coord_with_matrix(&pt->x, use_mat_local, diff_mat);
totsel++;
}
}
}
}
}
}
}
}
else if (Object *obedit = OBEDIT_FROM_OBACT(ob)) {
#define FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) \ #define FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) \
{ \ { \
@@ -1037,9 +977,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
if (totsel) { if (totsel) {
mul_v3_fl(tbounds->center, 1.0f / float(totsel)); /* Centroid! */ mul_v3_fl(tbounds->center, 1.0f / float(totsel)); /* Centroid! */
bGPdata *gpd = CTX_data_gpencil_data(C); if (obedit || (ob && (ob->mode & (OB_MODE_POSE | OB_MODE_SCULPT)))) {
const bool is_gp_edit = GPENCIL_ANY_MODE(gpd);
if (!is_gp_edit && (obedit || (ob && (ob->mode & (OB_MODE_POSE | OB_MODE_SCULPT))))) {
if (ob->mode & OB_MODE_POSE) { if (ob->mode & OB_MODE_POSE) {
invert_m4_m4(ob->runtime->world_to_object.ptr(), ob->object_to_world().ptr()); invert_m4_m4(ob->runtime->world_to_object.ptr(), ob->object_to_world().ptr());
} }

View File

@@ -167,7 +167,6 @@ static void ed_undo_step_pre(bContext *C,
Main *bmain = CTX_data_main(C); Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C); Scene *scene = CTX_data_scene(C);
ScrArea *area = CTX_wm_area(C);
/* undo during jobs are running can easily lead to freeing data using by jobs, /* undo during jobs are running can easily lead to freeing data using by jobs,
* or they can just lead to freezing job in some other cases */ * or they can just lead to freezing job in some other cases */
@@ -181,13 +180,6 @@ static void ed_undo_step_pre(bContext *C,
} }
} }
if (area && (area->spacetype == SPACE_VIEW3D)) {
Object *obact = CTX_data_active_object(C);
if (obact && (obact->type == OB_GPENCIL_LEGACY)) {
ED_gpencil_toggle_brush_cursor(C, false, nullptr);
}
}
/* App-Handlers (pre). */ /* App-Handlers (pre). */
{ {
/* NOTE: ignore grease pencil for now. */ /* NOTE: ignore grease pencil for now. */
@@ -213,24 +205,6 @@ static void ed_undo_step_post(bContext *C,
Main *bmain = CTX_data_main(C); Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C); Scene *scene = CTX_data_scene(C);
ScrArea *area = CTX_wm_area(C);
/* Set special modes for grease pencil */
if (area != nullptr && (area->spacetype == SPACE_VIEW3D)) {
Object *obact = CTX_data_active_object(C);
if (obact && (obact->type == OB_GPENCIL_LEGACY)) {
/* set cursor */
if (obact->mode & OB_MODE_ALL_PAINT_GPENCIL) {
ED_gpencil_toggle_brush_cursor(C, true, nullptr);
}
else {
ED_gpencil_toggle_brush_cursor(C, false, nullptr);
}
/* set workspace mode */
Base *basact = CTX_data_active_base(C);
object::base_activate(C, basact);
}
}
/* App-Handlers (post). */ /* App-Handlers (post). */
{ {

View File

@@ -121,23 +121,6 @@ void ED_editors_init(bContext *C)
/* For multi-edit mode we may already have mode data. */ /* For multi-edit mode we may already have mode data. */
continue; continue;
} }
if (ob->type == OB_GPENCIL_LEGACY) {
/* Grease pencil does not need a toggle of mode. However we may have a non-active object
* stuck in a grease-pencil edit mode. */
if (ob != obact) {
bGPdata *gpd = (bGPdata *)ob->data;
gpd->flag &= ~(GP_DATA_STROKE_PAINTMODE | GP_DATA_STROKE_EDITMODE |
GP_DATA_STROKE_SCULPTMODE | GP_DATA_STROKE_WEIGHTMODE |
GP_DATA_STROKE_VERTEXMODE);
ob->mode = OB_MODE_OBJECT;
DEG_id_tag_update(&ob->id, ID_RECALC_SYNC_TO_EVAL);
}
else if (mode & OB_MODE_ALL_PAINT_GPENCIL) {
ED_gpencil_toggle_brush_cursor(C, true, nullptr);
BKE_paint_ensure_from_paintmode(bmain, scene, BKE_paintmode_get_active_from_context(C));
}
continue;
}
/* Reset object to Object mode, so that code below can properly re-switch it to its /* Reset object to Object mode, so that code below can properly re-switch it to its
* previous mode if possible, re-creating its mode data, etc. */ * previous mode if possible, re-creating its mode data, etc. */

View File

@@ -19,7 +19,6 @@ if(WITH_IO_STL)
endif() endif()
if(WITH_IO_GREASE_PENCIL) if(WITH_IO_GREASE_PENCIL)
add_subdirectory(gpencil_legacy)
add_subdirectory(grease_pencil) add_subdirectory(grease_pencil)
endif() endif()

View File

@@ -1,87 +0,0 @@
# SPDX-FileCopyrightText: 2006 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
set(INC
.
../common
../../blenkernel
../../blenloader
../../bmesh
../../editors/include
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
../../../../intern/utfconv
)
set(INC_SYS
)
set(SRC
intern/gpencil_io_base.cc
intern/gpencil_io_capi.cc
intern/gpencil_io_import_base.cc
intern/gpencil_io_import_svg.cc
gpencil_io.h
intern/gpencil_io_base.hh
intern/gpencil_io_export_base.hh
intern/gpencil_io_import_base.hh
intern/gpencil_io_import_svg.hh
)
set(LIB
bf_blenkernel
PRIVATE bf::blenlib
PRIVATE bf::depsgraph
PRIVATE bf::dna
PRIVATE bf::extern::nanosvg
PRIVATE bf::intern::clog
PRIVATE bf::intern::guardedalloc
bf_io_common
)
if(WITH_PUGIXML)
list(APPEND SRC
intern/gpencil_io_export_svg.cc
intern/gpencil_io_export_svg.hh
)
list(APPEND INC_SYS
${PUGIXML_INCLUDE_DIR}
)
list(APPEND LIB
${PUGIXML_LIBRARIES}
)
add_definitions(-DWITH_PUGIXML)
endif()
if(WITH_HARU)
list(APPEND SRC
intern/gpencil_io_export_pdf.cc
intern/gpencil_io_export_pdf.hh
)
list(APPEND INC_SYS
${HARU_INCLUDE_DIRS}
)
list(APPEND LIB
${HARU_LIBRARIES}
# Haru needs `TIFFFaxBlackCodes` & `TIFFFaxWhiteCodes` symbols from TIFF.
# Can be removed with Haru 2.4.0. They should be shipping with their own
# Fax codes defined by default from that version onward.
${TIFF_LIBRARY}
)
add_definitions(-DWITH_HARU)
endif()
if(WITH_BOOST)
list(APPEND LIB
${BOOST_LIBRARIES}
)
endif()
blender_add_lib(bf_io_gpencil_legacy "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

View File

@@ -1,86 +0,0 @@
/* SPDX-FileCopyrightText: 2020 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bgpencil
*/
#ifdef __cplusplus
extern "C" {
#endif
struct ARegion;
struct Object;
struct View3D;
struct bContext;
typedef struct GpencilIOParams {
bContext *C;
ARegion *region;
View3D *v3d;
/** Grease pencil object. */
Object *ob;
/** Mode (see eGpencilIO_Modes). */
uint16_t mode;
int32_t frame_start;
int32_t frame_end;
int32_t frame_cur;
uint32_t flag;
float scale;
/** Select mode (see eGpencilExportSelect). */
uint16_t select_mode;
/** Frame mode (see eGpencilExportFrame). */
uint16_t frame_mode;
/** Stroke sampling factor. */
float stroke_sample;
int32_t resolution;
/** Filename to be used in new objects. */
char filename[128];
} GpencilIOParams;
/* GpencilIOParams->flag. */
typedef enum eGpencilIOParams_Flag {
/* Export Filled strokes. */
GP_EXPORT_FILL = (1 << 0),
/* Export normalized thickness. */
GP_EXPORT_NORM_THICKNESS = (1 << 1),
/* Clip camera area. */
GP_EXPORT_CLIP_CAMERA = (1 << 2),
} eGpencilIOParams_Flag;
typedef enum eGpencilIO_Modes {
GP_EXPORT_TO_SVG = 0,
GP_EXPORT_TO_PDF = 1,
GP_IMPORT_FROM_SVG = 2,
/* Add new formats here. */
} eGpencilIO_Modes;
/* Object to be exported. */
typedef enum eGpencilExportSelect {
GP_EXPORT_ACTIVE = 0,
GP_EXPORT_SELECTED = 1,
GP_EXPORT_VISIBLE = 2,
} eGpencilExportSelect;
/** Frame-range to be exported. */
typedef enum eGpencilExportFrame {
GP_EXPORT_FRAME_ACTIVE = 0,
GP_EXPORT_FRAME_SELECTED = 1,
GP_EXPORT_FRAME_SCENE = 2,
} eGpencilExportFrame;
/**
* Main export entry point function.
*/
bool gpencil_io_export(const char *filepath, struct GpencilIOParams *iparams);
/**
* Main import entry point function.
*/
bool gpencil_io_import(const char *filepath, struct GpencilIOParams *iparams);
#ifdef __cplusplus
}
#endif

View File

@@ -1,368 +0,0 @@
/* SPDX-FileCopyrightText: 2020 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bgpencil
*/
#include "BLI_math_matrix.hh"
#include "BLI_path_utils.hh"
#include "BLI_span.hh"
#include "BLI_string.h"
#include "DNA_gpencil_legacy_types.h"
#include "DNA_layer_types.h"
#include "DNA_material_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "BKE_camera.h"
#include "BKE_context.hh"
#include "BKE_gpencil_geom_legacy.h"
#include "BKE_gpencil_legacy.h"
#include "BKE_layer.hh"
#include "BKE_main.hh"
#include "BKE_material.h"
#include "BKE_scene.hh"
#include "UI_view2d.hh"
#include "ED_view3d.hh"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_query.hh"
#include "gpencil_io_base.hh"
using blender::Span;
namespace blender::io::gpencil {
/* Constructor. */
GpencilIO::GpencilIO(const GpencilIOParams *iparams)
{
params_ = *iparams;
/* Easy access data. */
bmain_ = CTX_data_main(params_.C);
depsgraph_ = CTX_data_depsgraph_pointer(params_.C);
scene_ = CTX_data_scene(params_.C);
rv3d_ = (RegionView3D *)params_.region->regiondata;
gpd_ = (params_.ob != nullptr) ? (bGPdata *)params_.ob->data : nullptr;
cfra_ = iparams->frame_cur;
/* Calculate camera matrix. */
prepare_camera_params(scene_, iparams);
}
void GpencilIO::prepare_camera_params(Scene *scene, const GpencilIOParams *iparams)
{
params_ = *iparams;
const bool is_pdf = params_.mode == GP_EXPORT_TO_PDF;
const bool any_camera = (params_.v3d->camera != nullptr);
const bool force_camera_view = is_pdf && any_camera;
/* Ensure camera switch is applied. */
BKE_scene_camera_switch_update(scene);
/* Calculate camera matrix. */
Object *cam_ob = scene->camera;
if (cam_ob != nullptr) {
/* Set up parameters. */
CameraParams params;
BKE_camera_params_init(&params);
BKE_camera_params_from_object(&params, cam_ob);
/* Compute matrix, view-plane, etc. */
RenderData *rd = &scene_->r;
BKE_camera_params_compute_viewplane(&params, rd->xsch, rd->ysch, rd->xasp, rd->yasp);
BKE_camera_params_compute_matrix(&params);
float4x4 viewmat = math::invert(cam_ob->object_to_world());
persmat_ = float4x4(params.winmat) * viewmat;
}
else {
persmat_ = float4x4::identity();
}
winx_ = params_.region->winx;
winy_ = params_.region->winy;
/* Camera rectangle. */
if ((rv3d_->persp == RV3D_CAMOB) || (force_camera_view)) {
BKE_render_resolution(&scene->r, false, &render_x_, &render_y_);
ED_view3d_calc_camera_border(CTX_data_scene(params_.C),
depsgraph_,
params_.region,
params_.v3d,
rv3d_,
true,
&camera_rect_);
is_camera_ = true;
camera_ratio_ = render_x_ / (camera_rect_.xmax - camera_rect_.xmin);
offset_.x = camera_rect_.xmin;
offset_.y = camera_rect_.ymin;
}
else {
is_camera_ = false;
/* Calc selected object boundbox. Need set initial value to some variables. */
camera_ratio_ = 1.0f;
offset_.x = 0.0f;
offset_.y = 0.0f;
create_object_list();
selected_objects_boundbox_calc();
rctf boundbox;
selected_objects_boundbox_get(&boundbox);
render_x_ = boundbox.xmax - boundbox.xmin;
render_y_ = boundbox.ymax - boundbox.ymin;
offset_.x = boundbox.xmin;
offset_.y = boundbox.ymin;
}
}
void GpencilIO::create_object_list()
{
Scene *scene = CTX_data_scene(params_.C);
ViewLayer *view_layer = CTX_data_view_layer(params_.C);
float3 camera_z_axis = float3(rv3d_->viewinv[2]);
ob_list_.clear();
BKE_view_layer_synced_ensure(scene, view_layer);
LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) {
Object *object = base->object;
if (object->type != OB_GPENCIL_LEGACY) {
continue;
}
if ((params_.select_mode == GP_EXPORT_ACTIVE) && (params_.ob != object)) {
continue;
}
if ((params_.select_mode == GP_EXPORT_SELECTED) && ((base->flag & BASE_SELECTED) == 0)) {
continue;
}
float3 object_position = float3(object->object_to_world().location());
/* Save z-depth from view to sort from back to front. */
if (is_camera_) {
float camera_z = math::dot(camera_z_axis, object_position);
ObjectZ obz = {camera_z, object};
ob_list_.append(obz);
}
else {
float zdepth = 0;
if (rv3d_->is_persp) {
zdepth = ED_view3d_calc_zfac(rv3d_, object_position);
}
else {
zdepth = -math::dot(camera_z_axis, object_position);
}
ObjectZ obz = {zdepth * -1.0f, object};
ob_list_.append(obz);
}
}
/* Sort list of objects from point of view. */
std::sort(ob_list_.begin(), ob_list_.end(), [](const ObjectZ &obz1, const ObjectZ &obz2) {
return obz1.zdepth < obz2.zdepth;
});
}
void GpencilIO::filepath_set(const char *filepath)
{
STRNCPY(filepath_, filepath);
BLI_path_abs(filepath_, BKE_main_blendfile_path(bmain_));
}
bool GpencilIO::gpencil_3D_point_to_screen_space(const float3 co, float2 &r_co)
{
float3 parent_co = math::transform_point(diff_mat_, co);
float2 screen_co;
eV3DProjTest test = (eV3DProjTest)(V3D_PROJ_RET_OK);
if (ED_view3d_project_float_global(params_.region, parent_co, screen_co, test) ==
V3D_PROJ_RET_OK)
{
if (!ELEM(V2D_IS_CLIPPED, screen_co[0], screen_co[1])) {
r_co = screen_co;
/* Invert X axis. */
if (invert_axis_[0]) {
r_co[0] = winx_ - r_co[0];
}
/* Invert Y axis. */
if (invert_axis_[1]) {
r_co[1] = winy_ - r_co[1];
}
/* Apply offset and scale. */
r_co -= offset_;
r_co *= camera_ratio_;
return true;
}
}
r_co[0] = V2D_IS_CLIPPED;
r_co[1] = V2D_IS_CLIPPED;
/* Invert X axis. */
if (invert_axis_[0]) {
r_co[0] = winx_ - r_co[0];
}
/* Invert Y axis. */
if (invert_axis_[1]) {
r_co[1] = winy_ - r_co[1];
}
return false;
}
float2 GpencilIO::gpencil_3D_point_to_render_space(const float3 co)
{
float3 parent_co = math::transform_point(diff_mat_, co);
float2 r_co = float2(math::project_point(persmat_, parent_co));
r_co = ((r_co + 1.0f) / 2.0f) * float2(render_x_, render_y_);
/* Invert X axis. */
if (invert_axis_[0]) {
r_co.x = float(render_x_) - r_co.x;
}
/* Invert Y axis. */
if (invert_axis_[1]) {
r_co.y = float(render_y_) - r_co.y;
}
return r_co;
}
float2 GpencilIO::gpencil_3D_point_to_2D(const float3 co)
{
const bool is_camera = bool(rv3d_->persp == RV3D_CAMOB);
if (is_camera) {
return gpencil_3D_point_to_render_space(co);
}
float2 result;
gpencil_3D_point_to_screen_space(co, result);
return result;
}
float GpencilIO::stroke_point_radius_get(bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps)
{
bGPDspoint *pt = &gps->points[0];
const float2 screen_co = gpencil_3D_point_to_2D(&pt->x);
/* Radius. */
bGPDstroke *gps_perimeter = BKE_gpencil_stroke_perimeter_from_view(
rv3d_->viewmat, gpd, gpl, gps, 3, diff_mat_.ptr(), 0.0f);
pt = &gps_perimeter->points[0];
const float2 screen_ex = gpencil_3D_point_to_2D(&pt->x);
const float2 v1 = screen_co - screen_ex;
float radius = math::length(v1);
BKE_gpencil_free_stroke(gps_perimeter);
return std::max(radius, 1.0f);
}
void GpencilIO::prepare_layer_export_matrix(Object *ob, bGPDlayer *gpl)
{
BKE_gpencil_layer_transform_matrix_get(depsgraph_, ob, gpl, diff_mat_.ptr());
diff_mat_ = diff_mat_ * float4x4(gpl->layer_invmat);
}
void GpencilIO::prepare_stroke_export_colors(Object *ob, bGPDstroke *gps)
{
MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
/* Stroke color. */
avg_opacity_ = 0.0f;
/* Get average vertex color and apply. */
float4 avg_color = {0.0f, 0.0f, 0.0f, 0.0f};
for (const bGPDspoint &pt : Span(gps->points, gps->totpoints)) {
avg_color += pt.vert_color;
avg_opacity_ += pt.strength;
}
avg_color /= float(gps->totpoints);
avg_opacity_ /= float(gps->totpoints);
stroke_color_ = math::interpolate(float4(gp_style->stroke_rgba), avg_color, avg_color[3]);
/* Apply vertex color for fill. */
fill_color_ = math::interpolate(
float4(gp_style->fill_rgba), float4(gps->vert_color_fill), gps->vert_color_fill[3]);
}
float GpencilIO::stroke_average_opacity_get()
{
return avg_opacity_;
}
bool GpencilIO::is_camera_mode()
{
return is_camera_;
}
void GpencilIO::selected_objects_boundbox_calc()
{
const float gap = 10.0f;
float2 min, max;
INIT_MINMAX2(min, max);
for (ObjectZ &obz : ob_list_) {
Object *ob = obz.ob;
/* Use evaluated version to get strokes with modifiers. */
Object *ob_eval = (Object *)DEG_get_evaluated_id(depsgraph_, &ob->id);
bGPdata *gpd_eval = (bGPdata *)ob_eval->data;
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_eval->layers) {
if (gpl->flag & GP_LAYER_HIDE) {
continue;
}
BKE_gpencil_layer_transform_matrix_get(depsgraph_, ob_eval, gpl, diff_mat_.ptr());
bGPDframe *gpf = gpl->actframe;
if (gpf == nullptr) {
continue;
}
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if (gps->totpoints == 0) {
continue;
}
for (const bGPDspoint &pt : MutableSpan(gps->points, gps->totpoints)) {
math::min_max(gpencil_3D_point_to_2D(&pt.x), min, max);
}
}
}
}
/* Add small gap. */
min -= gap;
max += gap;
select_boundbox_.xmin = min[0];
select_boundbox_.ymin = min[1];
select_boundbox_.xmax = max[0];
select_boundbox_.ymax = max[1];
}
void GpencilIO::selected_objects_boundbox_get(rctf *boundbox)
{
boundbox->xmin = select_boundbox_.xmin;
boundbox->xmax = select_boundbox_.xmax;
boundbox->ymin = select_boundbox_.ymin;
boundbox->ymax = select_boundbox_.ymax;
}
void GpencilIO::frame_number_set(const int value)
{
cfra_ = value;
}
} // namespace blender::io::gpencil

View File

@@ -1,111 +0,0 @@
/* SPDX-FileCopyrightText: 2020 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bgpencil
*/
#include "BLI_math_matrix_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_vector.hh"
#include "DNA_space_types.h" /* for FILE_MAX */
#include "gpencil_io.h"
struct Depsgraph;
struct Main;
struct Object;
struct RegionView3D;
struct Scene;
struct bGPDlayer;
struct bGPDstroke;
struct bGPdata;
using blender::Vector;
namespace blender::io::gpencil {
class GpencilIO {
public:
GpencilIO(const GpencilIOParams *iparams);
void frame_number_set(int value);
void prepare_camera_params(Scene *scene, const GpencilIOParams *iparams);
protected:
GpencilIOParams params_;
bool invert_axis_[2];
float4x4 diff_mat_;
char filepath_[FILE_MAX];
/* Used for sorting objects. */
struct ObjectZ {
float zdepth;
Object *ob;
};
/** List of included objects. */
blender::Vector<ObjectZ> ob_list_;
/* Data for easy access. */
Depsgraph *depsgraph_;
bGPdata *gpd_;
Main *bmain_;
Scene *scene_;
RegionView3D *rv3d_;
int winx_, winy_;
int render_x_, render_y_;
float camera_ratio_;
rctf camera_rect_;
float2 offset_;
int cfra_;
float4 stroke_color_, fill_color_;
/* Geometry functions. */
/** Convert to screen-space. */
bool gpencil_3D_point_to_screen_space(const float3 co, float2 &r_co);
/** Convert to render space. */
float2 gpencil_3D_point_to_render_space(const float3 co);
/** Convert to 2D. */
float2 gpencil_3D_point_to_2D(const float3 co);
/** Get radius of point. */
float stroke_point_radius_get(bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps);
/** Create a list of selected objects sorted from back to front */
void create_object_list();
bool is_camera_mode();
float stroke_average_opacity_get();
void prepare_layer_export_matrix(Object *ob, bGPDlayer *gpl);
void prepare_stroke_export_colors(Object *ob, bGPDstroke *gps);
/* Calculate selected strokes boundbox. */
void selected_objects_boundbox_calc();
void selected_objects_boundbox_get(rctf *boundbox);
/**
* Set file input_text full path.
* \param filepath: Path of the file provided by save dialog.
*/
void filepath_set(const char *filepath);
private:
float avg_opacity_;
bool is_camera_;
rctf select_boundbox_;
/* Camera matrix. */
float4x4 persmat_;
};
} // namespace blender::io::gpencil

View File

@@ -1,199 +0,0 @@
/* SPDX-FileCopyrightText: 2020 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bgpencil
*/
#include <cstdio>
#include "BLI_listbase.h"
#include "DNA_gpencil_legacy_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "BKE_context.hh"
#include "BKE_gpencil_legacy.h"
#include "BKE_main.hh"
#include "BKE_scene.hh"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_query.hh"
#include "../gpencil_io.h"
#ifdef WITH_HARU
# include "gpencil_io_export_pdf.hh"
#endif
#ifdef WITH_PUGIXML
# include "gpencil_io_export_svg.hh"
#endif
#include "gpencil_io_import_svg.hh"
#ifdef WITH_HARU
using blender::io::gpencil::GpencilExporterPDF;
#endif
#ifdef WITH_PUGIXML
using blender::io::gpencil::GpencilExporterSVG;
#endif
using blender::io::gpencil::GpencilImporterSVG;
/* Check if frame is included. */
#ifdef WITH_HARU
static bool is_keyframe_included(bGPdata *gpd_, const int32_t framenum, const bool use_selected)
{
/* Check if exist a frame. */
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_->layers) {
if (gpl->flag & GP_LAYER_HIDE) {
continue;
}
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
if (gpf->framenum == framenum) {
if ((!use_selected) || (use_selected && (gpf->flag & GP_FRAME_SELECT))) {
return true;
}
}
}
}
return false;
}
#endif
/* Import frame. */
static bool gpencil_io_import_frame(void *in_importer, const GpencilIOParams &iparams)
{
bool result = false;
switch (iparams.mode) {
case GP_IMPORT_FROM_SVG: {
GpencilImporterSVG *importer = (GpencilImporterSVG *)in_importer;
result |= importer->read();
break;
}
/* Add new import formats here. */
default:
break;
}
return result;
}
/* Export frame in PDF. */
#ifdef WITH_HARU
static bool gpencil_io_export_pdf(Depsgraph *depsgraph,
Scene *scene,
Object *ob,
GpencilExporterPDF *exporter,
const GpencilIOParams *iparams)
{
bool result = false;
Object *ob_eval_ = (Object *)DEG_get_evaluated_id(depsgraph, &ob->id);
bGPdata *gpd_eval = (bGPdata *)ob_eval_->data;
exporter->frame_number_set(iparams->frame_cur);
result |= exporter->new_document();
switch (iparams->frame_mode) {
case GP_EXPORT_FRAME_ACTIVE: {
exporter->prepare_camera_params(scene, iparams);
exporter->add_newpage();
exporter->add_body();
result = exporter->write();
break;
}
case GP_EXPORT_FRAME_SELECTED:
case GP_EXPORT_FRAME_SCENE: {
for (int32_t i = iparams->frame_start; i < iparams->frame_end + 1; i++) {
if ((iparams->frame_mode == GP_EXPORT_FRAME_SELECTED) &&
!is_keyframe_included(gpd_eval, i, true))
{
continue;
}
scene->r.cfra = i;
BKE_scene_graph_update_for_newframe(depsgraph);
exporter->prepare_camera_params(scene, iparams);
exporter->frame_number_set(i);
exporter->add_newpage();
exporter->add_body();
}
result = exporter->write();
/* Back to original frame. */
exporter->frame_number_set(iparams->frame_cur);
scene->r.cfra = iparams->frame_cur;
BKE_scene_camera_switch_update(scene);
BKE_scene_graph_update_for_newframe(depsgraph);
break;
}
default:
break;
}
return result;
}
#endif
/* Export current frame in SVG. */
#ifdef WITH_PUGIXML
static bool gpencil_io_export_frame_svg(GpencilExporterSVG *exporter,
Scene *scene,
const GpencilIOParams *iparams,
const bool newpage,
const bool body,
const bool savepage)
{
bool result = false;
exporter->frame_number_set(iparams->frame_cur);
exporter->prepare_camera_params(scene, iparams);
if (newpage) {
result |= exporter->add_newpage();
}
if (body) {
result |= exporter->add_body();
}
if (savepage) {
result = exporter->write();
}
return result;
}
#endif
bool gpencil_io_import(const char *filepath, GpencilIOParams *iparams)
{
GpencilImporterSVG importer = GpencilImporterSVG(filepath, iparams);
return gpencil_io_import_frame(&importer, *iparams);
}
bool gpencil_io_export(const char *filepath, GpencilIOParams *iparams)
{
Depsgraph *depsgraph_ = CTX_data_depsgraph_pointer(iparams->C);
Scene *scene_ = CTX_data_scene(iparams->C);
Object *ob = CTX_data_active_object(iparams->C);
UNUSED_VARS(filepath, depsgraph_, scene_, ob);
switch (iparams->mode) {
#ifdef WITH_PUGIXML
case GP_EXPORT_TO_SVG: {
GpencilExporterSVG exporter = GpencilExporterSVG(filepath, iparams);
return gpencil_io_export_frame_svg(&exporter, scene_, iparams, true, true, true);
}
#endif
#ifdef WITH_HARU
case GP_EXPORT_TO_PDF: {
GpencilExporterPDF exporter = GpencilExporterPDF(filepath, iparams);
return gpencil_io_export_pdf(depsgraph_, scene_, ob, &exporter, iparams);
}
#endif
/* Add new export formats here. */
default:
break;
}
return false;
}

View File

@@ -1,23 +0,0 @@
/* SPDX-FileCopyrightText: 2020 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bgpencil
*/
#include "gpencil_io_base.hh"
namespace blender::io::gpencil {
class GpencilExporter : public GpencilIO {
public:
GpencilExporter(const GpencilIOParams *iparams) : GpencilIO(iparams){};
virtual bool write() = 0;
protected:
private:
};
} // namespace blender::io::gpencil

View File

@@ -1,318 +0,0 @@
/* SPDX-FileCopyrightText: 2020 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bgpencil
*/
#include <algorithm>
#include "BLI_math_color.h"
#include "BLI_math_matrix.h"
#include "BLI_math_vector.h"
#include "BLI_math_vector.hh"
#include "DNA_gpencil_legacy_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
#include "BKE_context.hh"
#include "BKE_gpencil_geom_legacy.h"
#include "BKE_gpencil_legacy.h"
#include "BKE_main.hh"
#include "BKE_material.h"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_query.hh"
#include "ED_gpencil_legacy.hh"
#include "ED_view3d.hh"
#ifdef WIN32
# include "utfconv.hh"
#endif
#include "UI_view2d.hh"
#include "gpencil_io.h"
#include "gpencil_io_export_pdf.hh"
#include <iostream>
namespace blender ::io ::gpencil {
static void error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no, void * /*user_data*/)
{
printf("ERROR: error_no=%04X, detail_no=%u\n", (HPDF_UINT)error_no, (HPDF_UINT)detail_no);
}
/* Constructor. */
GpencilExporterPDF::GpencilExporterPDF(const char *filepath, const GpencilIOParams *iparams)
: GpencilExporter(iparams)
{
filepath_set(filepath);
invert_axis_[0] = false;
invert_axis_[1] = false;
pdf_ = nullptr;
page_ = nullptr;
}
bool GpencilExporterPDF::new_document()
{
return create_document();
}
bool GpencilExporterPDF::add_newpage()
{
return add_page();
}
bool GpencilExporterPDF::add_body()
{
export_gpencil_layers();
return true;
}
bool GpencilExporterPDF::write()
{
/* Support unicode character paths on Windows. */
HPDF_STATUS res = 0;
/* TODO: It looks `libharu` does not support unicode. */
#if 0 /* `ifdef WIN32` */
char filepath_cstr[FILE_MAX];
BLI_strncpy(filepath_cstr, filepath_, FILE_MAX);
UTF16_ENCODE(filepath_cstr);
std::wstring wstr(filepath_cstr_16);
res = HPDF_SaveToFile(pdf_, wstr.c_str());
UTF16_UN_ENCODE(filepath_cstr);
#else
res = HPDF_SaveToFile(pdf_, filepath_);
#endif
return (res == 0) ? true : false;
}
bool GpencilExporterPDF::create_document()
{
pdf_ = HPDF_New(error_handler, nullptr);
if (!pdf_) {
std::cout << "error: cannot create PdfDoc object\n";
return false;
}
return true;
}
bool GpencilExporterPDF::add_page()
{
/* Add a new page object. */
page_ = HPDF_AddPage(pdf_);
if (!pdf_) {
std::cout << "error: cannot create PdfPage\n";
return false;
}
HPDF_Page_SetWidth(page_, render_x_);
HPDF_Page_SetHeight(page_, render_y_);
return true;
}
void GpencilExporterPDF::export_gpencil_layers()
{
/* If is doing a set of frames, the list of objects can change for each frame. */
create_object_list();
const bool is_normalized = ((params_.flag & GP_EXPORT_NORM_THICKNESS) != 0);
for (ObjectZ &obz : ob_list_) {
Object *ob = obz.ob;
/* Use evaluated version to get strokes with modifiers. */
Object *ob_eval_ = (Object *)DEG_get_evaluated_id(depsgraph_, &ob->id);
bGPdata *gpd_eval = (bGPdata *)ob_eval_->data;
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_eval->layers) {
if (gpl->flag & GP_LAYER_HIDE) {
continue;
}
prepare_layer_export_matrix(ob, gpl);
bGPDframe *gpf = gpl->actframe;
if ((gpf == nullptr) || (gpf->strokes.first == nullptr)) {
continue;
}
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if (gps->totpoints < 2) {
continue;
}
if (!ED_gpencil_stroke_material_visible(ob, gps)) {
continue;
}
/* Skip invisible lines. */
prepare_stroke_export_colors(ob, gps);
const float fill_opacity = fill_color_[3] * gpl->opacity;
const float stroke_opacity = stroke_color_[3] * stroke_average_opacity_get() *
gpl->opacity;
if ((fill_opacity < GPENCIL_ALPHA_OPACITY_THRESH) &&
(stroke_opacity < GPENCIL_ALPHA_OPACITY_THRESH))
{
continue;
}
MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
const bool is_stroke = ((gp_style->flag & GP_MATERIAL_STROKE_SHOW) &&
(gp_style->stroke_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) &&
(stroke_opacity > GPENCIL_ALPHA_OPACITY_THRESH));
const bool is_fill = ((gp_style->flag & GP_MATERIAL_FILL_SHOW) &&
(gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH));
if ((!is_stroke) && (!is_fill)) {
continue;
}
/* Duplicate the stroke to apply any layer thickness change. */
bGPDstroke *gps_duplicate = BKE_gpencil_stroke_duplicate(gps, true, false);
/* Apply layer thickness change. */
gps_duplicate->thickness += gpl->line_change;
/* Apply object scale to thickness. */
const float scalef = mat4_to_scale(ob->object_to_world().ptr());
gps_duplicate->thickness = ceilf(float(gps_duplicate->thickness) * scalef);
CLAMP_MIN(gps_duplicate->thickness, 1.0f);
/* Fill. */
if ((is_fill) && (params_.flag & GP_EXPORT_FILL)) {
/* Fill is exported as polygon for fill and stroke in a different shape. */
export_stroke_to_polyline(gpd_eval, gpl, gps_duplicate, is_stroke, true, false);
}
/* Stroke. */
if (is_stroke) {
if (is_normalized) {
export_stroke_to_polyline(gpd_eval, gpl, gps_duplicate, is_stroke, false, true);
}
else {
bGPDstroke *gps_perimeter = BKE_gpencil_stroke_perimeter_from_view(
rv3d_->viewmat, gpd_eval, gpl, gps_duplicate, 3, diff_mat_.ptr(), 0.0f);
/* Sample stroke. */
if (params_.stroke_sample > 0.0f) {
BKE_gpencil_stroke_sample(gpd_eval, gps_perimeter, params_.stroke_sample, false, 0);
}
export_stroke_to_polyline(gpd_eval, gpl, gps_perimeter, is_stroke, false, false);
BKE_gpencil_free_stroke(gps_perimeter);
}
}
BKE_gpencil_free_stroke(gps_duplicate);
}
}
}
}
void GpencilExporterPDF::export_stroke_to_polyline(bGPdata *gpd,
bGPDlayer *gpl,
bGPDstroke *gps,
const bool is_stroke,
const bool do_fill,
const bool normalize)
{
const bool cyclic = ((gps->flag & GP_STROKE_CYCLIC) != 0);
const float avg_pressure = BKE_gpencil_stroke_average_pressure_get(gps);
/* Get the thickness in pixels using a simple 1 point stroke. */
bGPDstroke *gps_temp = BKE_gpencil_stroke_duplicate(gps, false, false);
gps_temp->totpoints = 1;
gps_temp->points = MEM_new<bGPDspoint>("gp_stroke_points");
const bGPDspoint *pt_src = &gps->points[0];
bGPDspoint *pt_dst = &gps_temp->points[0];
copy_v3_v3(&pt_dst->x, &pt_src->x);
pt_dst->pressure = avg_pressure;
const float radius = stroke_point_radius_get(gpd, gpl, gps_temp);
BKE_gpencil_free_stroke(gps_temp);
color_set(gpl, do_fill);
if (is_stroke && !do_fill) {
HPDF_Page_SetLineJoin(page_, HPDF_ROUND_JOIN);
const float defined_width = (gps->thickness * avg_pressure) + gpl->line_change;
const float estimated_width = (radius * 2.0f) + gpl->line_change;
const float final_width = (avg_pressure == 1.0f) ? std::max(defined_width, estimated_width) :
estimated_width;
HPDF_Page_SetLineWidth(page_, std::max(final_width, 1.0f));
}
/* Loop all points. */
for (const int i : IndexRange(gps->totpoints)) {
bGPDspoint *pt = &gps->points[i];
const float2 screen_co = gpencil_3D_point_to_2D(&pt->x);
if (i == 0) {
HPDF_Page_MoveTo(page_, screen_co.x, screen_co.y);
}
else {
HPDF_Page_LineTo(page_, screen_co.x, screen_co.y);
}
}
/* Close cyclic */
if (cyclic) {
HPDF_Page_ClosePath(page_);
}
if (do_fill || !normalize) {
HPDF_Page_Fill(page_);
}
else {
HPDF_Page_Stroke(page_);
}
HPDF_Page_GRestore(page_);
}
void GpencilExporterPDF::color_set(bGPDlayer *gpl, const bool do_fill)
{
const float fill_opacity = fill_color_[3] * gpl->opacity;
const float stroke_opacity = stroke_color_[3] * stroke_average_opacity_get() * gpl->opacity;
const bool need_state = (do_fill && fill_opacity < 1.0f) || (stroke_opacity < 1.0f);
HPDF_Page_GSave(page_);
HPDF_ExtGState gstate = (need_state) ? HPDF_CreateExtGState(pdf_) : nullptr;
float3 col;
if (do_fill) {
interp_v3_v3v3(col, fill_color_, gpl->tintcolor, gpl->tintcolor[3]);
linearrgb_to_srgb_v3_v3(col, col);
col = math::clamp(col, 0.0f, 1.0f);
HPDF_Page_SetRGBFill(page_, col[0], col[1], col[2]);
if (gstate) {
HPDF_ExtGState_SetAlphaFill(gstate, clamp_f(fill_opacity, 0.0f, 1.0f));
}
}
else {
interp_v3_v3v3(col, stroke_color_, gpl->tintcolor, gpl->tintcolor[3]);
linearrgb_to_srgb_v3_v3(col, col);
col = math::clamp(col, 0.0f, 1.0f);
HPDF_Page_SetRGBFill(page_, col[0], col[1], col[2]);
HPDF_Page_SetRGBStroke(page_, col[0], col[1], col[2]);
if (gstate) {
HPDF_ExtGState_SetAlphaFill(gstate, clamp_f(stroke_opacity, 0.0f, 1.0f));
HPDF_ExtGState_SetAlphaStroke(gstate, clamp_f(stroke_opacity, 0.0f, 1.0f));
}
}
if (gstate) {
HPDF_Page_SetExtGState(page_, gstate);
}
}
} // namespace blender::io::gpencil

View File

@@ -1,58 +0,0 @@
/* SPDX-FileCopyrightText: 2020 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bgpencil
*/
#include "gpencil_io_export_base.hh"
#include "hpdf.h"
struct GpencilIOParams;
struct bGPDlayer;
struct bGPDstroke;
#define PDF_EXPORTER_NAME "PDF Exporter for Grease Pencil"
#define PDF_EXPORTER_VERSION "v1.0"
namespace blender::io::gpencil {
class GpencilExporterPDF : public GpencilExporter {
public:
GpencilExporterPDF(const char *filepath, const GpencilIOParams *iparams);
bool new_document();
bool add_newpage();
bool add_body();
bool write();
protected:
private:
/** PDF document. */
HPDF_Doc pdf_;
/** PDF page. */
HPDF_Page page_;
/** Create PDF document. */
bool create_document();
/** Add page. */
bool add_page();
/** Main layer loop. */
void export_gpencil_layers();
/**
* Export a stroke using poly-line or polygon
* \param do_fill: True if the stroke is only fill
*/
void export_stroke_to_polyline(
bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps, bool is_stroke, bool do_fill, bool normalize);
/**
* Set color.
* \param do_fill: True if the stroke is only fill.
*/
void color_set(bGPDlayer *gpl, bool do_fill);
};
} // namespace blender::io::gpencil

View File

@@ -1,423 +0,0 @@
/* SPDX-FileCopyrightText: 2020 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bgpencil
*/
#include <algorithm>
#include "BLI_math_color.h"
#include "BLI_math_matrix.h"
#include "BLI_math_vector.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "DNA_gpencil_legacy_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "BKE_gpencil_geom_legacy.h"
#include "BKE_gpencil_legacy.h"
#include "BKE_main.hh"
#include "BKE_material.h"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_query.hh"
#include "ED_gpencil_legacy.hh"
#include "ED_view3d.hh"
#ifdef WIN32
# include "utfconv.hh"
#endif
#include "UI_view2d.hh"
#include "gpencil_io.h"
#include "gpencil_io_export_svg.hh"
#include "pugixml.hpp"
namespace blender ::io ::gpencil {
/* Constructor. */
GpencilExporterSVG::GpencilExporterSVG(const char *filepath, const GpencilIOParams *iparams)
: GpencilExporter(iparams)
{
filepath_set(filepath);
invert_axis_[0] = false;
invert_axis_[1] = true;
}
bool GpencilExporterSVG::add_newpage()
{
create_document_header();
return true;
}
bool GpencilExporterSVG::add_body()
{
export_gpencil_layers();
return true;
}
bool GpencilExporterSVG::write()
{
bool result = true;
/* Support unicode character paths on Windows. */
#ifdef WIN32
char filepath_cstr[FILE_MAX];
BLI_strncpy(filepath_cstr, filepath_, FILE_MAX);
UTF16_ENCODE(filepath_cstr);
std::wstring wstr(filepath_cstr_16);
result = main_doc_.save_file(wstr.c_str());
UTF16_UN_ENCODE(filepath_cstr);
#else
result = main_doc_.save_file(filepath_);
#endif
return result;
}
void GpencilExporterSVG::create_document_header()
{
/* Add a custom document declaration node. */
pugi::xml_node decl = main_doc_.prepend_child(pugi::node_declaration);
decl.append_attribute("version") = "1.0";
decl.append_attribute("encoding") = "UTF-8";
pugi::xml_node comment = main_doc_.append_child(pugi::node_comment);
char txt[128];
SNPRINTF(txt, " Generator: Blender, %s - %s ", SVG_EXPORTER_NAME, SVG_EXPORTER_VERSION);
comment.set_value(txt);
pugi::xml_node doctype = main_doc_.append_child(pugi::node_doctype);
doctype.set_value(
"svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" "
"\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"");
main_node_ = main_doc_.append_child("svg");
main_node_.append_attribute("version").set_value("1.0");
main_node_.append_attribute("x").set_value("0px");
main_node_.append_attribute("y").set_value("0px");
main_node_.append_attribute("xmlns").set_value("http://www.w3.org/2000/svg");
std::string width;
std::string height;
width = std::to_string(render_x_);
height = std::to_string(render_y_);
main_node_.append_attribute("width").set_value((width + "px").c_str());
main_node_.append_attribute("height").set_value((height + "px").c_str());
std::string viewbox = "0 0 " + width + " " + height;
main_node_.append_attribute("viewBox").set_value(viewbox.c_str());
}
void GpencilExporterSVG::export_gpencil_layers()
{
const bool is_clipping = is_camera_mode() && (params_.flag & GP_EXPORT_CLIP_CAMERA) != 0;
/* If is doing a set of frames, the list of objects can change for each frame. */
create_object_list();
for (ObjectZ &obz : ob_list_) {
Object *ob = obz.ob;
/* Camera clipping. */
if (is_clipping) {
pugi::xml_node clip_node = main_node_.append_child("clipPath");
clip_node.append_attribute("id").set_value(("clip-path" + std::to_string(cfra_)).c_str());
add_rect(clip_node, 0, 0, render_x_, render_y_, 0.0f, "#000000");
}
frame_node_ = main_node_.append_child("g");
std::string frametxt = "blender_frame_" + std::to_string(cfra_);
frame_node_.append_attribute("id").set_value(frametxt.c_str());
/* Clip area. */
if (is_clipping) {
frame_node_.append_attribute("clip-path")
.set_value(("url(#clip-path" + std::to_string(cfra_) + ")").c_str());
}
pugi::xml_node ob_node = frame_node_.append_child("g");
char obtxt[96];
SNPRINTF(obtxt, "blender_object_%s", ob->id.name + 2);
ob_node.append_attribute("id").set_value(obtxt);
/* Use evaluated version to get strokes with modifiers. */
Object *ob_eval_ = (Object *)DEG_get_evaluated_id(depsgraph_, &ob->id);
bGPdata *gpd_eval = (bGPdata *)ob_eval_->data;
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_eval->layers) {
if (gpl->flag & GP_LAYER_HIDE) {
continue;
}
prepare_layer_export_matrix(ob, gpl);
bGPDframe *gpf = gpl->actframe;
if ((gpf == nullptr) || (gpf->strokes.first == nullptr)) {
continue;
}
/* Layer node. */
std::string txt = "Layer: ";
txt.append(gpl->info);
ob_node.append_child(pugi::node_comment).set_value(txt.c_str());
pugi::xml_node node_gpl = ob_node.append_child("g");
node_gpl.append_attribute("id").set_value(gpl->info);
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if (gps->totpoints < 2) {
continue;
}
if (!ED_gpencil_stroke_material_visible(ob, gps)) {
continue;
}
/* Duplicate the stroke to apply any layer thickness change. */
bGPDstroke *gps_duplicate = BKE_gpencil_stroke_duplicate(gps, true, false);
MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob,
gps_duplicate->mat_nr + 1);
const bool is_stroke = ((gp_style->flag & GP_MATERIAL_STROKE_SHOW) &&
(gp_style->stroke_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH));
const bool is_fill = ((gp_style->flag & GP_MATERIAL_FILL_SHOW) &&
(gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH));
prepare_stroke_export_colors(ob, gps_duplicate);
/* Apply layer thickness change. */
gps_duplicate->thickness += gpl->line_change;
/* Apply object scale to thickness. */
const float scalef = mat4_to_scale(ob->object_to_world().ptr());
gps_duplicate->thickness = ceilf(float(gps_duplicate->thickness) * scalef);
CLAMP_MIN(gps_duplicate->thickness, 1.0f);
const bool is_normalized = ((params_.flag & GP_EXPORT_NORM_THICKNESS) != 0) ||
BKE_gpencil_stroke_is_pressure_constant(gps);
/* Fill. */
if ((is_fill) && (params_.flag & GP_EXPORT_FILL)) {
/* Fill is always exported as polygon because the stroke of the fill is done
* in a different SVG command. */
export_stroke_to_polyline(gpd_eval, gpl, gps_duplicate, node_gpl, is_stroke, true);
}
/* Stroke. */
if (is_stroke) {
if (is_normalized) {
export_stroke_to_polyline(gpd_eval, gpl, gps_duplicate, node_gpl, is_stroke, false);
}
else {
bGPDstroke *gps_perimeter = BKE_gpencil_stroke_perimeter_from_view(
rv3d_->viewmat, gpd_eval, gpl, gps_duplicate, 3, diff_mat_.ptr(), 0.0f);
/* Sample stroke. */
if (params_.stroke_sample > 0.0f) {
BKE_gpencil_stroke_sample(gpd_eval, gps_perimeter, params_.stroke_sample, false, 0);
}
export_stroke_to_path(gpl, gps_perimeter, node_gpl, false);
BKE_gpencil_free_stroke(gps_perimeter);
}
}
BKE_gpencil_free_stroke(gps_duplicate);
}
}
}
}
void GpencilExporterSVG::export_stroke_to_path(bGPDlayer *gpl,
bGPDstroke *gps,
pugi::xml_node node_gpl,
const bool do_fill)
{
pugi::xml_node node_gps = node_gpl.append_child("path");
float col[3];
std::string stroke_hex;
if (do_fill) {
node_gps.append_attribute("fill-opacity").set_value(fill_color_[3] * gpl->opacity);
interp_v3_v3v3(col, fill_color_, gpl->tintcolor, gpl->tintcolor[3]);
}
else {
node_gps.append_attribute("fill-opacity")
.set_value(stroke_color_[3] * stroke_average_opacity_get() * gpl->opacity);
interp_v3_v3v3(col, stroke_color_, gpl->tintcolor, gpl->tintcolor[3]);
}
linearrgb_to_srgb_v3_v3(col, col);
stroke_hex = rgb_to_hexstr(col);
node_gps.append_attribute("fill").set_value(stroke_hex.c_str());
node_gps.append_attribute("stroke").set_value("none");
std::string txt = "M";
for (const int i : IndexRange(gps->totpoints)) {
if (i > 0) {
txt.append("L");
}
bGPDspoint &pt = gps->points[i];
const float2 screen_co = gpencil_3D_point_to_2D(&pt.x);
txt.append(std::to_string(screen_co.x) + "," + std::to_string(screen_co.y));
}
/* Close patch (cyclic). */
if (gps->flag & GP_STROKE_CYCLIC) {
txt.append("z");
}
node_gps.append_attribute("d").set_value(txt.c_str());
}
void GpencilExporterSVG::export_stroke_to_polyline(bGPdata *gpd,
bGPDlayer *gpl,
bGPDstroke *gps,
pugi::xml_node node_gpl,
const bool is_stroke,
const bool do_fill)
{
const bool cyclic = ((gps->flag & GP_STROKE_CYCLIC) != 0);
const float avg_pressure = BKE_gpencil_stroke_average_pressure_get(gps);
/* Get the thickness in pixels using a simple 1 point stroke. */
bGPDstroke *gps_temp = BKE_gpencil_stroke_duplicate(gps, false, false);
gps_temp->totpoints = 1;
gps_temp->points = MEM_new<bGPDspoint>("gp_stroke_points");
bGPDspoint *pt_src = &gps->points[0];
bGPDspoint *pt_dst = &gps_temp->points[0];
copy_v3_v3(&pt_dst->x, &pt_src->x);
pt_dst->pressure = avg_pressure;
const float radius = stroke_point_radius_get(gpd, gpl, gps_temp);
BKE_gpencil_free_stroke(gps_temp);
pugi::xml_node node_gps = node_gpl.append_child(do_fill || cyclic ? "polygon" : "polyline");
color_string_set(gpl, gps, node_gps, do_fill);
if (is_stroke && !do_fill) {
const float defined_width = (gps->thickness * avg_pressure) + gpl->line_change;
const float estimated_width = (radius * 2.0f) + gpl->line_change;
const float final_width = (avg_pressure == 1.0f) ? std::max(defined_width, estimated_width) :
estimated_width;
node_gps.append_attribute("stroke-width").set_value(std::max(final_width, 1.0f));
}
std::string txt;
for (const int i : IndexRange(gps->totpoints)) {
if (i > 0) {
txt.append(" ");
}
bGPDspoint *pt = &gps->points[i];
const float2 screen_co = gpencil_3D_point_to_2D(&pt->x);
txt.append(std::to_string(screen_co.x) + "," + std::to_string(screen_co.y));
}
node_gps.append_attribute("points").set_value(txt.c_str());
}
void GpencilExporterSVG::color_string_set(bGPDlayer *gpl,
bGPDstroke *gps,
pugi::xml_node node_gps,
const bool do_fill)
{
const bool round_cap = (gps->caps[0] == GP_STROKE_CAP_ROUND ||
gps->caps[1] == GP_STROKE_CAP_ROUND);
float col[3];
if (do_fill) {
interp_v3_v3v3(col, fill_color_, gpl->tintcolor, gpl->tintcolor[3]);
linearrgb_to_srgb_v3_v3(col, col);
std::string stroke_hex = rgb_to_hexstr(col);
node_gps.append_attribute("fill").set_value(stroke_hex.c_str());
node_gps.append_attribute("stroke").set_value("none");
node_gps.append_attribute("fill-opacity").set_value(fill_color_[3] * gpl->opacity);
}
else {
interp_v3_v3v3(col, stroke_color_, gpl->tintcolor, gpl->tintcolor[3]);
linearrgb_to_srgb_v3_v3(col, col);
std::string stroke_hex = rgb_to_hexstr(col);
node_gps.append_attribute("stroke").set_value(stroke_hex.c_str());
node_gps.append_attribute("stroke-opacity")
.set_value(stroke_color_[3] * stroke_average_opacity_get() * gpl->opacity);
if (gps->totpoints > 1) {
node_gps.append_attribute("fill").set_value("none");
node_gps.append_attribute("stroke-linecap").set_value(round_cap ? "round" : "square");
}
else {
node_gps.append_attribute("fill").set_value(stroke_hex.c_str());
node_gps.append_attribute("fill-opacity").set_value(fill_color_[3] * gpl->opacity);
}
}
}
void GpencilExporterSVG::add_rect(pugi::xml_node node,
float x,
float y,
float width,
float height,
float thickness,
const std::string &hexcolor)
{
pugi::xml_node rect_node = node.append_child("rect");
rect_node.append_attribute("x").set_value(x);
rect_node.append_attribute("y").set_value(y);
rect_node.append_attribute("width").set_value(width);
rect_node.append_attribute("height").set_value(height);
rect_node.append_attribute("fill").set_value("none");
if (thickness > 0.0f) {
rect_node.append_attribute("stroke").set_value(hexcolor.c_str());
rect_node.append_attribute("stroke-width").set_value(thickness);
}
}
void GpencilExporterSVG::add_text(pugi::xml_node node,
float x,
float y,
const std::string &text,
const float size,
const std::string &hexcolor)
{
pugi::xml_node nodetxt = node.append_child("text");
nodetxt.append_attribute("x").set_value(x);
nodetxt.append_attribute("y").set_value(y);
// nodetxt.append_attribute("font-family").set_value("'system-ui'");
nodetxt.append_attribute("font-size").set_value(size);
nodetxt.append_attribute("fill").set_value(hexcolor.c_str());
nodetxt.text().set(text.c_str());
}
std::string GpencilExporterSVG::rgb_to_hexstr(const float color[3])
{
uint8_t r = color[0] * 255.0f;
uint8_t g = color[1] * 255.0f;
uint8_t b = color[2] * 255.0f;
char hex_string[20];
SNPRINTF(hex_string, "#%02X%02X%02X", r, g, b);
std::string hexstr = hex_string;
return hexstr;
}
} // namespace blender::io::gpencil

View File

@@ -1,109 +0,0 @@
/* SPDX-FileCopyrightText: 2020 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bgpencil
*/
#include "BLI_path_utils.hh"
#include "gpencil_io_export_base.hh"
#include "pugixml.hpp"
struct GpencilIOParams;
#define SVG_EXPORTER_NAME "SVG Export for Grease Pencil"
#define SVG_EXPORTER_VERSION "v1.0"
namespace blender::io::gpencil {
class GpencilExporterSVG : public GpencilExporter {
public:
GpencilExporterSVG(const char *filepath, const GpencilIOParams *iparams);
bool add_newpage();
bool add_body();
bool write();
protected:
/**
* Create a SVG rectangle
* \param node: Parent node
* \param x: X location
* \param y: Y location
* \param width: width of the rectangle
* \param height: Height of the rectangle
* \param thickness: Thickness of the line
* \param hexcolor: Color of the line
*/
static void add_rect(pugi::xml_node node,
float x,
float y,
float width,
float height,
float thickness,
const std::string &hexcolor);
/**
* Create SVG text
* \param node: Parent node
* \param x: X location
* \param y: Y location
* \param text: Text to include
* \param size: Size of the text
* \param hexcolor: Color of the text
*/
static void add_text(pugi::xml_node node,
float x,
float y,
const std::string &text,
float size,
const std::string &hexcolor);
private:
/** XML doc. */
pugi::xml_document main_doc_;
/** Main document node. */
pugi::xml_node main_node_;
/** Frame node. */
pugi::xml_node frame_node_;
/** Create document header and main SVG node. */
void create_document_header();
/** Main layer loop. */
void export_gpencil_layers();
/**
* Export a stroke using SVG path
* \param node_gpl: Node of the layer.
* \param do_fill: True if the stroke is only fill
*/
void export_stroke_to_path(bGPDlayer *gpl,
bGPDstroke *gps,
pugi::xml_node node_gpl,
bool do_fill);
/**
* Export a stroke using poly-line or polygon
* \param node_gpl: Node of the layer.
* \param do_fill: True if the stroke is only fill
*/
void export_stroke_to_polyline(bGPdata *gpd,
bGPDlayer *gpl,
bGPDstroke *gps,
pugi::xml_node node_gpl,
bool is_stroke,
bool do_fill);
/**
* Set color SVG string for stroke
* \param node_gps: Stroke node.
* \param do_fill: True if the stroke is only fill.
*/
void color_string_set(bGPDlayer *gpl, bGPDstroke *gps, pugi::xml_node node_gps, bool do_fill);
/** Convert a color to Hex value (#FFFFFF). */
std::string rgb_to_hexstr(const float color[3]);
};
} // namespace blender::io::gpencil

View File

@@ -1,79 +0,0 @@
/* SPDX-FileCopyrightText: 2020 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bgpencil
*/
#include "BLI_math_vector.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_gpencil_legacy.h"
#include "BKE_material.h"
#include "ED_gpencil_legacy.hh"
#include "ED_object.hh"
#include "gpencil_io_import_base.hh"
namespace blender::io::gpencil {
/* Constructor. */
GpencilImporter::GpencilImporter(const GpencilIOParams *iparams) : GpencilIO(iparams)
{
/* Nothing to do yet */
}
Object *GpencilImporter::create_object()
{
const float *cur_loc = scene_->cursor.location;
const float rot[3] = {0.0f};
ushort local_view_bits = (params_.v3d && params_.v3d->localvd) ? params_.v3d->local_view_uid :
ushort(0);
Object *ob_gpencil = ed::object::add_type(params_.C,
OB_GPENCIL_LEGACY,
(params_.filename[0] != '\0') ? params_.filename :
nullptr,
cur_loc,
rot,
false,
local_view_bits);
/* Set object defaults. */
ED_gpencil_add_defaults(params_.C, ob_gpencil);
return ob_gpencil;
}
int32_t GpencilImporter::create_material(const char *name, const bool stroke, const bool fill)
{
const float default_stroke_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
const float default_fill_color[4] = {0.5f, 0.5f, 0.5f, 1.0f};
int32_t mat_index = BKE_gpencil_material_find_index_by_name_prefix(params_.ob, name);
/* Stroke and Fill material. */
if (mat_index == -1) {
int32_t new_idx;
Material *mat_gp = BKE_gpencil_object_material_new(bmain_, params_.ob, name, &new_idx);
MaterialGPencilStyle *gp_style = mat_gp->gp_style;
gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
gp_style->flag &= ~GP_MATERIAL_FILL_SHOW;
copy_v4_v4(gp_style->stroke_rgba, default_stroke_color);
copy_v4_v4(gp_style->fill_rgba, default_fill_color);
if (stroke) {
gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
}
if (fill) {
gp_style->flag |= GP_MATERIAL_FILL_SHOW;
}
mat_index = params_.ob->totcol - 1;
}
return mat_index;
}
} // namespace blender::io::gpencil

View File

@@ -1,26 +0,0 @@
/* SPDX-FileCopyrightText: 2020 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bgpencil
*/
#include "gpencil_io_base.hh"
namespace blender::io::gpencil {
class GpencilImporter : public GpencilIO {
public:
GpencilImporter(const GpencilIOParams *iparams);
virtual bool read() = 0;
protected:
Object *create_object();
int32_t create_material(const char *name, bool stroke, bool fill);
private:
};
} // namespace blender::io::gpencil

View File

@@ -1,242 +0,0 @@
/* SPDX-FileCopyrightText: 2020 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bgpencil
*/
#include "BLI_math_color.h"
#include "BLI_math_matrix.h"
#include "BLI_math_rotation.h"
#include "BLI_math_vector.h"
#include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
#include "BLI_string.h"
#include "DNA_gpencil_legacy_types.h"
#include "BKE_gpencil_geom_legacy.h"
#include "BKE_gpencil_legacy.h"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_query.hh"
#include "ED_gpencil_legacy.hh"
#include "gpencil_io.h"
#include "gpencil_io_import_svg.hh"
#include "nanosvg.h"
#include <iostream>
using blender::MutableSpan;
namespace blender::io::gpencil {
/* Constructor. */
GpencilImporterSVG::GpencilImporterSVG(const char *filepath, const GpencilIOParams *iparams)
: GpencilImporter(iparams)
{
filepath_set(filepath);
}
bool GpencilImporterSVG::read()
{
bool result = true;
NSVGimage *svg_data = nullptr;
svg_data = nsvgParseFromFile(filepath_, "mm", 96.0f);
if (svg_data == nullptr) {
std::cout << " Could not open SVG.\n ";
return false;
}
/* Create grease pencil object. */
params_.ob = create_object();
if (params_.ob == nullptr) {
std::cout << "Unable to create new object.\n";
nsvgDelete(svg_data);
return false;
}
gpd_ = (bGPdata *)params_.ob->data;
/* Grease pencil is rotated 90 degrees in X axis by default. */
float matrix[4][4];
const float3 scale = float3(params_.scale);
unit_m4(matrix);
rotate_m4(matrix, 'X', DEG2RADF(-90.0f));
rescale_m4(matrix, scale);
/* Loop all shapes. */
char prv_id[70] = {"*"};
int prefix = 0;
for (NSVGshape *shape = svg_data->shapes; shape; shape = shape->next) {
char *layer_id = (shape->id_parent[0] == '\0') ? BLI_sprintfN("Layer_%03d", prefix) :
BLI_sprintfN("%s", shape->id_parent);
if (!STREQ(prv_id, layer_id)) {
prefix++;
MEM_freeN(layer_id);
layer_id = (shape->id_parent[0] == '\0') ? BLI_sprintfN("Layer_%03d", prefix) :
BLI_sprintfN("%s", shape->id_parent);
STRNCPY(prv_id, layer_id);
}
/* Check if the layer exist and create if needed. */
bGPDlayer *gpl = (bGPDlayer *)BLI_findstring(
&gpd_->layers, layer_id, offsetof(bGPDlayer, info));
if (gpl == nullptr) {
gpl = BKE_gpencil_layer_addnew(gpd_, layer_id, true, false);
/* Disable lights. */
gpl->flag &= ~GP_LAYER_USE_LIGHTS;
}
MEM_freeN(layer_id);
/* Check frame. */
bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, cfra_, GP_GETFRAME_ADD_NEW);
/* Create materials. */
bool is_stroke = bool(shape->stroke.type);
bool is_fill = bool(shape->fill.type);
if ((!is_stroke) && (!is_fill)) {
is_stroke = true;
}
/* Create_shape materials. */
const char *const mat_names[] = {"Stroke", "Fill", "Both"};
int index = 0;
if ((is_stroke) && (!is_fill)) {
index = 0;
}
else if ((!is_stroke) && (is_fill)) {
index = 1;
}
else if ((is_stroke) && (is_fill)) {
index = 2;
}
int32_t mat_index = create_material(mat_names[index], is_stroke, is_fill);
/* Loop all paths to create the stroke data. */
for (NSVGpath *path = shape->paths; path; path = path->next) {
create_stroke(gpd_, gpf, shape, path, mat_index, matrix);
}
}
/* Free SVG memory. */
nsvgDelete(svg_data);
/* Calculate bounding box and move all points to new origin center. */
float gp_center[3];
BKE_gpencil_centroid_3d(gpd_, gp_center);
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_->layers) {
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
for (bGPDspoint &pt : MutableSpan(gps->points, gps->totpoints)) {
sub_v3_v3(&pt.x, gp_center);
}
/* Calc stroke bounding box. */
BKE_gpencil_stroke_boundingbox_calc(gps);
}
}
}
return result;
}
void GpencilImporterSVG::create_stroke(bGPdata *gpd,
bGPDframe *gpf,
NSVGshape *shape,
NSVGpath *path,
const int32_t mat_index,
const float matrix[4][4])
{
const bool is_stroke = bool(shape->stroke.type);
const bool is_fill = bool(shape->fill.type);
const int edges = params_.resolution;
const float step = 1.0f / float(edges - 1);
const int totpoints = (path->npts / 3) * params_.resolution;
bGPDstroke *gps = BKE_gpencil_stroke_new(mat_index, totpoints, 1.0f);
BLI_addtail(&gpf->strokes, gps);
if (path->closed == '1') {
gps->flag |= GP_STROKE_CYCLIC;
}
if (is_stroke) {
gps->thickness = shape->strokeWidth * params_.scale;
}
/* Apply Fill vertex color. */
if (is_fill) {
NSVGpaint fill = shape->fill;
convert_color(fill.color, gps->vert_color_fill);
gps->fill_opacity_fac = gps->vert_color_fill[3];
gps->vert_color_fill[3] = 1.0f;
}
int start_index = 0;
for (int i = 0; i < path->npts - 1; i += 3) {
float *p = &path->pts[i * 2];
float a = 0.0f;
for (int v = 0; v < edges; v++) {
bGPDspoint *pt = &gps->points[start_index];
pt->strength = shape->opacity;
pt->pressure = 1.0f;
pt->z = 0.0f;
/* TODO(antoniov): Can be improved loading curve data instead of loading strokes. */
interp_v2_v2v2v2v2_cubic(&pt->x, &p[0], &p[2], &p[4], &p[6], a);
/* Scale from millimeters. */
mul_v3_fl(&pt->x, 0.001f);
mul_m4_v3(matrix, &pt->x);
/* Apply color to vertex color. */
if (is_fill) {
NSVGpaint fill = shape->fill;
convert_color(fill.color, pt->vert_color);
}
if (is_stroke) {
NSVGpaint stroke = shape->stroke;
convert_color(stroke.color, pt->vert_color);
gps->fill_opacity_fac = pt->vert_color[3];
}
pt->vert_color[3] = 1.0f;
a += step;
start_index++;
}
}
/* Cleanup and recalculate geometry. */
BKE_gpencil_stroke_merge_distance(gpd, gpf, gps, 0.001f, true);
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
/* Unpack internal NanoSVG color. */
static void unpack_nano_color(const uint pack, float r_col[4])
{
uchar rgb_u[4];
rgb_u[0] = ((pack) >> 0) & 0xFF;
rgb_u[1] = ((pack) >> 8) & 0xFF;
rgb_u[2] = ((pack) >> 16) & 0xFF;
rgb_u[3] = ((pack) >> 24) & 0xFF;
r_col[0] = float(rgb_u[0]) / 255.0f;
r_col[1] = float(rgb_u[1]) / 255.0f;
r_col[2] = float(rgb_u[2]) / 255.0f;
r_col[3] = float(rgb_u[3]) / 255.0f;
}
void GpencilImporterSVG::convert_color(const int32_t color, float r_linear_rgba[4])
{
float rgba[4];
unpack_nano_color(color, rgba);
srgb_to_linearrgb_v3_v3(r_linear_rgba, rgba);
r_linear_rgba[3] = rgba[3];
}
} // namespace blender::io::gpencil

View File

@@ -1,41 +0,0 @@
/* SPDX-FileCopyrightText: 2020 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bgpencil
*/
#include "gpencil_io_import_base.hh"
struct GpencilIOParams;
struct NSVGpath;
struct NSVGshape;
struct bGPDframe;
struct bGPdata;
#define SVG_IMPORTER_NAME "SVG Import for Grease Pencil"
#define SVG_IMPORTER_VERSION "v1.0"
namespace blender::io::gpencil {
class GpencilImporterSVG : public GpencilImporter {
public:
GpencilImporterSVG(const char *filepath, const GpencilIOParams *iparams);
bool read();
protected:
private:
void create_stroke(bGPdata *gpd,
bGPDframe *gpf,
NSVGshape *shape,
NSVGpath *path,
int32_t mat_index,
const float matrix[4][4]);
void convert_color(int32_t color, float r_linear_rgba[4]);
};
} // namespace blender::io::gpencil

View File

@@ -394,15 +394,6 @@ static bool rna_is_grease_pencil_get(PointerRNA *ptr)
return false; return false;
} }
static void rna_gpcolordata_uv_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
/* update all uv strokes of this color */
Material *ma = (Material *)ptr->owner_id;
ED_gpencil_update_color_uv(bmain, ma);
rna_MaterialGpencil_update(bmain, scene, ptr);
}
static std::optional<std::string> rna_GpencilColorData_path(const PointerRNA * /*ptr*/) static std::optional<std::string> rna_GpencilColorData_path(const PointerRNA * /*ptr*/)
{ {
return "grease_pencil"; return "grease_pencil";
@@ -624,7 +615,7 @@ static void rna_def_material_greasepencil(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, nullptr, "texture_pixsize"); RNA_def_property_float_sdna(prop, nullptr, "texture_pixsize");
RNA_def_property_range(prop, 1, 5000); RNA_def_property_range(prop, 1, 5000);
RNA_def_property_ui_text(prop, "UV Factor", "Texture Pixel Size factor along the stroke"); RNA_def_property_ui_text(prop, "UV Factor", "Texture Pixel Size factor along the stroke");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_gpcolordata_uv_update"); RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
/* Flags */ /* Flags */
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);

View File

@@ -776,50 +776,6 @@ static void rna_ToolSettings_snap_uv_mode_set(PointerRNA *ptr, int value)
} }
} }
/* Grease Pencil update cache */
static void rna_GPencil_update(Main * /*bmain*/, Scene *scene, PointerRNA * /*ptr*/)
{
if (scene != nullptr) {
ED_gpencil_tag_scene_gpencil(scene);
}
}
static void rna_Gpencil_extend_selection(bContext *C, PointerRNA * /*ptr*/)
{
/* Extend selection to all points in all selected strokes. */
const Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *ob = BKE_view_layer_active_object_get(view_layer);
if ((ob) && (ob->type == OB_GPENCIL_LEGACY)) {
bGPdata *gpd = (bGPdata *)ob->data;
CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
if ((gps->flag & GP_STROKE_SELECT) && (gps->totpoints > 1)) {
bGPDspoint *pt;
for (int i = 0; i < gps->totpoints; i++) {
pt = &gps->points[i];
pt->flag |= GP_SPOINT_SELECT;
}
}
}
CTX_DATA_END;
gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
}
}
static void rna_Gpencil_selectmode_update(bContext *C, PointerRNA *ptr)
{
ToolSettings *ts = (ToolSettings *)ptr->data;
/* If the mode is not Stroke, don't extend selection. */
if ((ts->gpencil_selectmode_edit & GP_SELECTMODE_STROKE) == 0) {
return;
}
rna_Gpencil_extend_selection(C, ptr);
}
static void rna_Gpencil_mask_point_update(bContext * /*C*/, PointerRNA *ptr) static void rna_Gpencil_mask_point_update(bContext * /*C*/, PointerRNA *ptr)
{ {
ToolSettings *ts = (ToolSettings *)ptr->data; ToolSettings *ts = (ToolSettings *)ptr->data;
@@ -828,14 +784,12 @@ static void rna_Gpencil_mask_point_update(bContext * /*C*/, PointerRNA *ptr)
ts->gpencil_selectmode_sculpt &= ~GP_SCULPT_MASK_SELECTMODE_SEGMENT; ts->gpencil_selectmode_sculpt &= ~GP_SCULPT_MASK_SELECTMODE_SEGMENT;
} }
static void rna_Gpencil_mask_stroke_update(bContext *C, PointerRNA *ptr) static void rna_Gpencil_mask_stroke_update(bContext * /*C*/, PointerRNA *ptr)
{ {
ToolSettings *ts = (ToolSettings *)ptr->data; ToolSettings *ts = (ToolSettings *)ptr->data;
ts->gpencil_selectmode_sculpt &= ~GP_SCULPT_MASK_SELECTMODE_POINT; ts->gpencil_selectmode_sculpt &= ~GP_SCULPT_MASK_SELECTMODE_POINT;
ts->gpencil_selectmode_sculpt &= ~GP_SCULPT_MASK_SELECTMODE_SEGMENT; ts->gpencil_selectmode_sculpt &= ~GP_SCULPT_MASK_SELECTMODE_SEGMENT;
rna_Gpencil_extend_selection(C, ptr);
} }
static void rna_Gpencil_mask_segment_update(bContext * /*C*/, PointerRNA *ptr) static void rna_Gpencil_mask_segment_update(bContext * /*C*/, PointerRNA *ptr)
@@ -846,36 +800,28 @@ static void rna_Gpencil_mask_segment_update(bContext * /*C*/, PointerRNA *ptr)
ts->gpencil_selectmode_sculpt &= ~GP_SCULPT_MASK_SELECTMODE_STROKE; ts->gpencil_selectmode_sculpt &= ~GP_SCULPT_MASK_SELECTMODE_STROKE;
} }
static void rna_Gpencil_vertex_mask_point_update(bContext *C, PointerRNA *ptr) static void rna_Gpencil_vertex_mask_point_update(bContext * /*C*/, PointerRNA *ptr)
{ {
ToolSettings *ts = (ToolSettings *)ptr->data; ToolSettings *ts = (ToolSettings *)ptr->data;
ts->gpencil_selectmode_vertex &= ~GP_VERTEX_MASK_SELECTMODE_STROKE; ts->gpencil_selectmode_vertex &= ~GP_VERTEX_MASK_SELECTMODE_STROKE;
ts->gpencil_selectmode_vertex &= ~GP_VERTEX_MASK_SELECTMODE_SEGMENT; ts->gpencil_selectmode_vertex &= ~GP_VERTEX_MASK_SELECTMODE_SEGMENT;
ED_gpencil_tag_scene_gpencil(CTX_data_scene(C));
} }
static void rna_Gpencil_vertex_mask_stroke_update(bContext *C, PointerRNA *ptr) static void rna_Gpencil_vertex_mask_stroke_update(bContext * /*C*/, PointerRNA *ptr)
{ {
ToolSettings *ts = (ToolSettings *)ptr->data; ToolSettings *ts = (ToolSettings *)ptr->data;
ts->gpencil_selectmode_vertex &= ~GP_VERTEX_MASK_SELECTMODE_POINT; ts->gpencil_selectmode_vertex &= ~GP_VERTEX_MASK_SELECTMODE_POINT;
ts->gpencil_selectmode_vertex &= ~GP_VERTEX_MASK_SELECTMODE_SEGMENT; ts->gpencil_selectmode_vertex &= ~GP_VERTEX_MASK_SELECTMODE_SEGMENT;
rna_Gpencil_extend_selection(C, ptr);
ED_gpencil_tag_scene_gpencil(CTX_data_scene(C));
} }
static void rna_Gpencil_vertex_mask_segment_update(bContext *C, PointerRNA *ptr) static void rna_Gpencil_vertex_mask_segment_update(bContext * /*C*/, PointerRNA *ptr)
{ {
ToolSettings *ts = (ToolSettings *)ptr->data; ToolSettings *ts = (ToolSettings *)ptr->data;
ts->gpencil_selectmode_vertex &= ~GP_VERTEX_MASK_SELECTMODE_POINT; ts->gpencil_selectmode_vertex &= ~GP_VERTEX_MASK_SELECTMODE_POINT;
ts->gpencil_selectmode_vertex &= ~GP_VERTEX_MASK_SELECTMODE_STROKE; ts->gpencil_selectmode_vertex &= ~GP_VERTEX_MASK_SELECTMODE_STROKE;
ED_gpencil_tag_scene_gpencil(CTX_data_scene(C));
} }
static void rna_active_grease_pencil_update(bContext *C, PointerRNA * /*ptr*/) static void rna_active_grease_pencil_update(bContext *C, PointerRNA * /*ptr*/)
@@ -3906,7 +3852,7 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Select Mode", ""); RNA_def_property_ui_text(prop, "Select Mode", "");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_Gpencil_selectmode_update"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, nullptr);
/* Grease Pencil - Select mode Sculpt */ /* Grease Pencil - Select mode Sculpt */
prop = RNA_def_property(srna, "use_gpencil_select_mask_point", PROP_BOOLEAN, PROP_NONE); prop = RNA_def_property(srna, "use_gpencil_select_mask_point", PROP_BOOLEAN, PROP_NONE);
@@ -4026,7 +3972,7 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_DEG_SYNC_ONLY); RNA_def_property_flag(prop, PROP_DEG_SYNC_ONLY);
RNA_def_property_range(prop, 1, 10); RNA_def_property_range(prop, 1, 10);
RNA_def_property_ui_text(prop, "Annotation Stroke Thickness", "Thickness of annotation strokes"); RNA_def_property_ui_text(prop, "Annotation Stroke Thickness", "Thickness of annotation strokes");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr);
/* Auto Keying */ /* Auto Keying */
prop = RNA_def_property(srna, "use_keyframe_insert_auto", PROP_BOOLEAN, PROP_NONE); prop = RNA_def_property(srna, "use_keyframe_insert_auto", PROP_BOOLEAN, PROP_NONE);
@@ -7459,39 +7405,39 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "simplify_gpencil", PROP_BOOLEAN, PROP_NONE); prop = RNA_def_property(srna, "simplify_gpencil", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "simplify_gpencil", SIMPLIFY_GPENCIL_ENABLE); RNA_def_property_boolean_sdna(prop, nullptr, "simplify_gpencil", SIMPLIFY_GPENCIL_ENABLE);
RNA_def_property_ui_text(prop, "Simplify", "Simplify Grease Pencil drawing"); RNA_def_property_ui_text(prop, "Simplify", "Simplify Grease Pencil drawing");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr);
prop = RNA_def_property(srna, "simplify_gpencil_onplay", PROP_BOOLEAN, PROP_NONE); prop = RNA_def_property(srna, "simplify_gpencil_onplay", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "simplify_gpencil", SIMPLIFY_GPENCIL_ON_PLAY); RNA_def_property_boolean_sdna(prop, nullptr, "simplify_gpencil", SIMPLIFY_GPENCIL_ON_PLAY);
RNA_def_property_ui_text( RNA_def_property_ui_text(
prop, "Playback Only", "Simplify Grease Pencil only during animation playback"); prop, "Playback Only", "Simplify Grease Pencil only during animation playback");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr);
prop = RNA_def_property(srna, "simplify_gpencil_antialiasing", PROP_BOOLEAN, PROP_NONE); prop = RNA_def_property(srna, "simplify_gpencil_antialiasing", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, nullptr, "simplify_gpencil", SIMPLIFY_GPENCIL_AA); RNA_def_property_boolean_negative_sdna(prop, nullptr, "simplify_gpencil", SIMPLIFY_GPENCIL_AA);
RNA_def_property_ui_text(prop, "Antialiasing", "Use Antialiasing to smooth stroke edges"); RNA_def_property_ui_text(prop, "Antialiasing", "Use Antialiasing to smooth stroke edges");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr);
prop = RNA_def_property(srna, "simplify_gpencil_view_fill", PROP_BOOLEAN, PROP_NONE); prop = RNA_def_property(srna, "simplify_gpencil_view_fill", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, nullptr, "simplify_gpencil", SIMPLIFY_GPENCIL_FILL); RNA_def_property_boolean_negative_sdna(prop, nullptr, "simplify_gpencil", SIMPLIFY_GPENCIL_FILL);
RNA_def_property_ui_text(prop, "Fill", "Display fill strokes in the viewport"); RNA_def_property_ui_text(prop, "Fill", "Display fill strokes in the viewport");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr);
prop = RNA_def_property(srna, "simplify_gpencil_modifier", PROP_BOOLEAN, PROP_NONE); prop = RNA_def_property(srna, "simplify_gpencil_modifier", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna( RNA_def_property_boolean_negative_sdna(
prop, nullptr, "simplify_gpencil", SIMPLIFY_GPENCIL_MODIFIER); prop, nullptr, "simplify_gpencil", SIMPLIFY_GPENCIL_MODIFIER);
RNA_def_property_ui_text(prop, "Modifiers", "Display modifiers"); RNA_def_property_ui_text(prop, "Modifiers", "Display modifiers");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr);
prop = RNA_def_property(srna, "simplify_gpencil_shader_fx", PROP_BOOLEAN, PROP_NONE); prop = RNA_def_property(srna, "simplify_gpencil_shader_fx", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, nullptr, "simplify_gpencil", SIMPLIFY_GPENCIL_FX); RNA_def_property_boolean_negative_sdna(prop, nullptr, "simplify_gpencil", SIMPLIFY_GPENCIL_FX);
RNA_def_property_ui_text(prop, "Shader Effects", "Display Shader Effects"); RNA_def_property_ui_text(prop, "Shader Effects", "Display Shader Effects");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr);
prop = RNA_def_property(srna, "simplify_gpencil_tint", PROP_BOOLEAN, PROP_NONE); prop = RNA_def_property(srna, "simplify_gpencil_tint", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, nullptr, "simplify_gpencil", SIMPLIFY_GPENCIL_TINT); RNA_def_property_boolean_negative_sdna(prop, nullptr, "simplify_gpencil", SIMPLIFY_GPENCIL_TINT);
RNA_def_property_ui_text(prop, "Layers Tinting", "Display layer tint"); RNA_def_property_ui_text(prop, "Layers Tinting", "Display layer tint");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr);
/* persistent data */ /* persistent data */
prop = RNA_def_property(srna, "use_persistent_data", PROP_BOOLEAN, PROP_NONE); prop = RNA_def_property(srna, "use_persistent_data", PROP_BOOLEAN, PROP_NONE);

View File

@@ -123,14 +123,6 @@ const EnumPropertyItem rna_enum_symmetrize_direction_items[] = {
# include "ED_paint.hh" # include "ED_paint.hh"
# include "ED_particle.hh" # include "ED_particle.hh"
static void rna_GPencil_update(Main * /*bmain*/, Scene *scene, PointerRNA * /*ptr*/)
{
/* mark all grease pencil datablocks of the scene */
if (scene != nullptr) {
ED_gpencil_tag_scene_gpencil(scene);
}
}
const EnumPropertyItem rna_enum_particle_edit_disconnected_hair_brush_items[] = { const EnumPropertyItem rna_enum_particle_edit_disconnected_hair_brush_items[] = {
{PE_BRUSH_COMB, "COMB", 0, "Comb", "Comb hairs"}, {PE_BRUSH_COMB, "COMB", 0, "Comb", "Comb hairs"},
{PE_BRUSH_SMOOTH, "SMOOTH", 0, "Smooth", "Smooth hairs"}, {PE_BRUSH_SMOOTH, "SMOOTH", 0, "Smooth", "Smooth hairs"},
@@ -1625,7 +1617,7 @@ static void rna_def_gpencil_sculpt(BlenderRNA *brna)
RNA_def_property_enum_items(prop, rna_enum_gpencil_lock_axis_items); RNA_def_property_enum_items(prop, rna_enum_gpencil_lock_axis_items);
RNA_def_property_ui_text(prop, "Lock Axis", ""); RNA_def_property_ui_text(prop, "Lock Axis", "");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr);
/* threshold for cutter */ /* threshold for cutter */
prop = RNA_def_property(srna, "intersection_threshold", PROP_FLOAT, PROP_NONE); prop = RNA_def_property(srna, "intersection_threshold", PROP_FLOAT, PROP_NONE);