New Grease Pencil object for 2D animation
This commit merge the full development done in greasepencil-object branch and include mainly the following features. - New grease pencil object. - New drawing engine. - New grease pencil modes Draw/Sculpt/Edit and Weight Paint. - New brushes for grease pencil. - New modifiers for grease pencil. - New shaders FX. - New material system (replace old palettes and colors). - Split of annotations (old grease pencil) and new grease pencil object. - UI adapted to blender 2.8. You can get more info here: https://code.blender.org/2017/12/drawing-2d-animation-in-blender-2-8/ https://code.blender.org/2018/07/grease-pencil-status-update/ This is the result of nearly two years of development and I want thanks firstly the other members of the grease pencil team: Daniel M. Lara, Matias Mendiola and Joshua Leung for their support, ideas and to keep working in the project all the time, without them this project had been impossible. Also, I want thanks other Blender developers for their help, advices and to be there always to help me, and specially to Clément Foucault, Dalai Felinto, Pablo Vázquez and Campbell Barton.
@ -598,12 +598,12 @@ function(SETUP_BLENDER_SORTED_LIBS)
|
||||
bf_editor_util
|
||||
bf_editor_uvedit
|
||||
bf_editor_curve
|
||||
bf_editor_gpencil
|
||||
bf_editor_interface
|
||||
bf_editor_gizmo_library
|
||||
bf_editor_mesh
|
||||
bf_editor_metaball
|
||||
bf_editor_object
|
||||
bf_editor_gpencil
|
||||
bf_editor_lattice
|
||||
bf_editor_armature
|
||||
bf_editor_physics
|
||||
@ -626,12 +626,15 @@ function(SETUP_BLENDER_SORTED_LIBS)
|
||||
bf_freestyle
|
||||
bf_ikplugin
|
||||
bf_modifiers
|
||||
bf_gpencil_modifiers
|
||||
bf_alembic
|
||||
bf_bmesh
|
||||
bf_gpu
|
||||
bf_draw
|
||||
bf_blenloader
|
||||
bf_blenkernel
|
||||
bf_shader_fx
|
||||
bf_gpencil_modifiers
|
||||
bf_physics
|
||||
bf_nodes
|
||||
bf_rna
|
||||
|
@ -895,7 +895,10 @@ class CYCLES_PT_context_material(CyclesButtonsPanel, Panel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return (context.material or context.object) and CyclesButtonsPanel.poll(context)
|
||||
if context.active_object and context.active_object.type == 'GPENCIL':
|
||||
return False
|
||||
else:
|
||||
return (context.material or context.object) and CyclesButtonsPanel.poll(context)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
BIN
release/datafiles/brushicons/gp_brush_block.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
release/datafiles/brushicons/gp_brush_clone.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
release/datafiles/brushicons/gp_brush_erase_hard.png
Normal file
After Width: | Height: | Size: 6.0 KiB |
BIN
release/datafiles/brushicons/gp_brush_erase_soft.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
release/datafiles/brushicons/gp_brush_erase_stroke.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
release/datafiles/brushicons/gp_brush_fill.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
release/datafiles/brushicons/gp_brush_grab.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
release/datafiles/brushicons/gp_brush_ink.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
release/datafiles/brushicons/gp_brush_inknoise.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
release/datafiles/brushicons/gp_brush_marker.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
release/datafiles/brushicons/gp_brush_pen.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
release/datafiles/brushicons/gp_brush_pencil.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
release/datafiles/brushicons/gp_brush_pinch.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
release/datafiles/brushicons/gp_brush_push.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
release/datafiles/brushicons/gp_brush_randomize.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
release/datafiles/brushicons/gp_brush_smooth.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
release/datafiles/brushicons/gp_brush_strength.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
release/datafiles/brushicons/gp_brush_thickness.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
release/datafiles/brushicons/gp_brush_twist.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
release/datafiles/brushicons/gp_brush_weight.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
release/datafiles/icons/brush.gpencil.draw.eraser_hard.dat
Normal file
BIN
release/datafiles/icons/brush.gpencil.draw.eraser_soft.dat
Normal file
BIN
release/datafiles/icons/brush.gpencil.draw.eraser_stroke.dat
Normal file
BIN
release/datafiles/icons/brush.gpencil.draw_block.dat
Normal file
BIN
release/datafiles/icons/brush.gpencil.draw_fill.dat
Normal file
BIN
release/datafiles/icons/brush.gpencil.draw_ink.dat
Normal file
BIN
release/datafiles/icons/brush.gpencil.draw_marker.dat
Normal file
BIN
release/datafiles/icons/brush.gpencil.draw_noise.dat
Normal file
BIN
release/datafiles/icons/brush.gpencil.draw_pen.dat
Normal file
BIN
release/datafiles/icons/brush.gpencil.draw_pencil.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.draw.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.draw.eraser.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.draw.line.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.draw.poly.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.edit_bend.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.edit_mirror.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.edit_shear.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.edit_to_sphere.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.sculpt_clone.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.sculpt_grab.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.sculpt_pinch.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.sculpt_push.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.sculpt_randomize.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.sculpt_smooth.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.sculpt_strength.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.sculpt_thickness.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.sculpt_twist.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.sculpt_weight.dat
Normal file
BIN
release/datafiles/preview_grease_pencil.blend
Normal file
@ -1,8 +1,8 @@
|
||||
/*
|
||||
* Generated by 'source/tools/utils/blender_theme_as_c.py'
|
||||
*
|
||||
* Do not hand edit this file!
|
||||
*/
|
||||
* Generated by 'source/tools/utils/blender_theme_as_c.py'
|
||||
*
|
||||
* Do not hand edit this file!
|
||||
*/
|
||||
|
||||
#include "DNA_userdef_types.h"
|
||||
|
||||
@ -1040,5 +1040,5 @@ const bTheme U_theme_default = {
|
||||
.select = RGBA(0x000000ff),
|
||||
.active = RGBA(0x000000ff),
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit c87ee4d46f16d60a2e1db7514c8d5ab42c5d93df
|
||||
Subproject commit 371960484a38fc64e0a2635170a41a0d8ab2f6bd
|
@ -1 +1 @@
|
||||
Subproject commit 15b25a42783d1e516b5298d70b582fae2559ae17
|
||||
Subproject commit 474702157831f1a58bb50f5240ab8b1b02b6ba37
|
@ -121,6 +121,12 @@ KM_HIERARCHY = [
|
||||
|
||||
('Grease Pencil', 'EMPTY', 'WINDOW', [ # grease pencil stuff (per region)
|
||||
('Grease Pencil Stroke Edit Mode', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Paint (Draw brush)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Paint (Fill)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Paint (Erase)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Paint Mode', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Sculpt Mode', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Weight Mode', 'EMPTY', 'WINDOW', []),
|
||||
]),
|
||||
('Mask Editing', 'EMPTY', 'WINDOW', []),
|
||||
('Frames', 'EMPTY', 'WINDOW', []), # frame navigation (per region)
|
||||
|
@ -670,6 +670,42 @@ class AddPresetUnitsLength(AddPresetBase, Operator):
|
||||
preset_subdir = "units_length"
|
||||
|
||||
|
||||
class AddPresetGpencilBrush(AddPresetBase, Operator):
|
||||
"""Add or remove grease pencil brush preset"""
|
||||
bl_idname = "scene.gpencil_brush_preset_add"
|
||||
bl_label = "Add Grease Pencil Brush Preset"
|
||||
preset_menu = "VIEW3D_PT_gpencil_brush_presets"
|
||||
|
||||
preset_defines = [
|
||||
"brush = bpy.context.active_gpencil_brush",
|
||||
"settings = brush.gpencil_settings"
|
||||
]
|
||||
|
||||
preset_values = [
|
||||
"settings.input_samples",
|
||||
"settings.active_smooth_factor",
|
||||
"settings.angle",
|
||||
"settings.angle_factor",
|
||||
"settings.use_stabilizer",
|
||||
"brush.smooth_stroke_radius",
|
||||
"brush.smooth_stroke_factor",
|
||||
"settings.pen_smooth_factor",
|
||||
"settings.pen_smooth_steps",
|
||||
"settings.pen_thick_smooth_factor",
|
||||
"settings.pen_thick_smooth_steps",
|
||||
"settings.pen_subdivision_steps",
|
||||
"settings.random_subdiv",
|
||||
"settings.enable_random",
|
||||
"settings.random_pressure",
|
||||
"settings.random_strength",
|
||||
"settings.uv_random",
|
||||
"settings.pen_jitter",
|
||||
"settings.use_jitter_pressure",
|
||||
]
|
||||
|
||||
preset_subdir = "gpencil_brush"
|
||||
|
||||
|
||||
classes = (
|
||||
AddPresetCamera,
|
||||
AddPresetCloth,
|
||||
@ -686,6 +722,7 @@ classes = (
|
||||
AddPresetTrackingSettings,
|
||||
AddPresetTrackingTrackColor,
|
||||
AddPresetUnitsLength,
|
||||
AddPresetGpencilBrush,
|
||||
ExecutePreset,
|
||||
WM_MT_operator_presets,
|
||||
)
|
||||
|
@ -34,16 +34,19 @@ _modules = [
|
||||
"properties_data_camera",
|
||||
"properties_data_curve",
|
||||
"properties_data_empty",
|
||||
"properties_data_gpencil",
|
||||
"properties_data_light",
|
||||
"properties_data_lattice",
|
||||
"properties_data_mesh",
|
||||
"properties_data_metaball",
|
||||
"properties_data_modifier",
|
||||
"properties_data_shaderfx",
|
||||
"properties_data_lightprobe",
|
||||
"properties_data_speaker",
|
||||
"properties_data_workspace",
|
||||
"properties_mask_common",
|
||||
"properties_material",
|
||||
"properties_material_gpencil",
|
||||
"properties_object",
|
||||
"properties_paint_common",
|
||||
"properties_grease_pencil_common",
|
||||
|
402
release/scripts/startup/bl_ui/properties_data_gpencil.py
Normal file
@ -0,0 +1,402 @@
|
||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
import bpy
|
||||
from bpy.types import Menu, Panel, UIList
|
||||
from rna_prop_ui import PropertyPanel
|
||||
from .properties_grease_pencil_common import (
|
||||
GreasePencilDataPanel,
|
||||
GreasePencilOnionPanel,
|
||||
)
|
||||
|
||||
###############################
|
||||
# Base-Classes (for shared stuff - e.g. poll, attributes, etc.)
|
||||
|
||||
class DataButtonsPanel:
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_context = "data"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.object and context.object.type == 'GPENCIL'
|
||||
|
||||
|
||||
class LayerDataButtonsPanel:
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_context = "data"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return (context.object and
|
||||
context.object.type == 'GPENCIL' and
|
||||
context.active_gpencil_layer)
|
||||
|
||||
|
||||
###############################
|
||||
# GP Object Properties Panels and Helper Classes
|
||||
|
||||
class DATA_PT_gpencil(DataButtonsPanel, Panel):
|
||||
bl_label = ""
|
||||
bl_options = {'HIDE_HEADER'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
# Grease Pencil data selector
|
||||
gpd_owner = context.gpencil_data_owner
|
||||
gpd = context.gpencil_data
|
||||
|
||||
layout.template_ID(gpd_owner, "data")
|
||||
|
||||
|
||||
class GPENCIL_UL_layer(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
|
||||
# assert(isinstance(item, bpy.types.GPencilLayer)
|
||||
gpl = item
|
||||
gpd = context.gpencil_data
|
||||
|
||||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
||||
if gpl.lock:
|
||||
layout.active = False
|
||||
|
||||
row = layout.row(align=True)
|
||||
if gpl.is_parented:
|
||||
icon = 'BONE_DATA'
|
||||
else:
|
||||
icon = 'BLANK1'
|
||||
|
||||
row.label(text="", icon=icon)
|
||||
row.prop(gpl, "info", text="", emboss=False)
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(gpl, "lock", text="", emboss=False)
|
||||
row.prop(gpl, "hide", text="", emboss=False)
|
||||
row.prop(gpl, "unlock_color", text="", emboss=False)
|
||||
if gpl.use_onion_skinning is False:
|
||||
icon = 'GHOST_DISABLED'
|
||||
else:
|
||||
icon = 'GHOST_ENABLED'
|
||||
subrow = row.row(align=True)
|
||||
subrow.prop(gpl, "use_onion_skinning", text="", icon=icon, emboss=False)
|
||||
subrow.active = gpd.use_onion_skinning
|
||||
elif self.layout_type == 'GRID':
|
||||
layout.alignment = 'CENTER'
|
||||
layout.label(text="", icon_value=icon)
|
||||
|
||||
|
||||
class GPENCIL_MT_layer_specials(Menu):
|
||||
bl_label = "Layer"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator("gpencil.layer_duplicate", icon='COPY_ID') # XXX: needs a dedicated icon
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.reveal", icon='RESTRICT_VIEW_OFF', text="Show All")
|
||||
layout.operator("gpencil.hide", icon='RESTRICT_VIEW_ON', text="Hide Others").unselected = True
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.lock_all", icon='LOCKED', text="Lock All")
|
||||
layout.operator("gpencil.unlock_all", icon='UNLOCKED', text="UnLock All")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.layer_merge", icon='NLA', text="Merge Down")
|
||||
|
||||
|
||||
class DATA_PT_gpencil_datapanel(Panel):
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_context = "data"
|
||||
bl_label = "Layers"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if context.gpencil_data is None:
|
||||
return False
|
||||
|
||||
ob = context.object
|
||||
if ob is not None and ob.type == 'GPENCIL':
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
#layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
gpd = context.gpencil_data
|
||||
|
||||
# Grease Pencil data...
|
||||
if (gpd is None) or (not gpd.layers):
|
||||
layout.operator("gpencil.layer_add", text="New Layer")
|
||||
else:
|
||||
self.draw_layers(context, layout, gpd)
|
||||
|
||||
def draw_layers(self, context, layout, gpd):
|
||||
row = layout.row()
|
||||
|
||||
col = row.column()
|
||||
if len(gpd.layers) >= 2:
|
||||
layer_rows = 5
|
||||
else:
|
||||
layer_rows = 2
|
||||
col.template_list("GPENCIL_UL_layer", "", gpd, "layers", gpd.layers, "active_index", rows=layer_rows)
|
||||
|
||||
col = row.column()
|
||||
|
||||
sub = col.column(align=True)
|
||||
sub.operator("gpencil.layer_add", icon='ZOOMIN', text="")
|
||||
sub.operator("gpencil.layer_remove", icon='ZOOMOUT', text="")
|
||||
|
||||
gpl = context.active_gpencil_layer
|
||||
if gpl:
|
||||
sub.menu("GPENCIL_MT_layer_specials", icon='DOWNARROW_HLT', text="")
|
||||
|
||||
if len(gpd.layers) > 1:
|
||||
col.separator()
|
||||
|
||||
sub = col.column(align=True)
|
||||
sub.operator("gpencil.layer_move", icon='TRIA_UP', text="").type = 'UP'
|
||||
sub.operator("gpencil.layer_move", icon='TRIA_DOWN', text="").type = 'DOWN'
|
||||
|
||||
col.separator()
|
||||
|
||||
sub = col.column(align=True)
|
||||
sub.operator("gpencil.layer_isolate", icon='LOCKED', text="").affect_visibility = False
|
||||
sub.operator("gpencil.layer_isolate", icon='RESTRICT_VIEW_OFF', text="").affect_visibility = True
|
||||
|
||||
row = layout.row(align=True)
|
||||
if gpl:
|
||||
row.prop(gpl, "opacity", text="Opacity", slider=True)
|
||||
|
||||
|
||||
class DATA_PT_gpencil_layer_optionpanel(LayerDataButtonsPanel, Panel):
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_context = "data"
|
||||
bl_label = "Adjustments"
|
||||
bl_parent_id = 'DATA_PT_gpencil_datapanel'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
|
||||
gpl = context.active_gpencil_layer
|
||||
layout.active = not gpl.lock
|
||||
|
||||
# Layer options
|
||||
# Offsets - Color Tint
|
||||
layout.enabled = not gpl.lock
|
||||
col = layout.column(align=True)
|
||||
col.prop(gpl, "tint_color")
|
||||
col.prop(gpl, "tint_factor", slider=True)
|
||||
|
||||
# Offsets - Thickness
|
||||
col = layout.row(align=True)
|
||||
col.prop(gpl, "line_change", text="Stroke Thickness")
|
||||
|
||||
|
||||
class DATA_PT_gpencil_parentpanel(LayerDataButtonsPanel, Panel):
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_context = "data"
|
||||
bl_label = "Relations"
|
||||
bl_parent_id = 'DATA_PT_gpencil_datapanel'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
gpl = context.active_gpencil_layer
|
||||
col = layout.column(align=True)
|
||||
col.active = not gpl.lock
|
||||
col.prop(gpl, "parent", text="Parent")
|
||||
col.prop(gpl, "parent_type", text="Parent Type")
|
||||
parent = gpl.parent
|
||||
|
||||
if parent and gpl.parent_type == 'BONE' and parent.type == 'ARMATURE':
|
||||
col.prop_search(gpl, "parent_bone", parent.data, "bones", text="Bone")
|
||||
|
||||
|
||||
class DATA_PT_gpencil_onionpanel(Panel):
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_context = "data"
|
||||
bl_label = "Onion Skinning"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return bool(context.active_gpencil_layer)
|
||||
|
||||
@staticmethod
|
||||
def draw_header(self, context):
|
||||
self.layout.prop(context.gpencil_data, "use_onion_skinning", text="")
|
||||
|
||||
def draw(self, context):
|
||||
gpd = context.gpencil_data
|
||||
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.enabled = gpd.use_onion_skinning
|
||||
|
||||
GreasePencilOnionPanel.draw_settings(layout, gpd)
|
||||
|
||||
|
||||
class GPENCIL_MT_gpencil_vertex_group(Menu):
|
||||
bl_label = "GP Vertex Groups"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator_context = 'EXEC_AREA'
|
||||
layout.operator("object.vertex_group_add")
|
||||
|
||||
ob = context.active_object
|
||||
if ob.vertex_groups.active:
|
||||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.vertex_group_assign", text="Assign to Active Group")
|
||||
layout.operator("gpencil.vertex_group_remove_from", text="Remove from Active Group")
|
||||
|
||||
layout.separator()
|
||||
layout.operator_menu_enum("object.vertex_group_set_active", "group", text="Set Active Group")
|
||||
layout.operator("object.vertex_group_remove", text="Remove Active Group").all = False
|
||||
layout.operator("object.vertex_group_remove", text="Remove All Groups").all = True
|
||||
|
||||
layout.separator()
|
||||
layout.operator("gpencil.vertex_group_select", text="Select Points")
|
||||
layout.operator("gpencil.vertex_group_deselect", text="Deselect Points")
|
||||
|
||||
|
||||
class GPENCIL_UL_vgroups(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
|
||||
vgroup = item
|
||||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
||||
layout.prop(vgroup, "name", text="", emboss=False, icon_value=icon)
|
||||
# icon = 'LOCKED' if vgroup.lock_weight else 'UNLOCKED'
|
||||
# layout.prop(vgroup, "lock_weight", text="", icon=icon, emboss=False)
|
||||
elif self.layout_type == 'GRID':
|
||||
layout.alignment = 'CENTER'
|
||||
layout.label(text="", icon_value=icon)
|
||||
|
||||
|
||||
class DATA_PT_gpencil_vertexpanel(DataButtonsPanel, Panel):
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_context = "data"
|
||||
bl_label = "Vertex Groups"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
ob = context.object
|
||||
group = ob.vertex_groups.active
|
||||
|
||||
rows = 2
|
||||
if group:
|
||||
rows = 4
|
||||
|
||||
row = layout.row()
|
||||
row.template_list("GPENCIL_UL_vgroups", "", ob, "vertex_groups", ob.vertex_groups, "active_index", rows=rows)
|
||||
|
||||
col = row.column(align=True)
|
||||
col.operator("object.vertex_group_add", icon='ZOOMIN', text="")
|
||||
col.operator("object.vertex_group_remove", icon='ZOOMOUT', text="").all = False
|
||||
|
||||
if ob.vertex_groups:
|
||||
row = layout.row()
|
||||
|
||||
sub = row.row(align=True)
|
||||
sub.operator("gpencil.vertex_group_assign", text="Assign")
|
||||
sub.operator("gpencil.vertex_group_remove_from", text="Remove")
|
||||
|
||||
sub = row.row(align=True)
|
||||
sub.operator("gpencil.vertex_group_select", text="Select")
|
||||
sub.operator("gpencil.vertex_group_deselect", text="Deselect")
|
||||
|
||||
layout.prop(context.tool_settings, "vertex_group_weight", text="Weight")
|
||||
|
||||
|
||||
class DATA_PT_gpencil_display(DataButtonsPanel, Panel):
|
||||
bl_label = "Viewport Display"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
|
||||
ob = context.object
|
||||
|
||||
gpd = context.gpencil_data
|
||||
gpl = context.active_gpencil_layer
|
||||
|
||||
layout.prop(gpd, "xray_mode", text="Depth Ordering")
|
||||
layout.prop(gpd, "edit_line_color", text="Edit Line Color")
|
||||
layout.prop(ob, "empty_draw_size", text="Marker Size")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(gpd, "show_constant_thickness")
|
||||
sub = col.column()
|
||||
sub.active = not gpd.show_constant_thickness
|
||||
sub.prop(gpd, "pixfactor", text="Thickness Scale")
|
||||
|
||||
if gpl:
|
||||
layout.prop(gpd, "show_stroke_direction", text="Show Stroke Directions")
|
||||
|
||||
|
||||
class DATA_PT_custom_props_gpencil(DataButtonsPanel, PropertyPanel, Panel):
|
||||
_context_path = "object.data"
|
||||
_property_type = bpy.types.GreasePencil
|
||||
|
||||
###############################
|
||||
|
||||
classes = (
|
||||
DATA_PT_gpencil,
|
||||
DATA_PT_gpencil_datapanel,
|
||||
DATA_PT_gpencil_onionpanel,
|
||||
DATA_PT_gpencil_layer_optionpanel,
|
||||
DATA_PT_gpencil_parentpanel,
|
||||
DATA_PT_gpencil_vertexpanel,
|
||||
DATA_PT_gpencil_display,
|
||||
DATA_PT_custom_props_gpencil,
|
||||
|
||||
GPENCIL_UL_layer,
|
||||
GPENCIL_UL_vgroups,
|
||||
|
||||
GPENCIL_MT_layer_specials,
|
||||
GPENCIL_MT_gpencil_vertex_group,
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
from bpy.utils import register_class
|
||||
for cls in classes:
|
||||
register_class(cls)
|
@ -28,10 +28,14 @@ class ModifierButtonsPanel:
|
||||
bl_context = "modifier"
|
||||
bl_options = {'HIDE_HEADER'}
|
||||
|
||||
|
||||
class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
||||
bl_label = "Modifiers"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
return ob and ob.type != 'GPENCIL'
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
@ -1563,8 +1567,447 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
||||
layout.operator("object.correctivesmooth_bind", text="Unbind" if is_bind else "Bind")
|
||||
|
||||
|
||||
class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
|
||||
bl_label = "Modifiers"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
return ob and ob.type == 'GPENCIL'
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
ob = context.object
|
||||
|
||||
layout.operator_menu_enum("object.gpencil_modifier_add", "type")
|
||||
|
||||
for md in ob.grease_pencil_modifiers:
|
||||
box = layout.template_greasepencil_modifier(md)
|
||||
if box:
|
||||
# match enum type to our functions, avoids a lookup table.
|
||||
getattr(self, md.type)(box, ob, md)
|
||||
|
||||
# the mt.type enum is (ab)used for a lookup on function names
|
||||
# ...to avoid lengthy if statements
|
||||
# so each type must have a function here.
|
||||
|
||||
def GP_NOISE(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "factor")
|
||||
row.prop(md, "random", text="", icon="TIME", toggle=True)
|
||||
row = col.row()
|
||||
row.enabled = md.random
|
||||
row.prop(md, "step")
|
||||
col.prop(md, "full_stroke")
|
||||
col.prop(md, "move_extreme")
|
||||
|
||||
col = split.column()
|
||||
col.label("Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
col.label("Vertex Group:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
|
||||
row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.label("Affect:")
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "affect_position", text="Position", icon='MESH_DATA', toggle=True)
|
||||
row.prop(md, "affect_strength", text="Strength", icon='COLOR', toggle=True)
|
||||
row.prop(md, "affect_thickness", text="Thickness", icon='LINE_DATA', toggle=True)
|
||||
row.prop(md, "affect_uv", text="UV", icon='MOD_UVPROJECT', toggle=True)
|
||||
|
||||
def GP_SMOOTH(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
row = layout.row(align=False)
|
||||
row.prop(md, "factor")
|
||||
row.prop(md, "step")
|
||||
|
||||
split = layout.split()
|
||||
col = split.column()
|
||||
col.label("Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
col = split.column()
|
||||
col.label("Vertex Group:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
|
||||
row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.label("Affect:")
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "affect_position", text="Position", icon='MESH_DATA', toggle=True)
|
||||
row.prop(md, "affect_strength", text="Strength", icon='COLOR', toggle=True)
|
||||
row.prop(md, "affect_thickness", text="Thickness", icon='LINE_DATA', toggle=True)
|
||||
row.prop(md, "affect_uv", text="UV", icon='MOD_UVPROJECT', toggle=True)
|
||||
|
||||
def GP_SUBDIV(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "level")
|
||||
row.prop(md, "simple", text="", icon="PARTICLE_POINT")
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
col = split.column()
|
||||
col.label("Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
def GP_SIMPLIFY(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
|
||||
row = layout.row()
|
||||
row.prop(md, "mode")
|
||||
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
col.label("Settings:")
|
||||
row = col.row(align=True)
|
||||
row.enabled = md.mode == 'FIXED'
|
||||
row.prop(md, "step")
|
||||
|
||||
row = col.row(align=True)
|
||||
row.enabled = not md.mode == 'FIXED'
|
||||
row.prop(md, "factor")
|
||||
|
||||
col = split.column()
|
||||
col.label("Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
def GP_THICK(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "thickness")
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
col.prop(md, "normalize_thickness")
|
||||
|
||||
col = split.column()
|
||||
col.label("Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
col.label("Vertex Group:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
|
||||
row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
if not md.normalize_thickness:
|
||||
split = layout.split()
|
||||
col = split.column()
|
||||
col.prop(md, "use_custom_curve")
|
||||
|
||||
if md.use_custom_curve:
|
||||
col.template_curve_mapping(md, "curve")
|
||||
|
||||
def GP_TINT(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
col.prop(md, "color")
|
||||
col.prop(md, "factor")
|
||||
|
||||
col = split.column()
|
||||
col.label("Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
row = layout.row()
|
||||
row.prop(md, "create_colors")
|
||||
|
||||
def GP_COLOR(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
col.label("Color:")
|
||||
col.prop(md, "hue", text="H")
|
||||
col.prop(md, "saturation", text="S")
|
||||
col.prop(md, "value", text="V")
|
||||
|
||||
col = split.column()
|
||||
col.label("Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
row = layout.row()
|
||||
row.prop(md, "create_colors")
|
||||
|
||||
def GP_OPACITY(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
col.label("Opacity:")
|
||||
col.prop(md, "factor")
|
||||
|
||||
col = split.column()
|
||||
col.label("Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
col.label("Vertex Group:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
|
||||
row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
def GP_INSTANCE(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
|
||||
col = layout.column()
|
||||
col.prop(md, "count")
|
||||
col.prop(md, "use_make_objects")
|
||||
|
||||
split = layout.split()
|
||||
col = split.column()
|
||||
col.label("Offset:")
|
||||
col.prop(md, "offset", text="")
|
||||
|
||||
col = split.column()
|
||||
col.label("Shift:")
|
||||
col.prop(md, "shift", text="")
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "lock_axis", expand=True)
|
||||
|
||||
split = layout.split()
|
||||
col = split.column()
|
||||
col.label("Rotation:")
|
||||
col.prop(md, "rotation", text="")
|
||||
col.separator()
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "random_rot", text="", icon="TIME", toggle=True)
|
||||
row.prop(md, "rot_factor", text="")
|
||||
|
||||
col = split.column()
|
||||
col.label("Scale:")
|
||||
col.prop(md, "scale", text="")
|
||||
col.separator()
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "random_scale", text="", icon="TIME", toggle=True)
|
||||
row.prop(md, "scale_factor", text="")
|
||||
|
||||
split = layout.split()
|
||||
col = split.column()
|
||||
col.label("Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
def GP_BUILD(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
col.prop(md, "mode")
|
||||
if md.mode == 'CONCURRENT':
|
||||
col.prop(md, "concurrent_time_alignment")
|
||||
else:
|
||||
col.separator() # For spacing
|
||||
col.separator()
|
||||
col.separator()
|
||||
|
||||
col.prop(md, "transition")
|
||||
sub = col.column(align=True)
|
||||
sub.prop(md, "start_delay")
|
||||
sub.prop(md, "length")
|
||||
|
||||
col = split.column(align=True)
|
||||
col.prop(md, "use_restrict_frame_range")
|
||||
sub = col.column(align=True)
|
||||
sub.active = md.use_restrict_frame_range
|
||||
sub.prop(md, "frame_start", text="Start")
|
||||
sub.prop(md, "frame_end", text="End")
|
||||
col.separator()
|
||||
|
||||
col.label("Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
def GP_LATTICE(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Object:")
|
||||
col.prop(md, "object", text="")
|
||||
|
||||
col = split.column()
|
||||
col.label("Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
col.label("Vertex Group:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
|
||||
row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
layout.separator()
|
||||
layout.prop(md, "strength", slider=True)
|
||||
|
||||
def GP_MIRROR(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "x_axis")
|
||||
row.prop(md, "y_axis")
|
||||
row.prop(md, "z_axis")
|
||||
|
||||
# GPXX: Not implemented yet
|
||||
# layout.separator()
|
||||
# layout.prop(md, "clip")
|
||||
|
||||
layout.label("Layer:")
|
||||
row = layout.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
layout.label(text="Object:")
|
||||
layout.prop(md, "object", text="")
|
||||
|
||||
|
||||
def GP_HOOK(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Object:")
|
||||
col.prop(md, "object", text="")
|
||||
if md.object and md.object.type == 'ARMATURE':
|
||||
col.label(text="Bone:")
|
||||
col.prop_search(md, "subtarget", md.object.data, "bones", text="")
|
||||
|
||||
col = split.column()
|
||||
col.label("Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
col.label("Vertex Group:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
|
||||
row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
use_falloff = (md.falloff_type != 'NONE')
|
||||
split = layout.split()
|
||||
|
||||
layout.separator()
|
||||
|
||||
row = layout.row(align=True)
|
||||
if use_falloff:
|
||||
row.prop(md, "falloff_radius")
|
||||
row.prop(md, "strength", slider=True)
|
||||
layout.prop(md, "falloff_type")
|
||||
|
||||
col = layout.column()
|
||||
if use_falloff:
|
||||
if md.falloff_type == 'CURVE':
|
||||
col.template_curve_mapping(md, "falloff_curve")
|
||||
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
col.prop(md, "use_falloff_uniform")
|
||||
|
||||
|
||||
def GP_OFFSET(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
col.prop(md, "location")
|
||||
col.prop(md, "scale")
|
||||
|
||||
col = split.column()
|
||||
col.prop(md, "rotation")
|
||||
|
||||
|
||||
col.label("Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
col.label("Vertex Group:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
|
||||
row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
|
||||
|
||||
|
||||
classes = (
|
||||
DATA_PT_modifiers,
|
||||
DATA_PT_gpencil_modifiers,
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
|
134
release/scripts/startup/bl_ui/properties_data_shaderfx.py
Normal file
@ -0,0 +1,134 @@
|
||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
import bpy
|
||||
from bpy.types import Panel
|
||||
from bpy.app.translations import pgettext_iface as iface_
|
||||
|
||||
|
||||
class ShaderFxButtonsPanel:
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_context = "shaderfx"
|
||||
bl_options = {'HIDE_HEADER'}
|
||||
|
||||
class DATA_PT_shader_fx(ShaderFxButtonsPanel, Panel):
|
||||
bl_label = "Effects"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return True
|
||||
ob = context.object
|
||||
return ob and ob.type == 'GPENCIL'
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
|
||||
ob = context.object
|
||||
|
||||
layout.operator_menu_enum("object.shaderfx_add", "type")
|
||||
|
||||
for fx in ob.shader_effects:
|
||||
box = layout.template_shaderfx(fx)
|
||||
if box:
|
||||
# match enum type to our functions, avoids a lookup table.
|
||||
getattr(self, fx.type)(box, fx)
|
||||
|
||||
# the mt.type enum is (ab)used for a lookup on function names
|
||||
# ...to avoid lengthy if statements
|
||||
# so each type must have a function here.
|
||||
|
||||
def FX_BLUR(self, layout, fx):
|
||||
|
||||
layout.prop(fx, "factor", text="Factor")
|
||||
layout.prop(fx, "samples", text="Samples")
|
||||
|
||||
layout.separator()
|
||||
layout.prop(fx, "use_dof_mode")
|
||||
if fx.use_dof_mode:
|
||||
layout.prop(fx, "coc")
|
||||
|
||||
def FX_COLORIZE(self, layout, fx):
|
||||
layout.prop(fx, "mode", text="Mode")
|
||||
|
||||
if fx.mode == 'BITONE':
|
||||
layout.prop(fx, "low_color", text="Low Color")
|
||||
if fx.mode == 'CUSTOM':
|
||||
layout.prop(fx, "low_color", text="Color")
|
||||
|
||||
if fx.mode == 'BITONE':
|
||||
layout.prop(fx, "high_color", text="High Color")
|
||||
|
||||
if fx.mode in {'BITONE', 'CUSTOM', 'TRANSPARENT'}:
|
||||
layout.prop(fx, "factor")
|
||||
|
||||
def FX_WAVE(self, layout,fx):
|
||||
layout.prop(fx, "orientation", expand=True)
|
||||
|
||||
layout.separator()
|
||||
layout.prop(fx, "amplitude")
|
||||
layout.prop(fx, "period")
|
||||
layout.prop(fx, "phase")
|
||||
|
||||
def FX_PIXEL(self, layout, fx):
|
||||
layout.prop(fx, "size", text="Size")
|
||||
|
||||
layout.prop(fx, "use_lines", text="Display Lines")
|
||||
|
||||
col = layout.column()
|
||||
col.enabled = fx.use_lines
|
||||
col.prop(fx, "color")
|
||||
|
||||
def FX_RIM(self, layout, fx):
|
||||
layout.prop(fx, "offset", text="Offset")
|
||||
|
||||
layout.prop(fx, "rim_color")
|
||||
layout.prop(fx, "mask_color")
|
||||
layout.prop(fx, "mode")
|
||||
layout.prop(fx, "blur")
|
||||
layout.prop(fx, "samples")
|
||||
|
||||
def FX_SWIRL(self, layout, fx):
|
||||
layout.prop(fx, "object", text="Object")
|
||||
|
||||
layout.prop(fx, "radius")
|
||||
layout.prop(fx, "angle")
|
||||
|
||||
layout.prop(fx, "transparent")
|
||||
|
||||
def FX_FLIP(self, layout, fx):
|
||||
layout.prop(fx, "flip_horizontal")
|
||||
layout.prop(fx, "flip_vertical")
|
||||
|
||||
def FX_LIGHT(self, layout, fx):
|
||||
layout.prop(fx, "object", text="Object")
|
||||
|
||||
layout.prop(fx, "energy")
|
||||
layout.prop(fx, "ambient")
|
||||
|
||||
|
||||
classes = (
|
||||
DATA_PT_shader_fx,
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
from bpy.utils import register_class
|
||||
for cls in classes:
|
||||
register_class(cls)
|
@ -86,8 +86,11 @@ class EEVEE_MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
engine = context.engine
|
||||
return (context.material or context.object) and (engine in cls.COMPAT_ENGINES)
|
||||
if context.active_object and context.active_object.type == 'GPENCIL':
|
||||
return False
|
||||
else:
|
||||
engine = context.engine
|
||||
return (context.material or context.object) and (engine in cls.COMPAT_ENGINES)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
322
release/scripts/startup/bl_ui/properties_material_gpencil.py
Normal file
@ -0,0 +1,322 @@
|
||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
import bpy
|
||||
from bpy.types import Menu, Panel, UIList
|
||||
from rna_prop_ui import PropertyPanel
|
||||
|
||||
|
||||
class GPENCIL_MT_color_specials(Menu):
|
||||
bl_label = "Layer"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator("gpencil.color_reveal", icon='RESTRICT_VIEW_OFF', text="Show All")
|
||||
layout.operator("gpencil.color_hide", icon='RESTRICT_VIEW_ON', text="Hide Others").unselected = True
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.color_lock_all", icon='LOCKED', text="Lock All")
|
||||
layout.operator("gpencil.color_unlock_all", icon='UNLOCKED', text="UnLock All")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.stroke_lock_color", icon='BORDER_RECT', text="Lock Unselected")
|
||||
layout.operator("gpencil.lock_layer", icon='COLOR', text="Lock Unused")
|
||||
|
||||
|
||||
class GPENCIL_UL_matslots(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
|
||||
slot = item
|
||||
ma = slot.material
|
||||
if (ma is not None) and (ma.grease_pencil is not None):
|
||||
gpcolor = ma.grease_pencil
|
||||
|
||||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
||||
if gpcolor.lock:
|
||||
layout.active = False
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.enabled = not gpcolor.lock
|
||||
row.prop(ma, "name", text="", emboss=False, icon_value=icon)
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(gpcolor, "lock", text="", emboss=False)
|
||||
row.prop(gpcolor, "hide", text="", emboss=False)
|
||||
if gpcolor.ghost is True:
|
||||
icon = 'GHOST_DISABLED'
|
||||
else:
|
||||
icon = 'GHOST_ENABLED'
|
||||
row.prop(gpcolor, "ghost", text="", icon=icon, emboss=False)
|
||||
|
||||
elif self.layout_type == 'GRID':
|
||||
layout.alignment = 'CENTER'
|
||||
layout.label(text="", icon_value=icon)
|
||||
|
||||
|
||||
class GPMaterialButtonsPanel:
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_context = "material"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
return (ob and ob.type == 'GPENCIL' and
|
||||
ob.active_material and
|
||||
ob.active_material.grease_pencil)
|
||||
|
||||
|
||||
|
||||
class MATERIAL_PT_gpencil_slots(Panel):
|
||||
bl_label = "Grease Pencil Material Slots"
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_context = "material"
|
||||
bl_options = {'HIDE_HEADER'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
return ob and ob.type == 'GPENCIL'
|
||||
|
||||
@staticmethod
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
gpd = context.gpencil_data
|
||||
|
||||
mat = context.object.active_material
|
||||
ob = context.object
|
||||
slot = context.material_slot
|
||||
space = context.space_data
|
||||
|
||||
if ob:
|
||||
is_sortable = len(ob.material_slots) > 1
|
||||
rows = 1
|
||||
if (is_sortable):
|
||||
rows = 4
|
||||
|
||||
row = layout.row()
|
||||
|
||||
row.template_list("GPENCIL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=rows)
|
||||
|
||||
col = row.column(align=True)
|
||||
col.operator("object.material_slot_add", icon='ZOOMIN', text="")
|
||||
col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")
|
||||
|
||||
col.menu("GPENCIL_MT_color_specials", icon='DOWNARROW_HLT', text="")
|
||||
|
||||
if is_sortable:
|
||||
col.separator()
|
||||
|
||||
col.operator("object.material_slot_move", icon='TRIA_UP', text="").direction = 'UP'
|
||||
col.operator("object.material_slot_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
|
||||
|
||||
col.separator()
|
||||
|
||||
sub = col.column(align=True)
|
||||
sub.operator("gpencil.color_isolate", icon='LOCKED', text="").affect_visibility = False
|
||||
sub.operator("gpencil.color_isolate", icon='RESTRICT_VIEW_OFF', text="").affect_visibility = True
|
||||
|
||||
row = layout.row()
|
||||
|
||||
if ob:
|
||||
row.template_ID(ob, "active_material", new="material.new", live_icon=True)
|
||||
|
||||
if slot:
|
||||
icon_link = 'MESH_DATA' if slot.link == 'DATA' else 'OBJECT_DATA'
|
||||
row.prop(slot, "link", icon=icon_link, icon_only=True)
|
||||
|
||||
if gpd.use_stroke_edit_mode:
|
||||
row = layout.row(align=True)
|
||||
row.operator("gpencil.stroke_change_color", text="Assign")
|
||||
row.operator("gpencil.color_select", text="Select")
|
||||
|
||||
elif mat:
|
||||
row.template_ID(space, "pin_id")
|
||||
|
||||
|
||||
# Used as parent for "Stroke" and "Fill" panels
|
||||
class MATERIAL_PT_gpencil_surface(GPMaterialButtonsPanel, Panel):
|
||||
bl_label = "Surface"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
ma = context.object.active_material
|
||||
if ma is None or ma.grease_pencil is None:
|
||||
return False
|
||||
|
||||
return ob and ob.type == 'GPENCIL'
|
||||
|
||||
@staticmethod
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
|
||||
|
||||
class MATERIAL_PT_gpencil_strokecolor(GPMaterialButtonsPanel, Panel):
|
||||
bl_label = "Stroke"
|
||||
bl_parent_id = 'MATERIAL_PT_gpencil_surface'
|
||||
|
||||
@staticmethod
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
|
||||
ma = context.object.active_material
|
||||
if ma is not None and ma.grease_pencil is not None:
|
||||
gpcolor = ma.grease_pencil
|
||||
|
||||
col = layout.column()
|
||||
col.active = not gpcolor.lock
|
||||
|
||||
col.prop(gpcolor, "mode")
|
||||
|
||||
col.prop(gpcolor, "stroke_style", text="Style")
|
||||
|
||||
if gpcolor.stroke_style == 'TEXTURE':
|
||||
row = col.row()
|
||||
row.enabled = not gpcolor.lock
|
||||
col = row.column(align=True)
|
||||
col.template_ID(gpcolor, "stroke_image", open="image.open")
|
||||
col.prop(gpcolor, "pixel_size", text="UV Factor")
|
||||
col.prop(gpcolor, "use_stroke_pattern", text="Use As Pattern")
|
||||
|
||||
if gpcolor.stroke_style == 'SOLID' or gpcolor.use_stroke_pattern is True:
|
||||
col.prop(gpcolor, "color", text="Color")
|
||||
|
||||
|
||||
class MATERIAL_PT_gpencil_fillcolor(GPMaterialButtonsPanel, Panel):
|
||||
bl_label = "Fill"
|
||||
bl_parent_id = 'MATERIAL_PT_gpencil_surface'
|
||||
|
||||
@staticmethod
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
|
||||
ma = context.object.active_material
|
||||
if ma is not None and ma.grease_pencil:
|
||||
gpcolor = ma.grease_pencil
|
||||
|
||||
# color settings
|
||||
col = layout.column()
|
||||
col.active = not gpcolor.lock
|
||||
col.prop(gpcolor, "fill_style", text="Style")
|
||||
|
||||
if gpcolor.fill_style == 'GRADIENT':
|
||||
col.prop(gpcolor, "gradient_type")
|
||||
|
||||
if gpcolor.fill_style != 'TEXTURE':
|
||||
col.prop(gpcolor, "fill_color", text="Color")
|
||||
|
||||
if gpcolor.fill_style in ('GRADIENT', 'CHESSBOARD'):
|
||||
col.prop(gpcolor, "mix_color", text="Secondary Color")
|
||||
|
||||
if gpcolor.fill_style == 'GRADIENT':
|
||||
col.prop(gpcolor, "mix_factor", text="Mix Factor", slider=True)
|
||||
|
||||
if gpcolor.fill_style in ('GRADIENT', 'CHESSBOARD'):
|
||||
col.prop(gpcolor, "flip", text="Flip Colors")
|
||||
|
||||
col.prop(gpcolor, "pattern_shift", text="Location")
|
||||
col.prop(gpcolor, "pattern_scale", text="Scale")
|
||||
|
||||
if gpcolor.gradient_type == 'RADIAL' and gpcolor.fill_style not in ('SOLID', 'CHESSBOARD'):
|
||||
col.prop(gpcolor, "pattern_radius", text="Radius")
|
||||
else:
|
||||
if gpcolor.fill_style != 'SOLID':
|
||||
col.prop(gpcolor, "pattern_angle", text="Angle")
|
||||
|
||||
if gpcolor.fill_style == 'CHESSBOARD':
|
||||
col.prop(gpcolor, "pattern_gridsize", text="Box Size")
|
||||
|
||||
# Texture
|
||||
if gpcolor.fill_style == 'TEXTURE' or (gpcolor.texture_mix is True and gpcolor.fill_style == 'SOLID'):
|
||||
col.template_ID(gpcolor, "fill_image", open="image.open")
|
||||
|
||||
if gpcolor.fill_style == 'TEXTURE':
|
||||
col.prop(gpcolor, "use_fill_pattern", text="Use As Pattern")
|
||||
if gpcolor.use_fill_pattern is True:
|
||||
col.prop(gpcolor, "fill_color", text="Color")
|
||||
|
||||
col.prop(gpcolor, "texture_offset", text="Offset")
|
||||
col.prop(gpcolor, "texture_scale", text="Scale")
|
||||
col.prop(gpcolor, "texture_angle")
|
||||
col.prop(gpcolor, "texture_opacity")
|
||||
col.prop(gpcolor, "texture_clamp", text="Clip Image")
|
||||
|
||||
if gpcolor.use_fill_pattern is False:
|
||||
col.prop(gpcolor, "texture_mix", text="Mix With Color")
|
||||
|
||||
if gpcolor.texture_mix is True:
|
||||
col.prop(gpcolor, "fill_color", text="Mix Color")
|
||||
col.prop(gpcolor, "mix_factor", text="Mix Factor", slider=True)
|
||||
|
||||
|
||||
class MATERIAL_PT_gpencil_preview(GPMaterialButtonsPanel, Panel):
|
||||
bl_label = "Preview"
|
||||
COMPAT_ENGINES = {'BLENDER_EEVEE'}
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
ma = context.object.active_material
|
||||
self.layout.label(ma.name)
|
||||
self.layout.template_preview(ma)
|
||||
|
||||
|
||||
class MATERIAL_PT_gpencil_custom_props(GPMaterialButtonsPanel, PropertyPanel, Panel):
|
||||
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_OPENGL'}
|
||||
_context_path = "object.active_material"
|
||||
_property_type = bpy.types.Material
|
||||
|
||||
|
||||
class MATERIAL_PT_gpencil_options(GPMaterialButtonsPanel, Panel):
|
||||
bl_label = "Options"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@staticmethod
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
|
||||
ma = context.object.active_material
|
||||
if ma is not None and ma.grease_pencil is not None:
|
||||
gpcolor = ma.grease_pencil
|
||||
layout.prop(gpcolor, "pass_index")
|
||||
|
||||
|
||||
classes = (
|
||||
GPENCIL_UL_matslots,
|
||||
GPENCIL_MT_color_specials,
|
||||
MATERIAL_PT_gpencil_slots,
|
||||
MATERIAL_PT_gpencil_preview,
|
||||
MATERIAL_PT_gpencil_surface,
|
||||
MATERIAL_PT_gpencil_strokecolor,
|
||||
MATERIAL_PT_gpencil_fillcolor,
|
||||
MATERIAL_PT_gpencil_options,
|
||||
MATERIAL_PT_gpencil_custom_props,
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
from bpy.utils import register_class
|
||||
for cls in classes:
|
||||
register_class(cls)
|
@ -28,9 +28,9 @@ from rna_prop_ui import PropertyPanel
|
||||
from bl_operators.presets import PresetMenu
|
||||
|
||||
from .properties_physics_common import (
|
||||
point_cache_ui,
|
||||
effector_weights_ui,
|
||||
)
|
||||
point_cache_ui,
|
||||
effector_weights_ui,
|
||||
)
|
||||
|
||||
|
||||
class SCENE_PT_units_length_presets(PresetMenu):
|
||||
@ -104,7 +104,6 @@ class SCENE_PT_unit(SceneButtonsPanel, Panel):
|
||||
col.prop(unit, "scale_length")
|
||||
col.prop(unit, "use_separate")
|
||||
|
||||
|
||||
class SceneKeyingSetsPanel:
|
||||
|
||||
@staticmethod
|
||||
@ -568,6 +567,33 @@ class SCENE_PT_simplify_render(SceneButtonsPanel, Panel):
|
||||
col.prop(rd, "simplify_child_particles_render", text="Max Child Particles")
|
||||
|
||||
|
||||
class SCENE_PT_simplify_greasepencil(SceneButtonsPanel, Panel):
|
||||
bl_label = "Simplify Grease Pencil"
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw_header(self, context):
|
||||
rd = context.scene.render
|
||||
self.layout.prop(rd, "simplify_gpencil", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
rd = context.scene.render
|
||||
|
||||
layout.active = rd.simplify_gpencil
|
||||
|
||||
row = layout.row()
|
||||
row.prop(rd, "simplify_gpencil_onplay", text="Only on Play")
|
||||
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
col.prop(rd, "simplify_gpencil_view_fill", text="Fill")
|
||||
col.prop(rd, "simplify_gpencil_remove_lines", text="Remove Fill Lines")
|
||||
col.prop(rd, "simplify_gpencil_view_modifier", text="Modifiers")
|
||||
|
||||
|
||||
class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, Panel):
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
|
||||
_context_path = "scene"
|
||||
@ -593,6 +619,7 @@ classes = (
|
||||
SCENE_PT_simplify,
|
||||
SCENE_PT_simplify_viewport,
|
||||
SCENE_PT_simplify_render,
|
||||
SCENE_PT_simplify_greasepencil,
|
||||
SCENE_PT_custom_props,
|
||||
)
|
||||
|
||||
|
@ -23,14 +23,8 @@ from bpy.types import Panel, Header, Menu, UIList
|
||||
from bpy.app.translations import pgettext_iface as iface_
|
||||
from bl_operators.presets import PresetMenu
|
||||
from .properties_grease_pencil_common import (
|
||||
GreasePencilDrawingToolsPanel,
|
||||
GreasePencilStrokeEditPanel,
|
||||
GreasePencilStrokeSculptPanel,
|
||||
GreasePencilBrushPanel,
|
||||
GreasePencilBrushCurvesPanel,
|
||||
GreasePencilDataPanel,
|
||||
GreasePencilPaletteColorPanel,
|
||||
)
|
||||
GreasePencilDrawingToolsPanel,
|
||||
GreasePencilDataPanel)
|
||||
|
||||
|
||||
class CLIP_UL_tracking_objects(UIList):
|
||||
@ -1154,40 +1148,12 @@ class CLIP_PT_grease_pencil(GreasePencilDataPanel, CLIP_PT_clip_view_panel, Pane
|
||||
# But, this should only be visible in "clip" view
|
||||
|
||||
|
||||
# Grease Pencil palette colors
|
||||
class CLIP_PT_grease_pencil_palettecolor(GreasePencilPaletteColorPanel, CLIP_PT_clip_view_panel, Panel):
|
||||
bl_space_type = 'CLIP_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
# NOTE: this is just a wrapper around the generic GP Panel
|
||||
# But, this should only be visible in "clip" view
|
||||
|
||||
|
||||
# Grease Pencil drawing tools
|
||||
class CLIP_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
|
||||
bl_space_type = 'CLIP_EDITOR'
|
||||
bl_region_type = 'TOOLS'
|
||||
|
||||
|
||||
# Grease Pencil stroke editing tools
|
||||
class CLIP_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
|
||||
bl_space_type = 'CLIP_EDITOR'
|
||||
|
||||
|
||||
# Grease Pencil stroke sculpting tools
|
||||
class CLIP_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, Panel):
|
||||
bl_space_type = 'CLIP_EDITOR'
|
||||
|
||||
|
||||
# Grease Pencil drawing brushes
|
||||
class CLIP_PT_tools_grease_pencil_brush(GreasePencilBrushPanel, Panel):
|
||||
bl_space_type = 'CLIP_EDITOR'
|
||||
|
||||
|
||||
# Grease Pencil drawing curves
|
||||
class CLIP_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Panel):
|
||||
bl_space_type = 'CLIP_EDITOR'
|
||||
|
||||
|
||||
class CLIP_MT_view(Menu):
|
||||
bl_label = "View"
|
||||
@ -1515,12 +1481,7 @@ classes = (
|
||||
CLIP_PT_footage_info,
|
||||
CLIP_PT_tools_scenesetup,
|
||||
CLIP_PT_grease_pencil,
|
||||
CLIP_PT_grease_pencil_palettecolor,
|
||||
CLIP_PT_tools_grease_pencil_draw,
|
||||
CLIP_PT_tools_grease_pencil_edit,
|
||||
CLIP_PT_tools_grease_pencil_sculpt,
|
||||
CLIP_PT_tools_grease_pencil_brush,
|
||||
CLIP_PT_tools_grease_pencil_brushcurves,
|
||||
CLIP_MT_view,
|
||||
CLIP_MT_clip,
|
||||
CLIP_MT_proxy,
|
||||
|
@ -21,20 +21,15 @@ import bpy
|
||||
import math
|
||||
from bpy.types import Header, Menu, Panel, UIList
|
||||
from .properties_paint_common import (
|
||||
UnifiedPaintPanel,
|
||||
brush_texture_settings,
|
||||
brush_texpaint_common,
|
||||
brush_mask_texture_settings,
|
||||
)
|
||||
UnifiedPaintPanel,
|
||||
brush_texture_settings,
|
||||
brush_texpaint_common,
|
||||
brush_mask_texture_settings,
|
||||
)
|
||||
from .properties_grease_pencil_common import (
|
||||
GreasePencilDrawingToolsPanel,
|
||||
GreasePencilStrokeEditPanel,
|
||||
GreasePencilStrokeSculptPanel,
|
||||
GreasePencilBrushPanel,
|
||||
GreasePencilBrushCurvesPanel,
|
||||
GreasePencilDataPanel,
|
||||
GreasePencilPaletteColorPanel,
|
||||
)
|
||||
GreasePencilDrawingToolsPanel,
|
||||
GreasePencilDataPanel
|
||||
)
|
||||
from bpy.app.translations import pgettext_iface as iface_
|
||||
|
||||
|
||||
@ -1346,39 +1341,12 @@ class IMAGE_PT_grease_pencil(GreasePencilDataPanel, Panel):
|
||||
|
||||
# NOTE: this is just a wrapper around the generic GP Panel
|
||||
|
||||
|
||||
# Grease Pencil palette colors
|
||||
class IMAGE_PT_grease_pencil_palettecolor(GreasePencilPaletteColorPanel, Panel):
|
||||
bl_space_type = 'IMAGE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
|
||||
# NOTE: this is just a wrapper around the generic GP Panel
|
||||
|
||||
|
||||
# Grease Pencil drawing tools
|
||||
class IMAGE_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
|
||||
bl_space_type = 'IMAGE_EDITOR'
|
||||
bl_region_type = 'TOOLS'
|
||||
|
||||
|
||||
# Grease Pencil stroke editing tools
|
||||
class IMAGE_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
|
||||
bl_space_type = 'IMAGE_EDITOR'
|
||||
|
||||
|
||||
# Grease Pencil stroke sculpting tools
|
||||
class IMAGE_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, Panel):
|
||||
bl_space_type = 'IMAGE_EDITOR'
|
||||
|
||||
|
||||
# Grease Pencil drawing brushes
|
||||
class IMAGE_PT_tools_grease_pencil_brush(GreasePencilBrushPanel, Panel):
|
||||
bl_space_type = 'IMAGE_EDITOR'
|
||||
|
||||
|
||||
# Grease Pencil drawing curves
|
||||
class IMAGE_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Panel):
|
||||
bl_space_type = 'IMAGE_EDITOR'
|
||||
|
||||
|
||||
classes = (
|
||||
IMAGE_MT_view,
|
||||
@ -1430,12 +1398,7 @@ classes = (
|
||||
IMAGE_PT_sample_line,
|
||||
IMAGE_PT_scope_sample,
|
||||
IMAGE_PT_grease_pencil,
|
||||
IMAGE_PT_grease_pencil_palettecolor,
|
||||
IMAGE_PT_tools_grease_pencil_draw,
|
||||
IMAGE_PT_tools_grease_pencil_edit,
|
||||
IMAGE_PT_tools_grease_pencil_sculpt,
|
||||
IMAGE_PT_tools_grease_pencil_brush,
|
||||
IMAGE_PT_tools_grease_pencil_brushcurves,
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
|
@ -23,15 +23,10 @@ from bpy.types import Header, Menu, Panel
|
||||
from bpy.app.translations import pgettext_iface as iface_
|
||||
from bl_operators.presets import PresetMenu
|
||||
from .properties_grease_pencil_common import (
|
||||
GreasePencilDrawingToolsPanel,
|
||||
GreasePencilStrokeEditPanel,
|
||||
GreasePencilStrokeSculptPanel,
|
||||
GreasePencilBrushPanel,
|
||||
GreasePencilBrushCurvesPanel,
|
||||
GreasePencilDataPanel,
|
||||
GreasePencilPaletteColorPanel,
|
||||
GreasePencilToolsPanel
|
||||
)
|
||||
GreasePencilDrawingToolsPanel,
|
||||
GreasePencilDataPanel,
|
||||
GreasePencilToolsPanel
|
||||
)
|
||||
|
||||
|
||||
class NODE_HT_header(Header):
|
||||
@ -539,19 +534,6 @@ class NODE_PT_grease_pencil(GreasePencilDataPanel, Panel):
|
||||
return snode is not None and snode.node_tree is not None
|
||||
|
||||
|
||||
# Grease Pencil palette colors
|
||||
class NODE_PT_grease_pencil_palettecolor(GreasePencilPaletteColorPanel, Panel):
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
|
||||
# NOTE: this is just a wrapper around the generic GP Panel
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
snode = context.space_data
|
||||
return snode is not None and snode.node_tree is not None
|
||||
|
||||
|
||||
class NODE_PT_grease_pencil_tools(GreasePencilToolsPanel, Panel):
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
@ -571,31 +553,6 @@ class NODE_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
|
||||
bl_region_type = 'TOOLS'
|
||||
|
||||
|
||||
# Grease Pencil stroke editing tools
|
||||
class NODE_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
bl_region_type = 'TOOLS'
|
||||
|
||||
|
||||
# Grease Pencil stroke sculpting tools
|
||||
class NODE_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, Panel):
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
bl_region_type = 'TOOLS'
|
||||
|
||||
# Grease Pencil drawing brushes
|
||||
|
||||
|
||||
class NODE_PT_tools_grease_pencil_brush(GreasePencilBrushPanel, Panel):
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
bl_region_type = 'TOOLS'
|
||||
|
||||
# Grease Pencil drawing curves
|
||||
|
||||
|
||||
class NODE_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Panel):
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
bl_region_type = 'TOOLS'
|
||||
|
||||
# -----------------------------
|
||||
|
||||
|
||||
@ -620,13 +577,8 @@ classes = (
|
||||
NODE_PT_quality,
|
||||
NODE_UL_interface_sockets,
|
||||
NODE_PT_grease_pencil,
|
||||
NODE_PT_grease_pencil_palettecolor,
|
||||
NODE_PT_grease_pencil_tools,
|
||||
NODE_PT_tools_grease_pencil_draw,
|
||||
NODE_PT_tools_grease_pencil_edit,
|
||||
NODE_PT_tools_grease_pencil_sculpt,
|
||||
NODE_PT_tools_grease_pencil_brush,
|
||||
NODE_PT_tools_grease_pencil_brushcurves,
|
||||
)
|
||||
|
||||
|
||||
|
@ -22,7 +22,6 @@ from bpy.types import Header, Menu, Panel
|
||||
from rna_prop_ui import PropertyPanel
|
||||
from .properties_grease_pencil_common import (
|
||||
GreasePencilDataPanel,
|
||||
GreasePencilPaletteColorPanel,
|
||||
GreasePencilToolsPanel,
|
||||
)
|
||||
from bpy.app.translations import pgettext_iface as iface_
|
||||
@ -1281,14 +1280,6 @@ class SEQUENCER_PT_grease_pencil(GreasePencilDataPanel, SequencerButtonsPanel_Ou
|
||||
# But, it should only show up when there are images in the preview region
|
||||
|
||||
|
||||
class SEQUENCER_PT_grease_pencil_palettecolor(GreasePencilPaletteColorPanel, SequencerButtonsPanel_Output, Panel):
|
||||
bl_space_type = 'SEQUENCE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
|
||||
# NOTE: this is just a wrapper around the generic GP Panel
|
||||
# But, it should only show up when there are images in the preview region
|
||||
|
||||
|
||||
class SEQUENCER_PT_grease_pencil_tools(GreasePencilToolsPanel, SequencerButtonsPanel_Output, Panel):
|
||||
bl_space_type = 'SEQUENCE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
@ -1333,7 +1324,6 @@ classes = (
|
||||
SEQUENCER_PT_view_safe_areas,
|
||||
SEQUENCER_PT_modifiers,
|
||||
SEQUENCER_PT_grease_pencil,
|
||||
SEQUENCER_PT_grease_pencil_palettecolor,
|
||||
SEQUENCER_PT_grease_pencil_tools,
|
||||
SEQUENCER_PT_custom_props,
|
||||
)
|
||||
|
@ -24,6 +24,7 @@
|
||||
# For now keep this in a single file since it's an area that may change,
|
||||
# so avoid making changes all over the place.
|
||||
|
||||
import bpy
|
||||
from bpy.types import Panel
|
||||
|
||||
from .space_toolsystem_common import (
|
||||
@ -39,21 +40,77 @@ def generate_from_brushes_ex(
|
||||
brush_category_attr,
|
||||
brush_category_layout,
|
||||
):
|
||||
def draw_settings(context, layout, tool):
|
||||
_defs_gpencil_paint.draw_settings_common(context, layout, tool)
|
||||
|
||||
# Categories
|
||||
brush_categories = {}
|
||||
for brush in context.blend_data.brushes:
|
||||
if getattr(brush, brush_test_attr):
|
||||
category = getattr(brush, brush_category_attr)
|
||||
name = brush.name
|
||||
brush_categories.setdefault(category, []).append(
|
||||
ToolDef.from_dict(
|
||||
dict(
|
||||
text=name,
|
||||
icon=icon_prefix + category.lower(),
|
||||
data_block=name,
|
||||
if context.mode != 'GPENCIL_PAINT':
|
||||
for brush in context.blend_data.brushes:
|
||||
if getattr(brush, brush_test_attr) and brush.gpencil_settings is None:
|
||||
category = getattr(brush, brush_category_attr)
|
||||
name = brush.name
|
||||
brush_categories.setdefault(category, []).append(
|
||||
ToolDef.from_dict(
|
||||
dict(
|
||||
text=name,
|
||||
icon=icon_prefix + category.lower(),
|
||||
data_block=name,
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
else:
|
||||
for brush_type in brush_category_layout:
|
||||
for brush in context.blend_data.brushes:
|
||||
if getattr(brush, brush_test_attr) and brush.gpencil_settings.gp_icon == brush_type[0]:
|
||||
category = brush_type[0]
|
||||
name = brush.name
|
||||
|
||||
# rename default brushes for tool bar
|
||||
if name.startswith("Draw "):
|
||||
text = name.replace("Draw ", "")
|
||||
elif name.startswith("Eraser "):
|
||||
text = name.replace("Eraser ", "")
|
||||
elif name.startswith("Fill "):
|
||||
text = name.replace(" Area", "")
|
||||
else:
|
||||
text = name
|
||||
|
||||
# define icon
|
||||
gp_icon = brush.gpencil_settings.gp_icon
|
||||
if gp_icon == 'PENCIL':
|
||||
icon_name = 'draw_pencil'
|
||||
elif gp_icon == 'PEN':
|
||||
icon_name = 'draw_pen'
|
||||
elif gp_icon == 'INK':
|
||||
icon_name = 'draw_ink'
|
||||
elif gp_icon == 'INKNOISE':
|
||||
icon_name = 'draw_noise'
|
||||
elif gp_icon == 'BLOCK':
|
||||
icon_name = 'draw_block'
|
||||
elif gp_icon == 'MARKER':
|
||||
icon_name = 'draw_marker'
|
||||
elif gp_icon == 'FILL':
|
||||
icon_name = 'draw_fill'
|
||||
elif gp_icon == 'SOFT':
|
||||
icon_name = 'draw.eraser_soft'
|
||||
elif gp_icon == 'HARD':
|
||||
icon_name = 'draw.eraser_hard'
|
||||
elif gp_icon == 'STROKE':
|
||||
icon_name = 'draw.eraser_stroke'
|
||||
|
||||
brush_categories.setdefault(category, []).append(
|
||||
ToolDef.from_dict(
|
||||
dict(
|
||||
text=text,
|
||||
icon=icon_prefix + icon_name,
|
||||
data_block=name,
|
||||
widget=None,
|
||||
operator="gpencil.draw",
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def tools_from_brush_group(groups):
|
||||
assert(type(groups) is tuple)
|
||||
@ -61,6 +118,7 @@ def generate_from_brushes_ex(
|
||||
tool_defs = tuple(brush_categories.pop(groups[0], ()))
|
||||
else:
|
||||
tool_defs = tuple(item for g in groups for item in brush_categories.pop(g, ()))
|
||||
|
||||
if len(tool_defs) > 1:
|
||||
return (tool_defs,)
|
||||
else:
|
||||
@ -125,6 +183,112 @@ class _defs_view3d_generic:
|
||||
)
|
||||
|
||||
|
||||
class _defs_annotate:
|
||||
@classmethod
|
||||
def draw_settings_common(cls, context, layout, tool):
|
||||
user_prefs = context.user_preferences
|
||||
ts = context.tool_settings
|
||||
|
||||
# XXX: These context checks are needed for layer-dependent settings,
|
||||
# but this breaks for using topbar for 2D editor active tools, etc.
|
||||
if type(context.gpencil_data_owner) is bpy.types.Object:
|
||||
gpd = context.scene.grease_pencil
|
||||
else:
|
||||
gpd = context.gpencil_data
|
||||
|
||||
gpl = gpd.layers.active if gpd else None
|
||||
|
||||
if gpd and gpl:
|
||||
layout.prop(gpd.layers, "active_note", text="")
|
||||
layout.prop(gpl, "thickness", text="Thickness")
|
||||
else:
|
||||
layout.prop(user_prefs.edit, "grease_pencil_default_color", text="Color")
|
||||
layout.prop(ts, "annotation_thickness", text="Thickness")
|
||||
|
||||
# For 3D view, show the stroke placement settings
|
||||
# XXX: How to tell what editor the active tool comes from?
|
||||
is_3d_view = True
|
||||
if is_3d_view:
|
||||
layout.separator()
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(ts, "annotation_stroke_placement_view3d", text="Orientation")
|
||||
if ts.gpencil_stroke_placement_view3d == 'CURSOR':
|
||||
row.prop(ts.gpencil_sculpt, "lockaxis")
|
||||
elif ts.gpencil_stroke_placement_view3d in {'SURFACE', 'STROKE'}:
|
||||
row.prop(ts, "use_gpencil_stroke_endpoints")
|
||||
|
||||
@ToolDef.from_fn
|
||||
def scribble():
|
||||
def draw_settings(context, layout, tool):
|
||||
_defs_annotate.draw_settings_common(context, layout, tool)
|
||||
|
||||
return dict(
|
||||
text="Annotate",
|
||||
icon="ops.gpencil.draw",
|
||||
cursor='PAINT_BRUSH',
|
||||
keymap=(
|
||||
("gpencil.annotate",
|
||||
dict(mode='DRAW', wait_for_input=False),
|
||||
dict(type='EVT_TWEAK_A', value='ANY')),
|
||||
),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def line():
|
||||
def draw_settings(context, layout, tool):
|
||||
_defs_annotate.draw_settings_common(context, layout, tool)
|
||||
|
||||
return dict(
|
||||
text="Draw Line",
|
||||
icon="ops.gpencil.draw.line",
|
||||
cursor='CROSSHAIR',
|
||||
keymap=(
|
||||
("gpencil.annotate",
|
||||
dict(mode='DRAW_STRAIGHT', wait_for_input=False),
|
||||
dict(type='EVT_TWEAK_A', value='ANY')),
|
||||
),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def poly():
|
||||
def draw_settings(context, layout, tool):
|
||||
_defs_annotate.draw_settings_common(context, layout, tool)
|
||||
|
||||
return dict(
|
||||
text="Draw Polygon",
|
||||
icon="ops.gpencil.draw.poly",
|
||||
cursor='CROSSHAIR',
|
||||
keymap=(
|
||||
("gpencil.annotate",
|
||||
dict(mode='DRAW_POLY', wait_for_input=False),
|
||||
dict(type='ACTIONMOUSE', value='PRESS')),
|
||||
),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def eraser():
|
||||
def draw_settings(context, layout, tool):
|
||||
# TODO: Move this setting to toolsettings
|
||||
user_prefs = context.user_preferences
|
||||
layout.prop(user_prefs.edit, "grease_pencil_eraser_radius", text="Radius")
|
||||
|
||||
return dict(
|
||||
text="Eraser",
|
||||
icon="ops.gpencil.draw.eraser",
|
||||
cursor='CROSSHAIR', # XXX: Always show brush circle when enabled
|
||||
keymap=(
|
||||
("gpencil.annotate",
|
||||
dict(mode='ERASER', wait_for_input=False),
|
||||
dict(type='ACTIONMOUSE', value='PRESS')),
|
||||
),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
|
||||
class _defs_transform:
|
||||
|
||||
@ToolDef.from_fn
|
||||
@ -865,6 +1029,331 @@ class _defs_uv_select:
|
||||
),
|
||||
)
|
||||
|
||||
class _defs_gpencil_paint:
|
||||
@classmethod
|
||||
def draw_color_selector(cls, context, layout):
|
||||
brush = context.active_gpencil_brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
ts = context.tool_settings
|
||||
row = layout.row(align=True)
|
||||
row.prop(ts, "use_gpencil_thumbnail_list", text="", icon="IMGDISPLAY")
|
||||
if ts.use_gpencil_thumbnail_list is False:
|
||||
row.template_ID(gp_settings, "material", live_icon=True)
|
||||
else:
|
||||
row.template_greasepencil_color(gp_settings, "material", rows=3, cols=8, scale=0.8)
|
||||
|
||||
@classmethod
|
||||
def draw_settings_common(cls, context, layout, tool):
|
||||
ob = context.active_object
|
||||
if ob and ob.mode == 'GPENCIL_PAINT':
|
||||
brush = context.active_gpencil_brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
tool_settings= context.tool_settings
|
||||
|
||||
if gp_settings.gpencil_brush_type == 'ERASE':
|
||||
row = layout.row()
|
||||
row.prop(brush, "size", text="Radius")
|
||||
elif gp_settings.gpencil_brush_type == 'FILL':
|
||||
row = layout.row()
|
||||
row.prop(gp_settings, "gpencil_fill_leak", text="Leak Size")
|
||||
row.prop(brush, "size", text="Thickness")
|
||||
row.prop(gp_settings, "gpencil_fill_simplyfy_level", text="Simplify")
|
||||
|
||||
_defs_gpencil_paint.draw_color_selector(context, layout)
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "gpencil_fill_draw_mode", text="")
|
||||
row.prop(gp_settings, "gpencil_fill_show_boundary", text="", icon='GRID')
|
||||
|
||||
else: # bgpsettings.gpencil_brush_type == 'DRAW':
|
||||
row = layout.row(align=True)
|
||||
row.prop(brush, "size", text="Radius")
|
||||
row.prop(gp_settings, "use_pressure", text="", icon='STYLUS_PRESSURE')
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "pen_strength", slider=True)
|
||||
row.prop(gp_settings, "use_strength_pressure", text="", icon='STYLUS_PRESSURE')
|
||||
|
||||
_defs_gpencil_paint.draw_color_selector(context, layout)
|
||||
|
||||
|
||||
@staticmethod
|
||||
def generate_from_brushes(context):
|
||||
return generate_from_brushes_ex(
|
||||
context,
|
||||
icon_prefix="brush.gpencil.",
|
||||
brush_test_attr="use_paint_grease_pencil",
|
||||
brush_category_attr="grease_pencil_tool",
|
||||
brush_category_layout=(
|
||||
('PENCIL',),
|
||||
('PEN',),
|
||||
('INK',),
|
||||
('INKNOISE',),
|
||||
('BLOCK',),
|
||||
('MARKER',),
|
||||
('FILL',),
|
||||
('SOFT',),
|
||||
('HARD',),
|
||||
('STROKE',),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class _defs_gpencil_edit:
|
||||
@ToolDef.from_fn
|
||||
def bend():
|
||||
return dict(
|
||||
text="Bend",
|
||||
icon="ops.gpencil.edit_bend",
|
||||
widget=None,
|
||||
keymap=(
|
||||
("transform.bend",
|
||||
dict(),
|
||||
dict(type='EVT_TWEAK_A', value='ANY')),
|
||||
),
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def mirror():
|
||||
return dict(
|
||||
text="Mirror",
|
||||
icon="ops.gpencil.edit_mirror",
|
||||
widget=None,
|
||||
keymap=(
|
||||
("transform.mirror",
|
||||
dict(),
|
||||
dict(type='EVT_TWEAK_A', value='ANY')),
|
||||
),
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def shear():
|
||||
return dict(
|
||||
text="Shear",
|
||||
icon="ops.gpencil.edit_shear",
|
||||
widget=None,
|
||||
keymap=(
|
||||
("transform.shear",
|
||||
dict(),
|
||||
dict(type='EVT_TWEAK_A', value='ANY')),
|
||||
),
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def tosphere():
|
||||
return dict(
|
||||
text="To Sphere",
|
||||
icon="ops.gpencil.edit_to_sphere",
|
||||
widget=None,
|
||||
keymap=(
|
||||
("transform.tosphere",
|
||||
dict(),
|
||||
dict(type='EVT_TWEAK_A', value='ANY')),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class _defs_gpencil_sculpt:
|
||||
@classmethod
|
||||
def draw_settings_common(cls, context, layout, tool):
|
||||
ob = context.active_object
|
||||
if ob and ob.mode == 'GPENCIL_SCULPT':
|
||||
ts = context.tool_settings
|
||||
settings = ts.gpencil_sculpt
|
||||
brush = settings.brush
|
||||
|
||||
layout.prop(brush, "size", slider=True)
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(brush, "strength", slider=True)
|
||||
row.prop(brush, "use_pressure_strength", text="")
|
||||
row.separator()
|
||||
row.prop(ts.gpencil_sculpt, "use_select_mask", text="")
|
||||
|
||||
@ToolDef.from_fn
|
||||
def smooth():
|
||||
def draw_settings(context, layout, tool):
|
||||
_defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
|
||||
|
||||
return dict(
|
||||
text="Smooth",
|
||||
icon="ops.gpencil.sculpt_smooth",
|
||||
widget=None,
|
||||
keymap=(
|
||||
("gpencil.brush_paint",
|
||||
dict(mode='SMOOTH', wait_for_input=False),
|
||||
dict(type='EVT_TWEAK_A', value='ANY')),
|
||||
),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def thickness():
|
||||
def draw_settings(context, layout, tool):
|
||||
_defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
|
||||
|
||||
return dict(
|
||||
text="Thickness",
|
||||
icon="ops.gpencil.sculpt_thickness",
|
||||
widget=None,
|
||||
keymap=(
|
||||
("gpencil.brush_paint",
|
||||
dict(mode='THICKNESS', wait_for_input=False),
|
||||
dict(type='EVT_TWEAK_A', value='ANY')),
|
||||
),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def strength():
|
||||
def draw_settings(context, layout, tool):
|
||||
_defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
|
||||
|
||||
return dict(
|
||||
text="Strength",
|
||||
icon="ops.gpencil.sculpt_strength",
|
||||
widget=None,
|
||||
keymap=(
|
||||
("gpencil.brush_paint",
|
||||
dict(mode='STRENGTH', wait_for_input=False),
|
||||
dict(type='EVT_TWEAK_A', value='ANY')),
|
||||
),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def grab():
|
||||
def draw_settings(context, layout, tool):
|
||||
_defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
|
||||
|
||||
return dict(
|
||||
text="Grab",
|
||||
icon="ops.gpencil.sculpt_grab",
|
||||
widget=None,
|
||||
keymap=(
|
||||
("gpencil.brush_paint",
|
||||
dict(mode='GRAB', wait_for_input=False),
|
||||
dict(type='EVT_TWEAK_A', value='ANY')),
|
||||
),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def push():
|
||||
def draw_settings(context, layout, tool):
|
||||
_defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
|
||||
|
||||
return dict(
|
||||
text="Push",
|
||||
icon="ops.gpencil.sculpt_push",
|
||||
widget=None,
|
||||
keymap=(
|
||||
("gpencil.brush_paint",
|
||||
dict(mode='PUSH', wait_for_input=False),
|
||||
dict(type='EVT_TWEAK_A', value='ANY')),
|
||||
),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def twist():
|
||||
def draw_settings(context, layout, tool):
|
||||
_defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
|
||||
|
||||
return dict(
|
||||
text="Twist",
|
||||
icon="ops.gpencil.sculpt_twist",
|
||||
widget=None,
|
||||
keymap=(
|
||||
("gpencil.brush_paint",
|
||||
dict(mode='TWIST', wait_for_input=False),
|
||||
dict(type='EVT_TWEAK_A', value='ANY')),
|
||||
),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def pinch():
|
||||
def draw_settings(context, layout, tool):
|
||||
_defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
|
||||
|
||||
return dict(
|
||||
text="Pinch",
|
||||
icon="ops.gpencil.sculpt_pinch",
|
||||
widget=None,
|
||||
keymap=(
|
||||
("gpencil.brush_paint",
|
||||
dict(mode='PINCH', wait_for_input=False),
|
||||
dict(type='EVT_TWEAK_A', value='ANY')),
|
||||
),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def randomize():
|
||||
def draw_settings(context, layout, tool):
|
||||
_defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
|
||||
|
||||
return dict(
|
||||
text="Randomize",
|
||||
icon="ops.gpencil.sculpt_randomize",
|
||||
widget=None,
|
||||
keymap=(
|
||||
("gpencil.brush_paint",
|
||||
dict(mode='RANDOMIZE', wait_for_input=False),
|
||||
dict(type='EVT_TWEAK_A', value='ANY')),
|
||||
),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def clone():
|
||||
def draw_settings(context, layout, tool):
|
||||
_defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
|
||||
|
||||
return dict(
|
||||
text="Clone",
|
||||
icon="ops.gpencil.sculpt_clone",
|
||||
widget=None,
|
||||
keymap=(
|
||||
("gpencil.brush_paint",
|
||||
dict(mode='CLONE', wait_for_input=False),
|
||||
dict(type='EVT_TWEAK_A', value='ANY')),
|
||||
),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
|
||||
class _defs_gpencil_weight:
|
||||
@classmethod
|
||||
def draw_settings_common(cls, context, layout, tool):
|
||||
ob = context.active_object
|
||||
if ob and ob.mode == 'GPENCIL_WEIGHT':
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
brush = settings.brush
|
||||
|
||||
layout.prop(brush, "size", slider=True)
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(brush, "strength", slider=True)
|
||||
row.prop(brush, "use_pressure_strength", text="")
|
||||
|
||||
@ToolDef.from_fn
|
||||
def paint():
|
||||
def draw_settings(context, layout, tool):
|
||||
_defs_gpencil_weight.draw_settings_common(context, layout, tool)
|
||||
|
||||
return dict(
|
||||
text="Draw",
|
||||
icon="ops.gpencil.sculpt_weight",
|
||||
widget=None,
|
||||
keymap=(
|
||||
("gpencil.brush_paint",
|
||||
dict(mode='WEIGHT', wait_for_input=False),
|
||||
dict(type='EVT_TWEAK_A', value='ANY')),
|
||||
),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
|
||||
class IMAGE_PT_tools_active(ToolSelectPanelHelper, Panel):
|
||||
bl_space_type = 'IMAGE_EDITOR'
|
||||
@ -951,8 +1440,6 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
|
||||
_defs_transform.scale,
|
||||
_defs_transform.scale_cage,
|
||||
),
|
||||
None,
|
||||
_defs_view3d_generic.ruler,
|
||||
)
|
||||
|
||||
_tools_select = (
|
||||
@ -963,6 +1450,16 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
|
||||
),
|
||||
)
|
||||
|
||||
_tools_annotate = (
|
||||
(
|
||||
_defs_annotate.scribble,
|
||||
_defs_annotate.line,
|
||||
_defs_annotate.poly,
|
||||
_defs_annotate.eraser,
|
||||
),
|
||||
_defs_view3d_generic.ruler,
|
||||
)
|
||||
|
||||
_tools = {
|
||||
None: [
|
||||
_defs_view3d_generic.cursor,
|
||||
@ -972,21 +1469,27 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
|
||||
*_tools_select,
|
||||
None,
|
||||
*_tools_transform,
|
||||
None,
|
||||
*_tools_annotate,
|
||||
],
|
||||
'POSE': [
|
||||
*_tools_select,
|
||||
*_tools_transform,
|
||||
None,
|
||||
*_tools_annotate,
|
||||
None,
|
||||
(
|
||||
_defs_pose.breakdown,
|
||||
_defs_pose.push,
|
||||
_defs_pose.relax,
|
||||
)
|
||||
),
|
||||
],
|
||||
'EDIT_ARMATURE': [
|
||||
*_tools_select,
|
||||
None,
|
||||
*_tools_transform,
|
||||
None,
|
||||
*_tools_annotate,
|
||||
_defs_edit_armature.roll,
|
||||
(
|
||||
_defs_edit_armature.bone_size,
|
||||
@ -996,13 +1499,15 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
|
||||
(
|
||||
_defs_edit_armature.extrude,
|
||||
_defs_edit_armature.extrude_cursor,
|
||||
)
|
||||
),
|
||||
],
|
||||
'EDIT_MESH': [
|
||||
*_tools_select,
|
||||
None,
|
||||
*_tools_transform,
|
||||
None,
|
||||
*_tools_annotate,
|
||||
None,
|
||||
_defs_edit_mesh.cube_add,
|
||||
None,
|
||||
(
|
||||
@ -1047,6 +1552,8 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
|
||||
None,
|
||||
*_tools_transform,
|
||||
None,
|
||||
*_tools_annotate,
|
||||
None,
|
||||
_defs_edit_curve.draw,
|
||||
_defs_edit_curve.extrude_cursor,
|
||||
],
|
||||
@ -1075,6 +1582,33 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
|
||||
None,
|
||||
_defs_weight_paint.gradient,
|
||||
],
|
||||
'GPENCIL_PAINT': [
|
||||
_defs_gpencil_paint.generate_from_brushes,
|
||||
],
|
||||
'GPENCIL_EDIT': [
|
||||
*_tools_select,
|
||||
None,
|
||||
*_tools_transform,
|
||||
None,
|
||||
_defs_gpencil_edit.bend,
|
||||
_defs_gpencil_edit.mirror,
|
||||
_defs_gpencil_edit.shear,
|
||||
_defs_gpencil_edit.tosphere,
|
||||
],
|
||||
'GPENCIL_SCULPT': [
|
||||
_defs_gpencil_sculpt.smooth,
|
||||
_defs_gpencil_sculpt.thickness,
|
||||
_defs_gpencil_sculpt.strength,
|
||||
_defs_gpencil_sculpt.grab,
|
||||
_defs_gpencil_sculpt.push,
|
||||
_defs_gpencil_sculpt.twist,
|
||||
_defs_gpencil_sculpt.pinch,
|
||||
_defs_gpencil_sculpt.randomize,
|
||||
_defs_gpencil_sculpt.clone,
|
||||
],
|
||||
'GPENCIL_WEIGHT': [
|
||||
_defs_gpencil_weight.paint,
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
|
@ -128,6 +128,8 @@ class TOPBAR_HT_lower_bar(Header):
|
||||
pass
|
||||
elif mode == 'PARTICLE':
|
||||
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".paint_common", category="")
|
||||
elif mode == 'GPENCIL_PAINT':
|
||||
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".greasepencil_paint", category="")
|
||||
|
||||
def draw_center(self, context):
|
||||
pass
|
||||
@ -165,6 +167,15 @@ class TOPBAR_HT_lower_bar(Header):
|
||||
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".particlemode", category="")
|
||||
elif mode == 'OBJECT':
|
||||
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".objectmode", category="")
|
||||
elif mode == 'GPENCIL_PAINT':
|
||||
layout.prop(context.tool_settings, "gpencil_stroke_placement_view3d", text='')
|
||||
if context.tool_settings.gpencil_stroke_placement_view3d in ('ORIGIN', 'CURSOR'):
|
||||
layout.prop(context.tool_settings.gpencil_sculpt, "lockaxis", text='')
|
||||
layout.prop(context.tool_settings, "use_gpencil_draw_onback", text="", icon='ORTHO')
|
||||
layout.prop(context.tool_settings, "use_gpencil_additive_drawing", text="", icon='FREEZE')
|
||||
|
||||
elif mode == 'GPENCIL_SCULPT':
|
||||
layout.prop(context.tool_settings.gpencil_sculpt, "lockaxis", text='')
|
||||
|
||||
|
||||
class _draw_left_context_mode:
|
||||
|
@ -361,14 +361,16 @@ class USERPREF_PT_edit(Panel):
|
||||
row.separator()
|
||||
|
||||
col = row.column()
|
||||
col.label(text="Grease Pencil:")
|
||||
col.label(text="Annotations:")
|
||||
sub = col.row()
|
||||
sub.prop(edit, "grease_pencil_default_color", text="Default Color")
|
||||
col.prop(edit, "grease_pencil_eraser_radius", text="Eraser Radius")
|
||||
col.separator()
|
||||
col.label(text="Grease Pencil/Annotations:")
|
||||
col.separator()
|
||||
col.prop(edit, "grease_pencil_manhattan_distance", text="Manhattan Distance")
|
||||
col.prop(edit, "grease_pencil_euclidean_distance", text="Euclidean Distance")
|
||||
col.separator()
|
||||
col.prop(edit, "grease_pencil_default_color", text="Default Color")
|
||||
col.separator()
|
||||
col.prop(edit, "use_grease_pencil_simplify_stroke", text="Simplify Stroke")
|
||||
col.separator()
|
||||
col.separator()
|
||||
@ -527,7 +529,10 @@ class USERPREF_PT_system(Panel):
|
||||
col.prop(system, "gpu_viewport_quality")
|
||||
|
||||
col.separator()
|
||||
col.label(text="Grease Pencil Options:")
|
||||
col.prop(system, "gpencil_multi_sample", text="")
|
||||
|
||||
col.separator()
|
||||
col.label(text="Text Draw Options:")
|
||||
col.prop(system, "use_text_antialiasing")
|
||||
if system.use_text_antialiasing:
|
||||
|
@ -19,11 +19,8 @@
|
||||
# <pep8 compliant>
|
||||
import bpy
|
||||
from bpy.types import Header, Menu, Panel
|
||||
from .properties_grease_pencil_common import (
|
||||
GreasePencilDataPanel,
|
||||
GreasePencilPaletteColorPanel,
|
||||
)
|
||||
from .properties_paint_common import UnifiedPaintPanel
|
||||
from .properties_grease_pencil_common import GreasePencilDataPanel
|
||||
from bpy.app.translations import contexts as i18n_contexts
|
||||
|
||||
|
||||
@ -80,18 +77,40 @@ class VIEW3D_HT_header(Header):
|
||||
row.operator("pose.paste", text="", icon='PASTEDOWN').flipped = False
|
||||
row.operator("pose.paste", text="", icon='PASTEFLIPDOWN').flipped = True
|
||||
|
||||
# GPencil
|
||||
if context.gpencil_data and context.gpencil_data.use_stroke_edit_mode:
|
||||
row = layout.row(align=True)
|
||||
row.operator("gpencil.copy", text="", icon='COPYDOWN')
|
||||
row.operator("gpencil.paste", text="", icon='PASTEDOWN')
|
||||
# Grease Pencil
|
||||
if obj and obj.type == 'GPENCIL' and context.gpencil_data:
|
||||
gpd = context.gpencil_data
|
||||
|
||||
# XXX: icon
|
||||
layout.prop(context.gpencil_data, "use_onion_skinning", text="Onion Skins", icon='PARTICLE_PATH')
|
||||
if gpd.is_stroke_paint_mode:
|
||||
row = layout.row(align=True)
|
||||
row.popover(
|
||||
panel="VIEW3D_PT_tools_grease_pencil_shapes",
|
||||
text="Shapes"
|
||||
)
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(tool_settings.gpencil_sculpt, "use_select_mask")
|
||||
row.prop(tool_settings.gpencil_sculpt, "selection_alpha", slider=True)
|
||||
if gpd.use_stroke_edit_mode or gpd.is_stroke_sculpt_mode or gpd.is_stroke_weight_mode:
|
||||
row = layout.row(align=True)
|
||||
row.prop(gpd, "use_multiedit", text="", icon="FORCE_HARMONIC")
|
||||
|
||||
sub = row.row(align=True)
|
||||
sub.active = gpd.use_multiedit
|
||||
sub.popover(
|
||||
panel="VIEW3D_PT_gpencil_multi_frame",
|
||||
text="Multiframe"
|
||||
)
|
||||
|
||||
if gpd.use_stroke_edit_mode:
|
||||
row = layout.row(align=True)
|
||||
row.operator("gpencil.copy", text="", icon='COPYDOWN')
|
||||
row.operator("gpencil.paste", text="", icon='PASTEDOWN')
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(tool_settings.gpencil_sculpt, "use_select_mask", text="")
|
||||
|
||||
row.popover(
|
||||
panel="VIEW3D_PT_tools_grease_pencil_interpolate",
|
||||
text="Interpolate"
|
||||
)
|
||||
|
||||
VIEW3D_MT_editor_menus.draw_collapsible(context, layout)
|
||||
|
||||
@ -101,7 +120,7 @@ class VIEW3D_HT_header(Header):
|
||||
scene = context.scene
|
||||
|
||||
# Orientation
|
||||
if object_mode in {'OBJECT', 'EDIT', 'POSE'}:
|
||||
if object_mode in {'OBJECT', 'EDIT', 'POSE', 'GPENCIL_EDIT'}:
|
||||
orientation = scene.transform_orientation
|
||||
current_orientation = scene.current_orientation
|
||||
|
||||
@ -126,7 +145,8 @@ class VIEW3D_HT_header(Header):
|
||||
if obj is None:
|
||||
show_snap = True
|
||||
else:
|
||||
if object_mode not in {'SCULPT', 'VERTEX_PAINT', 'WEIGHT_PAINT', 'TEXTURE_PAINT'}:
|
||||
if object_mode not in {'SCULPT', 'VERTEX_PAINT', 'WEIGHT_PAINT', 'TEXTURE_PAINT',
|
||||
'GPENCIL_PAINT', 'GPENCIL_SCULPT', 'GPENCIL_WEIGHT'}:
|
||||
show_snap = True
|
||||
else:
|
||||
|
||||
@ -160,13 +180,15 @@ class VIEW3D_HT_header(Header):
|
||||
|
||||
# Proportional editing
|
||||
if obj:
|
||||
if context.gpencil_data and context.gpencil_data.use_stroke_edit_mode:
|
||||
row = layout.row(align=True)
|
||||
row.prop(tool_settings, "proportional_edit", icon_only=True)
|
||||
gpd = context.gpencil_data
|
||||
if gpd is not None:
|
||||
if gpd.use_stroke_edit_mode or gpd.is_stroke_sculpt_mode:
|
||||
row = layout.row(align=True)
|
||||
row.prop(tool_settings, "proportional_edit", icon_only=True)
|
||||
|
||||
sub = row.row(align=True)
|
||||
sub.active = tool_settings.proportional_edit != 'DISABLED'
|
||||
sub.prop(tool_settings, "proportional_edit_falloff", icon_only=True)
|
||||
sub = row.row(align=True)
|
||||
sub.active = tool_settings.proportional_edit != 'DISABLED'
|
||||
sub.prop(tool_settings, "proportional_edit_falloff", icon_only=True)
|
||||
|
||||
elif object_mode in {'EDIT', 'PARTICLE_EDIT'}:
|
||||
row = layout.row(align=True)
|
||||
@ -190,7 +212,7 @@ class VIEW3D_HT_header(Header):
|
||||
sub.prop(tool_settings, "proportional_edit_falloff", icon_only=True)
|
||||
|
||||
# Pivot
|
||||
if object_mode in {'OBJECT', 'EDIT', 'POSE'}:
|
||||
if object_mode in {'OBJECT', 'EDIT', 'POSE', 'GPENCIL_EDIT', 'GPENCIL_SCULPT'}:
|
||||
pivot_point = tool_settings.transform_pivot_point
|
||||
act_pivot_point = bpy.types.ToolSettings.bl_rna.properties["transform_pivot_point"].enum_items[pivot_point]
|
||||
row = layout.row(align=True)
|
||||
@ -234,13 +256,14 @@ class VIEW3D_MT_editor_menus(Menu):
|
||||
obj = context.active_object
|
||||
mode_string = context.mode
|
||||
edit_object = context.edit_object
|
||||
gp_edit = context.gpencil_data and context.gpencil_data.use_stroke_edit_mode
|
||||
gp_edit = obj and obj.mode in {'GPENCIL_EDIT', 'GPENCIL_PAINT', 'GPENCIL_SCULPT', 'GPENCIL_WEIGHT'}
|
||||
|
||||
layout.menu("VIEW3D_MT_view")
|
||||
|
||||
# Select Menu
|
||||
if gp_edit:
|
||||
layout.menu("VIEW3D_MT_select_gpencil")
|
||||
if mode_string not in {'GPENCIL_PAINT', 'GPENCIL_WEIGHT'}:
|
||||
layout.menu("VIEW3D_MT_select_gpencil")
|
||||
elif mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX', 'PAINT_TEXTURE'}:
|
||||
mesh = obj.data
|
||||
if mesh.use_paint_mask:
|
||||
@ -266,7 +289,15 @@ class VIEW3D_MT_editor_menus(Menu):
|
||||
layout.menu("INFO_MT_edit_armature_add", text="Add")
|
||||
|
||||
if gp_edit:
|
||||
layout.menu("VIEW3D_MT_edit_gpencil")
|
||||
if obj and obj.mode == 'GPENCIL_PAINT':
|
||||
layout.menu("VIEW3D_MT_paint_gpencil")
|
||||
elif obj and obj.mode == 'GPENCIL_EDIT':
|
||||
layout.menu("VIEW3D_MT_edit_gpencil")
|
||||
elif obj and obj.mode == 'GPENCIL_SCULPT':
|
||||
layout.menu("VIEW3D_MT_sculpt_gpencil")
|
||||
elif obj and obj.mode == 'GPENCIL_WEIGHT':
|
||||
layout.menu("VIEW3D_MT_weight_gpencil")
|
||||
|
||||
elif edit_object:
|
||||
layout.menu("VIEW3D_MT_edit_%s" % edit_object.type.lower())
|
||||
|
||||
@ -1194,6 +1225,7 @@ class VIEW3D_MT_select_gpencil(Menu):
|
||||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.select_linked", text="Linked")
|
||||
layout.operator("gpencil.select_alternate")
|
||||
layout.operator_menu_enum("gpencil.select_grouped", "type", text="Grouped")
|
||||
|
||||
layout.separator()
|
||||
@ -1454,6 +1486,7 @@ class INFO_MT_add(Menu):
|
||||
layout.menu("INFO_MT_armature_add", icon='OUTLINER_OB_ARMATURE')
|
||||
layout.operator("object.add", text="Lattice", icon='OUTLINER_OB_LATTICE').type = 'LATTICE'
|
||||
layout.operator_menu_enum("object.empty_add", "type", text="Empty", icon='OUTLINER_OB_EMPTY')
|
||||
layout.operator_menu_enum("object.gpencil_add", "type", text="Grease Pencil", icon='OUTLINER_OB_GREASEPENCIL')
|
||||
layout.separator()
|
||||
|
||||
layout.operator("object.speaker_add", text="Speaker", icon='OUTLINER_OB_SPEAKER')
|
||||
@ -3110,12 +3143,17 @@ class VIEW3D_MT_edit_gpencil_delete(Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.dissolve")
|
||||
layout.operator_enum("gpencil.dissolve", "type")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.active_frames_delete_all")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.frame_clean_fill", text="Clean Boundary Strokes").mode = 'ACTIVE'
|
||||
layout.operator("gpencil.frame_clean_fill", text="Clean Boundary Strokes all Frames").mode = 'ALL'
|
||||
|
||||
|
||||
# Edit Curve
|
||||
# draw_curve is used by VIEW3D_MT_edit_curve and VIEW3D_MT_edit_surface
|
||||
@ -3476,11 +3514,34 @@ class VIEW3D_MT_edit_armature_delete(Menu):
|
||||
layout.operator("armature.dissolve", text="Dissolve")
|
||||
|
||||
|
||||
# ********** GPencil Stroke Edit menu **********
|
||||
# ********** Grease Pencil Stroke menus **********
|
||||
class VIEW3D_MT_gpencil_simplify(Menu):
|
||||
bl_label = "Simplify"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.operator("gpencil.stroke_simplify_fixed", text="Fixed")
|
||||
layout.operator("gpencil.stroke_simplify", text="Adaptative")
|
||||
|
||||
|
||||
class VIEW3D_MT_paint_gpencil(Menu):
|
||||
bl_label = "Strokes"
|
||||
|
||||
def draw(self, context):
|
||||
|
||||
layout = self.layout
|
||||
|
||||
layout.menu("VIEW3D_MT_gpencil_animation")
|
||||
layout.menu("VIEW3D_MT_edit_gpencil_interpolate")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.delete", text="Delete Frame").type = 'FRAME'
|
||||
layout.operator("gpencil.active_frames_delete_all")
|
||||
|
||||
|
||||
class VIEW3D_MT_edit_gpencil(Menu):
|
||||
bl_label = "GPencil"
|
||||
bl_label = "Strokes"
|
||||
|
||||
def draw(self, context):
|
||||
tool_settings = context.tool_settings
|
||||
@ -3488,44 +3549,41 @@ class VIEW3D_MT_edit_gpencil(Menu):
|
||||
layout = self.layout
|
||||
|
||||
layout.menu("VIEW3D_MT_edit_gpencil_transform")
|
||||
layout.operator("transform.mirror", text="Mirror")
|
||||
|
||||
layout.separator()
|
||||
layout.menu("GPENCIL_MT_snap")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.brush_paint", text="Sculpt Strokes").wait_for_input = True
|
||||
layout.prop_menu_enum(tool_settings.gpencil_sculpt, "tool", text="Sculpt Brush")
|
||||
layout.menu("VIEW3D_MT_gpencil_animation")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.menu("VIEW3D_MT_object_animation") # NOTE: provides keyingset access...
|
||||
layout.menu("VIEW3D_MT_edit_gpencil_interpolate")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.duplicate_move", text="Duplicate")
|
||||
layout.operator("gpencil.stroke_subdivide", text="Subdivide")
|
||||
layout.menu("VIEW3D_MT_gpencil_simplify")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator_menu_enum("gpencil.stroke_separate", "mode", text="Separate...")
|
||||
layout.operator("gpencil.stroke_split", text="Split")
|
||||
layout.operator_menu_enum("gpencil.stroke_join", "type", text="Join...")
|
||||
layout.operator("gpencil.stroke_flip", text="Flip Direction")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.copy", text="Copy")
|
||||
layout.operator("gpencil.paste", text="Paste")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.reveal")
|
||||
layout.operator("gpencil.hide", text="Show Active Layer Only").unselected = True
|
||||
layout.operator("gpencil.hide", text="Hide Active Layer").unselected = False
|
||||
layout.operator("gpencil.paste", text="Paste").type = 'COPY'
|
||||
layout.operator("gpencil.paste", text="Paste & Merge").type = 'MERGE'
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator_menu_enum("gpencil.move_to_layer", "layer", text="Move to Layer")
|
||||
layout.operator("gpencil.stroke_change_color", text="Move to Color")
|
||||
layout.operator("gpencil.stroke_change_color", text="Change Color")
|
||||
layout.operator_menu_enum("gpencil.stroke_arrange", "direction", text="Arrange Strokes...")
|
||||
|
||||
layout.separator()
|
||||
@ -3535,6 +3593,82 @@ class VIEW3D_MT_edit_gpencil(Menu):
|
||||
layout.separator()
|
||||
|
||||
layout.menu("VIEW3D_MT_edit_gpencil_delete")
|
||||
layout.operator("gpencil.stroke_cyclical_set", text="Toggle Cyclic").type = 'TOGGLE'
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator_menu_enum("gpencil.frame_clean_fill", text="Clean Boundary Strokes...", property="mode")
|
||||
|
||||
|
||||
class VIEW3D_MT_sculpt_gpencil(Menu):
|
||||
bl_label = "Strokes"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.menu("VIEW3D_MT_edit_gpencil_transform")
|
||||
|
||||
layout.separator()
|
||||
layout.menu("GPENCIL_MT_snap")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.duplicate_move", text="Duplicate")
|
||||
layout.operator("gpencil.stroke_subdivide", text="Subdivide")
|
||||
layout.menu("VIEW3D_MT_gpencil_simplify")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator_menu_enum("gpencil.stroke_separate", "mode", text="Separate...")
|
||||
layout.operator("gpencil.stroke_split", text="Split")
|
||||
layout.operator_menu_enum("gpencil.stroke_join", "type", text="Join...")
|
||||
layout.operator("gpencil.stroke_flip", text="Flip Direction")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.copy", text="Copy")
|
||||
layout.operator("gpencil.paste", text="Paste").type = 'COPY'
|
||||
layout.operator("gpencil.paste", text="Paste & Merge").type = 'MERGE'
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator_menu_enum("gpencil.move_to_layer", "layer", text="Move to Layer")
|
||||
layout.operator("gpencil.stroke_change_color", text="Change Color")
|
||||
layout.operator_menu_enum("gpencil.stroke_arrange", "direction", text="Arrange Strokes...")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator_menu_enum("gpencil.convert", "type", text="Convert to Geometry...")
|
||||
|
||||
|
||||
class VIEW3D_MT_weight_gpencil(Menu):
|
||||
bl_label = "Weights"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator("gpencil.vertex_group_invert", text="Invert")
|
||||
layout.operator("gpencil.vertex_group_smooth", text="Smooth")
|
||||
|
||||
|
||||
class VIEW3D_MT_gpencil_animation(Menu):
|
||||
bl_label = "Animation"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.active_object
|
||||
return ob and ob.type == 'GPENCIL' and ob.mode != 'OBJECT'
|
||||
|
||||
@staticmethod
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator("gpencil.blank_frame_add")
|
||||
layout.operator("gpencil.active_frames_delete_all", text="Delete Frame(s)")
|
||||
|
||||
layout.separator()
|
||||
layout.operator("gpencil.frame_duplicate", text="Duplicate Active Frame")
|
||||
layout.operator("gpencil.frame_duplicate", text="Duplicate All Layers").mode = 'ALL'
|
||||
|
||||
|
||||
class VIEW3D_MT_edit_gpencil_transform(Menu):
|
||||
@ -3595,20 +3729,6 @@ class VIEW3D_MT_view_pie(Menu):
|
||||
# ********** Panel **********
|
||||
|
||||
|
||||
class VIEW3D_PT_grease_pencil(GreasePencilDataPanel, Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'UI'
|
||||
|
||||
# NOTE: this is just a wrapper around the generic GP Panel
|
||||
|
||||
|
||||
class VIEW3D_PT_grease_pencil_palettecolor(GreasePencilPaletteColorPanel, Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'UI'
|
||||
|
||||
# NOTE: this is just a wrapper around the generic GP Panel
|
||||
|
||||
|
||||
class VIEW3D_PT_view3d_properties(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'UI'
|
||||
@ -3720,6 +3840,7 @@ class VIEW3D_PT_object_type_visibility(Panel):
|
||||
"armature",
|
||||
"lattice",
|
||||
"empty",
|
||||
"grease_pencil",
|
||||
"camera",
|
||||
"light",
|
||||
"light_probe",
|
||||
@ -4040,6 +4161,8 @@ class VIEW3D_PT_overlay_guides(Panel):
|
||||
if shading.type == 'MATERIAL':
|
||||
col.prop(overlay, "show_look_dev")
|
||||
|
||||
col.prop(overlay, "show_annotation", text="Annotations")
|
||||
|
||||
|
||||
class VIEW3D_PT_overlay_object(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
@ -4578,6 +4701,60 @@ class VIEW3D_PT_transform_orientations(Panel):
|
||||
row.operator("transform.delete_orientation", text="", icon='X', emboss=False)
|
||||
|
||||
|
||||
class VIEW3D_PT_overlay_gpencil_options(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'HEADER'
|
||||
bl_parent_id = 'VIEW3D_PT_overlay'
|
||||
bl_label = ""
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.object and context.object.type == 'GPENCIL'
|
||||
|
||||
def draw_header(self, context):
|
||||
layout = self.layout
|
||||
layout.label(text={
|
||||
'GPENCIL_PAINT': "Draw Grease Pencil",
|
||||
'GPENCIL_EDIT': "Edit Grease Pencil",
|
||||
'GPENCIL_SCULPT': "Sculpt Grease Pencil",
|
||||
'GPENCIL_WEIGHT': "Weight Grease Pencil",
|
||||
'OBJECT': "Grease Pencil",
|
||||
}[context.mode])
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
view = context.space_data
|
||||
overlay = view.overlay
|
||||
|
||||
layout.prop(overlay, "use_gpencil_onion_skin", text="Onion Skin")
|
||||
|
||||
col = layout.column()
|
||||
row = col.row()
|
||||
row.prop(overlay, "use_gpencil_paper", text="")
|
||||
sub = row.row()
|
||||
sub.active = overlay.use_gpencil_paper
|
||||
sub.prop(overlay, "gpencil_paper_opacity", text="Fade 3D Objects", slider=True)
|
||||
|
||||
col = layout.column()
|
||||
row = col.row()
|
||||
row.prop(overlay, "use_gpencil_grid", text="")
|
||||
sub = row.row()
|
||||
sub.active = overlay.use_gpencil_grid
|
||||
sub.prop(overlay, "gpencil_grid_opacity", text="Canvas Grid", slider=True)
|
||||
|
||||
if overlay.use_gpencil_grid:
|
||||
row = layout.row(align=True)
|
||||
row.prop(overlay, "gpencil_grid_scale")
|
||||
col = row.column()
|
||||
col.prop(overlay, "gpencil_grid_lines", text="Subdivisions")
|
||||
col.prop(overlay, "gpencil_grid_axis")
|
||||
|
||||
if context.object.mode in {'GPENCIL_EDIT', 'GPENCIL_SCULPT', 'GPENCIL_WEIGHT'}:
|
||||
layout.prop(overlay, "use_gpencil_edit_lines", text="Edit Lines")
|
||||
layout.prop(overlay, "use_gpencil_multiedit_line_only", text="Show Edit Lines only in multiframe")
|
||||
layout.prop(overlay, "vertex_opacity", text="Vertex Opacity", slider=True)
|
||||
|
||||
|
||||
class VIEW3D_PT_quad_view(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'UI'
|
||||
@ -4605,6 +4782,14 @@ class VIEW3D_PT_quad_view(Panel):
|
||||
row.prop(region, "use_box_clip")
|
||||
|
||||
|
||||
# Annotation properties
|
||||
class VIEW3D_PT_grease_pencil(GreasePencilDataPanel, Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'UI'
|
||||
|
||||
# NOTE: this is just a wrapper around the generic GP Panel
|
||||
|
||||
|
||||
class VIEW3D_PT_view3d_stereo(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'UI'
|
||||
@ -4684,6 +4869,27 @@ class VIEW3D_PT_context_properties(Panel):
|
||||
rna_prop_ui.draw(self.layout, context, member, object, False)
|
||||
|
||||
|
||||
# Grease Pencil Object - Multiframe falloff tools
|
||||
class VIEW3D_PT_gpencil_multi_frame(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'HEADER'
|
||||
bl_label = "Multi Frame"
|
||||
|
||||
@staticmethod
|
||||
def draw(self, context):
|
||||
gpd = context.gpencil_data
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
|
||||
layout = self.layout
|
||||
col = layout.column(align=True)
|
||||
col.prop(settings, "use_multiframe_falloff")
|
||||
|
||||
# Falloff curve
|
||||
if gpd.use_multiedit and settings.use_multiframe_falloff:
|
||||
layout.template_curve_mapping(settings, "multiframe_falloff_curve", brush=True)
|
||||
|
||||
|
||||
|
||||
classes = (
|
||||
VIEW3D_HT_header,
|
||||
VIEW3D_MT_editor_menus,
|
||||
@ -4791,8 +4997,13 @@ classes = (
|
||||
VIEW3D_MT_edit_mesh_clean,
|
||||
VIEW3D_MT_edit_mesh_delete,
|
||||
VIEW3D_MT_edit_mesh_showhide,
|
||||
VIEW3D_MT_paint_gpencil,
|
||||
VIEW3D_MT_edit_gpencil,
|
||||
VIEW3D_MT_edit_gpencil_delete,
|
||||
VIEW3D_MT_sculpt_gpencil,
|
||||
VIEW3D_MT_weight_gpencil,
|
||||
VIEW3D_MT_gpencil_animation,
|
||||
VIEW3D_MT_gpencil_simplify,
|
||||
VIEW3D_MT_edit_curve,
|
||||
VIEW3D_MT_edit_curve_ctrlpoints,
|
||||
VIEW3D_MT_edit_curve_segments,
|
||||
@ -4815,12 +5026,12 @@ classes = (
|
||||
VIEW3D_MT_edit_gpencil_interpolate,
|
||||
VIEW3D_MT_object_mode_pie,
|
||||
VIEW3D_MT_view_pie,
|
||||
VIEW3D_PT_grease_pencil,
|
||||
VIEW3D_PT_grease_pencil_palettecolor,
|
||||
VIEW3D_PT_view3d_properties,
|
||||
VIEW3D_PT_view3d_camera_lock,
|
||||
VIEW3D_PT_view3d_cursor,
|
||||
VIEW3D_PT_object_type_visibility,
|
||||
VIEW3D_PT_grease_pencil,
|
||||
VIEW3D_PT_gpencil_multi_frame,
|
||||
VIEW3D_PT_quad_view,
|
||||
VIEW3D_PT_view3d_stereo,
|
||||
VIEW3D_PT_shading,
|
||||
@ -4849,6 +5060,7 @@ classes = (
|
||||
VIEW3D_PT_pivot_point,
|
||||
VIEW3D_PT_snapping,
|
||||
VIEW3D_PT_transform_orientations,
|
||||
VIEW3D_PT_overlay_gpencil_options,
|
||||
VIEW3D_PT_context_properties,
|
||||
)
|
||||
|
||||
|
@ -20,19 +20,17 @@
|
||||
import bpy
|
||||
from bpy.types import Menu, Panel, UIList
|
||||
from .properties_grease_pencil_common import (
|
||||
GreasePencilDrawingToolsPanel,
|
||||
GreasePencilStrokeEditPanel,
|
||||
GreasePencilInterpolatePanel,
|
||||
GreasePencilStrokeSculptPanel,
|
||||
GreasePencilBrushPanel,
|
||||
GreasePencilBrushCurvesPanel
|
||||
)
|
||||
GreasePencilStrokeEditPanel,
|
||||
GreasePencilStrokeSculptPanel,
|
||||
GreasePencilAppearancePanel,
|
||||
)
|
||||
from .properties_paint_common import (
|
||||
UnifiedPaintPanel,
|
||||
brush_texture_settings,
|
||||
brush_texpaint_common,
|
||||
brush_mask_texture_settings,
|
||||
)
|
||||
UnifiedPaintPanel,
|
||||
brush_texture_settings,
|
||||
brush_texpaint_common,
|
||||
brush_mask_texture_settings,
|
||||
)
|
||||
from bl_operators.presets import PresetMenu
|
||||
|
||||
|
||||
class View3DPanel:
|
||||
@ -70,6 +68,12 @@ def draw_vpaint_symmetry(layout, vpaint):
|
||||
col.use_property_split = True
|
||||
col.prop(vpaint, "radial_symmetry", text="Radial")
|
||||
|
||||
# Most of these panels should not be visible in GP edit modes
|
||||
def is_not_gpencil_edit_mode(context):
|
||||
is_gpmode = context.active_object and \
|
||||
context.active_object.mode in {'GPENCIL_EDIT', 'GPENCIL_PAINT', 'GPENCIL_SCULPT', 'GPENCIL_WEIGHT'}
|
||||
return not is_gpmode
|
||||
|
||||
|
||||
# ********** default tools for editmode_mesh ****************
|
||||
|
||||
@ -1341,9 +1345,272 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
|
||||
sub.prop(pe, "fade_frames", slider=True)
|
||||
|
||||
|
||||
# Grease Pencil drawing tools
|
||||
class VIEW3D_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
|
||||
# ********** grease pencil object tool panels ****************
|
||||
|
||||
# Grease Pencil drawing brushes
|
||||
class VIEW3D_PT_tools_grease_pencil_brush(View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_paint"
|
||||
bl_label = "Brush"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
is_3d_view = context.space_data.type == 'VIEW_3D'
|
||||
if is_3d_view:
|
||||
if context.gpencil_data is None:
|
||||
return False
|
||||
|
||||
gpd = context.gpencil_data
|
||||
return bool(gpd.is_stroke_paint_mode)
|
||||
else:
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
ts = context.scene.tool_settings
|
||||
settings = ts.gpencil_paint
|
||||
|
||||
row = layout.row()
|
||||
col = row.column()
|
||||
col.template_ID_preview(settings, "brush", new="brush.add_gpencil", rows=3, cols=8)
|
||||
|
||||
col = row.column()
|
||||
brush = context.active_gpencil_brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
sub = col.column(align=True)
|
||||
sub.operator("gpencil.brush_presets_create", icon='HELP', text="")
|
||||
|
||||
if brush is not None:
|
||||
# XXX: Items in "sub" currently show up beside the brush selector in a separate column
|
||||
if gp_settings.gpencil_brush_type == 'ERASE':
|
||||
sub.prop(gp_settings, "default_eraser", text="")
|
||||
|
||||
# Brush details
|
||||
if gp_settings.gpencil_brush_type == 'ERASE':
|
||||
col = layout.column(align=True)
|
||||
col.prop(brush, "size", text="Radius")
|
||||
|
||||
col.separator()
|
||||
row = col.row()
|
||||
row.prop(gp_settings, "eraser_mode", expand=True)
|
||||
elif gp_settings.gpencil_brush_type == 'FILL':
|
||||
col = layout.column(align=True)
|
||||
col.prop(gp_settings, "gpencil_fill_leak", text="Leak Size")
|
||||
col.prop(brush, "size", text="Thickness")
|
||||
col.prop(gp_settings, "gpencil_fill_simplyfy_level", text="Simplify")
|
||||
|
||||
col = layout.row(align=True)
|
||||
col.template_ID(gp_settings, "material")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "gpencil_fill_draw_mode", text="Boundary Draw Mode")
|
||||
row.prop(gp_settings, "gpencil_fill_show_boundary", text="", icon='GRID')
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.enabled = gp_settings.gpencil_fill_draw_mode != "STROKE"
|
||||
col.prop(gp_settings, "gpencil_fill_hide", text="Hide Transparent Lines")
|
||||
sub = col.row(align=True)
|
||||
sub.enabled = gp_settings.gpencil_fill_hide
|
||||
sub.prop(gp_settings, "gpencil_fill_threshold", text="Threshold")
|
||||
else: # bgpsettings.gpencil_brush_type == 'DRAW':
|
||||
row = layout.row(align=True)
|
||||
row.prop(brush, "size", text="Radius")
|
||||
row.prop(gp_settings, "use_pressure", text="", icon='STYLUS_PRESSURE')
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "pen_strength", slider=True)
|
||||
row.prop(gp_settings, "use_strength_pressure", text="", icon='STYLUS_PRESSURE')
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.template_ID(gp_settings, "material")
|
||||
|
||||
|
||||
# Grease Pencil drawing brushes options
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_option(View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_paint"
|
||||
bl_label = "Options"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw_header_preset(self, context):
|
||||
VIEW3D_PT_gpencil_brush_presets.draw_panel_header(self.layout)
|
||||
|
||||
@staticmethod
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
brush = context.active_gpencil_brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
if brush is not None:
|
||||
col = layout.column(align=True)
|
||||
col.prop(gp_settings, "input_samples")
|
||||
col.separator()
|
||||
|
||||
col.prop(gp_settings, "active_smooth_factor")
|
||||
col.separator()
|
||||
|
||||
col.prop(gp_settings, "angle", slider=True)
|
||||
col.prop(gp_settings, "angle_factor", text="Factor", slider=True)
|
||||
col.separator()
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_stabilizer(View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_paint"
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_option'
|
||||
bl_label = "Stabilizer"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
brush = context.active_gpencil_brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
return brush is not None and gp_settings.gpencil_brush_type == 'DRAW'
|
||||
|
||||
def draw_header(self, context):
|
||||
brush = context.active_gpencil_brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
self.layout.prop(gp_settings, "use_stabilizer", text="")
|
||||
|
||||
@staticmethod
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
brush = context.active_gpencil_brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
layout.active = gp_settings.use_stabilizer
|
||||
|
||||
layout.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
|
||||
layout.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_settings(View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_paint"
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_option'
|
||||
bl_label = "Post-processing Settings"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
brush = context.active_gpencil_brush
|
||||
|
||||
return brush is not None
|
||||
|
||||
def draw_header(self, context):
|
||||
brush = context.active_gpencil_brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
self.layout.prop(gp_settings, "enable_settings", text="")
|
||||
|
||||
@staticmethod
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
brush = context.active_gpencil_brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
layout.active = gp_settings.enable_settings
|
||||
|
||||
layout.prop(gp_settings, "pen_smooth_factor")
|
||||
layout.prop(gp_settings, "pen_smooth_steps")
|
||||
|
||||
layout.prop(gp_settings, "pen_thick_smooth_factor")
|
||||
layout.prop(gp_settings, "pen_thick_smooth_steps")
|
||||
|
||||
layout.prop(gp_settings, "pen_subdivision_steps")
|
||||
layout.prop(gp_settings, "random_subdiv", text="Randomness", slider=True)
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_random(View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_paint"
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_option'
|
||||
bl_label = "Random Settings"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
brush = context.active_gpencil_brush
|
||||
|
||||
return brush is not None
|
||||
|
||||
def draw_header(self, context):
|
||||
brush = context.active_gpencil_brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
self.layout.prop(gp_settings, "enable_random", text="")
|
||||
|
||||
@staticmethod
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
brush = context.active_gpencil_brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
layout.active = gp_settings.enable_random
|
||||
|
||||
layout.prop(gp_settings, "random_pressure", text="Pressure", slider=True)
|
||||
layout.prop(gp_settings, "random_strength", text="Strength", slider=True)
|
||||
layout.prop(gp_settings, "uv_random", text="UV", slider=True)
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "pen_jitter", slider=True)
|
||||
row.prop(gp_settings, "use_jitter_pressure", text="", icon='STYLUS_PRESSURE')
|
||||
|
||||
|
||||
# Grease Pencil drawingcurves
|
||||
class VIEW3D_PT_tools_grease_pencil_brushcurves(View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_paint"
|
||||
bl_label = "Curves"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@staticmethod
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
|
||||
brush = context.active_gpencil_brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
# Brush
|
||||
layout.label("Sensitivity")
|
||||
layout.template_curve_mapping(gp_settings, "curve_sensitivity", brush=True)
|
||||
|
||||
layout.label("Strength")
|
||||
layout.template_curve_mapping(gp_settings, "curve_strength", brush=True)
|
||||
|
||||
layout.label("Jitter")
|
||||
layout.template_curve_mapping(gp_settings, "curve_jitter", brush=True)
|
||||
|
||||
|
||||
# Grease Pencil create shapes
|
||||
class VIEW3D_PT_tools_grease_pencil_shapes(View3DPanel, Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'HEADER'
|
||||
bl_label = "Shapes"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.active_object
|
||||
return ob and ob.type == 'GPENCIL'
|
||||
|
||||
@staticmethod
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.operator("gpencil.primitive", text="Line", icon='IPO_CONSTANT').type = 'LINE'
|
||||
col.operator("gpencil.primitive", text="Rectangle", icon='UV_FACESEL').type = 'BOX'
|
||||
col.operator("gpencil.primitive", text="Circle", icon='ANTIALIASED').type = 'CIRCLE'
|
||||
|
||||
layout.operator("object.gpencil_add", text="Monkey", icon='MONKEY').type = 'MONKEY'
|
||||
|
||||
|
||||
# Grease Pencil stroke editing tools
|
||||
@ -1352,24 +1619,109 @@ class VIEW3D_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
|
||||
|
||||
|
||||
# Grease Pencil stroke interpolation tools
|
||||
class VIEW3D_PT_tools_grease_pencil_interpolate(GreasePencilInterpolatePanel, Panel):
|
||||
class VIEW3D_PT_tools_grease_pencil_interpolate(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'HEADER'
|
||||
bl_label = "Interpolate"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if context.gpencil_data is None:
|
||||
return False
|
||||
|
||||
gpd = context.gpencil_data
|
||||
return bool(context.editable_gpencil_strokes) and bool(gpd.use_stroke_edit_mode)
|
||||
|
||||
@staticmethod
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
settings = context.tool_settings.gpencil_interpolate
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.label("Interpolate Strokes")
|
||||
col.operator("gpencil.interpolate", text="Interpolate")
|
||||
col.operator("gpencil.interpolate_sequence", text="Sequence")
|
||||
col.operator("gpencil.interpolate_reverse", text="Remove Breakdowns")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.label(text="Options:")
|
||||
col.prop(settings, "interpolate_all_layers")
|
||||
col.prop(settings, "interpolate_selected_only")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.label(text="Sequence Options:")
|
||||
col.prop(settings, "type")
|
||||
if settings.type == 'CUSTOM':
|
||||
# TODO: Options for loading/saving curve presets?
|
||||
col.template_curve_mapping(settings, "interpolation_curve", brush=True)
|
||||
elif settings.type != 'LINEAR':
|
||||
col.prop(settings, "easing")
|
||||
|
||||
if settings.type == 'BACK':
|
||||
layout.prop(settings, "back")
|
||||
elif setting.type == 'ELASTIC':
|
||||
sub = layout.column(align=True)
|
||||
sub.prop(settings, "amplitude")
|
||||
sub.prop(settings, "period")
|
||||
|
||||
|
||||
# Grease Pencil stroke sculpting tools
|
||||
class VIEW3D_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
class VIEW3D_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_sculpt"
|
||||
bl_category = "Tools"
|
||||
bl_label = "Sculpt Strokes"
|
||||
|
||||
|
||||
# Grease Pencil drawing brushes
|
||||
class VIEW3D_PT_tools_grease_pencil_brush(GreasePencilBrushPanel, Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
# Grease Pencil weight painting tools
|
||||
class VIEW3D_PT_tools_grease_pencil_weight_paint(View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_weight"
|
||||
bl_category = "Tools"
|
||||
bl_label = "Weight Paint"
|
||||
|
||||
# Grease Pencil drawingcurves
|
||||
@staticmethod
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
gpd = context.gpencil_data
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
tool = settings.tool
|
||||
brush = settings.brush
|
||||
|
||||
layout.template_icon_view(settings, "weight_tool", show_labels=True)
|
||||
|
||||
col = layout.column()
|
||||
col.prop(brush, "size", slider=True)
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "strength", slider=True)
|
||||
row.prop(brush, "use_pressure_strength", text="")
|
||||
|
||||
col.prop(brush, "use_falloff")
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
# Grease Pencil Brush Appeareance (one for each mode)
|
||||
class VIEW3D_PT_tools_grease_pencil_paint_appearance(GreasePencilAppearancePanel, View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_paint"
|
||||
bl_label = "Appearance"
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_sculpt_appearance(GreasePencilAppearancePanel, View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_sculpt"
|
||||
bl_label = "Appearance"
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_weight_appearance(GreasePencilAppearancePanel, View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_weight"
|
||||
bl_label = "Appearance"
|
||||
|
||||
|
||||
class VIEW3D_PT_gpencil_brush_presets(PresetMenu):
|
||||
"""Brush settings"""
|
||||
bl_label = "Brush Presets"
|
||||
preset_subdir = "gpencil_brush"
|
||||
preset_operator = "script.execute_preset"
|
||||
preset_add_operator = "scene.gpencil_brush_preset_add"
|
||||
|
||||
|
||||
classes = (
|
||||
@ -1401,12 +1753,21 @@ classes = (
|
||||
VIEW3D_PT_tools_projectpaint,
|
||||
VIEW3D_MT_tools_projectpaint_stencil,
|
||||
VIEW3D_PT_tools_particlemode,
|
||||
VIEW3D_PT_tools_grease_pencil_draw,
|
||||
VIEW3D_PT_tools_grease_pencil_edit,
|
||||
VIEW3D_PT_tools_grease_pencil_interpolate,
|
||||
VIEW3D_PT_tools_grease_pencil_sculpt,
|
||||
|
||||
VIEW3D_PT_gpencil_brush_presets,
|
||||
VIEW3D_PT_tools_grease_pencil_brush,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_option,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_settings,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_stabilizer,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_random,
|
||||
VIEW3D_PT_tools_grease_pencil_brushcurves,
|
||||
VIEW3D_PT_tools_grease_pencil_shapes,
|
||||
VIEW3D_PT_tools_grease_pencil_sculpt,
|
||||
VIEW3D_PT_tools_grease_pencil_weight_paint,
|
||||
VIEW3D_PT_tools_grease_pencil_paint_appearance,
|
||||
VIEW3D_PT_tools_grease_pencil_sculpt_appearance,
|
||||
VIEW3D_PT_tools_grease_pencil_weight_appearance,
|
||||
VIEW3D_PT_tools_grease_pencil_interpolate,
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
|
@ -44,7 +44,9 @@ set(SRC_DNA_INC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_fileglobal_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_freestyle_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_genfile.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpencil_modifier_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpencil_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_shader_fx_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpu_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_group_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_image_types.h
|
||||
@ -112,6 +114,8 @@ add_subdirectory(gpu)
|
||||
add_subdirectory(imbuf)
|
||||
add_subdirectory(nodes)
|
||||
add_subdirectory(modifiers)
|
||||
add_subdirectory(gpencil_modifiers)
|
||||
add_subdirectory(shader_fx)
|
||||
add_subdirectory(makesdna)
|
||||
add_subdirectory(makesrna)
|
||||
|
||||
|
@ -28,11 +28,14 @@
|
||||
*/
|
||||
|
||||
enum eCurveMappingPreset;
|
||||
struct bContext;
|
||||
struct Brush;
|
||||
struct Paint;
|
||||
struct ImBuf;
|
||||
struct ImagePool;
|
||||
struct Main;
|
||||
struct Scene;
|
||||
struct ToolSettings;
|
||||
struct UnifiedPaintSettings;
|
||||
// enum eCurveMappingPreset;
|
||||
|
||||
@ -45,14 +48,17 @@ void BKE_brush_system_exit(void);
|
||||
/* datablock functions */
|
||||
void BKE_brush_init(struct Brush *brush);
|
||||
struct Brush *BKE_brush_add(struct Main *bmain, const char *name, const eObjectMode ob_mode);
|
||||
struct Brush *BKE_brush_add_gpencil(struct Main *bmain, struct ToolSettings *ts, const char *name);
|
||||
struct Brush *BKE_brush_first_search(struct Main *bmain, const eObjectMode ob_mode);
|
||||
void BKE_brush_copy_data(struct Main *bmain, struct Brush *brush_dst, const struct Brush *brush_src, const int flag);
|
||||
struct Brush *BKE_brush_copy(struct Main *bmain, const struct Brush *brush);
|
||||
void BKE_brush_make_local(struct Main *bmain, struct Brush *brush, const bool lib_local);
|
||||
void BKE_brush_unlink(struct Main *bmain, struct Brush *brush);
|
||||
void BKE_brush_free(struct Brush *brush);
|
||||
|
||||
void BKE_brush_sculpt_reset(struct Brush *brush);
|
||||
void BKE_brush_gpencil_presets(struct bContext *C);
|
||||
struct Brush *BKE_brush_getactive_gpencil(struct ToolSettings *ts);
|
||||
struct Paint *BKE_brush_get_gpencil_paint(struct ToolSettings *ts);
|
||||
|
||||
/* image icon function */
|
||||
struct ImBuf *get_brush_icon(struct Brush *brush);
|
||||
|
@ -65,9 +65,7 @@ struct bPoseChannel;
|
||||
struct bGPdata;
|
||||
struct bGPDlayer;
|
||||
struct bGPDframe;
|
||||
struct bGPDpalette;
|
||||
struct bGPDpalettecolor;
|
||||
struct bGPDbrush;
|
||||
struct Brush;
|
||||
struct wmWindow;
|
||||
struct wmWindowManager;
|
||||
struct RenderEngineType;
|
||||
@ -120,6 +118,10 @@ enum {
|
||||
CTX_MODE_PAINT_TEXTURE,
|
||||
CTX_MODE_PARTICLE,
|
||||
CTX_MODE_OBJECT,
|
||||
CTX_MODE_GPENCIL_PAINT,
|
||||
CTX_MODE_GPENCIL_EDIT,
|
||||
CTX_MODE_GPENCIL_SCULPT,
|
||||
CTX_MODE_GPENCIL_WEIGHT,
|
||||
CTX_MODE_NUM /* must be last */
|
||||
};
|
||||
|
||||
@ -313,9 +315,7 @@ int CTX_data_visible_pose_bones(const bContext *C, ListBase *list);
|
||||
struct bGPdata *CTX_data_gpencil_data(const bContext *C);
|
||||
struct bGPDlayer *CTX_data_active_gpencil_layer(const bContext *C);
|
||||
struct bGPDframe *CTX_data_active_gpencil_frame(const bContext *C);
|
||||
struct bGPDpalette *CTX_data_active_gpencil_palette(const bContext *C);
|
||||
struct bGPDpalettecolor *CTX_data_active_gpencil_palettecolor(const bContext *C);
|
||||
struct bGPDbrush *CTX_data_active_gpencil_brush(const bContext *C);
|
||||
struct Brush *CTX_data_active_gpencil_brush(const bContext *C);
|
||||
int CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list);
|
||||
int CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list);
|
||||
int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list);
|
||||
|
@ -31,25 +31,45 @@
|
||||
* \author Joshua Leung
|
||||
*/
|
||||
|
||||
struct CurveMapping;
|
||||
struct Depsgraph;
|
||||
struct GpencilModifierData;
|
||||
struct ToolSettings;
|
||||
struct ListBase;
|
||||
struct bGPdata;
|
||||
struct bGPDlayer;
|
||||
struct bGPDframe;
|
||||
struct bGPDspoint;
|
||||
struct bGPDstroke;
|
||||
struct Material;
|
||||
struct bGPDpalette;
|
||||
struct bGPDpalettecolor;
|
||||
struct Main;
|
||||
struct BoundBox;
|
||||
struct Brush;
|
||||
struct Object;
|
||||
struct bDeformGroup;
|
||||
struct SimplifyGpencilModifierData;
|
||||
struct InstanceGpencilModifierData;
|
||||
struct LatticeGpencilModifierData;
|
||||
|
||||
struct MDeformVert;
|
||||
struct MDeformWeight;
|
||||
|
||||
/* ------------ Grease-Pencil API ------------------ */
|
||||
|
||||
void BKE_gpencil_free_point_weights(struct MDeformVert *dvert);
|
||||
void BKE_gpencil_free_stroke_weights(struct bGPDstroke *gps);
|
||||
void BKE_gpencil_free_stroke(struct bGPDstroke *gps);
|
||||
bool BKE_gpencil_free_strokes(struct bGPDframe *gpf);
|
||||
void BKE_gpencil_free_frames(struct bGPDlayer *gpl);
|
||||
void BKE_gpencil_free_layers(struct ListBase *list);
|
||||
void BKE_gpencil_free_brushes(struct ListBase *list);
|
||||
void BKE_gpencil_free_palettes(struct ListBase *list);
|
||||
void BKE_gpencil_free(struct bGPdata *gpd, bool free_palettes);
|
||||
bool BKE_gpencil_free_frame_runtime_data(struct bGPDframe *derived_gpf);
|
||||
void BKE_gpencil_free_derived_frames(struct bGPdata *gpd);
|
||||
void BKE_gpencil_free(struct bGPdata *gpd, bool free_all);
|
||||
|
||||
void BKE_gpencil_batch_cache_dirty(struct bGPdata *gpd);
|
||||
void BKE_gpencil_batch_cache_free(struct bGPdata *gpd);
|
||||
|
||||
void BKE_gpencil_stroke_sync_selection(struct bGPDstroke *gps);
|
||||
|
||||
@ -60,21 +80,36 @@ struct bGPdata *BKE_gpencil_data_addnew(struct Main *bmain, const char name[])
|
||||
|
||||
struct bGPDframe *BKE_gpencil_frame_duplicate(const struct bGPDframe *gpf_src);
|
||||
struct bGPDlayer *BKE_gpencil_layer_duplicate(const struct bGPDlayer *gpl_src);
|
||||
void BKE_gpencil_frame_copy_strokes(struct bGPDframe *gpf_src, struct bGPDframe *gpf_dst);
|
||||
struct bGPDstroke *BKE_gpencil_stroke_duplicate(struct bGPDstroke *gps_src);
|
||||
|
||||
void BKE_gpencil_copy_data(struct Main *bmain, struct bGPdata *gpd_dst, const struct bGPdata *gpd_src, const int flag);
|
||||
struct bGPdata *BKE_gpencil_copy(struct Main *bmain, const struct bGPdata *gpd);
|
||||
struct bGPdata *BKE_gpencil_data_duplicate(struct Main *bmain, const struct bGPdata *gpd, bool internal_copy);
|
||||
|
||||
void BKE_gpencil_make_local(struct Main *bmain, struct bGPdata *gpd, const bool lib_local);
|
||||
|
||||
void BKE_gpencil_frame_delete_laststroke(struct bGPDlayer *gpl, struct bGPDframe *gpf);
|
||||
|
||||
struct bGPDpalette *BKE_gpencil_palette_addnew(struct bGPdata *gpd, const char *name, bool setactive);
|
||||
struct bGPDpalette *BKE_gpencil_palette_duplicate(const struct bGPDpalette *palette_src);
|
||||
struct bGPDpalettecolor *BKE_gpencil_palettecolor_addnew(struct bGPDpalette *palette, const char *name, bool setactive);
|
||||
/* materials */
|
||||
void BKE_gpencil_material_index_remove(struct bGPdata *gpd, int index);
|
||||
void BKE_gpencil_material_remap(struct bGPdata *gpd, const unsigned int *remap, unsigned int remap_len);
|
||||
|
||||
struct bGPDbrush *BKE_gpencil_brush_addnew(struct ToolSettings *ts, const char *name, bool setactive);
|
||||
struct bGPDbrush *BKE_gpencil_brush_duplicate(const struct bGPDbrush *brush_src);
|
||||
void BKE_gpencil_brush_init_presets(struct ToolSettings *ts);
|
||||
/* statistics functions */
|
||||
void BKE_gpencil_stats_update(struct bGPdata *gpd);
|
||||
|
||||
/* Utilities for creating and populating GP strokes */
|
||||
/* - Number of values defining each point in the built-in data
|
||||
* buffers for primitives (e.g. 2D Monkey)
|
||||
*/
|
||||
#define GP_PRIM_DATABUF_SIZE 5
|
||||
|
||||
void BKE_gpencil_stroke_add_points(
|
||||
struct bGPDstroke *gps,
|
||||
const float *array, const int totpoints,
|
||||
const float mat[4][4]);
|
||||
|
||||
struct bGPDstroke *BKE_gpencil_add_stroke(struct bGPDframe *gpf, int mat_idx, int totpoints, short thickness);
|
||||
|
||||
/* Stroke and Fill - Alpha Visibility Threshold */
|
||||
#define GPENCIL_ALPHA_OPACITY_THRESH 0.001f
|
||||
@ -103,20 +138,40 @@ struct bGPDlayer *BKE_gpencil_layer_getactive(struct bGPdata *gpd);
|
||||
void BKE_gpencil_layer_setactive(struct bGPdata *gpd, struct bGPDlayer *active);
|
||||
void BKE_gpencil_layer_delete(struct bGPdata *gpd, struct bGPDlayer *gpl);
|
||||
|
||||
struct bGPDbrush *BKE_gpencil_brush_getactive(struct ToolSettings *ts);
|
||||
void BKE_gpencil_brush_setactive(struct ToolSettings *ts, struct bGPDbrush *active);
|
||||
void BKE_gpencil_brush_delete(struct ToolSettings *ts, struct bGPDbrush *brush);
|
||||
struct Material *BKE_gpencil_get_material_from_brush(struct Brush *brush);
|
||||
struct Material *BKE_gpencil_material_ensure(struct Main *bmain, struct Object *ob);
|
||||
|
||||
struct bGPDpalette *BKE_gpencil_palette_getactive(struct bGPdata *gpd);
|
||||
void BKE_gpencil_palette_setactive(struct bGPdata *gpd, struct bGPDpalette *active);
|
||||
void BKE_gpencil_palette_delete(struct bGPdata *gpd, struct bGPDpalette *palette);
|
||||
void BKE_gpencil_palette_change_strokes(struct bGPdata *gpd);
|
||||
/* object boundbox */
|
||||
bool BKE_gpencil_stroke_minmax(
|
||||
const struct bGPDstroke *gps, const bool use_select,
|
||||
float r_min[3], float r_max[3]);
|
||||
|
||||
struct bGPDpalettecolor *BKE_gpencil_palettecolor_getactive(struct bGPDpalette *palette);
|
||||
void BKE_gpencil_palettecolor_setactive(struct bGPDpalette *palette, struct bGPDpalettecolor *active);
|
||||
void BKE_gpencil_palettecolor_delete(struct bGPDpalette *palette, struct bGPDpalettecolor *palcolor);
|
||||
struct bGPDpalettecolor *BKE_gpencil_palettecolor_getbyname(struct bGPDpalette *palette, char *name);
|
||||
void BKE_gpencil_palettecolor_changename(struct bGPdata *gpd, char *oldname, const char *newname);
|
||||
void BKE_gpencil_palettecolor_delete_strokes(struct bGPdata *gpd, char *name);
|
||||
struct BoundBox *BKE_gpencil_boundbox_get(struct Object *ob);
|
||||
void BKE_gpencil_centroid_3D(struct bGPdata *gpd, float r_centroid[3]);
|
||||
|
||||
/* vertex groups */
|
||||
float BKE_gpencil_vgroup_use_index(struct MDeformVert *dvert, int index);
|
||||
void BKE_gpencil_vgroup_remove(struct Object *ob, struct bDeformGroup *defgroup);
|
||||
struct MDeformWeight *BKE_gpencil_vgroup_add_point_weight(struct MDeformVert *dvert, int index, float weight);
|
||||
bool BKE_gpencil_vgroup_remove_point_weight(struct MDeformVert *dvert, int index);
|
||||
void BKE_gpencil_stroke_weights_duplicate(struct bGPDstroke *gps_src, struct bGPDstroke *gps_dst);
|
||||
|
||||
/* GPencil geometry evaluation */
|
||||
void BKE_gpencil_eval_geometry(struct Depsgraph *depsgraph, struct bGPdata *gpd);
|
||||
|
||||
/* stroke geometry utilities */
|
||||
void BKE_gpencil_stroke_normal(const struct bGPDstroke *gps, float r_normal[3]);
|
||||
void BKE_gpencil_simplify_stroke(struct bGPDstroke *gps, float factor);
|
||||
void BKE_gpencil_simplify_fixed(struct bGPDstroke *gps);
|
||||
|
||||
void BKE_gpencil_transform(struct bGPdata *gpd, float mat[4][4]);
|
||||
|
||||
bool BKE_gpencil_smooth_stroke(struct bGPDstroke *gps, int i, float inf);
|
||||
bool BKE_gpencil_smooth_stroke_strength(struct bGPDstroke *gps, int point_index, float influence);
|
||||
bool BKE_gpencil_smooth_stroke_thickness(struct bGPDstroke *gps, int point_index, float influence);
|
||||
bool BKE_gpencil_smooth_stroke_uv(struct bGPDstroke *gps, int point_index, float influence);
|
||||
|
||||
void BKE_gpencil_get_range_selected(struct bGPDlayer *gpl, int *r_initframe, int *r_endframe);
|
||||
float BKE_gpencil_multiframe_falloff_calc(struct bGPDframe *gpf, int actnum, int f_init, int f_end, struct CurveMapping *cur_falloff);
|
||||
|
||||
#endif /* __BKE_GPENCIL_H__ */
|
||||
|
256
source/blender/blenkernel/BKE_gpencil_modifier.h
Normal file
@ -0,0 +1,256 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
#ifndef __BKE_GPENCIL_MODIFIER_H__
|
||||
#define __BKE_GPENCIL_MODIFIER_H__
|
||||
|
||||
/** \file BKE_greasepencil_modifier.h
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include "DNA_gpencil_modifier_types.h" /* needed for all enum typdefs */
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BKE_customdata.h"
|
||||
|
||||
struct ID;
|
||||
struct Depsgraph;
|
||||
struct DerivedMesh;
|
||||
struct bContext; /* NOTE: bakeModifier() - called from UI - needs to create new datablocks, hence the need for this */
|
||||
struct Mesh;
|
||||
struct Object;
|
||||
struct Scene;
|
||||
struct ViewLayer;
|
||||
struct ListBase;
|
||||
struct bArmature;
|
||||
struct Main;
|
||||
struct GpencilModifierData;
|
||||
struct BMEditMesh;
|
||||
struct DepsNodeHandle;
|
||||
struct bGPDlayer;
|
||||
struct bGPDframe;
|
||||
struct bGPDstroke;
|
||||
struct ModifierUpdateDepsgraphContext;
|
||||
|
||||
#define GPENCIL_MODIFIER_ACTIVE(_md, _is_render) (((_md->mode & eGpencilModifierMode_Realtime) && (_is_render == false)) || \
|
||||
((_md->mode & eGpencilModifierMode_Render) && (_is_render == true)))
|
||||
#define GPENCIL_MODIFIER_EDIT(_md, _is_edit) (((_md->mode & eGpencilModifierMode_Editmode) == 0) && (_is_edit))
|
||||
|
||||
typedef enum {
|
||||
/* Should not be used, only for None modifier type */
|
||||
eGpencilModifierTypeType_None,
|
||||
|
||||
/* grease pencil modifiers */
|
||||
eGpencilModifierTypeType_Gpencil,
|
||||
} GpencilModifierTypeType;
|
||||
|
||||
typedef enum {
|
||||
eGpencilModifierTypeFlag_SupportsMapping = (1 << 0),
|
||||
eGpencilModifierTypeFlag_SupportsEditmode = (1 << 1),
|
||||
|
||||
/* For modifiers that support editmode this determines if the
|
||||
* modifier should be enabled by default in editmode. This should
|
||||
* only be used by modifiers that are relatively speedy and
|
||||
* also generally used in editmode, otherwise let the user enable
|
||||
* it by hand.
|
||||
*/
|
||||
eGpencilModifierTypeFlag_EnableInEditmode = (1 << 2),
|
||||
|
||||
/* For modifiers that require original data and so cannot
|
||||
* be placed after any non-deformative modifier.
|
||||
*/
|
||||
eGpencilModifierTypeFlag_RequiresOriginalData = (1 << 3),
|
||||
|
||||
/* max one per type */
|
||||
eGpencilModifierTypeFlag_Single = (1 << 4),
|
||||
|
||||
/* can't be added manually by user */
|
||||
eGpencilModifierTypeFlag_NoUserAdd = (1 << 5),
|
||||
} GpencilModifierTypeFlag;
|
||||
|
||||
/* IMPORTANT! Keep ObjectWalkFunc and IDWalkFunc signatures compatible. */
|
||||
typedef void(*GreasePencilObjectWalkFunc)(void *userData, struct Object *ob, struct Object **obpoin, int cb_flag);
|
||||
typedef void(*GreasePencilIDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cb_flag);
|
||||
typedef void(*GreasePencilTexWalkFunc)(void *userData, struct Object *ob, struct GpencilModifierData *md, const char *propname);
|
||||
|
||||
typedef struct GpencilModifierTypeInfo {
|
||||
/* The user visible name for this modifier */
|
||||
char name[32];
|
||||
|
||||
/* The DNA struct name for the modifier data type, used to
|
||||
* write the DNA data out.
|
||||
*/
|
||||
char struct_name[32];
|
||||
|
||||
/* The size of the modifier data type, used by allocation. */
|
||||
int struct_size;
|
||||
|
||||
GpencilModifierType type;
|
||||
GpencilModifierTypeFlag flags;
|
||||
|
||||
|
||||
/********************* Non-optional functions *********************/
|
||||
|
||||
/* Copy instance data for this modifier type. Should copy all user
|
||||
* level settings to the target modifier.
|
||||
*/
|
||||
void (*copyData)(const struct GpencilModifierData *md, struct GpencilModifierData *target);
|
||||
|
||||
/* Callback for GP "stroke" modifiers that operate on the
|
||||
* shape and parameters of the provided strokes (e.g. Thickness, Noise, etc.)
|
||||
*
|
||||
* The gpl parameter contains the GP layer that the strokes come from.
|
||||
* While access is provided to this data, you should not directly access
|
||||
* the gpl->frames data from the modifier. Instead, use the gpf parameter
|
||||
* instead.
|
||||
*
|
||||
* The gps parameter contains the GP stroke to operate on. This is usually a copy
|
||||
* of the original (unmodified and saved to files) stroke data.
|
||||
*/
|
||||
void (*deformStroke)(struct GpencilModifierData *md, struct Depsgraph *depsgraph,
|
||||
struct Object *ob, struct bGPDlayer *gpl, struct bGPDstroke *gps);
|
||||
|
||||
/* Callback for GP "geometry" modifiers that create extra geometry
|
||||
* in the frame (e.g. Array)
|
||||
*
|
||||
* The gpf parameter contains the GP frame/strokes to operate on. This is
|
||||
* usually a copy of the original (unmodified and saved to files) stroke data.
|
||||
* Modifiers should only add any generated strokes to this frame (and not one accessed
|
||||
* via the gpl parameter).
|
||||
*
|
||||
* The modifier_index parameter indicates where the modifier is
|
||||
* in the modifier stack in relation to other modifiers.
|
||||
*/
|
||||
void (*generateStrokes)(struct GpencilModifierData *md, struct Depsgraph *depsgraph,
|
||||
struct Object *ob, struct bGPDlayer *gpl, struct bGPDframe *gpf);
|
||||
|
||||
/* Bake-down GP modifier's effects into the GP datablock.
|
||||
*
|
||||
* This gets called when the user clicks the "Apply" button in the UI.
|
||||
* As such, this callback needs to go through all layers/frames in the
|
||||
* datablock, mutating the geometry and/or creating new datablocks/objects
|
||||
*/
|
||||
void (*bakeModifier)(struct Main *bmain, struct Depsgraph *depsgraph,
|
||||
struct GpencilModifierData *md, struct Object *ob);
|
||||
|
||||
/********************* Optional functions *********************/
|
||||
|
||||
/* Initialize new instance data for this modifier type, this function
|
||||
* should set modifier variables to their default values.
|
||||
*
|
||||
* This function is optional.
|
||||
*/
|
||||
void (*initData)(struct GpencilModifierData *md);
|
||||
|
||||
/* Free internal modifier data variables, this function should
|
||||
* not free the md variable itself.
|
||||
*
|
||||
* This function is optional.
|
||||
*/
|
||||
void (*freeData)(struct GpencilModifierData *md);
|
||||
|
||||
/* Return a boolean value indicating if this modifier is able to be
|
||||
* calculated based on the modifier data. This is *not* regarding the
|
||||
* md->flag, that is tested by the system, this is just if the data
|
||||
* validates (for example, a lattice will return false if the lattice
|
||||
* object is not defined).
|
||||
*
|
||||
* This function is optional (assumes never disabled if not present).
|
||||
*/
|
||||
bool (*isDisabled)(struct GpencilModifierData *md, int userRenderParams);
|
||||
|
||||
/* Add the appropriate relations to the dependency graph.
|
||||
*
|
||||
* This function is optional.
|
||||
*/
|
||||
void (*updateDepsgraph)(struct GpencilModifierData *md,
|
||||
const struct ModifierUpdateDepsgraphContext *ctx);
|
||||
|
||||
/* Should return true if the modifier needs to be recalculated on time
|
||||
* changes.
|
||||
*
|
||||
* This function is optional (assumes false if not present).
|
||||
*/
|
||||
bool (*dependsOnTime)(struct GpencilModifierData *md);
|
||||
|
||||
|
||||
/* Should call the given walk function on with a pointer to each Object
|
||||
* pointer that the modifier data stores. This is used for linking on file
|
||||
* load and for unlinking objects or forwarding object references.
|
||||
*
|
||||
* This function is optional.
|
||||
*/
|
||||
void (*foreachObjectLink)(struct GpencilModifierData *md, struct Object *ob,
|
||||
GreasePencilObjectWalkFunc walk, void *userData);
|
||||
|
||||
/* Should call the given walk function with a pointer to each ID
|
||||
* pointer (i.e. each datablock pointer) that the modifier data
|
||||
* stores. This is used for linking on file load and for
|
||||
* unlinking datablocks or forwarding datablock references.
|
||||
*
|
||||
* This function is optional. If it is not present, foreachObjectLink
|
||||
* will be used.
|
||||
*/
|
||||
void (*foreachIDLink)(struct GpencilModifierData *md, struct Object *ob,
|
||||
GreasePencilIDWalkFunc walk, void *userData);
|
||||
|
||||
/* Should call the given walk function for each texture that the
|
||||
* modifier data stores. This is used for finding all textures in
|
||||
* the context for the UI.
|
||||
*
|
||||
* This function is optional. If it is not present, it will be
|
||||
* assumed the modifier has no textures.
|
||||
*/
|
||||
void (*foreachTexLink)(struct GpencilModifierData *md, struct Object *ob,
|
||||
GreasePencilTexWalkFunc walk, void *userData);
|
||||
} GpencilModifierTypeInfo;
|
||||
|
||||
void BKE_gpencil_instance_modifier_instance_tfm(struct InstanceGpencilModifierData *mmd, const int elem_idx[3], float r_mat[4][4]);
|
||||
|
||||
/* Initialize modifier's global data (type info and some common global storages). */
|
||||
void BKE_gpencil_modifier_init(void);
|
||||
|
||||
const GpencilModifierTypeInfo *BKE_gpencil_modifierType_getInfo(GpencilModifierType type);
|
||||
struct GpencilModifierData *BKE_gpencil_modifier_new(int type);
|
||||
void BKE_gpencil_modifier_free_ex(struct GpencilModifierData *md, const int flag);
|
||||
void BKE_gpencil_modifier_free(struct GpencilModifierData *md);
|
||||
bool BKE_gpencil_modifier_unique_name(struct ListBase *modifiers, struct GpencilModifierData *gmd);
|
||||
bool BKE_gpencil_modifier_dependsOnTime(struct GpencilModifierData *md);
|
||||
struct GpencilModifierData *BKE_gpencil_modifiers_findByType(struct Object *ob, GpencilModifierType type);
|
||||
struct GpencilModifierData *BKE_gpencil_modifiers_findByName(struct Object *ob, const char *name);
|
||||
void BKE_gpencil_modifier_copyData_generic(const struct GpencilModifierData *md_src, struct GpencilModifierData *md_dst);
|
||||
void BKE_gpencil_modifier_copyData(struct GpencilModifierData *md, struct GpencilModifierData *target);
|
||||
void BKE_gpencil_modifier_copyData_ex(struct GpencilModifierData *md, struct GpencilModifierData *target, const int flag);
|
||||
void BKE_gpencil_modifiers_foreachIDLink(struct Object *ob, GreasePencilIDWalkFunc walk, void *userData);
|
||||
void BKE_gpencil_modifiers_foreachTexLink(struct Object *ob, GreasePencilTexWalkFunc walk, void *userData);
|
||||
|
||||
bool BKE_gpencil_has_geometry_modifiers(struct Object *ob);
|
||||
|
||||
void BKE_gpencil_stroke_modifiers(
|
||||
struct Depsgraph *depsgraph, struct Object *ob,
|
||||
struct bGPDlayer *gpl, struct bGPDframe *gpf, struct bGPDstroke *gps, bool is_render);
|
||||
void BKE_gpencil_geometry_modifiers(
|
||||
struct Depsgraph *depsgraph, struct Object *ob,
|
||||
struct bGPDlayer *gpl, struct bGPDframe *gpf, bool is_render);
|
||||
|
||||
void BKE_gpencil_lattice_init(struct Object *ob);
|
||||
void BKE_gpencil_lattice_clear(struct Object *ob);
|
||||
|
||||
#endif /* __BKE_GPENCIL_MODIFIER_H__ */
|
@ -43,7 +43,10 @@ enum {
|
||||
ICON_DATA_PREVIEW,
|
||||
/** 2D triangles: obj is #Icon_Geom */
|
||||
ICON_DATA_GEOM,
|
||||
/** Studiolight */
|
||||
ICON_DATA_STUDIOLIGHT,
|
||||
/** GPencil Layer color preview (annotations): obj is #bGPDlayer */
|
||||
ICON_DATA_GPLAYER,
|
||||
};
|
||||
|
||||
struct Icon {
|
||||
@ -79,6 +82,7 @@ struct ImBuf;
|
||||
struct PreviewImage;
|
||||
struct ID;
|
||||
struct StudioLight;
|
||||
struct bGPDlayer;
|
||||
|
||||
enum eIconSizes;
|
||||
|
||||
@ -87,6 +91,9 @@ void BKE_icons_init(int first_dyn_id);
|
||||
/* return icon id for library object or create new icon if not found */
|
||||
int BKE_icon_id_ensure(struct ID *id);
|
||||
|
||||
/* return icon id for Grease Pencil layer (color preview) or create new icon if not found */
|
||||
int BKE_icon_gplayer_color_ensure(struct bGPDlayer *gpl);
|
||||
|
||||
int BKE_icon_preview_ensure(struct ID *id, struct PreviewImage *preview);
|
||||
|
||||
/* retrieve icon for id */
|
||||
|
@ -54,7 +54,6 @@ void BKE_lattice_free(struct Lattice *lt);
|
||||
void BKE_lattice_make_local(struct Main *bmain, struct Lattice *lt, const bool lib_local);
|
||||
void calc_lat_fudu(int flag, int res, float *r_fu, float *r_du);
|
||||
|
||||
struct LatticeDeformData;
|
||||
struct LatticeDeformData *init_latt_deform(struct Object *oblatt, struct Object *ob) ATTR_WARN_UNUSED_RESULT;
|
||||
void calc_latt_deform(struct LatticeDeformData *lattice_deform_data, float co[3], float weight);
|
||||
void end_latt_deform(struct LatticeDeformData *lattice_deform_data);
|
||||
|
@ -54,11 +54,13 @@ void BKE_material_init(struct Material *ma);
|
||||
void BKE_material_remap_object(struct Object *ob, const unsigned int *remap);
|
||||
void BKE_material_remap_object_calc(struct Object *ob_dst, struct Object *ob_src, short *remap_src_to_dst);
|
||||
struct Material *BKE_material_add(struct Main *bmain, const char *name);
|
||||
struct Material *BKE_material_add_gpencil(struct Main *bmain, const char *name);
|
||||
void BKE_material_copy_data(struct Main *bmain, struct Material *ma_dst, const struct Material *ma_src, const int flag);
|
||||
struct Material *BKE_material_copy(struct Main *bmain, const struct Material *ma);
|
||||
struct Material *BKE_material_localize(struct Material *ma);
|
||||
struct Material *give_node_material(struct Material *ma); /* returns node material or self */
|
||||
void BKE_material_make_local(struct Main *bmain, struct Material *ma, const bool lib_local);
|
||||
void BKE_material_init_gpencil_settings(struct Material *ma);
|
||||
|
||||
/* UNUSED */
|
||||
// void automatname(struct Material *);
|
||||
@ -87,6 +89,8 @@ short BKE_object_material_slot_find_index(struct Object *ob, struct Material *ma
|
||||
bool BKE_object_material_slot_add(struct Main *bmain, struct Object *ob);
|
||||
bool BKE_object_material_slot_remove(struct Main *bmain, struct Object *ob);
|
||||
|
||||
struct MaterialGPencilStyle *BKE_material_gpencil_settings_get(struct Object *ob, short act);
|
||||
|
||||
void BKE_texpaint_slot_refresh_cache(struct Scene *scene, struct Material *ma);
|
||||
void BKE_texpaint_slots_refresh_object(struct Scene *scene, struct Object *ob);
|
||||
|
||||
|
@ -37,8 +37,11 @@ extern "C" {
|
||||
|
||||
struct Base;
|
||||
struct Depsgraph;
|
||||
struct GpencilModifierData;
|
||||
struct Scene;
|
||||
struct ShaderFxData;
|
||||
struct ViewLayer;
|
||||
struct ID;
|
||||
struct Object;
|
||||
struct BoundBox;
|
||||
struct View3D;
|
||||
@ -49,6 +52,7 @@ struct Mesh;
|
||||
struct RigidBodyWorld;
|
||||
struct HookModifierData;
|
||||
struct ModifierData;
|
||||
struct HookGpencilModifierData;
|
||||
|
||||
#include "DNA_object_enums.h"
|
||||
|
||||
@ -69,11 +73,16 @@ void BKE_object_free_derived_mesh_caches(struct Object *ob);
|
||||
void BKE_object_free_caches(struct Object *object);
|
||||
|
||||
void BKE_object_modifier_hook_reset(struct Object *ob, struct HookModifierData *hmd);
|
||||
void BKE_object_modifier_gpencil_hook_reset(struct Object *ob, struct HookGpencilModifierData *hmd);
|
||||
bool BKE_object_modifier_gpencil_use_time(struct Object *ob, struct GpencilModifierData *md);
|
||||
|
||||
bool BKE_object_shaderfx_use_time(struct Object *ob, struct ShaderFxData *md);
|
||||
|
||||
bool BKE_object_support_modifier_type_check(const struct Object *ob, int modifier_type);
|
||||
|
||||
void BKE_object_link_modifiers(struct Scene *scene, struct Object *ob_dst, const struct Object *ob_src);
|
||||
void BKE_object_free_modifiers(struct Object *ob, const int flag);
|
||||
void BKE_object_free_shaderfx(struct Object *ob, const int flag);
|
||||
|
||||
void BKE_object_make_proxy(struct Main *bmain, struct Object *ob, struct Object *target, struct Object *gob);
|
||||
void BKE_object_copy_proxy_drivers(struct Object *ob, struct Object *target);
|
||||
@ -108,6 +117,9 @@ struct Object *BKE_object_add_from(
|
||||
struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer,
|
||||
int type, const char *name, struct Object *ob_src)
|
||||
ATTR_NONNULL(1, 2, 3, 6) ATTR_RETURNS_NONNULL;
|
||||
struct Object *BKE_object_add_for_data(
|
||||
struct Main *bmain, struct ViewLayer *view_layer,
|
||||
int type, const char *name, struct ID *data, bool do_id_user) ATTR_RETURNS_NONNULL;
|
||||
void *BKE_object_obdata_add_from_type(
|
||||
struct Main *bmain,
|
||||
int type, const char *name)
|
||||
|
@ -77,7 +77,8 @@ typedef enum ePaintMode {
|
||||
ePaintTextureProjective = 3,
|
||||
ePaintTexture2D = 4,
|
||||
ePaintSculptUV = 5,
|
||||
ePaintInvalid = 6
|
||||
ePaintInvalid = 6,
|
||||
ePaintGpencil = 7
|
||||
} ePaintMode;
|
||||
|
||||
/* overlay invalidation */
|
||||
|
180
source/blender/blenkernel/BKE_shader_fx.h
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
#ifndef __BKE_SHADER_FX_H__
|
||||
#define __BKE_SHADER_FX_H__
|
||||
|
||||
/** \file BKE_shader_fx.h
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include "DNA_shader_fx_types.h" /* needed for all enum typdefs */
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BKE_customdata.h"
|
||||
|
||||
struct ID;
|
||||
struct Depsgraph;
|
||||
struct DerivedMesh;
|
||||
struct Mesh;
|
||||
struct Object;
|
||||
struct Scene;
|
||||
struct ViewLayer;
|
||||
struct ListBase;
|
||||
struct bArmature;
|
||||
struct Main;
|
||||
struct ShaderFxData;
|
||||
struct DepsNodeHandle;
|
||||
struct bGPDlayer;
|
||||
struct bGPDframe;
|
||||
struct bGPDstroke;
|
||||
struct ModifierUpdateDepsgraphContext;
|
||||
|
||||
#define SHADER_FX_ACTIVE(_fx, _is_render) (((_fx->mode & eShaderFxMode_Realtime) && (_is_render == false)) || \
|
||||
((_fx->mode & eShaderFxMode_Render) && (_is_render == true)))
|
||||
#define SHADER_FX_EDIT(_fx, _is_edit) (((_fx->mode & eShaderFxMode_Editmode) == 0) && (_is_edit))
|
||||
|
||||
typedef enum {
|
||||
/* Should not be used, only for None type */
|
||||
eShaderFxType_NoneType,
|
||||
|
||||
/* grease pencil effects */
|
||||
eShaderFxType_GpencilType,
|
||||
} ShaderFxTypeType;
|
||||
|
||||
typedef enum {
|
||||
eShaderFxTypeFlag_SupportsEditmode = (1 << 0),
|
||||
|
||||
/* For effects that support editmode this determines if the
|
||||
* effect should be enabled by default in editmode.
|
||||
*/
|
||||
eShaderFxTypeFlag_EnableInEditmode = (1 << 2),
|
||||
|
||||
/* max one per type */
|
||||
eShaderFxTypeFlag_Single = (1 << 4),
|
||||
|
||||
/* can't be added manually by user */
|
||||
eShaderFxTypeFlag_NoUserAdd = (1 << 5),
|
||||
} ShaderFxTypeFlag;
|
||||
|
||||
/* IMPORTANT! Keep ObjectWalkFunc and IDWalkFunc signatures compatible. */
|
||||
typedef void(*ShaderFxObjectWalkFunc)(void *userData, struct Object *ob, struct Object **obpoin, int cb_flag);
|
||||
typedef void(*ShaderFxIDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cb_flag);
|
||||
typedef void(*ShaderFxTexWalkFunc)(void *userData, struct Object *ob, struct ShaderFxData *fx, const char *propname);
|
||||
|
||||
typedef struct ShaderFxTypeInfo {
|
||||
/* The user visible name for this effect */
|
||||
char name[32];
|
||||
|
||||
/* The DNA struct name for the effect data type, used to
|
||||
* write the DNA data out.
|
||||
*/
|
||||
char struct_name[32];
|
||||
|
||||
/* The size of the effect data type, used by allocation. */
|
||||
int struct_size;
|
||||
|
||||
ShaderFxTypeType type;
|
||||
ShaderFxTypeFlag flags;
|
||||
|
||||
/* Copy instance data for this effect type. Should copy all user
|
||||
* level settings to the target effect.
|
||||
*/
|
||||
void(*copyData)(const struct ShaderFxData *fx, struct ShaderFxData *target);
|
||||
|
||||
/* Initialize new instance data for this effect type, this function
|
||||
* should set effect variables to their default values.
|
||||
*
|
||||
* This function is optional.
|
||||
*/
|
||||
void (*initData)(struct ShaderFxData *fx);
|
||||
|
||||
/* Free internal effect data variables, this function should
|
||||
* not free the fx variable itself.
|
||||
*
|
||||
* This function is optional.
|
||||
*/
|
||||
void (*freeData)(struct ShaderFxData *fx);
|
||||
|
||||
/* Return a boolean value indicating if this effect is able to be
|
||||
* calculated based on the effect data. This is *not* regarding the
|
||||
* fx->flag, that is tested by the system, this is just if the data
|
||||
* validates (for example, a lattice will return false if the lattice
|
||||
* object is not defined).
|
||||
*
|
||||
* This function is optional (assumes never disabled if not present).
|
||||
*/
|
||||
bool (*isDisabled)(struct ShaderFxData *fx, int userRenderParams);
|
||||
|
||||
/* Add the appropriate relations to the dependency graph.
|
||||
*
|
||||
* This function is optional.
|
||||
*/
|
||||
void (*updateDepsgraph)(struct ShaderFxData *fx,
|
||||
const struct ModifierUpdateDepsgraphContext *ctx);
|
||||
|
||||
/* Should return true if the effect needs to be recalculated on time
|
||||
* changes.
|
||||
*
|
||||
* This function is optional (assumes false if not present).
|
||||
*/
|
||||
bool (*dependsOnTime)(struct ShaderFxData *fx);
|
||||
|
||||
|
||||
/* Should call the given walk function on with a pointer to each Object
|
||||
* pointer that the effect data stores. This is used for linking on file
|
||||
* load and for unlinking objects or forwarding object references.
|
||||
*
|
||||
* This function is optional.
|
||||
*/
|
||||
void (*foreachObjectLink)(struct ShaderFxData *fx, struct Object *ob,
|
||||
ShaderFxObjectWalkFunc walk, void *userData);
|
||||
|
||||
/* Should call the given walk function with a pointer to each ID
|
||||
* pointer (i.e. each datablock pointer) that the effect data
|
||||
* stores. This is used for linking on file load and for
|
||||
* unlinking datablocks or forwarding datablock references.
|
||||
*
|
||||
* This function is optional. If it is not present, foreachObjectLink
|
||||
* will be used.
|
||||
*/
|
||||
void (*foreachIDLink)(struct ShaderFxData *fx, struct Object *ob,
|
||||
ShaderFxIDWalkFunc walk, void *userData);
|
||||
} ShaderFxTypeInfo;
|
||||
|
||||
/* Initialize global data (type info and some common global storages). */
|
||||
void BKE_shaderfx_init(void);
|
||||
|
||||
const ShaderFxTypeInfo *BKE_shaderfxType_getInfo(ShaderFxType type);
|
||||
struct ShaderFxData *BKE_shaderfx_new(int type);
|
||||
void BKE_shaderfx_free_ex(struct ShaderFxData *fx, const int flag);
|
||||
void BKE_shaderfx_free(struct ShaderFxData *fx);
|
||||
bool BKE_shaderfx_unique_name(struct ListBase *shaderfx, struct ShaderFxData *fx);
|
||||
bool BKE_shaderfx_dependsOnTime(struct ShaderFxData *fx);
|
||||
struct ShaderFxData *BKE_shaderfx_findByType(struct Object *ob, ShaderFxType type);
|
||||
struct ShaderFxData *BKE_shaderfx_findByName(struct Object *ob, const char *name);
|
||||
void BKE_shaderfx_copyData_generic(const struct ShaderFxData *fx_src, struct ShaderFxData *fx_dst);
|
||||
void BKE_shaderfx_copyData(struct ShaderFxData *fx, struct ShaderFxData *target);
|
||||
void BKE_shaderfx_copyData_ex(struct ShaderFxData *fx, struct ShaderFxData *target, const int flag);
|
||||
void BKE_shaderfx_foreachIDLink(struct Object *ob, ShaderFxIDWalkFunc walk, void *userData);
|
||||
|
||||
bool BKE_shaderfx_has_gpencil(struct Object *ob);
|
||||
|
||||
#endif /* __BKE_SHADER_FX_H__ */
|
@ -38,6 +38,8 @@ set(INC
|
||||
../makesrna
|
||||
../bmesh
|
||||
../modifiers
|
||||
../gpencil_modifiers
|
||||
../shader_fx
|
||||
../nodes
|
||||
../physics
|
||||
../render/extern/include
|
||||
@ -115,6 +117,7 @@ set(SRC
|
||||
intern/font.c
|
||||
intern/freestyle.c
|
||||
intern/gpencil.c
|
||||
intern/gpencil_modifier.c
|
||||
intern/icons.c
|
||||
intern/icons_rasterize.c
|
||||
intern/idcode.c
|
||||
@ -180,6 +183,7 @@ set(SRC
|
||||
intern/seqeffects.c
|
||||
intern/seqmodifier.c
|
||||
intern/sequencer.c
|
||||
intern/shader_fx.c
|
||||
intern/shrinkwrap.c
|
||||
intern/smoke.c
|
||||
intern/softbody.c
|
||||
@ -259,6 +263,7 @@ set(SRC
|
||||
BKE_freestyle.h
|
||||
BKE_global.h
|
||||
BKE_gpencil.h
|
||||
BKE_gpencil_modifier.h
|
||||
BKE_icons.h
|
||||
BKE_idcode.h
|
||||
BKE_idprop.h
|
||||
@ -306,6 +311,7 @@ set(SRC
|
||||
BKE_scene.h
|
||||
BKE_screen.h
|
||||
BKE_sequencer.h
|
||||
BKE_shader_fx.h
|
||||
BKE_shrinkwrap.h
|
||||
BKE_smoke.h
|
||||
BKE_softbody.h
|
||||
|
@ -104,6 +104,7 @@ bool id_type_can_have_animdata(const short id_type)
|
||||
case ID_MSK:
|
||||
case ID_GD:
|
||||
case ID_CF:
|
||||
case ID_PAL:
|
||||
return true;
|
||||
|
||||
/* no AnimData */
|
||||
@ -1150,6 +1151,9 @@ void BKE_animdata_main_cb(Main *bmain, ID_AnimData_Edit_Callback func, void *use
|
||||
/* grease pencil */
|
||||
ANIMDATA_IDS_CB(bmain->gpencil.first);
|
||||
|
||||
/* palettes */
|
||||
ANIMDATA_IDS_CB(bmain->palettes.first);
|
||||
|
||||
/* cache files */
|
||||
ANIMDATA_IDS_CB(bmain->cachefiles.first);
|
||||
}
|
||||
@ -2925,6 +2929,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, Scene
|
||||
/* grease pencil */
|
||||
EVAL_ANIM_IDS(main->gpencil.first, ADT_RECALC_ANIM);
|
||||
|
||||
/* palettes */
|
||||
EVAL_ANIM_IDS(main->palettes.first, ADT_RECALC_ANIM);
|
||||
|
||||
/* cache files */
|
||||
EVAL_ANIM_IDS(main->cachefiles.first, ADT_RECALC_ANIM);
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "DNA_brush_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_gpencil_types.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_blenlib.h"
|
||||
@ -36,6 +37,7 @@
|
||||
|
||||
#include "BKE_brush.h"
|
||||
#include "BKE_colortools.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_library.h"
|
||||
#include "BKE_library_query.h"
|
||||
@ -129,6 +131,7 @@ static void brush_defaults(Brush *brush)
|
||||
|
||||
brush->stencil_dimension[0] = 256;
|
||||
brush->stencil_dimension[1] = 256;
|
||||
|
||||
}
|
||||
|
||||
/* Datablock add/copy/free/make_local */
|
||||
@ -164,6 +167,368 @@ Brush *BKE_brush_add(Main *bmain, const char *name, const eObjectMode ob_mode)
|
||||
return brush;
|
||||
}
|
||||
|
||||
/* add a new gp-brush */
|
||||
Brush *BKE_brush_add_gpencil(Main *bmain, ToolSettings *ts, const char *name)
|
||||
{
|
||||
Brush *brush;
|
||||
Paint *paint = BKE_brush_get_gpencil_paint(ts);
|
||||
brush = BKE_brush_add(bmain, name, OB_MODE_GPENCIL_PAINT);
|
||||
|
||||
BKE_paint_brush_set(paint, brush);
|
||||
id_us_min(&brush->id);
|
||||
|
||||
/* grease pencil basic settings */
|
||||
brush->size = 3;
|
||||
|
||||
brush->gpencil_settings = MEM_callocN(sizeof(BrushGpencilSettings), "BrushGpencilSettings");
|
||||
|
||||
brush->gpencil_settings->draw_smoothlvl = 1;
|
||||
brush->gpencil_settings->flag = 0;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
|
||||
brush->gpencil_settings->draw_sensitivity = 1.0f;
|
||||
brush->gpencil_settings->draw_strength = 1.0f;
|
||||
brush->gpencil_settings->draw_jitter = 0.0f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
|
||||
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PEN;
|
||||
|
||||
/* curves */
|
||||
brush->gpencil_settings->curve_sensitivity = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
brush->gpencil_settings->curve_strength = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
brush->gpencil_settings->curve_jitter = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
|
||||
/* return brush */
|
||||
return brush;
|
||||
}
|
||||
|
||||
Paint *BKE_brush_get_gpencil_paint(ToolSettings *ts)
|
||||
{
|
||||
/* alloc paint session */
|
||||
if (ts->gp_paint == NULL) {
|
||||
ts->gp_paint = MEM_callocN(sizeof(GpPaint), "GpPaint");
|
||||
}
|
||||
|
||||
return &ts->gp_paint->paint;
|
||||
}
|
||||
|
||||
/* grease pencil cumapping->preset */
|
||||
typedef enum eGPCurveMappingPreset {
|
||||
GPCURVE_PRESET_PENCIL = 0,
|
||||
GPCURVE_PRESET_INK = 1,
|
||||
GPCURVE_PRESET_INKNOISE = 2,
|
||||
} eGPCurveMappingPreset;
|
||||
|
||||
static void brush_gpencil_curvemap_reset(CurveMap *cuma, int preset)
|
||||
{
|
||||
if (cuma->curve)
|
||||
MEM_freeN(cuma->curve);
|
||||
|
||||
cuma->totpoint = 3;
|
||||
cuma->curve = MEM_callocN(cuma->totpoint * sizeof(CurveMapPoint), __func__);
|
||||
|
||||
switch (preset) {
|
||||
case GPCURVE_PRESET_PENCIL:
|
||||
cuma->curve[0].x = 0.0f;
|
||||
cuma->curve[0].y = 0.0f;
|
||||
cuma->curve[1].x = 0.75115f;
|
||||
cuma->curve[1].y = 0.25f;
|
||||
cuma->curve[2].x = 1.0f;
|
||||
cuma->curve[2].y = 1.0f;
|
||||
break;
|
||||
case GPCURVE_PRESET_INK:
|
||||
cuma->curve[0].x = 0.0f;
|
||||
cuma->curve[0].y = 0.0f;
|
||||
cuma->curve[1].x = 0.63448f;
|
||||
cuma->curve[1].y = 0.375f;
|
||||
cuma->curve[2].x = 1.0f;
|
||||
cuma->curve[2].y = 1.0f;
|
||||
break;
|
||||
case GPCURVE_PRESET_INKNOISE:
|
||||
cuma->curve[0].x = 0.0f;
|
||||
cuma->curve[0].y = 0.0f;
|
||||
cuma->curve[1].x = 0.63134f;
|
||||
cuma->curve[1].y = 0.3625f;
|
||||
cuma->curve[2].x = 1.0f;
|
||||
cuma->curve[2].y = 1.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cuma->table) {
|
||||
MEM_freeN(cuma->table);
|
||||
cuma->table = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* create a set of grease pencil presets */
|
||||
void BKE_brush_gpencil_presets(bContext *C)
|
||||
{
|
||||
#define SMOOTH_STROKE_RADIUS 40
|
||||
#define SMOOTH_STROKE_FACTOR 0.9f
|
||||
|
||||
ToolSettings *ts = CTX_data_tool_settings(C);
|
||||
Paint *paint = BKE_brush_get_gpencil_paint(ts);
|
||||
Main *bmain = CTX_data_main(C);
|
||||
|
||||
Brush *brush, *deft;
|
||||
CurveMapping *custom_curve;
|
||||
|
||||
/* Pencil brush */
|
||||
brush = BKE_brush_add_gpencil(bmain, ts, "Draw Pencil");
|
||||
brush->size = 25.0f;
|
||||
brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR);
|
||||
brush->gpencil_settings->draw_sensitivity = 1.0f;
|
||||
|
||||
brush->gpencil_settings->draw_strength = 0.6f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
|
||||
|
||||
brush->gpencil_settings->draw_random_press = 0.0f;
|
||||
|
||||
brush->gpencil_settings->draw_jitter = 0.0f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
|
||||
|
||||
brush->gpencil_settings->draw_angle = 0.0f;
|
||||
brush->gpencil_settings->draw_angle_factor = 0.0f;
|
||||
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
|
||||
brush->gpencil_settings->draw_smoothfac = 0.5f;
|
||||
brush->gpencil_settings->draw_smoothlvl = 1;
|
||||
brush->gpencil_settings->thick_smoothfac = 1.0f;
|
||||
brush->gpencil_settings->thick_smoothlvl = 3;
|
||||
brush->gpencil_settings->draw_subdivide = 1;
|
||||
brush->gpencil_settings->draw_random_sub = 0.0f;
|
||||
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PENCIL;
|
||||
brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW;
|
||||
|
||||
brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
|
||||
brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
|
||||
|
||||
/* Pen brush */
|
||||
brush = BKE_brush_add_gpencil(bmain, ts, "Draw Pen");
|
||||
deft = brush; /* save default brush */
|
||||
brush->size = 30.0f;
|
||||
brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR);
|
||||
brush->gpencil_settings->draw_sensitivity = 1.0f;
|
||||
|
||||
brush->gpencil_settings->draw_strength = 1.0f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
|
||||
|
||||
brush->gpencil_settings->draw_random_press = 0.0f;
|
||||
brush->gpencil_settings->draw_random_strength = 0.0f;
|
||||
|
||||
brush->gpencil_settings->draw_jitter = 0.0f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
|
||||
|
||||
brush->gpencil_settings->draw_angle = 0.0f;
|
||||
brush->gpencil_settings->draw_angle_factor = 0.0f;
|
||||
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
|
||||
brush->gpencil_settings->draw_smoothfac = 0.5f;
|
||||
brush->gpencil_settings->draw_smoothlvl = 1;
|
||||
brush->gpencil_settings->draw_subdivide = 1;
|
||||
brush->gpencil_settings->thick_smoothfac = 1.0f;
|
||||
brush->gpencil_settings->thick_smoothlvl = 3;
|
||||
brush->gpencil_settings->draw_random_sub = 0.0f;
|
||||
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PEN;
|
||||
brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW;
|
||||
|
||||
brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
|
||||
brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
|
||||
|
||||
/* Ink brush */
|
||||
brush = BKE_brush_add_gpencil(bmain, ts, "Draw Ink");
|
||||
brush->size = 60.0f;
|
||||
brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR);
|
||||
brush->gpencil_settings->draw_sensitivity = 1.6f;
|
||||
|
||||
brush->gpencil_settings->draw_strength = 1.0f;
|
||||
|
||||
brush->gpencil_settings->draw_random_press = 0.0f;
|
||||
|
||||
brush->gpencil_settings->draw_jitter = 0.0f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
|
||||
|
||||
brush->gpencil_settings->draw_angle = 0.0f;
|
||||
brush->gpencil_settings->draw_angle_factor = 0.0f;
|
||||
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
|
||||
brush->gpencil_settings->draw_smoothfac = 0.5f;
|
||||
brush->gpencil_settings->draw_smoothlvl = 1;
|
||||
brush->gpencil_settings->thick_smoothfac = 1.0f;
|
||||
brush->gpencil_settings->thick_smoothlvl = 3;
|
||||
brush->gpencil_settings->draw_subdivide = 1;
|
||||
brush->gpencil_settings->draw_random_sub = 0.0f;
|
||||
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_INK;
|
||||
brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW;
|
||||
|
||||
brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
|
||||
brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
|
||||
|
||||
/* Curve */
|
||||
custom_curve = brush->gpencil_settings->curve_sensitivity;
|
||||
curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
curvemapping_initialize(custom_curve);
|
||||
brush_gpencil_curvemap_reset(custom_curve->cm, GPCURVE_PRESET_INK);
|
||||
|
||||
/* Ink Noise brush */
|
||||
brush = BKE_brush_add_gpencil(bmain, ts, "Draw Noise");
|
||||
brush->size = 60.0f;
|
||||
brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR);
|
||||
brush->gpencil_settings->draw_sensitivity = 1.0f;
|
||||
|
||||
brush->gpencil_settings->draw_strength = 1.0f;
|
||||
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_GROUP_RANDOM;
|
||||
brush->gpencil_settings->draw_random_press = 0.7f;
|
||||
brush->gpencil_settings->draw_random_strength = 0.0f;
|
||||
|
||||
brush->gpencil_settings->draw_jitter = 0.0f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
|
||||
|
||||
brush->gpencil_settings->draw_angle = 0.0f;
|
||||
brush->gpencil_settings->draw_angle_factor = 0.0f;
|
||||
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
|
||||
brush->gpencil_settings->draw_smoothfac = 1.0f;
|
||||
brush->gpencil_settings->draw_smoothlvl = 2;
|
||||
brush->gpencil_settings->thick_smoothfac = 0.5f;
|
||||
brush->gpencil_settings->thick_smoothlvl = 2;
|
||||
brush->gpencil_settings->draw_subdivide = 1;
|
||||
brush->gpencil_settings->draw_random_sub = 0.0f;
|
||||
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_INKNOISE;
|
||||
brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW;
|
||||
|
||||
brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
|
||||
brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
|
||||
|
||||
/* Curve */
|
||||
custom_curve = brush->gpencil_settings->curve_sensitivity;
|
||||
curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
curvemapping_initialize(custom_curve);
|
||||
brush_gpencil_curvemap_reset(custom_curve->cm, GPCURVE_PRESET_INKNOISE);
|
||||
|
||||
/* Block Basic brush */
|
||||
brush = BKE_brush_add_gpencil(bmain, ts, "Draw Block");
|
||||
brush->size = 150.0f;
|
||||
brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR);
|
||||
brush->gpencil_settings->draw_sensitivity = 1.0f;
|
||||
|
||||
brush->gpencil_settings->draw_strength = 0.7f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
|
||||
|
||||
brush->gpencil_settings->draw_random_press = 0.0f;
|
||||
|
||||
brush->gpencil_settings->draw_jitter = 0.0f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
|
||||
|
||||
brush->gpencil_settings->draw_angle = 0.0f;
|
||||
brush->gpencil_settings->draw_angle_factor = 0.0f;
|
||||
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
|
||||
brush->gpencil_settings->draw_smoothfac = 0.0f;
|
||||
brush->gpencil_settings->draw_smoothlvl = 1;
|
||||
brush->gpencil_settings->thick_smoothfac = 1.0f;
|
||||
brush->gpencil_settings->thick_smoothlvl = 3;
|
||||
brush->gpencil_settings->draw_subdivide = 0;
|
||||
brush->gpencil_settings->draw_random_sub = 0;
|
||||
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_BLOCK;
|
||||
brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW;
|
||||
|
||||
brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
|
||||
brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
|
||||
|
||||
/* Marker brush */
|
||||
brush = BKE_brush_add_gpencil(bmain, ts, "Draw Marker");
|
||||
brush->size = 80.0f;
|
||||
brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR);
|
||||
brush->gpencil_settings->draw_sensitivity = 1.0f;
|
||||
|
||||
brush->gpencil_settings->draw_strength = 1.0f;
|
||||
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_GROUP_RANDOM;
|
||||
brush->gpencil_settings->draw_random_press = 0.374f;
|
||||
brush->gpencil_settings->draw_random_strength = 0.0f;
|
||||
|
||||
brush->gpencil_settings->draw_jitter = 0.0f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
|
||||
|
||||
brush->gpencil_settings->draw_angle = M_PI_4; /* 45 degrees */
|
||||
brush->gpencil_settings->draw_angle_factor = 1.0f;
|
||||
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
|
||||
brush->gpencil_settings->draw_smoothfac = 0.5f;
|
||||
brush->gpencil_settings->draw_smoothlvl = 1;
|
||||
brush->gpencil_settings->thick_smoothfac = 1.0f;
|
||||
brush->gpencil_settings->thick_smoothlvl = 3;
|
||||
brush->gpencil_settings->draw_subdivide = 1;
|
||||
brush->gpencil_settings->draw_random_sub = 0.0f;
|
||||
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_MARKER;
|
||||
brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW;
|
||||
|
||||
brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
|
||||
brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
|
||||
|
||||
/* Fill brush */
|
||||
brush = BKE_brush_add_gpencil(bmain, ts, "Fill Area");
|
||||
brush->size = 1.0f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_ENABLE_CURSOR;
|
||||
brush->gpencil_settings->draw_sensitivity = 1.0f;
|
||||
brush->gpencil_settings->fill_leak = 3;
|
||||
brush->gpencil_settings->fill_threshold = 0.1f;
|
||||
brush->gpencil_settings->fill_simplylvl = 1;
|
||||
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_FILL;
|
||||
brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_FILL;
|
||||
|
||||
brush->gpencil_settings->draw_smoothfac = 0.5f;
|
||||
brush->gpencil_settings->draw_smoothlvl = 1;
|
||||
brush->gpencil_settings->thick_smoothfac = 1.0f;
|
||||
brush->gpencil_settings->thick_smoothlvl = 3;
|
||||
brush->gpencil_settings->draw_subdivide = 1;
|
||||
|
||||
brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
|
||||
brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
|
||||
|
||||
brush->gpencil_settings->draw_strength = 1.0f;
|
||||
|
||||
/* Soft Eraser brush */
|
||||
brush = BKE_brush_add_gpencil(bmain, ts, "Eraser Soft");
|
||||
brush->size = 30.0f;
|
||||
brush->gpencil_settings->flag |= (GP_BRUSH_ENABLE_CURSOR | GP_BRUSH_DEFAULT_ERASER);
|
||||
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_SOFT;
|
||||
brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_ERASE;
|
||||
brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_SOFT;
|
||||
|
||||
/* Hard Eraser brush */
|
||||
brush = BKE_brush_add_gpencil(bmain, ts, "Eraser Hard");
|
||||
brush->size = 30.0f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_ENABLE_CURSOR;
|
||||
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_HARD;
|
||||
brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_ERASE;
|
||||
brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_HARD;
|
||||
|
||||
/* Stroke Eraser brush */
|
||||
brush = BKE_brush_add_gpencil(bmain, ts, "Eraser Stroke");
|
||||
brush->size = 30.0f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_ENABLE_CURSOR;
|
||||
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_STROKE;
|
||||
brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_ERASE;
|
||||
brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_STROKE;
|
||||
|
||||
/* set defaut brush */
|
||||
BKE_paint_brush_set(paint, deft);
|
||||
|
||||
}
|
||||
|
||||
/* get the active gp-brush for editing */
|
||||
Brush *BKE_brush_getactive_gpencil(ToolSettings *ts)
|
||||
{
|
||||
/* error checking */
|
||||
if (ELEM(NULL, ts, ts->gp_paint)) {
|
||||
return NULL;
|
||||
}
|
||||
Paint *paint = &ts->gp_paint->paint;
|
||||
|
||||
return paint->brush;
|
||||
}
|
||||
|
||||
struct Brush *BKE_brush_first_search(struct Main *bmain, const eObjectMode ob_mode)
|
||||
{
|
||||
Brush *brush;
|
||||
@ -197,6 +562,12 @@ void BKE_brush_copy_data(Main *UNUSED(bmain), Brush *brush_dst, const Brush *bru
|
||||
}
|
||||
|
||||
brush_dst->curve = curvemapping_copy(brush_src->curve);
|
||||
if (brush_src->gpencil_settings != NULL) {
|
||||
brush_dst->gpencil_settings = MEM_dupallocN(brush_src->gpencil_settings);
|
||||
brush_dst->gpencil_settings->curve_sensitivity = curvemapping_copy(brush_src->gpencil_settings->curve_sensitivity);
|
||||
brush_dst->gpencil_settings->curve_strength = curvemapping_copy(brush_src->gpencil_settings->curve_strength);
|
||||
brush_dst->gpencil_settings->curve_jitter = curvemapping_copy(brush_src->gpencil_settings->curve_jitter);
|
||||
}
|
||||
|
||||
/* enable fake user by default */
|
||||
id_fake_user_set(&brush_dst->id);
|
||||
@ -215,11 +586,18 @@ void BKE_brush_free(Brush *brush)
|
||||
if (brush->icon_imbuf) {
|
||||
IMB_freeImBuf(brush->icon_imbuf);
|
||||
}
|
||||
|
||||
curvemapping_free(brush->curve);
|
||||
|
||||
if (brush->gpencil_settings != NULL) {
|
||||
curvemapping_free(brush->gpencil_settings->curve_sensitivity);
|
||||
curvemapping_free(brush->gpencil_settings->curve_strength);
|
||||
curvemapping_free(brush->gpencil_settings->curve_jitter);
|
||||
MEM_SAFE_FREE(brush->gpencil_settings);
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(brush->gradient);
|
||||
|
||||
|
||||
BKE_previewimg_free(&(brush->preview));
|
||||
}
|
||||
|
||||
|
@ -282,6 +282,7 @@ void curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope)
|
||||
case CURVE_PRESET_MID9: cuma->totpoint = 9; break;
|
||||
case CURVE_PRESET_ROUND: cuma->totpoint = 4; break;
|
||||
case CURVE_PRESET_ROOT: cuma->totpoint = 4; break;
|
||||
case CURVE_PRESET_GAUSS: cuma->totpoint = 7; break;
|
||||
}
|
||||
|
||||
cuma->curve = MEM_callocN(cuma->totpoint * sizeof(CurveMapPoint), "curve points");
|
||||
@ -352,6 +353,24 @@ void curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope)
|
||||
cuma->curve[3].x = 1;
|
||||
cuma->curve[3].y = 0;
|
||||
break;
|
||||
case CURVE_PRESET_GAUSS:
|
||||
cuma->curve[0].x = 0;
|
||||
cuma->curve[0].y = 0.025f;
|
||||
cuma->curve[1].x = 0.16f;
|
||||
cuma->curve[1].y = 0.135f;
|
||||
cuma->curve[2].x = 0.298f;
|
||||
cuma->curve[2].y = 0.36f;
|
||||
|
||||
cuma->curve[3].x = 0.50f;
|
||||
cuma->curve[3].y = 1.0f;
|
||||
|
||||
cuma->curve[4].x = 0.70f;
|
||||
cuma->curve[4].y = 0.36f;
|
||||
cuma->curve[5].x = 0.84f;
|
||||
cuma->curve[5].y = 0.135f;
|
||||
cuma->curve[6].x = 1.0f;
|
||||
cuma->curve[6].y = 0.025f;
|
||||
break;
|
||||
}
|
||||
|
||||
/* mirror curve in x direction to have positive slope
|
||||
|
@ -1014,6 +1014,10 @@ int CTX_data_mode_enum_ex(const Object *obedit, const Object *ob, const eObjectM
|
||||
else if (object_mode & OB_MODE_VERTEX_PAINT) return CTX_MODE_PAINT_VERTEX;
|
||||
else if (object_mode & OB_MODE_TEXTURE_PAINT) return CTX_MODE_PAINT_TEXTURE;
|
||||
else if (object_mode & OB_MODE_PARTICLE_EDIT) return CTX_MODE_PARTICLE;
|
||||
else if (object_mode & OB_MODE_GPENCIL_PAINT) return CTX_MODE_GPENCIL_PAINT;
|
||||
else if (object_mode & OB_MODE_GPENCIL_EDIT) return CTX_MODE_GPENCIL_EDIT;
|
||||
else if (object_mode & OB_MODE_GPENCIL_SCULPT) return CTX_MODE_GPENCIL_SCULPT;
|
||||
else if (object_mode & OB_MODE_GPENCIL_WEIGHT) return CTX_MODE_GPENCIL_WEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1044,6 +1048,10 @@ static const char *data_mode_strings[] = {
|
||||
"imagepaint",
|
||||
"particlemode",
|
||||
"objectmode",
|
||||
"greasepencil_paint",
|
||||
"greasepencil_edit",
|
||||
"greasepencil_sculpt",
|
||||
"greasepencil_weight",
|
||||
NULL
|
||||
};
|
||||
BLI_STATIC_ASSERT(ARRAY_SIZE(data_mode_strings) == CTX_MODE_NUM + 1, "Must have a string for each context mode")
|
||||
@ -1212,17 +1220,7 @@ bGPDlayer *CTX_data_active_gpencil_layer(const bContext *C)
|
||||
return ctx_data_pointer_get(C, "active_gpencil_layer");
|
||||
}
|
||||
|
||||
bGPDpalette *CTX_data_active_gpencil_palette(const bContext *C)
|
||||
{
|
||||
return ctx_data_pointer_get(C, "active_gpencil_palette");
|
||||
}
|
||||
|
||||
bGPDpalettecolor *CTX_data_active_gpencil_palettecolor(const bContext *C)
|
||||
{
|
||||
return ctx_data_pointer_get(C, "active_gpencil_palettecolor");
|
||||
}
|
||||
|
||||
bGPDbrush *CTX_data_active_gpencil_brush(const bContext *C)
|
||||
Brush *CTX_data_active_gpencil_brush(const bContext *C)
|
||||
{
|
||||
return ctx_data_pointer_get(C, "active_gpencil_brush");
|
||||
}
|
||||
|
@ -74,7 +74,9 @@ bDeformGroup *BKE_defgroup_new(Object *ob, const char *name)
|
||||
BLI_addtail(&ob->defbase, defgroup);
|
||||
defgroup_unique_name(defgroup, ob);
|
||||
|
||||
BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
|
||||
if (ob->type != OB_GPENCIL) {
|
||||
BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
|
||||
}
|
||||
|
||||
return defgroup;
|
||||
}
|
||||
|
679
source/blender/blenkernel/intern/gpencil_modifier.c
Normal file
@ -0,0 +1,679 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2017, Blender Foundation
|
||||
* This is a new part of Blender
|
||||
*
|
||||
* Contributor(s): Antonio Vazquez
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/blenkernel/intern/gpencil_modifier.c
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_string_utils.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_gpencil_types.h"
|
||||
#include "DNA_gpencil_modifier_types.h"
|
||||
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_library.h"
|
||||
#include "BKE_library_query.h"
|
||||
#include "BKE_gpencil.h"
|
||||
#include "BKE_lattice.h"
|
||||
#include "BKE_gpencil_modifier.h"
|
||||
#include "BKE_object.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "MOD_gpencil_modifiertypes.h"
|
||||
|
||||
static GpencilModifierTypeInfo *modifier_gpencil_types[NUM_GREASEPENCIL_MODIFIER_TYPES] = { NULL };
|
||||
|
||||
/* *************************************************** */
|
||||
/* Geometry Utilities */
|
||||
|
||||
/* calculate stroke normal using some points */
|
||||
void BKE_gpencil_stroke_normal(const bGPDstroke *gps, float r_normal[3])
|
||||
{
|
||||
if (gps->totpoints < 3) {
|
||||
zero_v3(r_normal);
|
||||
return;
|
||||
}
|
||||
|
||||
bGPDspoint *points = gps->points;
|
||||
int totpoints = gps->totpoints;
|
||||
|
||||
const bGPDspoint *pt0 = &points[0];
|
||||
const bGPDspoint *pt1 = &points[1];
|
||||
const bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)];
|
||||
|
||||
float vec1[3];
|
||||
float vec2[3];
|
||||
|
||||
/* initial vector (p0 -> p1) */
|
||||
sub_v3_v3v3(vec1, &pt1->x, &pt0->x);
|
||||
|
||||
/* point vector at 3/4 */
|
||||
sub_v3_v3v3(vec2, &pt3->x, &pt0->x);
|
||||
|
||||
/* vector orthogonal to polygon plane */
|
||||
cross_v3_v3v3(r_normal, vec1, vec2);
|
||||
|
||||
/* Normalize vector */
|
||||
normalize_v3(r_normal);
|
||||
}
|
||||
|
||||
/* Get points of stroke always flat to view not affected by camera view or view position */
|
||||
static void gpencil_stroke_project_2d(const bGPDspoint *points, int totpoints, vec2f *points2d)
|
||||
{
|
||||
const bGPDspoint *pt0 = &points[0];
|
||||
const bGPDspoint *pt1 = &points[1];
|
||||
const bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)];
|
||||
|
||||
float locx[3];
|
||||
float locy[3];
|
||||
float loc3[3];
|
||||
float normal[3];
|
||||
|
||||
/* local X axis (p0 -> p1) */
|
||||
sub_v3_v3v3(locx, &pt1->x, &pt0->x);
|
||||
|
||||
/* point vector at 3/4 */
|
||||
sub_v3_v3v3(loc3, &pt3->x, &pt0->x);
|
||||
|
||||
/* vector orthogonal to polygon plane */
|
||||
cross_v3_v3v3(normal, locx, loc3);
|
||||
|
||||
/* local Y axis (cross to normal/x axis) */
|
||||
cross_v3_v3v3(locy, normal, locx);
|
||||
|
||||
/* Normalize vectors */
|
||||
normalize_v3(locx);
|
||||
normalize_v3(locy);
|
||||
|
||||
/* Get all points in local space */
|
||||
for (int i = 0; i < totpoints; i++) {
|
||||
const bGPDspoint *pt = &points[i];
|
||||
float loc[3];
|
||||
|
||||
/* Get local space using first point as origin */
|
||||
sub_v3_v3v3(loc, &pt->x, &pt0->x);
|
||||
|
||||
vec2f *point = &points2d[i];
|
||||
point->x = dot_v3v3(loc, locx);
|
||||
point->y = dot_v3v3(loc, locy);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Stroke Simplify ------------------------------------- */
|
||||
|
||||
/* Reduce a series of points to a simplified version, but
|
||||
* maintains the general shape of the series
|
||||
*
|
||||
* Ramer - Douglas - Peucker algorithm
|
||||
* by http ://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
|
||||
*/
|
||||
static void gpencil_rdp_stroke(bGPDstroke *gps, vec2f *points2d, float epsilon)
|
||||
{
|
||||
vec2f *old_points2d = points2d;
|
||||
int totpoints = gps->totpoints;
|
||||
char *marked = NULL;
|
||||
char work;
|
||||
|
||||
int start = 1;
|
||||
int end = gps->totpoints - 2;
|
||||
|
||||
marked = MEM_callocN(totpoints, "GP marked array");
|
||||
marked[start] = 1;
|
||||
marked[end] = 1;
|
||||
|
||||
work = 1;
|
||||
int totmarked = 0;
|
||||
/* while still reducing */
|
||||
while (work) {
|
||||
int ls, le;
|
||||
work = 0;
|
||||
|
||||
ls = start;
|
||||
le = start + 1;
|
||||
|
||||
/* while not over interval */
|
||||
while (ls < end) {
|
||||
int max_i = 0;
|
||||
float v1[2];
|
||||
/* divided to get more control */
|
||||
float max_dist = epsilon / 10.0f;
|
||||
|
||||
/* find the next marked point */
|
||||
while (marked[le] == 0) {
|
||||
le++;
|
||||
}
|
||||
|
||||
/* perpendicular vector to ls-le */
|
||||
v1[1] = old_points2d[le].x - old_points2d[ls].x;
|
||||
v1[0] = old_points2d[ls].y - old_points2d[le].y;
|
||||
|
||||
for (int i = ls + 1; i < le; i++) {
|
||||
float mul;
|
||||
float dist;
|
||||
float v2[2];
|
||||
|
||||
v2[0] = old_points2d[i].x - old_points2d[ls].x;
|
||||
v2[1] = old_points2d[i].y - old_points2d[ls].y;
|
||||
|
||||
if (v2[0] == 0 && v2[1] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mul = (float)(v1[0] * v2[0] + v1[1] * v2[1]) / (float)(v2[0] * v2[0] + v2[1] * v2[1]);
|
||||
|
||||
dist = mul * mul * (v2[0] * v2[0] + v2[1] * v2[1]);
|
||||
|
||||
if (dist > max_dist) {
|
||||
max_dist = dist;
|
||||
max_i = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (max_i != 0) {
|
||||
work = 1;
|
||||
marked[max_i] = 1;
|
||||
totmarked++;
|
||||
}
|
||||
|
||||
ls = le;
|
||||
le = ls + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* adding points marked */
|
||||
bGPDspoint *old_points = MEM_dupallocN(gps->points);
|
||||
MDeformVert *old_dvert = MEM_dupallocN(gps->dvert);
|
||||
|
||||
/* resize gps */
|
||||
gps->flag |= GP_STROKE_RECALC_CACHES;
|
||||
gps->tot_triangles = 0;
|
||||
|
||||
int j = 0;
|
||||
for (int i = 0; i < totpoints; i++) {
|
||||
bGPDspoint *pt_src = &old_points[i];
|
||||
bGPDspoint *pt = &gps->points[j];
|
||||
|
||||
MDeformVert *dvert_src = &old_dvert[i];
|
||||
MDeformVert *dvert = &gps->dvert[j];
|
||||
|
||||
if ((marked[i]) || (i == 0) || (i == totpoints - 1)) {
|
||||
memcpy(pt, pt_src, sizeof(bGPDspoint));
|
||||
memcpy(dvert, dvert_src, sizeof(MDeformVert));
|
||||
j++;
|
||||
}
|
||||
else {
|
||||
BKE_gpencil_free_point_weights(dvert_src);
|
||||
}
|
||||
}
|
||||
|
||||
gps->totpoints = j;
|
||||
|
||||
MEM_SAFE_FREE(old_points);
|
||||
MEM_SAFE_FREE(old_dvert);
|
||||
MEM_SAFE_FREE(marked);
|
||||
}
|
||||
|
||||
/* Simplify stroke using Ramer-Douglas-Peucker algorithm */
|
||||
void BKE_gpencil_simplify_stroke(bGPDstroke *gps, float factor)
|
||||
{
|
||||
/* first create temp data and convert points to 2D */
|
||||
vec2f *points2d = MEM_mallocN(sizeof(vec2f) * gps->totpoints, "GP Stroke temp 2d points");
|
||||
|
||||
gpencil_stroke_project_2d(gps->points, gps->totpoints, points2d);
|
||||
|
||||
gpencil_rdp_stroke(gps, points2d, factor);
|
||||
|
||||
MEM_SAFE_FREE(points2d);
|
||||
}
|
||||
|
||||
/* Simplify alternate vertex of stroke except extrems */
|
||||
void BKE_gpencil_simplify_fixed(bGPDstroke *gps)
|
||||
{
|
||||
if (gps->totpoints < 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* save points */
|
||||
bGPDspoint *old_points = MEM_dupallocN(gps->points);
|
||||
MDeformVert *old_dvert = MEM_dupallocN(gps->dvert);
|
||||
|
||||
/* resize gps */
|
||||
int newtot = (gps->totpoints - 2) / 2;
|
||||
if (((gps->totpoints - 2) % 2) > 0) {
|
||||
newtot++;
|
||||
}
|
||||
newtot += 2;
|
||||
|
||||
gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * newtot);
|
||||
gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot);
|
||||
gps->flag |= GP_STROKE_RECALC_CACHES;
|
||||
gps->tot_triangles = 0;
|
||||
|
||||
int j = 0;
|
||||
for (int i = 0; i < gps->totpoints; i++) {
|
||||
bGPDspoint *pt_src = &old_points[i];
|
||||
bGPDspoint *pt = &gps->points[j];
|
||||
|
||||
MDeformVert *dvert_src = &old_dvert[i];
|
||||
MDeformVert *dvert = &gps->dvert[j];
|
||||
|
||||
if ((i == 0) || (i == gps->totpoints - 1) || ((i % 2) > 0.0)) {
|
||||
memcpy(pt, pt_src, sizeof(bGPDspoint));
|
||||
memcpy(dvert, dvert_src, sizeof(MDeformVert));
|
||||
j++;
|
||||
}
|
||||
else {
|
||||
BKE_gpencil_free_point_weights(dvert_src);
|
||||
}
|
||||
}
|
||||
|
||||
gps->totpoints = j;
|
||||
|
||||
MEM_SAFE_FREE(old_points);
|
||||
MEM_SAFE_FREE(old_dvert);
|
||||
}
|
||||
|
||||
/* *************************************************** */
|
||||
/* Modifier Utilities */
|
||||
|
||||
/* Lattice Modifier ---------------------------------- */
|
||||
/* Usually, evaluation of the lattice modifier is self-contained.
|
||||
* However, since GP's modifiers operate on a per-stroke basis,
|
||||
* we need to these two extra functions that called before/after
|
||||
* each loop over all the geometry being evaluated.
|
||||
*/
|
||||
|
||||
/* init lattice deform data */
|
||||
void BKE_gpencil_lattice_init(Object *ob)
|
||||
{
|
||||
GpencilModifierData *md;
|
||||
for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
|
||||
if (md->type == eGpencilModifierType_Lattice) {
|
||||
LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md;
|
||||
Object *latob = NULL;
|
||||
|
||||
latob = mmd->object;
|
||||
if ((!latob) || (latob->type != OB_LATTICE)) {
|
||||
return;
|
||||
}
|
||||
if (mmd->cache_data) {
|
||||
end_latt_deform((struct LatticeDeformData *)mmd->cache_data);
|
||||
}
|
||||
|
||||
/* init deform data */
|
||||
mmd->cache_data = (struct LatticeDeformData *)init_latt_deform(latob, ob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* clear lattice deform data */
|
||||
void BKE_gpencil_lattice_clear(Object *ob)
|
||||
{
|
||||
GpencilModifierData *md;
|
||||
for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
|
||||
if (md->type == eGpencilModifierType_Lattice) {
|
||||
LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md;
|
||||
if ((mmd) && (mmd->cache_data)) {
|
||||
end_latt_deform((struct LatticeDeformData *)mmd->cache_data);
|
||||
mmd->cache_data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* *************************************************** */
|
||||
/* Modifier Methods - Evaluation Loops, etc. */
|
||||
|
||||
/* check if exist geometry modifiers */
|
||||
bool BKE_gpencil_has_geometry_modifiers(Object *ob)
|
||||
{
|
||||
GpencilModifierData *md;
|
||||
for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
|
||||
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
|
||||
|
||||
if (mti && mti->generateStrokes) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* apply stroke modifiers */
|
||||
void BKE_gpencil_stroke_modifiers(Depsgraph *depsgraph, Object *ob, bGPDlayer *gpl, bGPDframe *UNUSED(gpf), bGPDstroke *gps, bool is_render)
|
||||
{
|
||||
GpencilModifierData *md;
|
||||
bGPdata *gpd = ob->data;
|
||||
const bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd);
|
||||
|
||||
for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
|
||||
if (GPENCIL_MODIFIER_ACTIVE(md, is_render))
|
||||
{
|
||||
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
|
||||
|
||||
if (GPENCIL_MODIFIER_EDIT(md, is_edit)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mti && mti->deformStroke) {
|
||||
mti->deformStroke(md, depsgraph, ob, gpl, gps);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* apply stroke geometry modifiers */
|
||||
void BKE_gpencil_geometry_modifiers(Depsgraph *depsgraph, Object *ob, bGPDlayer *gpl, bGPDframe *gpf, bool is_render)
|
||||
{
|
||||
GpencilModifierData *md;
|
||||
bGPdata *gpd = ob->data;
|
||||
const bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd);
|
||||
|
||||
for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
|
||||
if (GPENCIL_MODIFIER_ACTIVE(md, is_render))
|
||||
{
|
||||
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
|
||||
|
||||
if (GPENCIL_MODIFIER_EDIT(md, is_edit)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mti->generateStrokes) {
|
||||
mti->generateStrokes(md, depsgraph, ob, gpl, gpf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* *************************************************** */
|
||||
|
||||
void BKE_gpencil_eval_geometry(Depsgraph *depsgraph,
|
||||
bGPdata *gpd)
|
||||
{
|
||||
DEG_debug_print_eval(depsgraph, __func__, gpd->id.name, gpd);
|
||||
int ctime = (int)DEG_get_ctime(depsgraph);
|
||||
|
||||
/* update active frame */
|
||||
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
|
||||
gpl->actframe = BKE_gpencil_layer_getframe(gpl, ctime, GP_GETFRAME_USE_PREV);
|
||||
}
|
||||
|
||||
/* TODO: Move "derived_gpf" logic here from DRW_gpencil_populate_datablock()?
|
||||
* This would be better than inventing our own logic for this stuff...
|
||||
*/
|
||||
|
||||
/* TODO: Move the following code to "BKE_gpencil_eval_done()" (marked as an exit node)
|
||||
* later when there's more happening here. For now, let's just keep this in here to avoid
|
||||
* needing to have one more node slowing down evaluation...
|
||||
*/
|
||||
if (DEG_is_active(depsgraph)) {
|
||||
bGPdata *gpd_orig = (bGPdata *)DEG_get_original_id(&gpd->id);
|
||||
|
||||
/* sync "actframe" changes back to main-db too,
|
||||
* so that editing tools work with copy-on-write
|
||||
* when the current frame changes
|
||||
*/
|
||||
for (bGPDlayer *gpl = gpd_orig->layers.first; gpl; gpl = gpl->next) {
|
||||
gpl->actframe = BKE_gpencil_layer_getframe(gpl, ctime, GP_GETFRAME_USE_PREV);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_gpencil_modifier_init(void)
|
||||
{
|
||||
/* Initialize modifier types */
|
||||
gpencil_modifier_type_init(modifier_gpencil_types); /* MOD_gpencil_util.c */
|
||||
}
|
||||
|
||||
GpencilModifierData *BKE_gpencil_modifier_new(int type)
|
||||
{
|
||||
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(type);
|
||||
GpencilModifierData *md = MEM_callocN(mti->struct_size, mti->struct_name);
|
||||
|
||||
/* note, this name must be made unique later */
|
||||
BLI_strncpy(md->name, DATA_(mti->name), sizeof(md->name));
|
||||
|
||||
md->type = type;
|
||||
md->mode = eGpencilModifierMode_Realtime | eGpencilModifierMode_Render | eGpencilModifierMode_Expanded;
|
||||
md->flag = eGpencilModifierFlag_StaticOverride_Local;
|
||||
|
||||
if (mti->flags & eGpencilModifierTypeFlag_EnableInEditmode)
|
||||
md->mode |= eGpencilModifierMode_Editmode;
|
||||
|
||||
if (mti->initData) mti->initData(md);
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
static void modifier_free_data_id_us_cb(void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin, int cb_flag)
|
||||
{
|
||||
ID *id = *idpoin;
|
||||
if (id != NULL && (cb_flag & IDWALK_CB_USER) != 0) {
|
||||
id_us_min(id);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_gpencil_modifier_free_ex(GpencilModifierData *md, const int flag)
|
||||
{
|
||||
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
|
||||
|
||||
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
|
||||
if (mti->foreachIDLink) {
|
||||
mti->foreachIDLink(md, NULL, modifier_free_data_id_us_cb, NULL);
|
||||
}
|
||||
else if (mti->foreachObjectLink) {
|
||||
mti->foreachObjectLink(md, NULL, (GreasePencilObjectWalkFunc)modifier_free_data_id_us_cb, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (mti->freeData) mti->freeData(md);
|
||||
if (md->error) MEM_freeN(md->error);
|
||||
|
||||
MEM_freeN(md);
|
||||
}
|
||||
|
||||
void BKE_gpencil_modifier_free(GpencilModifierData *md)
|
||||
{
|
||||
BKE_gpencil_modifier_free_ex(md, 0);
|
||||
}
|
||||
|
||||
/* check unique name */
|
||||
bool BKE_gpencil_modifier_unique_name(ListBase *modifiers, GpencilModifierData *gmd)
|
||||
{
|
||||
if (modifiers && gmd) {
|
||||
const GpencilModifierTypeInfo *gmti = BKE_gpencil_modifierType_getInfo(gmd->type);
|
||||
return BLI_uniquename(modifiers, gmd, DATA_(gmti->name), '.', offsetof(GpencilModifierData, name), sizeof(gmd->name));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BKE_gpencil_modifier_dependsOnTime(GpencilModifierData *md)
|
||||
{
|
||||
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
|
||||
|
||||
return mti->dependsOnTime && mti->dependsOnTime(md);
|
||||
}
|
||||
|
||||
const GpencilModifierTypeInfo *BKE_gpencil_modifierType_getInfo(GpencilModifierType type)
|
||||
{
|
||||
/* type unsigned, no need to check < 0 */
|
||||
if (type < NUM_GREASEPENCIL_MODIFIER_TYPES && modifier_gpencil_types[type]->name[0] != '\0') {
|
||||
return modifier_gpencil_types[type];
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_gpencil_modifier_copyData_generic(const GpencilModifierData *md_src, GpencilModifierData *md_dst)
|
||||
{
|
||||
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md_src->type);
|
||||
|
||||
/* md_dst may have alredy be fully initialized with some extra allocated data,
|
||||
* we need to free it now to avoid memleak. */
|
||||
if (mti->freeData) {
|
||||
mti->freeData(md_dst);
|
||||
}
|
||||
|
||||
const size_t data_size = sizeof(GpencilModifierData);
|
||||
const char *md_src_data = ((const char *)md_src) + data_size;
|
||||
char *md_dst_data = ((char *)md_dst) + data_size;
|
||||
BLI_assert(data_size <= (size_t)mti->struct_size);
|
||||
memcpy(md_dst_data, md_src_data, (size_t)mti->struct_size - data_size);
|
||||
}
|
||||
|
||||
static void gpencil_modifier_copy_data_id_us_cb(void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin, int cb_flag)
|
||||
{
|
||||
ID *id = *idpoin;
|
||||
if (id != NULL && (cb_flag & IDWALK_CB_USER) != 0) {
|
||||
id_us_plus(id);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_gpencil_modifier_copyData_ex(GpencilModifierData *md, GpencilModifierData *target, const int flag)
|
||||
{
|
||||
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
|
||||
|
||||
target->mode = md->mode;
|
||||
target->flag = md->flag;
|
||||
|
||||
if (mti->copyData) {
|
||||
mti->copyData(md, target);
|
||||
}
|
||||
|
||||
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
|
||||
if (mti->foreachIDLink) {
|
||||
mti->foreachIDLink(target, NULL, gpencil_modifier_copy_data_id_us_cb, NULL);
|
||||
}
|
||||
else if (mti->foreachObjectLink) {
|
||||
mti->foreachObjectLink(target, NULL, (GreasePencilObjectWalkFunc)gpencil_modifier_copy_data_id_us_cb, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_gpencil_modifier_copyData(GpencilModifierData *md, GpencilModifierData *target)
|
||||
{
|
||||
BKE_gpencil_modifier_copyData_ex(md, target, 0);
|
||||
}
|
||||
|
||||
GpencilModifierData *BKE_gpencil_modifiers_findByType(Object *ob, GpencilModifierType type)
|
||||
{
|
||||
GpencilModifierData *md = ob->greasepencil_modifiers.first;
|
||||
|
||||
for (; md; md = md->next)
|
||||
if (md->type == type)
|
||||
break;
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
void BKE_gpencil_modifiers_foreachIDLink(Object *ob, GreasePencilIDWalkFunc walk, void *userData)
|
||||
{
|
||||
GpencilModifierData *md = ob->greasepencil_modifiers.first;
|
||||
|
||||
for (; md; md = md->next) {
|
||||
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
|
||||
|
||||
if (mti->foreachIDLink) mti->foreachIDLink(md, ob, walk, userData);
|
||||
else if (mti->foreachObjectLink) {
|
||||
/* each Object can masquerade as an ID, so this should be OK */
|
||||
GreasePencilObjectWalkFunc fp = (GreasePencilObjectWalkFunc)walk;
|
||||
mti->foreachObjectLink(md, ob, fp, userData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_gpencil_modifiers_foreachTexLink(Object *ob, GreasePencilTexWalkFunc walk, void *userData)
|
||||
{
|
||||
GpencilModifierData *md = ob->greasepencil_modifiers.first;
|
||||
|
||||
for (; md; md = md->next) {
|
||||
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
|
||||
|
||||
if (mti->foreachTexLink)
|
||||
mti->foreachTexLink(md, ob, walk, userData);
|
||||
}
|
||||
}
|
||||
|
||||
GpencilModifierData *BKE_gpencil_modifiers_findByName(Object *ob, const char *name)
|
||||
{
|
||||
return BLI_findstring(&(ob->greasepencil_modifiers), name, offsetof(GpencilModifierData, name));
|
||||
}
|
||||
|
||||
/* helper function for per-instance positioning */
|
||||
void BKE_gpencil_instance_modifier_instance_tfm(InstanceGpencilModifierData *mmd, const int elem_idx[3], float r_mat[4][4])
|
||||
{
|
||||
float offset[3], rot[3], scale[3];
|
||||
int ri = mmd->rnd[0];
|
||||
float factor;
|
||||
|
||||
offset[0] = mmd->offset[0] * elem_idx[0];
|
||||
offset[1] = mmd->offset[1] * elem_idx[1];
|
||||
offset[2] = mmd->offset[2] * elem_idx[2];
|
||||
|
||||
/* rotation */
|
||||
if (mmd->flag & GP_INSTANCE_RANDOM_ROT) {
|
||||
factor = mmd->rnd_rot * mmd->rnd[ri];
|
||||
mul_v3_v3fl(rot, mmd->rot, factor);
|
||||
add_v3_v3(rot, mmd->rot);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(rot, mmd->rot);
|
||||
}
|
||||
|
||||
/* scale */
|
||||
if (mmd->flag & GP_INSTANCE_RANDOM_SIZE) {
|
||||
factor = mmd->rnd_size * mmd->rnd[ri];
|
||||
mul_v3_v3fl(scale, mmd->scale, factor);
|
||||
add_v3_v3(scale, mmd->scale);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(scale, mmd->scale);
|
||||
}
|
||||
|
||||
/* advance random index */
|
||||
mmd->rnd[0]++;
|
||||
if (mmd->rnd[0] > 19) {
|
||||
mmd->rnd[0] = 1;
|
||||
}
|
||||
|
||||
/* calculate matrix */
|
||||
loc_eul_size_to_mat4(r_mat, offset, rot, scale);
|
||||
}
|
@ -37,6 +37,8 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_brush_types.h"
|
||||
#include "DNA_gpencil_types.h"
|
||||
#include "DNA_group_types.h"
|
||||
#include "DNA_lamp_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
@ -45,7 +47,6 @@
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_texture_types.h"
|
||||
#include "DNA_world_types.h"
|
||||
#include "DNA_brush_types.h"
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_ghash.h"
|
||||
@ -127,6 +128,9 @@ static void icon_free_data(int icon_id, Icon *icon)
|
||||
else if (icon->obj_type == ICON_DATA_PREVIEW) {
|
||||
((PreviewImage *)(icon->obj))->icon_id = 0;
|
||||
}
|
||||
else if (icon->obj_type == ICON_DATA_GPLAYER) {
|
||||
((bGPDlayer *)(icon->obj))->runtime.icon_id = 0;
|
||||
}
|
||||
else if (icon->obj_type == ICON_DATA_GEOM) {
|
||||
((struct Icon_Geom *)(icon->obj))->icon_id = 0;
|
||||
}
|
||||
@ -598,6 +602,44 @@ int BKE_icon_id_ensure(struct ID *id)
|
||||
return icon_id_ensure_create_icon(id);
|
||||
}
|
||||
|
||||
|
||||
static int icon_gplayer_color_ensure_create_icon(bGPDlayer *gpl)
|
||||
{
|
||||
BLI_assert(BLI_thread_is_main());
|
||||
|
||||
/* NOTE: The color previews for GP Layers don't really need
|
||||
* to be "rendered" to image per se (as it will just be a plain
|
||||
* colored rectangle), we need to define icon data here so that
|
||||
* we can store a pointer to the layer data in icon->obj.
|
||||
*/
|
||||
Icon *icon = icon_create(gpl->runtime.icon_id, ICON_DATA_GPLAYER, gpl);
|
||||
icon->flag = ICON_FLAG_MANAGED;
|
||||
|
||||
return gpl->runtime.icon_id;
|
||||
}
|
||||
|
||||
int BKE_icon_gplayer_color_ensure(bGPDlayer *gpl)
|
||||
{
|
||||
/* Never handle icons in non-main thread! */
|
||||
BLI_assert(BLI_thread_is_main());
|
||||
|
||||
if (!gpl || G.background) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (gpl->runtime.icon_id)
|
||||
return gpl->runtime.icon_id;
|
||||
|
||||
gpl->runtime.icon_id = get_next_free_id();
|
||||
|
||||
if (!gpl->runtime.icon_id) {
|
||||
printf("%s: Internal error - not enough IDs\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return icon_gplayer_color_ensure_create_icon(gpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return icon id of given preview, or create new icon if not found.
|
||||
*/
|
||||
|
@ -1073,6 +1073,7 @@ int set_listbasepointers(Main *main, ListBase **lb)
|
||||
lb[INDEX_ID_IP] = &(main->ipo);
|
||||
lb[INDEX_ID_AC] = &(main->action); /* moved here to avoid problems when freeing with animato (aligorith) */
|
||||
lb[INDEX_ID_KE] = &(main->key);
|
||||
lb[INDEX_ID_PAL] = &(main->palettes); /* referenced by gpencil, so needs to be before that to avoid crashes */
|
||||
lb[INDEX_ID_GD] = &(main->gpencil); /* referenced by nodes, objects, view, scene etc, before to free after. */
|
||||
lb[INDEX_ID_NT] = &(main->nodetree);
|
||||
lb[INDEX_ID_IM] = &(main->image);
|
||||
|
@ -417,7 +417,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
|
||||
SEQ_END
|
||||
}
|
||||
|
||||
CALLBACK_INVOKE(scene->gpd, IDWALK_CB_USER);
|
||||
|
||||
for (CollectionObject *cob = scene->master_collection->gobject.first; cob; cob = cob->next) {
|
||||
CALLBACK_INVOKE(cob->ob, IDWALK_CB_USER);
|
||||
@ -478,6 +477,9 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
|
||||
if (toolsett->uvsculpt) {
|
||||
library_foreach_paint(&data, &toolsett->uvsculpt->paint);
|
||||
}
|
||||
if (toolsett->gp_paint) {
|
||||
library_foreach_paint(&data, &toolsett->gp_paint->paint);
|
||||
}
|
||||
}
|
||||
|
||||
if (scene->rigidbody_world) {
|
||||
@ -641,6 +643,10 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
|
||||
if (material->texpaintslot != NULL) {
|
||||
CALLBACK_INVOKE(material->texpaintslot->ima, IDWALK_CB_NOP);
|
||||
}
|
||||
if (material->gp_style != NULL) {
|
||||
CALLBACK_INVOKE(material->gp_style->sima, IDWALK_CB_USER);
|
||||
CALLBACK_INVOKE(material->gp_style->ima, IDWALK_CB_USER);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -758,6 +764,9 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
|
||||
CALLBACK_INVOKE(brush->toggle_brush, IDWALK_CB_NOP);
|
||||
CALLBACK_INVOKE(brush->clone.image, IDWALK_CB_NOP);
|
||||
CALLBACK_INVOKE(brush->paint_curve, IDWALK_CB_USER);
|
||||
if (brush->gpencil_settings) {
|
||||
CALLBACK_INVOKE(brush->gpencil_settings->material, IDWALK_CB_USER);
|
||||
}
|
||||
library_foreach_mtex(&data, &brush->mtex);
|
||||
library_foreach_mtex(&data, &brush->mask_mtex);
|
||||
break;
|
||||
@ -941,10 +950,15 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
|
||||
case ID_GD:
|
||||
{
|
||||
bGPdata *gpencil = (bGPdata *) id;
|
||||
|
||||
for (bGPDlayer *gp_layer = gpencil->layers.first; gp_layer; gp_layer = gp_layer->next) {
|
||||
CALLBACK_INVOKE(gp_layer->parent, IDWALK_CB_NOP);
|
||||
/* materials */
|
||||
for (i = 0; i < gpencil->totcol; i++) {
|
||||
CALLBACK_INVOKE(gpencil->mat[i], IDWALK_CB_USER);
|
||||
}
|
||||
|
||||
for (bGPDlayer *gplayer = gpencil->layers.first; gplayer != NULL; gplayer = gplayer->next) {
|
||||
CALLBACK_INVOKE(gplayer->parent, IDWALK_CB_NOP);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1072,7 +1086,7 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
|
||||
return true;
|
||||
#endif
|
||||
case ID_BR:
|
||||
return ELEM(id_type_used, ID_BR, ID_IM, ID_PC, ID_TE);
|
||||
return ELEM(id_type_used, ID_BR, ID_IM, ID_PC, ID_TE, ID_MA);
|
||||
case ID_PA:
|
||||
return ELEM(id_type_used, ID_OB, ID_GR, ID_TE);
|
||||
case ID_MC:
|
||||
@ -1083,6 +1097,8 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
|
||||
return (ELEM(id_type_used, ID_TE, ID_OB));
|
||||
case ID_LP:
|
||||
return ELEM(id_type_used, ID_IM);
|
||||
case ID_GD:
|
||||
return ELEM(id_type_used, ID_MA);
|
||||
case ID_WS:
|
||||
return ELEM(id_type_used, ID_SCR, ID_SCE);
|
||||
case ID_IM:
|
||||
@ -1091,7 +1107,6 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
|
||||
case ID_SO:
|
||||
case ID_AR:
|
||||
case ID_AC:
|
||||
case ID_GD:
|
||||
case ID_WM:
|
||||
case ID_PAL:
|
||||
case ID_PC:
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_customdata_types.h"
|
||||
#include "DNA_gpencil_types.h"
|
||||
#include "DNA_ID.h"
|
||||
#include "DNA_meta_types.h"
|
||||
#include "DNA_node_types.h"
|
||||
@ -58,6 +59,7 @@
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_displist.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_gpencil.h"
|
||||
#include "BKE_icons.h"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_library.h"
|
||||
@ -103,10 +105,30 @@ void BKE_material_free(Material *ma)
|
||||
|
||||
MEM_SAFE_FREE(ma->texpaintslot);
|
||||
|
||||
MEM_SAFE_FREE(ma->gp_style);
|
||||
|
||||
BKE_icon_id_delete((ID *)ma);
|
||||
BKE_previewimg_free(&ma->preview);
|
||||
}
|
||||
|
||||
void BKE_material_init_gpencil_settings(Material *ma)
|
||||
{
|
||||
if ((ma) && (ma->gp_style == NULL)) {
|
||||
ma->gp_style = MEM_callocN(sizeof(MaterialGPencilStyle), "Grease Pencil Material Settings");
|
||||
|
||||
MaterialGPencilStyle *gp_style = ma->gp_style;
|
||||
/* set basic settings */
|
||||
gp_style->stroke_rgba[3] = 1.0f;
|
||||
gp_style->pattern_gridsize = 0.1f;
|
||||
gp_style->gradient_radius = 0.5f;
|
||||
ARRAY_SET_ITEMS(gp_style->mix_rgba, 1.0f, 1.0f, 1.0f, 0.2f);
|
||||
ARRAY_SET_ITEMS(gp_style->gradient_scale, 1.0f, 1.0f);
|
||||
ARRAY_SET_ITEMS(gp_style->texture_scale, 1.0f, 1.0f);
|
||||
gp_style->texture_opacity = 1.0f;
|
||||
gp_style->texture_pixsize = 100.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_material_init(Material *ma)
|
||||
{
|
||||
BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(ma, id));
|
||||
@ -124,6 +146,7 @@ void BKE_material_init(Material *ma)
|
||||
ma->preview = NULL;
|
||||
|
||||
ma->alpha_threshold = 0.5f;
|
||||
|
||||
}
|
||||
|
||||
Material *BKE_material_add(Main *bmain, const char *name)
|
||||
@ -137,6 +160,19 @@ Material *BKE_material_add(Main *bmain, const char *name)
|
||||
return ma;
|
||||
}
|
||||
|
||||
Material *BKE_material_add_gpencil(Main *bmain, const char *name)
|
||||
{
|
||||
Material *ma;
|
||||
|
||||
ma = BKE_material_add(bmain, name);
|
||||
|
||||
/* grease pencil settings */
|
||||
BKE_material_init_gpencil_settings(ma);
|
||||
|
||||
return ma;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Only copy internal data of Material ID from source to already allocated/initialized destination.
|
||||
* You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
|
||||
@ -164,6 +200,10 @@ void BKE_material_copy_data(Main *bmain, Material *ma_dst, const Material *ma_sr
|
||||
ma_dst->texpaintslot = MEM_dupallocN(ma_src->texpaintslot);
|
||||
}
|
||||
|
||||
if (ma_src->gp_style != NULL) {
|
||||
ma_dst->gp_style = MEM_dupallocN(ma_src->gp_style);
|
||||
}
|
||||
|
||||
BLI_listbase_clear(&ma_dst->gpumaterial);
|
||||
|
||||
/* TODO Duplicate Engine Settings and set runtime to NULL */
|
||||
@ -199,6 +239,7 @@ Material *BKE_material_localize(Material *ma)
|
||||
man->texpaintslot = NULL;
|
||||
man->preview = NULL;
|
||||
|
||||
/* man->gp_style = NULL; */ /* XXX: We probably don't want to clear here, or else we may get problems with COW later? */
|
||||
BLI_listbase_clear(&man->gpumaterial);
|
||||
|
||||
/* TODO Duplicate Engine Settings and set runtime to NULL */
|
||||
@ -218,6 +259,7 @@ Material ***give_matarar(Object *ob)
|
||||
Mesh *me;
|
||||
Curve *cu;
|
||||
MetaBall *mb;
|
||||
bGPdata *gpd;
|
||||
|
||||
if (ob->type == OB_MESH) {
|
||||
me = ob->data;
|
||||
@ -231,6 +273,10 @@ Material ***give_matarar(Object *ob)
|
||||
mb = ob->data;
|
||||
return &(mb->mat);
|
||||
}
|
||||
else if (ob->type == OB_GPENCIL) {
|
||||
gpd = ob->data;
|
||||
return &(gpd->mat);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -239,6 +285,7 @@ short *give_totcolp(Object *ob)
|
||||
Mesh *me;
|
||||
Curve *cu;
|
||||
MetaBall *mb;
|
||||
bGPdata *gpd;
|
||||
|
||||
if (ob->type == OB_MESH) {
|
||||
me = ob->data;
|
||||
@ -252,6 +299,10 @@ short *give_totcolp(Object *ob)
|
||||
mb = ob->data;
|
||||
return &(mb->totcol);
|
||||
}
|
||||
else if (ob->type == OB_GPENCIL) {
|
||||
gpd = ob->data;
|
||||
return &(gpd->totcol);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -286,6 +337,8 @@ short *give_totcolp_id(ID *id)
|
||||
return &(((Curve *)id)->totcol);
|
||||
case ID_MB:
|
||||
return &(((MetaBall *)id)->totcol);
|
||||
case ID_GD:
|
||||
return &(((bGPdata *)id)->totcol);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -307,6 +360,9 @@ static void material_data_index_remove_id(ID *id, short index)
|
||||
case ID_MB:
|
||||
/* meta-elems don't have materials atm */
|
||||
break;
|
||||
case ID_GD:
|
||||
BKE_gpencil_material_index_remove((bGPdata *)id, index);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -487,6 +543,21 @@ Material *give_current_material(Object *ob, short act)
|
||||
return ma;
|
||||
}
|
||||
|
||||
MaterialGPencilStyle *BKE_material_gpencil_settings_get(Object *ob, short act)
|
||||
{
|
||||
Material *ma = give_current_material(ob, act);
|
||||
if (ma != NULL) {
|
||||
if (ma->gp_style == NULL) {
|
||||
BKE_material_init_gpencil_settings(ma);
|
||||
}
|
||||
|
||||
return ma->gp_style;
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Material *give_node_material(Material *ma)
|
||||
{
|
||||
if (ma && ma->use_nodes && ma->nodetree) {
|
||||
@ -727,6 +798,9 @@ void BKE_material_remap_object(Object *ob, const unsigned int *remap)
|
||||
else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
|
||||
BKE_curve_material_remap(ob->data, remap, ob->totcol);
|
||||
}
|
||||
if (ob->type == OB_GPENCIL) {
|
||||
BKE_gpencil_material_remap(ob->data, remap, ob->totcol);
|
||||
}
|
||||
else {
|
||||
/* add support for this object data! */
|
||||
BLI_assert(matar == NULL);
|
||||
@ -924,7 +998,7 @@ bool BKE_object_material_slot_remove(Main *bmain, Object *ob)
|
||||
}
|
||||
|
||||
/* check indices from mesh */
|
||||
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
|
||||
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_GPENCIL)) {
|
||||
material_data_index_remove_id((ID *)ob->data, actcol - 1);
|
||||
if (ob->runtime.curve_cache) {
|
||||
BKE_displist_free(&ob->runtime.curve_cache->disp);
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_constraint_types.h"
|
||||
#include "DNA_gpencil_types.h"
|
||||
#include "DNA_gpencil_modifier_types.h"
|
||||
#include "DNA_group_types.h"
|
||||
#include "DNA_key_types.h"
|
||||
#include "DNA_lamp_types.h"
|
||||
@ -53,6 +54,7 @@
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_sequence_types.h"
|
||||
#include "DNA_shader_fx_types.h"
|
||||
#include "DNA_smoke_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
@ -86,6 +88,7 @@
|
||||
#include "BKE_displist.h"
|
||||
#include "BKE_effect.h"
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_gpencil_modifier.h"
|
||||
#include "BKE_icons.h"
|
||||
#include "BKE_key.h"
|
||||
#include "BKE_lamp.h"
|
||||
@ -110,12 +113,14 @@
|
||||
#include "BKE_rigidbody.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_sequencer.h"
|
||||
#include "BKE_shader_fx.h"
|
||||
#include "BKE_speaker.h"
|
||||
#include "BKE_softbody.h"
|
||||
#include "BKE_subsurf.h"
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_camera.h"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_gpencil.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_query.h"
|
||||
@ -185,11 +190,15 @@ void BKE_object_free_curve_cache(Object *ob)
|
||||
void BKE_object_free_modifiers(Object *ob, const int flag)
|
||||
{
|
||||
ModifierData *md;
|
||||
GpencilModifierData *gp_md;
|
||||
|
||||
while ((md = BLI_pophead(&ob->modifiers))) {
|
||||
modifier_free_ex(md, flag);
|
||||
}
|
||||
|
||||
while ((gp_md = BLI_pophead(&ob->greasepencil_modifiers))) {
|
||||
BKE_gpencil_modifier_free_ex(gp_md, flag);
|
||||
}
|
||||
/* particle modifiers were freed, so free the particlesystems as well */
|
||||
BKE_object_free_particlesystems(ob);
|
||||
|
||||
@ -200,6 +209,15 @@ void BKE_object_free_modifiers(Object *ob, const int flag)
|
||||
BKE_object_free_derived_caches(ob);
|
||||
}
|
||||
|
||||
void BKE_object_free_shaderfx(Object *ob, const int flag)
|
||||
{
|
||||
ShaderFxData *fx;
|
||||
|
||||
while ((fx = BLI_pophead(&ob->shader_fx))) {
|
||||
BKE_shaderfx_free_ex(fx, flag);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_object_modifier_hook_reset(Object *ob, HookModifierData *hmd)
|
||||
{
|
||||
/* reset functionality */
|
||||
@ -222,6 +240,29 @@ void BKE_object_modifier_hook_reset(Object *ob, HookModifierData *hmd)
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_object_modifier_gpencil_hook_reset(Object *ob, HookGpencilModifierData *hmd)
|
||||
{
|
||||
if (hmd->object == NULL) {
|
||||
return;
|
||||
}
|
||||
/* reset functionality */
|
||||
bPoseChannel *pchan = BKE_pose_channel_find_name(hmd->object->pose, hmd->subtarget);
|
||||
|
||||
if (hmd->subtarget[0] && pchan) {
|
||||
float imat[4][4], mat[4][4];
|
||||
|
||||
/* calculate the world-space matrix for the pose-channel target first, then carry on as usual */
|
||||
mul_m4_m4m4(mat, hmd->object->obmat, pchan->pose_mat);
|
||||
|
||||
invert_m4_m4(imat, mat);
|
||||
mul_m4_m4m4(hmd->parentinv, imat, ob->obmat);
|
||||
}
|
||||
else {
|
||||
invert_m4_m4(hmd->object->imat, hmd->object->obmat);
|
||||
mul_m4_m4m4(hmd->parentinv, hmd->object->imat, ob->obmat);
|
||||
}
|
||||
}
|
||||
|
||||
bool BKE_object_support_modifier_type_check(const Object *ob, int modifier_type)
|
||||
{
|
||||
const ModifierTypeInfo *mti;
|
||||
@ -428,6 +469,7 @@ void BKE_object_free(Object *ob)
|
||||
|
||||
/* BKE_<id>_free shall never touch to ID->us. Never ever. */
|
||||
BKE_object_free_modifiers(ob, LIB_ID_CREATE_NO_USER_REFCOUNT);
|
||||
BKE_object_free_shaderfx(ob, LIB_ID_CREATE_NO_USER_REFCOUNT);
|
||||
|
||||
MEM_SAFE_FREE(ob->mat);
|
||||
MEM_SAFE_FREE(ob->matbits);
|
||||
@ -653,6 +695,7 @@ static const char *get_obdata_defname(int type)
|
||||
case OB_ARMATURE: return DATA_("Armature");
|
||||
case OB_SPEAKER: return DATA_("Speaker");
|
||||
case OB_EMPTY: return DATA_("Empty");
|
||||
case OB_GPENCIL: return DATA_("GPencil");
|
||||
default:
|
||||
printf("get_obdata_defname: Internal error, bad type: %d\n", type);
|
||||
return DATA_("Empty");
|
||||
@ -677,6 +720,7 @@ void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
|
||||
case OB_ARMATURE: return BKE_armature_add(bmain, name);
|
||||
case OB_SPEAKER: return BKE_speaker_add(bmain, name);
|
||||
case OB_LIGHTPROBE:return BKE_lightprobe_add(bmain, name);
|
||||
case OB_GPENCIL: return BKE_gpencil_data_addnew(bmain, name);
|
||||
case OB_EMPTY: return NULL;
|
||||
default:
|
||||
printf("%s: Internal error, bad type: %d\n", __func__, type);
|
||||
@ -810,7 +854,7 @@ Object *BKE_object_add(
|
||||
/**
|
||||
* Add a new object, using another one as a reference
|
||||
*
|
||||
* /param ob_src object to use to determine the collections of the new object.
|
||||
* \param ob_src object to use to determine the collections of the new object.
|
||||
*/
|
||||
Object *BKE_object_add_from(
|
||||
Main *bmain, Scene *scene, ViewLayer *view_layer,
|
||||
@ -828,6 +872,41 @@ Object *BKE_object_add_from(
|
||||
return ob;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new object, but assign the given datablock as the ob->data
|
||||
* for the newly created object.
|
||||
*
|
||||
* \param data The datablock to assign as ob->data for the new object.
|
||||
* This is assumed to be of the correct type.
|
||||
* \param do_id_user If true, id_us_plus() will be called on data when
|
||||
* assigning it to the object.
|
||||
*/
|
||||
Object *BKE_object_add_for_data(
|
||||
Main *bmain, ViewLayer *view_layer,
|
||||
int type, const char *name, ID *data, bool do_id_user)
|
||||
{
|
||||
Object *ob;
|
||||
Base *base;
|
||||
LayerCollection *layer_collection;
|
||||
|
||||
/* same as object_add_common, except we don't create new ob->data */
|
||||
ob = BKE_object_add_only_object(bmain, type, name);
|
||||
ob->data = data;
|
||||
if (do_id_user) id_us_plus(data);
|
||||
|
||||
BKE_view_layer_base_deselect_all(view_layer);
|
||||
DEG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
|
||||
|
||||
layer_collection = BKE_layer_collection_get_active(view_layer);
|
||||
BKE_collection_object_add(bmain, layer_collection->collection, ob);
|
||||
|
||||
base = BKE_view_layer_base_find(view_layer, ob);
|
||||
BKE_view_layer_base_select(view_layer, base);
|
||||
|
||||
return ob;
|
||||
}
|
||||
|
||||
|
||||
void BKE_object_copy_softbody(struct Object *ob_dst, const struct Object *ob_src, const int flag)
|
||||
{
|
||||
SoftBody *sb = ob_src->soft;
|
||||
@ -1153,6 +1232,8 @@ void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
|
||||
void BKE_object_copy_data(Main *bmain, Object *ob_dst, const Object *ob_src, const int flag)
|
||||
{
|
||||
ModifierData *md;
|
||||
GpencilModifierData *gmd;
|
||||
ShaderFxData *fx;
|
||||
|
||||
/* Do not copy runtime data. */
|
||||
BKE_object_runtime_reset(ob_dst);
|
||||
@ -1179,6 +1260,24 @@ void BKE_object_copy_data(Main *bmain, Object *ob_dst, const Object *ob_src, con
|
||||
BLI_addtail(&ob_dst->modifiers, nmd);
|
||||
}
|
||||
|
||||
BLI_listbase_clear(&ob_dst->greasepencil_modifiers);
|
||||
|
||||
for (gmd = ob_src->greasepencil_modifiers.first; gmd; gmd = gmd->next) {
|
||||
GpencilModifierData *nmd = BKE_gpencil_modifier_new(gmd->type);
|
||||
BLI_strncpy(nmd->name, gmd->name, sizeof(nmd->name));
|
||||
BKE_gpencil_modifier_copyData_ex(gmd, nmd, flag_subdata);
|
||||
BLI_addtail(&ob_dst->greasepencil_modifiers, nmd);
|
||||
}
|
||||
|
||||
BLI_listbase_clear(&ob_dst->shader_fx);
|
||||
|
||||
for (fx = ob_src->shader_fx.first; fx; fx = fx->next) {
|
||||
ShaderFxData *nfx = BKE_shaderfx_new(fx->type);
|
||||
BLI_strncpy(nfx->name, fx->name, sizeof(nfx->name));
|
||||
BKE_shaderfx_copyData_ex(fx, nfx, flag_subdata);
|
||||
BLI_addtail(&ob_dst->shader_fx, nfx);
|
||||
}
|
||||
|
||||
if (ob_src->pose) {
|
||||
copy_object_pose(ob_dst, ob_src, flag_subdata);
|
||||
/* backwards compat... non-armatures can get poses in older files? */
|
||||
@ -1210,6 +1309,10 @@ void BKE_object_copy_data(Main *bmain, Object *ob_dst, const Object *ob_src, con
|
||||
BLI_listbase_clear((ListBase *)&ob_dst->drawdata);
|
||||
BLI_listbase_clear(&ob_dst->pc_ids);
|
||||
|
||||
/* grease pencil: clean derived data */
|
||||
if (ob_dst->type == OB_GPENCIL)
|
||||
BKE_gpencil_free_derived_frames(ob_dst->data);
|
||||
|
||||
ob_dst->avs = ob_src->avs;
|
||||
ob_dst->mpath = animviz_copy_motionpath(ob_src->mpath);
|
||||
|
||||
@ -1469,6 +1572,11 @@ void BKE_object_obdata_size_init(struct Object *ob, const float size)
|
||||
ob->empty_drawsize *= size;
|
||||
break;
|
||||
}
|
||||
case OB_GPENCIL:
|
||||
{
|
||||
ob->empty_drawsize *= size;
|
||||
break;
|
||||
}
|
||||
case OB_FONT:
|
||||
{
|
||||
Curve *cu = ob->data;
|
||||
@ -2452,7 +2560,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us
|
||||
float size[3];
|
||||
|
||||
copy_v3_v3(size, ob->size);
|
||||
if (ob->type == OB_EMPTY) {
|
||||
if ((ob->type == OB_EMPTY) || (ob->type == OB_GPENCIL)) {
|
||||
mul_v3_fl(size, ob->empty_drawsize);
|
||||
}
|
||||
|
||||
@ -3694,6 +3802,88 @@ bool BKE_object_modifier_use_time(Object *ob, ModifierData *md)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BKE_object_modifier_gpencil_use_time(Object *ob, GpencilModifierData *md)
|
||||
{
|
||||
if (BKE_gpencil_modifier_dependsOnTime(md)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Check whether modifier is animated. */
|
||||
/* TODO (Aligorith): this should be handled as part of build_animdata() */
|
||||
if (ob->adt) {
|
||||
AnimData *adt = ob->adt;
|
||||
FCurve *fcu;
|
||||
|
||||
char pattern[MAX_NAME + 32];
|
||||
BLI_snprintf(pattern, sizeof(pattern), "grease_pencil_modifiers[\"%s\"]", md->name);
|
||||
|
||||
/* action - check for F-Curves with paths containing 'grease_pencil_modifiers[' */
|
||||
if (adt->action) {
|
||||
for (fcu = (FCurve *)adt->action->curves.first;
|
||||
fcu != NULL;
|
||||
fcu = (FCurve *)fcu->next)
|
||||
{
|
||||
if (fcu->rna_path && strstr(fcu->rna_path, pattern))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* This here allows modifier properties to get driven and still update properly
|
||||
*
|
||||
*/
|
||||
for (fcu = (FCurve *)adt->drivers.first;
|
||||
fcu != NULL;
|
||||
fcu = (FCurve *)fcu->next)
|
||||
{
|
||||
if (fcu->rna_path && strstr(fcu->rna_path, pattern))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BKE_object_shaderfx_use_time(Object *ob, ShaderFxData *fx)
|
||||
{
|
||||
if (BKE_shaderfx_dependsOnTime(fx)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Check whether effect is animated. */
|
||||
/* TODO (Aligorith): this should be handled as part of build_animdata() */
|
||||
if (ob->adt) {
|
||||
AnimData *adt = ob->adt;
|
||||
FCurve *fcu;
|
||||
|
||||
char pattern[MAX_NAME + 32];
|
||||
BLI_snprintf(pattern, sizeof(pattern), "shader_effects[\"%s\"]", fx->name);
|
||||
|
||||
/* action - check for F-Curves with paths containing string[' */
|
||||
if (adt->action) {
|
||||
for (fcu = (FCurve *)adt->action->curves.first;
|
||||
fcu != NULL;
|
||||
fcu = (FCurve *)fcu->next)
|
||||
{
|
||||
if (fcu->rna_path && strstr(fcu->rna_path, pattern))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* This here allows properties to get driven and still update properly
|
||||
*
|
||||
*/
|
||||
for (fcu = (FCurve *)adt->drivers.first;
|
||||
fcu != NULL;
|
||||
fcu = (FCurve *)fcu->next)
|
||||
{
|
||||
if (fcu->rna_path && strstr(fcu->rna_path, pattern))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* set "ignore cache" flag for all caches on this object */
|
||||
static void object_cacheIgnoreClear(Object *ob, int state)
|
||||
{
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_gpencil.h"
|
||||
|
||||
/** \name Misc helpers
|
||||
* \{ */
|
||||
@ -402,12 +403,17 @@ static void object_defgroup_remove_edit_mode(Object *ob, bDeformGroup *dg)
|
||||
*/
|
||||
void BKE_object_defgroup_remove(Object *ob, bDeformGroup *defgroup)
|
||||
{
|
||||
if (BKE_object_is_in_editmode_vgroup(ob))
|
||||
object_defgroup_remove_edit_mode(ob, defgroup);
|
||||
else
|
||||
object_defgroup_remove_object_mode(ob, defgroup);
|
||||
if ((ob) && (ob->type == OB_GPENCIL)) {
|
||||
BKE_gpencil_vgroup_remove(ob, defgroup);
|
||||
}
|
||||
else {
|
||||
if (BKE_object_is_in_editmode_vgroup(ob))
|
||||
object_defgroup_remove_edit_mode(ob, defgroup);
|
||||
else
|
||||
object_defgroup_remove_object_mode(ob, defgroup);
|
||||
|
||||
BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
|
||||
BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,6 +62,7 @@
|
||||
#include "BKE_particle.h"
|
||||
#include "BKE_pointcache.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_gpencil.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
@ -324,6 +325,9 @@ void BKE_object_eval_uber_data(Depsgraph *depsgraph,
|
||||
case OB_MBALL:
|
||||
BKE_mball_batch_cache_dirty(ob->data, BKE_MBALL_BATCH_DIRTY_ALL);
|
||||
break;
|
||||
case OB_GPENCIL:
|
||||
BKE_gpencil_batch_cache_dirty(ob->data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,13 +41,19 @@
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_brush_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_gpencil_types.h"
|
||||
#include "DNA_workspace_types.h"
|
||||
|
||||
#include "BLI_bitmap.h"
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_brush.h"
|
||||
#include "BKE_colortools.h"
|
||||
#include "BKE_deform.h"
|
||||
@ -55,6 +61,7 @@
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_crazyspace.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_gpencil.h"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_key.h"
|
||||
#include "BKE_library.h"
|
||||
@ -151,6 +158,8 @@ Paint *BKE_paint_get_active_from_paintmode(Scene *sce, ePaintMode mode)
|
||||
return &ts->imapaint.paint;
|
||||
case ePaintSculptUV:
|
||||
return &ts->uvsculpt->paint;
|
||||
case ePaintGpencil:
|
||||
return &ts->gp_paint->paint;
|
||||
case ePaintInvalid:
|
||||
return NULL;
|
||||
default:
|
||||
@ -176,6 +185,8 @@ Paint *BKE_paint_get_active(Scene *sce, ViewLayer *view_layer)
|
||||
return &ts->wpaint->paint;
|
||||
case OB_MODE_TEXTURE_PAINT:
|
||||
return &ts->imapaint.paint;
|
||||
case OB_MODE_GPENCIL_PAINT:
|
||||
return &ts->gp_paint->paint;
|
||||
case OB_MODE_EDIT:
|
||||
if (ts->use_uv_sculpt)
|
||||
return &ts->uvsculpt->paint;
|
||||
@ -430,13 +441,11 @@ PaletteColor *BKE_palette_color_add(Palette *palette)
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
bool BKE_palette_is_empty(const struct Palette *palette)
|
||||
{
|
||||
return BLI_listbase_is_empty(&palette->colors);
|
||||
}
|
||||
|
||||
|
||||
/* are we in vertex paint or weight pain face select mode? */
|
||||
bool BKE_paint_select_face_test(Object *ob)
|
||||
{
|
||||
|