UI: Asset Shelf (Experimental Feature) #104831
|
@ -22,6 +22,7 @@ endif()
|
|||
|
||||
|
||||
add_subdirectory(rangetree)
|
||||
add_subdirectory(nanosvg)
|
||||
add_subdirectory(wcwidth)
|
||||
|
||||
if(WITH_BULLET)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Project: JSON
|
||||
URL: https://github.com/nlohmann/json/
|
||||
License: MIT License
|
||||
Upstream version: 3.10.2
|
||||
Upstream version: 3.11.2
|
||||
Local modifications: None
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,21 @@
|
|||
# SPDX-FileCopyrightText: 2002-2022 Blender Foundation
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
set(INC
|
||||
PUBLIC .
|
||||
../../source/blender/blenlib
|
||||
)
|
||||
|
||||
set(SRC
|
||||
nanosvg.h
|
||||
nanosvgrast.h
|
||||
blender_nanosvg.c
|
||||
blender_raster.c
|
||||
)
|
||||
|
||||
set(LIB
|
||||
)
|
||||
|
||||
blender_add_lib(extern_nanosvg "${SRC}" "${INC}" "" "${LIB}")
|
||||
add_library(bf::extern::nanosvg ALIAS extern_nanosvg)
|
|
@ -1,7 +1,9 @@
|
|||
Project: NanoSVG
|
||||
URL: https://github.com/memononen/nanosvg
|
||||
License: zlib
|
||||
Upstream version: 3cdd4a9d7886
|
||||
Local modifications: Added some functionality to manage grease pencil layers
|
||||
Upstream SHA: 9da543e8329fdd81b64eb48742d8ccb09377aed1
|
||||
GPG key ID: 4AEE18F83AFDEB23
|
||||
Last Commit: "Merge pull request #236 from sezero/signed-char"
|
||||
Last Commit Date: December 4, 2022
|
||||
|
||||
Added a fix to SVG import arc and float errors (https://developer.blender.org/rB11dc674c78b49fc4e0b7c134c375b6c8b8eacbcc)
|
||||
Local modifications: Added some functionality to manage grease pencil layers
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#define NANOSVG_IMPLEMENTATION
|
||||
#define NANOSVG_ALL_COLOR_KEYWORDS
|
||||
|
||||
#include <stdio.h>
|
||||
#include "BLI_utildefines.h"
|
||||
#include "nanosvg.h"
|
|
@ -0,0 +1,6 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#define NANOSVGRAST_IMPLEMENTATION
|
||||
#include "nanosvgrast.h"
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,86 +1,647 @@
|
|||
diff --git a/c:/tmp/nanosvg_original.h b/c:/tmp/nanosvg_modif.h
|
||||
index 24a01a86d3d..eca0d07e79d 100644
|
||||
--- a/c:/tmp/nanosvg_original.h
|
||||
+++ b/c:/tmp/nanosvg_modif.h
|
||||
@@ -24,7 +24,8 @@
|
||||
diff --git a/extern/nanosvg/nanosvg.h b/extern/nanosvg/nanosvg.h
|
||||
index 60a323820cb..1bfb891c397 100644
|
||||
--- a/extern/nanosvg/nanosvg.h
|
||||
+++ b/extern/nanosvg/nanosvg.h
|
||||
@@ -1,56 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14 Mikko Mononen memon@inside.org
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* The SVG parser is based on Anti-Grain Geometry 2.4 SVG example
|
||||
* Copyright (C) 2002-2004 Maxim Shemanarev (McSeem) (http://www.antigrain.com/)
|
||||
*
|
||||
* Arc calculation code based on canvg (https://code.google.com/p/canvg/)
|
||||
*
|
||||
* Bounding box calculation based on http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
|
||||
*
|
||||
- */
|
||||
+ * This is a modified version for Blender used by importers.
|
||||
+ **/
|
||||
+ *
|
||||
*/
|
||||
|
||||
#ifndef NANOSVG_H
|
||||
#define NANOSVG_H
|
||||
@@ -148,6 +149,8 @@ extern "C" {
|
||||
typedef struct NSVGshape
|
||||
{
|
||||
char id[64]; // Optional 'id' attr of the shape or its group
|
||||
+ /* Blender: Parent ID used for layer creation. */
|
||||
+ char id_parent[64];
|
||||
NSVGpaint fill; // Fill paint
|
||||
NSVGpaint stroke; // Stroke paint
|
||||
float opacity; // Opacity of the shape.
|
||||
@@ -370,6 +373,7 @@ int nsvg__parseXML(char* input,
|
||||
|
||||
#ifndef NANOSVG_CPLUSPLUS
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// NanoSVG is a simple stupid single-header-file SVG parse. The output of the parser is a list of cubic bezier shapes.
|
||||
//
|
||||
// The library suits well for anything from rendering scalable icons in your editor application to prototyping a game.
|
||||
//
|
||||
// NanoSVG supports a wide range of SVG features, but something may be missing, feel free to create a pull request!
|
||||
//
|
||||
// The shapes in the SVG images are transformed by the viewBox and converted to specified units.
|
||||
// That is, you should get the same looking data as your designed in your favorite app.
|
||||
//
|
||||
// NanoSVG can return the paths in few different units. For example if you want to render an image, you may choose
|
||||
// to get the paths in pixels, or if you are feeding the data into a CNC-cutter, you may want to use millimeters.
|
||||
//
|
||||
// The units passed to NanoSVG should be one of: 'px', 'pt', 'pc' 'mm', 'cm', or 'in'.
|
||||
// DPI (dots-per-inch) controls how the unit conversion is done.
|
||||
//
|
||||
// If you don't know or care about the units stuff, "px" and 96 should get you going.
|
||||
|
||||
|
||||
/* Example Usage:
|
||||
@@ -112,60 +114,61 @@ typedef struct NSVGgradientStop {
|
||||
} NSVGgradientStop;
|
||||
|
||||
typedef struct NSVGgradient {
|
||||
float xform[6];
|
||||
char spread;
|
||||
float fx, fy;
|
||||
int nstops;
|
||||
NSVGgradientStop stops[1];
|
||||
} NSVGgradient;
|
||||
|
||||
typedef struct NSVGpaint {
|
||||
signed char type;
|
||||
union {
|
||||
unsigned int color;
|
||||
NSVGgradient* gradient;
|
||||
};
|
||||
} NSVGpaint;
|
||||
|
||||
typedef struct NSVGpath
|
||||
{
|
||||
float* pts; // Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ...
|
||||
int npts; // Total number of bezier points.
|
||||
char closed; // Flag indicating if shapes should be treated as closed.
|
||||
float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy].
|
||||
struct NSVGpath* next; // Pointer to next path, or NULL if last element.
|
||||
} NSVGpath;
|
||||
|
||||
typedef struct NSVGshape
|
||||
{
|
||||
char id[64]; // Optional 'id' attr of the shape or its group
|
||||
+ char id_parent[64]; // Blender: Parent ID used for layer creation.
|
||||
NSVGpaint fill; // Fill paint
|
||||
NSVGpaint stroke; // Stroke paint
|
||||
float opacity; // Opacity of the shape.
|
||||
float strokeWidth; // Stroke width (scaled).
|
||||
float strokeDashOffset; // Stroke dash offset (scaled).
|
||||
float strokeDashArray[8]; // Stroke dash array (scaled).
|
||||
char strokeDashCount; // Number of dash values in dash array.
|
||||
char strokeLineJoin; // Stroke join type.
|
||||
char strokeLineCap; // Stroke cap type.
|
||||
float miterLimit; // Miter limit
|
||||
char fillRule; // Fill rule, see NSVGfillRule.
|
||||
unsigned char flags; // Logical or of NSVG_FLAGS_* flags
|
||||
float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy].
|
||||
char fillGradient[64]; // Optional 'id' of fill gradient
|
||||
char strokeGradient[64]; // Optional 'id' of stroke gradient
|
||||
float xform[6]; // Root transformation for fill/stroke gradient
|
||||
NSVGpath* paths; // Linked list of paths in the image.
|
||||
struct NSVGshape* next; // Pointer to next shape, or NULL if last element.
|
||||
} NSVGshape;
|
||||
|
||||
typedef struct NSVGimage
|
||||
{
|
||||
float width; // Width of the image.
|
||||
float height; // Height of the image.
|
||||
NSVGshape* shapes; // Linked list of shapes in the image.
|
||||
} NSVGimage;
|
||||
|
||||
// Parses SVG file from a file, returns SVG image as paths.
|
||||
NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi);
|
||||
|
||||
@@ -333,60 +336,61 @@ int nsvg__parseXML(char* input,
|
||||
void* ud)
|
||||
{
|
||||
char* s = input;
|
||||
char* mark = s;
|
||||
int state = NSVG_XML_CONTENT;
|
||||
while (*s) {
|
||||
if (*s == '<' && state == NSVG_XML_CONTENT) {
|
||||
// Start of a tag
|
||||
*s++ = '\0';
|
||||
nsvg__parseContent(mark, contentCb, ud);
|
||||
mark = s;
|
||||
state = NSVG_XML_TAG;
|
||||
} else if (*s == '>' && state == NSVG_XML_TAG) {
|
||||
// Start of a content or new tag.
|
||||
*s++ = '\0';
|
||||
nsvg__parseElement(mark, startelCb, endelCb, ud);
|
||||
mark = s;
|
||||
state = NSVG_XML_CONTENT;
|
||||
} else {
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Simple SVG parser. */
|
||||
|
||||
#define NSVG_MAX_ATTR 128
|
||||
+#define NSVG_MAX_BREADCRUMB 5
|
||||
|
||||
enum NSVGgradientUnits
|
||||
enum NSVGgradientUnits {
|
||||
NSVG_USER_SPACE = 0,
|
||||
NSVG_OBJECT_SPACE = 1
|
||||
};
|
||||
|
||||
#define NSVG_MAX_DASHES 8
|
||||
|
||||
enum NSVGunits {
|
||||
NSVG_UNITS_USER,
|
||||
NSVG_UNITS_PX,
|
||||
NSVG_UNITS_PT,
|
||||
NSVG_UNITS_PC,
|
||||
NSVG_UNITS_MM,
|
||||
NSVG_UNITS_CM,
|
||||
NSVG_UNITS_IN,
|
||||
NSVG_UNITS_PERCENT,
|
||||
NSVG_UNITS_EM,
|
||||
NSVG_UNITS_EX
|
||||
};
|
||||
|
||||
typedef struct NSVGcoordinate {
|
||||
float value;
|
||||
int units;
|
||||
} NSVGcoordinate;
|
||||
|
||||
typedef struct NSVGlinearData {
|
||||
NSVGcoordinate x1, y1, x2, y2;
|
||||
} NSVGlinearData;
|
||||
|
||||
@@ -428,60 +432,64 @@ typedef struct NSVGattrib
|
||||
int strokeDashCount;
|
||||
char strokeLineJoin;
|
||||
char strokeLineCap;
|
||||
float miterLimit;
|
||||
char fillRule;
|
||||
float fontSize;
|
||||
unsigned int stopColor;
|
||||
float stopOpacity;
|
||||
float stopOffset;
|
||||
char hasFill;
|
||||
char hasStroke;
|
||||
char visible;
|
||||
} NSVGattrib;
|
||||
|
||||
typedef struct NSVGparser
|
||||
{
|
||||
@@ -471,6 +475,10 @@ typedef struct NSVGparser
|
||||
NSVGattrib attr[NSVG_MAX_ATTR];
|
||||
int attrHead;
|
||||
float* pts;
|
||||
int npts;
|
||||
int cpts;
|
||||
NSVGpath* plist;
|
||||
NSVGimage* image;
|
||||
NSVGgradientData* gradients;
|
||||
NSVGshape* shapesTail;
|
||||
float viewMinx, viewMiny, viewWidth, viewHeight;
|
||||
int alignX, alignY, alignType;
|
||||
float dpi;
|
||||
char pathFlag;
|
||||
char defsFlag;
|
||||
+ /** Blender breadcrumb for layers. */
|
||||
+ char breadcrumb[NSVG_MAX_BREADCRUMB][64];
|
||||
+ /** Blender number of elements in breadcrumb. */
|
||||
+ int breadcrumb_len;
|
||||
+ /** Blender breadcrumb for layers. */
|
||||
+ char breadcrumb[NSVG_MAX_BREADCRUMB][64];
|
||||
+ /** Blender number of elements in breadcrumb. */
|
||||
+ int breadcrumb_len;
|
||||
} NSVGparser;
|
||||
|
||||
static void nsvg__xformIdentity(float* t)
|
||||
@@ -980,6 +988,14 @@ static void nsvg__addShape(NSVGparser* p)
|
||||
{
|
||||
t[0] = 1.0f; t[1] = 0.0f;
|
||||
t[2] = 0.0f; t[3] = 1.0f;
|
||||
t[4] = 0.0f; t[5] = 0.0f;
|
||||
}
|
||||
|
||||
static void nsvg__xformSetTranslation(float* t, float tx, float ty)
|
||||
{
|
||||
t[0] = 1.0f; t[1] = 0.0f;
|
||||
t[2] = 0.0f; t[3] = 1.0f;
|
||||
t[4] = tx; t[5] = ty;
|
||||
}
|
||||
|
||||
static void nsvg__xformSetScale(float* t, float sx, float sy)
|
||||
{
|
||||
t[0] = sx; t[1] = 0.0f;
|
||||
t[2] = 0.0f; t[3] = sy;
|
||||
t[4] = 0.0f; t[5] = 0.0f;
|
||||
}
|
||||
|
||||
static void nsvg__xformSetSkewX(float* t, float a)
|
||||
{
|
||||
t[0] = 1.0f; t[1] = 0.0f;
|
||||
t[2] = tanf(a); t[3] = 1.0f;
|
||||
t[4] = 0.0f; t[5] = 0.0f;
|
||||
}
|
||||
|
||||
@@ -930,60 +938,68 @@ static void nsvg__getLocalBounds(float* bounds, NSVGshape *shape, float* xform)
|
||||
bounds[2] = curveBounds[2];
|
||||
bounds[3] = curveBounds[3];
|
||||
first = 0;
|
||||
} else {
|
||||
bounds[0] = nsvg__minf(bounds[0], curveBounds[0]);
|
||||
bounds[1] = nsvg__minf(bounds[1], curveBounds[1]);
|
||||
bounds[2] = nsvg__maxf(bounds[2], curveBounds[2]);
|
||||
bounds[3] = nsvg__maxf(bounds[3], curveBounds[3]);
|
||||
}
|
||||
curve[0] = curve[6];
|
||||
curve[1] = curve[7];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void nsvg__addShape(NSVGparser* p)
|
||||
{
|
||||
NSVGattrib* attr = nsvg__getAttr(p);
|
||||
float scale = 1.0f;
|
||||
NSVGshape* shape;
|
||||
NSVGpath* path;
|
||||
int i;
|
||||
|
||||
if (p->plist == NULL)
|
||||
return;
|
||||
|
||||
shape = (NSVGshape*)malloc(sizeof(NSVGshape));
|
||||
if (shape == NULL) goto error;
|
||||
memset(shape, 0, sizeof(NSVGshape));
|
||||
|
||||
memcpy(shape->id, attr->id, sizeof shape->id);
|
||||
+ /* Copy parent id from breadcrumb. */
|
||||
+ if (p->breadcrumb_len > 0) {
|
||||
+ memcpy(shape->id_parent, p->breadcrumb[0], sizeof shape->id_parent);
|
||||
+ }
|
||||
+ else {
|
||||
+ memcpy(shape->id_parent, attr->id, sizeof shape->id_parent);
|
||||
+ }
|
||||
+ /* Copy parent id from breadcrumb. */
|
||||
+ if (p->breadcrumb_len > 0) {
|
||||
+ memcpy(shape->id_parent, p->breadcrumb[0], sizeof shape->id_parent);
|
||||
+ }
|
||||
+ else {
|
||||
+ memcpy(shape->id_parent, attr->id, sizeof shape->id_parent);
|
||||
+ }
|
||||
+
|
||||
memcpy(shape->id, attr->id, sizeof shape->id);
|
||||
memcpy(shape->fillGradient, attr->fillGradient, sizeof shape->fillGradient);
|
||||
memcpy(shape->strokeGradient, attr->strokeGradient, sizeof shape->strokeGradient);
|
||||
memcpy(shape->xform, attr->xform, sizeof shape->xform);
|
||||
scale = nsvg__getAverageScale(attr->xform);
|
||||
shape->strokeWidth = attr->strokeWidth * scale;
|
||||
shape->strokeDashOffset = attr->strokeDashOffset * scale;
|
||||
@@ -2814,6 +2830,14 @@ static void nsvg__startElement(void* ud, const char* el, const char** attr)
|
||||
shape->strokeDashCount = (char)attr->strokeDashCount;
|
||||
for (i = 0; i < attr->strokeDashCount; i++)
|
||||
shape->strokeDashArray[i] = attr->strokeDashArray[i] * scale;
|
||||
shape->strokeLineJoin = attr->strokeLineJoin;
|
||||
shape->strokeLineCap = attr->strokeLineCap;
|
||||
shape->miterLimit = attr->miterLimit;
|
||||
shape->fillRule = attr->fillRule;
|
||||
shape->opacity = attr->opacity;
|
||||
|
||||
shape->paths = p->plist;
|
||||
p->plist = NULL;
|
||||
|
||||
// Calculate shape bounds
|
||||
shape->bounds[0] = shape->paths->bounds[0];
|
||||
shape->bounds[1] = shape->paths->bounds[1];
|
||||
shape->bounds[2] = shape->paths->bounds[2];
|
||||
shape->bounds[3] = shape->paths->bounds[3];
|
||||
for (path = shape->paths->next; path != NULL; path = path->next) {
|
||||
shape->bounds[0] = nsvg__minf(shape->bounds[0], path->bounds[0]);
|
||||
shape->bounds[1] = nsvg__minf(shape->bounds[1], path->bounds[1]);
|
||||
shape->bounds[2] = nsvg__maxf(shape->bounds[2], path->bounds[2]);
|
||||
shape->bounds[3] = nsvg__maxf(shape->bounds[3], path->bounds[3]);
|
||||
}
|
||||
@@ -1175,66 +1191,75 @@ static const char* nsvg__parseNumber(const char* s, char* it, const int size)
|
||||
if ((*s == 'e' || *s == 'E') && (s[1] != 'm' && s[1] != 'x')) {
|
||||
if (i < last) it[i++] = *s;
|
||||
s++;
|
||||
if (*s == '-' || *s == '+') {
|
||||
if (i < last) it[i++] = *s;
|
||||
s++;
|
||||
}
|
||||
while (*s && nsvg__isdigit(*s)) {
|
||||
if (i < last) it[i++] = *s;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
it[i] = '\0';
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static const char* nsvg__getNextPathItemWhenArcFlag(const char* s, char* it)
|
||||
{
|
||||
it[0] = '\0';
|
||||
while (*s && (nsvg__isspace(*s) || *s == ',')) s++;
|
||||
if (!*s) return s;
|
||||
if (*s == '0' || *s == '1') {
|
||||
it[0] = *s++;
|
||||
it[1] = '\0';
|
||||
return s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
-static const char* nsvg__getNextPathItem(const char* s, char* it)
|
||||
+static const char* nsvg__getNextPathItem(const char* s, char* it, char cmd, int nargs)
|
||||
{
|
||||
it[0] = '\0';
|
||||
// Skip white spaces and commas
|
||||
while (*s && (nsvg__isspace(*s) || *s == ',')) s++;
|
||||
if (!*s) return s;
|
||||
+
|
||||
+ /* Blender: Special case for arc command's 4th and 5th arguments. */
|
||||
+ if ((cmd == 'a' || cmd == 'A') && (nargs == 3 || nargs == 4)) {
|
||||
+ it[0] = s[0];
|
||||
+ it[1] = '\0';
|
||||
+ s++;
|
||||
+ return s;
|
||||
+ }
|
||||
+
|
||||
if (*s == '-' || *s == '+' || *s == '.' || nsvg__isdigit(*s)) {
|
||||
s = nsvg__parseNumber(s, it, 64);
|
||||
} else {
|
||||
// Parse command
|
||||
it[0] = *s++;
|
||||
it[1] = '\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static unsigned int nsvg__parseColorHex(const char* str)
|
||||
{
|
||||
unsigned int r=0, g=0, b=0;
|
||||
if (sscanf(str, "#%2x%2x%2x", &r, &g, &b) == 3 ) // 2 digit hex
|
||||
return NSVG_RGB(r, g, b);
|
||||
if (sscanf(str, "#%1x%1x%1x", &r, &g, &b) == 3 ) // 1 digit hex, e.g. #abc -> 0xccbbaa
|
||||
return NSVG_RGB(r*17, g*17, b*17); // same effect as (r<<4|r), (g<<4|g), ..
|
||||
return NSVG_RGB(128, 128, 128);
|
||||
}
|
||||
|
||||
// Parse rgb color. The pointer 'str' must point at "rgb(" (4+ characters).
|
||||
// This function returns gray (rgb(128, 128, 128) == '#808080') on parse errors
|
||||
// for backwards compatibility. Note: other image viewers return black instead.
|
||||
|
||||
static unsigned int nsvg__parseColorRGB(const char* str)
|
||||
{
|
||||
int i;
|
||||
unsigned int rgbi[3];
|
||||
@@ -2264,61 +2289,61 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr)
|
||||
const char* tmp[4];
|
||||
char closedFlag;
|
||||
int i;
|
||||
char item[64];
|
||||
|
||||
for (i = 0; attr[i]; i += 2) {
|
||||
if (strcmp(attr[i], "d") == 0) {
|
||||
s = attr[i + 1];
|
||||
} else {
|
||||
tmp[0] = attr[i];
|
||||
tmp[1] = attr[i + 1];
|
||||
tmp[2] = 0;
|
||||
tmp[3] = 0;
|
||||
nsvg__parseAttribs(p, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
if (s) {
|
||||
nsvg__resetPath(p);
|
||||
cpx = 0; cpy = 0;
|
||||
cpx2 = 0; cpy2 = 0;
|
||||
initPoint = 0;
|
||||
closedFlag = 0;
|
||||
nargs = 0;
|
||||
|
||||
while (*s) {
|
||||
item[0] = '\0';
|
||||
if ((cmd == 'A' || cmd == 'a') && (nargs == 3 || nargs == 4))
|
||||
s = nsvg__getNextPathItemWhenArcFlag(s, item);
|
||||
if (!*item)
|
||||
- s = nsvg__getNextPathItem(s, item);
|
||||
+ s = nsvg__getNextPathItem(s, item, cmd, nargs);
|
||||
if (!*item) break;
|
||||
if (cmd != '\0' && nsvg__isCoordinate(item)) {
|
||||
if (nargs < 10)
|
||||
args[nargs++] = (float)nsvg__atof(item);
|
||||
if (nargs >= rargs) {
|
||||
switch (cmd) {
|
||||
case 'm':
|
||||
case 'M':
|
||||
nsvg__pathMoveTo(p, &cpx, &cpy, args, cmd == 'm' ? 1 : 0);
|
||||
// Moveto can be followed by multiple coordinate pairs,
|
||||
// which should be treated as linetos.
|
||||
cmd = (cmd == 'm') ? 'l' : 'L';
|
||||
rargs = nsvg__getArgsPerElement(cmd);
|
||||
cpx2 = cpx; cpy2 = cpy;
|
||||
initPoint = 1;
|
||||
break;
|
||||
case 'l':
|
||||
case 'L':
|
||||
nsvg__pathLineTo(p, &cpx, &cpy, args, cmd == 'l' ? 1 : 0);
|
||||
cpx2 = cpx; cpy2 = cpy;
|
||||
break;
|
||||
case 'H':
|
||||
case 'h':
|
||||
nsvg__pathHLineTo(p, &cpx, &cpy, args, cmd == 'h' ? 1 : 0);
|
||||
cpx2 = cpx; cpy2 = cpy;
|
||||
break;
|
||||
case 'V':
|
||||
case 'v':
|
||||
nsvg__pathVLineTo(p, &cpx, &cpy, args, cmd == 'v' ? 1 : 0);
|
||||
cpx2 = cpx; cpy2 = cpy;
|
||||
@@ -2534,61 +2559,61 @@ static void nsvg__parseLine(NSVGparser* p, const char** attr)
|
||||
if (strcmp(attr[i], "y2") == 0) y2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
|
||||
}
|
||||
}
|
||||
|
||||
nsvg__resetPath(p);
|
||||
|
||||
nsvg__moveTo(p, x1, y1);
|
||||
nsvg__lineTo(p, x2, y2);
|
||||
|
||||
nsvg__addPath(p, 0);
|
||||
|
||||
nsvg__addShape(p);
|
||||
}
|
||||
|
||||
static void nsvg__parsePoly(NSVGparser* p, const char** attr, int closeFlag)
|
||||
{
|
||||
int i;
|
||||
const char* s;
|
||||
float args[2];
|
||||
int nargs, npts = 0;
|
||||
char item[64];
|
||||
|
||||
nsvg__resetPath(p);
|
||||
|
||||
for (i = 0; attr[i]; i += 2) {
|
||||
if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
|
||||
if (strcmp(attr[i], "points") == 0) {
|
||||
s = attr[i + 1];
|
||||
nargs = 0;
|
||||
while (*s) {
|
||||
- s = nsvg__getNextPathItem(s, item);
|
||||
+ s = nsvg__getNextPathItem(s, item, '\0', nargs);
|
||||
args[nargs++] = (float)nsvg__atof(item);
|
||||
if (nargs >= 2) {
|
||||
if (npts == 0)
|
||||
nsvg__moveTo(p, args[0], args[1]);
|
||||
else
|
||||
nsvg__lineTo(p, args[0], args[1]);
|
||||
nargs = 0;
|
||||
npts++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsvg__addPath(p, (char)closeFlag);
|
||||
|
||||
nsvg__addShape(p);
|
||||
}
|
||||
|
||||
static void nsvg__parseSVG(NSVGparser* p, const char** attr)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; attr[i]; i += 2) {
|
||||
if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
|
||||
if (strcmp(attr[i], "width") == 0) {
|
||||
p->image->width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
|
||||
} else if (strcmp(attr[i], "height") == 0) {
|
||||
p->image->height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
|
||||
} else if (strcmp(attr[i], "viewBox") == 0) {
|
||||
const char *s = attr[i + 1];
|
||||
@@ -2740,108 +2765,122 @@ static void nsvg__parseGradientStop(NSVGparser* p, const char** attr)
|
||||
if (idx != grad->nstops-1) {
|
||||
for (i = grad->nstops-1; i > idx; i--)
|
||||
grad->stops[i] = grad->stops[i-1];
|
||||
}
|
||||
|
||||
stop = &grad->stops[idx];
|
||||
stop->color = curAttr->stopColor;
|
||||
stop->color |= (unsigned int)(curAttr->stopOpacity*255) << 24;
|
||||
stop->offset = curAttr->stopOffset;
|
||||
}
|
||||
|
||||
static void nsvg__startElement(void* ud, const char* el, const char** attr)
|
||||
{
|
||||
NSVGparser* p = (NSVGparser*)ud;
|
||||
|
||||
if (p->defsFlag) {
|
||||
// Skip everything but gradients in defs
|
||||
if (strcmp(el, "linearGradient") == 0) {
|
||||
nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT);
|
||||
} else if (strcmp(el, "radialGradient") == 0) {
|
||||
nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT);
|
||||
} else if (strcmp(el, "stop") == 0) {
|
||||
nsvg__parseGradientStop(p, attr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(el, "g") == 0) {
|
||||
nsvg__pushAttr(p);
|
||||
nsvg__parseAttribs(p, attr);
|
||||
+
|
||||
+ /* Save the breadcrumb of groups. */
|
||||
+ if (p->breadcrumb_len < NSVG_MAX_BREADCRUMB) {
|
||||
+ NSVGattrib *attr_id = nsvg__getAttr(p);
|
||||
+ memcpy(
|
||||
+ p->breadcrumb[p->breadcrumb_len], attr_id->id, sizeof(p->breadcrumb[p->breadcrumb_len]));
|
||||
+ p->breadcrumb_len++;
|
||||
+ }
|
||||
}
|
||||
else if (strcmp(el, "path") == 0) {
|
||||
+ /* Save the breadcrumb of groups. */
|
||||
+ if (p->breadcrumb_len < NSVG_MAX_BREADCRUMB) {
|
||||
+ NSVGattrib *attr_id = nsvg__getAttr(p);
|
||||
+ memcpy(
|
||||
+ p->breadcrumb[p->breadcrumb_len], attr_id->id, sizeof(p->breadcrumb[p->breadcrumb_len]));
|
||||
+ p->breadcrumb_len++;
|
||||
+ }
|
||||
} else if (strcmp(el, "path") == 0) {
|
||||
if (p->pathFlag) // Do not allow nested paths.
|
||||
@@ -2874,7 +2898,12 @@ static void nsvg__endElement(void* ud, const char* el)
|
||||
return;
|
||||
nsvg__pushAttr(p);
|
||||
nsvg__parsePath(p, attr);
|
||||
nsvg__popAttr(p);
|
||||
} else if (strcmp(el, "rect") == 0) {
|
||||
nsvg__pushAttr(p);
|
||||
nsvg__parseRect(p, attr);
|
||||
nsvg__popAttr(p);
|
||||
} else if (strcmp(el, "circle") == 0) {
|
||||
nsvg__pushAttr(p);
|
||||
nsvg__parseCircle(p, attr);
|
||||
nsvg__popAttr(p);
|
||||
} else if (strcmp(el, "ellipse") == 0) {
|
||||
nsvg__pushAttr(p);
|
||||
nsvg__parseEllipse(p, attr);
|
||||
nsvg__popAttr(p);
|
||||
} else if (strcmp(el, "line") == 0) {
|
||||
nsvg__pushAttr(p);
|
||||
nsvg__parseLine(p, attr);
|
||||
nsvg__popAttr(p);
|
||||
} else if (strcmp(el, "polyline") == 0) {
|
||||
nsvg__pushAttr(p);
|
||||
nsvg__parsePoly(p, attr, 0);
|
||||
nsvg__popAttr(p);
|
||||
} else if (strcmp(el, "polygon") == 0) {
|
||||
nsvg__pushAttr(p);
|
||||
nsvg__parsePoly(p, attr, 1);
|
||||
nsvg__popAttr(p);
|
||||
} else if (strcmp(el, "linearGradient") == 0) {
|
||||
nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT);
|
||||
} else if (strcmp(el, "radialGradient") == 0) {
|
||||
nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT);
|
||||
} else if (strcmp(el, "stop") == 0) {
|
||||
nsvg__parseGradientStop(p, attr);
|
||||
} else if (strcmp(el, "defs") == 0) {
|
||||
p->defsFlag = 1;
|
||||
} else if (strcmp(el, "svg") == 0) {
|
||||
nsvg__parseSVG(p, attr);
|
||||
}
|
||||
}
|
||||
|
||||
static void nsvg__endElement(void* ud, const char* el)
|
||||
{
|
||||
NSVGparser* p = (NSVGparser*)ud;
|
||||
|
||||
if (strcmp(el, "g") == 0) {
|
||||
- nsvg__popAttr(p);
|
||||
+ /* Remove the breadcrumb level. */
|
||||
+ if (p->breadcrumb_len > 0) {
|
||||
+ p->breadcrumb[p->breadcrumb_len - 1][0] = '\0';
|
||||
+ p->breadcrumb_len--;
|
||||
+ }
|
||||
+ nsvg__popAttr(p);
|
||||
}
|
||||
else if (strcmp(el, "path") == 0) {
|
||||
+ /* Remove the breadcrumb level. */
|
||||
+ if (p->breadcrumb_len > 0) {
|
||||
+ p->breadcrumb[p->breadcrumb_len - 1][0] = '\0';
|
||||
+ p->breadcrumb_len--;
|
||||
+ }
|
||||
+
|
||||
nsvg__popAttr(p);
|
||||
} else if (strcmp(el, "path") == 0) {
|
||||
p->pathFlag = 0;
|
||||
} else if (strcmp(el, "defs") == 0) {
|
||||
p->defsFlag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void nsvg__content(void* ud, const char* s)
|
||||
{
|
||||
NSVG_NOTUSED(ud);
|
||||
NSVG_NOTUSED(s);
|
||||
// empty
|
||||
}
|
||||
|
||||
static void nsvg__imageBounds(NSVGparser* p, float* bounds)
|
||||
{
|
||||
NSVGshape* shape;
|
||||
shape = p->image->shapes;
|
||||
if (shape == NULL) {
|
||||
bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0;
|
||||
return;
|
||||
}
|
||||
bounds[0] = shape->bounds[0];
|
||||
bounds[1] = shape->bounds[1];
|
||||
bounds[2] = shape->bounds[2];
|
||||
bounds[3] = shape->bounds[3];
|
||||
for (shape = shape->next; shape != NULL; shape = shape->next) {
|
||||
bounds[0] = nsvg__minf(bounds[0], shape->bounds[0]);
|
||||
bounds[1] = nsvg__minf(bounds[1], shape->bounds[1]);
|
||||
|
|
|
@ -6,7 +6,6 @@ set(INC
|
|||
..
|
||||
../../mikktspace
|
||||
../../../source/blender/makesrna
|
||||
../../../source/blender/blenkernel
|
||||
../../../source/blender/gpu
|
||||
../../../source/blender/render
|
||||
${CMAKE_BINARY_DIR}/source/blender/makesrna/intern
|
||||
|
@ -57,6 +56,7 @@ set(SRC
|
|||
)
|
||||
|
||||
set(LIB
|
||||
PRIVATE bf::blenkernel
|
||||
PRIVATE bf::blenlib
|
||||
PRIVATE bf::dna
|
||||
PRIVATE bf::intern::guardedalloc
|
||||
|
|
|
@ -860,7 +860,7 @@ bool BlenderDisplayDriver::gpu_resources_create()
|
|||
gpu_render_sync_ = GPU_fence_create();
|
||||
|
||||
if (!DCHECK_NOTNULL(gpu_upload_sync_) || !DCHECK_NOTNULL(gpu_render_sync_)) {
|
||||
LOG(ERROR) << "Error creating GPU synchronization primtiives.";
|
||||
LOG(ERROR) << "Error creating GPU synchronization primitives.";
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -157,12 +157,6 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
|
|||
*sampled_roughness = zero_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_REFLECTION_ID:
|
||||
case CLOSURE_BSDF_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_SHARP_GLASS_ID:
|
||||
label = bsdf_microfacet_sharp_sample(
|
||||
sc, path_flag, Ng, sd->wi, rand, eval, wo, pdf, sampled_roughness, eta);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
|
@ -296,9 +290,6 @@ ccl_device_inline void bsdf_roughness_eta(const KernelGlobals kg,
|
|||
*roughness = zero_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_REFLECTION_ID:
|
||||
case CLOSURE_BSDF_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_SHARP_GLASS_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
|
@ -398,9 +389,6 @@ ccl_device_inline int bsdf_label(const KernelGlobals kg,
|
|||
case CLOSURE_BSDF_TRANSPARENT_ID:
|
||||
label = LABEL_TRANSMIT | LABEL_TRANSPARENT;
|
||||
break;
|
||||
case CLOSURE_BSDF_REFLECTION_ID:
|
||||
case CLOSURE_BSDF_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_SHARP_GLASS_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
|
@ -410,7 +398,7 @@ ccl_device_inline int bsdf_label(const KernelGlobals kg,
|
|||
case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID: {
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
label = ((bsdf_is_transmission(sc, wo)) ? LABEL_TRANSMIT : LABEL_REFLECT) |
|
||||
((bsdf->alpha_x * bsdf->alpha_y <= 1e-7f) ? LABEL_SINGULAR : LABEL_GLOSSY);
|
||||
((bsdf_microfacet_eval_flag(bsdf)) ? LABEL_GLOSSY : LABEL_SINGULAR);
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
||||
|
@ -499,11 +487,6 @@ ccl_device_inline
|
|||
case CLOSURE_BSDF_TRANSPARENT_ID:
|
||||
eval = bsdf_transparent_eval(sc, sd->wi, wo, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_REFLECTION_ID:
|
||||
case CLOSURE_BSDF_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_SHARP_GLASS_ID:
|
||||
eval = bsdf_microfacet_sharp_eval(sc, sd->N, sd->wi, wo, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
|
@ -579,13 +562,11 @@ ccl_device void bsdf_blur(KernelGlobals kg, ccl_private ShaderClosure *sc, float
|
|||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
|
||||
/* TODO: Recompute energy preservation after blur? */
|
||||
bsdf_microfacet_ggx_blur(sc, roughness);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID:
|
||||
bsdf_microfacet_beckmann_blur(sc, roughness);
|
||||
/* TODO: Recompute energy preservation after blur? */
|
||||
bsdf_microfacet_blur(sc, roughness);
|
||||
break;
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
||||
bsdf_ashikhmin_shirley_blur(sc, roughness);
|
||||
|
|
|
@ -18,7 +18,6 @@ CCL_NAMESPACE_BEGIN
|
|||
enum MicrofacetType {
|
||||
BECKMANN,
|
||||
GGX,
|
||||
SHARP,
|
||||
};
|
||||
|
||||
enum MicrofacetFresnel {
|
||||
|
@ -444,6 +443,12 @@ ccl_device_inline float bsdf_aniso_D(float alpha_x, float alpha_y, float3 H)
|
|||
}
|
||||
}
|
||||
|
||||
/* Do not set `SD_BSDF_HAS_EVAL` flag if the squared roughness is below a certain threshold. */
|
||||
ccl_device_forceinline int bsdf_microfacet_eval_flag(const ccl_private MicrofacetBsdf *bsdf)
|
||||
{
|
||||
return (bsdf->alpha_x * bsdf->alpha_y > BSDF_ROUGHNESS_SQ_THRESH) ? SD_BSDF_HAS_EVAL : 0;
|
||||
}
|
||||
|
||||
template<MicrofacetType m_type>
|
||||
ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 Ng,
|
||||
|
@ -451,11 +456,6 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc,
|
|||
const float3 wo,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
if (m_type == MicrofacetType::SHARP) {
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
/* Refraction: Only consider BTDF
|
||||
* Glass: Consider both BRDF and BTDF, mix based on Fresnel
|
||||
|
@ -481,7 +481,7 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc,
|
|||
* - Purely reflective closures can't have refraction.
|
||||
* - Purely refractive closures can't have reflection.
|
||||
*/
|
||||
if ((cos_NI <= 0) || (alpha_x * alpha_y <= 5e-7f) || ((cos_NgO < 0.0f) != is_transmission) ||
|
||||
if ((cos_NI <= 0) || !bsdf_microfacet_eval_flag(bsdf) || ((cos_NgO < 0.0f) != is_transmission) ||
|
||||
(is_transmission && m_reflection) || (!is_transmission && m_refraction))
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
|
@ -565,7 +565,7 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
|
|||
const bool m_reflection = !(m_refraction || m_glass);
|
||||
const float alpha_x = bsdf->alpha_x;
|
||||
const float alpha_y = bsdf->alpha_y;
|
||||
bool m_singular = (m_type == MicrofacetType::SHARP) || (alpha_x * alpha_y <= 5e-7f);
|
||||
bool m_singular = !bsdf_microfacet_eval_flag(bsdf);
|
||||
|
||||
const float3 N = bsdf->N;
|
||||
const float cos_NI = dot(N, wi);
|
||||
|
@ -848,7 +848,7 @@ ccl_device int bsdf_microfacet_ggx_setup(ccl_private MicrofacetBsdf *bsdf)
|
|||
bsdf->energy_scale = 1.0f;
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
|
||||
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
return SD_BSDF | bsdf_microfacet_eval_flag(bsdf);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_clearcoat_setup(ccl_private MicrofacetBsdf *bsdf,
|
||||
|
@ -862,7 +862,7 @@ ccl_device int bsdf_microfacet_ggx_clearcoat_setup(ccl_private MicrofacetBsdf *b
|
|||
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID;
|
||||
bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf, true, true));
|
||||
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
return SD_BSDF | bsdf_microfacet_eval_flag(bsdf);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
|
||||
|
@ -874,7 +874,7 @@ ccl_device int bsdf_microfacet_ggx_refraction_setup(ccl_private MicrofacetBsdf *
|
|||
bsdf->energy_scale = 1.0f;
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
|
||||
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_HAS_TRANSMISSION;
|
||||
return SD_BSDF | SD_BSDF_HAS_TRANSMISSION | bsdf_microfacet_eval_flag(bsdf);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_glass_setup(ccl_private MicrofacetBsdf *bsdf)
|
||||
|
@ -886,10 +886,10 @@ ccl_device int bsdf_microfacet_ggx_glass_setup(ccl_private MicrofacetBsdf *bsdf)
|
|||
bsdf->energy_scale = 1.0f;
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
|
||||
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_HAS_TRANSMISSION;
|
||||
return SD_BSDF | SD_BSDF_HAS_TRANSMISSION | bsdf_microfacet_eval_flag(bsdf);
|
||||
}
|
||||
|
||||
ccl_device void bsdf_microfacet_ggx_blur(ccl_private ShaderClosure *sc, float roughness)
|
||||
ccl_device void bsdf_microfacet_blur(ccl_private ShaderClosure *sc, float roughness)
|
||||
{
|
||||
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)sc;
|
||||
|
||||
|
@ -937,7 +937,8 @@ ccl_device int bsdf_microfacet_beckmann_setup(ccl_private MicrofacetBsdf *bsdf)
|
|||
|
||||
bsdf->fresnel_type = MicrofacetFresnel::NONE;
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
|
||||
return SD_BSDF | bsdf_microfacet_eval_flag(bsdf);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_beckmann_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
|
||||
|
@ -947,7 +948,8 @@ ccl_device int bsdf_microfacet_beckmann_refraction_setup(ccl_private MicrofacetB
|
|||
|
||||
bsdf->fresnel_type = MicrofacetFresnel::NONE;
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_HAS_TRANSMISSION;
|
||||
|
||||
return SD_BSDF | SD_BSDF_HAS_TRANSMISSION | bsdf_microfacet_eval_flag(bsdf);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_beckmann_glass_setup(ccl_private MicrofacetBsdf *bsdf)
|
||||
|
@ -957,15 +959,8 @@ ccl_device int bsdf_microfacet_beckmann_glass_setup(ccl_private MicrofacetBsdf *
|
|||
|
||||
bsdf->fresnel_type = MicrofacetFresnel::DIELECTRIC;
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID;
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_HAS_TRANSMISSION;
|
||||
}
|
||||
|
||||
ccl_device void bsdf_microfacet_beckmann_blur(ccl_private ShaderClosure *sc, float roughness)
|
||||
{
|
||||
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)sc;
|
||||
|
||||
bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
|
||||
bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
|
||||
return SD_BSDF | SD_BSDF_HAS_TRANSMISSION | bsdf_microfacet_eval_flag(bsdf);
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_microfacet_beckmann_eval(ccl_private const ShaderClosure *sc,
|
||||
|
@ -992,58 +987,4 @@ ccl_device int bsdf_microfacet_beckmann_sample(ccl_private const ShaderClosure *
|
|||
sc, path_flag, Ng, wi, rand, eval, wo, pdf, sampled_roughness, eta);
|
||||
}
|
||||
|
||||
/* Specular interface, not really a microfacet model but close enough that sharing code makes
|
||||
* sense. */
|
||||
|
||||
ccl_device int bsdf_reflection_setup(ccl_private MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->fresnel_type = MicrofacetFresnel::NONE;
|
||||
bsdf->type = CLOSURE_BSDF_REFLECTION_ID;
|
||||
bsdf->alpha_x = 0.0f;
|
||||
bsdf->alpha_y = 0.0f;
|
||||
return SD_BSDF;
|
||||
}
|
||||
|
||||
ccl_device int bsdf_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->fresnel_type = MicrofacetFresnel::NONE;
|
||||
bsdf->type = CLOSURE_BSDF_REFRACTION_ID;
|
||||
bsdf->alpha_x = 0.0f;
|
||||
bsdf->alpha_y = 0.0f;
|
||||
return SD_BSDF | SD_BSDF_HAS_TRANSMISSION;
|
||||
}
|
||||
|
||||
ccl_device int bsdf_sharp_glass_setup(ccl_private MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->fresnel_type = MicrofacetFresnel::DIELECTRIC;
|
||||
bsdf->type = CLOSURE_BSDF_SHARP_GLASS_ID;
|
||||
bsdf->alpha_x = 0.0f;
|
||||
bsdf->alpha_y = 0.0f;
|
||||
return SD_BSDF | SD_BSDF_HAS_TRANSMISSION;
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_microfacet_sharp_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 Ng,
|
||||
const float3 wi,
|
||||
const float3 wo,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
return bsdf_microfacet_eval<MicrofacetType::SHARP>(sc, Ng, wi, wo, pdf);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_sharp_sample(ccl_private const ShaderClosure *sc,
|
||||
const int path_flag,
|
||||
float3 Ng,
|
||||
float3 wi,
|
||||
const float3 rand,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *wo,
|
||||
ccl_private float *pdf,
|
||||
ccl_private float2 *sampled_roughness,
|
||||
ccl_private float *eta)
|
||||
{
|
||||
return bsdf_microfacet_sample<MicrofacetType::SHARP>(
|
||||
sc, path_flag, Ng, wi, rand, eval, wo, pdf, sampled_roughness, eta);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
@ -224,6 +224,12 @@ ccl_device_inline void surface_shader_prepare_closures(KernelGlobals kg,
|
|||
bsdf_blur(kg, sc, blur_roughness);
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTE: this is a sufficient condition. If `blur_roughness < THRESH < original_roughness`
|
||||
* then the flag was already set. */
|
||||
if (sqr(blur_roughness) > BSDF_ROUGHNESS_SQ_THRESH) {
|
||||
sd->flag |= SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,8 +142,9 @@ ccl_device void osl_closure_reflection_setup(KernelGlobals kg,
|
|||
}
|
||||
|
||||
bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N);
|
||||
bsdf->alpha_x = bsdf->alpha_y = 0.0f;
|
||||
|
||||
sd->flag |= bsdf_reflection_setup(bsdf);
|
||||
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
|
||||
}
|
||||
|
||||
ccl_device void osl_closure_refraction_setup(KernelGlobals kg,
|
||||
|
@ -164,8 +165,9 @@ ccl_device void osl_closure_refraction_setup(KernelGlobals kg,
|
|||
|
||||
bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N);
|
||||
bsdf->ior = closure->ior;
|
||||
bsdf->alpha_x = bsdf->alpha_y = 0.0f;
|
||||
|
||||
sd->flag |= bsdf_refraction_setup(bsdf);
|
||||
sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
|
||||
}
|
||||
|
||||
ccl_device void osl_closure_transparent_setup(KernelGlobals kg,
|
||||
|
@ -397,18 +399,6 @@ ccl_device void osl_closure_microfacet_setup(KernelGlobals kg,
|
|||
sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
|
||||
}
|
||||
}
|
||||
/* Sharp */
|
||||
else if (closure->distribution == make_string("sharp", 1870681295563127462ull)) {
|
||||
if (closure->refract == 1) {
|
||||
sd->flag |= bsdf_refraction_setup(bsdf);
|
||||
}
|
||||
else if (closure->refract == 2) {
|
||||
sd->flag |= bsdf_sharp_glass_setup(bsdf);
|
||||
}
|
||||
else {
|
||||
sd->flag |= bsdf_reflection_setup(bsdf);
|
||||
}
|
||||
}
|
||||
/* Ashikhmin-Shirley */
|
||||
else if (closure->distribution == make_string("ashikhmin_shirley", 11318482998918370922ull)) {
|
||||
sd->flag |= bsdf_ashikhmin_shirley_setup(bsdf);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "stdcycles.h"
|
||||
|
||||
shader node_glass_bsdf(color Color = 0.8,
|
||||
string distribution = "sharp",
|
||||
string distribution = "ggx",
|
||||
float Roughness = 0.2,
|
||||
float IOR = 1.45,
|
||||
normal Normal = N,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "stdcycles.h"
|
||||
|
||||
shader node_refraction_bsdf(color Color = 0.8,
|
||||
string distribution = "sharp",
|
||||
string distribution = "ggx",
|
||||
float Roughness = 0.2,
|
||||
float IOR = 1.45,
|
||||
normal Normal = N,
|
||||
|
|
|
@ -472,7 +472,6 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
bsdf_transparent_setup(sd, weight, path_flag);
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_REFLECTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
||||
|
@ -521,10 +520,9 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
}
|
||||
|
||||
/* setup bsdf */
|
||||
if (type == CLOSURE_BSDF_REFLECTION_ID)
|
||||
sd->flag |= bsdf_reflection_setup(bsdf);
|
||||
else if (type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID)
|
||||
if (type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID) {
|
||||
sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
|
||||
}
|
||||
else if (type == CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID) {
|
||||
sd->flag |= bsdf_ashikhmin_shirley_setup(bsdf);
|
||||
}
|
||||
|
@ -539,7 +537,6 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: {
|
||||
#ifdef __CAUSTICS_TRICKS__
|
||||
|
@ -558,29 +555,21 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
eta = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
|
||||
|
||||
/* setup bsdf */
|
||||
if (type == CLOSURE_BSDF_REFRACTION_ID) {
|
||||
bsdf->alpha_x = 0.0f;
|
||||
bsdf->alpha_y = 0.0f;
|
||||
bsdf->ior = eta;
|
||||
float roughness = sqr(param1);
|
||||
bsdf->alpha_x = roughness;
|
||||
bsdf->alpha_y = roughness;
|
||||
bsdf->ior = eta;
|
||||
|
||||
sd->flag |= bsdf_refraction_setup(bsdf);
|
||||
if (type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) {
|
||||
sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
|
||||
}
|
||||
else {
|
||||
float roughness = sqr(param1);
|
||||
bsdf->alpha_x = roughness;
|
||||
bsdf->alpha_y = roughness;
|
||||
bsdf->ior = eta;
|
||||
|
||||
if (type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID)
|
||||
sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
|
||||
else
|
||||
sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
|
||||
sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_SHARP_GLASS_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID: {
|
||||
|
@ -602,28 +591,20 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
eta = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
|
||||
|
||||
/* setup bsdf */
|
||||
if (type == CLOSURE_BSDF_SHARP_GLASS_ID) {
|
||||
bsdf->alpha_x = 0.0f;
|
||||
bsdf->alpha_y = 0.0f;
|
||||
bsdf->ior = eta;
|
||||
float roughness = sqr(param1);
|
||||
bsdf->alpha_x = roughness;
|
||||
bsdf->alpha_y = roughness;
|
||||
bsdf->ior = eta;
|
||||
|
||||
sd->flag |= bsdf_sharp_glass_setup(bsdf);
|
||||
if (type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID) {
|
||||
sd->flag |= bsdf_microfacet_beckmann_glass_setup(bsdf);
|
||||
}
|
||||
else {
|
||||
float roughness = sqr(param1);
|
||||
bsdf->alpha_x = roughness;
|
||||
bsdf->alpha_y = roughness;
|
||||
bsdf->ior = eta;
|
||||
|
||||
if (type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID)
|
||||
sd->flag |= bsdf_microfacet_beckmann_glass_setup(bsdf);
|
||||
else {
|
||||
sd->flag |= bsdf_microfacet_ggx_glass_setup(bsdf);
|
||||
if (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) {
|
||||
kernel_assert(stack_valid(data_node.z));
|
||||
const Spectrum color = rgb_to_spectrum(stack_load_float3(stack, data_node.z));
|
||||
bsdf_microfacet_setup_fresnel_constant(kg, bsdf, sd, color);
|
||||
}
|
||||
sd->flag |= bsdf_microfacet_ggx_glass_setup(bsdf);
|
||||
if (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) {
|
||||
kernel_assert(stack_valid(data_node.z));
|
||||
const Spectrum color = rgb_to_spectrum(stack_load_float3(stack, data_node.z));
|
||||
bsdf_microfacet_setup_fresnel_constant(kg, bsdf, sd, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -420,7 +420,6 @@ typedef enum ClosureType {
|
|||
CLOSURE_BSDF_TRANSLUCENT_ID,
|
||||
|
||||
/* Glossy */
|
||||
CLOSURE_BSDF_REFLECTION_ID,
|
||||
CLOSURE_BSDF_MICROFACET_GGX_ID,
|
||||
CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID,
|
||||
CLOSURE_BSDF_MICROFACET_BECKMANN_ID,
|
||||
|
@ -432,14 +431,12 @@ typedef enum ClosureType {
|
|||
CLOSURE_BSDF_HAIR_REFLECTION_ID,
|
||||
|
||||
/* Transmission */
|
||||
CLOSURE_BSDF_REFRACTION_ID,
|
||||
CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID,
|
||||
CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID,
|
||||
CLOSURE_BSDF_HAIR_PRINCIPLED_ID,
|
||||
CLOSURE_BSDF_HAIR_TRANSMISSION_ID,
|
||||
|
||||
/* Glass */
|
||||
CLOSURE_BSDF_SHARP_GLASS_ID,
|
||||
CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID,
|
||||
CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID,
|
||||
CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID, /* virtual closure */
|
||||
|
@ -470,21 +467,22 @@ typedef enum ClosureType {
|
|||
#define CLOSURE_IS_BSDF_DIFFUSE(type) \
|
||||
(type >= CLOSURE_BSDF_DIFFUSE_ID && type <= CLOSURE_BSDF_TRANSLUCENT_ID)
|
||||
#define CLOSURE_IS_BSDF_GLOSSY(type) \
|
||||
((type >= CLOSURE_BSDF_REFLECTION_ID && type <= CLOSURE_BSDF_HAIR_REFLECTION_ID) || \
|
||||
((type >= CLOSURE_BSDF_MICROFACET_GGX_ID && type <= CLOSURE_BSDF_HAIR_REFLECTION_ID) || \
|
||||
(type == CLOSURE_BSDF_HAIR_PRINCIPLED_ID))
|
||||
#define CLOSURE_IS_BSDF_TRANSMISSION(type) \
|
||||
(type >= CLOSURE_BSDF_REFRACTION_ID && type <= CLOSURE_BSDF_HAIR_TRANSMISSION_ID)
|
||||
#define CLOSURE_IS_BSDF_SINGULAR(type) \
|
||||
(type == CLOSURE_BSDF_REFLECTION_ID || type == CLOSURE_BSDF_REFRACTION_ID || \
|
||||
type == CLOSURE_BSDF_TRANSPARENT_ID || type == CLOSURE_BSDF_SHARP_GLASS_ID)
|
||||
(type >= CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID && \
|
||||
type <= CLOSURE_BSDF_HAIR_TRANSMISSION_ID)
|
||||
#define CLOSURE_IS_BSDF_SINGULAR(type) (type == CLOSURE_BSDF_TRANSPARENT_ID)
|
||||
#define CLOSURE_IS_BSDF_TRANSPARENT(type) (type == CLOSURE_BSDF_TRANSPARENT_ID)
|
||||
#define CLOSURE_IS_BSDF_MULTISCATTER(type) \
|
||||
(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID || \
|
||||
type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
|
||||
#define CLOSURE_IS_BSDF_MICROFACET(type) \
|
||||
((type >= CLOSURE_BSDF_REFLECTION_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID) || \
|
||||
(type >= CLOSURE_BSDF_REFRACTION_ID && type <= CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID) || \
|
||||
(type >= CLOSURE_BSDF_SHARP_GLASS_ID && type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID))
|
||||
((type >= CLOSURE_BSDF_MICROFACET_GGX_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID) || \
|
||||
(type >= CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID && \
|
||||
type <= CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID) || \
|
||||
(type >= CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID && \
|
||||
type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID))
|
||||
#define CLOSURE_IS_BSDF_OR_BSSRDF(type) (type <= CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID)
|
||||
#define CLOSURE_IS_BSSRDF(type) \
|
||||
(type >= CLOSURE_BSSRDF_BURLEY_ID && type <= CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID)
|
||||
|
@ -495,11 +493,15 @@ typedef enum ClosureType {
|
|||
#define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID)
|
||||
#define CLOSURE_IS_PHASE(type) (type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
|
||||
#define CLOSURE_IS_REFRACTION(type) \
|
||||
(type >= CLOSURE_BSDF_REFRACTION_ID && type <= CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID)
|
||||
(type >= CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID && \
|
||||
type <= CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID)
|
||||
#define CLOSURE_IS_GLASS(type) \
|
||||
(type >= CLOSURE_BSDF_SHARP_GLASS_ID && type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
|
||||
(type >= CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID && \
|
||||
type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
|
||||
#define CLOSURE_IS_PRINCIPLED(type) (type == CLOSURE_BSDF_PRINCIPLED_ID)
|
||||
|
||||
#define CLOSURE_WEIGHT_CUTOFF 1e-5f
|
||||
/* Treat closure as singular if the squared roughness is below this threshold. */
|
||||
#define BSDF_ROUGHNESS_SQ_THRESH 5e-7f
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
@ -324,15 +324,6 @@ void Integrator::tag_update(Scene *scene, uint32_t flag)
|
|||
tag_ao_bounces_modified();
|
||||
}
|
||||
|
||||
if (filter_glossy_is_modified()) {
|
||||
foreach (Shader *shader, scene->shaders) {
|
||||
if (shader->has_integrator_dependency) {
|
||||
scene->shader_manager->tag_update(scene, ShaderManager::INTEGRATOR_MODIFIED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (motion_blur_is_modified()) {
|
||||
scene->object_manager->tag_update(scene, ObjectManager::MOTION_BLUR_MODIFIED);
|
||||
scene->camera->tag_modified();
|
||||
|
|
|
@ -1253,7 +1253,9 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
|
|||
klights[light_index].distant.eval_fac = (light->normalize && angle > 0) ?
|
||||
M_1_PI_F / sqr(sinf(angle)) :
|
||||
1.0f;
|
||||
klights[light_index].distant.half_inv_sin_half_angle = 0.5f / sinf(0.5f * angle);
|
||||
klights[light_index].distant.half_inv_sin_half_angle = (angle == 0.0f) ?
|
||||
0.0f :
|
||||
0.5f / sinf(0.5f * angle);
|
||||
}
|
||||
else if (light->light_type == LIGHT_BACKGROUND) {
|
||||
uint visibility = scene->background->get_visibility();
|
||||
|
|
|
@ -895,10 +895,6 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
|
|||
if (node->has_attribute_dependency())
|
||||
current_shader->has_volume_attribute_dependency = true;
|
||||
}
|
||||
|
||||
if (node->has_integrator_dependency()) {
|
||||
current_shader->has_integrator_dependency = true;
|
||||
}
|
||||
}
|
||||
|
||||
static TypeDesc array_typedesc(TypeDesc typedesc, int arraylength)
|
||||
|
@ -1259,10 +1255,7 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
|
|||
output->input("Surface")->link && output->input("Displacement")->link;
|
||||
|
||||
/* finalize */
|
||||
shader->graph->finalize(scene,
|
||||
has_bump,
|
||||
shader->has_integrator_dependency,
|
||||
shader->get_displacement_method() == DISPLACE_BOTH);
|
||||
shader->graph->finalize(scene, has_bump, shader->get_displacement_method() == DISPLACE_BOTH);
|
||||
|
||||
current_shader = shader;
|
||||
|
||||
|
@ -1277,7 +1270,6 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
|
|||
shader->has_surface_spatial_varying = false;
|
||||
shader->has_volume_spatial_varying = false;
|
||||
shader->has_volume_attribute_dependency = false;
|
||||
shader->has_integrator_dependency = false;
|
||||
|
||||
/* generate surface shader */
|
||||
if (shader->reference_count() && graph && output->input("Surface")->link) {
|
||||
|
|
|
@ -103,7 +103,6 @@ Shader::Shader() : Node(get_node_type())
|
|||
has_surface_spatial_varying = false;
|
||||
has_volume_spatial_varying = false;
|
||||
has_volume_attribute_dependency = false;
|
||||
has_integrator_dependency = false;
|
||||
has_volume_connected = false;
|
||||
prev_volume_step_rate = 0.0f;
|
||||
|
||||
|
|
|
@ -113,7 +113,6 @@ class Shader : public Node {
|
|||
bool has_surface_spatial_varying;
|
||||
bool has_volume_spatial_varying;
|
||||
bool has_volume_attribute_dependency;
|
||||
bool has_integrator_dependency;
|
||||
|
||||
float3 emission_estimate;
|
||||
EmissionSampling emission_sampling;
|
||||
|
@ -168,7 +167,6 @@ class ShaderManager {
|
|||
enum : uint32_t {
|
||||
SHADER_ADDED = (1 << 0),
|
||||
SHADER_MODIFIED = (1 << 2),
|
||||
INTEGRATOR_MODIFIED = (1 << 3),
|
||||
|
||||
/* tag everything in the manager for an update */
|
||||
UPDATE_ALL = ~0u,
|
||||
|
|
|
@ -359,7 +359,7 @@ void ShaderGraph::simplify(Scene *scene)
|
|||
}
|
||||
}
|
||||
|
||||
void ShaderGraph::finalize(Scene *scene, bool do_bump, bool do_simplify, bool bump_in_object_space)
|
||||
void ShaderGraph::finalize(Scene *scene, bool do_bump, bool bump_in_object_space)
|
||||
{
|
||||
/* before compiling, the shader graph may undergo a number of modifications.
|
||||
* currently we set default geometry shader inputs, and create automatic bump
|
||||
|
@ -384,9 +384,6 @@ void ShaderGraph::finalize(Scene *scene, bool do_bump, bool do_simplify, bool bu
|
|||
|
||||
finalized = true;
|
||||
}
|
||||
else if (do_simplify) {
|
||||
simplify_settings(scene);
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderGraph::find_dependencies(ShaderNodeSet &dependencies, ShaderInput *input)
|
||||
|
|
|
@ -200,10 +200,6 @@ class ShaderNode : public Node {
|
|||
{
|
||||
return false;
|
||||
}
|
||||
virtual bool has_integrator_dependency()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual bool has_volume_support()
|
||||
{
|
||||
return false;
|
||||
|
@ -315,10 +311,7 @@ class ShaderGraph : public NodeOwner {
|
|||
void remove_proxy_nodes();
|
||||
void compute_displacement_hash();
|
||||
void simplify(Scene *scene);
|
||||
void finalize(Scene *scene,
|
||||
bool do_bump = false,
|
||||
bool do_simplify = false,
|
||||
bool bump_in_object_space = false);
|
||||
void finalize(Scene *scene, bool do_bump = false, bool bump_in_object_space = false);
|
||||
|
||||
int get_num_closures();
|
||||
|
||||
|
|
|
@ -2361,7 +2361,6 @@ NODE_DEFINE(GlossyBsdfNode)
|
|||
SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
|
||||
|
||||
static NodeEnum distribution_enum;
|
||||
distribution_enum.insert("sharp", CLOSURE_BSDF_REFLECTION_ID);
|
||||
distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
|
||||
distribution_enum.insert("ggx", CLOSURE_BSDF_MICROFACET_GGX_ID);
|
||||
distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
|
||||
|
@ -2382,7 +2381,6 @@ NODE_DEFINE(GlossyBsdfNode)
|
|||
GlossyBsdfNode::GlossyBsdfNode() : BsdfNode(get_node_type())
|
||||
{
|
||||
closure = CLOSURE_BSDF_MICROFACET_GGX_ID;
|
||||
distribution_orig = NBUILTIN_CLOSURES;
|
||||
}
|
||||
|
||||
bool GlossyBsdfNode::is_isotropic()
|
||||
|
@ -2403,68 +2401,27 @@ void GlossyBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
|
|||
ShaderNode::attributes(shader, attributes);
|
||||
}
|
||||
|
||||
void GlossyBsdfNode::simplify_settings(Scene *scene)
|
||||
void GlossyBsdfNode::simplify_settings(Scene * /* scene */)
|
||||
{
|
||||
/* If the anisotropy is close enough to zero, fall back to the isotropic case. */
|
||||
ShaderInput *tangent_input = input("Tangent");
|
||||
if (tangent_input->link && is_isotropic()) {
|
||||
tangent_input->disconnect();
|
||||
}
|
||||
|
||||
if (distribution_orig == NBUILTIN_CLOSURES) {
|
||||
roughness_orig = roughness;
|
||||
distribution_orig = distribution;
|
||||
}
|
||||
else {
|
||||
/* By default we use original values, so we don't worry about restoring
|
||||
* defaults later one and can only do override when needed.
|
||||
*/
|
||||
roughness = roughness_orig;
|
||||
distribution = distribution_orig;
|
||||
}
|
||||
Integrator *integrator = scene->integrator;
|
||||
ShaderInput *roughness_input = input("Roughness");
|
||||
if (integrator->get_filter_glossy() == 0.0f) {
|
||||
/* Fallback to Sharp closure for Roughness close to 0.
|
||||
* NOTE: Keep the epsilon in sync with kernel!
|
||||
*/
|
||||
if (!roughness_input->link && roughness <= 1e-4f) {
|
||||
VLOG_DEBUG << "Using sharp glossy BSDF.";
|
||||
distribution = CLOSURE_BSDF_REFLECTION_ID;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* If filter glossy is used we replace Sharp glossy with GGX so we can
|
||||
* benefit from closure blur to remove unwanted noise.
|
||||
*/
|
||||
if (roughness_input->link == NULL && distribution == CLOSURE_BSDF_REFLECTION_ID) {
|
||||
VLOG_DEBUG << "Using GGX glossy with filter glossy.";
|
||||
distribution = CLOSURE_BSDF_MICROFACET_GGX_ID;
|
||||
roughness = 0.0f;
|
||||
}
|
||||
}
|
||||
closure = distribution;
|
||||
}
|
||||
|
||||
bool GlossyBsdfNode::has_integrator_dependency()
|
||||
{
|
||||
ShaderInput *roughness_input = input("Roughness");
|
||||
return !roughness_input->link &&
|
||||
(distribution == CLOSURE_BSDF_REFLECTION_ID || roughness <= 1e-4f);
|
||||
}
|
||||
|
||||
void GlossyBsdfNode::compile(SVMCompiler &compiler)
|
||||
{
|
||||
closure = distribution;
|
||||
|
||||
if (closure == CLOSURE_BSDF_REFLECTION_ID)
|
||||
BsdfNode::compile(compiler, NULL, NULL);
|
||||
/* TODO: Just use weight for legacy MultiGGX? Would also simplify OSL. */
|
||||
else if (closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID)
|
||||
if (closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID) {
|
||||
BsdfNode::compile(
|
||||
compiler, input("Roughness"), input("Anisotropy"), input("Rotation"), input("Color"));
|
||||
else
|
||||
}
|
||||
else {
|
||||
BsdfNode::compile(compiler, input("Roughness"), input("Anisotropy"), input("Rotation"));
|
||||
}
|
||||
}
|
||||
|
||||
void GlossyBsdfNode::compile(OSLCompiler &compiler)
|
||||
|
@ -2484,7 +2441,6 @@ NODE_DEFINE(GlassBsdfNode)
|
|||
SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
|
||||
|
||||
static NodeEnum distribution_enum;
|
||||
distribution_enum.insert("sharp", CLOSURE_BSDF_SHARP_GLASS_ID);
|
||||
distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID);
|
||||
distribution_enum.insert("ggx", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
|
||||
distribution_enum.insert("multi_ggx", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
|
||||
|
@ -2500,64 +2456,19 @@ NODE_DEFINE(GlassBsdfNode)
|
|||
|
||||
GlassBsdfNode::GlassBsdfNode() : BsdfNode(get_node_type())
|
||||
{
|
||||
closure = CLOSURE_BSDF_SHARP_GLASS_ID;
|
||||
distribution_orig = NBUILTIN_CLOSURES;
|
||||
}
|
||||
|
||||
void GlassBsdfNode::simplify_settings(Scene *scene)
|
||||
{
|
||||
if (distribution_orig == NBUILTIN_CLOSURES) {
|
||||
roughness_orig = roughness;
|
||||
distribution_orig = distribution;
|
||||
}
|
||||
else {
|
||||
/* By default we use original values, so we don't worry about restoring
|
||||
* defaults later one and can only do override when needed.
|
||||
*/
|
||||
roughness = roughness_orig;
|
||||
distribution = distribution_orig;
|
||||
}
|
||||
Integrator *integrator = scene->integrator;
|
||||
ShaderInput *roughness_input = input("Roughness");
|
||||
if (integrator->get_filter_glossy() == 0.0f) {
|
||||
/* Fallback to Sharp closure for Roughness close to 0.
|
||||
* NOTE: Keep the epsilon in sync with kernel!
|
||||
*/
|
||||
if (!roughness_input->link && roughness <= 1e-4f) {
|
||||
VLOG_DEBUG << "Using sharp glass BSDF.";
|
||||
distribution = CLOSURE_BSDF_SHARP_GLASS_ID;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* If filter glossy is used we replace Sharp glossy with GGX so we can
|
||||
* benefit from closure blur to remove unwanted noise.
|
||||
*/
|
||||
if (roughness_input->link == NULL && distribution == CLOSURE_BSDF_SHARP_GLASS_ID) {
|
||||
VLOG_DEBUG << "Using GGX glass with filter glossy.";
|
||||
distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
|
||||
roughness = 0.0f;
|
||||
}
|
||||
}
|
||||
closure = distribution;
|
||||
}
|
||||
|
||||
bool GlassBsdfNode::has_integrator_dependency()
|
||||
{
|
||||
ShaderInput *roughness_input = input("Roughness");
|
||||
return !roughness_input->link &&
|
||||
(distribution == CLOSURE_BSDF_SHARP_GLASS_ID || roughness <= 1e-4f);
|
||||
closure = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
|
||||
}
|
||||
|
||||
void GlassBsdfNode::compile(SVMCompiler &compiler)
|
||||
{
|
||||
closure = distribution;
|
||||
|
||||
if (closure == CLOSURE_BSDF_SHARP_GLASS_ID)
|
||||
BsdfNode::compile(compiler, NULL, input("IOR"));
|
||||
else if (closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
|
||||
if (closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) {
|
||||
BsdfNode::compile(compiler, input("Roughness"), input("IOR"), input("Color"));
|
||||
else
|
||||
}
|
||||
else {
|
||||
BsdfNode::compile(compiler, input("Roughness"), input("IOR"));
|
||||
}
|
||||
}
|
||||
|
||||
void GlassBsdfNode::compile(OSLCompiler &compiler)
|
||||
|
@ -2577,7 +2488,6 @@ NODE_DEFINE(RefractionBsdfNode)
|
|||
SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
|
||||
|
||||
static NodeEnum distribution_enum;
|
||||
distribution_enum.insert("sharp", CLOSURE_BSDF_REFRACTION_ID);
|
||||
distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID);
|
||||
distribution_enum.insert("ggx", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
|
||||
SOCKET_ENUM(
|
||||
|
@ -2593,62 +2503,14 @@ NODE_DEFINE(RefractionBsdfNode)
|
|||
|
||||
RefractionBsdfNode::RefractionBsdfNode() : BsdfNode(get_node_type())
|
||||
{
|
||||
closure = CLOSURE_BSDF_REFRACTION_ID;
|
||||
distribution_orig = NBUILTIN_CLOSURES;
|
||||
}
|
||||
|
||||
void RefractionBsdfNode::simplify_settings(Scene *scene)
|
||||
{
|
||||
if (distribution_orig == NBUILTIN_CLOSURES) {
|
||||
roughness_orig = roughness;
|
||||
distribution_orig = distribution;
|
||||
}
|
||||
else {
|
||||
/* By default we use original values, so we don't worry about restoring
|
||||
* defaults later one and can only do override when needed.
|
||||
*/
|
||||
roughness = roughness_orig;
|
||||
distribution = distribution_orig;
|
||||
}
|
||||
Integrator *integrator = scene->integrator;
|
||||
ShaderInput *roughness_input = input("Roughness");
|
||||
if (integrator->get_filter_glossy() == 0.0f) {
|
||||
/* Fallback to Sharp closure for Roughness close to 0.
|
||||
* NOTE: Keep the epsilon in sync with kernel!
|
||||
*/
|
||||
if (!roughness_input->link && roughness <= 1e-4f) {
|
||||
VLOG_DEBUG << "Using sharp refraction BSDF.";
|
||||
distribution = CLOSURE_BSDF_REFRACTION_ID;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* If filter glossy is used we replace Sharp glossy with GGX so we can
|
||||
* benefit from closure blur to remove unwanted noise.
|
||||
*/
|
||||
if (roughness_input->link == NULL && distribution == CLOSURE_BSDF_REFRACTION_ID) {
|
||||
VLOG_DEBUG << "Using GGX refraction with filter glossy.";
|
||||
distribution = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
|
||||
roughness = 0.0f;
|
||||
}
|
||||
}
|
||||
closure = distribution;
|
||||
}
|
||||
|
||||
bool RefractionBsdfNode::has_integrator_dependency()
|
||||
{
|
||||
ShaderInput *roughness_input = input("Roughness");
|
||||
return !roughness_input->link &&
|
||||
(distribution == CLOSURE_BSDF_REFRACTION_ID || roughness <= 1e-4f);
|
||||
closure = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
|
||||
}
|
||||
|
||||
void RefractionBsdfNode::compile(SVMCompiler &compiler)
|
||||
{
|
||||
closure = distribution;
|
||||
|
||||
if (closure == CLOSURE_BSDF_REFRACTION_ID)
|
||||
BsdfNode::compile(compiler, NULL, input("IOR"));
|
||||
else
|
||||
BsdfNode::compile(compiler, input("Roughness"), input("IOR"));
|
||||
BsdfNode::compile(compiler, input("Roughness"), input("IOR"));
|
||||
}
|
||||
|
||||
void RefractionBsdfNode::compile(OSLCompiler &compiler)
|
||||
|
@ -2816,7 +2678,6 @@ PrincipledBsdfNode::PrincipledBsdfNode() : BsdfBaseNode(get_node_type())
|
|||
{
|
||||
closure = CLOSURE_BSDF_PRINCIPLED_ID;
|
||||
distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
|
||||
distribution_orig = NBUILTIN_CLOSURES;
|
||||
}
|
||||
|
||||
void PrincipledBsdfNode::expand(ShaderGraph *graph)
|
||||
|
@ -2987,12 +2848,6 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler,
|
|||
__float_as_int(ss_default.z));
|
||||
}
|
||||
|
||||
bool PrincipledBsdfNode::has_integrator_dependency()
|
||||
{
|
||||
ShaderInput *roughness_input = input("Roughness");
|
||||
return !roughness_input->link && roughness <= 1e-4f;
|
||||
}
|
||||
|
||||
void PrincipledBsdfNode::compile(SVMCompiler &compiler)
|
||||
{
|
||||
compile(compiler,
|
||||
|
|
|
@ -563,11 +563,7 @@ class PrincipledBsdfNode : public BsdfBaseNode {
|
|||
NODE_SOCKET_API(float, emission_strength)
|
||||
NODE_SOCKET_API(float, alpha)
|
||||
|
||||
private:
|
||||
ClosureType distribution_orig;
|
||||
|
||||
public:
|
||||
bool has_integrator_dependency();
|
||||
void attributes(Shader *shader, AttributeRequestSet *attributes);
|
||||
bool has_attribute_dependency()
|
||||
{
|
||||
|
@ -602,7 +598,6 @@ class GlossyBsdfNode : public BsdfNode {
|
|||
SHADER_NODE_CLASS(GlossyBsdfNode)
|
||||
|
||||
void simplify_settings(Scene *scene);
|
||||
bool has_integrator_dependency();
|
||||
ClosureType get_closure_type()
|
||||
{
|
||||
return distribution;
|
||||
|
@ -620,10 +615,6 @@ class GlossyBsdfNode : public BsdfNode {
|
|||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
float roughness_orig;
|
||||
ClosureType distribution_orig;
|
||||
|
||||
bool is_isotropic();
|
||||
};
|
||||
|
||||
|
@ -631,8 +622,6 @@ class GlassBsdfNode : public BsdfNode {
|
|||
public:
|
||||
SHADER_NODE_CLASS(GlassBsdfNode)
|
||||
|
||||
void simplify_settings(Scene *scene);
|
||||
bool has_integrator_dependency();
|
||||
ClosureType get_closure_type()
|
||||
{
|
||||
return distribution;
|
||||
|
@ -641,18 +630,12 @@ class GlassBsdfNode : public BsdfNode {
|
|||
NODE_SOCKET_API(float, roughness)
|
||||
NODE_SOCKET_API(float, IOR)
|
||||
NODE_SOCKET_API(ClosureType, distribution)
|
||||
|
||||
private:
|
||||
float roughness_orig;
|
||||
ClosureType distribution_orig;
|
||||
};
|
||||
|
||||
class RefractionBsdfNode : public BsdfNode {
|
||||
public:
|
||||
SHADER_NODE_CLASS(RefractionBsdfNode)
|
||||
|
||||
void simplify_settings(Scene *scene);
|
||||
bool has_integrator_dependency();
|
||||
ClosureType get_closure_type()
|
||||
{
|
||||
return distribution;
|
||||
|
@ -661,10 +644,6 @@ class RefractionBsdfNode : public BsdfNode {
|
|||
NODE_SOCKET_API(float, roughness)
|
||||
NODE_SOCKET_API(float, IOR)
|
||||
NODE_SOCKET_API(ClosureType, distribution)
|
||||
|
||||
private:
|
||||
float roughness_orig;
|
||||
ClosureType distribution_orig;
|
||||
};
|
||||
|
||||
class ToonBsdfNode : public BsdfNode {
|
||||
|
|
|
@ -442,10 +442,6 @@ void SVMCompiler::generate_node(ShaderNode *node, ShaderNodeSet &done)
|
|||
if (node->has_attribute_dependency())
|
||||
current_shader->has_volume_attribute_dependency = true;
|
||||
}
|
||||
|
||||
if (node->has_integrator_dependency()) {
|
||||
current_shader->has_integrator_dependency = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SVMCompiler::generate_svm_nodes(const ShaderNodeSet &nodes, CompilerState *state)
|
||||
|
@ -858,10 +854,7 @@ void SVMCompiler::compile(Shader *shader, array<int4> &svm_nodes, int index, Sum
|
|||
/* finalize */
|
||||
{
|
||||
scoped_timer timer((summary != NULL) ? &summary->time_finalize : NULL);
|
||||
shader->graph->finalize(scene,
|
||||
has_bump,
|
||||
shader->has_integrator_dependency,
|
||||
shader->get_displacement_method() == DISPLACE_BOTH);
|
||||
shader->graph->finalize(scene, has_bump, shader->get_displacement_method() == DISPLACE_BOTH);
|
||||
}
|
||||
|
||||
current_shader = shader;
|
||||
|
@ -877,7 +870,6 @@ void SVMCompiler::compile(Shader *shader, array<int4> &svm_nodes, int index, Sum
|
|||
shader->has_surface_spatial_varying = false;
|
||||
shader->has_volume_spatial_varying = false;
|
||||
shader->has_volume_attribute_dependency = false;
|
||||
shader->has_integrator_dependency = false;
|
||||
|
||||
/* generate bump shader */
|
||||
if (has_bump) {
|
||||
|
|
|
@ -77,7 +77,7 @@ static GHOST_TButton convertButton(int button)
|
|||
* \param recvChar: the character ignoring modifiers (except for shift)
|
||||
* \return Ghost key code
|
||||
*/
|
||||
static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
|
||||
static GHOST_TKey convertKey(int rawCode, unichar recvChar)
|
||||
{
|
||||
// printf("\nrecvchar %c 0x%x",recvChar,recvChar);
|
||||
switch (rawCode) {
|
||||
|
@ -238,7 +238,10 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
|
|||
return GHOST_kKeyUpPage;
|
||||
case kVK_PageDown:
|
||||
return GHOST_kKeyDownPage;
|
||||
#if 0 /* TODO: why are these commented? */
|
||||
#if 0
|
||||
/* These constants with "ANSI" in the name are labeled according to the key position on an
|
||||
* ANSI-standard US keyboard. Therefore they may not match the physical key label on other
|
||||
* keyboard layouts. */
|
||||
case kVK_ANSI_Minus: return GHOST_kKeyMinus;
|
||||
case kVK_ANSI_Equal: return GHOST_kKeyEqual;
|
||||
case kVK_ANSI_Comma: return GHOST_kKeyComma;
|
||||
|
@ -284,10 +287,10 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
|
|||
|
||||
UCKeyTranslate((UCKeyboardLayout *)CFDataGetBytePtr(uchrHandle),
|
||||
rawCode,
|
||||
keyAction,
|
||||
kUCKeyActionDown,
|
||||
0,
|
||||
LMGetKbdType(),
|
||||
kUCKeyTranslateNoDeadKeysBit,
|
||||
kUCKeyTranslateNoDeadKeysMask,
|
||||
&deadKeyState,
|
||||
1,
|
||||
&actualStrLength,
|
||||
|
@ -1830,18 +1833,13 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
|
|||
|
||||
case NSEventTypeKeyDown:
|
||||
case NSEventTypeKeyUp:
|
||||
/* Returns an empty string for dead keys. */
|
||||
charsIgnoringModifiers = [event charactersIgnoringModifiers];
|
||||
if ([charsIgnoringModifiers length] > 0) {
|
||||
keyCode = convertKey([event keyCode],
|
||||
[charsIgnoringModifiers characterAtIndex:0],
|
||||
[event type] == NSEventTypeKeyDown ? kUCKeyActionDown :
|
||||
kUCKeyActionUp);
|
||||
keyCode = convertKey([event keyCode], [charsIgnoringModifiers characterAtIndex:0]);
|
||||
}
|
||||
else {
|
||||
keyCode = convertKey([event keyCode],
|
||||
0,
|
||||
[event type] == NSEventTypeKeyDown ? kUCKeyActionDown :
|
||||
kUCKeyActionUp);
|
||||
keyCode = convertKey([event keyCode], 0);
|
||||
}
|
||||
|
||||
characters = [event characters];
|
||||
|
|
|
@ -464,24 +464,27 @@ GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(int32_t x, int32_t y)
|
|||
|
||||
GHOST_TSuccess GHOST_SystemWin32::getModifierKeys(GHOST_ModifierKeys &keys) const
|
||||
{
|
||||
bool down = HIBYTE(::GetKeyState(VK_LSHIFT)) != 0;
|
||||
/* `GetAsyncKeyState` returns the current interrupt-level state of the hardware, which is needed
|
||||
* when passing key states to a newly-activated window - #40059. Alterative `GetKeyState` only
|
||||
* returns the state as processed by the thread's message queue. */
|
||||
bool down = HIBYTE(::GetAsyncKeyState(VK_LSHIFT)) != 0;
|
||||
keys.set(GHOST_kModifierKeyLeftShift, down);
|
||||
down = HIBYTE(::GetKeyState(VK_RSHIFT)) != 0;
|
||||
down = HIBYTE(::GetAsyncKeyState(VK_RSHIFT)) != 0;
|
||||
keys.set(GHOST_kModifierKeyRightShift, down);
|
||||
|
||||
down = HIBYTE(::GetKeyState(VK_LMENU)) != 0;
|
||||
down = HIBYTE(::GetAsyncKeyState(VK_LMENU)) != 0;
|
||||
keys.set(GHOST_kModifierKeyLeftAlt, down);
|
||||
down = HIBYTE(::GetKeyState(VK_RMENU)) != 0;
|
||||
down = HIBYTE(::GetAsyncKeyState(VK_RMENU)) != 0;
|
||||
keys.set(GHOST_kModifierKeyRightAlt, down);
|
||||
|
||||
down = HIBYTE(::GetKeyState(VK_LCONTROL)) != 0;
|
||||
down = HIBYTE(::GetAsyncKeyState(VK_LCONTROL)) != 0;
|
||||
keys.set(GHOST_kModifierKeyLeftControl, down);
|
||||
down = HIBYTE(::GetKeyState(VK_RCONTROL)) != 0;
|
||||
down = HIBYTE(::GetAsyncKeyState(VK_RCONTROL)) != 0;
|
||||
keys.set(GHOST_kModifierKeyRightControl, down);
|
||||
|
||||
down = HIBYTE(::GetKeyState(VK_LWIN)) != 0;
|
||||
down = HIBYTE(::GetAsyncKeyState(VK_LWIN)) != 0;
|
||||
keys.set(GHOST_kModifierKeyLeftOS, down);
|
||||
down = HIBYTE(::GetKeyState(VK_RWIN)) != 0;
|
||||
down = HIBYTE(::GetAsyncKeyState(VK_RWIN)) != 0;
|
||||
keys.set(GHOST_kModifierKeyRightOS, down);
|
||||
|
||||
return GHOST_kSuccess;
|
||||
|
@ -1207,16 +1210,11 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RA
|
|||
bool is_repeat = false;
|
||||
bool is_repeated_modifier = false;
|
||||
if (key_down) {
|
||||
if (system->m_keycode_last_repeat_key == vk) {
|
||||
if (HIBYTE(::GetKeyState(vk)) != 0) {
|
||||
/* This thread's message queue shows this key as already down. */
|
||||
is_repeat = true;
|
||||
is_repeated_modifier = GHOST_KEY_MODIFIER_CHECK(key);
|
||||
}
|
||||
system->m_keycode_last_repeat_key = vk;
|
||||
}
|
||||
else {
|
||||
if (system->m_keycode_last_repeat_key == vk) {
|
||||
system->m_keycode_last_repeat_key = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* We used to check `if (key != GHOST_kKeyUnknown)`, but since the message
|
||||
|
@ -1890,8 +1888,14 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, uint msg, WPARAM wParam,
|
|||
else if (!new_parent && !old_parent) {
|
||||
/* Between main windows that don't overlap. */
|
||||
RECT new_rect, old_rect, dest_rect;
|
||||
::GetWindowRect(hwnd, &new_rect);
|
||||
::GetWindowRect(old_hwnd, &old_rect);
|
||||
|
||||
/* The rects without the outside shadows and slightly inset. */
|
||||
DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &new_rect, sizeof(RECT));
|
||||
::InflateRect(&new_rect, -1, -1);
|
||||
DwmGetWindowAttribute(
|
||||
old_hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &old_rect, sizeof(RECT));
|
||||
::InflateRect(&old_rect, -1, -1);
|
||||
|
||||
if (!IntersectRect(&dest_rect, &new_rect, &old_rect)) {
|
||||
::SetFocus(hwnd);
|
||||
}
|
||||
|
@ -1986,7 +1990,6 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, uint msg, WPARAM wParam,
|
|||
* so the window is activated immediately. */
|
||||
|
||||
system->m_wheelDeltaAccum = 0;
|
||||
system->m_keycode_last_repeat_key = 0;
|
||||
event = processWindowEvent(
|
||||
LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window);
|
||||
/* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL
|
||||
|
|
|
@ -455,8 +455,6 @@ class GHOST_SystemWin32 : public GHOST_System {
|
|||
*/
|
||||
bool setConsoleWindowState(GHOST_TConsoleWindowState action);
|
||||
|
||||
/** The virtual-key code (VKey) of the last press event. Used to detect repeat events. */
|
||||
unsigned short m_keycode_last_repeat_key;
|
||||
/** State variable set at initialization. */
|
||||
bool m_hasPerformanceCounter;
|
||||
/** High frequency timer variable. */
|
||||
|
|
|
@ -90,7 +90,9 @@ GHOST_Wintab *GHOST_Wintab::loadWintab(HWND hwnd)
|
|||
/* Wintab provides no way to determine the maximum queue size aside from checking if attempts
|
||||
* to change the queue size are successful. */
|
||||
const int maxQueue = 500;
|
||||
int queueSize = queueSizeGet(hctx.get());
|
||||
/* < 0 should realistically never happen, but given we cast to size_t later on better safe than
|
||||
* sorry. */
|
||||
int queueSize = max(0, queueSizeGet(hctx.get()));
|
||||
|
||||
while (queueSize < maxQueue) {
|
||||
int testSize = min(queueSize + 16, maxQueue);
|
||||
|
@ -136,7 +138,7 @@ GHOST_Wintab *GHOST_Wintab::loadWintab(HWND hwnd)
|
|||
std::move(hctx),
|
||||
tablet,
|
||||
system,
|
||||
queueSize);
|
||||
size_t(queueSize));
|
||||
}
|
||||
|
||||
void GHOST_Wintab::modifyContext(LOGCONTEXT &lc)
|
||||
|
@ -179,7 +181,7 @@ GHOST_Wintab::GHOST_Wintab(unique_hmodule handle,
|
|||
unique_hctx hctx,
|
||||
Coord tablet,
|
||||
Coord system,
|
||||
int queueSize)
|
||||
size_t queueSize)
|
||||
: m_handle{std::move(handle)},
|
||||
m_fpInfo{info},
|
||||
m_fpGet{get},
|
||||
|
|
|
@ -237,7 +237,7 @@ class GHOST_Wintab {
|
|||
unique_hctx hctx,
|
||||
Coord tablet,
|
||||
Coord system,
|
||||
int queueSize);
|
||||
size_t queueSize);
|
||||
|
||||
/**
|
||||
* Convert Wintab system mapped (mouse) buttons into Ghost button mask.
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <unordered_map>
|
||||
|
||||
#ifdef WITH_TBB
|
||||
# include <tbb/parallel_for.h>
|
||||
|
|
|
@ -877,6 +877,7 @@ const bTheme U_theme_default = {
|
|||
.nodeclass_geometry = RGBA(0x00d6a3ff),
|
||||
.nodeclass_attribute = RGBA(0x001566ff),
|
||||
.node_zone_simulation = RGBA(0x66416233),
|
||||
.node_zone_repeat = RGBA(0x76512f33),
|
||||
.movie = RGBA(0x0f0f0fcc),
|
||||
.gp_vertex_size = 3,
|
||||
.gp_vertex = RGBA(0x97979700),
|
||||
|
|
|
@ -350,6 +350,105 @@ class SimulationZoneItemMoveOperator(SimulationZoneOperator, Operator):
|
|||
return {'FINISHED'}
|
||||
|
||||
|
||||
class RepeatZoneOperator:
|
||||
input_node_type = 'GeometryNodeRepeatInput'
|
||||
output_node_type = 'GeometryNodeRepeatOutput'
|
||||
|
||||
@classmethod
|
||||
def get_output_node(cls, context):
|
||||
node = context.active_node
|
||||
if node.bl_idname == cls.input_node_type:
|
||||
return node.paired_output
|
||||
if node.bl_idname == cls.output_node_type:
|
||||
return node
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
space = context.space_data
|
||||
# Needs active node editor and a tree.
|
||||
if not space or space.type != 'NODE_EDITOR' or not space.edit_tree or space.edit_tree.library:
|
||||
return False
|
||||
node = context.active_node
|
||||
if node is None or node.bl_idname not in [cls.input_node_type, cls.output_node_type]:
|
||||
return False
|
||||
if cls.get_output_node(context) is None:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
class RepeatZoneItemAddOperator(RepeatZoneOperator, Operator):
|
||||
"""Add a repeat item to the repeat zone"""
|
||||
bl_idname = "node.repeat_zone_item_add"
|
||||
bl_label = "Add Repeat Item"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
default_socket_type = 'GEOMETRY'
|
||||
|
||||
def execute(self, context):
|
||||
node = self.get_output_node(context)
|
||||
repeat_items = node.repeat_items
|
||||
|
||||
# Remember index to move the item.
|
||||
if node.active_item:
|
||||
dst_index = node.active_index + 1
|
||||
dst_type = node.active_item.socket_type
|
||||
dst_name = node.active_item.name
|
||||
else:
|
||||
dst_index = len(repeat_items)
|
||||
dst_type = self.default_socket_type
|
||||
# Empty name so it is based on the type.
|
||||
dst_name = ""
|
||||
repeat_items.new(dst_type, dst_name)
|
||||
repeat_items.move(len(repeat_items) - 1, dst_index)
|
||||
node.active_index = dst_index
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class RepeatZoneItemRemoveOperator(RepeatZoneOperator, Operator):
|
||||
"""Remove a repeat item from the repeat zone"""
|
||||
bl_idname = "node.repeat_zone_item_remove"
|
||||
bl_label = "Remove Repeat Item"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
def execute(self, context):
|
||||
node = self.get_output_node(context)
|
||||
repeat_items = node.repeat_items
|
||||
|
||||
if node.active_item:
|
||||
repeat_items.remove(node.active_item)
|
||||
node.active_index = min(node.active_index, len(repeat_items) - 1)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class RepeatZoneItemMoveOperator(RepeatZoneOperator, Operator):
|
||||
"""Move a repeat item up or down in the list"""
|
||||
bl_idname = "node.repeat_zone_item_move"
|
||||
bl_label = "Move Repeat Item"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
direction: EnumProperty(
|
||||
name="Direction",
|
||||
items=[('UP', "Up", ""), ('DOWN', "Down", "")],
|
||||
default='UP',
|
||||
)
|
||||
|
||||
def execute(self, context):
|
||||
node = self.get_output_node(context)
|
||||
repeat_items = node.repeat_items
|
||||
|
||||
if self.direction == 'UP' and node.active_index > 0:
|
||||
repeat_items.move(node.active_index, node.active_index - 1)
|
||||
node.active_index = node.active_index - 1
|
||||
elif self.direction == 'DOWN' and node.active_index < len(repeat_items) - 1:
|
||||
repeat_items.move(node.active_index, node.active_index + 1)
|
||||
node.active_index = node.active_index + 1
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
classes = (
|
||||
NewGeometryNodesModifier,
|
||||
NewGeometryNodeTreeAssign,
|
||||
|
@ -357,4 +456,7 @@ classes = (
|
|||
SimulationZoneItemAddOperator,
|
||||
SimulationZoneItemRemoveOperator,
|
||||
SimulationZoneItemMoveOperator,
|
||||
RepeatZoneItemAddOperator,
|
||||
RepeatZoneItemRemoveOperator,
|
||||
RepeatZoneItemMoveOperator,
|
||||
)
|
||||
|
|
|
@ -154,14 +154,7 @@ class NODE_OT_add_node(NodeAddOperator, Operator):
|
|||
return ""
|
||||
|
||||
|
||||
class NODE_OT_add_simulation_zone(NodeAddOperator, Operator):
|
||||
"""Add simulation zone input and output nodes to the active tree"""
|
||||
bl_idname = "node.add_simulation_zone"
|
||||
bl_label = "Add Simulation Zone"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
input_node_type = "GeometryNodeSimulationInput"
|
||||
output_node_type = "GeometryNodeSimulationOutput"
|
||||
class NodeAddZoneOperator(NodeAddOperator):
|
||||
offset: FloatVectorProperty(
|
||||
name="Offset",
|
||||
description="Offset of nodes from the cursor when added",
|
||||
|
@ -196,6 +189,26 @@ class NODE_OT_add_simulation_zone(NodeAddOperator, Operator):
|
|||
return {'FINISHED'}
|
||||
|
||||
|
||||
class NODE_OT_add_simulation_zone(NodeAddZoneOperator, Operator):
|
||||
"""Add simulation zone input and output nodes to the active tree"""
|
||||
bl_idname = "node.add_simulation_zone"
|
||||
bl_label = "Add Simulation Zone"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
input_node_type = "GeometryNodeSimulationInput"
|
||||
output_node_type = "GeometryNodeSimulationOutput"
|
||||
|
||||
|
||||
class NODE_OT_add_repeat_zone(NodeAddZoneOperator, Operator):
|
||||
"""Add a repeat zone that allows executing nodes a dynamic number of times"""
|
||||
bl_idname = "node.add_repeat_zone"
|
||||
bl_label = "Add Repeat Zone"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
input_node_type = "GeometryNodeRepeatInput"
|
||||
output_node_type = "GeometryNodeRepeatOutput"
|
||||
|
||||
|
||||
class NODE_OT_collapse_hide_unused_toggle(Operator):
|
||||
"""Toggle collapsed nodes and hide unused sockets"""
|
||||
bl_idname = "node.collapse_hide_unused_toggle"
|
||||
|
@ -328,6 +341,7 @@ classes = (
|
|||
|
||||
NODE_OT_add_node,
|
||||
NODE_OT_add_simulation_zone,
|
||||
NODE_OT_add_repeat_zone,
|
||||
NODE_OT_collapse_hide_unused_toggle,
|
||||
NODE_OT_panel_add,
|
||||
NODE_OT_panel_remove,
|
||||
|
|
|
@ -72,6 +72,12 @@ def add_simulation_zone(layout, label):
|
|||
return props
|
||||
|
||||
|
||||
def add_repeat_zone(layout, label):
|
||||
props = layout.operator("node.add_repeat_zone", text=label)
|
||||
props.use_transform = True
|
||||
return props
|
||||
|
||||
|
||||
classes = (
|
||||
)
|
||||
|
||||
|
|
|
@ -530,6 +530,7 @@ class NODE_MT_category_GEO_UTILITIES(Menu):
|
|||
layout.menu("NODE_MT_category_GEO_UTILITIES_ROTATION")
|
||||
layout.separator()
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeRandomValue")
|
||||
node_add_menu.add_repeat_zone(layout, label="Repeat Zone")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSwitch")
|
||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
||||
|
||||
|
|
|
@ -309,6 +309,7 @@ class GRAPH_MT_key_smoothing(Menu):
|
|||
layout.operator_context = 'INVOKE_DEFAULT'
|
||||
layout.operator("graph.gaussian_smooth", text="Smooth (Gaussian)")
|
||||
layout.operator("graph.smooth", text="Smooth (Legacy)")
|
||||
layout.operator("graph.butterworth_smooth")
|
||||
|
||||
|
||||
class GRAPH_MT_key(Menu):
|
||||
|
|
|
@ -139,7 +139,8 @@ class NODE_HT_header(Header):
|
|||
layout.prop(snode_id, "use_nodes")
|
||||
|
||||
elif snode.tree_type == 'GeometryNodeTree':
|
||||
layout.prop(snode, "geometry_nodes_type", text="")
|
||||
if context.preferences.experimental.use_node_group_operators:
|
||||
layout.prop(snode, "geometry_nodes_type", text="")
|
||||
NODE_MT_editor_menus.draw_collapsible(context, layout)
|
||||
layout.separator_spacer()
|
||||
|
||||
|
@ -816,6 +817,10 @@ class NODE_PT_overlay(Panel):
|
|||
col.prop(overlay, "show_context_path", text="Context Path")
|
||||
col.prop(snode, "show_annotation", text="Annotations")
|
||||
|
||||
if snode.supports_preview:
|
||||
col.separator()
|
||||
col.prop(overlay, "show_previews", text="Previews")
|
||||
|
||||
if snode.tree_type == 'GeometryNodeTree':
|
||||
col.separator()
|
||||
col.prop(overlay, "show_timing", text="Timings")
|
||||
|
@ -1106,6 +1111,80 @@ class NODE_PT_simulation_zone_items(Panel):
|
|||
layout.prop(active_item, "attribute_domain")
|
||||
|
||||
|
||||
class NODE_UL_repeat_zone_items(bpy.types.UIList):
|
||||
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
|
||||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
||||
row = layout.row(align=True)
|
||||
row.template_node_socket(color=item.color)
|
||||
row.prop(item, "name", text="", emboss=False, icon_value=icon)
|
||||
elif self.layout_type == 'GRID':
|
||||
layout.alignment = 'CENTER'
|
||||
layout.template_node_socket(color=item.color)
|
||||
|
||||
|
||||
class NODE_PT_repeat_zone_items(Panel):
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
bl_category = "Node"
|
||||
bl_label = "Repeat"
|
||||
|
||||
input_node_type = 'GeometryNodeRepeatInput'
|
||||
output_node_type = 'GeometryNodeRepeatOutput'
|
||||
|
||||
@classmethod
|
||||
def get_output_node(cls, context):
|
||||
node = context.active_node
|
||||
if node.bl_idname == cls.input_node_type:
|
||||
return node.paired_output
|
||||
if node.bl_idname == cls.output_node_type:
|
||||
return node
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
snode = context.space_data
|
||||
if snode is None:
|
||||
return False
|
||||
node = context.active_node
|
||||
if node is None or node.bl_idname not in (cls.input_node_type, cls.output_node_type):
|
||||
return False
|
||||
if cls.get_output_node(context) is None:
|
||||
return False
|
||||
return True
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
output_node = self.get_output_node(context)
|
||||
split = layout.row()
|
||||
split.template_list(
|
||||
"NODE_UL_repeat_zone_items",
|
||||
"",
|
||||
output_node,
|
||||
"repeat_items",
|
||||
output_node,
|
||||
"active_index")
|
||||
|
||||
ops_col = split.column()
|
||||
|
||||
add_remove_col = ops_col.column(align=True)
|
||||
add_remove_col.operator("node.repeat_zone_item_add", icon='ADD', text="")
|
||||
add_remove_col.operator("node.repeat_zone_item_remove", icon='REMOVE', text="")
|
||||
|
||||
ops_col.separator()
|
||||
|
||||
up_down_col = ops_col.column(align=True)
|
||||
props = up_down_col.operator("node.repeat_zone_item_move", icon='TRIA_UP', text="")
|
||||
props.direction = 'UP'
|
||||
props = up_down_col.operator("node.repeat_zone_item_move", icon='TRIA_DOWN', text="")
|
||||
props.direction = 'DOWN'
|
||||
|
||||
active_item = output_node.active_item
|
||||
if active_item is not None:
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
layout.prop(active_item, "socket_type")
|
||||
|
||||
|
||||
# Grease Pencil properties
|
||||
class NODE_PT_annotation(AnnotationDataPanel, Panel):
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
|
@ -1173,6 +1252,8 @@ classes = (
|
|||
NODE_PT_panels,
|
||||
NODE_UL_simulation_zone_items,
|
||||
NODE_PT_simulation_zone_items,
|
||||
NODE_UL_repeat_zone_items,
|
||||
NODE_PT_repeat_zone_items,
|
||||
NODE_PT_active_node_properties,
|
||||
|
||||
node_panel(EEVEE_MATERIAL_PT_settings),
|
||||
|
|
|
@ -2490,6 +2490,7 @@ class SEQUENCER_PT_view_safe_areas_center_cut(SequencerButtonsPanel_Output, Pane
|
|||
|
||||
col = layout.column()
|
||||
col.prop(safe_data, "title_center", slider=True)
|
||||
col.prop(safe_data, "action_center", slider=True)
|
||||
|
||||
|
||||
class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel):
|
||||
|
|
|
@ -91,6 +91,8 @@ class SPREADSHEET_HT_header(bpy.types.Header):
|
|||
layout.label(text=ctx.ui_name, icon='NODE')
|
||||
elif ctx.type == 'SIMULATION_ZONE':
|
||||
layout.label(text="Simulation Zone")
|
||||
elif ctx.type == 'REPEAT_ZONE':
|
||||
layout.label(text="Repeat Zone")
|
||||
elif ctx.type == 'VIEWER_NODE':
|
||||
layout.label(text=ctx.ui_name)
|
||||
|
||||
|
|
|
@ -2428,6 +2428,7 @@ class USERPREF_PT_experimental_new_features(ExperimentalPanel, Panel):
|
|||
({"property": "use_new_volume_nodes"}, ("blender/blender/issues/103248", "#103248")),
|
||||
({"property": "use_node_panels"}, ("blender/blender/issues/105248", "#105248")),
|
||||
({"property": "use_rotation_socket"}, ("/blender/blender/issues/92967", "#92967")),
|
||||
({"property": "use_node_group_operators"}, ("/blender/blender/issues/101778", "#101778")),
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
@ -752,8 +752,18 @@ class VIEW3D_HT_header(Header):
|
|||
# Select mode for Editing
|
||||
if object_mode == 'EDIT':
|
||||
row = layout.row(align=True)
|
||||
row.prop_enum(tool_settings, "gpencil_selectmode_edit", text="", value='POINT')
|
||||
row.prop_enum(tool_settings, "gpencil_selectmode_edit", text="", value='STROKE')
|
||||
row.operator(
|
||||
"grease_pencil.set_selection_mode",
|
||||
text="",
|
||||
icon="GP_SELECT_POINTS",
|
||||
depress=(tool_settings.gpencil_selectmode_edit == 'POINT'),
|
||||
).mode = 'POINT'
|
||||
row.operator(
|
||||
"grease_pencil.set_selection_mode",
|
||||
text="",
|
||||
icon="GP_SELECT_STROKES",
|
||||
depress=(tool_settings.gpencil_selectmode_edit == 'STROKE'),
|
||||
).mode = 'STROKE'
|
||||
|
||||
# Grease Pencil (legacy)
|
||||
if obj and obj.type == 'GPENCIL' and context.gpencil_data:
|
||||
|
|
|
@ -70,7 +70,6 @@ set(SRC_DNA_INC
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_sequence_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_session_uuid_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_shader_fx_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_simulation_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_sound_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_space_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_speaker_types.h
|
||||
|
@ -119,7 +118,6 @@ set(SRC_DNA_DEFAULTS_INC
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_particle_defaults.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_pointcloud_defaults.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_scene_defaults.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_simulation_defaults.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_space_defaults.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_speaker_defaults.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_texture_defaults.h
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
set(INC
|
||||
.
|
||||
intern
|
||||
../blenkernel
|
||||
../../../intern/clog
|
||||
)
|
||||
|
||||
|
@ -39,7 +38,7 @@ set(SRC
|
|||
)
|
||||
|
||||
set(LIB
|
||||
bf_blenkernel
|
||||
PRIVATE bf::blenkernel
|
||||
PRIVATE bf::blenlib
|
||||
PRIVATE bf::dna
|
||||
PRIVATE bf::intern::guardedalloc
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
set(INC
|
||||
.
|
||||
../blenkernel
|
||||
../blentranslation
|
||||
../gpu
|
||||
../imbuf
|
||||
|
@ -31,6 +30,7 @@ set(SRC
|
|||
)
|
||||
|
||||
set(LIB
|
||||
PRIVATE bf::blenkernel
|
||||
PRIVATE bf::blenlib
|
||||
PRIVATE bf::dna
|
||||
bf_gpu
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
* \brief Blender kernel action and pose functionality.
|
||||
*/
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
|
||||
#include "DNA_listBase.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -73,7 +75,8 @@ typedef enum eAction_TransformFlags {
|
|||
eAction_TransformFlags BKE_action_get_item_transform_flags(struct bAction *act,
|
||||
struct Object *ob,
|
||||
struct bPoseChannel *pchan,
|
||||
ListBase *curves);
|
||||
ListBase *curves)
|
||||
ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/**
|
||||
* Calculate the extents of given action.
|
||||
|
@ -81,23 +84,24 @@ eAction_TransformFlags BKE_action_get_item_transform_flags(struct bAction *act,
|
|||
void BKE_action_frame_range_calc(const struct bAction *act,
|
||||
bool include_modifiers,
|
||||
float *r_start,
|
||||
float *r_end);
|
||||
float *r_end) ATTR_NONNULL(3, 4);
|
||||
|
||||
/**
|
||||
* Retrieve the intended playback frame range, using the manually set range if available,
|
||||
* or falling back to scanning F-Curves for their first & last frames otherwise.
|
||||
*/
|
||||
void BKE_action_frame_range_get(const struct bAction *act, float *r_start, float *r_end);
|
||||
void BKE_action_frame_range_get(const struct bAction *act, float *r_start, float *r_end)
|
||||
ATTR_NONNULL(2, 3);
|
||||
|
||||
/**
|
||||
* Check if the given action has any keyframes.
|
||||
*/
|
||||
bool BKE_action_has_motion(const struct bAction *act);
|
||||
bool BKE_action_has_motion(const struct bAction *act) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/**
|
||||
* Is the action configured as cyclic.
|
||||
*/
|
||||
bool BKE_action_is_cyclic(const struct bAction *act);
|
||||
bool BKE_action_is_cyclic(const struct bAction *act) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/**
|
||||
* Remove all fcurves from the action.
|
||||
|
@ -109,7 +113,7 @@ void BKE_action_fcurves_clear(struct bAction *act);
|
|||
/**
|
||||
* Get the active action-group for an Action.
|
||||
*/
|
||||
struct bActionGroup *get_active_actiongroup(struct bAction *act);
|
||||
struct bActionGroup *get_active_actiongroup(struct bAction *act) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/**
|
||||
* Make the given Action-Group the active one.
|
||||
|
@ -166,58 +170,58 @@ void action_groups_clear_tempflags(struct bAction *act);
|
|||
* \return `false` when there is no keyframe at all or keys on different points in time, `true`
|
||||
* when exactly one point in time is keyed.
|
||||
*/
|
||||
bool BKE_action_has_single_frame(const struct bAction *act);
|
||||
bool BKE_action_has_single_frame(const struct bAction *act) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Pose API ----------------- */
|
||||
|
||||
void BKE_pose_channel_free(struct bPoseChannel *pchan);
|
||||
void BKE_pose_channel_free(struct bPoseChannel *pchan) ATTR_NONNULL(1);
|
||||
/**
|
||||
* Deallocates a pose channel.
|
||||
* Does not free the pose channel itself.
|
||||
*/
|
||||
void BKE_pose_channel_free_ex(struct bPoseChannel *pchan, bool do_id_user);
|
||||
void BKE_pose_channel_free_ex(struct bPoseChannel *pchan, bool do_id_user) ATTR_NONNULL(1);
|
||||
|
||||
/**
|
||||
* Clears the runtime cache of a pose channel without free.
|
||||
*/
|
||||
void BKE_pose_channel_runtime_reset(struct bPoseChannel_Runtime *runtime);
|
||||
void BKE_pose_channel_runtime_reset(struct bPoseChannel_Runtime *runtime) ATTR_NONNULL(1);
|
||||
/**
|
||||
* Reset all non-persistent fields.
|
||||
*/
|
||||
void BKE_pose_channel_runtime_reset_on_copy(struct bPoseChannel_Runtime *runtime);
|
||||
void BKE_pose_channel_runtime_reset_on_copy(struct bPoseChannel_Runtime *runtime) ATTR_NONNULL(1);
|
||||
|
||||
/**
|
||||
* Deallocates runtime cache of a pose channel
|
||||
*/
|
||||
void BKE_pose_channel_runtime_free(struct bPoseChannel_Runtime *runtime);
|
||||
void BKE_pose_channel_runtime_free(struct bPoseChannel_Runtime *runtime) ATTR_NONNULL(1);
|
||||
|
||||
/**
|
||||
* Deallocates runtime cache of a pose channel's B-Bone shape.
|
||||
*/
|
||||
void BKE_pose_channel_free_bbone_cache(struct bPoseChannel_Runtime *runtime);
|
||||
void BKE_pose_channel_free_bbone_cache(struct bPoseChannel_Runtime *runtime) ATTR_NONNULL(1);
|
||||
|
||||
void BKE_pose_channels_free(struct bPose *pose);
|
||||
void BKE_pose_channels_free(struct bPose *pose) ATTR_NONNULL(1);
|
||||
/**
|
||||
* Removes and deallocates all channels from a pose.
|
||||
* Does not free the pose itself.
|
||||
*/
|
||||
void BKE_pose_channels_free_ex(struct bPose *pose, bool do_id_user);
|
||||
void BKE_pose_channels_free_ex(struct bPose *pose, bool do_id_user) ATTR_NONNULL(1);
|
||||
|
||||
/**
|
||||
* Removes the hash for quick lookup of channels, must be done when adding/removing channels.
|
||||
*/
|
||||
void BKE_pose_channels_hash_ensure(struct bPose *pose);
|
||||
void BKE_pose_channels_hash_free(struct bPose *pose);
|
||||
void BKE_pose_channels_hash_ensure(struct bPose *pose) ATTR_NONNULL(1);
|
||||
void BKE_pose_channels_hash_free(struct bPose *pose) ATTR_NONNULL(1);
|
||||
|
||||
/**
|
||||
* Selectively remove pose channels.
|
||||
*/
|
||||
void BKE_pose_channels_remove(struct Object *ob,
|
||||
bool (*filter_fn)(const char *bone_name, void *user_data),
|
||||
void *user_data);
|
||||
void *user_data) ATTR_NONNULL(1, 2);
|
||||
|
||||
void BKE_pose_free_data_ex(struct bPose *pose, bool do_id_user);
|
||||
void BKE_pose_free_data(struct bPose *pose);
|
||||
void BKE_pose_free_data_ex(struct bPose *pose, bool do_id_user) ATTR_NONNULL(1);
|
||||
void BKE_pose_free_data(struct bPose *pose) ATTR_NONNULL(1);
|
||||
void BKE_pose_free(struct bPose *pose);
|
||||
/**
|
||||
* Removes and deallocates all data from a pose, and also frees the pose.
|
||||
|
@ -253,7 +257,8 @@ struct bPoseChannel *BKE_pose_channel_find_name(const struct bPose *pose, const
|
|||
*
|
||||
* \return true if on a visible layer, false otherwise.
|
||||
*/
|
||||
bool BKE_pose_is_layer_visible(const struct bArmature *arm, const struct bPoseChannel *pchan);
|
||||
bool BKE_pose_is_layer_visible(const struct bArmature *arm,
|
||||
const struct bPoseChannel *pchan) ATTR_WARN_UNUSED_RESULT;
|
||||
/**
|
||||
* Find the active pose-channel for an object
|
||||
*
|
||||
|
@ -270,7 +275,8 @@ struct bPoseChannel *BKE_pose_channel_active(struct Object *ob, bool check_arm_l
|
|||
* \return #bPoseChannel if found or NULL.
|
||||
* \note #Object, not #bPose is used here, as we need info (layer/active bone) from Armature.
|
||||
*/
|
||||
struct bPoseChannel *BKE_pose_channel_active_if_layer_visible(struct Object *ob);
|
||||
struct bPoseChannel *BKE_pose_channel_active_if_layer_visible(struct Object *ob)
|
||||
ATTR_WARN_UNUSED_RESULT;
|
||||
/**
|
||||
* Use this when detecting the "other selected bone",
|
||||
* when we have multiple armatures in pose mode.
|
||||
|
@ -280,7 +286,8 @@ struct bPoseChannel *BKE_pose_channel_active_if_layer_visible(struct Object *ob)
|
|||
* active object is the _real_ active bone, so any other non-active selected bone
|
||||
* is a candidate for being the other selected bone, see: #58447.
|
||||
*/
|
||||
struct bPoseChannel *BKE_pose_channel_active_or_first_selected(struct Object *ob);
|
||||
struct bPoseChannel *BKE_pose_channel_active_or_first_selected(struct Object *ob)
|
||||
ATTR_WARN_UNUSED_RESULT;
|
||||
/**
|
||||
* Looks to see if the channel with the given name already exists
|
||||
* in this pose - if not a new one is allocated and initialized.
|
||||
|
@ -288,38 +295,39 @@ struct bPoseChannel *BKE_pose_channel_active_or_first_selected(struct Object *ob
|
|||
* \note Use with care, not on Armature poses but for temporal ones.
|
||||
* \note (currently used for action constraints and in rebuild_pose).
|
||||
*/
|
||||
struct bPoseChannel *BKE_pose_channel_ensure(struct bPose *pose, const char *name);
|
||||
struct bPoseChannel *BKE_pose_channel_ensure(struct bPose *pose, const char *name) ATTR_NONNULL(2);
|
||||
/**
|
||||
* \see #ED_armature_ebone_get_mirrored (edit-mode, matching function)
|
||||
*/
|
||||
struct bPoseChannel *BKE_pose_channel_get_mirrored(const struct bPose *pose, const char *name);
|
||||
struct bPoseChannel *BKE_pose_channel_get_mirrored(const struct bPose *pose,
|
||||
const char *name) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
void BKE_pose_check_uuids_unique_and_report(const struct bPose *pose);
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool BKE_pose_channels_is_valid(const struct bPose *pose);
|
||||
bool BKE_pose_channels_is_valid(const struct bPose *pose) ATTR_WARN_UNUSED_RESULT;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Checks for IK constraint, Spline IK, and also for Follow-Path constraint.
|
||||
* can do more constraints flags later. pose should be entirely OK.
|
||||
*/
|
||||
void BKE_pose_update_constraint_flags(struct bPose *pose);
|
||||
void BKE_pose_update_constraint_flags(struct bPose *pose) ATTR_NONNULL(1);
|
||||
|
||||
/**
|
||||
* Tag constraint flags for update.
|
||||
*/
|
||||
void BKE_pose_tag_update_constraint_flags(struct bPose *pose);
|
||||
void BKE_pose_tag_update_constraint_flags(struct bPose *pose) ATTR_NONNULL(1);
|
||||
|
||||
/**
|
||||
* Return the name of structure pointed by `pose->ikparam`.
|
||||
*/
|
||||
const char *BKE_pose_ikparam_get_name(struct bPose *pose);
|
||||
const char *BKE_pose_ikparam_get_name(struct bPose *pose) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/**
|
||||
* Allocate and initialize `pose->ikparam` according to `pose->iksolver`.
|
||||
*/
|
||||
void BKE_pose_ikparam_init(struct bPose *pose);
|
||||
void BKE_pose_ikparam_init(struct bPose *pose) ATTR_NONNULL(1);
|
||||
|
||||
/**
|
||||
* Initialize a #bItasc structure with default value.
|
||||
|
@ -336,17 +344,18 @@ bool BKE_pose_channel_in_IK_chain(struct Object *ob, struct bPoseChannel *pchan)
|
|||
/**
|
||||
* Adds a new bone-group (name may be NULL).
|
||||
*/
|
||||
struct bActionGroup *BKE_pose_add_group(struct bPose *pose, const char *name);
|
||||
struct bActionGroup *BKE_pose_add_group(struct bPose *pose, const char *name) ATTR_NONNULL(1);
|
||||
|
||||
/**
|
||||
* Remove the given bone-group (expects 'virtual' index (+1 one, used by active_group etc.))
|
||||
* index might be invalid ( < 1), in which case it will be find from grp.
|
||||
*/
|
||||
void BKE_pose_remove_group(struct bPose *pose, struct bActionGroup *grp, int index);
|
||||
void BKE_pose_remove_group(struct bPose *pose, struct bActionGroup *grp, int index)
|
||||
ATTR_NONNULL(1);
|
||||
/**
|
||||
* Remove the indexed bone-group (expects 'virtual' index (+1 one, used by active_group etc.)).
|
||||
*/
|
||||
void BKE_pose_remove_group_index(struct bPose *pose, int index);
|
||||
void BKE_pose_remove_group_index(struct bPose *pose, int index) ATTR_NONNULL(1);
|
||||
|
||||
/* Assorted Evaluation ----------------- */
|
||||
|
||||
|
@ -359,10 +368,10 @@ void what_does_obaction(struct Object *ob,
|
|||
struct bPose *pose,
|
||||
struct bAction *act,
|
||||
char groupname[],
|
||||
const struct AnimationEvalContext *anim_eval_context);
|
||||
const struct AnimationEvalContext *anim_eval_context) ATTR_NONNULL(1, 2);
|
||||
|
||||
void BKE_pose_copy_pchan_result(struct bPoseChannel *pchanto,
|
||||
const struct bPoseChannel *pchanfrom);
|
||||
void BKE_pose_copy_pchan_result(struct bPoseChannel *pchanto, const struct bPoseChannel *pchanfrom)
|
||||
ATTR_NONNULL(1, 2);
|
||||
/**
|
||||
* Both poses should be in sync.
|
||||
*/
|
||||
|
@ -375,16 +384,19 @@ void BKE_pose_rest(struct bPose *pose, bool selected_bones_only);
|
|||
/**
|
||||
* Tag pose for recalculation. Also tag all related data to be recalculated.
|
||||
*/
|
||||
void BKE_pose_tag_recalc(struct Main *bmain, struct bPose *pose);
|
||||
void BKE_pose_tag_recalc(struct Main *bmain, struct bPose *pose) ATTR_NONNULL(1, 2);
|
||||
|
||||
void BKE_pose_blend_write(struct BlendWriter *writer, struct bPose *pose, struct bArmature *arm);
|
||||
void BKE_pose_blend_read_data(struct BlendDataReader *reader, struct bPose *pose);
|
||||
void BKE_pose_blend_read_lib(struct BlendLibReader *reader, struct Object *ob, struct bPose *pose);
|
||||
void BKE_pose_blend_read_expand(struct BlendExpander *expander, struct bPose *pose);
|
||||
void BKE_pose_blend_write(struct BlendWriter *writer, struct bPose *pose, struct bArmature *arm)
|
||||
ATTR_NONNULL(1, 2, 3);
|
||||
void BKE_pose_blend_read_data(struct BlendDataReader *reader, struct bPose *pose) ATTR_NONNULL(1);
|
||||
void BKE_pose_blend_read_lib(struct BlendLibReader *reader, struct Object *ob, struct bPose *pose)
|
||||
ATTR_NONNULL(1, 2);
|
||||
void BKE_pose_blend_read_expand(struct BlendExpander *expander, struct bPose *pose)
|
||||
ATTR_NONNULL(1);
|
||||
|
||||
/* action_mirror.c */
|
||||
|
||||
void BKE_action_flip_with_pose(struct bAction *act, struct Object *ob_arm);
|
||||
void BKE_action_flip_with_pose(struct bAction *act, struct Object *ob_arm) ATTR_NONNULL(1, 2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
|
|
|
@ -115,7 +115,7 @@ const char *BKE_id_attributes_default_color_name(const struct ID *id);
|
|||
void BKE_id_attributes_active_color_set(struct ID *id, const char *name);
|
||||
void BKE_id_attributes_default_color_set(struct ID *id, const char *name);
|
||||
|
||||
struct CustomDataLayer *BKE_id_attributes_color_find(const struct ID *id, const char *name);
|
||||
const struct CustomDataLayer *BKE_id_attributes_color_find(const struct ID *id, const char *name);
|
||||
|
||||
bool BKE_id_attribute_calc_unique_name(struct ID *id, const char *name, char *outname);
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ extern "C" {
|
|||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 9
|
||||
#define BLENDER_FILE_SUBVERSION 10
|
||||
|
||||
/* 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
|
||||
|
|
|
@ -78,4 +78,29 @@ class SimulationZoneComputeContext : public ComputeContext {
|
|||
void print_current_in_line(std::ostream &stream) const override;
|
||||
};
|
||||
|
||||
class RepeatZoneComputeContext : public ComputeContext {
|
||||
private:
|
||||
static constexpr const char *s_static_type = "REPEAT_ZONE";
|
||||
|
||||
int32_t output_node_id_;
|
||||
int iteration_;
|
||||
|
||||
public:
|
||||
RepeatZoneComputeContext(const ComputeContext *parent, int32_t output_node_id, int iteration);
|
||||
RepeatZoneComputeContext(const ComputeContext *parent, const bNode &node, int iteration);
|
||||
|
||||
int32_t output_node_id() const
|
||||
{
|
||||
return output_node_id_;
|
||||
}
|
||||
|
||||
int iteration() const
|
||||
{
|
||||
return iteration_;
|
||||
}
|
||||
|
||||
private:
|
||||
void print_current_in_line(std::ostream &stream) const override;
|
||||
};
|
||||
|
||||
} // namespace blender::bke
|
||||
|
|
|
@ -85,7 +85,8 @@ class Drawing : public ::GreasePencilDrawing {
|
|||
MutableSpan<float> radii_for_write();
|
||||
|
||||
/**
|
||||
* Opacities for the points. Used by the render engine as an alpha value so they are expected to
|
||||
* Opacity array for the points.
|
||||
* Used by the render engine as an alpha value so they are expected to
|
||||
* be between 0 and 1 inclusive.
|
||||
*/
|
||||
VArray<float> opacities() const;
|
||||
|
|
|
@ -277,7 +277,6 @@ extern IDTypeInfo IDType_ID_LP;
|
|||
extern IDTypeInfo IDType_ID_CV;
|
||||
extern IDTypeInfo IDType_ID_PT;
|
||||
extern IDTypeInfo IDType_ID_VO;
|
||||
extern IDTypeInfo IDType_ID_SIM;
|
||||
extern IDTypeInfo IDType_ID_GP;
|
||||
|
||||
/** Empty shell mostly, but needed for read code. */
|
||||
|
|
|
@ -530,7 +530,7 @@ void BKE_lib_override_library_main_update(struct Main *bmain);
|
|||
bool BKE_lib_override_library_id_is_user_deletable(struct Main *bmain, struct ID *id);
|
||||
|
||||
/**
|
||||
* Debuging helper to show content of given liboverride data.
|
||||
* Debugging helper to show content of given liboverride data.
|
||||
*/
|
||||
void BKE_lib_override_debug_print(struct IDOverrideLibrary *override, const char *intro_txt);
|
||||
|
||||
|
|
|
@ -225,7 +225,6 @@ typedef struct Main {
|
|||
ListBase hair_curves;
|
||||
ListBase pointclouds;
|
||||
ListBase volumes;
|
||||
ListBase simulations;
|
||||
|
||||
/**
|
||||
* Must be generated, used and freed by same code - never assume this is valid data unless you
|
||||
|
|
|
@ -880,7 +880,6 @@ struct NodeTreeIterStore {
|
|||
struct Light *light;
|
||||
struct World *world;
|
||||
struct FreestyleLineStyle *linestyle;
|
||||
struct Simulation *simulation;
|
||||
};
|
||||
|
||||
void BKE_node_tree_iter_init(struct NodeTreeIterStore *ntreeiter, struct Main *bmain);
|
||||
|
@ -1362,6 +1361,10 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
|
|||
#define GEO_NODE_INPUT_SIGNED_DISTANCE 2102
|
||||
#define GEO_NODE_SAMPLE_VOLUME 2103
|
||||
#define GEO_NODE_MESH_TOPOLOGY_CORNERS_OF_EDGE 2104
|
||||
/* Leaving out two indices to avoid crashes with files that were created during the development of
|
||||
* the repeat zone. */
|
||||
#define GEO_NODE_REPEAT_INPUT 2107
|
||||
#define GEO_NODE_REPEAT_OUTPUT 2108
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -259,8 +259,6 @@ class bNodeRuntime : NonCopyable, NonMovable {
|
|||
short preview_xsize, preview_ysize = 0;
|
||||
/** Entire bound-box (world-space). */
|
||||
rctf totr{};
|
||||
/** Optional preview area. */
|
||||
rctf prvr{};
|
||||
|
||||
/** Used at runtime when going through the tree. Initialize before use. */
|
||||
short tmp_flag = 0;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "BLI_compiler_compat.h"
|
||||
#ifdef __cplusplus
|
||||
# include "BLI_array.hh"
|
||||
# include "BLI_math_vector_types.hh"
|
||||
# include "BLI_offset_indices.hh"
|
||||
#endif
|
||||
#include "BLI_utildefines.h"
|
||||
|
@ -594,7 +595,7 @@ typedef struct SculptSession {
|
|||
struct Depsgraph *depsgraph;
|
||||
|
||||
/* These are always assigned to base mesh data when using PBVH_FACES and PBVH_GRIDS. */
|
||||
float (*vert_positions)[3];
|
||||
blender::MutableSpan<blender::float3> vert_positions;
|
||||
blender::OffsetIndices<int> polys;
|
||||
blender::Span<int> corner_verts;
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "BLI_bitmap.h"
|
||||
#include "BLI_compiler_compat.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_offset_indices.hh"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
|
@ -498,8 +499,8 @@ struct PBVHVertexIter {
|
|||
int gridsize;
|
||||
|
||||
/* mesh */
|
||||
float (*vert_positions)[3];
|
||||
float (*vert_normals)[3];
|
||||
blender::MutableSpan<blender::float3> vert_positions;
|
||||
blender::MutableSpan<blender::float3> vert_normals;
|
||||
const bool *hide_vert;
|
||||
int totvert;
|
||||
const int *vert_indices;
|
||||
|
@ -558,7 +559,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
|
|||
} \
|
||||
} \
|
||||
} \
|
||||
else if (vi.vert_positions) { \
|
||||
else if (!vi.vert_positions.is_empty()) { \
|
||||
vi.visible = !(vi.hide_vert && vi.hide_vert[vi.vert_indices[vi.gx]]); \
|
||||
if (mode == PBVH_ITER_UNIQUE && !vi.visible) { \
|
||||
continue; \
|
||||
|
@ -682,7 +683,7 @@ const bool *BKE_pbvh_get_poly_hide(const PBVH *pbvh);
|
|||
|
||||
PBVHColorBufferNode *BKE_pbvh_node_color_buffer_get(PBVHNode *node);
|
||||
void BKE_pbvh_node_color_buffer_free(PBVH *pbvh);
|
||||
bool BKE_pbvh_get_color_layer(const Mesh *me, CustomDataLayer **r_layer, eAttrDomain *r_attr);
|
||||
bool BKE_pbvh_get_color_layer(Mesh *me, CustomDataLayer **r_layer, eAttrDomain *r_domain);
|
||||
|
||||
/* Swaps colors at each element in indices (of domain pbvh->vcol_domain)
|
||||
* with values in colors. */
|
||||
|
@ -709,7 +710,7 @@ bool BKE_pbvh_is_drawing(const PBVH *pbvh);
|
|||
/* Do not call in PBVH_GRIDS mode */
|
||||
void BKE_pbvh_node_num_loops(PBVH *pbvh, PBVHNode *node, int *r_totloop);
|
||||
|
||||
void BKE_pbvh_update_active_vcol(PBVH *pbvh, const Mesh *mesh);
|
||||
void BKE_pbvh_update_active_vcol(PBVH *pbvh, Mesh *mesh);
|
||||
|
||||
void BKE_pbvh_vertex_color_set(PBVH *pbvh, PBVHVertRef vertex, const float color[4]);
|
||||
void BKE_pbvh_vertex_color_get(const PBVH *pbvh, PBVHVertRef vertex, float r_color[4]);
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct Depsgraph;
|
||||
struct Main;
|
||||
struct Scene;
|
||||
struct Simulation;
|
||||
|
||||
void *BKE_simulation_add(struct Main *bmain, const char *name);
|
||||
|
||||
void BKE_simulation_data_update(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Simulation *simulation);
|
||||
|
||||
void BKE_simulation_reset_scene(Scene *scene);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -197,4 +197,10 @@ class ModifierSimulationCache {
|
|||
void reset();
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset all simulation caches in the scene, for use when some fundamental change made them
|
||||
* impossible to reuse.
|
||||
*/
|
||||
void scene_simulation_states_reset(Scene &scene);
|
||||
|
||||
} // namespace blender::bke::sim
|
||||
|
|
|
@ -53,6 +53,7 @@ ModifierViewerPathElem *BKE_viewer_path_elem_new_modifier(void);
|
|||
GroupNodeViewerPathElem *BKE_viewer_path_elem_new_group_node(void);
|
||||
SimulationZoneViewerPathElem *BKE_viewer_path_elem_new_simulation_zone(void);
|
||||
ViewerNodeViewerPathElem *BKE_viewer_path_elem_new_viewer_node(void);
|
||||
RepeatZoneViewerPathElem *BKE_viewer_path_elem_new_repeat_zone(void);
|
||||
ViewerPathElem *BKE_viewer_path_elem_copy(const ViewerPathElem *src);
|
||||
bool BKE_viewer_path_elem_equal(const ViewerPathElem *a, const ViewerPathElem *b);
|
||||
void BKE_viewer_path_elem_free(ViewerPathElem *elem);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
set(INC
|
||||
.
|
||||
PUBLIC .
|
||||
../asset_system
|
||||
../blenfont
|
||||
../blenloader
|
||||
|
@ -264,7 +264,6 @@ set(SRC
|
|||
intern/screen.c
|
||||
intern/shader_fx.c
|
||||
intern/shrinkwrap.cc
|
||||
intern/simulation.cc
|
||||
intern/simulation_state.cc
|
||||
intern/simulation_state_serialize.cc
|
||||
intern/softbody.c
|
||||
|
@ -471,7 +470,6 @@ set(SRC
|
|||
BKE_sequencer_offscreen.h
|
||||
BKE_shader_fx.h
|
||||
BKE_shrinkwrap.h
|
||||
BKE_simulation.h
|
||||
BKE_simulation_state.hh
|
||||
BKE_simulation_state_serialize.hh
|
||||
BKE_softbody.h
|
||||
|
@ -814,6 +812,7 @@ endif()
|
|||
# endif()
|
||||
|
||||
blender_add_lib(bf_blenkernel "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
add_library(bf::blenkernel ALIAS bf_blenkernel)
|
||||
|
||||
# RNA_prototypes.h
|
||||
add_dependencies(bf_blenkernel bf_rna)
|
||||
|
|
|
@ -1489,7 +1489,7 @@ void BKE_action_frame_range_get(const bAction *act, float *r_start, float *r_end
|
|||
*r_end = act->frame_end;
|
||||
}
|
||||
else {
|
||||
BKE_action_frame_range_calc(act, r_start, r_end, false);
|
||||
BKE_action_frame_range_calc(act, false, r_start, r_end);
|
||||
}
|
||||
|
||||
/* Ensure that action is at least 1 frame long (for NLA strips to have a valid length). */
|
||||
|
@ -1839,12 +1839,9 @@ void BKE_pose_check_uuids_unique_and_report(const bPose *pose)
|
|||
|
||||
void BKE_pose_blend_write(BlendWriter *writer, bPose *pose, bArmature *arm)
|
||||
{
|
||||
/* Write each channel */
|
||||
if (pose == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
BLI_assert(arm != NULL);
|
||||
#ifndef __GNUC__
|
||||
BLI_assert(pose != NULL && arm != NULL);
|
||||
#endif
|
||||
|
||||
/* Write channels */
|
||||
LISTBASE_FOREACH (bPoseChannel *, chan, &pose->chanbase) {
|
||||
|
|
|
@ -1313,9 +1313,6 @@ void BKE_animdata_main_cb(Main *bmain, ID_AnimData_Edit_Callback func, void *use
|
|||
|
||||
/* volumes */
|
||||
ANIMDATA_IDS_CB(bmain->volumes.first);
|
||||
|
||||
/* simulations */
|
||||
ANIMDATA_IDS_CB(bmain->simulations.first);
|
||||
}
|
||||
|
||||
void BKE_animdata_fix_paths_rename_all(ID *ref_id,
|
||||
|
@ -1443,9 +1440,6 @@ void BKE_animdata_fix_paths_rename_all_ex(Main *bmain,
|
|||
/* volumes */
|
||||
RENAMEFIX_ANIM_IDS(bmain->volumes.first);
|
||||
|
||||
/* simulations */
|
||||
RENAMEFIX_ANIM_IDS(bmain->simulations.first);
|
||||
|
||||
/* scenes */
|
||||
RENAMEFIX_ANIM_NODETREE_IDS(bmain->scenes.first, Scene);
|
||||
}
|
||||
|
|
|
@ -4103,9 +4103,6 @@ void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float
|
|||
/* volumes */
|
||||
EVAL_ANIM_IDS(main->volumes.first, ADT_RECALC_ANIM);
|
||||
|
||||
/* simulations */
|
||||
EVAL_ANIM_IDS(main->simulations.first, ADT_RECALC_ANIM);
|
||||
|
||||
/* objects */
|
||||
/* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets
|
||||
* this tagged by Depsgraph on frame-change. This optimization means that objects
|
||||
|
|
|
@ -868,26 +868,10 @@ void BKE_id_attributes_default_color_set(ID *id, const char *name)
|
|||
}
|
||||
}
|
||||
|
||||
CustomDataLayer *BKE_id_attributes_color_find(const ID *id, const char *name)
|
||||
const CustomDataLayer *BKE_id_attributes_color_find(const ID *id, const char *name)
|
||||
{
|
||||
if (CustomDataLayer *layer = BKE_id_attribute_find(id, name, CD_PROP_COLOR, ATTR_DOMAIN_POINT)) {
|
||||
return layer;
|
||||
}
|
||||
if (CustomDataLayer *layer = BKE_id_attribute_find(id, name, CD_PROP_COLOR, ATTR_DOMAIN_CORNER))
|
||||
{
|
||||
return layer;
|
||||
}
|
||||
if (CustomDataLayer *layer = BKE_id_attribute_find(
|
||||
id, name, CD_PROP_BYTE_COLOR, ATTR_DOMAIN_POINT))
|
||||
{
|
||||
return layer;
|
||||
}
|
||||
if (CustomDataLayer *layer = BKE_id_attribute_find(
|
||||
id, name, CD_PROP_BYTE_COLOR, ATTR_DOMAIN_CORNER))
|
||||
{
|
||||
return layer;
|
||||
}
|
||||
return nullptr;
|
||||
return BKE_id_attribute_search(
|
||||
const_cast<ID *>(id), name, CD_MASK_COLOR_ALL, ATTR_DOMAIN_MASK_COLOR);
|
||||
}
|
||||
|
||||
const char *BKE_uv_map_vert_select_name_get(const char *uv_map_name, char *buffer)
|
||||
|
|
|
@ -88,4 +88,33 @@ void SimulationZoneComputeContext::print_current_in_line(std::ostream &stream) c
|
|||
stream << "Simulation Zone ID: " << output_node_id_;
|
||||
}
|
||||
|
||||
RepeatZoneComputeContext::RepeatZoneComputeContext(const ComputeContext *parent,
|
||||
const int32_t output_node_id,
|
||||
const int iteration)
|
||||
: ComputeContext(s_static_type, parent), output_node_id_(output_node_id), iteration_(iteration)
|
||||
{
|
||||
/* Mix static type and node id into a single buffer so that only a single call to #mix_in is
|
||||
* necessary. */
|
||||
const int type_size = strlen(s_static_type);
|
||||
const int buffer_size = type_size + 1 + sizeof(int32_t) + sizeof(int);
|
||||
DynamicStackBuffer<64, 8> buffer_owner(buffer_size, 8);
|
||||
char *buffer = static_cast<char *>(buffer_owner.buffer());
|
||||
memcpy(buffer, s_static_type, type_size + 1);
|
||||
memcpy(buffer + type_size + 1, &output_node_id_, sizeof(int32_t));
|
||||
memcpy(buffer + type_size + 1 + sizeof(int32_t), &iteration_, sizeof(int));
|
||||
hash_.mix_in(buffer, buffer_size);
|
||||
}
|
||||
|
||||
RepeatZoneComputeContext::RepeatZoneComputeContext(const ComputeContext *parent,
|
||||
const bNode &node,
|
||||
const int iteration)
|
||||
: RepeatZoneComputeContext(parent, node.identifier, iteration)
|
||||
{
|
||||
}
|
||||
|
||||
void RepeatZoneComputeContext::print_current_in_line(std::ostream &stream) const
|
||||
{
|
||||
stream << "Repeat Zone ID: " << output_node_id_;
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
|
|
@ -56,6 +56,7 @@ static void grease_pencil_init_data(ID *id)
|
|||
|
||||
new (&grease_pencil->root_group) greasepencil::LayerGroup();
|
||||
grease_pencil->active_layer = nullptr;
|
||||
grease_pencil->flag |= GREASE_PENCIL_ANIM_CHANNEL_EXPANDED;
|
||||
}
|
||||
|
||||
static void grease_pencil_copy_data(Main * /*bmain*/,
|
||||
|
|
|
@ -95,7 +95,6 @@ static void id_type_init(void)
|
|||
INIT_TYPE(ID_CV);
|
||||
INIT_TYPE(ID_PT);
|
||||
INIT_TYPE(ID_VO);
|
||||
INIT_TYPE(ID_SIM);
|
||||
INIT_TYPE(ID_GP);
|
||||
|
||||
/* Special naughty boy... */
|
||||
|
@ -248,7 +247,6 @@ uint64_t BKE_idtype_idcode_to_idfilter(const short idcode)
|
|||
CASE_IDFILTER(PT);
|
||||
CASE_IDFILTER(SCE);
|
||||
CASE_IDFILTER(SCR);
|
||||
CASE_IDFILTER(SIM);
|
||||
CASE_IDFILTER(SO);
|
||||
CASE_IDFILTER(SPK);
|
||||
CASE_IDFILTER(TE);
|
||||
|
@ -307,7 +305,6 @@ short BKE_idtype_idcode_from_idfilter(const uint64_t idfilter)
|
|||
CASE_IDFILTER(PT);
|
||||
CASE_IDFILTER(SCE);
|
||||
CASE_IDFILTER(SCR);
|
||||
CASE_IDFILTER(SIM);
|
||||
CASE_IDFILTER(SO);
|
||||
CASE_IDFILTER(SPK);
|
||||
CASE_IDFILTER(TE);
|
||||
|
@ -364,7 +361,6 @@ int BKE_idtype_idcode_to_index(const short idcode)
|
|||
CASE_IDINDEX(LP);
|
||||
CASE_IDINDEX(SCE);
|
||||
CASE_IDINDEX(SCR);
|
||||
CASE_IDINDEX(SIM);
|
||||
CASE_IDINDEX(SPK);
|
||||
CASE_IDINDEX(SO);
|
||||
CASE_IDINDEX(TE);
|
||||
|
@ -424,7 +420,6 @@ short BKE_idtype_idcode_from_index(const int index)
|
|||
CASE_IDCODE(LP);
|
||||
CASE_IDCODE(SCE);
|
||||
CASE_IDCODE(SCR);
|
||||
CASE_IDCODE(SIM);
|
||||
CASE_IDCODE(SPK);
|
||||
CASE_IDCODE(SO);
|
||||
CASE_IDCODE(TE);
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
#include "DNA_packedFile_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_sequence_types.h"
|
||||
#include "DNA_simulation_types.h"
|
||||
#include "DNA_world_types.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
|
@ -2881,11 +2880,6 @@ static void image_walk_id_all_users(
|
|||
}
|
||||
break;
|
||||
}
|
||||
case ID_SIM: {
|
||||
Simulation *simulation = (Simulation *)id;
|
||||
image_walk_ntree_all_users(simulation->nodetree, &simulation->id, customdata, callback);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "BLI_linklist.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_memarena.h"
|
||||
#include "BLI_set.hh"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_task.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
@ -276,9 +277,12 @@ static ID *lib_override_library_create_from(Main *bmain,
|
|||
LIB_ID_COPY_DEFAULT | LIB_ID_COPY_NO_LIB_OVERRIDE |
|
||||
lib_id_copy_flags);
|
||||
|
||||
/* Incase we could not get an override ID with the exact same name as its linked reference, ensure we at least get a uniquely named override ID over the whole current Main data, to reduce potential name collisions with other reference IDs.
|
||||
/* In case we could not get an override ID with the exact same name as its linked reference,
|
||||
* ensure we at least get a uniquely named override ID over the whole current Main data, to
|
||||
* reduce potential name collisions with other reference IDs.
|
||||
*
|
||||
* While in normal cases this would not be an issue, when files start to get heavily broken and not sound, such conflicts can become a source of problems. */
|
||||
* While in normal cases this would not be an issue, when files start to get heavily broken and
|
||||
* not sound, such conflicts can become a source of problems. */
|
||||
if (!STREQ(local_id->name + 2, reference_id->name + 2)) {
|
||||
BLI_strncpy(local_id->name + 2, reference_id->name + 2, MAX_ID_NAME - 2);
|
||||
BKE_main_namemap_get_name(bmain, local_id, local_id->name + 2, true);
|
||||
|
@ -1614,8 +1618,14 @@ static ID *lib_override_root_find(Main *bmain, ID *id, const int curr_level, int
|
|||
return best_root_id_candidate;
|
||||
}
|
||||
|
||||
static void lib_override_root_hierarchy_set(Main *bmain, ID *id_root, ID *id, ID *id_from)
|
||||
static void lib_override_root_hierarchy_set(
|
||||
Main *bmain, ID *id_root, ID *id, ID *id_from, blender::Set<ID *> &processed_ids)
|
||||
{
|
||||
if (processed_ids.contains(id)) {
|
||||
/* This ID has already been checked as having a valid hierarchy root, do not attempt to replace
|
||||
* it with another one just because it is also used by another liboverride hierarchy. */
|
||||
return;
|
||||
}
|
||||
if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
|
||||
if (id->override_library->hierarchy_root == id_root) {
|
||||
/* Already set, nothing else to do here, sub-hierarchy is also assumed to be properly set
|
||||
|
@ -1685,6 +1695,15 @@ static void lib_override_root_hierarchy_set(Main *bmain, ID *id_root, ID *id, ID
|
|||
}
|
||||
}
|
||||
|
||||
CLOG_INFO(&LOG,
|
||||
3,
|
||||
"Modifying library override hierarchy of ID '%s'.\n"
|
||||
"\tFrom old root '%s' to new root '%s'.",
|
||||
id->name,
|
||||
id->override_library->hierarchy_root ? id->override_library->hierarchy_root->name :
|
||||
"<NONE>",
|
||||
id_root->name);
|
||||
|
||||
id->override_library->hierarchy_root = id_root;
|
||||
}
|
||||
|
||||
|
@ -1709,7 +1728,7 @@ static void lib_override_root_hierarchy_set(Main *bmain, ID *id_root, ID *id, ID
|
|||
}
|
||||
|
||||
/* Recursively process the sub-hierarchy. */
|
||||
lib_override_root_hierarchy_set(bmain, id_root, to_id, id);
|
||||
lib_override_root_hierarchy_set(bmain, id_root, to_id, id, processed_ids);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1718,9 +1737,11 @@ void BKE_lib_override_library_main_hierarchy_root_ensure(Main *bmain)
|
|||
ID *id;
|
||||
|
||||
BKE_main_relations_create(bmain, 0);
|
||||
blender::Set<ID *> processed_ids;
|
||||
|
||||
FOREACH_MAIN_ID_BEGIN (bmain, id) {
|
||||
if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
|
||||
processed_ids.add(id);
|
||||
continue;
|
||||
}
|
||||
if (id->override_library->hierarchy_root != nullptr) {
|
||||
|
@ -1738,6 +1759,8 @@ void BKE_lib_override_library_main_hierarchy_root_ensure(Main *bmain)
|
|||
id->override_library->hierarchy_root = nullptr;
|
||||
}
|
||||
else {
|
||||
/* This ID is considered as having a valid hierarchy root. */
|
||||
processed_ids.add(id);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -1748,16 +1771,20 @@ void BKE_lib_override_library_main_hierarchy_root_ensure(Main *bmain)
|
|||
ID *id_root = lib_override_root_find(bmain, id, best_level, &best_level);
|
||||
|
||||
if (!ELEM(id_root->override_library->hierarchy_root, id_root, nullptr)) {
|
||||
/* FIXME This is probably never actually reached with current code? Check above for non-null
|
||||
* hierarchy root pointer either skip the rest of the loop, or reset it to nullptr. */
|
||||
CLOG_WARN(&LOG,
|
||||
"Potential inconsistency in library override hierarchy of ID '%s', detected as "
|
||||
"part of the hierarchy of '%s', which has a different root '%s'",
|
||||
"Potential inconsistency in library override hierarchy of ID '%s' (current root "
|
||||
"%s), detected as part of the hierarchy of '%s' (current root '%s')",
|
||||
id->name,
|
||||
id->override_library->hierarchy_root->name,
|
||||
id_root->name,
|
||||
id_root->override_library->hierarchy_root->name);
|
||||
processed_ids.add(id);
|
||||
continue;
|
||||
}
|
||||
|
||||
lib_override_root_hierarchy_set(bmain, id_root, id, nullptr);
|
||||
lib_override_root_hierarchy_set(bmain, id_root, id, nullptr, processed_ids);
|
||||
|
||||
BLI_assert(id->override_library->hierarchy_root != nullptr);
|
||||
}
|
||||
|
@ -2413,7 +2440,10 @@ static bool lib_override_library_resync(Main *bmain,
|
|||
do_delete = false;
|
||||
id_fake_user_set(id);
|
||||
id->flag |= LIB_LIB_OVERRIDE_RESYNC_LEFTOVER;
|
||||
CLOG_INFO(&LOG_RESYNC, 2, "Old override %s is being kept around as it was user-edited", id->name);
|
||||
CLOG_INFO(&LOG_RESYNC,
|
||||
2,
|
||||
"Old override %s is being kept around as it was user-edited",
|
||||
id->name);
|
||||
}
|
||||
#else
|
||||
else {
|
||||
|
@ -4859,7 +4889,8 @@ ID *BKE_lib_override_library_operations_store_start(Main *bmain,
|
|||
RNA_id_pointer_create(storage_id, &rnaptr_storage);
|
||||
|
||||
if (!RNA_struct_override_store(
|
||||
bmain, &rnaptr_final, &rnaptr_reference, &rnaptr_storage, local->override_library)) {
|
||||
bmain, &rnaptr_final, &rnaptr_reference, &rnaptr_storage, local->override_library))
|
||||
{
|
||||
BKE_id_free_ex(override_storage, storage_id, LIB_ID_FREE_NO_UI_USER, true);
|
||||
storage_id = nullptr;
|
||||
}
|
||||
|
|
|
@ -475,8 +475,6 @@ uint64_t BKE_library_id_can_use_filter_id(const ID *owner_id, const bool include
|
|||
return FILTER_ID_MA;
|
||||
case ID_VO:
|
||||
return FILTER_ID_MA;
|
||||
case ID_SIM:
|
||||
return FILTER_ID_OB | FILTER_ID_IM;
|
||||
case ID_WM:
|
||||
return FILTER_ID_SCE | FILTER_ID_WS;
|
||||
case ID_IM:
|
||||
|
|
|
@ -597,8 +597,6 @@ ListBase *which_libbase(Main *bmain, short type)
|
|||
return &(bmain->pointclouds);
|
||||
case ID_VO:
|
||||
return &(bmain->volumes);
|
||||
case ID_SIM:
|
||||
return &(bmain->simulations);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -664,7 +662,6 @@ int set_listbasepointers(Main *bmain, ListBase *lb[/*INDEX_ID_MAX*/])
|
|||
lb[INDEX_ID_WS] = &(bmain->workspaces); /* before wm, so it's freed after it! */
|
||||
lb[INDEX_ID_WM] = &(bmain->wm);
|
||||
lb[INDEX_ID_MSK] = &(bmain->masks);
|
||||
lb[INDEX_ID_SIM] = &(bmain->simulations);
|
||||
|
||||
lb[INDEX_ID_NULL] = NULL;
|
||||
|
||||
|
|
|
@ -2046,7 +2046,7 @@ void BKE_mesh_legacy_convert_polys_to_offsets(Mesh *mesh)
|
|||
}
|
||||
});
|
||||
|
||||
CustomData_free(&old_poly_data, mesh->totloop);
|
||||
CustomData_free(&old_poly_data, mesh->totpoly);
|
||||
}
|
||||
|
||||
CustomData_free_layers(&mesh->pdata, CD_MPOLY, mesh->totpoly);
|
||||
|
|
|
@ -1188,11 +1188,11 @@ static void loop_split_generator(LoopSplitTaskDataCommon *common_data,
|
|||
|
||||
#if 0
|
||||
printf("Checking loop %d / edge %u / vert %u (sharp edge: %d, skiploop: %d)",
|
||||
ml_curr_index,
|
||||
corner_edges[ml_curr_index],
|
||||
corner_verts[ml_curr_index],
|
||||
IS_EDGE_SHARP(edge_to_loops[corner_edges[ml_curr_index]]),
|
||||
skip_loops[ml_curr_index]);
|
||||
ml_curr_index,
|
||||
corner_edges[ml_curr_index],
|
||||
corner_verts[ml_curr_index],
|
||||
IS_EDGE_SHARP(edge_to_loops[corner_edges[ml_curr_index]]),
|
||||
skip_loops[ml_curr_index]);
|
||||
#endif
|
||||
|
||||
/* A smooth edge, we have to check for cyclic smooth fan case.
|
||||
|
|
|
@ -174,6 +174,9 @@ const float (*BKE_mesh_wrapper_vert_coords(const Mesh *mesh))[3]
|
|||
{
|
||||
switch (mesh->runtime->wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_BMESH:
|
||||
if (mesh->runtime->edit_data->vertexCos.is_empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<const float(*)[3]>(mesh->runtime->edit_data->vertexCos.data());
|
||||
case ME_WRAPPER_TYPE_MDATA:
|
||||
case ME_WRAPPER_TYPE_SUBD:
|
||||
|
@ -187,6 +190,9 @@ const float (*BKE_mesh_wrapper_poly_normals(Mesh *mesh))[3]
|
|||
switch (mesh->runtime->wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_BMESH:
|
||||
BKE_editmesh_cache_ensure_poly_normals(mesh->edit_mesh, mesh->runtime->edit_data);
|
||||
if (mesh->runtime->edit_data->polyNos.is_empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<const float(*)[3]>(mesh->runtime->edit_data->polyNos.data());
|
||||
case ME_WRAPPER_TYPE_MDATA:
|
||||
case ME_WRAPPER_TYPE_SUBD:
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_simulation_types.h"
|
||||
#include "DNA_texture_types.h"
|
||||
#include "DNA_world_types.h"
|
||||
|
||||
|
@ -676,6 +675,14 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree)
|
|||
BLO_write_string(writer, item.name);
|
||||
}
|
||||
}
|
||||
if (node->type == GEO_NODE_REPEAT_OUTPUT) {
|
||||
const NodeGeometryRepeatOutput &storage = *static_cast<const NodeGeometryRepeatOutput *>(
|
||||
node->storage);
|
||||
BLO_write_struct_array(writer, NodeRepeatItem, storage.items_num, storage.items);
|
||||
for (const NodeRepeatItem &item : Span(storage.items, storage.items_num)) {
|
||||
BLO_write_string(writer, item.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
|
||||
|
@ -872,6 +879,15 @@ void ntreeBlendReadData(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case GEO_NODE_REPEAT_OUTPUT: {
|
||||
NodeGeometryRepeatOutput &storage = *static_cast<NodeGeometryRepeatOutput *>(
|
||||
node->storage);
|
||||
BLO_read_data_address(reader, &storage.items);
|
||||
for (const NodeRepeatItem &item : Span(storage.items, storage.items_num)) {
|
||||
BLO_read_data_address(reader, &item.name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@ -3594,8 +3610,6 @@ bNodeTree **BKE_ntree_ptr_from_id(ID *id)
|
|||
return &reinterpret_cast<Scene *>(id)->nodetree;
|
||||
case ID_LS:
|
||||
return &reinterpret_cast<FreestyleLineStyle *>(id)->nodetree;
|
||||
case ID_SIM:
|
||||
return &reinterpret_cast<Simulation *>(id)->nodetree;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -4726,7 +4740,6 @@ void BKE_node_tree_iter_init(NodeTreeIterStore *ntreeiter, Main *bmain)
|
|||
ntreeiter->light = (Light *)bmain->lights.first;
|
||||
ntreeiter->world = (World *)bmain->worlds.first;
|
||||
ntreeiter->linestyle = (FreestyleLineStyle *)bmain->linestyles.first;
|
||||
ntreeiter->simulation = (Simulation *)bmain->simulations.first;
|
||||
}
|
||||
bool BKE_node_tree_iter_step(NodeTreeIterStore *ntreeiter, bNodeTree **r_nodetree, ID **r_id)
|
||||
{
|
||||
|
@ -4766,11 +4779,6 @@ bool BKE_node_tree_iter_step(NodeTreeIterStore *ntreeiter, bNodeTree **r_nodetre
|
|||
*r_id = &ntreeiter->linestyle->id;
|
||||
ntreeiter->linestyle = reinterpret_cast<FreestyleLineStyle *>(ntreeiter->linestyle->id.next);
|
||||
}
|
||||
else if (ntreeiter->simulation) {
|
||||
*r_nodetree = reinterpret_cast<bNodeTree *>(ntreeiter->simulation->nodetree);
|
||||
*r_id = &ntreeiter->simulation->id;
|
||||
ntreeiter->simulation = reinterpret_cast<Simulation *>(ntreeiter->simulation->id.next);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -294,6 +294,17 @@ static Vector<const bNode *> get_implicit_origin_nodes(const bNodeTree &ntree, b
|
|||
}
|
||||
}
|
||||
}
|
||||
if (node.type == GEO_NODE_REPEAT_OUTPUT) {
|
||||
for (const bNode *repeat_input_node :
|
||||
ntree.runtime->nodes_by_type.lookup(nodeTypeFind("GeometryNodeRepeatInput")))
|
||||
{
|
||||
const auto &storage = *static_cast<const NodeGeometryRepeatInput *>(
|
||||
repeat_input_node->storage);
|
||||
if (storage.output_node_id == node.identifier) {
|
||||
origin_nodes.append(repeat_input_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
return origin_nodes;
|
||||
}
|
||||
|
||||
|
@ -306,6 +317,12 @@ static Vector<const bNode *> get_implicit_target_nodes(const bNodeTree &ntree, b
|
|||
target_nodes.append(sim_output_node);
|
||||
}
|
||||
}
|
||||
if (node.type == GEO_NODE_REPEAT_INPUT) {
|
||||
const auto &storage = *static_cast<const NodeGeometryRepeatInput *>(node.storage);
|
||||
if (const bNode *repeat_output_node = ntree.node_by_id(storage.output_node_id)) {
|
||||
target_nodes.append(repeat_output_node);
|
||||
}
|
||||
}
|
||||
return target_nodes;
|
||||
}
|
||||
|
||||
|
|
|
@ -99,6 +99,48 @@ static const aal::RelationsInNode &get_relations_in_node(const bNode &node, Reso
|
|||
}
|
||||
return relations;
|
||||
}
|
||||
if (ELEM(node.type, GEO_NODE_REPEAT_INPUT, GEO_NODE_REPEAT_OUTPUT)) {
|
||||
aal::RelationsInNode &relations = scope.construct<aal::RelationsInNode>();
|
||||
/* TODO: Add a smaller set of relations. This requires changing the inferencing algorithm to
|
||||
* make it aware of loops. */
|
||||
for (const bNodeSocket *socket : node.output_sockets()) {
|
||||
if (socket->type == SOCK_GEOMETRY) {
|
||||
for (const bNodeSocket *other_output : node.output_sockets()) {
|
||||
if (socket_is_field(*other_output)) {
|
||||
relations.available_relations.append({other_output->index(), socket->index()});
|
||||
}
|
||||
}
|
||||
for (const bNodeSocket *input_socket : node.input_sockets()) {
|
||||
if (input_socket->type == SOCK_GEOMETRY) {
|
||||
relations.propagate_relations.append({input_socket->index(), socket->index()});
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (socket_is_field(*socket)) {
|
||||
/* Reference relations are not added for the output node, because then nodes after the
|
||||
* repeat zone would have to know about the individual field sources within the repeat
|
||||
* zone. This is not necessary, because the field outputs of a repeat zone already serve as
|
||||
* field sources and anonymous attributes are extracted from them. */
|
||||
if (node.type == GEO_NODE_REPEAT_INPUT) {
|
||||
for (const bNodeSocket *input_socket : node.input_sockets()) {
|
||||
if (socket_is_field(*input_socket)) {
|
||||
relations.reference_relations.append({input_socket->index(), socket->index()});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const bNodeSocket *socket : node.input_sockets()) {
|
||||
if (socket->type == SOCK_GEOMETRY) {
|
||||
for (const bNodeSocket *other_input : node.input_sockets()) {
|
||||
if (socket_is_field(*other_input)) {
|
||||
relations.eval_relations.append({other_input->index(), socket->index()});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return relations;
|
||||
}
|
||||
if (const NodeDeclaration *node_decl = node.declaration()) {
|
||||
if (const aal::RelationsInNode *relations = node_decl->anonymous_attribute_relations()) {
|
||||
return *relations;
|
||||
|
|
|
@ -319,6 +319,22 @@ static eFieldStateSyncResult simulation_nodes_field_state_sync(
|
|||
return res;
|
||||
}
|
||||
|
||||
static eFieldStateSyncResult repeat_field_state_sync(
|
||||
const bNode &input_node,
|
||||
const bNode &output_node,
|
||||
const MutableSpan<SocketFieldState> field_state_by_socket_id)
|
||||
{
|
||||
eFieldStateSyncResult res = eFieldStateSyncResult::NONE;
|
||||
for (const int i : output_node.output_sockets().index_range()) {
|
||||
const bNodeSocket &input_socket = input_node.output_socket(i);
|
||||
const bNodeSocket &output_socket = output_node.output_socket(i);
|
||||
SocketFieldState &input_state = field_state_by_socket_id[input_socket.index_in_tree()];
|
||||
SocketFieldState &output_state = field_state_by_socket_id[output_socket.index_in_tree()];
|
||||
res |= sync_field_states(input_state, output_state);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool propagate_special_data_requirements(
|
||||
const bNodeTree &tree,
|
||||
const bNode &node,
|
||||
|
@ -328,29 +344,59 @@ static bool propagate_special_data_requirements(
|
|||
|
||||
bool need_update = false;
|
||||
|
||||
/* Sync field state between simulation nodes and schedule another pass if necessary. */
|
||||
if (node.type == GEO_NODE_SIMULATION_INPUT) {
|
||||
const NodeGeometrySimulationInput &data = *static_cast<const NodeGeometrySimulationInput *>(
|
||||
node.storage);
|
||||
if (const bNode *output_node = tree.node_by_id(data.output_node_id)) {
|
||||
const eFieldStateSyncResult sync_result = simulation_nodes_field_state_sync(
|
||||
node, *output_node, field_state_by_socket_id);
|
||||
if (bool(sync_result & eFieldStateSyncResult::CHANGED_B)) {
|
||||
need_update = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (node.type == GEO_NODE_SIMULATION_OUTPUT) {
|
||||
for (const bNode *input_node : tree.nodes_by_type("GeometryNodeSimulationInput")) {
|
||||
/* Sync field state between zone nodes and schedule another pass if necessary. */
|
||||
switch (node.type) {
|
||||
case GEO_NODE_SIMULATION_INPUT: {
|
||||
const NodeGeometrySimulationInput &data = *static_cast<const NodeGeometrySimulationInput *>(
|
||||
input_node->storage);
|
||||
if (node.identifier == data.output_node_id) {
|
||||
node.storage);
|
||||
if (const bNode *output_node = tree.node_by_id(data.output_node_id)) {
|
||||
const eFieldStateSyncResult sync_result = simulation_nodes_field_state_sync(
|
||||
*input_node, node, field_state_by_socket_id);
|
||||
if (bool(sync_result & eFieldStateSyncResult::CHANGED_A)) {
|
||||
node, *output_node, field_state_by_socket_id);
|
||||
if (bool(sync_result & eFieldStateSyncResult::CHANGED_B)) {
|
||||
need_update = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GEO_NODE_SIMULATION_OUTPUT: {
|
||||
for (const bNode *input_node : tree.nodes_by_type("GeometryNodeSimulationInput")) {
|
||||
const NodeGeometrySimulationInput &data =
|
||||
*static_cast<const NodeGeometrySimulationInput *>(input_node->storage);
|
||||
if (node.identifier == data.output_node_id) {
|
||||
const eFieldStateSyncResult sync_result = simulation_nodes_field_state_sync(
|
||||
*input_node, node, field_state_by_socket_id);
|
||||
if (bool(sync_result & eFieldStateSyncResult::CHANGED_A)) {
|
||||
need_update = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GEO_NODE_REPEAT_INPUT: {
|
||||
const NodeGeometryRepeatInput &data = *static_cast<const NodeGeometryRepeatInput *>(
|
||||
node.storage);
|
||||
if (const bNode *output_node = tree.node_by_id(data.output_node_id)) {
|
||||
const eFieldStateSyncResult sync_result = repeat_field_state_sync(
|
||||
node, *output_node, field_state_by_socket_id);
|
||||
if (bool(sync_result & eFieldStateSyncResult::CHANGED_B)) {
|
||||
need_update = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GEO_NODE_REPEAT_OUTPUT: {
|
||||
for (const bNode *input_node : tree.nodes_by_type("GeometryNodeRepeatInput")) {
|
||||
const NodeGeometryRepeatInput &data = *static_cast<const NodeGeometryRepeatInput *>(
|
||||
input_node->storage);
|
||||
if (node.identifier == data.output_node_id) {
|
||||
const eFieldStateSyncResult sync_result = repeat_field_state_sync(
|
||||
*input_node, node, field_state_by_socket_id);
|
||||
if (bool(sync_result & eFieldStateSyncResult::CHANGED_A)) {
|
||||
need_update = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -365,8 +411,8 @@ static void propagate_data_requirements_from_right_to_left(
|
|||
const Span<const bNode *> toposort_result = tree.toposort_right_to_left();
|
||||
|
||||
while (true) {
|
||||
/* Node updates may require several passes due to cyclic dependencies caused by simulation
|
||||
* input/output nodes. */
|
||||
/* Node updates may require several passes due to cyclic dependencies caused by simulation or
|
||||
* repeat input/output nodes. */
|
||||
bool need_update = false;
|
||||
|
||||
for (const bNode *node : toposort_result) {
|
||||
|
|
|
@ -588,6 +588,15 @@ class NodeTreeMainUpdater {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (node.type == GEO_NODE_REPEAT_INPUT) {
|
||||
const NodeGeometryRepeatInput *data = static_cast<const NodeGeometryRepeatInput *>(
|
||||
node.storage);
|
||||
if (const bNode *output_node = ntree.node_by_id(data->output_node_id)) {
|
||||
if (output_node->runtime->changed_flag & NTREE_CHANGED_NODE_PROPERTY) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,10 @@ static Vector<std::unique_ptr<bNodeTreeZone>> find_zone_nodes(
|
|||
Map<const bNode *, bNodeTreeZone *> &r_zone_by_inout_node)
|
||||
{
|
||||
Vector<std::unique_ptr<bNodeTreeZone>> zones;
|
||||
for (const bNode *node : tree.nodes_by_type("GeometryNodeSimulationOutput")) {
|
||||
Vector<const bNode *> zone_output_nodes;
|
||||
zone_output_nodes.extend(tree.nodes_by_type("GeometryNodeSimulationOutput"));
|
||||
zone_output_nodes.extend(tree.nodes_by_type("GeometryNodeRepeatOutput"));
|
||||
for (const bNode *node : zone_output_nodes) {
|
||||
auto zone = std::make_unique<bNodeTreeZone>();
|
||||
zone->owner = &owner;
|
||||
zone->index = zones.size();
|
||||
|
@ -50,6 +53,15 @@ static Vector<std::unique_ptr<bNodeTreeZone>> find_zone_nodes(
|
|||
}
|
||||
}
|
||||
}
|
||||
for (const bNode *node : tree.nodes_by_type("GeometryNodeRepeatInput")) {
|
||||
const auto &storage = *static_cast<NodeGeometryRepeatInput *>(node->storage);
|
||||
if (const bNode *repeat_output_node = tree.node_by_id(storage.output_node_id)) {
|
||||
if (bNodeTreeZone *zone = r_zone_by_inout_node.lookup_default(repeat_output_node, nullptr)) {
|
||||
zone->input_node = node;
|
||||
r_zone_by_inout_node.add(node, zone);
|
||||
}
|
||||
}
|
||||
}
|
||||
return zones;
|
||||
}
|
||||
|
||||
|
@ -227,13 +239,13 @@ static std::unique_ptr<bNodeTreeZones> discover_tree_zones(const bNodeTree &tree
|
|||
depend_on_output_flags |= depend_on_output_flag_array[from_node_i];
|
||||
}
|
||||
}
|
||||
if (node->type == GEO_NODE_SIMULATION_INPUT) {
|
||||
if (ELEM(node->type, GEO_NODE_SIMULATION_INPUT, GEO_NODE_REPEAT_INPUT)) {
|
||||
if (const bNodeTreeZone *zone = zone_by_inout_node.lookup_default(node, nullptr)) {
|
||||
/* Now entering a zone, so set the corresponding bit. */
|
||||
depend_on_input_flags[zone->index].set();
|
||||
}
|
||||
}
|
||||
else if (node->type == GEO_NODE_SIMULATION_OUTPUT) {
|
||||
else if (ELEM(node->type, GEO_NODE_SIMULATION_OUTPUT, GEO_NODE_REPEAT_OUTPUT)) {
|
||||
if (const bNodeTreeZone *zone = zone_by_inout_node.lookup_default(node, nullptr)) {
|
||||
/* The output is implicitly linked to the input, so also propagate the bits from there. */
|
||||
if (const bNode *zone_input_node = zone->input_node) {
|
||||
|
|
|
@ -577,7 +577,9 @@ static void object_blend_write(BlendWriter *writer, ID *id, const void *id_addre
|
|||
arm = (bArmature *)ob->data;
|
||||
}
|
||||
|
||||
BKE_pose_blend_write(writer, ob->pose, arm);
|
||||
if (ob->pose) {
|
||||
BKE_pose_blend_write(writer, ob->pose, arm);
|
||||
}
|
||||
BKE_constraint_blend_write(writer, &ob->constraints);
|
||||
animviz_motionpath_blend_write(writer, ob->mpath);
|
||||
|
||||
|
|
|
@ -1737,7 +1737,7 @@ static void sculpt_update_object(
|
|||
|
||||
/* These are assigned to the base mesh in Multires. This is needed because Face Sets operators
|
||||
* and tools use the Face Sets data from the base mesh when Multires is active. */
|
||||
ss->vert_positions = BKE_mesh_vert_positions_for_write(me);
|
||||
ss->vert_positions = me->vert_positions_for_write();
|
||||
ss->polys = me->polys();
|
||||
ss->corner_verts = me->corner_verts();
|
||||
}
|
||||
|
@ -1745,7 +1745,7 @@ static void sculpt_update_object(
|
|||
ss->totvert = me->totvert;
|
||||
ss->totpoly = me->totpoly;
|
||||
ss->totfaces = me->totpoly;
|
||||
ss->vert_positions = BKE_mesh_vert_positions_for_write(me);
|
||||
ss->vert_positions = me->vert_positions_for_write();
|
||||
ss->polys = me->polys();
|
||||
ss->corner_verts = me->corner_verts();
|
||||
ss->multires.active = false;
|
||||
|
@ -1756,7 +1756,6 @@ static void sculpt_update_object(
|
|||
|
||||
CustomDataLayer *layer;
|
||||
eAttrDomain domain;
|
||||
|
||||
if (BKE_pbvh_get_color_layer(me, &layer, &domain)) {
|
||||
if (layer->type == CD_PROP_COLOR) {
|
||||
ss->vcol = static_cast<MPropCol *>(layer->data);
|
||||
|
|
|
@ -699,7 +699,6 @@ static void pbvh_draw_args_init(PBVH *pbvh, PBVH_GPU_Args *args, PBVHNode *node)
|
|||
memset((void *)args, 0, sizeof(*args));
|
||||
|
||||
args->pbvh_type = pbvh->header.type;
|
||||
args->mesh_verts_num = pbvh->totvert;
|
||||
args->mesh_grids_num = pbvh->totgrid;
|
||||
args->node = node;
|
||||
|
||||
|
@ -857,7 +856,7 @@ void BKE_pbvh_update_mesh_pointers(PBVH *pbvh, Mesh *mesh)
|
|||
if (!pbvh->deformed) {
|
||||
/* Deformed positions not matching the original mesh are owned directly by the PBVH, and are
|
||||
* set separately by #BKE_pbvh_vert_coords_apply. */
|
||||
pbvh->vert_positions = BKE_mesh_vert_positions_for_write(mesh);
|
||||
pbvh->vert_positions = mesh->vert_positions_for_write();
|
||||
}
|
||||
|
||||
pbvh->hide_poly = static_cast<bool *>(CustomData_get_layer_named_for_write(
|
||||
|
@ -869,7 +868,7 @@ void BKE_pbvh_update_mesh_pointers(PBVH *pbvh, Mesh *mesh)
|
|||
mesh->vert_normals();
|
||||
mesh->poly_normals();
|
||||
|
||||
pbvh->vert_normals = BKE_mesh_vert_normals_for_write(mesh);
|
||||
pbvh->vert_normals = mesh->runtime->vert_normals;
|
||||
pbvh->poly_normals = mesh->runtime->poly_normals;
|
||||
|
||||
pbvh->vdata = &mesh->vdata;
|
||||
|
@ -1095,14 +1094,6 @@ void BKE_pbvh_free(PBVH *pbvh)
|
|||
}
|
||||
}
|
||||
|
||||
if (pbvh->deformed) {
|
||||
if (pbvh->vert_positions) {
|
||||
/* if pbvh was deformed, new memory was allocated for verts/faces -- free it */
|
||||
|
||||
MEM_freeN((void *)pbvh->vert_positions);
|
||||
}
|
||||
}
|
||||
|
||||
if (pbvh->looptri) {
|
||||
MEM_freeN((void *)pbvh->looptri);
|
||||
}
|
||||
|
@ -1119,7 +1110,7 @@ void BKE_pbvh_free(PBVH *pbvh)
|
|||
|
||||
pbvh_pixels_free(pbvh);
|
||||
|
||||
MEM_freeN(pbvh);
|
||||
MEM_delete(pbvh);
|
||||
}
|
||||
|
||||
static void pbvh_iter_begin(PBVHIter *iter,
|
||||
|
@ -1387,8 +1378,7 @@ static void pbvh_faces_update_normals(PBVH *pbvh, Span<PBVHNode *> nodes)
|
|||
{
|
||||
using namespace blender;
|
||||
using namespace blender::bke;
|
||||
const Span<float3> positions(reinterpret_cast<const float3 *>(pbvh->vert_positions),
|
||||
pbvh->totvert);
|
||||
const Span<float3> positions = pbvh->vert_positions;
|
||||
const OffsetIndices polys = pbvh->polys;
|
||||
const Span<int> corner_verts(pbvh->corner_verts, pbvh->mesh->totloop);
|
||||
|
||||
|
@ -1407,7 +1397,7 @@ static void pbvh_faces_update_normals(PBVH *pbvh, Span<PBVHNode *> nodes)
|
|||
return;
|
||||
}
|
||||
|
||||
MutableSpan<float3> vert_normals(reinterpret_cast<float3 *>(pbvh->vert_normals), pbvh->totvert);
|
||||
MutableSpan<float3> vert_normals = pbvh->vert_normals;
|
||||
MutableSpan<float3> poly_normals = pbvh->poly_normals;
|
||||
|
||||
VectorSet<int> verts_to_update;
|
||||
|
@ -1565,28 +1555,12 @@ static void pbvh_update_BB_redraw(PBVH *pbvh, Span<PBVHNode *> nodes, int flag)
|
|||
BLI_task_parallel_range(0, nodes.size(), &data, pbvh_update_BB_redraw_task_cb, &settings);
|
||||
}
|
||||
|
||||
bool BKE_pbvh_get_color_layer(const Mesh *me, CustomDataLayer **r_layer, eAttrDomain *r_attr)
|
||||
bool BKE_pbvh_get_color_layer(Mesh *me, CustomDataLayer **r_layer, eAttrDomain *r_domain)
|
||||
{
|
||||
CustomDataLayer *layer = BKE_id_attributes_color_find(&me->id, me->active_color_attribute);
|
||||
|
||||
if (!layer || !ELEM(layer->type, CD_PROP_COLOR, CD_PROP_BYTE_COLOR)) {
|
||||
*r_layer = nullptr;
|
||||
*r_attr = ATTR_DOMAIN_POINT;
|
||||
return false;
|
||||
}
|
||||
|
||||
eAttrDomain domain = BKE_id_attribute_domain(&me->id, layer);
|
||||
|
||||
if (!ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CORNER)) {
|
||||
*r_layer = nullptr;
|
||||
*r_attr = ATTR_DOMAIN_POINT;
|
||||
return false;
|
||||
}
|
||||
|
||||
*r_layer = layer;
|
||||
*r_attr = domain;
|
||||
|
||||
return true;
|
||||
*r_layer = BKE_id_attribute_search(
|
||||
&me->id, me->active_color_attribute, CD_MASK_COLOR_ALL, ATTR_DOMAIN_MASK_COLOR);
|
||||
*r_domain = *r_layer ? BKE_id_attribute_domain(&me->id, *r_layer) : ATTR_DOMAIN_POINT;
|
||||
return *r_layer != nullptr;
|
||||
}
|
||||
|
||||
static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
|
||||
|
@ -2470,7 +2444,7 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh,
|
|||
int *r_active_face_index,
|
||||
float *r_face_normal)
|
||||
{
|
||||
const float(*positions)[3] = pbvh->vert_positions;
|
||||
const Span<float3> positions = pbvh->vert_positions;
|
||||
const int *corner_verts = pbvh->corner_verts;
|
||||
const int *looptris = node->prim_indices;
|
||||
int looptris_num = node->totprim;
|
||||
|
@ -2819,7 +2793,7 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh,
|
|||
float *depth,
|
||||
float *dist_sq)
|
||||
{
|
||||
const float(*positions)[3] = pbvh->vert_positions;
|
||||
const Span<float3> positions = pbvh->vert_positions;
|
||||
const int *corner_verts = pbvh->corner_verts;
|
||||
const int *looptris = node->prim_indices;
|
||||
int i, looptris_num = node->totprim;
|
||||
|
@ -3182,10 +3156,10 @@ float (*BKE_pbvh_vert_coords_alloc(PBVH *pbvh))[3]
|
|||
{
|
||||
float(*vertCos)[3] = nullptr;
|
||||
|
||||
if (pbvh->vert_positions) {
|
||||
if (!pbvh->vert_positions.is_empty()) {
|
||||
vertCos = static_cast<float(*)[3]>(
|
||||
MEM_malloc_arrayN(pbvh->totvert, sizeof(float[3]), __func__));
|
||||
memcpy(vertCos, pbvh->vert_positions, sizeof(float[3]) * pbvh->totvert);
|
||||
memcpy(vertCos, pbvh->vert_positions.data(), sizeof(float[3]) * pbvh->totvert);
|
||||
}
|
||||
|
||||
return vertCos;
|
||||
|
@ -3199,12 +3173,13 @@ void BKE_pbvh_vert_coords_apply(PBVH *pbvh, const float (*vertCos)[3], const int
|
|||
}
|
||||
|
||||
if (!pbvh->deformed) {
|
||||
if (pbvh->vert_positions) {
|
||||
if (!pbvh->vert_positions.is_empty()) {
|
||||
/* if pbvh is not already deformed, verts/faces points to the */
|
||||
/* original data and applying new coords to this arrays would lead to */
|
||||
/* unneeded deformation -- duplicate verts/faces to avoid this */
|
||||
pbvh->vert_positions_deformed = blender::Array<float3>(pbvh->vert_positions.as_span());
|
||||
pbvh->vert_positions = pbvh->vert_positions_deformed;
|
||||
|
||||
pbvh->vert_positions = static_cast<float(*)[3]>(MEM_dupallocN(pbvh->vert_positions));
|
||||
/* No need to dupalloc pbvh->looptri, this one is 'totally owned' by pbvh,
|
||||
* it's never some mesh data. */
|
||||
|
||||
|
@ -3212,8 +3187,8 @@ void BKE_pbvh_vert_coords_apply(PBVH *pbvh, const float (*vertCos)[3], const int
|
|||
}
|
||||
}
|
||||
|
||||
if (pbvh->vert_positions) {
|
||||
float(*positions)[3] = pbvh->vert_positions;
|
||||
if (!pbvh->vert_positions.is_empty()) {
|
||||
MutableSpan<float3> positions = pbvh->vert_positions;
|
||||
/* copy new verts coords */
|
||||
for (int a = 0; a < pbvh->totvert; a++) {
|
||||
/* no need for float comparison here (memory is exactly equal or not) */
|
||||
|
@ -3301,7 +3276,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
|
|||
vi->grid = nullptr;
|
||||
vi->no = nullptr;
|
||||
vi->fno = nullptr;
|
||||
vi->vert_positions = nullptr;
|
||||
vi->vert_positions = {};
|
||||
vi->vertex.i = 0LL;
|
||||
|
||||
BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, nullptr, &gridsize, &grids);
|
||||
|
@ -3322,7 +3297,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
|
|||
}
|
||||
vi->vert_indices = vert_indices;
|
||||
vi->vert_positions = pbvh->vert_positions;
|
||||
vi->is_mesh = pbvh->vert_positions != nullptr;
|
||||
vi->is_mesh = !pbvh->vert_positions.is_empty();
|
||||
|
||||
if (pbvh->header.type == PBVH_BMESH) {
|
||||
BLI_gsetIterator_init(&vi->bm_unique_verts, node->bm_unique_verts);
|
||||
|
@ -3402,13 +3377,13 @@ void BKE_pbvh_parallel_range_settings(TaskParallelSettings *settings,
|
|||
float (*BKE_pbvh_get_vert_positions(const PBVH *pbvh))[3]
|
||||
{
|
||||
BLI_assert(pbvh->header.type == PBVH_FACES);
|
||||
return pbvh->vert_positions;
|
||||
return reinterpret_cast<float(*)[3]>(pbvh->vert_positions.data());
|
||||
}
|
||||
|
||||
const float (*BKE_pbvh_get_vert_normals(const PBVH *pbvh))[3]
|
||||
{
|
||||
BLI_assert(pbvh->header.type == PBVH_FACES);
|
||||
return pbvh->vert_normals;
|
||||
return reinterpret_cast<const float(*)[3]>(pbvh->vert_normals.data());
|
||||
}
|
||||
|
||||
const bool *BKE_pbvh_get_vert_hide(const PBVH *pbvh)
|
||||
|
@ -3484,7 +3459,7 @@ void BKE_pbvh_node_num_loops(PBVH *pbvh, PBVHNode *node, int *r_totloop)
|
|||
}
|
||||
}
|
||||
|
||||
void BKE_pbvh_update_active_vcol(PBVH *pbvh, const Mesh *mesh)
|
||||
void BKE_pbvh_update_active_vcol(PBVH *pbvh, Mesh *mesh)
|
||||
{
|
||||
BKE_pbvh_get_color_layer(mesh, &pbvh->color_layer, &pbvh->color_domain);
|
||||
}
|
||||
|
|
|
@ -2198,13 +2198,15 @@ static void pbvh_bmesh_print(PBVH *pbvh)
|
|||
BMIter iter;
|
||||
BMFace *f;
|
||||
BM_ITER_MESH (f, &iter, pbvh->header.bm, BM_FACES_OF_MESH) {
|
||||
fprintf(stderr, " %d -> %d\n", BM_elem_index_get(f), pbvh_bmesh_node_index_from_face(pbvh, f));
|
||||
fprintf(
|
||||
stderr, " %d -> %d\n", BM_elem_index_get(f), pbvh_bmesh_node_index_from_face(pbvh, f));
|
||||
}
|
||||
|
||||
fprintf(stderr, "bm_vert_to_node:\n");
|
||||
BMVert *v;
|
||||
BM_ITER_MESH (v, &iter, pbvh->header.bm, BM_FACES_OF_MESH) {
|
||||
fprintf(stderr, " %d -> %d\n", BM_elem_index_get(v), pbvh_bmesh_node_index_from_vert(pbvh, v));
|
||||
fprintf(
|
||||
stderr, " %d -> %d\n", BM_elem_index_get(v), pbvh_bmesh_node_index_from_vert(pbvh, v));
|
||||
}
|
||||
|
||||
for (int n = 0; n < pbvh->totnode; n++) {
|
||||
|
|
|
@ -157,10 +157,12 @@ struct PBVH {
|
|||
Mesh *mesh;
|
||||
|
||||
/* NOTE: Normals are not `const` because they can be updated for drawing by sculpt code. */
|
||||
float (*vert_normals)[3];
|
||||
blender::MutableSpan<blender::float3> vert_normals;
|
||||
blender::MutableSpan<blender::float3> poly_normals;
|
||||
bool *hide_vert;
|
||||
float (*vert_positions)[3];
|
||||
blender::MutableSpan<blender::float3> vert_positions;
|
||||
/** Local vertex positions owned by the PVBH when not sculpting base mesh positions directly. */
|
||||
blender::Array<blender::float3> vert_positions_deformed;
|
||||
blender::OffsetIndices<int> polys;
|
||||
bool *hide_poly;
|
||||
/** Only valid for polygon meshes. */
|
||||
|
|
|
@ -670,11 +670,10 @@ static bool update_pixels(PBVH *pbvh, Mesh *mesh, Image *image, ImageUser *image
|
|||
const AttributeAccessor attributes = mesh->attributes();
|
||||
const VArraySpan uv_map = *attributes.lookup<float2>(active_uv_name, ATTR_DOMAIN_CORNER);
|
||||
|
||||
uv_islands::MeshData mesh_data(
|
||||
{pbvh->looptri, pbvh->totprim},
|
||||
{pbvh->corner_verts, mesh->totloop},
|
||||
uv_map,
|
||||
{static_cast<blender::float3 *>(static_cast<void *>(pbvh->vert_positions)), pbvh->totvert});
|
||||
uv_islands::MeshData mesh_data({pbvh->looptri, pbvh->totprim},
|
||||
{pbvh->corner_verts, mesh->totloop},
|
||||
uv_map,
|
||||
pbvh->vert_positions);
|
||||
uv_islands::UVIslands islands(mesh_data);
|
||||
|
||||
uv_islands::UVIslandsMask uv_masks;
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "DNA_particle_types.h"
|
||||
#include "DNA_rigidbody_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_simulation_types.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_endian_switch.h"
|
||||
|
|
|
@ -1,205 +0,0 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_ID.h"
|
||||
#include "DNA_defaults.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_simulation_types.h"
|
||||
|
||||
#include "BLI_compiler_compat.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_rand.h"
|
||||
#include "BLI_span.hh"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_anim_data.h"
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_collection.h"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_idtype.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_lib_query.h"
|
||||
#include "BKE_lib_remap.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_node.hh"
|
||||
#include "BKE_pointcache.h"
|
||||
#include "BKE_simulation.h"
|
||||
#include "BKE_simulation_state.hh"
|
||||
|
||||
#include "NOD_geometry.hh"
|
||||
|
||||
#include "BLI_map.hh"
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "MOD_nodes.hh"
|
||||
|
||||
#include "BLO_read_write.h"
|
||||
|
||||
static void simulation_init_data(ID *id)
|
||||
{
|
||||
Simulation *simulation = (Simulation *)id;
|
||||
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(simulation, id));
|
||||
|
||||
MEMCPY_STRUCT_AFTER(simulation, DNA_struct_default_get(Simulation), id);
|
||||
|
||||
blender::bke::ntreeAddTreeEmbedded(nullptr, id, "Geometry Nodetree", ntreeType_Geometry->idname);
|
||||
}
|
||||
|
||||
static void simulation_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)
|
||||
{
|
||||
Simulation *simulation_dst = (Simulation *)id_dst;
|
||||
const Simulation *simulation_src = (const Simulation *)id_src;
|
||||
|
||||
/* We always need allocation of our private ID data. */
|
||||
const int flag_private_id_data = flag & ~LIB_ID_CREATE_NO_ALLOCATE;
|
||||
|
||||
if (simulation_src->nodetree) {
|
||||
BKE_id_copy_ex(bmain,
|
||||
(ID *)simulation_src->nodetree,
|
||||
(ID **)&simulation_dst->nodetree,
|
||||
flag_private_id_data);
|
||||
simulation_dst->nodetree->owner_id = &simulation_dst->id;
|
||||
}
|
||||
}
|
||||
|
||||
static void simulation_free_data(ID *id)
|
||||
{
|
||||
Simulation *simulation = (Simulation *)id;
|
||||
|
||||
BKE_animdata_free(&simulation->id, false);
|
||||
|
||||
if (simulation->nodetree) {
|
||||
ntreeFreeEmbeddedTree(simulation->nodetree);
|
||||
MEM_freeN(simulation->nodetree);
|
||||
simulation->nodetree = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static void simulation_foreach_id(ID *id, LibraryForeachIDData *data)
|
||||
{
|
||||
Simulation *simulation = (Simulation *)id;
|
||||
if (simulation->nodetree) {
|
||||
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
||||
data, BKE_library_foreach_ID_embedded(data, (ID **)&simulation->nodetree));
|
||||
}
|
||||
}
|
||||
|
||||
static void simulation_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
||||
{
|
||||
Simulation *simulation = (Simulation *)id;
|
||||
|
||||
BLO_write_id_struct(writer, Simulation, id_address, &simulation->id);
|
||||
BKE_id_blend_write(writer, &simulation->id);
|
||||
|
||||
if (simulation->adt) {
|
||||
BKE_animdata_blend_write(writer, simulation->adt);
|
||||
}
|
||||
|
||||
/* nodetree is integral part of simulation, no libdata */
|
||||
if (simulation->nodetree) {
|
||||
BLO_Write_IDBuffer *temp_embedded_id_buffer = BLO_write_allocate_id_buffer();
|
||||
BLO_write_init_id_buffer_from_id(
|
||||
temp_embedded_id_buffer, &simulation->nodetree->id, BLO_write_is_undo(writer));
|
||||
BLO_write_struct_at_address(writer,
|
||||
bNodeTree,
|
||||
simulation->nodetree,
|
||||
BLO_write_get_id_buffer_temp_id(temp_embedded_id_buffer));
|
||||
ntreeBlendWrite(
|
||||
writer,
|
||||
reinterpret_cast<bNodeTree *>(BLO_write_get_id_buffer_temp_id(temp_embedded_id_buffer)));
|
||||
BLO_write_destroy_id_buffer(&temp_embedded_id_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static void simulation_blend_read_data(BlendDataReader *reader, ID *id)
|
||||
{
|
||||
Simulation *simulation = (Simulation *)id;
|
||||
BLO_read_data_address(reader, &simulation->adt);
|
||||
BKE_animdata_blend_read_data(reader, simulation->adt);
|
||||
}
|
||||
|
||||
static void simulation_blend_read_lib(BlendLibReader *reader, ID *id)
|
||||
{
|
||||
Simulation *simulation = (Simulation *)id;
|
||||
UNUSED_VARS(simulation, reader);
|
||||
}
|
||||
|
||||
static void simulation_blend_read_expand(BlendExpander *expander, ID *id)
|
||||
{
|
||||
Simulation *simulation = (Simulation *)id;
|
||||
UNUSED_VARS(simulation, expander);
|
||||
}
|
||||
|
||||
IDTypeInfo IDType_ID_SIM = {
|
||||
/*id_code*/ ID_SIM,
|
||||
/*id_filter*/ FILTER_ID_SIM,
|
||||
/*main_listbase_index*/ INDEX_ID_SIM,
|
||||
/*struct_size*/ sizeof(Simulation),
|
||||
/*name*/ "Simulation",
|
||||
/*name_plural*/ "simulations",
|
||||
/*translation_context*/ BLT_I18NCONTEXT_ID_SIMULATION,
|
||||
/*flags*/ IDTYPE_FLAGS_APPEND_IS_REUSABLE,
|
||||
/*asset_type_info*/ nullptr,
|
||||
|
||||
/*init_data*/ simulation_init_data,
|
||||
/*copy_data*/ simulation_copy_data,
|
||||
/*free_data*/ simulation_free_data,
|
||||
/*make_local*/ nullptr,
|
||||
/*foreach_id*/ simulation_foreach_id,
|
||||
/*foreach_cache*/ nullptr,
|
||||
/*foreach_path*/ nullptr,
|
||||
/*owner_pointer_get*/ nullptr,
|
||||
|
||||
/*blend_write*/ simulation_blend_write,
|
||||
/*blend_read_data*/ simulation_blend_read_data,
|
||||
/*blend_read_lib*/ simulation_blend_read_lib,
|
||||
/*blend_read_expand*/ simulation_blend_read_expand,
|
||||
|
||||
/*blend_read_undo_preserve*/ nullptr,
|
||||
|
||||
/*lib_override_apply_post*/ nullptr,
|
||||
};
|
||||
|
||||
void *BKE_simulation_add(Main *bmain, const char *name)
|
||||
{
|
||||
Simulation *simulation = (Simulation *)BKE_id_new(bmain, ID_SIM, name);
|
||||
return simulation;
|
||||
}
|
||||
|
||||
void BKE_simulation_data_update(Depsgraph * /*depsgraph*/,
|
||||
Scene * /*scene*/,
|
||||
Simulation * /*simulation*/)
|
||||
{
|
||||
}
|
||||
|
||||
void BKE_simulation_reset_scene(Scene *scene)
|
||||
{
|
||||
FOREACH_SCENE_OBJECT_BEGIN (scene, ob) {
|
||||
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
|
||||
if (md->type != eModifierType_Nodes) {
|
||||
continue;
|
||||
}
|
||||
NodesModifierData *nmd = (NodesModifierData *)md;
|
||||
nmd->runtime->simulation_cache.reset();
|
||||
}
|
||||
}
|
||||
FOREACH_SCENE_OBJECT_END;
|
||||
}
|
|
@ -2,12 +2,12 @@
|
|||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BKE_collection.h"
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_simulation_state.hh"
|
||||
#include "BKE_simulation_state_serialize.hh"
|
||||
|
||||
#include "DNA_curves_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_pointcloud_types.h"
|
||||
|
||||
|
@ -17,6 +17,8 @@
|
|||
#include "BLI_path_util.h"
|
||||
#include "BLI_string_utils.h"
|
||||
|
||||
#include "MOD_nodes.hh"
|
||||
|
||||
namespace blender::bke::sim {
|
||||
|
||||
GeometrySimulationStateItem::GeometrySimulationStateItem(GeometrySet geometry)
|
||||
|
@ -251,4 +253,18 @@ void ModifierSimulationCache::reset()
|
|||
this->cache_state = CacheState::Valid;
|
||||
}
|
||||
|
||||
void scene_simulation_states_reset(Scene &scene)
|
||||
{
|
||||
FOREACH_SCENE_OBJECT_BEGIN (&scene, ob) {
|
||||
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
|
||||
if (md->type != eModifierType_Nodes) {
|
||||
continue;
|
||||
}
|
||||
NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
|
||||
nmd->runtime->simulation_cache->reset();
|
||||
}
|
||||
}
|
||||
FOREACH_SCENE_OBJECT_END;
|
||||
}
|
||||
|
||||
} // namespace blender::bke::sim
|
||||
|
|
|
@ -231,7 +231,7 @@ void BKE_vfont_builtin_register(const void *mem, int size)
|
|||
builtin_font_size = size;
|
||||
}
|
||||
|
||||
static PackedFile *get_builtin_packedfile(void)
|
||||
static PackedFile *get_builtin_packedfile()
|
||||
{
|
||||
if (!builtin_font_data) {
|
||||
CLOG_ERROR(&LOG, "Internal error, builtin font not loaded");
|
||||
|
@ -410,7 +410,7 @@ static VFont *which_vfont(Curve *cu, CharInfo *info)
|
|||
}
|
||||
}
|
||||
|
||||
VFont *BKE_vfont_builtin_get(void)
|
||||
VFont *BKE_vfont_builtin_get()
|
||||
{
|
||||
LISTBASE_FOREACH (VFont *, vfont, &G_MAIN->fonts) {
|
||||
if (BKE_vfont_is_builtin(vfont)) {
|
||||
|
@ -2053,7 +2053,7 @@ static struct {
|
|||
size_t len_utf8;
|
||||
} g_vfont_clipboard = {nullptr};
|
||||
|
||||
void BKE_vfont_clipboard_free(void)
|
||||
void BKE_vfont_clipboard_free()
|
||||
{
|
||||
MEM_SAFE_FREE(g_vfont_clipboard.text_buffer);
|
||||
MEM_SAFE_FREE(g_vfont_clipboard.info_buffer);
|
||||
|
|
|
@ -88,6 +88,11 @@ void BKE_viewer_path_blend_write(BlendWriter *writer, const ViewerPath *viewer_p
|
|||
BLO_write_struct(writer, ViewerNodeViewerPathElem, typed_elem);
|
||||
break;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: {
|
||||
const auto *typed_elem = reinterpret_cast<RepeatZoneViewerPathElem *>(elem);
|
||||
BLO_write_struct(writer, RepeatZoneViewerPathElem, typed_elem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
BLO_write_string(writer, elem->ui_name);
|
||||
}
|
||||
|
@ -102,6 +107,7 @@ void BKE_viewer_path_blend_read_data(BlendDataReader *reader, ViewerPath *viewer
|
|||
case VIEWER_PATH_ELEM_TYPE_GROUP_NODE:
|
||||
case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE:
|
||||
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE:
|
||||
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE:
|
||||
case VIEWER_PATH_ELEM_TYPE_ID: {
|
||||
break;
|
||||
}
|
||||
|
@ -126,7 +132,8 @@ void BKE_viewer_path_blend_read_lib(BlendLibReader *reader, ID *self_id, ViewerP
|
|||
case VIEWER_PATH_ELEM_TYPE_MODIFIER:
|
||||
case VIEWER_PATH_ELEM_TYPE_GROUP_NODE:
|
||||
case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE:
|
||||
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE: {
|
||||
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE:
|
||||
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -145,7 +152,8 @@ void BKE_viewer_path_foreach_id(LibraryForeachIDData *data, ViewerPath *viewer_p
|
|||
case VIEWER_PATH_ELEM_TYPE_MODIFIER:
|
||||
case VIEWER_PATH_ELEM_TYPE_GROUP_NODE:
|
||||
case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE:
|
||||
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE: {
|
||||
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE:
|
||||
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -164,7 +172,8 @@ void BKE_viewer_path_id_remap(ViewerPath *viewer_path, const IDRemapper *mapping
|
|||
case VIEWER_PATH_ELEM_TYPE_MODIFIER:
|
||||
case VIEWER_PATH_ELEM_TYPE_GROUP_NODE:
|
||||
case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE:
|
||||
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE: {
|
||||
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE:
|
||||
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -196,6 +205,9 @@ ViewerPathElem *BKE_viewer_path_elem_new(const ViewerPathElemType type)
|
|||
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE: {
|
||||
return &make_elem<ViewerNodeViewerPathElem>(type)->base;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: {
|
||||
return &make_elem<RepeatZoneViewerPathElem>(type)->base;
|
||||
}
|
||||
}
|
||||
BLI_assert_unreachable();
|
||||
return nullptr;
|
||||
|
@ -230,6 +242,12 @@ ViewerNodeViewerPathElem *BKE_viewer_path_elem_new_viewer_node()
|
|||
BKE_viewer_path_elem_new(VIEWER_PATH_ELEM_TYPE_VIEWER_NODE));
|
||||
}
|
||||
|
||||
RepeatZoneViewerPathElem *BKE_viewer_path_elem_new_repeat_zone()
|
||||
{
|
||||
return reinterpret_cast<RepeatZoneViewerPathElem *>(
|
||||
BKE_viewer_path_elem_new(VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE));
|
||||
}
|
||||
|
||||
ViewerPathElem *BKE_viewer_path_elem_copy(const ViewerPathElem *src)
|
||||
{
|
||||
ViewerPathElem *dst = BKE_viewer_path_elem_new(ViewerPathElemType(src->type));
|
||||
|
@ -269,6 +287,13 @@ ViewerPathElem *BKE_viewer_path_elem_copy(const ViewerPathElem *src)
|
|||
new_elem->node_id = old_elem->node_id;
|
||||
break;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: {
|
||||
const auto *old_elem = reinterpret_cast<const RepeatZoneViewerPathElem *>(src);
|
||||
auto *new_elem = reinterpret_cast<RepeatZoneViewerPathElem *>(dst);
|
||||
new_elem->repeat_output_node_id = old_elem->repeat_output_node_id;
|
||||
new_elem->iteration = old_elem->iteration;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
@ -304,6 +329,12 @@ bool BKE_viewer_path_elem_equal(const ViewerPathElem *a, const ViewerPathElem *b
|
|||
const auto *b_elem = reinterpret_cast<const ViewerNodeViewerPathElem *>(b);
|
||||
return a_elem->node_id == b_elem->node_id;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: {
|
||||
const auto *a_elem = reinterpret_cast<const RepeatZoneViewerPathElem *>(a);
|
||||
const auto *b_elem = reinterpret_cast<const RepeatZoneViewerPathElem *>(b);
|
||||
return a_elem->repeat_output_node_id == b_elem->repeat_output_node_id &&
|
||||
a_elem->iteration == b_elem->iteration;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -314,7 +345,8 @@ void BKE_viewer_path_elem_free(ViewerPathElem *elem)
|
|||
case VIEWER_PATH_ELEM_TYPE_ID:
|
||||
case VIEWER_PATH_ELEM_TYPE_GROUP_NODE:
|
||||
case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE:
|
||||
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE: {
|
||||
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE:
|
||||
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: {
|
||||
break;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_MODIFIER: {
|
||||
|
|
|
@ -87,6 +87,17 @@ struct FloatTraits {
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T> struct TraitsType {
|
||||
using type = void;
|
||||
};
|
||||
template<> struct TraitsType<ColorPaint4f> {
|
||||
using type = FloatTraits;
|
||||
};
|
||||
template<> struct TraitsType<ColorPaint4b> {
|
||||
using type = ByteTraits;
|
||||
};
|
||||
template<typename T> using Traits = typename TraitsType<T>::type;
|
||||
|
||||
static float get_luminance(ColorPaint4f c)
|
||||
{
|
||||
return IMB_colormanagement_get_luminance(&c.r);
|
||||
|
|
|
@ -50,12 +50,9 @@
|
|||
* memory usage of the map.
|
||||
* - The method names don't follow the std::unordered_map names in many cases. Searching for such
|
||||
* names in this file will usually let you discover the new name.
|
||||
* - There is a StdUnorderedMapWrapper class, that wraps std::unordered_map and gives it the same
|
||||
* interface as blender::Map. This is useful for benchmarking.
|
||||
*/
|
||||
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "BLI_array.hh"
|
||||
#include "BLI_hash.hh"
|
||||
|
@ -1287,71 +1284,4 @@ template<typename Key,
|
|||
using RawMap =
|
||||
Map<Key, Value, InlineBufferCapacity, ProbingStrategy, Hash, IsEqual, Slot, RawAllocator>;
|
||||
|
||||
/**
|
||||
* A wrapper for std::unordered_map with the API of blender::Map. This can be used for
|
||||
* benchmarking.
|
||||
*/
|
||||
template<typename Key, typename Value> class StdUnorderedMapWrapper {
|
||||
private:
|
||||
using MapType = std::unordered_map<Key, Value, blender::DefaultHash<Key>>;
|
||||
MapType map_;
|
||||
|
||||
public:
|
||||
int64_t size() const
|
||||
{
|
||||
return int64_t(map_.size());
|
||||
}
|
||||
|
||||
bool is_empty() const
|
||||
{
|
||||
return map_.empty();
|
||||
}
|
||||
|
||||
void reserve(int64_t n)
|
||||
{
|
||||
map_.reserve(n);
|
||||
}
|
||||
|
||||
template<typename ForwardKey, typename... ForwardValue>
|
||||
void add_new(ForwardKey &&key, ForwardValue &&...value)
|
||||
{
|
||||
map_.insert({std::forward<ForwardKey>(key), Value(std::forward<ForwardValue>(value)...)});
|
||||
}
|
||||
|
||||
template<typename ForwardKey, typename... ForwardValue>
|
||||
bool add(ForwardKey &&key, ForwardValue &&...value)
|
||||
{
|
||||
return map_
|
||||
.insert({std::forward<ForwardKey>(key), Value(std::forward<ForwardValue>(value)...)})
|
||||
.second;
|
||||
}
|
||||
|
||||
bool contains(const Key &key) const
|
||||
{
|
||||
return map_.find(key) != map_.end();
|
||||
}
|
||||
|
||||
bool remove(const Key &key)
|
||||
{
|
||||
return bool(map_.erase(key));
|
||||
}
|
||||
|
||||
Value &lookup(const Key &key)
|
||||
{
|
||||
return map_.find(key)->second;
|
||||
}
|
||||
|
||||
const Value &lookup(const Key &key) const
|
||||
{
|
||||
return map_.find(key)->second;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
map_.clear();
|
||||
}
|
||||
|
||||
void print_stats(StringRef /*name*/ = "") const {}
|
||||
};
|
||||
|
||||
} // namespace blender
|
||||
|
|
|
@ -45,8 +45,6 @@
|
|||
* memory usage of the set.
|
||||
* - The method names don't follow the std::unordered_set names in many cases. Searching for such
|
||||
* names in this file will usually let you discover the new name.
|
||||
* - There is a #StdUnorderedSetWrapper class, that wraps std::unordered_set and gives it the same
|
||||
* interface as blender::Set. This is useful for bench-marking.
|
||||
*
|
||||
* Possible Improvements:
|
||||
* - Use a branch-less loop over slots in grow function (measured ~10% performance improvement when
|
||||
|
@ -57,8 +55,6 @@
|
|||
* to make a nice interface for this functionality.
|
||||
*/
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
#include "BLI_array.hh"
|
||||
#include "BLI_hash.hh"
|
||||
#include "BLI_hash_tables.hh"
|
||||
|
@ -889,87 +885,6 @@ class Set {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A wrapper for std::unordered_set with the API of blender::Set. This can be used for
|
||||
* benchmarking.
|
||||
*/
|
||||
template<typename Key> class StdUnorderedSetWrapper {
|
||||
private:
|
||||
using SetType = std::unordered_set<Key, blender::DefaultHash<Key>>;
|
||||
SetType set_;
|
||||
|
||||
public:
|
||||
int64_t size() const
|
||||
{
|
||||
return int64_t(set_.size());
|
||||
}
|
||||
|
||||
bool is_empty() const
|
||||
{
|
||||
return set_.empty();
|
||||
}
|
||||
|
||||
void reserve(int64_t n)
|
||||
{
|
||||
set_.reserve(n);
|
||||
}
|
||||
|
||||
void add_new(const Key &key)
|
||||
{
|
||||
set_.insert(key);
|
||||
}
|
||||
void add_new(Key &&key)
|
||||
{
|
||||
set_.insert(std::move(key));
|
||||
}
|
||||
|
||||
bool add(const Key &key)
|
||||
{
|
||||
return set_.insert(key).second;
|
||||
}
|
||||
bool add(Key &&key)
|
||||
{
|
||||
return set_.insert(std::move(key)).second;
|
||||
}
|
||||
|
||||
void add_multiple(Span<Key> keys)
|
||||
{
|
||||
for (const Key &key : keys) {
|
||||
set_.insert(key);
|
||||
}
|
||||
}
|
||||
|
||||
bool contains(const Key &key) const
|
||||
{
|
||||
return set_.find(key) != set_.end();
|
||||
}
|
||||
|
||||
bool remove(const Key &key)
|
||||
{
|
||||
return bool(set_.erase(key));
|
||||
}
|
||||
|
||||
void remove_contained(const Key &key)
|
||||
{
|
||||
return set_.erase(key);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
set_.clear();
|
||||
}
|
||||
|
||||
typename SetType::iterator begin() const
|
||||
{
|
||||
return set_.begin();
|
||||
}
|
||||
|
||||
typename SetType::iterator end() const
|
||||
{
|
||||
return set_.end();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Same as a normal Set, but does not use Blender's guarded allocator. This is useful when
|
||||
* allocating memory with static storage duration.
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue