Merge branch 'master' into sculpt-dev

This commit is contained in:
Pablo Dobarro 2021-06-30 01:31:21 +02:00
commit 9838e9e485
85 changed files with 1503 additions and 793 deletions

View File

@ -85,7 +85,9 @@ ccl_device_inline float3 smooth_surface_offset(KernelGlobals *kg, ShaderData *sd
const float w = 1 - u - v;
float3 P = V[0] * u + V[1] * v + V[2] * w; /* Local space */
float3 n = N[0] * u + N[1] * v + N[2] * w; /* We get away without normalization */
n = transform_direction(&(sd->ob_tfm), n); /* Normal x scale, world space */
n = normalize(
transform_direction_transposed_auto(&sd->ob_itfm, n)); /* Normal x scale, world space */
/* Parabolic approximation */
float a = dot(N[2] - N[0], V[0] - V[2]);

View File

@ -77,7 +77,10 @@ ccl_device_inline void triangle_vertices(KernelGlobals *kg, int prim, float3 P[3
/* Triangle vertex locations and vertex normals */
ccl_device_inline void triangle_vertices_and_normals(KernelGlobals *kg, int prim, float3 P[3], float3 N[3])
ccl_device_inline void triangle_vertices_and_normals(KernelGlobals *kg,
int prim,
float3 P[3],
float3 N[3])
{
const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
P[0] = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 0));

View File

@ -689,12 +689,11 @@ typedef enum PrimitiveType {
PRIMITIVE_MOTION_CURVE_THICK = (1 << 3),
PRIMITIVE_CURVE_RIBBON = (1 << 4),
PRIMITIVE_MOTION_CURVE_RIBBON = (1 << 5),
PRIMITIVE_VOLUME = (1 << 6),
/* Lamp primitive is not included below on purpose,
* since it is no real traceable primitive.
*/
PRIMITIVE_LAMP = (1 << 6),
PRIMITIVE_VOLUME = (1 << 7),
PRIMITIVE_LAMP = (1 << 7),
PRIMITIVE_ALL_TRIANGLE = (PRIMITIVE_TRIANGLE | PRIMITIVE_MOTION_TRIANGLE),
PRIMITIVE_ALL_CURVE = (PRIMITIVE_CURVE_THICK | PRIMITIVE_MOTION_CURVE_THICK |

View File

@ -48,6 +48,7 @@ void ConstantFolder::make_constant(float value) const
foreach (ShaderInput *sock, output->links) {
sock->set(value);
sock->constant_folded_in = true;
}
graph->disconnect(output);
@ -59,6 +60,7 @@ void ConstantFolder::make_constant(float3 value) const
foreach (ShaderInput *sock, output->links) {
sock->set(value);
sock->constant_folded_in = true;
}
graph->disconnect(output);

View File

@ -79,7 +79,11 @@ enum ShaderNodeSpecialType {
class ShaderInput {
public:
ShaderInput(const SocketType &socket_type_, ShaderNode *parent_)
: socket_type(socket_type_), parent(parent_), link(NULL), stack_offset(SVM_STACK_INVALID)
: socket_type(socket_type_),
parent(parent_),
link(NULL),
stack_offset(SVM_STACK_INVALID),
constant_folded_in(false)
{
}
@ -111,6 +115,10 @@ class ShaderInput {
ShaderNode *parent;
ShaderOutput *link;
int stack_offset; /* for SVM compiler */
/* Keeps track of whether a constant was folded in this socket, to avoid over-optimizing when the
* link is null. */
bool constant_folded_in;
};
/* Output

View File

@ -304,7 +304,7 @@ int SVMCompiler::stack_assign(ShaderOutput *output)
int SVMCompiler::stack_assign_if_linked(ShaderInput *input)
{
if (input->link)
if (input->link || input->constant_folded_in)
return stack_assign(input);
return SVM_STACK_INVALID;

View File

@ -1634,7 +1634,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
}
/* Reset pointer pen info if pen device has left tracking range. */
if (pointerInfo.pointerType == PT_PEN && !IS_POINTER_INRANGE_WPARAM(wParam)) {
if (pointerInfo.pointerType == PT_PEN) {
window->resetPointerPenInfo();
eventHandled = true;
}

View File

@ -38,6 +38,7 @@
#include <assert.h>
#include <math.h>
#include <shellscalingapi.h>
#include <string.h>
#include <windowsx.h>
@ -80,13 +81,10 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_wintab(NULL),
m_lastPointerTabletData(GHOST_TABLET_DATA_NONE),
m_normal_state(GHOST_kWindowStateNormal),
m_user32(NULL),
m_user32(::LoadLibrary("user32.dll")),
m_parentWindowHwnd(parentwindow ? parentwindow->m_hWnd : HWND_DESKTOP),
m_debug_context(is_debug)
{
wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0);
RECT win_rect = {left, top, (long)(left + width), (long)(top + height)};
DWORD style = parentwindow ?
WS_POPUPWINDOW | WS_CAPTION | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX :
WS_OVERLAPPEDWINDOW;
@ -105,27 +103,10 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
*/
}
/* Monitor details. */
MONITORINFOEX monitor;
monitor.cbSize = sizeof(MONITORINFOEX);
monitor.dwFlags = 0;
GetMonitorInfo(MonitorFromRect(&win_rect, MONITOR_DEFAULTTONEAREST), &monitor);
/* Constrain requested size and position to fit within this monitor. */
width = min(monitor.rcWork.right - monitor.rcWork.left, win_rect.right - win_rect.left);
height = min(monitor.rcWork.bottom - monitor.rcWork.top, win_rect.bottom - win_rect.top);
win_rect.left = min(max(monitor.rcWork.left, win_rect.left), monitor.rcWork.right - width);
win_rect.right = win_rect.left + width;
win_rect.top = min(max(monitor.rcWork.top, win_rect.top), monitor.rcWork.bottom - height);
win_rect.bottom = win_rect.top + height;
/* Adjust to allow for caption, borders, shadows, scaling, etc. Resulting values can be
* correctly outside of monitor bounds. Note: You cannot specify WS_OVERLAPPED when calling. */
AdjustWindowRectEx(&win_rect, style & ~WS_OVERLAPPED, FALSE, extended_style);
/* But never allow a top position that can hide part of the title bar. */
win_rect.top = max(monitor.rcWork.top, win_rect.top);
RECT win_rect = {left, top, (long)(left + width), (long)(top + height)};
adjustWindowRectForClosestMonitor(&win_rect, style, extended_style);
wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0);
m_hWnd = ::CreateWindowExW(extended_style, // window extended style
s_windowClassName, // pointer to registered class name
title_16, // pointer to window name
@ -140,81 +121,78 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
0); // pointer to window-creation data
free(title_16);
m_user32 = ::LoadLibrary("user32.dll");
if (m_hWnd) {
RegisterTouchWindow(m_hWnd, 0);
// Register this window as a droptarget. Requires m_hWnd to be valid.
// Note that OleInitialize(0) has to be called prior to this. Done in GHOST_SystemWin32.
m_dropTarget = new GHOST_DropTargetWin32(this, m_system);
if (m_dropTarget) {
::RegisterDragDrop(m_hWnd, m_dropTarget);
}
// Store a pointer to this class in the window structure
::SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG_PTR)this);
if (!m_system->m_windowFocus) {
// Lower to bottom and don't activate if we don't want focus
::SetWindowPos(m_hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
// Store the device context
m_hDC = ::GetDC(m_hWnd);
GHOST_TSuccess success = setDrawingContextType(type);
if (success) {
// Show the window
int nCmdShow;
switch (state) {
case GHOST_kWindowStateMaximized:
nCmdShow = SW_SHOWMAXIMIZED;
break;
case GHOST_kWindowStateMinimized:
nCmdShow = (m_system->m_windowFocus) ? SW_SHOWMINIMIZED : SW_SHOWMINNOACTIVE;
break;
case GHOST_kWindowStateNormal:
default:
nCmdShow = (m_system->m_windowFocus) ? SW_SHOWNORMAL : SW_SHOWNOACTIVATE;
break;
}
::ShowWindow(m_hWnd, nCmdShow);
#ifdef WIN32_COMPOSITING
if (alphaBackground && parentwindowhwnd == 0) {
HRESULT hr = S_OK;
// Create and populate the Blur Behind structure
DWM_BLURBEHIND bb = {0};
// Enable Blur Behind and apply to the entire client area
bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
bb.fEnable = true;
bb.hRgnBlur = CreateRectRgn(0, 0, -1, -1);
// Apply Blur Behind
hr = DwmEnableBlurBehindWindow(m_hWnd, &bb);
DeleteObject(bb.hRgnBlur);
}
#endif
// Force an initial paint of the window
::UpdateWindow(m_hWnd);
}
else {
// invalidate the window
::DestroyWindow(m_hWnd);
m_hWnd = NULL;
}
if (m_hWnd == NULL) {
return;
}
// Initialize Wintab
/* Store the device context. */
m_hDC = ::GetDC(m_hWnd);
if (!setDrawingContextType(type)) {
::DestroyWindow(m_hWnd);
m_hWnd = NULL;
return;
}
RegisterTouchWindow(m_hWnd, 0);
/* Register as droptarget. OleInitialize(0) required first, done in GHOST_SystemWin32. */
m_dropTarget = new GHOST_DropTargetWin32(this, m_system);
::RegisterDragDrop(m_hWnd, m_dropTarget);
/* Store a pointer to this class in the window structure. */
::SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG_PTR)this);
if (!m_system->m_windowFocus) {
/* If we don't want focus then lower to bottom. */
::SetWindowPos(m_hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
/* Show the window. */
int nCmdShow;
switch (state) {
case GHOST_kWindowStateMaximized:
nCmdShow = SW_SHOWMAXIMIZED;
break;
case GHOST_kWindowStateMinimized:
nCmdShow = (m_system->m_windowFocus) ? SW_SHOWMINIMIZED : SW_SHOWMINNOACTIVE;
break;
case GHOST_kWindowStateNormal:
default:
nCmdShow = (m_system->m_windowFocus) ? SW_SHOWNORMAL : SW_SHOWNOACTIVATE;
break;
}
::ShowWindow(m_hWnd, nCmdShow);
#ifdef WIN32_COMPOSITING
if (alphaBackground && parentwindowhwnd == 0) {
HRESULT hr = S_OK;
/* Create and populate the Blur Behind structure. */
DWM_BLURBEHIND bb = {0};
/* Enable Blur Behind and apply to the entire client area. */
bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
bb.fEnable = true;
bb.hRgnBlur = CreateRectRgn(0, 0, -1, -1);
/* Apply Blur Behind. */
hr = DwmEnableBlurBehindWindow(m_hWnd, &bb);
DeleteObject(bb.hRgnBlur);
}
#endif
/* Force an initial paint of the window. */
::UpdateWindow(m_hWnd);
/* Initialize Wintab. */
if (system->getTabletAPI() != GHOST_kTabletWinPointer) {
loadWintab(GHOST_kWindowStateMinimized != state);
}
/* Allow the showing of a progress bar on the taskbar. */
CoCreateInstance(
CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID *)&m_Bar);
}
@ -268,6 +246,47 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
}
}
void GHOST_WindowWin32::adjustWindowRectForClosestMonitor(LPRECT win_rect,
DWORD dwStyle,
DWORD dwExStyle)
{
/* Get Details of the closest monitor. */
HMONITOR hmonitor = MonitorFromRect(win_rect, MONITOR_DEFAULTTONEAREST);
MONITORINFOEX monitor;
monitor.cbSize = sizeof(MONITORINFOEX);
monitor.dwFlags = 0;
GetMonitorInfo(hmonitor, &monitor);
/* Constrain requested size and position to fit within this monitor. */
LONG width = min(monitor.rcWork.right - monitor.rcWork.left, win_rect->right - win_rect->left);
LONG height = min(monitor.rcWork.bottom - monitor.rcWork.top, win_rect->bottom - win_rect->top);
win_rect->left = min(max(monitor.rcWork.left, win_rect->left), monitor.rcWork.right - width);
win_rect->right = win_rect->left + width;
win_rect->top = min(max(monitor.rcWork.top, win_rect->top), monitor.rcWork.bottom - height);
win_rect->bottom = win_rect->top + height;
/* With Windows 10 and newer we can adjust for chrome that differs with DPI and scale. */
GHOST_WIN32_AdjustWindowRectExForDpi fpAdjustWindowRectExForDpi = nullptr;
if (m_user32) {
fpAdjustWindowRectExForDpi = (GHOST_WIN32_AdjustWindowRectExForDpi)::GetProcAddress(
m_user32, "AdjustWindowRectExForDpi");
}
/* Adjust to allow for caption, borders, shadows, scaling, etc. Resulting values can be
* correctly outside of monitor bounds. Note: You cannot specify WS_OVERLAPPED when calling. */
if (fpAdjustWindowRectExForDpi) {
UINT dpiX, dpiY;
GetDpiForMonitor(hmonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
fpAdjustWindowRectExForDpi(win_rect, dwStyle & ~WS_OVERLAPPED, FALSE, dwExStyle, dpiX);
}
else {
AdjustWindowRectEx(win_rect, dwStyle & ~WS_OVERLAPPED, FALSE, dwExStyle);
}
/* But never allow a top position that can hide part of the title bar. */
win_rect->top = max(monitor.rcWork.top, win_rect->top);
}
bool GHOST_WindowWin32::getValid() const
{
return GHOST_Window::getValid() && m_hWnd != 0 && m_hDC != 0;

View File

@ -43,6 +43,9 @@ class GHOST_DropTargetWin32;
// typedefs for user32 functions to allow dynamic loading of Windows 10 DPI scaling functions
typedef UINT(API *GHOST_WIN32_GetDpiForWindow)(HWND);
typedef BOOL(API *GHOST_WIN32_AdjustWindowRectExForDpi)(
LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle, UINT dpi);
struct GHOST_PointerInfoWin32 {
GHOST_TInt32 pointerId;
GHOST_TInt32 isPrimary;
@ -98,6 +101,14 @@ class GHOST_WindowWin32 : public GHOST_Window {
*/
~GHOST_WindowWin32();
/**
* Adjusts a requested window rect to fit and position correctly in monitor.
* \param win_rect: pointer to rectangle that will be modified.
* \param dwStyle: The Window Style of the window whose required size is to be calculated.
* \param dwExStyle: The Extended Window Style of the window.
*/
void adjustWindowRectForClosestMonitor(LPRECT win_rect, DWORD dwStyle, DWORD dwExStyle);
/**
* Returns indication as to whether the window is valid.
* \return The validity of the window.

View File

@ -86,6 +86,13 @@ class COLLECTION_PT_lineart_collection(CollectionButtonsPanel, Panel):
row = layout.row()
row.prop(collection, "lineart_usage")
layout.prop(collection, "lineart_use_intersection_mask")
row = layout.row(align=True, heading="Masks")
row.active = collection.lineart_use_intersection_mask
for i in range(0,8):
row.prop(collection, "lineart_intersection_mask", index=i, text=str(i), toggle=True)
classes = (
COLLECTION_PT_collection_flags,

View File

@ -162,6 +162,14 @@ class SEQUENCER_HT_header(Header):
if tool_settings.use_proportional_edit:
row.prop(tool_settings, "proportional_edit_falloff", icon_only=True)
if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
tool_settings = context.tool_settings
row = layout.row(align=True)
row.prop(tool_settings, "use_snap_sequencer", text="")
sub = row.row(align=True)
sub.popover(panel="SEQUENCER_PT_snapping")
layout.separator_spacer()
row = layout.row(align=True)
row.prop(st, "show_strip_overlay", text="", icon='OVERLAY')
sub = row.row(align=True)
@ -2264,6 +2272,30 @@ class SEQUENCER_PT_custom_props(SequencerButtonsPanel, PropertyPanel, Panel):
bl_category = "Strip"
class SEQUENCER_PT_snapping(Panel):
bl_space_type = 'SEQUENCE_EDITOR'
bl_region_type = 'HEADER'
bl_label = ""
def draw(self, context):
tool_settings = context.tool_settings
sequencer_tool_settings = tool_settings.sequencer_tool_settings
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
col = layout.column(heading="Snap to", align=True)
col.prop(sequencer_tool_settings, "snap_seq_element", expand=True)
col = layout.column(heading="Ignore", align=True)
col.prop(sequencer_tool_settings, "snap_ignore_muted", text="Muted Strips")
col.prop(sequencer_tool_settings, "snap_ignore_sound",text="Sound Strips")
col = layout.column()
col.prop(sequencer_tool_settings, "snap_distance", slider=True, text="Distance")
classes = (
SEQUENCER_MT_change,
SEQUENCER_HT_tool_header,
@ -2333,6 +2365,8 @@ classes = (
SEQUENCER_PT_annotation,
SEQUENCER_PT_annotation_onion,
SEQUENCER_PT_snapping,
)
if __name__ == "__main__": # only for live edit.

View File

@ -39,7 +39,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 6
#define BLENDER_FILE_SUBVERSION 7
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file

View File

@ -121,6 +121,7 @@ void BKE_curve_material_remap(struct Curve *cu, const unsigned int *remap, unsig
void BKE_curve_smooth_flag_set(struct Curve *cu, const bool use_smooth);
ListBase *BKE_curve_nurbs_get(struct Curve *cu);
const ListBase *BKE_curve_nurbs_get_for_read(const struct Curve *cu);
int BKE_curve_nurb_vert_index_get(const struct Nurb *nu, const void *vert);
void BKE_curve_nurb_active_set(struct Curve *cu, const struct Nurb *nu);
@ -153,9 +154,10 @@ void BKE_curve_editNurb_keyIndex_delCV(struct GHash *keyindex, const void *cv);
void BKE_curve_editNurb_keyIndex_free(struct GHash **keyindex);
void BKE_curve_editNurb_free(struct Curve *cu);
struct ListBase *BKE_curve_editNurbs_get(struct Curve *cu);
const struct ListBase *BKE_curve_editNurbs_get_for_read(const struct Curve *cu);
void BKE_curve_bevelList_free(struct ListBase *bev);
void BKE_curve_bevelList_make(struct Object *ob, struct ListBase *nurbs, bool for_render);
void BKE_curve_bevelList_make(struct Object *ob, const struct ListBase *nurbs, bool for_render);
ListBase BKE_curve_bevel_make(const struct Curve *curve);
void BKE_curve_forward_diff_bezier(

View File

@ -87,13 +87,11 @@ bool BKE_displist_has_faces(const struct ListBase *lb);
void BKE_displist_make_curveTypes(struct Depsgraph *depsgraph,
const struct Scene *scene,
struct Object *ob,
const bool for_render,
const bool for_orco);
const bool for_render);
void BKE_displist_make_curveTypes_forRender(struct Depsgraph *depsgraph,
const struct Scene *scene,
struct Object *ob,
struct ListBase *dispbase,
const bool for_orco,
struct Mesh **r_final);
void BKE_displist_make_mball(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob);
void BKE_displist_make_mball_forRender(struct Depsgraph *depsgraph,

View File

@ -128,7 +128,8 @@ struct Mesh *BKE_mesh_copy_for_eval(struct Mesh *source, bool reference);
/* These functions construct a new Mesh,
* contrary to BKE_mesh_from_nurbs which modifies ob itself. */
struct Mesh *BKE_mesh_new_nomain_from_curve(struct Object *ob);
struct Mesh *BKE_mesh_new_nomain_from_curve_displist(struct Object *ob, struct ListBase *dispbase);
struct Mesh *BKE_mesh_new_nomain_from_curve_displist(const struct Object *ob,
const struct ListBase *dispbase);
bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me);
bool BKE_mesh_clear_facemap_customdata(struct Mesh *me);
@ -151,7 +152,7 @@ int BKE_mesh_nurbs_to_mdata(struct Object *ob,
struct MPoly **r_allpoly,
int *r_totloop,
int *r_totpoly);
int BKE_mesh_nurbs_displist_to_mdata(struct Object *ob,
int BKE_mesh_nurbs_displist_to_mdata(const struct Object *ob,
const struct ListBase *dispbase,
struct MVert **r_allvert,
int *r_totvert,

View File

@ -32,6 +32,7 @@
#include "BKE_attribute_math.hh"
struct Curve;
struct ListBase;
class Spline;
using SplinePtr = std::unique_ptr<Spline>;
@ -546,4 +547,6 @@ struct CurveEval {
void assert_valid_point_attributes() const;
};
std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &curve);
std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &curve,
const ListBase &nurbs_list);
std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &dna_curve);

View File

@ -442,6 +442,15 @@ ListBase *BKE_curve_editNurbs_get(Curve *cu)
return NULL;
}
const ListBase *BKE_curve_editNurbs_get_for_read(const Curve *cu)
{
if (cu->editnurb) {
return &cu->editnurb->nurbs;
}
return NULL;
}
short BKE_curve_type_get(const Curve *cu)
{
int type = cu->type;
@ -2049,7 +2058,7 @@ static void calc_bevel_sin_cos(
static void tilt_bezpart(const BezTriple *prevbezt,
const BezTriple *bezt,
Nurb *nu,
const Nurb *nu,
float *tilt_array,
float *radius_array,
float *weight_array,
@ -2611,7 +2620,7 @@ static void make_bevel_list_2D(BevList *bl)
}
}
static void bevlist_firstlast_direction_calc_from_bpoint(Nurb *nu, BevList *bl)
static void bevlist_firstlast_direction_calc_from_bpoint(const Nurb *nu, BevList *bl)
{
if (nu->pntsu > 1) {
BPoint *first_bp = nu->bp, *last_bp = nu->bp + (nu->pntsu - 1);
@ -2646,7 +2655,7 @@ void BKE_curve_bevelList_free(ListBase *bev)
BLI_listbase_clear(bev);
}
void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_render)
{
/*
* - convert all curves to polys, with indication of resol and flags for double-vertices
@ -2691,7 +2700,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
is_editmode = 1;
}
LISTBASE_FOREACH (Nurb *, nu, nurbs) {
LISTBASE_FOREACH (const Nurb *, nu, nurbs) {
if (nu->hide && is_editmode) {
continue;
}
@ -5078,6 +5087,15 @@ ListBase *BKE_curve_nurbs_get(Curve *cu)
return &cu->nurb;
}
const ListBase *BKE_curve_nurbs_get_for_read(const Curve *cu)
{
if (cu->editnurb) {
return BKE_curve_editNurbs_get_for_read(cu);
}
return &cu->nurb;
}
void BKE_curve_nurb_active_set(Curve *cu, const Nurb *nu)
{
if (nu == NULL) {

View File

@ -257,9 +257,10 @@ static SplinePtr spline_from_dna_poly(const Nurb &nurb)
return spline;
}
std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &dna_curve)
std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &dna_curve,
const ListBase &nurbs_list)
{
Vector<const Nurb *> nurbs(*BKE_curve_nurbs_get(&const_cast<Curve &>(dna_curve)));
Vector<const Nurb *> nurbs(nurbs_list);
std::unique_ptr<CurveEval> curve = std::make_unique<CurveEval>();
curve->resize(nurbs.size());
@ -295,6 +296,11 @@ std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &dna_curve)
return curve;
}
std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &dna_curve)
{
return curve_eval_from_dna_curve(dna_curve, *BKE_curve_nurbs_get_for_read(&dna_curve));
}
/**
* Check the invariants that curve control point attributes should always uphold, necessary
* because attributes are stored on splines rather than in a flat array on the curve:

View File

@ -135,7 +135,7 @@ void BKE_displist_normals_add(ListBase *lb)
LISTBASE_FOREACH (DispList *, dl, lb) {
if (dl->type == DL_INDEX3) {
if (dl->nors == nullptr) {
dl->nors = (float *)MEM_callocN(sizeof(float[3]), "dlnors");
dl->nors = (float *)MEM_callocN(sizeof(float[3]), __func__);
if (dl->flag & DL_BACK_CURVE) {
dl->nors[2] = -1.0f;
@ -147,7 +147,7 @@ void BKE_displist_normals_add(ListBase *lb)
}
else if (dl->type == DL_SURF) {
if (dl->nors == nullptr) {
dl->nors = (float *)MEM_callocN(sizeof(float[3]) * dl->nr * dl->parts, "dlnors");
dl->nors = (float *)MEM_callocN(sizeof(float[3]) * dl->nr * dl->parts, __func__);
vdata = dl->verts;
ndata = dl->nors;
@ -328,7 +328,7 @@ static void curve_to_displist(const Curve *cu,
DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), __func__);
/* Add one to the length because of 'BKE_curve_forward_diff_bezier'. */
dl->verts = (float *)MEM_mallocN(sizeof(float[3]) * (samples_len + 1), "dlverts");
dl->verts = (float *)MEM_mallocN(sizeof(float[3]) * (samples_len + 1), __func__);
BLI_addtail(r_dispbase, dl);
dl->parts = 1;
dl->nr = samples_len;
@ -382,7 +382,7 @@ static void curve_to_displist(const Curve *cu,
else if (nu->type == CU_NURBS) {
const int len = (resolution * SEGMENTSU(nu));
DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), __func__);
dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), "dlverts");
dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), __func__);
BLI_addtail(r_dispbase, dl);
dl->parts = 1;
dl->nr = len;
@ -395,7 +395,7 @@ static void curve_to_displist(const Curve *cu,
else if (nu->type == CU_POLY) {
const int len = nu->pntsu;
DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), __func__);
dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), "dlverts");
dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), __func__);
BLI_addtail(r_dispbase, dl);
dl->parts = 1;
dl->nr = len;
@ -491,7 +491,7 @@ void BKE_displist_fill(const ListBase *dispbase,
const int triangles_len = BLI_scanfill_calc_ex(&sf_ctx, scanfill_flag, normal_proj);
if (totvert != 0 && triangles_len != 0) {
DispList *dlnew = (DispList *)MEM_callocN(sizeof(DispList), "filldisplist");
DispList *dlnew = (DispList *)MEM_callocN(sizeof(DispList), __func__);
dlnew->type = DL_INDEX3;
dlnew->flag = (dl_flag_accum & (DL_BACK_CURVE | DL_FRONT_CURVE));
dlnew->rt = (dl_rt_accum & CU_SMOOTH);
@ -499,8 +499,8 @@ void BKE_displist_fill(const ListBase *dispbase,
dlnew->nr = totvert;
dlnew->parts = triangles_len;
dlnew->index = (int *)MEM_mallocN(sizeof(int[3]) * triangles_len, "dlindex");
dlnew->verts = (float *)MEM_mallocN(sizeof(float[3]) * totvert, "dlverts");
dlnew->index = (int *)MEM_mallocN(sizeof(int[3]) * triangles_len, __func__);
dlnew->verts = (float *)MEM_mallocN(sizeof(float[3]) * totvert, __func__);
/* vert data */
int i;
@ -630,7 +630,7 @@ static float displist_calc_taper(Depsgraph *depsgraph,
(DispList *)taperobj->runtime.curve_cache->disp.first :
nullptr;
if (dl == nullptr) {
BKE_displist_make_curveTypes(depsgraph, scene, taperobj, false, false);
BKE_displist_make_curveTypes(depsgraph, scene, taperobj, false);
dl = (DispList *)taperobj->runtime.curve_cache->disp.first;
}
if (dl) {
@ -681,8 +681,7 @@ void BKE_displist_make_mball(Depsgraph *depsgraph, Scene *scene, Object *ob)
BKE_displist_free(&(ob->runtime.curve_cache->disp));
}
else {
ob->runtime.curve_cache = (CurveCache *)MEM_callocN(sizeof(CurveCache),
"CurveCache for MBall");
ob->runtime.curve_cache = (CurveCache *)MEM_callocN(sizeof(CurveCache), __func__);
}
BKE_mball_polygonize(depsgraph, scene, ob, &ob->runtime.curve_cache->disp);
@ -1068,7 +1067,7 @@ static void displist_surf_indices(DispList *dl)
dl->totindex = 0;
int *index = dl->index = (int *)MEM_mallocN(sizeof(int[4]) * (dl->parts + 1) * (dl->nr + 1),
"index array nurbs");
__func__);
for (int a = 0; a < dl->parts; a++) {
@ -1092,31 +1091,29 @@ static void displist_surf_indices(DispList *dl)
}
}
static void displist_make_surf(Depsgraph *depsgraph,
const Scene *scene,
Object *ob,
ListBase *dispbase,
Mesh **r_final,
const bool for_render,
const bool for_orco)
static void evaluate_surface_object(Depsgraph *depsgraph,
const Scene *scene,
Object *ob,
const bool for_render,
ListBase *r_dispbase,
Mesh **r_final)
{
ListBase nubase = {nullptr, nullptr};
BLI_assert(ob->type == OB_SURF);
const Curve *cu = (const Curve *)ob->data;
ListBase *deformed_nurbs = &ob->runtime.curve_cache->deformed_nurbs;
if (!for_render && cu->editnurb) {
BKE_nurbList_duplicate(&nubase, BKE_curve_editNurbs_get(const_cast<Curve *>(cu)));
BKE_nurbList_duplicate(deformed_nurbs, BKE_curve_editNurbs_get_for_read(cu));
}
else {
BKE_nurbList_duplicate(&nubase, &cu->nurb);
BKE_nurbList_duplicate(deformed_nurbs, &cu->nurb);
}
bool force_mesh_conversion = false;
if (!for_orco) {
force_mesh_conversion = BKE_curve_calc_modifiers_pre(
depsgraph, scene, ob, &nubase, &nubase, for_render);
}
bool force_mesh_conversion = BKE_curve_calc_modifiers_pre(
depsgraph, scene, ob, deformed_nurbs, deformed_nurbs, for_render);
LISTBASE_FOREACH (Nurb *, nu, &nubase) {
LISTBASE_FOREACH (const Nurb *, nu, deformed_nurbs) {
if (!(for_render || nu->hide == 0) || !BKE_nurb_check_valid_uv(nu)) {
continue;
}
@ -1127,10 +1124,10 @@ static void displist_make_surf(Depsgraph *depsgraph,
if (nu->pntsv == 1) {
const int len = SEGMENTSU(nu) * resolu;
DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), "makeDispListsurf");
dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), "dlverts");
DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), __func__);
dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), __func__);
BLI_addtail(dispbase, dl);
BLI_addtail(r_dispbase, dl);
dl->parts = 1;
dl->nr = len;
dl->col = nu->mat_nr;
@ -1150,9 +1147,9 @@ static void displist_make_surf(Depsgraph *depsgraph,
else {
const int len = (nu->pntsu * resolu) * (nu->pntsv * resolv);
DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), "makeDispListsurf");
dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), "dlverts");
BLI_addtail(dispbase, dl);
DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), __func__);
dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), __func__);
BLI_addtail(r_dispbase, dl);
dl->col = nu->mat_nr;
dl->charidx = nu->charidx;
@ -1177,13 +1174,8 @@ static void displist_make_surf(Depsgraph *depsgraph,
}
}
if (!for_orco) {
BKE_nurbList_duplicate(&ob->runtime.curve_cache->deformed_nurbs, &nubase);
curve_calc_modifiers_post(
depsgraph, scene, ob, dispbase, for_render, force_mesh_conversion, r_final);
}
BKE_nurbList_free(&nubase);
curve_calc_modifiers_post(
depsgraph, scene, ob, r_dispbase, for_render, force_mesh_conversion, r_final);
}
static void rotateBevelPiece(const Curve *cu,
@ -1252,8 +1244,8 @@ static void fillBevelCap(const Nurb *nu,
const float *prev_fp,
ListBase *dispbase)
{
DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), "makeDispListbev2");
dl->verts = (float *)MEM_mallocN(sizeof(float[3]) * dlb->nr, "dlverts");
DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), __func__);
dl->verts = (float *)MEM_mallocN(sizeof(float[3]) * dlb->nr, __func__);
memcpy(dl->verts, prev_fp, sizeof(float[3]) * dlb->nr);
dl->type = DL_POLY;
@ -1403,67 +1395,47 @@ static void calc_bevfac_mapping(const Curve *cu,
}
}
static void do_makeDispListCurveTypes(Depsgraph *depsgraph,
const Scene *scene,
Object *ob,
ListBase *dispbase,
const bool for_render,
const bool for_orco,
Mesh **r_final)
static void evaluate_curve_type_object(Depsgraph *depsgraph,
const Scene *scene,
Object *ob,
const bool for_render,
ListBase *r_dispbase,
Mesh **r_final)
{
BLI_assert(ELEM(ob->type, OB_CURVE, OB_FONT));
const Curve *cu = (const Curve *)ob->data;
/* we do allow duplis... this is only displist on curve level */
if (!ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
return;
}
if (ob->type == OB_SURF) {
displist_make_surf(depsgraph, scene, ob, dispbase, r_final, for_render, for_orco);
return;
}
ListBase nubase = {nullptr, nullptr};
bool force_mesh_conversion = false;
BKE_curve_bevelList_free(&ob->runtime.curve_cache->bev);
/* We only re-evaluate path if evaluation is not happening for orco.
* If the calculation happens for orco, we should never free data which
* was needed before and only not needed for orco calculation. */
if (!for_orco) {
if (ob->runtime.curve_cache->anim_path_accum_length) {
MEM_freeN((void *)ob->runtime.curve_cache->anim_path_accum_length);
}
ob->runtime.curve_cache->anim_path_accum_length = nullptr;
}
ListBase *deformed_nurbs = &ob->runtime.curve_cache->deformed_nurbs;
if (ob->type == OB_FONT) {
BKE_vfont_to_curve_nubase(ob, FO_EDIT, &nubase);
BKE_vfont_to_curve_nubase(ob, FO_EDIT, deformed_nurbs);
}
else {
BKE_nurbList_duplicate(&nubase, BKE_curve_nurbs_get(const_cast<Curve *>(cu)));
BKE_nurbList_duplicate(deformed_nurbs, BKE_curve_nurbs_get_for_read(cu));
}
if (!for_orco) {
force_mesh_conversion = BKE_curve_calc_modifiers_pre(
depsgraph, scene, ob, &nubase, &nubase, for_render);
}
bool force_mesh_conversion = BKE_curve_calc_modifiers_pre(
depsgraph, scene, ob, deformed_nurbs, deformed_nurbs, for_render);
BKE_curve_bevelList_make(ob, &nubase, for_render);
BKE_curve_bevelList_make(ob, deformed_nurbs, for_render);
if ((cu->flag & CU_PATH) ||
DEG_get_eval_flags_for_id(depsgraph, &ob->id) & DAG_EVAL_NEED_CURVE_PATH) {
BKE_anim_path_calc_data(ob);
}
/* If curve has no bevel will return nothing */
ListBase dlbev = BKE_curve_bevel_make(cu);
/* no bevel or extrude, and no width correction? */
if (BLI_listbase_is_empty(&dlbev) && cu->width == 1.0f) {
curve_to_displist(cu, &nubase, for_render, dispbase);
curve_to_displist(cu, deformed_nurbs, for_render, r_dispbase);
}
else {
const float widfac = cu->width - 1.0f;
BevList *bl = (BevList *)ob->runtime.curve_cache->bev.first;
Nurb *nu = (Nurb *)nubase.first;
const BevList *bl = (BevList *)ob->runtime.curve_cache->bev.first;
const Nurb *nu = (Nurb *)deformed_nurbs->first;
for (; bl && nu; bl = bl->next, nu = nu->next) {
float *data;
@ -1475,7 +1447,7 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph,
if (BLI_listbase_is_empty(&dlbev)) {
DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), "makeDispListbev");
dl->verts = (float *)MEM_mallocN(sizeof(float[3]) * bl->nr, "dlverts");
BLI_addtail(dispbase, dl);
BLI_addtail(r_dispbase, dl);
if (bl->poly != -1) {
dl->type = DL_POLY;
@ -1523,9 +1495,9 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph,
LISTBASE_FOREACH (DispList *, dlb, &dlbev) {
/* for each part of the bevel use a separate displblock */
DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), "makeDispListbev1");
dl->verts = data = (float *)MEM_mallocN(sizeof(float[3]) * dlb->nr * steps, "dlverts");
BLI_addtail(dispbase, dl);
DispList *dl = (DispList *)MEM_callocN(sizeof(DispList), __func__);
dl->verts = data = (float *)MEM_mallocN(sizeof(float[3]) * dlb->nr * steps, __func__);
BLI_addtail(r_dispbase, dl);
dl->type = DL_SURF;
@ -1621,62 +1593,51 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph,
}
if (bottom_capbase.first) {
BKE_displist_fill(&bottom_capbase, dispbase, bottom_no, false);
BKE_displist_fill(&top_capbase, dispbase, top_no, false);
BKE_displist_fill(&bottom_capbase, r_dispbase, bottom_no, false);
BKE_displist_fill(&top_capbase, r_dispbase, top_no, false);
BKE_displist_free(&bottom_capbase);
BKE_displist_free(&top_capbase);
}
}
}
BKE_displist_free(&dlbev);
}
BKE_displist_free(&dlbev);
if (!(cu->flag & CU_DEFORM_FILL)) {
curve_to_filledpoly(cu, dispbase);
curve_to_filledpoly(cu, r_dispbase);
}
if (!for_orco) {
if ((cu->flag & CU_PATH) ||
DEG_get_eval_flags_for_id(depsgraph, &ob->id) & DAG_EVAL_NEED_CURVE_PATH) {
BKE_anim_path_calc_data(ob);
}
BKE_nurbList_duplicate(&ob->runtime.curve_cache->deformed_nurbs, &nubase);
curve_calc_modifiers_post(
depsgraph, scene, ob, dispbase, for_render, force_mesh_conversion, r_final);
}
curve_calc_modifiers_post(
depsgraph, scene, ob, r_dispbase, for_render, force_mesh_conversion, r_final);
if (cu->flag & CU_DEFORM_FILL && !ob->runtime.data_eval) {
curve_to_filledpoly(cu, dispbase);
curve_to_filledpoly(cu, r_dispbase);
}
BKE_nurbList_free(&nubase);
}
void BKE_displist_make_curveTypes(Depsgraph *depsgraph,
const Scene *scene,
Object *ob,
const bool for_render,
const bool for_orco)
const bool for_render)
{
/* The same check for duplis as in do_makeDispListCurveTypes.
* Happens when curve used for constraint/bevel was converted to mesh.
* check there is still needed for render displist and orco displists. */
if (!ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
return;
}
BLI_assert(ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT));
BKE_object_free_derived_caches(ob);
if (!ob->runtime.curve_cache) {
ob->runtime.curve_cache = (CurveCache *)MEM_callocN(sizeof(CurveCache),
"CurveCache for curve types");
ob->runtime.curve_cache = (CurveCache *)MEM_callocN(sizeof(CurveCache), __func__);
}
ListBase *dispbase = &(ob->runtime.curve_cache->disp);
Mesh *mesh_eval = nullptr;
do_makeDispListCurveTypes(depsgraph, scene, ob, dispbase, for_render, for_orco, &mesh_eval);
if (ob->type == OB_SURF) {
evaluate_surface_object(depsgraph, scene, ob, for_render, dispbase, &mesh_eval);
}
else {
evaluate_curve_type_object(depsgraph, scene, ob, for_render, dispbase, &mesh_eval);
}
if (mesh_eval != nullptr) {
BKE_object_eval_assign_data(ob, &mesh_eval->id, true);
@ -1685,19 +1646,19 @@ void BKE_displist_make_curveTypes(Depsgraph *depsgraph,
boundbox_displist_object(ob);
}
void BKE_displist_make_curveTypes_forRender(Depsgraph *depsgraph,
const Scene *scene,
Object *ob,
ListBase *dispbase,
const bool for_orco,
Mesh **r_final)
void BKE_displist_make_curveTypes_forRender(
Depsgraph *depsgraph, const Scene *scene, Object *ob, ListBase *r_dispbase, Mesh **r_final)
{
if (ob->runtime.curve_cache == nullptr) {
ob->runtime.curve_cache = (CurveCache *)MEM_callocN(sizeof(CurveCache),
"CurveCache for Curve");
ob->runtime.curve_cache = (CurveCache *)MEM_callocN(sizeof(CurveCache), __func__);
}
do_makeDispListCurveTypes(depsgraph, scene, ob, dispbase, true, for_orco, r_final);
if (ob->type == OB_SURF) {
evaluate_surface_object(depsgraph, scene, ob, true, r_dispbase, r_final);
}
else {
evaluate_curve_type_object(depsgraph, scene, ob, true, r_dispbase, r_final);
}
}
void BKE_displist_minmax(const ListBase *dispbase, float min[3], float max[3])
@ -1730,7 +1691,7 @@ static void boundbox_displist_object(Object *ob)
/* object's BB is calculated from final displist */
if (ob->runtime.bb == nullptr) {
ob->runtime.bb = (BoundBox *)MEM_callocN(sizeof(BoundBox), "boundbox");
ob->runtime.bb = (BoundBox *)MEM_callocN(sizeof(BoundBox), __func__);
}
Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);

View File

@ -163,7 +163,7 @@ static void precalculate_effector(struct Depsgraph *depsgraph, EffectorCache *ef
if (cu->flag & CU_PATH) {
if (eff->ob->runtime.curve_cache == NULL ||
eff->ob->runtime.curve_cache->anim_path_accum_length == NULL) {
BKE_displist_make_curveTypes(depsgraph, eff->scene, eff->ob, false, false);
BKE_displist_make_curveTypes(depsgraph, eff->scene, eff->ob, false);
}
if (eff->ob->runtime.curve_cache->anim_path_accum_length) {

View File

@ -56,7 +56,7 @@ static void add_curve_data_as_geometry_component(const Object &object, GeometryS
{
BLI_assert(object.type == OB_CURVE);
if (object.data != nullptr) {
std::unique_ptr<CurveEval> curve = curve_eval_from_dna_curve(*(Curve *)object.data);
std::unique_ptr<CurveEval> curve = curve_eval_from_dna_curve(*(const Curve *)object.data);
CurveComponent &curve_component = geometry_set.get_component_for_write<CurveComponent>();
curve_component.replace(curve.release(), GeometryOwnershipType::Owned);
}

View File

@ -646,8 +646,8 @@ static void lib_override_linked_group_tag(LibOverrideGroupTagData *data)
instantiating_collection->id.lib->temp_index < id_root->lib->temp_index)) {
break;
}
else if (ID_IS_LINKED(instantiating_collection) &&
(!is_resync || instantiating_collection->id.lib == id_root->lib)) {
if (ID_IS_LINKED(instantiating_collection) &&
(!is_resync || instantiating_collection->id.lib == id_root->lib)) {
instantiating_collection_override_candidate = instantiating_collection;
}
}

View File

@ -247,7 +247,7 @@ int BKE_mesh_nurbs_to_mdata(Object *ob,
/* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */
/* use specified dispbase */
int BKE_mesh_nurbs_displist_to_mdata(Object *ob,
int BKE_mesh_nurbs_displist_to_mdata(const Object *ob,
const ListBase *dispbase,
MVert **r_allvert,
int *r_totvert,
@ -259,8 +259,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob,
int *r_totloop,
int *r_totpoly)
{
Curve *cu = ob->data;
DispList *dl;
const Curve *cu = ob->data;
MVert *mvert;
MPoly *mpoly;
MLoop *mloop;
@ -276,8 +275,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob,
(ob->type == OB_SURF));
/* count */
dl = dispbase->first;
while (dl) {
LISTBASE_FOREACH (const DispList *, dl, dispbase) {
if (dl->type == DL_SEGM) {
totvert += dl->parts * dl->nr;
totedge += dl->parts * (dl->nr - 1);
@ -305,7 +303,6 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob,
totpoly += tot;
totloop += tot * 3;
}
dl = dl->next;
}
if (totvert == 0) {
@ -327,8 +324,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob,
/* verts and faces */
vertcount = 0;
dl = dispbase->first;
while (dl) {
LISTBASE_FOREACH (const DispList *, dl, dispbase) {
const bool is_smooth = (dl->rt & CU_SMOOTH) != 0;
if (dl->type == DL_SEGM) {
@ -507,8 +503,6 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob,
}
}
}
dl = dl->next;
}
if (totpoly) {
@ -523,7 +517,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob,
return 0;
}
Mesh *BKE_mesh_new_nomain_from_curve_displist(Object *ob, ListBase *dispbase)
Mesh *BKE_mesh_new_nomain_from_curve_displist(const Object *ob, const ListBase *dispbase)
{
Mesh *mesh;
MVert *allvert;
@ -551,10 +545,18 @@ Mesh *BKE_mesh_new_nomain_from_curve_displist(Object *ob, ListBase *dispbase)
mesh = BKE_mesh_new_nomain(totvert, totedge, 0, totloop, totpoly);
mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
memcpy(mesh->mvert, allvert, totvert * sizeof(MVert));
memcpy(mesh->medge, alledge, totedge * sizeof(MEdge));
memcpy(mesh->mloop, allloop, totloop * sizeof(MLoop));
memcpy(mesh->mpoly, allpoly, totpoly * sizeof(MPoly));
if (totvert != 0) {
memcpy(mesh->mvert, allvert, totvert * sizeof(MVert));
}
if (totedge != 0) {
memcpy(mesh->medge, alledge, totedge * sizeof(MEdge));
}
if (totloop != 0) {
memcpy(mesh->mloop, allloop, totloop * sizeof(MLoop));
}
if (totpoly != 0) {
memcpy(mesh->mpoly, allpoly, totpoly * sizeof(MPoly));
}
if (alluv) {
const char *uvname = "UVMap";
@ -1113,7 +1115,7 @@ static void curve_to_mesh_eval_ensure(Object *object)
* Brecht says hold off with that. */
Mesh *mesh_eval = NULL;
BKE_displist_make_curveTypes_forRender(
NULL, NULL, &remapped_object, &remapped_object.runtime.curve_cache->disp, false, &mesh_eval);
NULL, NULL, &remapped_object, &remapped_object.runtime.curve_cache->disp, &mesh_eval);
/* Note: this is to be consistent with `BKE_displist_make_curveTypes()`, however that is not a
* real issue currently, code here is broken in more than one way, fix(es) will be done

View File

@ -224,7 +224,7 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
case OB_SURF:
case OB_FONT: {
bool for_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
BKE_displist_make_curveTypes(depsgraph, scene, ob, for_render, false);
BKE_displist_make_curveTypes(depsgraph, scene, ob, for_render);
break;
}

View File

@ -228,7 +228,10 @@ static void scene_init_data(ID *id)
/* Curve Profile */
scene->toolsettings->custom_bevel_profile_preset = BKE_curveprofile_add(PROF_PRESET_LINE);
/* Sequencer */
scene->toolsettings->sequencer_tool_settings = SEQ_tool_settings_init();
scene->toolsettings->snap_flag |= SCE_SNAP_SEQ;
for (size_t i = 0; i < ARRAY_SIZE(scene->orientation_slots); i++) {
scene->orientation_slots[i].index_custom = -1;

View File

@ -213,7 +213,8 @@ class Vector {
* Example Usage:
* Vector<ModifierData *> modifiers(ob->modifiers);
*/
Vector(ListBase &values, Allocator allocator = {}) : Vector(NoExceptConstructor(), allocator)
Vector(const ListBase &values, Allocator allocator = {})
: Vector(NoExceptConstructor(), allocator)
{
LISTBASE_FOREACH (T, value, &values) {
this->append(value);

View File

@ -92,12 +92,12 @@ static const char *utf8_invalid_tests[][3] = {
"\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
"\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
"\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\" |",
"3.1.9 \"\" |", "\x40"},
"3.1.9 \"\" |", "\x40"}, /* NOLINT: modernize-raw-string-literal. */
/* 3.2 Lonely start characters
* 3.2.1 All 32 first bytes of 2-byte sequences (0xc0-0xdf), each followed by a space character: */
{"3.2.1 \"\xc0 \xc1 \xc2 \xc3 \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf "
"\xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf \" |",
"3.2.1 \" \" |", "\x20"},
"3.2.1 \" \" |", "\x20"}, /* NOLINT: modernize-raw-string-literal. */
/* 3.2.2 All 16 first bytes of 3-byte sequences (0xe0-0xef), each followed by a space character: */
{"3.2.2 \"\xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef \" |",
"3.2.2 \" \" |", "\x10"},

View File

@ -44,6 +44,8 @@
#include "readfile.h"
#include "versioning_common.h"
#include "SEQ_sequencer.h"
#include "MEM_guardedalloc.h"
#include "versioning_common.h"
@ -430,6 +432,37 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 300, 7)) {
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
ToolSettings *tool_settings = scene->toolsettings;
tool_settings->snap_flag |= SCE_SNAP_SEQ;
short snap_mode = tool_settings->snap_mode;
short snap_node_mode = tool_settings->snap_node_mode;
tool_settings->snap_mode &= ~((1 << 4) | (1 << 5) | (1 << 6));
tool_settings->snap_node_mode &= ~((1 << 5) | (1 << 6));
if (snap_mode & (1 << 4)) {
tool_settings->snap_mode |= (1 << 6); /* SCE_SNAP_MODE_INCREMENT */
}
if (snap_mode & (1 << 5)) {
tool_settings->snap_mode |= (1 << 4); /* SCE_SNAP_MODE_EDGE_MIDPOINT */
}
if (snap_mode & (1 << 6)) {
tool_settings->snap_mode |= (1 << 5); /* SCE_SNAP_MODE_EDGE_PERPENDICULAR */
}
if (snap_node_mode & (1 << 5)) {
tool_settings->snap_node_mode |= (1 << 0); /* SCE_SNAP_MODE_NODE_X */
}
if (snap_node_mode & (1 << 6)) {
tool_settings->snap_node_mode |= (1 << 1); /* SCE_SNAP_MODE_NODE_Y */
}
SequencerToolSettings *sequencer_tool_settings = SEQ_tool_settings_ensure(scene);
sequencer_tool_settings->snap_mode = SEQ_SNAP_TO_STRIPS | SEQ_SNAP_TO_PLAYHEAD |
SEQ_SNAP_TO_STRIP_HOLD;
sequencer_tool_settings->snap_distance = 15;
}
}
/**
* Versioning code until next subversion bump goes here.
*

View File

@ -123,7 +123,7 @@ bool BlendfileLoadingBaseTest::blendfile_load(const char *filepath)
char abspath[FILENAME_MAX];
BLI_path_join(abspath, sizeof(abspath), test_assets_dir.c_str(), filepath, NULL);
BlendFileReadReport bf_reports = {NULL};
BlendFileReadReport bf_reports = {nullptr};
bfile = BLO_read_from_file(abspath, BLO_READ_SKIP_NONE, &bf_reports);
if (bfile == nullptr) {
ADD_FAILURE() << "Unable to load file '" << filepath << "' from test assets dir '"

View File

@ -2434,6 +2434,7 @@ static int animchannels_clean_empty_exec(bContext *C, wmOperator *UNUSED(op))
/* send notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_REMOVED, NULL);
return OPERATOR_FINISHED;
}

View File

@ -2425,12 +2425,20 @@ void uiItemPopoverPanelFromGroup(uiLayout *layout,
void uiItemMenuF(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg);
void uiItemMenuFN(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *argN);
void uiItemMenuEnumO_ptr(uiLayout *layout,
void uiItemMenuEnumFullO_ptr(uiLayout *layout,
struct bContext *C,
struct wmOperatorType *ot,
const char *propname,
const char *name,
int icon,
struct PointerRNA *r_opptr);
void uiItemMenuEnumFullO(uiLayout *layout,
struct bContext *C,
struct wmOperatorType *ot,
const char *opname,
const char *propname,
const char *name,
int icon);
int icon,
struct PointerRNA *r_opptr);
void uiItemMenuEnumO(uiLayout *layout,
struct bContext *C,
const char *opname,

View File

@ -2108,7 +2108,8 @@ int ui_but_is_pushed_ex(uiBut *but, double *value)
if (but->pushed_state_func) {
return but->pushed_state_func(but, but->pushed_state_arg);
}
else if (but->bit) {
if (but->bit) {
const bool state = !ELEM(
but->type, UI_BTYPE_TOGGLE_N, UI_BTYPE_ICON_TOGGLE_N, UI_BTYPE_CHECKBOX_N);
int lvalue;

View File

@ -4552,7 +4552,7 @@ static int ui_do_but_TEX(
if (ELEM(event->type, EVT_PADENTER, EVT_RETKEY) && (!UI_but_is_utf8(but))) {
/* pass - allow filesel, enter to execute */
}
else if (but->emboss == UI_EMBOSS_NONE && !event->ctrl) {
else if (ELEM(but->emboss, UI_EMBOSS_NONE, UI_EMBOSS_NONE_OR_STATUS) && !event->ctrl) {
/* pass */
}
else {

View File

@ -2355,7 +2355,7 @@ void uiItemFullR(uiLayout *layout,
/* Mark non-embossed textfields inside a listbox. */
if (but && (block->flag & UI_BLOCK_LIST_ITEM) && (but->type == UI_BTYPE_TEXT) &&
(but->emboss & UI_EMBOSS_NONE)) {
ELEM(but->emboss, UI_EMBOSS_NONE, UI_EMBOSS_NONE_OR_STATUS)) {
UI_but_flag_enable(but, UI_BUT_LIST_ITEM);
}
@ -3381,10 +3381,13 @@ typedef struct MenuItemLevel {
static void menu_item_enum_opname_menu(bContext *UNUSED(C), uiLayout *layout, void *arg)
{
MenuItemLevel *lvl = (MenuItemLevel *)(((uiBut *)arg)->func_argN);
uiBut *but = arg;
MenuItemLevel *lvl = but->func_argN;
/* Use the operator properties from the button owning the menu. */
IDProperty *op_props = but->opptr ? but->opptr->data : NULL;
uiLayoutSetOperatorContext(layout, lvl->opcontext);
uiItemsEnumO(layout, lvl->opname, lvl->propname);
uiItemsFullEnumO(layout, lvl->opname, lvl->propname, op_props, lvl->opcontext, 0);
layout->root->block->flag |= UI_BLOCK_IS_FLIP;
@ -3392,12 +3395,13 @@ static void menu_item_enum_opname_menu(bContext *UNUSED(C), uiLayout *layout, vo
UI_block_direction_set(layout->root->block, UI_DIR_DOWN);
}
void uiItemMenuEnumO_ptr(uiLayout *layout,
bContext *C,
wmOperatorType *ot,
const char *propname,
const char *name,
int icon)
void uiItemMenuEnumFullO_ptr(uiLayout *layout,
bContext *C,
wmOperatorType *ot,
const char *propname,
const char *name,
int icon,
PointerRNA *r_opptr)
{
/* Caller must check */
BLI_assert(ot->srna != NULL);
@ -3416,6 +3420,15 @@ void uiItemMenuEnumO_ptr(uiLayout *layout,
lvl->opcontext = layout->root->opcontext;
uiBut *but = ui_item_menu(layout, name, icon, menu_item_enum_opname_menu, NULL, lvl, NULL, true);
/* Use the menu button as owner for the operator properties, which will then be passed to the
* individual menu items. */
if (r_opptr) {
but->opptr = MEM_callocN(sizeof(PointerRNA), "uiButOpPtr");
WM_operator_properties_create_ptr(but->opptr, ot);
BLI_assert(but->opptr->data == NULL);
WM_operator_properties_alloc(&but->opptr, (IDProperty **)&but->opptr->data, ot->idname);
*r_opptr = *but->opptr;
}
/* add hotkey here, lower UI code can't detect it */
if ((layout->root->block->flag & UI_BLOCK_LOOP) && (ot->prop && ot->invoke)) {
@ -3427,12 +3440,13 @@ void uiItemMenuEnumO_ptr(uiLayout *layout,
}
}
void uiItemMenuEnumO(uiLayout *layout,
bContext *C,
const char *opname,
const char *propname,
const char *name,
int icon)
void uiItemMenuEnumFullO(uiLayout *layout,
bContext *C,
const char *opname,
const char *propname,
const char *name,
int icon,
PointerRNA *r_opptr)
{
wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
@ -3444,7 +3458,17 @@ void uiItemMenuEnumO(uiLayout *layout,
return;
}
uiItemMenuEnumO_ptr(layout, C, ot, propname, name, icon);
uiItemMenuEnumFullO_ptr(layout, C, ot, propname, name, icon, r_opptr);
}
void uiItemMenuEnumO(uiLayout *layout,
bContext *C,
const char *opname,
const char *propname,
const char *name,
int icon)
{
uiItemMenuEnumFullO(layout, C, opname, propname, name, icon, NULL);
}
static void menu_item_enum_rna_menu(bContext *UNUSED(C), uiLayout *layout, void *arg)

View File

@ -91,7 +91,8 @@ bool ui_but_is_interactive(const uiBut *but, const bool labeledit)
if (but->flag & UI_SCROLLED) {
return false;
}
if ((but->type == UI_BTYPE_TEXT) && (but->emboss == UI_EMBOSS_NONE) && !labeledit) {
if ((but->type == UI_BTYPE_TEXT) &&
(ELEM(but->emboss, UI_EMBOSS_NONE, UI_EMBOSS_NONE_OR_STATUS)) && !labeledit) {
return false;
}
if ((but->type == UI_BTYPE_LISTROW) && labeledit) {

View File

@ -2575,7 +2575,7 @@ static void object_data_convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *
if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
/* We need 'for render' ON here, to enable computing bevel dipslist if needed.
* Also makes sense anyway, we would not want e.g. to lose hidden parts etc. */
BKE_displist_make_curveTypes(depsgraph, scene, ob, true, false);
BKE_displist_make_curveTypes(depsgraph, scene, ob, true);
}
else if (ob->type == OB_MBALL) {
BKE_displist_make_mball(depsgraph, scene, ob);

View File

@ -125,7 +125,7 @@ static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object *
BKE_displist_make_mball(depsgraph, scene_eval, ob_eval);
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false, false);
BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false);
}
else if (ob->type == OB_GPENCIL) {
BKE_gpencil_modifiers_calc(depsgraph, scene_eval, ob_eval);

View File

@ -715,7 +715,7 @@ bool ED_object_parent_set(ReportList *reports,
cu->flag |= CU_PATH | CU_FOLLOW;
cu_eval->flag |= CU_PATH | CU_FOLLOW;
/* force creation of path data */
BKE_displist_make_curveTypes(depsgraph, scene, par, false, false);
BKE_displist_make_curveTypes(depsgraph, scene, par, false);
}
else {
cu->flag |= CU_FOLLOW;

View File

@ -709,7 +709,7 @@ static int apply_objects_internal(bContext *C,
if (has_unparented_layers == false) {
BKE_reportf(reports,
RPT_ERROR,
"Can't apply to a GP datablock where all layers are parented: Object "
"Can't apply to a GP data-block where all layers are parented: Object "
"\"%s\", %s \"%s\", aborting",
ob->id.name + 2,
BKE_idtype_idcode_to_name(ID_GD),
@ -722,7 +722,7 @@ static int apply_objects_internal(bContext *C,
BKE_reportf(
reports,
RPT_ERROR,
"Can't apply to GP datablock with no layers: Object \"%s\", %s \"%s\", aborting",
"Can't apply to GP data-block with no layers: Object \"%s\", %s \"%s\", aborting",
ob->id.name + 2,
BKE_idtype_idcode_to_name(ID_GD),
gpd->id.name + 2);
@ -1255,7 +1255,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
}
}
else if (ob->type == OB_FONT) {
/* Det from bounding-box. */
/* Get from bounding-box. */
Curve *cu = ob->data;
@ -1490,7 +1490,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
BKE_object_batch_cache_dirty_tag(tob);
DEG_id_tag_update(&tob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
}
/* special support for dupligroups */
/* Special support for dupli-groups. */
else if (tob->instance_collection && tob->instance_collection->id.tag & LIB_TAG_DOIT) {
DEG_id_tag_update(&tob->id, ID_RECALC_TRANSFORM);
DEG_id_tag_update(&tob->instance_collection->id, ID_RECALC_COPY_ON_WRITE);

View File

@ -1564,6 +1564,14 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, const
BLI_assert(CTX_wm_screen(C) == screen);
BLI_assert(CTX_wm_area(C) == NULL); /* May have been freed. */
/* Setting the area is only needed for Python scripts that call
* operators in succession before returning to the main event loop.
* Without this, scripts can't run any operators that require
* an area after toggling full-screen for example (see: T89526).
* NOTE: an old comment stated this was "bad code",
* however it doesn't cause problems so leave as-is. */
CTX_wm_area_set(C, screen->areabase.first);
return screen->areabase.first;
}

View File

@ -489,7 +489,8 @@ static void file_draw_preview(const SpaceFile *sfile,
UI_but_drag_set_id(but, id);
}
/* path is no more static, cannot give it directly to but... */
else if (file->typeflag & FILE_TYPE_ASSET) {
else if (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS &&
(file->typeflag & FILE_TYPE_ASSET) != 0) {
char blend_path[FILE_MAX_LIBEXTRA];
if (BLO_library_path_explode(path, blend_path, NULL, NULL)) {

View File

@ -1766,7 +1766,7 @@ static void node_update(const bContext *C, bNodeTree *ntree, bNode *node)
}
}
static void count_mutli_input_socket_links(bNodeTree *ntree, SpaceNode *snode)
static void count_multi_input_socket_links(bNodeTree *ntree, SpaceNode *snode)
{
Map<bNodeSocket *, int> counts;
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
@ -1800,7 +1800,7 @@ void node_update_nodetree(const bContext *C, bNodeTree *ntree)
SpaceNode *snode = CTX_wm_space_node(C);
ntreeTagUsedSockets(ntree);
count_mutli_input_socket_links(ntree, snode);
count_multi_input_socket_links(ntree, snode);
/* Update nodes front to back, so children sizes get updated before parents. */
LISTBASE_FOREACH_BACKWARD (bNode *, node, &ntree->nodes) {

View File

@ -606,7 +606,7 @@ static void spreadsheet_dataset_region_draw(const bContext *C, ARegion *region)
UI_view2d_view_restore(C);
/* scrollers */
UI_view2d_scrollers_draw(v2d, NULL);
UI_view2d_scrollers_draw(v2d, nullptr);
}
static void spreadsheet_sidebar_init(wmWindowManager *wm, ARegion *region)

View File

@ -119,7 +119,7 @@ void DatasetRegionDrawer::draw_hierarchy(const DatasetLayoutHierarchy &layout)
/* Iterate attribute domains, skip unset ones (storage has to be in a enum-based, fixed size
* array so uses optionals to support skipping enum values that shouldn't be displayed for a
* component). */
for (auto &optional_domain : component.attr_domains) {
for (const auto &optional_domain : component.attr_domains) {
if (!optional_domain) {
continue;
}
@ -212,7 +212,7 @@ void DatasetRegionDrawer::draw_dataset_row(const int indentation,
rect.ymin,
BLI_rctf_size_x(&rect),
BLI_rctf_size_y(&rect),
NULL);
nullptr);
UI_but_datasetrow_indentation_set(bt, indentation);

View File

@ -114,7 +114,7 @@ static int select_component_domain_invoke(bContext *C,
sspreadsheet->attribute_domain = attribute_domain;
/* Refresh header and main region. */
WM_main_add_notifier(NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
WM_main_add_notifier(NC_SPACE | ND_SPACE_SPREADSHEET, nullptr);
return OPERATOR_FINISHED;
}

View File

@ -102,6 +102,7 @@ set(SRC
transform_orientations.c
transform_snap.c
transform_snap_object.c
transform_snap_sequencer.c
transform.h
transform_constraints.h

View File

@ -1697,31 +1697,11 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->draw_handle_cursor = WM_paint_cursor_activate(
SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t);
}
else if (t->spacetype == SPACE_IMAGE) {
else if (t->spacetype == SPACE_SEQ) {
t->draw_handle_view = ED_region_draw_cb_activate(
t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_cursor = WM_paint_cursor_activate(
SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t);
}
else if (t->spacetype == SPACE_CLIP) {
t->draw_handle_view = ED_region_draw_cb_activate(
t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_cursor = WM_paint_cursor_activate(
SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t);
}
else if (t->spacetype == SPACE_NODE) {
t->draw_handle_view = ED_region_draw_cb_activate(
t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_cursor = WM_paint_cursor_activate(
SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t);
}
else if (t->spacetype == SPACE_GRAPH) {
t->draw_handle_view = ED_region_draw_cb_activate(
t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_cursor = WM_paint_cursor_activate(
SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t);
}
else if (t->spacetype == SPACE_ACTION) {
else if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_CLIP, SPACE_NODE, SPACE_GRAPH, SPACE_ACTION)) {
t->draw_handle_view = ED_region_draw_cb_activate(
t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_cursor = WM_paint_cursor_activate(

View File

@ -335,7 +335,10 @@ typedef struct TransSnap {
/**
* Re-usable snap context data.
*/
struct SnapObjectContext *object_context;
union {
struct SnapObjectContext *object_context;
struct TransSeqSnapData *seq_context;
};
} TransSnap;
typedef struct TransCon {
@ -356,22 +359,22 @@ typedef struct TransCon {
/** Apply function pointer for linear vectorial transformation
* The last three parameters are pointers to the in/out/printable vectors. */
void (*applyVec)(struct TransInfo *t,
struct TransDataContainer *tc,
void (*applyVec)(const struct TransInfo *t,
const struct TransDataContainer *tc,
struct TransData *td,
const float in[3],
float out[3]);
float r_out[3]);
/** Apply function pointer for size transformation. */
void (*applySize)(struct TransInfo *t,
struct TransDataContainer *tc,
void (*applySize)(const struct TransInfo *t,
const struct TransDataContainer *tc,
struct TransData *td,
float smat[3][3]);
float r_smat[3][3]);
/** Apply function pointer for rotation transformation */
void (*applyRot)(struct TransInfo *t,
struct TransDataContainer *tc,
void (*applyRot)(const struct TransInfo *t,
const struct TransDataContainer *tc,
struct TransData *td,
float vec[3],
float *angle);
float r_axis[3],
float *r_angle);
} TransCon;
typedef struct MouseInput {

View File

@ -97,7 +97,7 @@ static void view_vector_calc(const TransInfo *t, const float focus[3], float r_v
/* ************************** CONSTRAINTS ************************* */
#define CONSTRAIN_EPSILON 0.0001f
static void constraint_plane_calc(TransInfo *t, float r_plane[4])
static void constraint_plane_calc(const TransInfo *t, float r_plane[4])
{
const float *constraint_vector[2];
int n = 0;
@ -391,8 +391,11 @@ static void planeProjection(const TransInfo *t, const float in[3], float out[3])
* projected along the view vector.
* (in perspective mode, the view vector is relative to the position on screen)
*/
static void applyAxisConstraintVec(
TransInfo *t, TransDataContainer *UNUSED(tc), TransData *td, const float in[3], float out[3])
static void applyAxisConstraintVec(const TransInfo *t,
const TransDataContainer *UNUSED(tc),
TransData *td,
const float in[3],
float out[3])
{
copy_v3_v3(out, in);
if (!td && t->con.mode & CON_APPLY) {
@ -472,8 +475,11 @@ static void applyAxisConstraintVec(
*
* Further down, that vector is mapped to each data's space.
*/
static void applyObjectConstraintVec(
TransInfo *t, TransDataContainer *tc, TransData *td, const float in[3], float out[3])
static void applyObjectConstraintVec(const TransInfo *t,
const TransDataContainer *tc,
TransData *td,
const float in[3],
float out[3])
{
if (!td) {
applyAxisConstraintVec(t, tc, td, in, out);
@ -494,36 +500,36 @@ static void applyObjectConstraintVec(
/**
* Generic callback for constant spatial constraints applied to resize motion.
*/
static void applyAxisConstraintSize(TransInfo *t,
TransDataContainer *UNUSED(tc),
static void applyAxisConstraintSize(const TransInfo *t,
const TransDataContainer *UNUSED(tc),
TransData *td,
float smat[3][3])
float r_smat[3][3])
{
if (!td && t->con.mode & CON_APPLY) {
float tmat[3][3];
if (!(t->con.mode & CON_AXIS0)) {
smat[0][0] = 1.0f;
r_smat[0][0] = 1.0f;
}
if (!(t->con.mode & CON_AXIS1)) {
smat[1][1] = 1.0f;
r_smat[1][1] = 1.0f;
}
if (!(t->con.mode & CON_AXIS2)) {
smat[2][2] = 1.0f;
r_smat[2][2] = 1.0f;
}
mul_m3_m3m3(tmat, smat, t->spacemtx_inv);
mul_m3_m3m3(smat, t->spacemtx, tmat);
mul_m3_m3m3(tmat, r_smat, t->spacemtx_inv);
mul_m3_m3m3(r_smat, t->spacemtx, tmat);
}
}
/**
* Callback for object based spatial constraints applied to resize motion.
*/
static void applyObjectConstraintSize(TransInfo *t,
TransDataContainer *tc,
static void applyObjectConstraintSize(const TransInfo *t,
const TransDataContainer *tc,
TransData *td,
float smat[3][3])
float r_smat[3][3])
{
if (td && t->con.mode & CON_APPLY) {
float tmat[3][3];
@ -532,26 +538,26 @@ static void applyObjectConstraintSize(TransInfo *t,
invert_m3_m3(imat, td->axismtx);
if (!(t->con.mode & CON_AXIS0)) {
smat[0][0] = 1.0f;
r_smat[0][0] = 1.0f;
}
if (!(t->con.mode & CON_AXIS1)) {
smat[1][1] = 1.0f;
r_smat[1][1] = 1.0f;
}
if (!(t->con.mode & CON_AXIS2)) {
smat[2][2] = 1.0f;
r_smat[2][2] = 1.0f;
}
mul_m3_m3m3(tmat, smat, imat);
mul_m3_m3m3(tmat, r_smat, imat);
if (t->flag & T_EDIT) {
mul_m3_m3m3(smat, tc->mat3_unit, smat);
mul_m3_m3m3(r_smat, tc->mat3_unit, r_smat);
}
mul_m3_m3m3(smat, td->axismtx, tmat);
mul_m3_m3m3(r_smat, td->axismtx, tmat);
}
}
static void constraints_rotation_impl(TransInfo *t,
static void constraints_rotation_impl(const TransInfo *t,
const float axismtx[3][3],
float r_vec[3],
float r_axis[3],
float *r_angle)
{
BLI_assert(t->con.mode & CON_APPLY);
@ -560,15 +566,15 @@ static void constraints_rotation_impl(TransInfo *t,
switch (mode) {
case CON_AXIS0:
case (CON_AXIS1 | CON_AXIS2):
copy_v3_v3(r_vec, axismtx[0]);
copy_v3_v3(r_axis, axismtx[0]);
break;
case CON_AXIS1:
case (CON_AXIS0 | CON_AXIS2):
copy_v3_v3(r_vec, axismtx[1]);
copy_v3_v3(r_axis, axismtx[1]);
break;
case CON_AXIS2:
case (CON_AXIS0 | CON_AXIS1):
copy_v3_v3(r_vec, axismtx[2]);
copy_v3_v3(r_axis, axismtx[2]);
break;
}
/* don't flip axis if asked to or if num input */
@ -576,7 +582,7 @@ static void constraints_rotation_impl(TransInfo *t,
!((mode & CON_NOFLIP) || hasNumInput(&t->num) || (t->flag & T_INPUT_IS_VALUES_FINAL))) {
float view_vector[3];
view_vector_calc(t, t->center_global, view_vector);
if (dot_v3v3(r_vec, view_vector) > 0.0f) {
if (dot_v3v3(r_axis, view_vector) > 0.0f) {
*r_angle = -(*r_angle);
}
}
@ -595,11 +601,14 @@ static void constraints_rotation_impl(TransInfo *t,
* This insures that the rotation is always logically following the mouse.
* (ie: not doing counterclockwise rotations when the mouse moves clockwise).
*/
static void applyAxisConstraintRot(
TransInfo *t, TransDataContainer *UNUSED(tc), TransData *td, float vec[3], float *angle)
static void applyAxisConstraintRot(const TransInfo *t,
const TransDataContainer *UNUSED(tc),
TransData *td,
float r_axis[3],
float *r_angle)
{
if (!td && t->con.mode & CON_APPLY) {
constraints_rotation_impl(t, t->spacemtx, vec, angle);
constraints_rotation_impl(t, t->spacemtx, r_axis, r_angle);
}
}
@ -616,8 +625,11 @@ static void applyAxisConstraintRot(
* This insures that the rotation is always logically following the mouse.
* (ie: not doing counterclockwise rotations when the mouse moves clockwise).
*/
static void applyObjectConstraintRot(
TransInfo *t, TransDataContainer *tc, TransData *td, float vec[3], float *angle)
static void applyObjectConstraintRot(const TransInfo *t,
const TransDataContainer *tc,
TransData *td,
float r_axis[3],
float *r_angle)
{
if (t->con.mode & CON_APPLY) {
float tmp_axismtx[3][3];
@ -638,7 +650,7 @@ static void applyObjectConstraintRot(
axismtx = td->axismtx;
}
constraints_rotation_impl(t, axismtx, vec, angle);
constraints_rotation_impl(t, axismtx, r_axis, r_angle);
}
}
@ -1164,7 +1176,7 @@ bool isLockConstraint(TransInfo *t)
* even if they aren't actually used in the callback function.
* (Which could happen for weird constraints not yet designed. Along a path for example.)
*/
int getConstraintSpaceDimension(TransInfo *t)
int getConstraintSpaceDimension(const TransInfo *t)
{
int n = 0;

View File

@ -47,4 +47,4 @@ void setNearestAxis(TransInfo *t);
int constraintModeToIndex(const TransInfo *t);
char constraintModeToChar(const TransInfo *t);
bool isLockConstraint(TransInfo *t);
int getConstraintSpaceDimension(TransInfo *t);
int getConstraintSpaceDimension(const TransInfo *t);

View File

@ -48,8 +48,8 @@ void clipUVData(TransInfo *t);
void transform_convert_mesh_customdatacorrect_init(TransInfo *t);
/* transform_convert_sequencer.c */
int transform_convert_sequencer_get_snap_bound(TransInfo *t);
void transform_convert_sequencer_channel_clamp(TransInfo *t);
void transform_convert_sequencer_channel_clamp(TransInfo *t, float r_val[2]);
/********************* intern **********************/
/* transform_convert.c */

View File

@ -63,9 +63,6 @@ typedef struct TransDataSeq {
*/
typedef struct TransSeq {
TransDataSeq *tdseq;
int min;
int max;
bool snap_left;
int selection_channel_range_min;
int selection_channel_range_max;
} TransSeq;
@ -252,42 +249,6 @@ static int SeqToTransData_build(
return tot;
}
static void SeqTransDataBounds(TransInfo *t, ListBase *seqbase, TransSeq *ts)
{
Sequence *seq;
int count, flag;
int max = INT32_MIN, min = INT32_MAX;
for (seq = seqbase->first; seq; seq = seq->next) {
/* just to get the flag since there are corner cases where this isn't totally obvious */
SeqTransInfo(t, seq, &count, &flag);
/* use 'flag' which is derived from seq->flag but modified for special cases */
if (flag & SELECT) {
if (flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) {
if (flag & SEQ_LEFTSEL) {
min = min_ii(seq->startdisp, min);
max = max_ii(seq->startdisp, max);
}
if (flag & SEQ_RIGHTSEL) {
min = min_ii(seq->enddisp, min);
max = max_ii(seq->enddisp, max);
}
}
else {
min = min_ii(seq->startdisp, min);
max = max_ii(seq->enddisp, max);
}
}
}
if (ts) {
ts->max = max;
ts->min = min;
}
}
static void free_transform_custom_data(TransCustomData *custom_data)
{
if ((custom_data->data != NULL) && custom_data->use_free) {
@ -544,15 +505,6 @@ void createTransSeqData(TransInfo *t)
/* loop 2: build transdata array */
SeqToTransData_build(t, ed->seqbasep, td, td2d, tdsq);
SeqTransDataBounds(t, ed->seqbasep, ts);
if (t->flag & T_MODAL) {
/* set the snap mode based on how close the mouse is at the end/start points */
int xmouse = (int)UI_view2d_region_to_view_x((View2D *)t->view, t->mouse.imval[0]);
if (abs(xmouse - ts->max) > abs(xmouse - ts->min)) {
ts->snap_left = true;
}
}
ts->selection_channel_range_min = MAXSEQ + 1;
LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
@ -719,25 +671,19 @@ void special_aftertrans_update__sequencer(bContext *UNUSED(C), TransInfo *t)
}
}
void transform_convert_sequencer_channel_clamp(TransInfo *t)
void transform_convert_sequencer_channel_clamp(TransInfo *t, float r_val[2])
{
const TransSeq *ts = (TransSeq *)TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->custom.type.data;
const int channel_offset = round_fl_to_int(t->values[1]);
const int channel_offset = round_fl_to_int(r_val[1]);
const int min_channel_after_transform = ts->selection_channel_range_min + channel_offset;
const int max_channel_after_transform = ts->selection_channel_range_max + channel_offset;
if (max_channel_after_transform > MAXSEQ) {
t->values[1] -= max_channel_after_transform - MAXSEQ;
r_val[1] -= max_channel_after_transform - MAXSEQ;
}
if (min_channel_after_transform < 1) {
t->values[1] -= min_channel_after_transform - 1;
r_val[1] -= min_channel_after_transform - 1;
}
}
int transform_convert_sequencer_get_snap_bound(TransInfo *t)
{
TransSeq *ts = TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->custom.type.data;
return ts->snap_left ? ts->min : ts->max;
}
/** \} */

View File

@ -68,7 +68,7 @@ int transform_mode_really_used(bContext *C, int mode)
return mode;
}
bool transdata_check_local_center(TransInfo *t, short around)
bool transdata_check_local_center(const TransInfo *t, short around)
{
return ((around == V3D_AROUND_LOCAL_ORIGINS) &&
((t->options & (CTX_OBJECT | CTX_POSE_BONE)) ||
@ -248,7 +248,7 @@ void protectedSizeBits(short protectflag, float size[3])
/** \name Transform Limits
* \{ */
void constraintTransLim(TransInfo *t, TransData *td)
void constraintTransLim(const TransInfo *t, TransData *td)
{
if (td->con) {
const bConstraintTypeInfo *ctiLoc = BKE_constraint_typeinfo_from_type(
@ -359,7 +359,7 @@ static void constraintob_from_transdata(bConstraintOb *cob, TransData *td)
}
}
static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
static void constraintRotLim(const TransInfo *UNUSED(t), TransData *td)
{
if (td->con) {
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_ROTLIMIT);
@ -432,7 +432,7 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
}
}
void constraintSizeLim(TransInfo *t, TransData *td)
void constraintSizeLim(const TransInfo *t, TransData *td)
{
if (td->con && td->ext) {
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_SIZELIMIT);
@ -557,8 +557,8 @@ void headerRotation(TransInfo *t, char *str, const int str_size, float final)
*
* Protected axis and other transform settings are taken into account.
*/
void ElementRotation_ex(TransInfo *t,
TransDataContainer *tc,
void ElementRotation_ex(const TransInfo *t,
const TransDataContainer *tc,
TransData *td,
const float mat[3][3],
const float *center)
@ -810,8 +810,11 @@ void ElementRotation_ex(TransInfo *t,
}
}
void ElementRotation(
TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around)
void ElementRotation(const TransInfo *t,
const TransDataContainer *tc,
TransData *td,
const float mat[3][3],
const short around)
{
const float *center;
@ -921,7 +924,10 @@ static void TransMat3ToSize(const float mat[3][3], const float smat[3][3], float
}
}
void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3])
void ElementResize(const TransInfo *t,
const TransDataContainer *tc,
TransData *td,
const float mat[3][3])
{
float tmat[3][3], smat[3][3], center[3];
float vec[3];
@ -1014,17 +1020,31 @@ void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, float ma
sub_v3_v3(vec, td->center);
}
/* grease pencil falloff */
/* Grease pencil falloff.
*
* FIXME: This is bad on multiple levels!
*
* - #applyNumInput is not intended to be run for every element,
* this writes back into the number input in a way that doesn't make sense to run many times.
*
* - Writing into #TransInfo should be avoided since it means order of operations
* may impact the result and isn't thread-safe.
*
* Operating on copies as a temporary solution.
*/
if (t->options & CTX_GPENCIL_STROKES) {
bGPDstroke *gps = (bGPDstroke *)td->extra;
mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff);
/* scale stroke thickness */
/* Scale stroke thickness. */
if (td->val) {
transform_snap_increment(t, t->values_final);
applyNumInput(&t->num, t->values_final);
NumInput num_evil = t->num;
float values_final_evil[4];
copy_v4_v4(values_final_evil, t->values_final);
transform_snap_increment(t, values_final_evil);
applyNumInput(&num_evil, values_final_evil);
float ratio = t->values_final[0];
float ratio = values_final_evil[0];
*td->val = td->ival * ratio * gps->runtime.multi_frame_falloff;
CLAMP_MIN(*td->val, 0.001f);
}
@ -1044,6 +1064,7 @@ void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, float ma
constraintTransLim(t, td);
}
/** \} */
/* -------------------------------------------------------------------- */

View File

@ -41,22 +41,28 @@ typedef struct TransDataGenericSlideVert {
/* transform_mode.c */
int transform_mode_really_used(struct bContext *C, int mode);
bool transdata_check_local_center(TransInfo *t, short around);
bool transdata_check_local_center(const TransInfo *t, short around);
bool transform_mode_is_changeable(const int mode);
void protectedTransBits(short protectflag, float vec[3]);
void protectedSizeBits(short protectflag, float size[3]);
void constraintTransLim(TransInfo *t, TransData *td);
void constraintSizeLim(TransInfo *t, TransData *td);
void constraintTransLim(const TransInfo *t, TransData *td);
void constraintSizeLim(const TransInfo *t, TransData *td);
void headerRotation(TransInfo *t, char *str, int str_size, float final);
void ElementRotation_ex(TransInfo *t,
TransDataContainer *tc,
void ElementRotation_ex(const TransInfo *t,
const TransDataContainer *tc,
TransData *td,
const float mat[3][3],
const float *center);
void ElementRotation(
TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around);
void ElementRotation(const TransInfo *t,
const TransDataContainer *tc,
TransData *td,
const float mat[3][3],
const short around);
void headerResize(TransInfo *t, const float vec[3], char *str, int str_size);
void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3]);
void ElementResize(const TransInfo *t,
const TransDataContainer *tc,
TransData *td,
const float mat[3][3]);
short getAnimEdit_SnapMode(TransInfo *t);
void doAnimEdit_SnapFrame(
TransInfo *t, TransData *td, TransData2D *td2d, struct AnimData *adt, short autosnap);

View File

@ -23,8 +23,10 @@
#include <stdlib.h>
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_string.h"
#include "BKE_context.h"
#include "BKE_unit.h"
@ -37,6 +39,10 @@
#include "UI_interface.h"
#include "UI_view2d.h"
#include "SEQ_iterator.h"
#include "SEQ_sequencer.h"
#include "SEQ_time.h"
#include "BLT_translation.h"
#include "transform.h"
@ -102,13 +108,11 @@ static void applySeqSlideValue(TransInfo *t, const float val[2])
}
}
static void applySeqSlide(TransInfo *t, const int mval[2])
static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2]))
{
char str[UI_MAX_DRAW_STR];
float values_final[3] = {0.0f};
snapSequenceBounds(t, mval);
transform_convert_sequencer_channel_clamp(t);
if (applyNumInput(&t->num, values_final)) {
if (t->con.mode & CON_APPLY) {
if (t->con.mode & CON_AXIS0) {
@ -119,11 +123,14 @@ static void applySeqSlide(TransInfo *t, const int mval[2])
}
}
}
else if (t->con.mode & CON_APPLY) {
t->con.applyVec(t, NULL, NULL, t->values, values_final);
}
else {
copy_v2_v2(values_final, t->values);
applySnapping(t, values_final);
transform_convert_sequencer_channel_clamp(t, values_final);
if (t->con.mode & CON_APPLY) {
t->con.applyVec(t, NULL, NULL, t->values, values_final);
}
}
values_final[0] = floorf(values_final[0] + 0.5f);
@ -142,6 +149,7 @@ void initSeqSlide(TransInfo *t)
{
t->transform = applySeqSlide;
t->handleEvent = seq_slide_handleEvent;
t->tsnap.applySnap = transform_snap_sequencer_apply_translate;
initMouseInputMode(t, &t->mouse, INPUT_VECTOR);
@ -164,4 +172,5 @@ void initSeqSlide(TransInfo *t)
t->custom.mode.data = (void *)WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE);
}
}
/** \} */

View File

@ -222,6 +222,9 @@ static void ApplySnapTranslation(TransInfo *t, float vec[3])
vec[1] = point[1] - t->tsnap.snapTarget[1];
}
}
else if (t->spacetype == SPACE_SEQ) {
transform_snap_sequencer_apply_translate(t, vec);
}
else {
if (t->spacetype == SPACE_VIEW3D) {
if (t->options & CTX_PAINT_CURVE) {
@ -238,13 +241,13 @@ static void ApplySnapTranslation(TransInfo *t, float vec[3])
static void applyTranslationValue(TransInfo *t, const float vec[3])
{
const bool apply_snap_align_rotation = usingSnappingNormal(
t); // && (t->tsnap.status & POINT_INIT);
const bool apply_snap_align_rotation = usingSnappingNormal(t);
float tvec[3];
/* The ideal would be "apply_snap_align_rotation" only when a snap point is found
* so, maybe inside this function is not the best place to apply this rotation.
* but you need "handle snapping rotation before doing the translation" (really?) */
/* Ideally "apply_snap_align_rotation" would only be used when a snap point is found:
* `t->tsnap.status & POINT_INIT` - perhaps this function isn't the best place to apply rotation.
* However snapping rotation needs to be handled before doing the translation
* (unless the pivot is also translated). */
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
float pivot[3];
@ -265,14 +268,14 @@ static void applyTranslationValue(TransInfo *t, const float vec[3])
float rotate_offset[3] = {0};
bool use_rotate_offset = false;
/* handle snapping rotation before doing the translation */
/* Handle snapping rotation before doing the translation. */
if (apply_snap_align_rotation) {
float mat[3][3];
if (validSnappingNormal(t)) {
const float *original_normal;
/* In pose mode, we want to align normals with Y axis of bones... */
/* In pose mode, we want to align normals with Y axis of bones. */
if (t->options & CTX_POSE_BONE) {
original_normal = td->axismtx[1];
}
@ -308,7 +311,7 @@ static void applyTranslationValue(TransInfo *t, const float vec[3])
}
if (t->options & CTX_GPENCIL_STROKES) {
/* grease pencil multiframe falloff */
/* Grease pencil multi-frame falloff. */
bGPDstroke *gps = (bGPDstroke *)td->extra;
if (gps != NULL) {
mul_v3_fl(tvec, td->factor * gps->runtime.multi_frame_falloff);
@ -318,7 +321,7 @@ static void applyTranslationValue(TransInfo *t, const float vec[3])
}
}
else {
/* proportional editing falloff */
/* Proportional editing falloff. */
mul_v3_fl(tvec, td->factor);
}

View File

@ -41,9 +41,6 @@
#include "RNA_access.h"
#include "SEQ_sequencer.h"
#include "SEQ_time.h"
#include "WM_types.h"
#include "ED_gizmo_library.h"
@ -55,6 +52,10 @@
#include "UI_resources.h"
#include "UI_view2d.h"
#include "SEQ_iterator.h"
#include "SEQ_sequencer.h"
#include "SEQ_time.h"
#include "MEM_guardedalloc.h"
#include "transform.h"
@ -75,7 +76,10 @@ static bool doForceIncrementSnap(const TransInfo *t);
static void setSnappingCallback(TransInfo *t);
/* static void CalcSnapGrid(TransInfo *t, float *vec); */
static void CalcSnapGeometry(TransInfo *t, float *vec);
static void snap_calc_view3d_fn(TransInfo *t, float *vec);
static void snap_calc_uv_fn(TransInfo *t, float *vec);
static void snap_calc_node_fn(TransInfo *t, float *vec);
static void snap_calc_sequencer_fn(TransInfo *t, float *vec);
static void TargetSnapMedian(TransInfo *t);
static void TargetSnapCenter(TransInfo *t);
@ -164,10 +168,7 @@ bool transformModeUseSnap(const TransInfo *t)
if (t->mode == TFM_RESIZE) {
return (ts->snap_transform_mode_flag & SCE_SNAP_TRANSFORM_MODE_SCALE) != 0;
}
if (t->mode == TFM_VERT_SLIDE) {
return true;
}
if (t->mode == TFM_EDGE_SLIDE) {
if (ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE, TFM_SEQ_SLIDE)) {
return true;
}
@ -295,6 +296,21 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
GPU_blend(GPU_BLEND_NONE);
}
}
else if (t->spacetype == SPACE_SEQ) {
if (validSnap(t)) {
const ARegion *region = CTX_wm_region(C);
GPU_blend(GPU_BLEND_ALPHA);
uint pos = GPU_vertformat_attr_add(
immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, t->tsnap.snapPoint[0], region->v2d.cur.ymin);
immVertex2f(pos, t->tsnap.snapPoint[0], region->v2d.cur.ymax);
immEnd();
immUnbindProgram();
GPU_blend(GPU_BLEND_NONE);
}
}
}
eRedrawFlag handleSnapping(TransInfo *t, const wmEvent *event)
@ -476,10 +492,13 @@ void applySnapping(TransInfo *t, float *vec)
/* TODO: add exception for object mode, no need to slow it down then. */
if (current - t->tsnap.last >= 0.01) {
t->tsnap.calcSnap(t, vec);
t->tsnap.targetSnap(t);
t->tsnap.last = current;
if (t->tsnap.targetSnap) {
t->tsnap.targetSnap(t);
}
}
t->tsnap.last = current;
if (validSnap(t)) {
t->tsnap.applySnap(t, vec);
}
@ -567,6 +586,9 @@ static void initSnappingMode(TransInfo *t)
t->tsnap.mode = ts->snap_uv_mode;
}
else if (t->spacetype == SPACE_SEQ) {
t->tsnap.mode = SEQ_tool_settings_snap_mode_get(t->scene);
}
else {
/* force project off when not supported */
if ((ts->snap_mode & SCE_SNAP_MODE_FACE) == 0) {
@ -626,16 +648,12 @@ static void initSnappingMode(TransInfo *t)
t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
}
}
else if (t->spacetype == SPACE_NODE) {
else if (ELEM(t->spacetype, SPACE_NODE, SPACE_SEQ)) {
setSnappingCallback(t);
t->tsnap.modeSelect = SNAP_NOT_SELECTED;
}
else if (t->spacetype == SPACE_SEQ) {
/* We do our own snapping currently, so nothing here */
t->tsnap.mode = SCE_SNAP_MODE_GRID; /* Dummy, should we rather add a NOP mode? */
}
else {
/* Always increment outside of 3D view */
/* Fallback. */
t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
}
@ -656,6 +674,11 @@ static void initSnappingMode(TransInfo *t)
}
}
}
else if (t->spacetype == SPACE_SEQ) {
if (t->tsnap.seq_context == NULL) {
t->tsnap.seq_context = transform_snap_sequencer_data_alloc(t);
}
}
}
void initSnapping(TransInfo *t, wmOperator *op)
@ -708,6 +731,9 @@ void initSnapping(TransInfo *t, wmOperator *op)
t->tsnap.snap_self = !((t->settings->snap_flag & SCE_SNAP_NO_SELF) != 0);
t->tsnap.peel = ((t->settings->snap_flag & SCE_SNAP_PROJECT) != 0);
}
else if ((t->spacetype == SPACE_SEQ) && (ts->snap_flag & SCE_SNAP_SEQ)) {
t->modifiers |= MOD_SNAP;
}
}
t->tsnap.target = snap_target;
@ -717,7 +743,11 @@ void initSnapping(TransInfo *t, wmOperator *op)
void freeSnapping(TransInfo *t)
{
if (t->tsnap.object_context) {
if ((t->spacetype == SPACE_SEQ) && t->tsnap.seq_context) {
transform_snap_sequencer_data_free(t->tsnap.seq_context);
t->tsnap.seq_context = NULL;
}
else if (t->tsnap.object_context) {
ED_transform_snap_object_context_destroy(t->tsnap.object_context);
t->tsnap.object_context = NULL;
}
@ -725,7 +755,20 @@ void freeSnapping(TransInfo *t)
static void setSnappingCallback(TransInfo *t)
{
t->tsnap.calcSnap = CalcSnapGeometry;
if (t->spacetype == SPACE_VIEW3D) {
t->tsnap.calcSnap = snap_calc_view3d_fn;
}
else if (t->spacetype == SPACE_IMAGE && t->obedit_type == OB_MESH) {
t->tsnap.calcSnap = snap_calc_uv_fn;
}
else if (t->spacetype == SPACE_NODE) {
t->tsnap.calcSnap = snap_calc_node_fn;
}
else if (t->spacetype == SPACE_SEQ) {
t->tsnap.calcSnap = snap_calc_sequencer_fn;
/* The target is calculated along with the snap point. */
return;
}
switch (t->tsnap.target) {
case SCE_SNAP_TARGET_CLOSEST:
@ -846,89 +889,105 @@ void getSnapPoint(const TransInfo *t, float vec[3])
/** \} */
/* -------------------------------------------------------------------- */
/** \name Calc Snap (Generic)
/** \name Calc Snap
* \{ */
static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
static void snap_calc_view3d_fn(TransInfo *t, float *UNUSED(vec))
{
if (t->spacetype == SPACE_VIEW3D) {
float loc[3];
float no[3];
float mval[2];
bool found = false;
short snap_elem = 0;
float dist_px = SNAP_MIN_DISTANCE; /* Use a user defined value here. */
BLI_assert(t->spacetype == SPACE_VIEW3D);
float loc[3];
float no[3];
float mval[2];
bool found = false;
short snap_elem = 0;
float dist_px = SNAP_MIN_DISTANCE; /* Use a user defined value here. */
mval[0] = t->mval[0];
mval[1] = t->mval[1];
mval[0] = t->mval[0];
mval[1] = t->mval[1];
if (t->tsnap.mode & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) {
zero_v3(no); /* objects won't set this */
snap_elem = snapObjectsTransform(t, mval, &dist_px, loc, no);
found = snap_elem != 0;
if (t->tsnap.mode & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) {
zero_v3(no); /* objects won't set this */
snap_elem = snapObjectsTransform(t, mval, &dist_px, loc, no);
found = snap_elem != 0;
}
if ((found == false) && (t->tsnap.mode & SCE_SNAP_MODE_VOLUME)) {
found = peelObjectsTransform(
t, mval, (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0, loc, no, NULL);
if (found) {
snap_elem = SCE_SNAP_MODE_VOLUME;
}
if ((found == false) && (t->tsnap.mode & SCE_SNAP_MODE_VOLUME)) {
found = peelObjectsTransform(
t, mval, (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0, loc, no, NULL);
}
if (found) {
snap_elem = SCE_SNAP_MODE_VOLUME;
}
}
if (found == true) {
copy_v3_v3(t->tsnap.snapPoint, loc);
copy_v3_v3(t->tsnap.snapNormal, no);
if (found == true) {
copy_v3_v3(t->tsnap.snapPoint, loc);
copy_v3_v3(t->tsnap.snapNormal, no);
t->tsnap.status |= POINT_INIT;
}
else {
t->tsnap.status &= ~POINT_INIT;
}
t->tsnap.snapElem = (char)snap_elem;
}
static void snap_calc_uv_fn(TransInfo *t, float *UNUSED(vec))
{
BLI_assert(t->spacetype == SPACE_IMAGE && t->obedit_type == OB_MESH);
if (t->tsnap.mode & SCE_SNAP_MODE_VERTEX) {
float co[2];
UI_view2d_region_to_view(&t->region->v2d, t->mval[0], t->mval[1], &co[0], &co[1]);
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
t->view_layer, NULL, &objects_len);
float dist_sq = FLT_MAX;
if (ED_uvedit_nearest_uv_multi(
t->scene, objects, objects_len, co, &dist_sq, t->tsnap.snapPoint)) {
t->tsnap.snapPoint[0] *= t->aspect[0];
t->tsnap.snapPoint[1] *= t->aspect[1];
t->tsnap.status |= POINT_INIT;
}
else {
t->tsnap.status &= ~POINT_INIT;
}
t->tsnap.snapElem = (char)snap_elem;
MEM_freeN(objects);
}
else if (t->spacetype == SPACE_IMAGE && t->obedit_type == OB_MESH) {
if (t->tsnap.mode & SCE_SNAP_MODE_VERTEX) {
float co[2];
}
UI_view2d_region_to_view(&t->region->v2d, t->mval[0], t->mval[1], &co[0], &co[1]);
static void snap_calc_node_fn(TransInfo *t, float *UNUSED(vec))
{
BLI_assert(t->spacetype == SPACE_NODE);
if (t->tsnap.mode & (SCE_SNAP_MODE_NODE_X | SCE_SNAP_MODE_NODE_Y)) {
float loc[2];
float dist_px = SNAP_MIN_DISTANCE; /* Use a user defined value here. */
char node_border;
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
t->view_layer, NULL, &objects_len);
if (snapNodesTransform(t, t->mval, loc, &dist_px, &node_border)) {
copy_v2_v2(t->tsnap.snapPoint, loc);
t->tsnap.snapNodeBorder = node_border;
float dist_sq = FLT_MAX;
if (ED_uvedit_nearest_uv_multi(
t->scene, objects, objects_len, co, &dist_sq, t->tsnap.snapPoint)) {
t->tsnap.snapPoint[0] *= t->aspect[0];
t->tsnap.snapPoint[1] *= t->aspect[1];
t->tsnap.status |= POINT_INIT;
}
else {
t->tsnap.status &= ~POINT_INIT;
}
MEM_freeN(objects);
t->tsnap.status |= POINT_INIT;
}
else {
t->tsnap.status &= ~POINT_INIT;
}
}
else if (t->spacetype == SPACE_NODE) {
if (t->tsnap.mode & (SCE_SNAP_MODE_NODE_X | SCE_SNAP_MODE_NODE_Y)) {
float loc[2];
float dist_px = SNAP_MIN_DISTANCE; /* Use a user defined value here. */
char node_border;
}
if (snapNodesTransform(t, t->mval, loc, &dist_px, &node_border)) {
copy_v2_v2(t->tsnap.snapPoint, loc);
t->tsnap.snapNodeBorder = node_border;
t->tsnap.status |= POINT_INIT;
}
else {
t->tsnap.status &= ~POINT_INIT;
}
}
static void snap_calc_sequencer_fn(TransInfo *t, float *UNUSED(vec))
{
BLI_assert(t->spacetype == SPACE_SEQ);
if (transform_snap_sequencer_calc(t)) {
t->tsnap.status |= (POINT_INIT | TARGET_INIT);
}
else {
t->tsnap.status &= ~(POINT_INIT | TARGET_INIT);
}
}
@ -1441,28 +1500,6 @@ void snapFrameTransform(TransInfo *t,
*r_val = (float)val;
}
/*================================================================*/
void snapSequenceBounds(TransInfo *t, const int mval[2])
{
/* Reuse increment, strictly speaking could be another snap mode, but leave as is. */
if (!(t->modifiers & MOD_SNAP_INVERT)) {
return;
}
/* Convert to frame range. */
float xmouse, ymouse;
UI_view2d_region_to_view(&t->region->v2d, mval[0], mval[1], &xmouse, &ymouse);
const int frame_curr = round_fl_to_int(xmouse);
/* Now find the closest sequence. */
const int frame_near = SEQ_time_find_next_prev_edit(
t->scene, frame_curr, SEQ_SIDE_BOTH, true, false, true);
const int frame_snap = transform_convert_sequencer_get_snap_bound(t);
t->values[0] = frame_near - frame_snap;
}
static void snap_grid_apply(
TransInfo *t, const int max_index, const float grid_dist, const float loc[3], float r_out[3])
{
@ -1517,7 +1554,7 @@ bool transform_snap_grid(TransInfo *t, float *val)
return true;
}
static void snap_increment_apply_ex(TransInfo *UNUSED(t),
static void snap_increment_apply_ex(const TransInfo *UNUSED(t),
const int max_index,
const float increment_val,
const float aspect[3],
@ -1531,8 +1568,8 @@ static void snap_increment_apply_ex(TransInfo *UNUSED(t),
}
}
static void snap_increment_apply(TransInfo *t,
int max_index,
static void snap_increment_apply(const TransInfo *t,
const int max_index,
const float increment_dist,
float *r_val)
{
@ -1564,7 +1601,7 @@ static void snap_increment_apply(TransInfo *t,
snap_increment_apply_ex(t, max_index, increment_dist, asp, r_val, r_val);
}
bool transform_snap_increment_ex(TransInfo *t, bool use_local_space, float *r_val)
bool transform_snap_increment_ex(const TransInfo *t, bool use_local_space, float *r_val)
{
if (!activeSnap(t)) {
return false;
@ -1595,7 +1632,7 @@ bool transform_snap_increment_ex(TransInfo *t, bool use_local_space, float *r_va
return true;
}
bool transform_snap_increment(TransInfo *t, float *r_val)
bool transform_snap_increment(const TransInfo *t, float *r_val)
{
return transform_snap_increment_ex(t, false, r_val);
}

View File

@ -54,12 +54,10 @@ void snapFrameTransform(struct TransInfo *t,
bool transformModeUseSnap(const TransInfo *t);
bool transform_snap_increment_ex(TransInfo *t, bool use_local_space, float *r_val);
bool transform_snap_increment(TransInfo *t, float *val);
bool transform_snap_increment_ex(const TransInfo *t, bool use_local_space, float *r_val);
bool transform_snap_increment(const TransInfo *t, float *val);
bool transform_snap_grid(TransInfo *t, float *val);
void snapSequenceBounds(TransInfo *t, const int mval[2]);
bool activeSnap(const TransInfo *t);
bool activeSnap_with_project(const TransInfo *t);
@ -82,3 +80,9 @@ eRedrawFlag updateSelectedSnapPoint(TransInfo *t);
void removeSnapPoint(TransInfo *t);
float transform_snap_distance_len_squared_fn(TransInfo *t, const float p1[3], const float p2[3]);
/* transform_snap_sequencer.c */
struct TransSeqSnapData *transform_snap_sequencer_data_alloc(const TransInfo *t);
void transform_snap_sequencer_data_free(struct TransSeqSnapData *data);
bool transform_snap_sequencer_calc(struct TransInfo *t);
void transform_snap_sequencer_apply_translate(TransInfo *t, float *vec);

View File

@ -0,0 +1,270 @@
/*
* 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) 2001-2002 by NaN Holding BV.
* All rights reserved.
*/
/** \file
* \ingroup edtransform
*/
#include <stdlib.h>
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BKE_context.h"
#include "ED_screen.h"
#include "UI_view2d.h"
#include "SEQ_iterator.h"
#include "SEQ_sequencer.h"
#include "transform.h"
#include "transform_snap.h"
typedef struct TransSeqSnapData {
int *source_snap_points;
int *target_snap_points;
int source_snap_point_count;
int target_snap_point_count;
int final_snap_frame;
} TransSeqSnapData;
/* -------------------------------------------------------------------- */
/** \name Snap sources
* \{ */
static int seq_get_snap_source_points_count(SeqCollection *snap_sources)
{
return SEQ_collection_count(snap_sources) * 2;
}
static void seq_snap_source_points_alloc(TransSeqSnapData *snap_data, SeqCollection *snap_sources)
{
const size_t point_count = seq_get_snap_source_points_count(snap_sources);
snap_data->source_snap_points = MEM_callocN(sizeof(int) * point_count, __func__);
memset(snap_data->source_snap_points, 0, sizeof(int));
snap_data->source_snap_point_count = point_count;
}
static int cmp_fn(const void *a, const void *b)
{
return (*(int *)a - *(int *)b);
}
static void seq_snap_source_points_build(const TransInfo *t,
TransSeqSnapData *snap_data,
SeqCollection *snap_sources)
{
int i = 0;
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, snap_sources) {
int left = 0, right = 0;
if (seq->flag & SEQ_LEFTSEL) {
left = right = seq->startdisp;
}
else if (seq->flag & SEQ_RIGHTSEL) {
left = right = seq->enddisp;
}
else {
left = seq->startdisp;
right = seq->enddisp;
}
snap_data->source_snap_points[i] = left;
snap_data->source_snap_points[i + 1] = right;
i += 2;
BLI_assert(i <= snap_data->source_snap_point_count);
}
qsort(snap_data->source_snap_points, snap_data->source_snap_point_count, sizeof(int), cmp_fn);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Snap targets
* \{ */
static SeqCollection *query_snap_targets(const TransInfo *t)
{
const ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(t->scene, false));
const short snap_flag = SEQ_tool_settings_snap_flag_get(t->scene);
SeqCollection *collection = SEQ_collection_create();
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
if ((seq->flag & SELECT)) {
continue; /* Selected are being transformed. */
}
if ((seq->flag & SEQ_MUTE) && (snap_flag & SEQ_SNAP_IGNORE_MUTED)) {
continue;
}
if (seq->type == SEQ_TYPE_SOUND_RAM && (snap_flag & SEQ_SNAP_IGNORE_SOUND)) {
continue;
}
SEQ_collection_append_strip(seq, collection);
}
return collection;
}
static int seq_get_snap_target_points_count(const TransInfo *t,
TransSeqSnapData *snap_data,
SeqCollection *snap_targets)
{
const short snap_mode = t->tsnap.mode;
int count = 2; /* Strip start and end are always used. */
if (snap_mode & SEQ_SNAP_TO_STRIP_HOLD) {
count += 2;
}
count *= SEQ_collection_count(snap_targets);
if (snap_mode & SEQ_SNAP_TO_PLAYHEAD) {
count++;
}
return count;
}
static void seq_snap_target_points_alloc(const TransInfo *t,
TransSeqSnapData *snap_data,
SeqCollection *snap_targets)
{
const size_t point_count = seq_get_snap_target_points_count(t, snap_data, snap_targets);
snap_data->target_snap_points = MEM_callocN(sizeof(int) * point_count, __func__);
memset(snap_data->target_snap_points, 0, sizeof(int));
snap_data->target_snap_point_count = point_count;
}
static void seq_snap_target_points_build(const TransInfo *t,
TransSeqSnapData *snap_data,
SeqCollection *snap_targets)
{
const Scene *scene = t->scene;
const short snap_mode = t->tsnap.mode;
int i = 0;
if (snap_mode & SEQ_SNAP_TO_PLAYHEAD) {
snap_data->target_snap_points[i] = CFRA;
i++;
}
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, snap_targets) {
snap_data->target_snap_points[i] = seq->startdisp;
snap_data->target_snap_points[i + 1] = seq->enddisp;
i += 2;
if (snap_mode & SEQ_SNAP_TO_STRIP_HOLD) {
int content_start = min_ii(seq->enddisp, seq->start);
int content_end = max_ii(seq->startdisp, seq->start + seq->len);
if (seq->anim_startofs == 0) {
content_start = seq->startdisp;
}
if (seq->anim_endofs == 0) {
content_end = seq->enddisp;
}
snap_data->target_snap_points[i] = content_start;
snap_data->target_snap_points[i + 1] = content_end;
i += 2;
}
}
BLI_assert(i <= snap_data->target_snap_point_count);
qsort(snap_data->target_snap_points, snap_data->target_snap_point_count, sizeof(int), cmp_fn);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Snap utilities
* \{ */
static int seq_snap_threshold_get_frame_distance(const TransInfo *t)
{
const int snap_distance = SEQ_tool_settings_snap_distance_get(t->scene);
const struct View2D *v2d = &t->region->v2d;
return round_fl_to_int(UI_view2d_region_to_view_x(v2d, snap_distance) -
UI_view2d_region_to_view_x(v2d, 0));
}
/** \} */
TransSeqSnapData *transform_snap_sequencer_data_alloc(const TransInfo *t)
{
TransSeqSnapData *snap_data = MEM_callocN(sizeof(TransSeqSnapData), __func__);
ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(t->scene, false));
/* Build arrays of snap points. */
SeqCollection *snap_sources = SEQ_query_selected_strips(seqbase);
seq_snap_source_points_alloc(snap_data, snap_sources);
seq_snap_source_points_build(t, snap_data, snap_sources);
SEQ_collection_free(snap_sources);
SeqCollection *snap_targets = query_snap_targets(t);
seq_snap_target_points_alloc(t, snap_data, snap_targets);
seq_snap_target_points_build(t, snap_data, snap_targets);
SEQ_collection_free(snap_targets);
return snap_data;
}
void transform_snap_sequencer_data_free(TransSeqSnapData *data)
{
MEM_freeN(data->source_snap_points);
MEM_freeN(data->target_snap_points);
MEM_freeN(data);
}
bool transform_snap_sequencer_calc(TransInfo *t)
{
const TransSeqSnapData *snap_data = t->tsnap.seq_context;
int best_dist = MAXFRAME, best_target_frame = 0, best_source_frame = 0;
for (int i = 0; i < snap_data->source_snap_point_count; i++) {
int snap_source_frame = snap_data->source_snap_points[i] + round_fl_to_int(t->values[0]);
for (int j = 0; j < snap_data->target_snap_point_count; j++) {
int snap_target_frame = snap_data->target_snap_points[j];
int dist = abs(snap_target_frame - snap_source_frame);
if (dist > best_dist) {
continue;
}
best_dist = dist;
best_target_frame = snap_target_frame;
best_source_frame = snap_source_frame;
}
}
if (best_dist > seq_snap_threshold_get_frame_distance(t)) {
return false;
}
t->tsnap.snapPoint[0] = best_target_frame;
t->tsnap.snapTarget[0] = best_source_frame;
return true;
}
void transform_snap_sequencer_apply_translate(TransInfo *t, float *vec)
{
*vec += t->tsnap.snapPoint[0] - t->tsnap.snapTarget[0];
}

View File

@ -101,8 +101,9 @@ static void generate_strokes_actual(
lmd->use_multiple_levels ? lmd->level_end : lmd->level_start,
lmd->target_material ? BKE_gpencil_object_material_index_get(ob, lmd->target_material) : 0,
lmd->edge_types,
lmd->material_mask_flags,
lmd->mask_switches,
lmd->material_mask_bits,
lmd->intersection_mask,
lmd->thickness,
lmd->opacity,
lmd->source_vertex_group,
@ -280,8 +281,6 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
const int source_type = RNA_enum_get(ptr, "source_type");
const bool is_baked = RNA_boolean_get(ptr, "is_baked");
const bool use_cache = RNA_boolean_get(ptr, "use_cache");
const bool is_first = BKE_gpencil_is_first_lineart_in_stack(ob_ptr.data, ptr->data);
uiLayoutSetPropSep(layout, true);
uiLayoutSetEnabled(layout, !is_baked);
@ -301,26 +300,6 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
else {
/* Source is Scene. */
}
uiLayout *col = uiLayoutColumnWithHeading(layout, true, IFACE_("Edge Types"));
uiItemR(col, ptr, "use_contour", 0, IFACE_("Contour"), ICON_NONE);
uiItemR(col, ptr, "use_floating", 0, IFACE_("Floating"), ICON_NONE);
uiItemR(col, ptr, "use_material", 0, IFACE_("Material Borders"), ICON_NONE);
uiItemR(col, ptr, "use_edge_mark", 0, IFACE_("Edge Marks"), ICON_NONE);
uiItemR(col, ptr, "use_intersection", 0, IFACE_("Intersections"), ICON_NONE);
uiLayout *sub = uiLayoutRowWithHeading(col, false, IFACE_("Crease"));
uiItemR(sub, ptr, "use_crease", 0, "", ICON_NONE);
uiLayout *entry = uiLayoutRow(sub, false);
uiLayoutSetEnabled(entry, RNA_boolean_get(ptr, "use_crease") || is_first);
if (use_cache && !is_first) {
uiItemL(entry, IFACE_("Angle Cached"), ICON_INFO);
}
else {
uiItemR(entry, ptr, "crease_threshold", UI_ITEM_R_SLIDER, " ", ICON_NONE);
}
uiItemPointerR(layout, ptr, "target_layer", &obj_data_ptr, "layers", NULL, ICON_GREASEPENCIL);
/* Material has to be used by grease pencil object already, it was possible to assign materials
@ -345,6 +324,42 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
gpencil_modifier_panel_end(layout, ptr);
}
static void edge_types_panel_draw(const bContext *UNUSED(C), Panel *panel)
{
uiLayout *layout = panel->layout;
PointerRNA ob_ptr;
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, &ob_ptr);
const bool is_baked = RNA_boolean_get(ptr, "is_baked");
const bool use_cache = RNA_boolean_get(ptr, "use_cached_result");
const bool is_first = BKE_gpencil_is_first_lineart_in_stack(ob_ptr.data, ptr->data);
uiLayoutSetEnabled(layout, !is_baked);
uiLayoutSetPropSep(layout, true);
uiLayout *col = uiLayoutColumn(layout, true);
uiItemR(col, ptr, "use_contour", 0, IFACE_("Contour"), ICON_NONE);
uiItemR(col, ptr, "use_loose", 0, IFACE_("Loose"), ICON_NONE);
uiItemR(col, ptr, "use_material", 0, IFACE_("Material Borders"), ICON_NONE);
uiItemR(col, ptr, "use_edge_mark", 0, IFACE_("Edge Marks"), ICON_NONE);
uiItemR(col, ptr, "use_intersection", 0, IFACE_("Intersections"), ICON_NONE);
uiLayout *sub = uiLayoutRowWithHeading(col, false, IFACE_("Crease"));
uiItemR(sub, ptr, "use_crease", 0, "", ICON_NONE);
uiLayout *entry = uiLayoutRow(sub, false);
uiLayoutSetEnabled(entry, RNA_boolean_get(ptr, "use_crease") || is_first);
if (use_cache && !is_first) {
uiItemL(entry, IFACE_("Angle Cached"), ICON_INFO);
}
else {
uiItemR(entry, ptr, "crease_threshold", UI_ITEM_R_SLIDER, " ", ICON_NONE);
}
uiItemR(layout, ptr, "use_overlap_edge_type_support", 0, IFACE_("Allow Overlap"), ICON_NONE);
}
static void options_panel_draw(const bContext *UNUSED(C), Panel *panel)
{
uiLayout *layout = panel->layout;
@ -369,7 +384,6 @@ static void options_panel_draw(const bContext *UNUSED(C), Panel *panel)
uiItemR(col, ptr, "use_edge_overlap", 0, IFACE_("Overlapping Edges As Contour"), ICON_NONE);
uiItemR(col, ptr, "use_object_instances", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "use_clip_plane_boundaries", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "allow_overlap_edge_types", 0, NULL, ICON_NONE);
}
static void style_panel_draw(const bContext *UNUSED(C), Panel *panel)
@ -449,6 +463,32 @@ static void material_mask_panel_draw(const bContext *UNUSED(C), Panel *panel)
uiItemR(col, ptr, "use_material_mask_match", 0, IFACE_("Match All Masks"), ICON_NONE);
}
static void intersection_panel_draw(const bContext *UNUSED(C), Panel *panel)
{
uiLayout *layout = panel->layout;
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
const bool is_baked = RNA_boolean_get(ptr, "is_baked");
uiLayoutSetEnabled(layout, !is_baked);
uiLayoutSetPropSep(layout, true);
uiLayoutSetActive(layout, RNA_boolean_get(ptr, "use_intersection"));
uiLayout *row = uiLayoutRow(layout, true);
uiLayoutSetPropDecorate(row, false);
uiLayout *sub = uiLayoutRowWithHeading(row, true, IFACE_("Masks"));
char text[2] = "0";
PropertyRNA *prop = RNA_struct_find_property(ptr, "use_intersection_mask");
for (int i = 0; i < 8; i++, text[0]++) {
uiItemFullR(sub, ptr, prop, i, 0, UI_ITEM_R_TOGGLE, text, ICON_NONE);
}
uiItemL(row, "", ICON_BLANK1); /* Space for decorator. */
uiLayout *col = uiLayoutColumn(layout, true);
uiItemR(col, ptr, "use_intersection_match", 0, IFACE_("Match All Masks"), ICON_NONE);
}
static void face_mark_panel_draw_header(const bContext *UNUSED(C), Panel *panel)
{
uiLayout *layout = panel->layout;
@ -504,7 +544,7 @@ static void chaining_panel_draw(const bContext *UNUSED(C), Panel *panel)
const bool is_baked = RNA_boolean_get(ptr, "is_baked");
const bool use_cache = RNA_boolean_get(ptr, "use_cache");
const bool is_first = BKE_gpencil_is_first_lineart_in_stack(ob_ptr.data, ptr->data);
const bool is_geom = RNA_boolean_get(ptr, "chain_geometry_space");
const bool is_geom = RNA_boolean_get(ptr, "use_geometry_space_chain");
uiLayoutSetPropSep(layout, true);
uiLayoutSetEnabled(layout, !is_baked);
@ -517,9 +557,9 @@ static void chaining_panel_draw(const bContext *UNUSED(C), Panel *panel)
uiLayout *col = uiLayoutColumnWithHeading(layout, true, IFACE_("Chain"));
uiItemR(col, ptr, "use_fuzzy_intersections", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "use_fuzzy_all", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "chain_floating_edges", 0, IFACE_("Floating Edges"), ICON_NONE);
uiItemR(col, ptr, "floating_as_contour", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "chain_geometry_space", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "use_loose_edge_chain", 0, IFACE_("Loose Edges"), ICON_NONE);
uiItemR(col, ptr, "use_loose_as_contour", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "use_geometry_space_chain", 0, NULL, ICON_NONE);
uiItemR(layout,
ptr,
@ -599,6 +639,8 @@ static void panelRegister(ARegionType *region_type)
PanelType *panel_type = gpencil_modifier_panel_register(
region_type, eGpencilModifierType_Lineart, panel_draw);
gpencil_modifier_subpanel_register(
region_type, "edge_types", "Edge Types", NULL, edge_types_panel_draw, panel_type);
gpencil_modifier_subpanel_register(
region_type, "geometry", "Geometry Processing", NULL, options_panel_draw, panel_type);
gpencil_modifier_subpanel_register(
@ -611,6 +653,8 @@ static void panelRegister(ARegionType *region_type)
material_mask_panel_draw_header,
material_mask_panel_draw,
occlusion_panel);
gpencil_modifier_subpanel_register(
region_type, "intersection", "Intersection", NULL, intersection_panel_draw, panel_type);
gpencil_modifier_subpanel_register(
region_type, "face_mark", "", face_mark_panel_draw_header, face_mark_panel_draw, panel_type);
gpencil_modifier_subpanel_register(

View File

@ -313,7 +313,7 @@ static void random_header_draw(const bContext *UNUSED(C), Panel *panel)
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
uiItemR(layout, ptr, "random", 0, IFACE_("Randomize"), ICON_NONE);
uiItemR(layout, ptr, "use_random", 0, IFACE_("Randomize"), ICON_NONE);
}
static void random_panel_draw(const bContext *UNUSED(C), Panel *panel)

View File

@ -52,8 +52,8 @@ typedef struct LineartTriangle {
/* first culled in line list to use adjacent triangle info, then go through triangle list. */
double gn[3];
/* Material flag is removed to save space. */
unsigned char material_mask_bits;
unsigned char intersection_mask;
unsigned char mat_occlusion;
unsigned char flags; /* #eLineartTriangleFlags */
@ -149,6 +149,7 @@ typedef struct LineartEdge {
/** Also for line type determination on chaining. */
unsigned char flags;
unsigned char intersection_mask;
/**
* Still need this entry because culled lines will not add to object
@ -174,6 +175,7 @@ typedef struct LineartEdgeChain {
/** Chain now only contains one type of segments */
int type;
unsigned char material_mask_bits;
unsigned char intersection_mask;
struct Object *object_ref;
} LineartEdgeChain;
@ -188,6 +190,7 @@ typedef struct LineartEdgeChainItem {
unsigned char line_type;
char occlusion;
unsigned char material_mask_bits;
unsigned char intersection_mask;
size_t index;
} LineartEdgeChainItem;
@ -284,16 +287,16 @@ typedef struct LineartRenderBuffer {
bool use_material;
bool use_edge_marks;
bool use_intersections;
bool use_floating;
bool use_loose;
bool fuzzy_intersections;
bool fuzzy_everything;
bool allow_boundaries;
bool allow_overlapping_edges;
bool allow_duplicated_types;
bool remove_doubles;
bool floating_as_contour;
bool chain_floating_edges;
bool chain_geometry_space;
bool use_loose_as_contour;
bool use_loose_edge_chain;
bool use_geometry_space_chain;
bool filter_face_mark;
bool filter_face_mark_invert;
@ -377,6 +380,7 @@ typedef struct LineartObjectInfo {
double normal[4][4];
LineartElementLinkNode *v_eln;
int usage;
uint8_t override_intersection_mask;
int global_i_offset;
bool free_use_mesh;
@ -612,8 +616,9 @@ void MOD_lineart_gpencil_generate(LineartCache *cache,
int level_end,
int mat_nr,
short edge_types,
unsigned char material_mask_flags,
unsigned char mask_switches,
unsigned char material_mask_bits,
unsigned char intersection_mask,
short thickness,
float opacity,
const char *source_vgname,

View File

@ -38,7 +38,8 @@
static LineartEdge *lineart_line_get_connected(LineartBoundingArea *ba,
LineartVert *vt,
LineartVert **new_vt,
int match_flag)
int match_flag,
unsigned char match_isec_mask)
{
for (int i = 0; i < ba->line_count; i++) {
LineartEdge *n_e = ba->linked_lines[i];
@ -51,6 +52,10 @@ static LineartEdge *lineart_line_get_connected(LineartBoundingArea *ba,
continue;
}
if (n_e->intersection_mask != match_isec_mask) {
continue;
}
*new_vt = LRT_OTHER_VERT(n_e, vt);
if (*new_vt) {
return n_e;
@ -112,11 +117,11 @@ static LineartEdgeChainItem *lineart_chain_append_point(LineartRenderBuffer *rb,
/* Because the new chain point is overlapping, just replace the type and occlusion level of the
* current point. This makes it so that the line to the point after this one has the correct
* type and level. */
LineartEdgeChainItem *old_rlci = ec->chain.last;
old_rlci->line_type = type;
old_rlci->occlusion = level;
old_rlci->material_mask_bits = material_mask_bits;
return old_rlci;
LineartEdgeChainItem *old_eci = ec->chain.last;
old_eci->line_type = type;
old_eci->occlusion = level;
old_eci->material_mask_bits = material_mask_bits;
return old_eci;
}
eci = lineart_mem_acquire(rb->chain_data_pool, sizeof(LineartEdgeChainItem));
@ -194,9 +199,10 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
ec = lineart_chain_create(rb);
/* One chain can only have one object_ref,
* so we assign it based on the first segment we found. */
/* One chain can only have one object_ref and intersection_mask,
* so we assign them based on the first segment we found. */
ec->object_ref = e->object_ref;
ec->intersection_mask = e->intersection_mask;
LineartEdge *new_e;
LineartVert *new_vt;
@ -230,7 +236,8 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
es->occlusion,
es->material_mask_bits,
e->v1_obindex);
while (ba && (new_e = lineart_line_get_connected(ba, new_vt, &new_vt, e->flags))) {
while (ba && (new_e = lineart_line_get_connected(
ba, new_vt, &new_vt, e->flags, e->intersection_mask))) {
new_e->flags |= LRT_EDGE_FLAG_CHAIN_PICKED;
if (new_e->t1 || new_e->t2) {
@ -360,7 +367,8 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
/* Step 3: grow right. */
ba = MOD_lineart_get_bounding_area(rb, e->v2->fbcoord[0], e->v2->fbcoord[1]);
new_vt = e->v2;
while (ba && (new_e = lineart_line_get_connected(ba, new_vt, &new_vt, e->flags))) {
while (ba && (new_e = lineart_line_get_connected(
ba, new_vt, &new_vt, e->flags, e->intersection_mask))) {
new_e->flags |= LRT_EDGE_FLAG_CHAIN_PICKED;
if (new_e->t1 || new_e->t2) {
@ -560,8 +568,8 @@ static void lineart_bounding_area_link_chain(LineartRenderBuffer *rb, LineartEdg
void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb)
{
LineartEdgeChain *ec, *new_rlc;
LineartEdgeChainItem *eci, *next_rlci;
LineartEdgeChain *ec, *new_ec;
LineartEdgeChainItem *eci, *next_eci;
ListBase swap = {0};
swap.first = rb->chains.first;
@ -572,16 +580,16 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb)
while ((ec = BLI_pophead(&swap)) != NULL) {
ec->next = ec->prev = NULL;
BLI_addtail(&rb->chains, ec);
LineartEdgeChainItem *first_rlci = (LineartEdgeChainItem *)ec->chain.first;
int fixed_occ = first_rlci->occlusion;
unsigned char fixed_mask = first_rlci->material_mask_bits;
LineartEdgeChainItem *first_eci = (LineartEdgeChainItem *)ec->chain.first;
int fixed_occ = first_eci->occlusion;
unsigned char fixed_mask = first_eci->material_mask_bits;
ec->level = fixed_occ;
ec->material_mask_bits = fixed_mask;
for (eci = first_rlci->next; eci; eci = next_rlci) {
next_rlci = eci->next;
for (eci = first_eci->next; eci; eci = next_eci) {
next_eci = eci->next;
if (eci->occlusion != fixed_occ || eci->material_mask_bits != fixed_mask) {
if (next_rlci) {
if (lineart_point_overlapping(next_rlci, eci->pos[0], eci->pos[1], 1e-5)) {
if (next_eci) {
if (lineart_point_overlapping(next_eci, eci->pos[0], eci->pos[1], 1e-5)) {
continue;
}
}
@ -593,9 +601,9 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb)
/* No need to split at the last point anyway. */
break;
}
new_rlc = lineart_chain_create(rb);
new_rlc->chain.first = eci;
new_rlc->chain.last = ec->chain.last;
new_ec = lineart_chain_create(rb);
new_ec->chain.first = eci;
new_ec->chain.last = ec->chain.last;
ec->chain.last = eci->prev;
((LineartEdgeChainItem *)ec->chain.last)->next = 0;
eci->prev = 0;
@ -610,9 +618,10 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb)
fixed_occ,
fixed_mask,
eci->index);
new_rlc->object_ref = ec->object_ref;
new_rlc->type = ec->type;
ec = new_rlc;
new_ec->object_ref = ec->object_ref;
new_ec->type = ec->type;
new_ec->intersection_mask = ec->intersection_mask;
ec = new_ec;
fixed_occ = eci->occlusion;
fixed_mask = eci->material_mask_bits;
ec->level = fixed_occ;
@ -684,6 +693,7 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartRenderBuf
LineartEdgeChainItem *eci,
int occlusion,
unsigned char material_mask_bits,
unsigned char isec_mask,
float dist,
float *result_new_len,
LineartBoundingArea *caller_ba)
@ -712,7 +722,8 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartRenderBuf
continue;
}
if (cre->ec == ec || (!cre->ec->chain.first) || (cre->ec->level != occlusion) ||
(cre->ec->material_mask_bits != material_mask_bits)) {
(cre->ec->material_mask_bits != material_mask_bits) ||
(cre->ec->intersection_mask != isec_mask)) {
continue;
}
if (!rb->fuzzy_everything) {
@ -729,8 +740,8 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartRenderBuf
}
}
float new_len = rb->chain_geometry_space ? len_v3v3(cre->eci->gpos, eci->gpos) :
len_v2v2(cre->eci->pos, eci->pos);
float new_len = rb->use_geometry_space_chain ? len_v3v3(cre->eci->gpos, eci->gpos) :
len_v2v2(cre->eci->pos, eci->pos);
if (new_len < dist) {
closest_cre = cre;
dist = new_len;
@ -748,8 +759,16 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartRenderBuf
if (dist_to < dist && dist_to > 0) { \
LISTBASE_FOREACH (LinkData *, ld, list) { \
LineartBoundingArea *sba = (LineartBoundingArea *)ld->data; \
adjacent_closest = lineart_chain_get_closest_cre( \
rb, sba, ec, eci, occlusion, material_mask_bits, dist, &adjacent_new_len, ba); \
adjacent_closest = lineart_chain_get_closest_cre(rb, \
sba, \
ec, \
eci, \
occlusion, \
material_mask_bits, \
isec_mask, \
dist, \
&adjacent_new_len, \
ba); \
if (adjacent_new_len < dist) { \
dist = adjacent_new_len; \
closest_cre = adjacent_closest; \
@ -776,13 +795,13 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartRenderBuf
void MOD_lineart_chain_connect(LineartRenderBuffer *rb)
{
LineartEdgeChain *ec;
LineartEdgeChainItem *rlci_l, *rlci_r;
LineartEdgeChainItem *eci_l, *eci_r;
LineartBoundingArea *ba_l, *ba_r;
LineartChainRegisterEntry *closest_cre_l, *closest_cre_r, *closest_cre;
float dist = rb->chaining_image_threshold;
float dist_l, dist_r;
int occlusion, reverse_main;
unsigned char material_mask_bits;
unsigned char material_mask_bits, isec_mask;
ListBase swap = {0};
if (rb->chaining_image_threshold < 0.0001) {
@ -801,21 +820,22 @@ void MOD_lineart_chain_connect(LineartRenderBuffer *rb)
}
BLI_addtail(&rb->chains, ec);
if (ec->type == LRT_EDGE_FLAG_FLOATING && (!rb->chain_floating_edges)) {
if (ec->type == LRT_EDGE_FLAG_LOOSE && (!rb->use_loose_edge_chain)) {
continue;
}
occlusion = ec->level;
material_mask_bits = ec->material_mask_bits;
isec_mask = ec->intersection_mask;
rlci_l = ec->chain.first;
rlci_r = ec->chain.last;
while ((ba_l = lineart_bounding_area_get_end_point(rb, rlci_l)) &&
(ba_r = lineart_bounding_area_get_end_point(rb, rlci_r))) {
eci_l = ec->chain.first;
eci_r = ec->chain.last;
while ((ba_l = lineart_bounding_area_get_end_point(rb, eci_l)) &&
(ba_r = lineart_bounding_area_get_end_point(rb, eci_r))) {
closest_cre_l = lineart_chain_get_closest_cre(
rb, ba_l, ec, rlci_l, occlusion, material_mask_bits, dist, &dist_l, NULL);
rb, ba_l, ec, eci_l, occlusion, material_mask_bits, isec_mask, dist, &dist_l, NULL);
closest_cre_r = lineart_chain_get_closest_cre(
rb, ba_r, ec, rlci_r, occlusion, material_mask_bits, dist, &dist_r, NULL);
rb, ba_r, ec, eci_r, occlusion, material_mask_bits, isec_mask, dist, &dist_r, NULL);
if (closest_cre_l && closest_cre_r) {
if (dist_l < dist_r) {
closest_cre = closest_cre_l;
@ -847,8 +867,8 @@ void MOD_lineart_chain_connect(LineartRenderBuffer *rb)
lineart_chain_connect(rb, ec, closest_cre->ec, reverse_main, 1);
}
BLI_remlink(&swap, closest_cre->ec);
rlci_l = ec->chain.first;
rlci_r = ec->chain.last;
eci_l = ec->chain.first;
eci_r = ec->chain.last;
}
ec->picked = 1;
}
@ -876,9 +896,9 @@ float MOD_lineart_chain_compute_length(LineartEdgeChain *ec)
void MOD_lineart_chain_discard_short(LineartRenderBuffer *rb, const float threshold)
{
LineartEdgeChain *ec, *next_rlc;
for (ec = rb->chains.first; ec; ec = next_rlc) {
next_rlc = ec->next;
LineartEdgeChain *ec, *next_ec;
for (ec = rb->chains.first; ec; ec = next_ec) {
next_ec = ec->next;
if (MOD_lineart_chain_compute_length(ec) < threshold) {
BLI_remlink(&rb->chains, ec);
}
@ -910,8 +930,8 @@ void MOD_lineart_chain_clear_picked_flag(LineartCache *lc)
*/
void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshold_rad)
{
LineartEdgeChain *ec, *new_rlc;
LineartEdgeChainItem *eci, *next_rlci, *prev_rlci;
LineartEdgeChain *ec, *new_ec;
LineartEdgeChainItem *eci, *next_eci, *prev_eci;
ListBase swap = {0};
swap.first = rb->chains.first;
@ -922,21 +942,21 @@ void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshol
while ((ec = BLI_pophead(&swap)) != NULL) {
ec->next = ec->prev = NULL;
BLI_addtail(&rb->chains, ec);
LineartEdgeChainItem *first_rlci = (LineartEdgeChainItem *)ec->chain.first;
for (eci = first_rlci->next; eci; eci = next_rlci) {
next_rlci = eci->next;
prev_rlci = eci->prev;
LineartEdgeChainItem *first_eci = (LineartEdgeChainItem *)ec->chain.first;
for (eci = first_eci->next; eci; eci = next_eci) {
next_eci = eci->next;
prev_eci = eci->prev;
float angle = M_PI;
if (next_rlci && prev_rlci) {
angle = angle_v2v2v2(prev_rlci->pos, eci->pos, next_rlci->pos);
if (next_eci && prev_eci) {
angle = angle_v2v2v2(prev_eci->pos, eci->pos, next_eci->pos);
}
else {
break; /* No need to split at the last point anyway. */
}
if (angle < angle_threshold_rad) {
new_rlc = lineart_chain_create(rb);
new_rlc->chain.first = eci;
new_rlc->chain.last = ec->chain.last;
new_ec = lineart_chain_create(rb);
new_ec->chain.first = eci;
new_ec->chain.last = ec->chain.last;
ec->chain.last = eci->prev;
((LineartEdgeChainItem *)ec->chain.last)->next = 0;
eci->prev = 0;
@ -951,11 +971,11 @@ void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshol
ec->level,
eci->material_mask_bits,
eci->index);
new_rlc->object_ref = ec->object_ref;
new_rlc->type = ec->type;
new_rlc->level = ec->level;
new_rlc->material_mask_bits = ec->material_mask_bits;
ec = new_rlc;
new_ec->object_ref = ec->object_ref;
new_ec->type = ec->type;
new_ec->level = ec->level;
new_ec->material_mask_bits = ec->material_mask_bits;
ec = new_ec;
}
}
}

View File

@ -875,7 +875,7 @@ static void lineart_triangle_cull_single(LineartRenderBuffer *rb,
* (!in0) means "when point 0 is visible".
* conditions for point 1, 2 are the same idea.
*
* \code{.txt}
* \code{.txt}identify
* 1-----|-------0
* | | ---
* | |---
@ -1463,6 +1463,10 @@ static uint16_t lineart_identify_feature_line(LineartRenderBuffer *rb,
lr = e->l->radial_next;
}
if (!ll && !lr) {
return LRT_EDGE_FLAG_LOOSE;
}
FreestyleEdge *fel, *fer;
bool face_mark_filtered = false;
uint16_t edge_flag_result = 0;
@ -1563,6 +1567,9 @@ static void lineart_add_edge_to_list(LineartRenderBuffer *rb, LineartEdge *e)
case LRT_EDGE_FLAG_INTERSECTION:
lineart_prepend_edge_direct(&rb->intersection.first, e);
break;
case LRT_EDGE_FLAG_LOOSE:
lineart_prepend_edge_direct(&rb->floating.first, e);
break;
}
}
@ -1590,7 +1597,7 @@ static void lineart_add_edge_to_list_thread(LineartObjectInfo *obi, LineartEdge
case LRT_EDGE_FLAG_INTERSECTION:
LRT_ASSIGN_EDGE(intersection);
break;
case LRT_EDGE_FLAG_FLOATING:
case LRT_EDGE_FLAG_LOOSE:
LRT_ASSIGN_EDGE(floating);
break;
}
@ -1632,7 +1639,7 @@ static int lineart_edge_type_duplication_count(char eflag)
{
int count = 0;
/* See eLineartEdgeFlag for details. */
for (int i = 0; i < LRT_EDGE_FLAG_FLOATING; i++) {
for (int i = 0; i < 6; i++) {
if (eflag & (1 << i)) {
count++;
}
@ -1800,6 +1807,8 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu
mat->lineart.mat_occlusion :
1);
tri->intersection_mask = obi->override_intersection_mask;
double gn[3];
copy_v3db_v3fl(gn, f->no);
mul_v3_mat3_m4v3_db(tri->gn, normal, gn);
@ -1868,7 +1877,7 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu
bool edge_added = false;
/* See eLineartEdgeFlag for details. */
for (int flag_bit = 0; flag_bit < LRT_EDGE_FLAG_FLOATING; flag_bit++) {
for (int flag_bit = 0; flag_bit < 6; flag_bit++) {
char use_type = 1 << flag_bit;
if (!(use_type & e->head.hflag)) {
continue;
@ -1923,28 +1932,30 @@ static void lineart_object_load_worker(TaskPool *__restrict UNUSED(pool),
}
}
static bool _lineart_object_not_in_source_collection(Collection *source, Object *ob)
static uchar lineart_intersection_mask_check(Collection *c, Object *ob)
{
CollectionChild *cc;
Collection *c = source->id.orig_id ? (Collection *)source->id.orig_id : source;
if (BKE_collection_has_object_recursive_instanced(c, (Object *)(ob->id.orig_id))) {
return false;
}
for (cc = source->children.first; cc; cc = cc->next) {
if (!_lineart_object_not_in_source_collection(cc->collection, ob)) {
return false;
LISTBASE_FOREACH (CollectionChild *, cc, &c->children) {
uchar result = lineart_intersection_mask_check(cc->collection, ob);
if (result) {
return result;
}
}
return true;
if (c->children.first == NULL) {
if (BKE_collection_has_object(c, (Object *)(ob->id.orig_id))) {
if (c->lineart_flags & COLLECTION_LRT_USE_INTERSECTION_MASK) {
return c->lineart_intersection_mask;
}
}
}
return 0;
}
/**
* See if this object in such collection is used for generating line art,
* Disabling a collection for line art will doable all objects inside.
* `_rb` is used to provide source selection info.
* See the definition of `rb->_source_type` for details.
*/
static int lineart_usage_check(Collection *c, Object *ob, LineartRenderBuffer *_rb)
static int lineart_usage_check(Collection *c, Object *ob)
{
if (!c) {
@ -1974,29 +1985,15 @@ static int lineart_usage_check(Collection *c, Object *ob, LineartRenderBuffer *_
}
return ob->lineart.usage;
}
return OBJECT_LRT_INHERIT;
}
LISTBASE_FOREACH (CollectionChild *, cc, &c->children) {
int result = lineart_usage_check(cc->collection, ob, _rb);
int result = lineart_usage_check(cc->collection, ob);
if (result > OBJECT_LRT_INHERIT) {
return result;
}
}
/* Temp solution to speed up calculation in the modifier without cache. See the definition of
* rb->_source_type for details. */
if (_rb->_source_type == LRT_SOURCE_OBJECT) {
if (ob != _rb->_source_object && ob->id.orig_id != (ID *)_rb->_source_object) {
return OBJECT_LRT_OCCLUSION_ONLY;
}
}
else if (_rb->_source_type == LRT_SOURCE_COLLECTION) {
if (_lineart_object_not_in_source_collection(_rb->_source_collection, ob)) {
return OBJECT_LRT_OCCLUSION_ONLY;
}
}
return OBJECT_LRT_INHERIT;
}
@ -2116,7 +2113,9 @@ static void lineart_main_load_geometries(
DEG_OBJECT_ITER_BEGIN (depsgraph, ob, flags) {
LineartObjectInfo *obi = lineart_mem_acquire(&rb->render_data_pool, sizeof(LineartObjectInfo));
obi->usage = lineart_usage_check(scene->master_collection, ob, rb);
obi->usage = lineart_usage_check(scene->master_collection, ob);
obi->override_intersection_mask = lineart_intersection_mask_check(scene->master_collection,
ob);
Mesh *use_mesh;
if (obi->usage == OBJECT_LRT_EXCLUDE) {
@ -2834,6 +2833,7 @@ static LineartEdge *lineart_triangle_intersect(LineartRenderBuffer *rb,
BLI_addtail(&result->segments, es);
/* Don't need to OR flags right now, just a type mark. */
result->flags = LRT_EDGE_FLAG_INTERSECTION;
result->intersection_mask = (tri->intersection_mask | testing->intersection_mask);
lineart_prepend_edge_direct(&rb->intersection.first, result);
int r1, r2, c1, c2, row, col;
@ -3033,9 +3033,9 @@ static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene,
rb->fuzzy_everything = (lmd->calculation_flags & LRT_EVERYTHING_AS_CONTOUR) != 0;
rb->allow_boundaries = (lmd->calculation_flags & LRT_ALLOW_CLIPPING_BOUNDARIES) != 0;
rb->remove_doubles = (lmd->calculation_flags & LRT_REMOVE_DOUBLES) != 0;
rb->floating_as_contour = (lmd->calculation_flags & LRT_FLOATING_AS_CONTOUR) != 0;
rb->chain_floating_edges = (lmd->calculation_flags & LRT_CHAIN_FLOATING_EDGES) != 0;
rb->chain_geometry_space = (lmd->calculation_flags & LRT_CHAIN_GEOMETRY_SPACE) != 0;
rb->use_loose_as_contour = (lmd->calculation_flags & LRT_LOOSE_AS_CONTOUR) != 0;
rb->use_loose_edge_chain = (lmd->calculation_flags & LRT_CHAIN_LOOSE_EDGES) != 0;
rb->use_geometry_space_chain = (lmd->calculation_flags & LRT_CHAIN_GEOMETRY_SPACE) != 0;
/* See lineart_edge_from_triangle() for how this option may impact performance. */
rb->allow_overlapping_edges = (lmd->calculation_flags & LRT_ALLOW_OVERLAPPING_EDGES) != 0;
@ -3049,7 +3049,7 @@ static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene,
rb->use_material = (edge_types & LRT_EDGE_FLAG_MATERIAL) != 0;
rb->use_edge_marks = (edge_types & LRT_EDGE_FLAG_EDGE_MARK) != 0;
rb->use_intersections = (edge_types & LRT_EDGE_FLAG_INTERSECTION) != 0;
rb->use_floating = (edge_types & LRT_EDGE_FLAG_FLOATING) != 0;
rb->use_loose = (edge_types & LRT_EDGE_FLAG_LOOSE) != 0;
rb->filter_face_mark_invert = (lmd->calculation_flags & LRT_FILTER_FACE_MARK_INVERT) != 0;
rb->filter_face_mark = (lmd->calculation_flags & LRT_FILTER_FACE_MARK) != 0;
@ -4168,7 +4168,7 @@ static int UNUSED_FUNCTION(lineart_rb_edge_types)(LineartRenderBuffer *rb)
types |= rb->use_material ? LRT_EDGE_FLAG_MATERIAL : 0;
types |= rb->use_edge_marks ? LRT_EDGE_FLAG_EDGE_MARK : 0;
types |= rb->use_intersections ? LRT_EDGE_FLAG_INTERSECTION : 0;
types |= rb->use_floating ? LRT_EDGE_FLAG_FLOATING : 0;
types |= rb->use_loose ? LRT_EDGE_FLAG_LOOSE : 0;
return types;
}
@ -4184,8 +4184,9 @@ static void lineart_gpencil_generate(LineartCache *cache,
Object *source_object,
Collection *source_collection,
int types,
uchar material_mask_flags,
uchar mask_switches,
uchar material_mask_bits,
uchar intersection_mask,
short thickness,
float opacity,
const char *source_vgname,
@ -4241,8 +4242,8 @@ static void lineart_gpencil_generate(LineartCache *cache,
continue;
}
}
if (material_mask_flags & LRT_GPENCIL_MATERIAL_MASK_ENABLE) {
if (material_mask_flags & LRT_GPENCIL_MATERIAL_MASK_MATCH) {
if (mask_switches & LRT_GPENCIL_MATERIAL_MASK_ENABLE) {
if (mask_switches & LRT_GPENCIL_MATERIAL_MASK_MATCH) {
if (ec->material_mask_bits != material_mask_bits) {
continue;
}
@ -4253,6 +4254,18 @@ static void lineart_gpencil_generate(LineartCache *cache,
}
}
}
if (types & LRT_EDGE_FLAG_INTERSECTION) {
if (mask_switches & LRT_GPENCIL_INTERSECTION_MATCH) {
if (ec->intersection_mask != intersection_mask) {
continue;
}
}
else {
if ((intersection_mask) && !(ec->intersection_mask & intersection_mask)) {
continue;
}
}
}
/* Preserved: If we ever do asynchronous generation, this picked flag should be set here. */
// ec->picked = 1;
@ -4347,8 +4360,9 @@ void MOD_lineart_gpencil_generate(LineartCache *cache,
int level_end,
int mat_nr,
short edge_types,
uchar material_mask_flags,
uchar mask_switches,
uchar material_mask_bits,
uchar intersection_mask,
short thickness,
float opacity,
const char *source_vgname,
@ -4396,8 +4410,9 @@ void MOD_lineart_gpencil_generate(LineartCache *cache,
source_object,
source_collection,
use_types,
material_mask_flags,
mask_switches,
material_mask_bits,
intersection_mask,
thickness,
opacity,
source_vgname,

View File

@ -143,8 +143,9 @@ static bool bake_strokes(Object *ob,
lmd->use_multiple_levels ? lmd->level_end : lmd->level_start,
lmd->target_material ? BKE_gpencil_object_material_index_get(ob, lmd->target_material) : 0,
lmd->edge_types,
lmd->material_mask_flags,
lmd->mask_switches,
lmd->material_mask_bits,
lmd->intersection_mask,
lmd->thickness,
lmd->opacity,
lmd->source_vertex_group,

View File

@ -35,7 +35,6 @@
extern "C" char datatoc_gpu_shader_colorspace_lib_glsl[];
using namespace blender;
using namespace blender::gpu;

View File

@ -177,14 +177,41 @@ char *GPULogParser::skip_severity(char *log_line,
return log_line;
}
char *GPULogParser::skip_separators(char *log_line, char sep1, char sep2, char sep3) const
char *GPULogParser::skip_separators(char *log_line, const StringRef separators) const
{
while (ELEM(log_line[0], sep1, sep2, sep3)) {
while (at_any(log_line, separators)) {
log_line++;
}
return log_line;
}
char *GPULogParser::skip_until(char *log_line, char stop_char) const
{
char *cursor = log_line;
while (!ELEM(cursor[0], '\n', '\0')) {
if (cursor[0] == stop_char) {
return cursor;
}
cursor++;
}
return log_line;
}
bool GPULogParser::at_number(const char *log_line) const
{
return log_line[0] >= '0' && log_line[0] <= '9';
}
bool GPULogParser::at_any(const char *log_line, const StringRef chars) const
{
return chars.find(log_line[0]) != StringRef::not_found;
}
int GPULogParser::parse_number(const char *log_line, char **r_new_position) const
{
return (int)strtol(log_line, r_new_position, 10);
}
/** \} */
} // namespace blender::gpu

View File

@ -21,6 +21,7 @@
#pragma once
#include "BLI_span.hh"
#include "BLI_string_ref.hh"
#include "GPU_shader.h"
#include "gpu_shader_interface.hh"
@ -123,7 +124,11 @@ class GPULogParser {
GPULogItem &log_item,
const char *error_msg,
const char *warning_msg) const;
char *skip_separators(char *log_line, char sep1, char sep2, char sep3) const;
char *skip_separators(char *log_line, const StringRef separators) const;
char *skip_until(char *log_line, char stop_char) const;
bool at_number(const char *log_line) const;
bool at_any(const char *log_line, const StringRef chars) const;
int parse_number(const char *log_line, char **r_new_position) const;
MEM_CXX_CLASS_ALLOC_FUNCS("GPULogParser");
};

View File

@ -38,6 +38,17 @@ namespace blender::gpu {
/** \name Platform
* \{ */
static bool match_renderer(StringRef renderer, const Vector<std::string> &items)
{
for (const std::string &item : items) {
const std::string wrapped = " " + item + " ";
if (renderer.endswith(item) || renderer.find(wrapped) != StringRef::not_found) {
return true;
}
}
return false;
}
void GLBackend::platform_init()
{
BLI_assert(!GPG.initialized);
@ -288,14 +299,25 @@ static void detect_workarounds()
* The work around uses `GPU_RGBA16I`.
*/
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_OFFICIAL)) {
if (strstr(renderer, " RX 460 ") || strstr(renderer, " RX 470 ") ||
strstr(renderer, " RX 480 ") || strstr(renderer, " RX 490 ") ||
strstr(renderer, " RX 560 ") || strstr(renderer, " RX 560X ") ||
strstr(renderer, " RX 570 ") || strstr(renderer, " RX 580 ") ||
strstr(renderer, " RX 580X ") || strstr(renderer, " RX 590 ") ||
strstr(renderer, " RX550/550 ") || strstr(renderer, "(TM) 520 ") ||
strstr(renderer, "(TM) 530 ") || strstr(renderer, "(TM) 535 ") ||
strstr(renderer, " R5 ") || strstr(renderer, " R7 ") || strstr(renderer, " R9 ")) {
const Vector<std::string> matches = {"RX 460",
"RX 470",
"RX 480",
"RX 490",
"RX 560",
"RX 560X",
"RX 570",
"RX 580",
"RX 580X",
"RX 590",
"RX550/550",
"(TM) 520",
"(TM) 530",
"(TM) 535",
"R5",
"R7",
"R9"};
if (match_renderer(renderer, matches)) {
GCaps.use_hq_normals_workaround = true;
}
}

View File

@ -31,24 +31,24 @@ char *GLLogParser::parse_line(char *log_line, GPULogItem &log_item)
{
/* Skip ERROR: or WARNING:. */
log_line = skip_severity_prefix(log_line, log_item);
log_line = skip_separators(log_line, ':', '(', ' ');
log_line = skip_separators(log_line, "(: ");
/* Parse error line & char numbers. */
if (log_line[0] >= '0' && log_line[0] <= '9') {
if (at_number(log_line)) {
char *error_line_number_end;
log_item.cursor.row = (int)strtol(log_line, &error_line_number_end, 10);
log_item.cursor.row = parse_number(log_line, &error_line_number_end);
/* Try to fetch the error character (not always available). */
if (ELEM(error_line_number_end[0], '(', ':') && error_line_number_end[1] != ' ') {
log_item.cursor.column = (int)strtol(error_line_number_end + 1, &log_line, 10);
if (at_any(error_line_number_end, "(:") && at_number(&error_line_number_end[1])) {
log_item.cursor.column = parse_number(error_line_number_end + 1, &log_line);
}
else {
log_line = error_line_number_end;
}
/* There can be a 3rd number (case of mesa driver). */
if (ELEM(log_line[0], '(', ':') && log_line[1] >= '0' && log_line[1] <= '9') {
if (at_any(log_line, "(:") && at_number(&log_line[1])) {
log_item.cursor.source = log_item.cursor.row;
log_item.cursor.row = log_item.cursor.column;
log_item.cursor.column = (int)strtol(log_line + 1, &error_line_number_end, 10);
log_item.cursor.column = parse_number(log_line + 1, &error_line_number_end);
log_line = error_line_number_end;
}
}
@ -65,11 +65,11 @@ char *GLLogParser::parse_line(char *log_line, GPULogItem &log_item)
}
}
log_line = skip_separators(log_line, ':', ')', ' ');
log_line = skip_separators(log_line, ":) ");
/* Skip to message. Avoid redundant info. */
log_line = skip_severity_keyword(log_line, log_item);
log_line = skip_separators(log_line, ':', ')', ' ');
log_line = skip_separators(log_line, ":) ");
return log_line;
}

View File

@ -46,9 +46,6 @@ typedef struct CollectionChild {
struct Collection *collection;
} CollectionChild;
/**
* \warning while the values seem to be flags, they aren't treated as flags.
*/
enum eCollectionLineArt_Usage {
COLLECTION_LRT_INCLUDE = 0,
COLLECTION_LRT_OCCLUSION_ONLY = (1 << 0),
@ -57,6 +54,10 @@ enum eCollectionLineArt_Usage {
COLLECTION_LRT_NO_INTERSECTION = (1 << 3),
};
enum eCollectionLineArt_Flags {
COLLECTION_LRT_USE_INTERSECTION_MASK = (1 << 0),
};
typedef struct Collection {
ID id;
@ -74,8 +75,10 @@ typedef struct Collection {
/* Runtime-only, always cleared on file load. */
short tag;
/** Line Art engine specific */
short lineart_usage;
short lineart_usage; /* eCollectionLineArt_Usage */
unsigned char lineart_flags; /* eCollectionLineArt_Flags */
unsigned char lineart_intersection_mask;
char _pad[6];
int16_t color_tag;

View File

@ -883,11 +883,14 @@ typedef enum eLineArtGPencilModifierFlags {
LRT_GPENCIL_USE_CACHE = (1 << 4),
} eLineArtGPencilModifierFlags;
typedef enum eLineartGpencilMaterialMaskFlags {
typedef enum eLineartGpencilMaskSwitches {
LRT_GPENCIL_MATERIAL_MASK_ENABLE = (1 << 0),
/** When set, material mask bit comparisons are done with bit wise "AND" instead of "OR". */
LRT_GPENCIL_MATERIAL_MASK_MATCH = (1 << 1),
} eLineartGpencilMaterialMaskFlags;
LRT_GPENCIL_INTERSECTION_MATCH = (1 << 2),
} eLineartGpencilMaskSwitches;
struct LineartCache;
struct LineartCache;
@ -918,8 +921,11 @@ typedef struct LineartGpencilModifierData {
float opacity;
short thickness;
unsigned char material_mask_flags; /* eLineartGpencilMaterialMaskFlags */
unsigned char mask_switches; /* eLineartGpencilMaskSwitches */
unsigned char material_mask_bits;
unsigned char intersection_mask;
char _pad[7];
/** `0..1` range for cosine angle */
float crease_threshold;

View File

@ -47,13 +47,13 @@ typedef enum eLineartMainFlags {
LRT_ALLOW_OVERLAPPING_EDGES = (1 << 3),
LRT_ALLOW_CLIPPING_BOUNDARIES = (1 << 4),
LRT_REMOVE_DOUBLES = (1 << 5),
LRT_FLOATING_AS_CONTOUR = (1 << 6),
LRT_LOOSE_AS_CONTOUR = (1 << 6),
LRT_GPENCIL_INVERT_SOURCE_VGROUP = (1 << 7),
LRT_GPENCIL_MATCH_OUTPUT_VGROUP = (1 << 8),
LRT_FILTER_FACE_MARK = (1 << 9),
LRT_FILTER_FACE_MARK_INVERT = (1 << 10),
LRT_FILTER_FACE_MARK_BOUNDARIES = (1 << 11),
LRT_CHAIN_FLOATING_EDGES = (1 << 12),
LRT_CHAIN_LOOSE_EDGES = (1 << 12),
LRT_CHAIN_GEOMETRY_SPACE = (1 << 13),
LRT_ALLOW_OVERLAP_EDGE_TYPES = (1 << 14),
} eLineartMainFlags;
@ -64,9 +64,7 @@ typedef enum eLineartEdgeFlag {
LRT_EDGE_FLAG_CREASE = (1 << 2),
LRT_EDGE_FLAG_MATERIAL = (1 << 3),
LRT_EDGE_FLAG_INTERSECTION = (1 << 4),
/** Floating edge, unimplemented yet. */
LRT_EDGE_FLAG_FLOATING = (1 << 5),
/** Also used as discarded line mark. */
LRT_EDGE_FLAG_LOOSE = (1 << 5),
LRT_EDGE_FLAG_CHAIN_PICKED = (1 << 6),
LRT_EDGE_FLAG_CLIPPED = (1 << 7),
/** Limited to 8 bits, DON'T ADD ANYMORE until improvements on the data structure. */

View File

@ -152,7 +152,7 @@ typedef struct MaterialLineArt {
/* Used to filter line art occlusion edges */
unsigned char material_mask_bits;
/** Maximum 255 levels of equavalent occlusion. */
/** Maximum 255 levels of equivalent occlusion. */
unsigned char mat_occlusion;
unsigned char _pad[2];

View File

@ -1344,6 +1344,12 @@ typedef struct MeshStatVis {
typedef struct SequencerToolSettings {
/* eSeqImageFitMethod */
int fit_method;
short snap_mode;
short snap_flag;
int _pad0;
/** When there are many snap points, 0-1 range corresponds to resolution from boundbox to all
* possible snap points. */
int snap_distance;
} SequencerToolSettings;
typedef enum eSeqImageFitMethod {
@ -2047,6 +2053,7 @@ enum {
#define SCE_SNAP_NO_SELF (1 << 4)
#define SCE_SNAP_ABS_GRID (1 << 5)
#define SCE_SNAP_BACKFACE_CULLING (1 << 6)
#define SCE_SNAP_SEQ (1 << 7)
/** #ToolSettings.snap_target */
#define SCE_SNAP_TARGET_CLOSEST 0
@ -2059,15 +2066,26 @@ enum {
#define SCE_SNAP_MODE_EDGE (1 << 1)
#define SCE_SNAP_MODE_FACE (1 << 2)
#define SCE_SNAP_MODE_VOLUME (1 << 3)
#define SCE_SNAP_MODE_INCREMENT (1 << 4)
#define SCE_SNAP_MODE_EDGE_MIDPOINT (1 << 5)
#define SCE_SNAP_MODE_EDGE_PERPENDICULAR (1 << 6)
#define SCE_SNAP_MODE_EDGE_MIDPOINT (1 << 4)
#define SCE_SNAP_MODE_EDGE_PERPENDICULAR (1 << 5)
/** #SequencerToolSettings.snap_mode */
#define SEQ_SNAP_TO_STRIPS (1 << 0)
#define SEQ_SNAP_TO_PLAYHEAD (1 << 1)
#define SEQ_SNAP_TO_STRIP_HOLD (1 << 2)
/** #SequencerToolSettings.snap_flag */
#define SEQ_SNAP_IGNORE_MUTED (1 << 0)
#define SEQ_SNAP_IGNORE_SOUND (1 << 1)
/** #ToolSettings.snap_node_mode */
#define SCE_SNAP_MODE_NODE_X (1 << 5)
#define SCE_SNAP_MODE_NODE_Y (1 << 6)
#define SCE_SNAP_MODE_NODE_X (1 << 0)
#define SCE_SNAP_MODE_NODE_Y (1 << 1)
/** #ToolSettings.snap_mode and #ToolSettings.snap_node_mode */
/**
* #ToolSettings.snap_mode and #ToolSettings.snap_node_mode
*/
#define SCE_SNAP_MODE_INCREMENT (1 << 6)
#define SCE_SNAP_MODE_GRID (1 << 7)
/** #ToolSettings.snap_transform_mode_flag */

View File

@ -134,6 +134,6 @@ DNA_STRUCT_RENAME_ELEM(RigidBodyWorld, steps_per_second, substeps_per_frame)
* global_areas. See D9442. */
DNA_STRUCT_RENAME_ELEM(wmWindow, global_area_map, global_areas)
DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, line_types, edge_types)
DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, transparency_flags, material_mask_flags)
DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, transparency_flags, mask_switches)
DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, transparency_mask, material_mask_bits)
DNA_STRUCT_RENAME_ELEM(MaterialLineArt, transparency_mask, material_mask_bits)

View File

@ -548,6 +548,19 @@ void RNA_def_collections(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Usage", "How to use this collection in line art");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "lineart_use_intersection_mask", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "lineart_flags", 1);
RNA_def_property_ui_text(
prop, "Use Intersection Masks", "Use custom intersection mask for faces in this collection");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "lineart_intersection_mask", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "lineart_intersection_mask", 1);
RNA_def_property_array(prop, 8);
RNA_def_property_ui_text(
prop, "Masks", "Intersection generated by this collection will have this mask value");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "color_tag", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "color_tag");
RNA_def_property_enum_funcs(

View File

@ -701,7 +701,7 @@ static void rna_def_modifier_gpencilnoise(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "UV Factor", "Amount of noise to apply uv rotation");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "random", PROP_BOOLEAN, PROP_NONE);
prop = RNA_def_property(srna, "use_random", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_NOISE_USE_RANDOM);
RNA_def_property_ui_text(prop, "Random", "Use random values over time");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
@ -2812,9 +2812,9 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna)
prop, "Remove Doubles", "Remove doubles from the source geometry before generating stokes");
RNA_def_property_update(prop, NC_SCENE, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "floating_as_contour", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "calculation_flags", LRT_FLOATING_AS_CONTOUR);
RNA_def_property_ui_text(prop, "Floating As Contour", "Floating edges will have contour type");
prop = RNA_def_property(srna, "use_loose_as_contour", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "calculation_flags", LRT_LOOSE_AS_CONTOUR);
RNA_def_property_ui_text(prop, "Loose As Contour", "Loose edges will have contour type");
RNA_def_property_update(prop, NC_SCENE, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "invert_source_vertex_group", PROP_BOOLEAN, PROP_NONE);
@ -2853,19 +2853,18 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, 0.3f);
RNA_def_property_update(prop, NC_SCENE, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "chain_floating_edges", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "calculation_flags", LRT_CHAIN_FLOATING_EDGES);
RNA_def_property_ui_text(
prop, "Chain Floating Edges", "Allow floating edges to be chained together");
prop = RNA_def_property(srna, "use_loose_edge_chain", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "calculation_flags", LRT_CHAIN_LOOSE_EDGES);
RNA_def_property_ui_text(prop, "Chain Loose Edges", "Allow loose edges to be chained together");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "chain_geometry_space", PROP_BOOLEAN, PROP_NONE);
prop = RNA_def_property(srna, "use_geometry_space_chain", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "calculation_flags", LRT_CHAIN_GEOMETRY_SPACE);
RNA_def_property_ui_text(
prop, "Use Geometry Space", "Use geometry distance for chaining instead of image space");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "allow_overlap_edge_types", PROP_BOOLEAN, PROP_NONE);
prop = RNA_def_property(srna, "use_overlap_edge_type_support", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "calculation_flags", LRT_ALLOW_OVERLAP_EDGE_TYPES);
RNA_def_property_ui_text(prop,
"Overlapping Edge Types",
@ -2898,9 +2897,9 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Use Contour", "Generate strokes from contours lines");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "use_floating", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "edge_types", LRT_EDGE_FLAG_FLOATING);
RNA_def_property_ui_text(prop, "Use Floating", "Generate strokes from floating edges");
prop = RNA_def_property(srna, "use_loose", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "edge_types", LRT_EDGE_FLAG_LOOSE);
RNA_def_property_ui_text(prop, "Use Loose", "Generate strokes from loose edges");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "use_crease", PROP_BOOLEAN, PROP_NONE);
@ -2998,15 +2997,13 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "use_material_mask", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
prop, NULL, "material_mask_flags", LRT_GPENCIL_MATERIAL_MASK_ENABLE);
RNA_def_property_boolean_sdna(prop, NULL, "mask_switches", LRT_GPENCIL_MATERIAL_MASK_ENABLE);
RNA_def_property_ui_text(
prop, "Use Material Mask", "Use material masks to filter out occluded strokes");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "use_material_mask_match", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
prop, NULL, "material_mask_flags", LRT_GPENCIL_MATERIAL_MASK_MATCH);
RNA_def_property_boolean_sdna(prop, NULL, "mask_switches", LRT_GPENCIL_MATERIAL_MASK_MATCH);
RNA_def_property_ui_text(
prop, "Match Masks", "Require matching all material masks instead of just one");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
@ -3014,7 +3011,19 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_material_mask_bits", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "material_mask_bits", 1);
RNA_def_property_array(prop, 8);
RNA_def_property_ui_text(prop, "Mask", "");
RNA_def_property_ui_text(prop, "Masks", "Mask bits to match from Material Line Art settings");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "use_intersection_match", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mask_switches", LRT_GPENCIL_INTERSECTION_MATCH);
RNA_def_property_ui_text(
prop, "Match Intersection", "Require matching all intersection masks instead of just one");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "use_intersection_mask", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "intersection_mask", 1);
RNA_def_property_array(prop, 8);
RNA_def_property_ui_text(prop, "Masks", "Mask bits to match from Collection Line Art settings");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
RNA_define_lib_overridable(false);

View File

@ -190,6 +190,12 @@ const EnumPropertyItem rna_enum_snap_node_element_items[] = {
{0, NULL, 0, NULL, NULL},
};
const EnumPropertyItem rna_enum_snap_seq_element_items[] = {
{SEQ_SNAP_TO_PLAYHEAD, "PLAYHEAD", ICON_NONE, "Playhead", "Snap to current frame"},
{SEQ_SNAP_TO_STRIP_HOLD, "STRIP_HOLD", ICON_NONE, "Hold Offset", "Snap to strip hold offset"},
{0, NULL, 0, NULL, NULL},
};
#ifndef RNA_RUNTIME
static const EnumPropertyItem snap_uv_element_items[] = {
{SCE_SNAP_MODE_INCREMENT,
@ -3111,6 +3117,12 @@ static void rna_def_tool_settings(BlenderRNA *brna)
"Absolute grid alignment while translating (based on the pivot center)");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
prop = RNA_def_property(srna, "use_snap_sequencer", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_SEQ);
RNA_def_property_ui_text(prop, "Use Snapping", "Snap to strip edges or current frame");
RNA_def_property_ui_icon(prop, ICON_SNAP_OFF, 1);
RNA_def_property_boolean_default(prop, true);
prop = RNA_def_property(srna, "snap_elements", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "snap_mode");
RNA_def_property_enum_items(prop, rna_enum_snap_element_items);
@ -3505,9 +3517,36 @@ static void rna_def_sequencer_tool_settings(BlenderRNA *brna)
RNA_def_struct_path_func(srna, "rna_SequencerToolSettings_path");
RNA_def_struct_ui_text(srna, "Sequencer Tool Settings", "");
/* Add strip settings. */
prop = RNA_def_property(srna, "fit_method", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, scale_fit_methods);
RNA_def_property_ui_text(prop, "Fit Method", "Scale fit method");
/* Transform snapping. */
/* Sequencer editor uses own set of snap modes */
prop = RNA_def_property(srna, "snap_seq_element", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "snap_mode");
RNA_def_property_enum_items(prop, rna_enum_snap_seq_element_items);
RNA_def_property_ui_text(prop, "Snap To", "Type of element to snap to");
RNA_def_property_flag(prop, PROP_ENUM_FLAG);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
prop = RNA_def_property(srna, "snap_ignore_muted", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SEQ_SNAP_IGNORE_MUTED);
RNA_def_property_boolean_default(prop, true);
RNA_def_property_ui_text(prop, "Ignore Muted Strips", "Don't snap to hidden strips");
prop = RNA_def_property(srna, "snap_ignore_sound", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SEQ_SNAP_IGNORE_SOUND);
RNA_def_property_boolean_default(prop, true);
RNA_def_property_ui_text(prop, "Ignore Sound Strips", "Don't snap to sound strips");
prop = RNA_def_property(srna, "snap_distance", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "snap_distance");
RNA_def_property_int_default(prop, 15);
RNA_def_property_ui_range(prop, 0, 50, 1, 1);
RNA_def_property_ui_text(prop, "Snapping Distance", "Maximum distance for snapping in pixels");
}
static void rna_def_unified_paint_settings(BlenderRNA *brna)

View File

@ -384,26 +384,28 @@ static void rna_uiItemsEnumO(uiLayout *layout,
uiItemsFullEnumO(layout, opname, propname, NULL, uiLayoutGetOperatorContext(layout), flag);
}
static void rna_uiItemMenuEnumO(uiLayout *layout,
bContext *C,
const char *opname,
const char *propname,
const char *name,
const char *text_ctxt,
bool translate,
int icon)
static PointerRNA rna_uiItemMenuEnumO(uiLayout *layout,
bContext *C,
const char *opname,
const char *propname,
const char *name,
const char *text_ctxt,
bool translate,
int icon)
{
wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
if (!ot || !ot->srna) {
RNA_warning("%s '%s'", ot ? "unknown operator" : "operator missing srna", opname);
return;
return PointerRNA_NULL;
}
/* Get translated name (label). */
name = rna_translate_ui_text(name, text_ctxt, ot->srna, NULL, translate);
uiItemMenuEnumO_ptr(layout, C, ot, propname, name, icon);
PointerRNA opptr;
uiItemMenuEnumFullO_ptr(layout, C, ot, propname, name, icon, &opptr);
return opptr;
}
static void rna_uiItemL(uiLayout *layout,
@ -1028,6 +1030,10 @@ void RNA_api_ui_layout(StructRNA *srna)
parm = RNA_def_string(func, "property", NULL, 0, "", "Identifier of property in operator");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
api_ui_item_common(func);
parm = RNA_def_pointer(
func, "properties", "OperatorProperties", "", "Operator properties to fill in");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_function_return(func, parm);
/* useful in C but not in python */
# if 0

View File

@ -71,6 +71,7 @@ bool SEQ_iterator_ensure(SeqCollection *collection,
struct Sequence *SEQ_iterator_yield(SeqIterator *iterator);
SeqCollection *SEQ_collection_create(void);
uint SEQ_collection_count(SeqCollection *collection);
bool SEQ_collection_append_strip(struct Sequence *seq, SeqCollection *data);
bool SEQ_collection_remove_strip(struct Sequence *seq, SeqCollection *data);
void SEQ_collection_free(SeqCollection *collection);

View File

@ -55,6 +55,9 @@ struct SequencerToolSettings *SEQ_tool_settings_ensure(struct Scene *scene);
void SEQ_tool_settings_free(struct SequencerToolSettings *tool_settings);
eSeqImageFitMethod SEQ_tool_settings_fit_method_get(struct Scene *scene);
void SEQ_tool_settings_fit_method_set(struct Scene *scene, eSeqImageFitMethod fit_method);
short SEQ_tool_settings_snap_flag_get(struct Scene *scene);
short SEQ_tool_settings_snap_mode_get(struct Scene *scene);
int SEQ_tool_settings_snap_distance_get(struct Scene *scene);
struct SequencerToolSettings *SEQ_tool_settings_copy(struct SequencerToolSettings *tool_settings);
struct Editing *SEQ_editing_get(struct Scene *scene, bool alloc);
struct Editing *SEQ_editing_ensure(struct Scene *scene);

View File

@ -114,6 +114,14 @@ SeqCollection *SEQ_collection_create(void)
return collection;
}
/**
* Return number of items in collection.
*/
uint SEQ_collection_count(SeqCollection *collection)
{
return BLI_gset_len(collection->set);
}
/**
* Query strips from seqbase. seq_reference is used by query function as filter condition.
*

View File

@ -311,6 +311,8 @@ SequencerToolSettings *SEQ_tool_settings_init(void)
SequencerToolSettings *tool_settings = MEM_callocN(sizeof(SequencerToolSettings),
"Sequencer tool settings");
tool_settings->fit_method = SEQ_SCALE_TO_FIT;
tool_settings->snap_mode = SEQ_SNAP_TO_STRIPS | SEQ_SNAP_TO_PLAYHEAD | SEQ_SNAP_TO_STRIP_HOLD;
tool_settings->snap_distance = 15;
return tool_settings;
}
@ -336,6 +338,24 @@ eSeqImageFitMethod SEQ_tool_settings_fit_method_get(Scene *scene)
return tool_settings->fit_method;
}
short SEQ_tool_settings_snap_mode_get(Scene *scene)
{
const SequencerToolSettings *tool_settings = SEQ_tool_settings_ensure(scene);
return tool_settings->snap_mode;
}
short SEQ_tool_settings_snap_flag_get(Scene *scene)
{
const SequencerToolSettings *tool_settings = SEQ_tool_settings_ensure(scene);
return tool_settings->snap_flag;
}
int SEQ_tool_settings_snap_distance_get(Scene *scene)
{
const SequencerToolSettings *tool_settings = SEQ_tool_settings_ensure(scene);
return tool_settings->snap_distance;
}
void SEQ_tool_settings_fit_method_set(Scene *scene, eSeqImageFitMethod fit_method)
{
SequencerToolSettings *tool_settings = SEQ_tool_settings_ensure(scene);

View File

@ -827,14 +827,13 @@ wmWindow *WM_window_open(bContext *C,
win = wm_window_new(bmain, wm, toplevel ? NULL : win_prev, dialog);
win->posx = rect.xmin;
win->posy = rect.ymin;
win->sizex = BLI_rcti_size_x(&rect);
win->sizey = BLI_rcti_size_y(&rect);
*win->stereo3d_format = *win_prev->stereo3d_format;
}
bScreen *screen = WM_window_get_active_screen(win);
win->sizex = BLI_rcti_size_x(&rect);
win->sizey = BLI_rcti_size_y(&rect);
if (WM_window_get_active_workspace(win) == NULL) {
WorkSpace *workspace = WM_window_get_active_workspace(win_prev);
BKE_workspace_active_set(win->workspace_hook, workspace);