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:
@@ -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)],
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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"));
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ***************************************************************** */
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \} */
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|
||||||
/* ****************************************************** */
|
|
||||||
|
|||||||
@@ -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) --------------- */
|
||||||
|
|||||||
@@ -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 = ®ion->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,
|
|
||||||
¶ms,
|
|
||||||
&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(®ion->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;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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]);
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
|
||||||
@@ -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, ¶ms);
|
|
||||||
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, ¶ms);
|
|
||||||
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 */
|
|
||||||
@@ -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(), ¶ms);
|
|
||||||
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 */
|
|
||||||
@@ -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 */
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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). */
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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. */
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|
||||||
|
|||||||
@@ -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}")
|
|
||||||
@@ -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
|
|
||||||
@@ -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(¶ms);
|
|
||||||
BKE_camera_params_from_object(¶ms, cam_ob);
|
|
||||||
|
|
||||||
/* Compute matrix, view-plane, etc. */
|
|
||||||
RenderData *rd = &scene_->r;
|
|
||||||
BKE_camera_params_compute_viewplane(¶ms, rd->xsch, rd->ysch, rd->xasp, rd->yasp);
|
|
||||||
BKE_camera_params_compute_matrix(¶ms);
|
|
||||||
|
|
||||||
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
|
|
||||||
@@ -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
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user