GPU: Add Texture Usage Parameter to GPUOffscreen. #106899
|
@ -803,6 +803,16 @@ static void attr_create_generic(Scene *scene,
|
|||
num_curves, num_keys, data, element, [&](int i) { return float(src[i]); });
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_INT32_2D: {
|
||||
BL::Int2Attribute b_int2_attribute{b_attribute};
|
||||
const int2 *src = static_cast<const int2 *>(b_int2_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat2, element);
|
||||
float2 *data = attr->data_float2();
|
||||
fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) {
|
||||
return make_float2(float(src[i][0]), float(src[i][1]));
|
||||
});
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_FLOAT_VECTOR: {
|
||||
BL::FloatVectorAttribute b_vector_attribute{b_attribute};
|
||||
const float(*src)[3] = static_cast<const float(*)[3]>(b_vector_attribute.data[0].ptr.data);
|
||||
|
|
|
@ -528,6 +528,19 @@ static void attr_create_generic(Scene *scene,
|
|||
});
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_INT32_2D: {
|
||||
BL::Int2Attribute b_int2_attribute{b_attribute};
|
||||
if (b_int2_attribute.data.length() == 0) {
|
||||
continue;
|
||||
}
|
||||
const int2 *src = static_cast<const int2 *>(b_int2_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat2, element);
|
||||
float2 *data = attr->data_float2();
|
||||
fill_generic_attribute(b_mesh, data, b_domain, subdivision, [&](int i) {
|
||||
return make_float2(float(src[i][0]), float(src[i][1]));
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* Not supported. */
|
||||
break;
|
||||
|
|
|
@ -102,6 +102,16 @@ static void copy_attributes(PointCloud *pointcloud,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_INT32_2D: {
|
||||
BL::Int2Attribute b_int2_attribute{b_attribute};
|
||||
const int2 *src = static_cast<const int2 *>(b_int2_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat2, element);
|
||||
float2 *data = attr->data_float2();
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
data[i] = make_float2(float(src[i][0]), float(src[i][1]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_FLOAT_VECTOR: {
|
||||
BL::FloatVectorAttribute b_vector_attribute{b_attribute};
|
||||
const float(*src)[3] = static_cast<const float(*)[3]>(b_vector_attribute.data[0].ptr.data);
|
||||
|
|
|
@ -357,8 +357,12 @@ void PathTraceWorkCPU::guiding_push_sample_data_to_global_storage(
|
|||
# if PATH_GUIDING_LEVEL >= 2
|
||||
const bool use_direct_light = kernel_data.integrator.use_guiding_direct_light;
|
||||
const bool use_mis_weights = kernel_data.integrator.use_guiding_mis_weights;
|
||||
# if OPENPGL_VERSION_MINOR >= 5
|
||||
kg->opgl_path_segment_storage->PrepareSamples(use_mis_weights, use_direct_light, false);
|
||||
# else
|
||||
kg->opgl_path_segment_storage->PrepareSamples(
|
||||
false, nullptr, use_mis_weights, use_direct_light, false);
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef WITH_CYCLES_DEBUG
|
||||
|
|
|
@ -454,8 +454,13 @@ ccl_device_forceinline bool guiding_bsdf_init(KernelGlobals kg,
|
|||
ccl_private float &rand)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4
|
||||
# if OPENPGL_VERSION_MINOR >= 5
|
||||
if (kg->opgl_surface_sampling_distribution->Init(
|
||||
kg->opgl_guiding_field, guiding_point3f(P), rand)) {
|
||||
# else
|
||||
if (kg->opgl_surface_sampling_distribution->Init(
|
||||
kg->opgl_guiding_field, guiding_point3f(P), rand, true)) {
|
||||
# endif
|
||||
kg->opgl_surface_sampling_distribution->ApplyCosineProduct(guiding_point3f(N));
|
||||
return true;
|
||||
}
|
||||
|
@ -506,8 +511,13 @@ ccl_device_forceinline bool guiding_phase_init(KernelGlobals kg,
|
|||
return false;
|
||||
}
|
||||
|
||||
# if OPENPGL_VERSION_MINOR >= 5
|
||||
if (kg->opgl_volume_sampling_distribution->Init(
|
||||
kg->opgl_guiding_field, guiding_point3f(P), rand)) {
|
||||
# else
|
||||
if (kg->opgl_volume_sampling_distribution->Init(
|
||||
kg->opgl_guiding_field, guiding_point3f(P), rand, true)) {
|
||||
# endif
|
||||
kg->opgl_volume_sampling_distribution->ApplySingleLobeHenyeyGreensteinProduct(guiding_vec3f(D),
|
||||
g);
|
||||
return true;
|
||||
|
|
|
@ -1390,19 +1390,128 @@ ccl_device_extern void osl_noiseparams_set_impulses(ccl_private OSLNoiseOptions
|
|||
res->y = n; \
|
||||
res->z = n; \
|
||||
} \
|
||||
ccl_device_extern void name##_vv(ccl_private float3 *res, const float3 *v) \
|
||||
ccl_device_extern void name##_vv(ccl_private float3 *res, ccl_private const float3 *v) \
|
||||
{ \
|
||||
const float n = name##_fv(v); \
|
||||
res->x = n; \
|
||||
res->y = n; \
|
||||
res->z = n; \
|
||||
} \
|
||||
ccl_device_extern void name##_vvf(ccl_private float3 *res, const float3 *v, float w) \
|
||||
ccl_device_extern void name##_vvf( \
|
||||
ccl_private float3 *res, ccl_private const float3 *v, float w) \
|
||||
{ \
|
||||
const float n = name##_fvf(v, w); \
|
||||
res->x = n; \
|
||||
res->y = n; \
|
||||
res->z = n; \
|
||||
} \
|
||||
ccl_device_extern void name##_dfdf(ccl_private float *res, ccl_private const float *x) \
|
||||
{ \
|
||||
res[0] = name##_ff(x[0]); \
|
||||
res[1] = name##_ff(x[1]); \
|
||||
res[2] = name##_ff(x[2]); \
|
||||
} \
|
||||
ccl_device_extern void name##_dfdff( \
|
||||
ccl_private float *res, ccl_private const float *x, float y) \
|
||||
{ \
|
||||
res[0] = name##_fff(x[0], y); \
|
||||
res[1] = name##_fff(x[1], y); \
|
||||
res[2] = name##_fff(x[2], y); \
|
||||
} \
|
||||
ccl_device_extern void name##_dffdf( \
|
||||
ccl_private float *res, float x, ccl_private const float *y) \
|
||||
{ \
|
||||
res[0] = name##_fff(x, y[0]); \
|
||||
res[1] = name##_fff(x, y[1]); \
|
||||
res[2] = name##_fff(x, y[2]); \
|
||||
} \
|
||||
ccl_device_extern void name##_dfdfdf( \
|
||||
ccl_private float *res, ccl_private const float *x, ccl_private const float *y) \
|
||||
{ \
|
||||
res[0] = name##_fff(x[0], y[0]); \
|
||||
res[1] = name##_fff(x[1], y[1]); \
|
||||
res[2] = name##_fff(x[2], y[2]); \
|
||||
} \
|
||||
ccl_device_extern void name##_dfdv(ccl_private float *res, ccl_private const float3 *v) \
|
||||
{ \
|
||||
res[0] = name##_fv(&v[0]); \
|
||||
res[1] = name##_fv(&v[1]); \
|
||||
res[2] = name##_fv(&v[2]); \
|
||||
} \
|
||||
ccl_device_extern void name##_dfdvf( \
|
||||
ccl_private float *res, ccl_private const float3 *v, float w) \
|
||||
{ \
|
||||
res[0] = name##_fvf(&v[0], w); \
|
||||
res[1] = name##_fvf(&v[1], w); \
|
||||
res[2] = name##_fvf(&v[2], w); \
|
||||
} \
|
||||
ccl_device_extern void name##_dfvdf( \
|
||||
ccl_private float *res, ccl_private const float3 *v, ccl_private const float *w) \
|
||||
{ \
|
||||
res[0] = name##_fvf(v, w[0]); \
|
||||
res[1] = name##_fvf(v, w[1]); \
|
||||
res[2] = name##_fvf(v, w[2]); \
|
||||
} \
|
||||
ccl_device_extern void name##_dfdvdf( \
|
||||
ccl_private float *res, ccl_private const float3 *v, ccl_private const float *w) \
|
||||
{ \
|
||||
res[0] = name##_fvf(&v[0], w[0]); \
|
||||
res[1] = name##_fvf(&v[1], w[1]); \
|
||||
res[2] = name##_fvf(&v[2], w[2]); \
|
||||
} \
|
||||
ccl_device_extern void name##_dvdf(ccl_private float3 *res, ccl_private const float *x) \
|
||||
{ \
|
||||
name##_vf(&res[0], x[0]); \
|
||||
name##_vf(&res[1], x[1]); \
|
||||
name##_vf(&res[2], x[2]); \
|
||||
} \
|
||||
ccl_device_extern void name##_dvdff( \
|
||||
ccl_private float3 *res, ccl_private const float *x, float y) \
|
||||
{ \
|
||||
name##_vff(&res[0], x[0], y); \
|
||||
name##_vff(&res[1], x[1], y); \
|
||||
name##_vff(&res[2], x[2], y); \
|
||||
} \
|
||||
ccl_device_extern void name##_dvfdf( \
|
||||
ccl_private float3 *res, float x, ccl_private const float *y) \
|
||||
{ \
|
||||
name##_vff(&res[0], x, y[0]); \
|
||||
name##_vff(&res[1], x, y[1]); \
|
||||
name##_vff(&res[2], x, y[2]); \
|
||||
} \
|
||||
ccl_device_extern void name##_dvdfdf( \
|
||||
ccl_private float3 *res, ccl_private const float *x, ccl_private const float *y) \
|
||||
{ \
|
||||
name##_vff(&res[0], x[0], y[0]); \
|
||||
name##_vff(&res[1], x[1], y[1]); \
|
||||
name##_vff(&res[2], x[2], y[2]); \
|
||||
} \
|
||||
ccl_device_extern void name##_dvdv(ccl_private float3 *res, ccl_private const float3 *v) \
|
||||
{ \
|
||||
name##_vv(&res[0], &v[0]); \
|
||||
name##_vv(&res[1], &v[1]); \
|
||||
name##_vv(&res[2], &v[2]); \
|
||||
} \
|
||||
ccl_device_extern void name##_dvdvf( \
|
||||
ccl_private float3 *res, ccl_private const float3 *v, float w) \
|
||||
{ \
|
||||
name##_vvf(&res[0], &v[0], w); \
|
||||
name##_vvf(&res[1], &v[1], w); \
|
||||
name##_vvf(&res[2], &v[2], w); \
|
||||
} \
|
||||
ccl_device_extern void name##_dvvdf( \
|
||||
ccl_private float3 *res, ccl_private const float3 *v, ccl_private const float *w) \
|
||||
{ \
|
||||
name##_vvf(&res[0], v, w[0]); \
|
||||
name##_vvf(&res[1], v, w[1]); \
|
||||
name##_vvf(&res[2], v, w[2]); \
|
||||
} \
|
||||
ccl_device_extern void name##_dvdvdf( \
|
||||
ccl_private float3 *res, ccl_private const float3 *v, ccl_private const float *w) \
|
||||
{ \
|
||||
name##_vvf(&res[0], &v[0], w[0]); \
|
||||
name##_vvf(&res[1], &v[1], w[1]); \
|
||||
name##_vvf(&res[2], &v[2], w[2]); \
|
||||
}
|
||||
|
||||
ccl_device_forceinline float hashnoise_1d(float p)
|
||||
|
|
|
@ -152,10 +152,12 @@ LightTreeBucket operator+(const LightTreeBucket &a, const LightTreeBucket &b);
|
|||
struct LightTreeNode {
|
||||
LightTreeMeasure measure;
|
||||
uint bit_trail;
|
||||
int num_emitters = -1; /* The number of emitters a leaf node stores. A negative number indicates
|
||||
it is an inner node. */
|
||||
int first_emitter_index; /* Leaf nodes contain an index to first emitter. */
|
||||
unique_ptr<LightTreeNode> children[2]; /* Inner node has two children. */
|
||||
/* The number of emitters a leaf node stores. A negative number indicates it is an inner node. */
|
||||
int num_emitters = -1;
|
||||
/* Leaf nodes contain an index to first emitter. */
|
||||
int first_emitter_index;
|
||||
/* Inner node has two children. */
|
||||
unique_ptr<LightTreeNode> children[2];
|
||||
|
||||
LightTreeNode() = default;
|
||||
|
||||
|
|
|
@ -703,8 +703,11 @@ string OSLCompiler::id(ShaderNode *node)
|
|||
{
|
||||
/* assign layer unique name based on pointer address + bump mode */
|
||||
stringstream stream;
|
||||
stream.imbue(std::locale("C")); /* Ensure that no grouping characters (e.g. commas with en_US
|
||||
locale) are added to the pointer string */
|
||||
|
||||
/* Ensure that no grouping characters (e.g. commas with en_US locale)
|
||||
* are added to the pointer string. */
|
||||
stream.imbue(std::locale("C"));
|
||||
|
||||
stream << "node_" << node->type->name << "_" << node;
|
||||
|
||||
return stream.str();
|
||||
|
|
|
@ -214,8 +214,8 @@ void deinterlace_line_inplace(
|
|||
}
|
||||
|
||||
/* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
|
||||
top field is copied as is, but the bottom field is deinterlaced
|
||||
against the top field. */
|
||||
* top field is copied as is, but the bottom field is deinterlaced
|
||||
* against the top field. */
|
||||
FFMPEG_INLINE
|
||||
void deinterlace_bottom_field(
|
||||
uint8_t *dst, int dst_wrap, const uint8_t *src1, int src_wrap, int width, int height)
|
||||
|
|
|
@ -911,6 +911,27 @@ extern char *GHOST_getClipboard(bool selection);
|
|||
*/
|
||||
extern void GHOST_putClipboard(const char *buffer, bool selection);
|
||||
|
||||
/**
|
||||
* Returns GHOST_kSuccess if the clipboard contains an image.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_hasClipboardImage(void);
|
||||
|
||||
/**
|
||||
* Get image data from the Clipboard
|
||||
* \param r_width: the returned image width in pixels.
|
||||
* \param r_height: the returned image height in pixels.
|
||||
* \return pointer uint array in RGBA byte order. Caller must free.
|
||||
*/
|
||||
extern uint *GHOST_getClipboardImage(int *r_width, int *r_height);
|
||||
|
||||
/**
|
||||
* Put image data to the Clipboard
|
||||
* \param rgba: uint array in RGBA byte order.
|
||||
* \param width: the image width in pixels.
|
||||
* \param height: the image height in pixels.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_putClipboardImage(uint *rgba, int width, int height);
|
||||
|
||||
/**
|
||||
* Set the Console State
|
||||
* \param action: console state
|
||||
|
|
|
@ -471,6 +471,27 @@ class GHOST_ISystem {
|
|||
*/
|
||||
virtual void putClipboard(const char *buffer, bool selection) const = 0;
|
||||
|
||||
/**
|
||||
* Returns GHOST_kSuccess if the clipboard contains an image.
|
||||
*/
|
||||
virtual GHOST_TSuccess hasClipboardImage(void) const = 0;
|
||||
|
||||
/**
|
||||
* Get image data from the Clipboard
|
||||
* \param r_width: the returned image width in pixels.
|
||||
* \param r_height: the returned image height in pixels.
|
||||
* \return pointer uint array in RGBA byte order. Caller must free.
|
||||
*/
|
||||
virtual uint *getClipboardImage(int *r_width, int *r_height) const = 0;
|
||||
|
||||
/**
|
||||
* Put image data to the Clipboard
|
||||
* \param rgba: uint array in RGBA byte order.
|
||||
* \param width: the image width in pixels.
|
||||
* \param height: the image height in pixels.
|
||||
*/
|
||||
virtual GHOST_TSuccess putClipboardImage(uint *rgba, int width, int height) const = 0;
|
||||
|
||||
/***************************************************************************************
|
||||
* System Message Box.
|
||||
***************************************************************************************/
|
||||
|
|
|
@ -883,6 +883,24 @@ void GHOST_putClipboard(const char *buffer, bool selection)
|
|||
system->putClipboard(buffer, selection);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_hasClipboardImage(void)
|
||||
{
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
return system->hasClipboardImage();
|
||||
}
|
||||
|
||||
uint *GHOST_getClipboardImage(int *r_width, int *r_height)
|
||||
{
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
return system->getClipboardImage(r_width, r_height);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_putClipboardImage(uint *rgba, int width, int height)
|
||||
{
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
return system->putClipboardImage(rgba, width, height);
|
||||
}
|
||||
|
||||
bool GHOST_setConsoleWindowState(GHOST_TConsoleWindowState action)
|
||||
{
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
|
|
|
@ -42,6 +42,23 @@ GHOST_System::~GHOST_System()
|
|||
exit();
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_System::hasClipboardImage(void) const
|
||||
{
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
uint *GHOST_System::getClipboardImage(int * /*r_width*/, int * /*r_height*/) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_System::putClipboardImage(uint * /*rgba*/,
|
||||
int /*width*/,
|
||||
int /*height*/) const
|
||||
{
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
uint64_t GHOST_System::getMilliSeconds() const
|
||||
{
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
|
|
|
@ -330,6 +330,27 @@ class GHOST_System : public GHOST_ISystem {
|
|||
*/
|
||||
virtual void putClipboard(const char *buffer, bool selection) const = 0;
|
||||
|
||||
/**
|
||||
* Returns GHOST_kSuccess if the clipboard contains an image.
|
||||
*/
|
||||
GHOST_TSuccess hasClipboardImage(void) const;
|
||||
|
||||
/**
|
||||
* Get image data from the Clipboard
|
||||
* \param r_width: the returned image width in pixels.
|
||||
* \param r_height: the returned image height in pixels.
|
||||
* \return pointer uint array in RGBA byte order. Caller must free.
|
||||
*/
|
||||
uint *getClipboardImage(int *r_width, int *r_height) const;
|
||||
|
||||
/**
|
||||
* Put image data to the Clipboard
|
||||
* \param rgba: uint array in RGBA byte order.
|
||||
* \param width: the image width in pixels.
|
||||
* \param height: the image height in pixels.
|
||||
*/
|
||||
GHOST_TSuccess putClipboardImage(uint *rgba, int width, int height) const;
|
||||
|
||||
/**
|
||||
* Show a system message box
|
||||
* \param title: The title of the message box.
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#include "utf_winfunc.h"
|
||||
#include "utfconv.h"
|
||||
|
||||
#include "IMB_imbuf.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "GHOST_DisplayManagerWin32.hh"
|
||||
#include "GHOST_EventButton.hh"
|
||||
#include "GHOST_EventCursor.hh"
|
||||
|
@ -2305,6 +2308,257 @@ void GHOST_SystemWin32::putClipboard(const char *buffer, bool selection) const
|
|||
}
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SystemWin32::hasClipboardImage(void) const
|
||||
{
|
||||
if (IsClipboardFormatAvailable(CF_DIBV5) ||
|
||||
IsClipboardFormatAvailable(RegisterClipboardFormat("PNG"))) {
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
static uint *getClipboardImageDibV5(int *r_width, int *r_height)
|
||||
{
|
||||
HANDLE hGlobal = GetClipboardData(CF_DIBV5);
|
||||
if (hGlobal == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BITMAPV5HEADER *bitmapV5Header = (BITMAPV5HEADER *)GlobalLock(hGlobal);
|
||||
if (bitmapV5Header == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int offset = bitmapV5Header->bV5Size + bitmapV5Header->bV5ClrUsed * sizeof(RGBQUAD);
|
||||
|
||||
if (bitmapV5Header->bV5Compression == BI_BITFIELDS) {
|
||||
offset += 12;
|
||||
}
|
||||
BYTE *buffer = (BYTE *)bitmapV5Header + offset;
|
||||
int bitcount = bitmapV5Header->bV5BitCount;
|
||||
int width = bitmapV5Header->bV5Width;
|
||||
int height = bitmapV5Header->bV5Height;
|
||||
*r_width = width;
|
||||
*r_height = height;
|
||||
|
||||
DWORD ColorMasks[4];
|
||||
ColorMasks[0] = bitmapV5Header->bV5RedMask ? bitmapV5Header->bV5RedMask : 0xff;
|
||||
ColorMasks[1] = bitmapV5Header->bV5GreenMask ? bitmapV5Header->bV5GreenMask : 0xff00;
|
||||
ColorMasks[2] = bitmapV5Header->bV5BlueMask ? bitmapV5Header->bV5BlueMask : 0xff0000;
|
||||
ColorMasks[3] = bitmapV5Header->bV5AlphaMask ? bitmapV5Header->bV5AlphaMask : 0xff000000;
|
||||
|
||||
/* Bit shifts needed for the ColorMasks. */
|
||||
DWORD ColorShifts[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
_BitScanForward(&ColorShifts[i], ColorMasks[i]);
|
||||
}
|
||||
|
||||
uchar *source = (uchar *)buffer;
|
||||
uint *rgba = (uint *)malloc(width * height * 4);
|
||||
uint8_t *target = (uint8_t *)rgba;
|
||||
|
||||
if (bitmapV5Header->bV5Compression == BI_BITFIELDS && bitcount == 32) {
|
||||
for (int h = 0; h < height; h++) {
|
||||
for (int w = 0; w < width; w++, target += 4, source += 4) {
|
||||
DWORD *pix = (DWORD *)source;
|
||||
target[0] = uint8_t((*pix & ColorMasks[0]) >> ColorShifts[0]);
|
||||
target[1] = uint8_t((*pix & ColorMasks[1]) >> ColorShifts[1]);
|
||||
target[2] = uint8_t((*pix & ColorMasks[2]) >> ColorShifts[2]);
|
||||
target[3] = uint8_t((*pix & ColorMasks[3]) >> ColorShifts[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bitmapV5Header->bV5Compression == BI_RGB && bitcount == 32) {
|
||||
for (int h = 0; h < height; h++) {
|
||||
for (int w = 0; w < width; w++, target += 4, source += 4) {
|
||||
RGBQUAD *quad = (RGBQUAD *)source;
|
||||
target[0] = uint8_t(quad->rgbRed);
|
||||
target[1] = uint8_t(quad->rgbGreen);
|
||||
target[2] = uint8_t(quad->rgbBlue);
|
||||
target[3] = (bitmapV5Header->bV5AlphaMask) ? uint8_t(quad->rgbReserved) : 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bitmapV5Header->bV5Compression == BI_RGB && bitcount == 24) {
|
||||
int bytes_per_row = ((((width * bitcount) + 31) & ~31) >> 3);
|
||||
int slack = bytes_per_row - (width * 3);
|
||||
for (int h = 0; h < height; h++, source += slack) {
|
||||
for (int w = 0; w < width; w++, target += 4, source += 3) {
|
||||
RGBTRIPLE *triple = (RGBTRIPLE *)source;
|
||||
target[0] = uint8_t(triple->rgbtRed);
|
||||
target[1] = uint8_t(triple->rgbtGreen);
|
||||
target[2] = uint8_t(triple->rgbtBlue);
|
||||
target[3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GlobalUnlock(hGlobal);
|
||||
return rgba;
|
||||
}
|
||||
|
||||
/* Works with any image format that ImBuf can load. */
|
||||
static uint *getClipboardImageImBuf(int *r_width, int *r_height, UINT format)
|
||||
{
|
||||
HANDLE hGlobal = GetClipboardData(format);
|
||||
if (hGlobal == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LPVOID pMem = GlobalLock(hGlobal);
|
||||
if (!pMem) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint *rgba = nullptr;
|
||||
|
||||
ImBuf *ibuf = IMB_ibImageFromMemory(
|
||||
(uchar *)pMem, GlobalSize(hGlobal), IB_rect, nullptr, "<clipboard>");
|
||||
|
||||
if (ibuf) {
|
||||
*r_width = ibuf->x;
|
||||
*r_height = ibuf->y;
|
||||
rgba = (uint *)malloc(4 * ibuf->x * ibuf->y);
|
||||
memcpy(rgba, ibuf->rect, 4 * ibuf->x * ibuf->y);
|
||||
IMB_freeImBuf(ibuf);
|
||||
}
|
||||
|
||||
GlobalUnlock(hGlobal);
|
||||
return rgba;
|
||||
}
|
||||
|
||||
uint *GHOST_SystemWin32::getClipboardImage(int *r_width, int *r_height) const
|
||||
{
|
||||
if (!OpenClipboard(nullptr)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Synthesized formats are placed after posted formats. */
|
||||
UINT cfPNG = RegisterClipboardFormat("PNG");
|
||||
UINT format = 0;
|
||||
for (int cf = EnumClipboardFormats(0); cf; cf = EnumClipboardFormats(cf)) {
|
||||
if (ELEM(cf, CF_DIBV5, cfPNG)) {
|
||||
format = cf;
|
||||
}
|
||||
if (cf == CF_DIBV5 || (cf == CF_BITMAP && format == cfPNG)) {
|
||||
break; /* Favor CF_DIBV5, but not if synthesized. */
|
||||
}
|
||||
}
|
||||
|
||||
uint *rgba = nullptr;
|
||||
|
||||
if (format == CF_DIBV5) {
|
||||
rgba = getClipboardImageDibV5(r_width, r_height);
|
||||
}
|
||||
else if (format == cfPNG) {
|
||||
rgba = getClipboardImageImBuf(r_width, r_height, cfPNG);
|
||||
}
|
||||
else {
|
||||
*r_width = 0;
|
||||
*r_height = 0;
|
||||
}
|
||||
|
||||
CloseClipboard();
|
||||
return rgba;
|
||||
}
|
||||
|
||||
static bool putClipboardImageDibV5(uint *rgba, int width, int height)
|
||||
{
|
||||
DWORD size_pixels = width * height * 4;
|
||||
|
||||
/* Pixel data is 12 bytes after the header. */
|
||||
HGLOBAL hMem = GlobalAlloc(GHND, sizeof(BITMAPV5HEADER) + 12 + size_pixels);
|
||||
if (!hMem) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BITMAPV5HEADER *hdr = (BITMAPV5HEADER *)GlobalLock(hMem);
|
||||
if (!hdr) {
|
||||
GlobalFree(hMem);
|
||||
return false;
|
||||
}
|
||||
|
||||
hdr->bV5Size = sizeof(BITMAPV5HEADER);
|
||||
hdr->bV5Width = width;
|
||||
hdr->bV5Height = height;
|
||||
hdr->bV5Planes = 1;
|
||||
hdr->bV5BitCount = 32;
|
||||
hdr->bV5SizeImage = size_pixels;
|
||||
hdr->bV5Compression = BI_BITFIELDS;
|
||||
hdr->bV5RedMask = 0x000000ff;
|
||||
hdr->bV5GreenMask = 0x0000ff00;
|
||||
hdr->bV5BlueMask = 0x00ff0000;
|
||||
hdr->bV5AlphaMask = 0xff000000;
|
||||
hdr->bV5CSType = LCS_sRGB;
|
||||
hdr->bV5Intent = LCS_GM_IMAGES;
|
||||
hdr->bV5ClrUsed = 0;
|
||||
|
||||
memcpy((char *)hdr + sizeof(BITMAPV5HEADER) + 12, rgba, size_pixels);
|
||||
|
||||
GlobalUnlock(hMem);
|
||||
|
||||
if (!SetClipboardData(CF_DIBV5, hMem)) {
|
||||
GlobalFree(hMem);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool putClipboardImagePNG(uint *rgba, int width, int height)
|
||||
{
|
||||
UINT cf = RegisterClipboardFormat("PNG");
|
||||
|
||||
/* Load buffer into ImBuf, convert to PNG. */
|
||||
ImBuf *ibuf = IMB_allocFromBuffer(rgba, nullptr, width, height, 32);
|
||||
ibuf->ftype = IMB_FTYPE_PNG;
|
||||
ibuf->foptions.quality = 15;
|
||||
if (!IMB_saveiff(ibuf, "<memory>", IB_rect | IB_mem)) {
|
||||
IMB_freeImBuf(ibuf);
|
||||
return false;
|
||||
}
|
||||
|
||||
HGLOBAL hMem = GlobalAlloc(GHND, ibuf->encodedbuffersize);
|
||||
if (!hMem) {
|
||||
IMB_freeImBuf(ibuf);
|
||||
return false;
|
||||
}
|
||||
|
||||
LPVOID pMem = GlobalLock(hMem);
|
||||
if (!pMem) {
|
||||
IMB_freeImBuf(ibuf);
|
||||
GlobalFree(hMem);
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(pMem, ibuf->encodedbuffer, ibuf->encodedbuffersize);
|
||||
|
||||
GlobalUnlock(hMem);
|
||||
IMB_freeImBuf(ibuf);
|
||||
|
||||
if (!SetClipboardData(cf, hMem)) {
|
||||
GlobalFree(hMem);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SystemWin32::putClipboardImage(uint *rgba, int width, int height) const
|
||||
{
|
||||
if (!OpenClipboard(nullptr) || !EmptyClipboard()) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
bool ok = putClipboardImageDibV5(rgba, width, height) &&
|
||||
putClipboardImagePNG(rgba, width, height);
|
||||
|
||||
CloseClipboard();
|
||||
|
||||
return (ok) ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Message Box
|
||||
* \{ */
|
||||
|
|
|
@ -215,6 +215,27 @@ class GHOST_SystemWin32 : public GHOST_System {
|
|||
*/
|
||||
void putClipboard(const char *buffer, bool selection) const;
|
||||
|
||||
/**
|
||||
* Returns GHOST_kSuccess if the clipboard contains an image.
|
||||
*/
|
||||
GHOST_TSuccess hasClipboardImage(void) const;
|
||||
|
||||
/**
|
||||
* Get image data from the Clipboard
|
||||
* \param r_width: the returned image width in pixels.
|
||||
* \param r_height: the returned image height in pixels.
|
||||
* \return pointer uint array in RGBA byte order. Caller must free.
|
||||
*/
|
||||
uint *getClipboardImage(int *r_width, int *r_height) const;
|
||||
|
||||
/**
|
||||
* Put image data to the Clipboard
|
||||
* \param rgba: uint array in RGBA byte order.
|
||||
* \param width: the image width in pixels.
|
||||
* \param height: the image height in pixels.
|
||||
*/
|
||||
GHOST_TSuccess putClipboardImage(uint *rgba, int width, int height) const;
|
||||
|
||||
/**
|
||||
* Show a system message box
|
||||
* \param title: The title of the message box.
|
||||
|
|
|
@ -93,7 +93,7 @@ def write_sysinfo(filepath):
|
|||
output.write("\t%r\n" % p)
|
||||
output.write("datafiles: %r\n" % (bpy.utils.user_resource('DATAFILES')))
|
||||
output.write("config: %r\n" % (bpy.utils.user_resource('CONFIG')))
|
||||
output.write("scripts : %r\n" % (bpy.utils.user_resource('SCRIPTS')))
|
||||
output.write("scripts: %r\n" % (bpy.utils.user_resource('SCRIPTS')))
|
||||
output.write("autosave: %r\n" % (bpy.utils.user_resource('AUTOSAVE')))
|
||||
output.write("tempdir: %r\n" % (bpy.app.tempdir))
|
||||
|
||||
|
@ -123,7 +123,7 @@ def write_sysinfo(filepath):
|
|||
output.write("OpenColorIO: ")
|
||||
if ocio.supported:
|
||||
if ocio.version_string == "fallback":
|
||||
output.write("Blender was built with OpenColorIO, " +
|
||||
output.write("Blender was built with OpenColorIO, "
|
||||
"but it currently uses fallback color management.\n")
|
||||
else:
|
||||
output.write("%s\n" % (ocio.version_string))
|
||||
|
|
|
@ -7,8 +7,7 @@ class CONSOLE_HT_header(Header):
|
|||
bl_space_type = 'CONSOLE'
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout.row()
|
||||
|
||||
layout = self.layout
|
||||
layout.template_header()
|
||||
|
||||
CONSOLE_MT_editor_menus.draw_collapsible(context, layout)
|
||||
|
|
|
@ -184,6 +184,8 @@ class IMAGE_MT_image(Menu):
|
|||
bl_label = "Image"
|
||||
|
||||
def draw(self, context):
|
||||
import sys
|
||||
|
||||
layout = self.layout
|
||||
|
||||
sima = context.space_data
|
||||
|
@ -207,6 +209,11 @@ class IMAGE_MT_image(Menu):
|
|||
|
||||
layout.separator()
|
||||
|
||||
if sys.platform[:3] == "win":
|
||||
layout.operator("image.clipboard_copy", text="Copy")
|
||||
layout.operator("image.clipboard_paste", text="Paste")
|
||||
layout.separator()
|
||||
|
||||
if ima:
|
||||
layout.operator("image.save", text="Save", icon='FILE_TICK')
|
||||
layout.operator("image.save_as", text="Save As...")
|
||||
|
|
|
@ -31,21 +31,44 @@ def generate_from_enum_ex(
|
|||
type,
|
||||
attr,
|
||||
cursor='DEFAULT',
|
||||
tooldef_keywords={},
|
||||
exclude_filter={},
|
||||
tooldef_keywords=None,
|
||||
icon_map=None,
|
||||
use_separators=True,
|
||||
):
|
||||
if tooldef_keywords is None:
|
||||
tooldef_keywords = {}
|
||||
|
||||
tool_defs = []
|
||||
for enum in type.bl_rna.properties[attr].enum_items_static:
|
||||
name = enum.name
|
||||
idname = enum.identifier
|
||||
if idname in exclude_filter:
|
||||
continue
|
||||
|
||||
enum_items = getattr(
|
||||
type.bl_rna.properties[attr],
|
||||
"enum_items_static_ui" if use_separators else
|
||||
"enum_items_static",
|
||||
)
|
||||
|
||||
for enum in enum_items:
|
||||
if use_separators:
|
||||
if not (name := enum.name):
|
||||
# Empty string for a UI Separator.
|
||||
tool_defs.append(None)
|
||||
continue
|
||||
if not (idname := enum.identifier):
|
||||
# This is a heading, there is no purpose in showing headings here.
|
||||
continue
|
||||
else:
|
||||
name = enum.name
|
||||
idname = enum.identifier
|
||||
|
||||
icon = icon_prefix + idname.lower()
|
||||
if icon_map is not None:
|
||||
icon = icon_map.get(icon, icon)
|
||||
|
||||
tool_defs.append(
|
||||
ToolDef.from_dict(
|
||||
dict(
|
||||
idname=idname_prefix + name,
|
||||
label=name,
|
||||
icon=icon_prefix + idname.lower(),
|
||||
icon=icon,
|
||||
cursor=cursor,
|
||||
data_block=idname,
|
||||
**tooldef_keywords,
|
||||
|
@ -1316,6 +1339,9 @@ class _defs_sculpt:
|
|||
icon_prefix="brush.sculpt.",
|
||||
type=bpy.types.Brush,
|
||||
attr="sculpt_tool",
|
||||
# TODO(@ideasman42): we may want to enable this,
|
||||
# it causes awkward grouping with 2x column button layout.
|
||||
use_separators=False,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
|
@ -2326,103 +2352,18 @@ class _defs_gpencil_weight:
|
|||
|
||||
class _defs_curves_sculpt:
|
||||
|
||||
@ToolDef.from_fn
|
||||
def selection_paint():
|
||||
return dict(
|
||||
idname="builtin_brush.selection_paint",
|
||||
label="Selection Paint",
|
||||
icon="ops.generic.select_paint",
|
||||
data_block="SELECTION_PAINT",
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def comb():
|
||||
return dict(
|
||||
idname="builtin_brush.comb",
|
||||
label="Comb",
|
||||
icon="ops.curves.sculpt_comb",
|
||||
data_block='COMB',
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def add():
|
||||
return dict(
|
||||
idname="builtin_brush.add",
|
||||
label="Add",
|
||||
icon="ops.curves.sculpt_add",
|
||||
data_block='ADD',
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def delete():
|
||||
return dict(
|
||||
idname="builtin_brush.delete",
|
||||
label="Delete",
|
||||
icon="ops.curves.sculpt_delete",
|
||||
data_block='DELETE',
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def snake_hook():
|
||||
return dict(
|
||||
idname="builtin_brush.snake_hook",
|
||||
label="Snake Hook",
|
||||
icon="ops.curves.sculpt_snake_hook",
|
||||
data_block='SNAKE_HOOK',
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def grow_shrink():
|
||||
return dict(
|
||||
idname="builtin_brush.grow_shrink",
|
||||
label="Grow/Shrink",
|
||||
icon="ops.curves.sculpt_grow_shrink",
|
||||
data_block='GROW_SHRINK',
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def pinch():
|
||||
return dict(
|
||||
idname="builtin_brush.pinch",
|
||||
label="Pinch",
|
||||
icon="ops.curves.sculpt_pinch",
|
||||
data_block='PINCH',
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def smooth():
|
||||
return dict(
|
||||
idname="builtin_brush.smooth",
|
||||
label="Smooth",
|
||||
icon="ops.curves.sculpt_smooth",
|
||||
data_block='SMOOTH',
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def puff():
|
||||
return dict(
|
||||
idname="builtin_brush.puff",
|
||||
label="Puff",
|
||||
icon="ops.curves.sculpt_puff",
|
||||
data_block='PUFF',
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def density():
|
||||
return dict(
|
||||
idname="builtin_brush.density",
|
||||
label="Density",
|
||||
icon="ops.curves.sculpt_density",
|
||||
data_block="DENSITY",
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def slide():
|
||||
return dict(
|
||||
idname="builtin_brush.slide",
|
||||
label="Slide",
|
||||
icon="ops.curves.sculpt_slide",
|
||||
data_block="SLIDE",
|
||||
@staticmethod
|
||||
def generate_from_brushes(context):
|
||||
return generate_from_enum_ex(
|
||||
context,
|
||||
idname_prefix="builtin_brush.",
|
||||
icon_prefix="ops.curves.sculpt_",
|
||||
type=bpy.types.Brush,
|
||||
attr="curves_sculpt_tool",
|
||||
icon_map={
|
||||
# Use the generic icon for selection painting.
|
||||
"ops.curves.sculpt_selection_paint": "ops.generic.select_paint",
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
|
@ -3193,19 +3134,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
|
|||
),
|
||||
],
|
||||
'SCULPT_CURVES': [
|
||||
_defs_curves_sculpt.selection_paint,
|
||||
None,
|
||||
_defs_curves_sculpt.add,
|
||||
_defs_curves_sculpt.delete,
|
||||
_defs_curves_sculpt.density,
|
||||
None,
|
||||
_defs_curves_sculpt.comb,
|
||||
_defs_curves_sculpt.snake_hook,
|
||||
_defs_curves_sculpt.grow_shrink,
|
||||
_defs_curves_sculpt.pinch,
|
||||
_defs_curves_sculpt.puff,
|
||||
_defs_curves_sculpt.smooth,
|
||||
_defs_curves_sculpt.slide,
|
||||
_defs_curves_sculpt.generate_from_brushes,
|
||||
None,
|
||||
*_tools_annotate,
|
||||
],
|
||||
|
|
|
@ -147,7 +147,7 @@ add_subdirectory(imbuf)
|
|||
add_subdirectory(imbuf/intern/oiio)
|
||||
add_subdirectory(nodes)
|
||||
add_subdirectory(modifiers)
|
||||
add_subdirectory(gpencil_modifiers)
|
||||
add_subdirectory(gpencil_modifiers_legacy)
|
||||
add_subdirectory(sequencer)
|
||||
add_subdirectory(shader_fx)
|
||||
add_subdirectory(io)
|
||||
|
|
|
@ -802,7 +802,6 @@ class CustomDataAttributes {
|
|||
|
||||
std::optional<blender::GMutableSpan> get_for_write(const AttributeIDRef &attribute_id);
|
||||
bool create(const AttributeIDRef &attribute_id, eCustomDataType data_type);
|
||||
bool create_by_move(const AttributeIDRef &attribute_id, eCustomDataType data_type, void *buffer);
|
||||
bool remove(const AttributeIDRef &attribute_id);
|
||||
|
||||
bool foreach_attribute(const AttributeForeachCallback callback, eAttrDomain domain) const;
|
||||
|
|
|
@ -23,6 +23,7 @@ inline void convert_to_static_type(const CPPType &cpp_type, const Func &func)
|
|||
float2,
|
||||
float3,
|
||||
int,
|
||||
int2,
|
||||
bool,
|
||||
int8_t,
|
||||
ColorGeometry4f,
|
||||
|
@ -68,6 +69,11 @@ template<> inline int mix2(const float factor, const int &a, const int &b)
|
|||
return int(std::round((1.0f - factor) * a + factor * b));
|
||||
}
|
||||
|
||||
template<> inline int2 mix2(const float factor, const int2 &a, const int2 &b)
|
||||
{
|
||||
return math::interpolate(a, b, factor);
|
||||
}
|
||||
|
||||
template<> inline float mix2(const float factor, const float &a, const float &b)
|
||||
{
|
||||
return (1.0f - factor) * a + factor * b;
|
||||
|
@ -121,6 +127,11 @@ template<> inline int mix3(const float3 &weights, const int &v0, const int &v1,
|
|||
return int(std::round(weights.x * v0 + weights.y * v1 + weights.z * v2));
|
||||
}
|
||||
|
||||
template<> inline int2 mix3(const float3 &weights, const int2 &v0, const int2 &v1, const int2 &v2)
|
||||
{
|
||||
return int2(weights.x * float2(v0) + weights.y * float2(v1) + weights.z * float2(v2));
|
||||
}
|
||||
|
||||
template<>
|
||||
inline float mix3(const float3 &weights, const float &v0, const float &v1, const float &v2)
|
||||
{
|
||||
|
@ -194,6 +205,14 @@ inline int mix4(const float4 &weights, const int &v0, const int &v1, const int &
|
|||
return int(std::round(weights.x * v0 + weights.y * v1 + weights.z * v2 + weights.w * v3));
|
||||
}
|
||||
|
||||
template<>
|
||||
inline int2 mix4(
|
||||
const float4 &weights, const int2 &v0, const int2 &v1, const int2 &v2, const int2 &v3)
|
||||
{
|
||||
return int2(weights.x * float2(v0) + weights.y * float2(v1) + weights.z * float2(v2) +
|
||||
weights.w * float2(v3));
|
||||
}
|
||||
|
||||
template<>
|
||||
inline float mix4(
|
||||
const float4 &weights, const float &v0, const float &v1, const float &v2, const float &v3)
|
||||
|
@ -382,7 +401,7 @@ class SimpleMixerWithAccumulationType {
|
|||
private:
|
||||
struct Item {
|
||||
/* Store both values together, because they are accessed together. */
|
||||
AccumulationT value = {0};
|
||||
AccumulationT value = AccumulationT(0);
|
||||
float weight = 0.0f;
|
||||
};
|
||||
|
||||
|
@ -517,6 +536,15 @@ template<> struct DefaultMixerStruct<int> {
|
|||
* uses double instead of float so that it is accurate for all 32 bit integers. */
|
||||
using type = SimpleMixerWithAccumulationType<int, double, double_to_int>;
|
||||
};
|
||||
template<> struct DefaultMixerStruct<int2> {
|
||||
static int2 double_to_int(const double2 &value)
|
||||
{
|
||||
return int2(math::round(value));
|
||||
}
|
||||
/* Store interpolated ints in a double temporarily, so that weights are handled correctly. It
|
||||
* uses double instead of float so that it is accurate for all 32 bit integers. */
|
||||
using type = SimpleMixerWithAccumulationType<int2, double2, double_to_int>;
|
||||
};
|
||||
template<> struct DefaultMixerStruct<bool> {
|
||||
static bool float_to_bool(const float &value)
|
||||
{
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_implicit_sharing.h"
|
||||
#include "BLI_sys_types.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#ifdef __cplusplus
|
||||
|
@ -74,14 +75,8 @@ extern const CustomData_MeshMasks CD_MASK_EVERYTHING;
|
|||
|
||||
/** Add/copy/merge allocation types. */
|
||||
typedef enum eCDAllocType {
|
||||
/** Use the data pointer. */
|
||||
CD_ASSIGN = 0,
|
||||
/** Allocate and set to default, which is usually just zeroed memory. */
|
||||
CD_SET_DEFAULT = 2,
|
||||
/** Use data pointers, set layer flag NOFREE. */
|
||||
CD_REFERENCE = 3,
|
||||
/** Do a full copy of all layers, only allowed if source has same number of elements. */
|
||||
CD_DUPLICATE = 4,
|
||||
/**
|
||||
* Default construct new layer values. Does nothing for trivial types. This should be used
|
||||
* if all layer values will be set by the caller after creating the layer.
|
||||
|
@ -158,28 +153,43 @@ void CustomData_data_multiply(eCustomDataType type, void *data, float fac);
|
|||
void CustomData_data_add(eCustomDataType type, void *data1, const void *data2);
|
||||
|
||||
/**
|
||||
* Initializes a CustomData object with the same layer setup as source.
|
||||
* mask is a bit-field where `(mask & (1 << (layer type)))` indicates
|
||||
* if a layer should be copied or not. alloctype must be one of the above.
|
||||
* Initializes a CustomData object with the same layer setup as source. `mask` is a bit-field where
|
||||
* `(mask & (1 << (layer type)))` indicates if a layer should be copied or not. Data layers using
|
||||
* implicit-sharing will not actually be copied but will be shared between source and destination.
|
||||
*/
|
||||
void CustomData_copy(const struct CustomData *source,
|
||||
struct CustomData *dest,
|
||||
eCustomDataMask mask,
|
||||
eCDAllocType alloctype,
|
||||
int totelem);
|
||||
/**
|
||||
* Initializes a CustomData object with the same layers as source. The data is not copied from the
|
||||
* source. Instead, the new layers are initialized using the given `alloctype`.
|
||||
*/
|
||||
void CustomData_copy_layout(const struct CustomData *source,
|
||||
struct CustomData *dest,
|
||||
eCustomDataMask mask,
|
||||
eCDAllocType alloctype,
|
||||
int totelem);
|
||||
|
||||
/* BMESH_TODO, not really a public function but readfile.c needs it */
|
||||
void CustomData_update_typemap(struct CustomData *data);
|
||||
|
||||
/**
|
||||
* Same as the above, except that this will preserve existing layers, and only
|
||||
* add the layers that were not there yet.
|
||||
* Copies all layers from source to destination that don't exist there yet.
|
||||
*/
|
||||
bool CustomData_merge(const struct CustomData *source,
|
||||
struct CustomData *dest,
|
||||
eCustomDataMask mask,
|
||||
eCDAllocType alloctype,
|
||||
int totelem);
|
||||
/**
|
||||
* Copies all layers from source to destination that don't exist there yet. The layer data is not
|
||||
* copied. Instead the newly created layers are initialized using the given `alloctype`.
|
||||
*/
|
||||
bool CustomData_merge_layout(const struct CustomData *source,
|
||||
struct CustomData *dest,
|
||||
eCustomDataMask mask,
|
||||
eCDAllocType alloctype,
|
||||
int totelem);
|
||||
|
||||
/**
|
||||
* Reallocate custom data to a new element count. If the new size is larger, the new values use
|
||||
|
@ -189,16 +199,16 @@ bool CustomData_merge(const struct CustomData *source,
|
|||
void CustomData_realloc(struct CustomData *data, int old_size, int new_size);
|
||||
|
||||
/**
|
||||
* BMesh version of CustomData_merge; merges the layouts of source and `dest`,
|
||||
* BMesh version of CustomData_merge_layout; merges the layouts of source and `dest`,
|
||||
* then goes through the mesh and makes sure all the custom-data blocks are
|
||||
* consistent with the new layout.
|
||||
*/
|
||||
bool CustomData_bmesh_merge(const struct CustomData *source,
|
||||
struct CustomData *dest,
|
||||
eCustomDataMask mask,
|
||||
eCDAllocType alloctype,
|
||||
struct BMesh *bm,
|
||||
char htype);
|
||||
bool CustomData_bmesh_merge_layout(const struct CustomData *source,
|
||||
struct CustomData *dest,
|
||||
eCustomDataMask mask,
|
||||
eCDAllocType alloctype,
|
||||
struct BMesh *bm,
|
||||
char htype);
|
||||
|
||||
/**
|
||||
* Remove layers that aren't stored in BMesh or are stored as flags on BMesh.
|
||||
|
@ -229,18 +239,25 @@ void CustomData_free_typemask(struct CustomData *data, int totelem, eCustomDataM
|
|||
void CustomData_free_temporary(struct CustomData *data, int totelem);
|
||||
|
||||
/**
|
||||
* Adds a data layer of the given type to the #CustomData object, optionally
|
||||
* backed by an external data array. the different allocation types are
|
||||
* defined above. returns the data of the layer.
|
||||
* Adds a layer of the given type to the #CustomData object. The new layer is initialized based on
|
||||
* the given alloctype.
|
||||
* \return The layer data.
|
||||
*/
|
||||
void *CustomData_add_layer(struct CustomData *data,
|
||||
eCustomDataType type,
|
||||
eCDAllocType alloctype,
|
||||
int totelem);
|
||||
|
||||
/**
|
||||
* Adds a layer of the given type to the #CustomData object. The new layer takes ownership of the
|
||||
* passed in `layer_data`. If a #ImplicitSharingInfoHandle is passed in, its user count is
|
||||
* increased.
|
||||
*/
|
||||
const void *CustomData_add_layer_with_data(struct CustomData *data,
|
||||
eCustomDataType type,
|
||||
void *layer_data,
|
||||
int totelem);
|
||||
int totelem,
|
||||
const ImplicitSharingInfoHandle *sharing_info);
|
||||
|
||||
/**
|
||||
* Same as above but accepts a name.
|
||||
|
@ -250,17 +267,26 @@ void *CustomData_add_layer_named(struct CustomData *data,
|
|||
eCDAllocType alloctype,
|
||||
int totelem,
|
||||
const char *name);
|
||||
|
||||
const void *CustomData_add_layer_named_with_data(struct CustomData *data,
|
||||
eCustomDataType type,
|
||||
void *layer_data,
|
||||
int totelem,
|
||||
const char *name);
|
||||
const char *name,
|
||||
const ImplicitSharingInfoHandle *sharing_info);
|
||||
|
||||
void *CustomData_add_layer_anonymous(struct CustomData *data,
|
||||
eCustomDataType type,
|
||||
eCDAllocType alloctype,
|
||||
void *layer,
|
||||
int totelem,
|
||||
const AnonymousAttributeIDHandle *anonymous_id);
|
||||
const void *CustomData_add_layer_anonymous_with_data(
|
||||
struct CustomData *data,
|
||||
eCustomDataType type,
|
||||
const AnonymousAttributeIDHandle *anonymous_id,
|
||||
int totelem,
|
||||
void *layer_data,
|
||||
const ImplicitSharingInfoHandle *sharing_info);
|
||||
|
||||
/**
|
||||
* Frees the active or first data layer with the give type.
|
||||
|
@ -296,11 +322,6 @@ int CustomData_number_of_layers(const struct CustomData *data, eCustomDataType t
|
|||
int CustomData_number_of_anonymous_layers(const struct CustomData *data, eCustomDataType type);
|
||||
int CustomData_number_of_layers_typemask(const struct CustomData *data, eCustomDataMask mask);
|
||||
|
||||
/**
|
||||
* Duplicate all the layers with flag NOFREE, and remove the flag from duplicated layers.
|
||||
*/
|
||||
void CustomData_duplicate_referenced_layers(CustomData *data, int totelem);
|
||||
|
||||
/**
|
||||
* Set the #CD_FLAG_NOCOPY flag in custom data layers where the mask is
|
||||
* zero for the layer type, so only layer types specified by the mask will be copied
|
||||
|
|
|
@ -54,37 +54,45 @@ enum {
|
|||
* This means callback shall not *do* anything, only use this as informative data if it needs it.
|
||||
*/
|
||||
IDWALK_CB_EMBEDDED = (1 << 4),
|
||||
/**
|
||||
* That ID pointer points to an embedded ID, but does not own it.
|
||||
*
|
||||
* E.g the `collection` pointer of the first ViewLayerCollection of a ViewLayer should always
|
||||
* point to the scene's master collection, which is an embedded ID 'owned' by
|
||||
* `Scene.master_collection`.
|
||||
*/
|
||||
IDWALK_CB_EMBEDDED_NOT_OWNING = (1 << 5),
|
||||
|
||||
/**
|
||||
* That ID is not really used by its owner, it's just an internal hint/helper.
|
||||
* This marks the 'from' pointers issue, like Key->from.
|
||||
* How to handle that kind of cases totally depends on what caller code is doing... */
|
||||
IDWALK_CB_LOOPBACK = (1 << 5),
|
||||
IDWALK_CB_LOOPBACK = (1 << 6),
|
||||
|
||||
/** That ID is used as library override's reference by its owner. */
|
||||
IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE = (1 << 6),
|
||||
IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE = (1 << 7),
|
||||
|
||||
/** That ID pointer is not overridable. */
|
||||
IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE = (1 << 7),
|
||||
IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE = (1 << 8),
|
||||
|
||||
/**
|
||||
* Indicates that this is an internal runtime ID pointer, like e.g. `ID.newid` or `ID.original`.
|
||||
* \note Those should be ignored in most cases, and won't be processed/generated anyway unless
|
||||
* `IDWALK_DO_INTERNAL_RUNTIME_POINTERS` option is enabled.
|
||||
*/
|
||||
IDWALK_CB_INTERNAL = (1 << 8),
|
||||
IDWALK_CB_INTERNAL = (1 << 9),
|
||||
|
||||
/**
|
||||
* This ID usage is fully refcounted.
|
||||
* Callback is responsible to deal accordingly with #ID.us if needed.
|
||||
*/
|
||||
IDWALK_CB_USER = (1 << 9),
|
||||
IDWALK_CB_USER = (1 << 10),
|
||||
/**
|
||||
* This ID usage is not refcounted, but at least one user should be generated by it (to avoid
|
||||
* e.g. losing the used ID on save/reload).
|
||||
* Callback is responsible to deal accordingly with #ID.us if needed.
|
||||
*/
|
||||
IDWALK_CB_USER_ONE = (1 << 10),
|
||||
IDWALK_CB_USER_ONE = (1 << 11),
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -123,7 +131,9 @@ typedef int (*LibraryIDLinkCallback)(LibraryIDLinkCallbackData *cb_data);
|
|||
/* Flags for the foreach function itself. */
|
||||
enum {
|
||||
IDWALK_NOP = 0,
|
||||
/** The callback will never modify the ID pointers it processes. */
|
||||
/** The callback will never modify the ID pointers it processes.
|
||||
* WARNING: It is very important to pass this flag when valid, as it can lead to important
|
||||
* optimizations and debug/assert code. */
|
||||
IDWALK_READONLY = (1 << 0),
|
||||
/** Recurse into 'descendant' IDs.
|
||||
* Each ID is only processed once. Order of ID processing is not guaranteed.
|
||||
|
|
|
@ -562,8 +562,6 @@ void BKE_pbvh_update_hide_attributes_from_mesh(PBVH *pbvh);
|
|||
|
||||
void BKE_pbvh_face_sets_color_set(PBVH *pbvh, int seed, int color_default);
|
||||
|
||||
void BKE_pbvh_respect_hide_set(PBVH *pbvh, bool respect_hide);
|
||||
|
||||
/* Vertex Deformer. */
|
||||
|
||||
float (*BKE_pbvh_vert_coords_alloc(struct PBVH *pbvh))[3];
|
||||
|
@ -591,7 +589,6 @@ typedef struct PBVHVertexIter {
|
|||
int i;
|
||||
int index;
|
||||
PBVHVertRef vertex;
|
||||
bool respect_hide;
|
||||
|
||||
/* grid */
|
||||
struct CCGKey key;
|
||||
|
@ -664,14 +661,9 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
|
|||
} \
|
||||
} \
|
||||
else if (vi.vert_positions) { \
|
||||
if (vi.respect_hide) { \
|
||||
vi.visible = !(vi.hide_vert && vi.hide_vert[vi.vert_indices[vi.gx]]); \
|
||||
if (mode == PBVH_ITER_UNIQUE && !vi.visible) { \
|
||||
continue; \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
BLI_assert(vi.visible); \
|
||||
vi.visible = !(vi.hide_vert && vi.hide_vert[vi.vert_indices[vi.gx]]); \
|
||||
if (mode == PBVH_ITER_UNIQUE && !vi.visible) { \
|
||||
continue; \
|
||||
} \
|
||||
vi.co = vi.vert_positions[vi.vert_indices[vi.gx]]; \
|
||||
vi.no = vi.vert_normals[vi.vert_indices[vi.gx]]; \
|
||||
|
|
|
@ -13,6 +13,10 @@
|
|||
# include "BLI_bounds_types.hh"
|
||||
# include "BLI_math_vector_types.hh"
|
||||
# include "BLI_shared_cache.hh"
|
||||
|
||||
# include "DNA_pointcloud_types.h"
|
||||
|
||||
# include "BKE_customdata.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -45,6 +49,21 @@ struct PointCloudRuntime {
|
|||
};
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
inline blender::Span<blender::float3> PointCloud::positions() const
|
||||
{
|
||||
return {static_cast<const blender::float3 *>(
|
||||
CustomData_get_layer_named(&this->pdata, CD_PROP_FLOAT3, "position")),
|
||||
this->totpoint};
|
||||
}
|
||||
|
||||
inline blender::MutableSpan<blender::float3> PointCloud::positions_for_write()
|
||||
{
|
||||
return {static_cast<blender::float3 *>(CustomData_get_layer_named_for_write(
|
||||
&this->pdata, CD_PROP_FLOAT3, "position", this->totpoint)),
|
||||
this->totpoint};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void *BKE_pointcloud_add(struct Main *bmain, const char *name);
|
||||
|
|
|
@ -12,7 +12,7 @@ set(INC
|
|||
../depsgraph
|
||||
../draw
|
||||
../functions
|
||||
../gpencil_modifiers
|
||||
../gpencil_modifiers_legacy
|
||||
../gpu
|
||||
../ikplugin
|
||||
../imbuf
|
||||
|
@ -525,7 +525,7 @@ set(LIB
|
|||
bf_depsgraph
|
||||
bf_draw
|
||||
bf_functions
|
||||
bf_gpencil_modifiers
|
||||
bf_gpencil_modifiers_legacy
|
||||
bf_gpu
|
||||
bf_ikplugin
|
||||
bf_imbuf
|
||||
|
|
|
@ -207,11 +207,12 @@ void DM_from_template(DerivedMesh *dm,
|
|||
int numPolys)
|
||||
{
|
||||
const CustomData_MeshMasks *mask = &CD_MASK_DERIVEDMESH;
|
||||
CustomData_copy(&source->vertData, &dm->vertData, mask->vmask, CD_SET_DEFAULT, numVerts);
|
||||
CustomData_copy(&source->edgeData, &dm->edgeData, mask->emask, CD_SET_DEFAULT, numEdges);
|
||||
CustomData_copy(&source->faceData, &dm->faceData, mask->fmask, CD_SET_DEFAULT, numTessFaces);
|
||||
CustomData_copy(&source->loopData, &dm->loopData, mask->lmask, CD_SET_DEFAULT, numLoops);
|
||||
CustomData_copy(&source->polyData, &dm->polyData, mask->pmask, CD_SET_DEFAULT, numPolys);
|
||||
CustomData_copy_layout(&source->vertData, &dm->vertData, mask->vmask, CD_SET_DEFAULT, numVerts);
|
||||
CustomData_copy_layout(&source->edgeData, &dm->edgeData, mask->emask, CD_SET_DEFAULT, numEdges);
|
||||
CustomData_copy_layout(
|
||||
&source->faceData, &dm->faceData, mask->fmask, CD_SET_DEFAULT, numTessFaces);
|
||||
CustomData_copy_layout(&source->loopData, &dm->loopData, mask->lmask, CD_SET_DEFAULT, numLoops);
|
||||
CustomData_copy_layout(&source->polyData, &dm->polyData, mask->pmask, CD_SET_DEFAULT, numPolys);
|
||||
dm->poly_offsets = static_cast<int *>(MEM_dupallocN(source->poly_offsets));
|
||||
|
||||
dm->type = type;
|
||||
|
|
|
@ -92,17 +92,19 @@ static int attribute_data_type_complexity(const eCustomDataType data_type)
|
|||
return 2;
|
||||
case CD_PROP_FLOAT:
|
||||
return 3;
|
||||
case CD_PROP_FLOAT2:
|
||||
case CD_PROP_INT32_2D:
|
||||
return 4;
|
||||
case CD_PROP_FLOAT3:
|
||||
case CD_PROP_FLOAT2:
|
||||
return 5;
|
||||
case CD_PROP_BYTE_COLOR:
|
||||
case CD_PROP_FLOAT3:
|
||||
return 6;
|
||||
case CD_PROP_COLOR:
|
||||
case CD_PROP_BYTE_COLOR:
|
||||
return 7;
|
||||
case CD_PROP_COLOR:
|
||||
return 8;
|
||||
#if 0 /* These attribute types are not supported yet. */
|
||||
case CD_PROP_STRING:
|
||||
return 6;
|
||||
return 9;
|
||||
#endif
|
||||
default:
|
||||
/* Only accept "generic" custom data types used by the attribute system. */
|
||||
|
@ -201,13 +203,16 @@ static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data
|
|||
return true;
|
||||
}
|
||||
case AttributeInit::Type::MoveArray: {
|
||||
void *source_data = static_cast<const AttributeInitMoveArray &>(initializer).data;
|
||||
const void *data = CustomData_add_layer_with_data(
|
||||
&custom_data, data_type, source_data, domain_num);
|
||||
if (data == nullptr) {
|
||||
MEM_freeN(source_data);
|
||||
void *src_data = static_cast<const AttributeInitMoveArray &>(initializer).data;
|
||||
const void *stored_data = CustomData_add_layer_with_data(
|
||||
&custom_data, data_type, src_data, domain_num, nullptr);
|
||||
if (stored_data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (stored_data != src_data) {
|
||||
MEM_freeN(src_data);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -230,25 +235,26 @@ static void *add_generic_custom_data_layer(CustomData &custom_data,
|
|||
}
|
||||
const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id();
|
||||
return CustomData_add_layer_anonymous(
|
||||
&custom_data, data_type, alloctype, nullptr, domain_size, &anonymous_id);
|
||||
&custom_data, data_type, alloctype, domain_size, &anonymous_id);
|
||||
}
|
||||
|
||||
static const void *add_generic_custom_data_layer_with_existing_data(
|
||||
CustomData &custom_data,
|
||||
const eCustomDataType data_type,
|
||||
void *layer_data,
|
||||
const AttributeIDRef &attribute_id,
|
||||
const int domain_size,
|
||||
const AttributeIDRef &attribute_id)
|
||||
void *layer_data,
|
||||
const ImplicitSharingInfo *sharing_info)
|
||||
{
|
||||
if (!attribute_id.is_anonymous()) {
|
||||
char attribute_name_c[MAX_CUSTOMDATA_LAYER_NAME];
|
||||
attribute_id.name().copy(attribute_name_c);
|
||||
return CustomData_add_layer_named_with_data(
|
||||
&custom_data, data_type, layer_data, domain_size, attribute_name_c);
|
||||
if (attribute_id.is_anonymous()) {
|
||||
const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id();
|
||||
return CustomData_add_layer_anonymous_with_data(
|
||||
&custom_data, data_type, &anonymous_id, domain_size, layer_data, sharing_info);
|
||||
}
|
||||
const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id();
|
||||
return CustomData_add_layer_anonymous(
|
||||
&custom_data, data_type, CD_ASSIGN, layer_data, domain_size, &anonymous_id);
|
||||
char attribute_name_c[MAX_CUSTOMDATA_LAYER_NAME];
|
||||
attribute_id.name().copy(attribute_name_c);
|
||||
return CustomData_add_layer_named_with_data(
|
||||
&custom_data, data_type, layer_data, domain_size, attribute_name_c, sharing_info);
|
||||
}
|
||||
|
||||
static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attribute_id,
|
||||
|
@ -279,9 +285,9 @@ static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr
|
|||
break;
|
||||
}
|
||||
case AttributeInit::Type::MoveArray: {
|
||||
void *source_data = static_cast<const AttributeInitMoveArray &>(initializer).data;
|
||||
void *data = static_cast<const AttributeInitMoveArray &>(initializer).data;
|
||||
add_generic_custom_data_layer_with_existing_data(
|
||||
custom_data, data_type, source_data, domain_num, attribute_id);
|
||||
custom_data, data_type, attribute_id, domain_num, data, nullptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -571,7 +577,7 @@ CustomDataAttributes::~CustomDataAttributes()
|
|||
CustomDataAttributes::CustomDataAttributes(const CustomDataAttributes &other)
|
||||
{
|
||||
size_ = other.size_;
|
||||
CustomData_copy(&other.data, &data, CD_MASK_ALL, CD_DUPLICATE, size_);
|
||||
CustomData_copy(&other.data, &data, CD_MASK_ALL, size_);
|
||||
}
|
||||
|
||||
CustomDataAttributes::CustomDataAttributes(CustomDataAttributes &&other)
|
||||
|
@ -655,15 +661,6 @@ bool CustomDataAttributes::create(const AttributeIDRef &attribute_id,
|
|||
return result != nullptr;
|
||||
}
|
||||
|
||||
bool CustomDataAttributes::create_by_move(const AttributeIDRef &attribute_id,
|
||||
const eCustomDataType data_type,
|
||||
void *buffer)
|
||||
{
|
||||
const void *result = add_generic_custom_data_layer_with_existing_data(
|
||||
data, data_type, buffer, size_, attribute_id);
|
||||
return result != nullptr;
|
||||
}
|
||||
|
||||
bool CustomDataAttributes::remove(const AttributeIDRef &attribute_id)
|
||||
{
|
||||
for (const int i : IndexRange(data.totlayer)) {
|
||||
|
|
|
@ -923,8 +923,8 @@ static int foreach_libblock_link_append_callback(LibraryIDLinkCallbackData *cb_d
|
|||
{
|
||||
/* NOTE: It is important to also skip liboverride references here, as those should never be made
|
||||
* local. */
|
||||
if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_INTERNAL | IDWALK_CB_LOOPBACK |
|
||||
IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) {
|
||||
if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_EMBEDDED_NOT_OWNING | IDWALK_CB_INTERNAL |
|
||||
IDWALK_CB_LOOPBACK | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) {
|
||||
return IDWALK_RET_NOP;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "BKE_editmesh.h"
|
||||
#include "BKE_mesh.hh"
|
||||
#include "BKE_mesh_runtime.h"
|
||||
#include "BKE_pointcloud.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
|
@ -1425,10 +1426,7 @@ BVHTree *BKE_bvhtree_from_pointcloud_get(BVHTreeFromPointCloud *data,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
blender::bke::AttributeAccessor attributes = pointcloud->attributes();
|
||||
blender::VArraySpan<blender::float3> positions = attributes.lookup_or_default<blender::float3>(
|
||||
"position", ATTR_DOMAIN_POINT, blender::float3(0));
|
||||
|
||||
const Span<float3> positions = pointcloud->positions();
|
||||
for (const int i : positions.index_range()) {
|
||||
BLI_bvhtree_insert(tree, i, positions[i], 1);
|
||||
}
|
||||
|
|
|
@ -147,9 +147,7 @@ static CDDerivedMesh *cdDM_create(const char *desc)
|
|||
return cddm;
|
||||
}
|
||||
|
||||
static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
|
||||
eCDAllocType alloctype,
|
||||
const CustomData_MeshMasks *mask)
|
||||
static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh, const CustomData_MeshMasks *mask)
|
||||
{
|
||||
CDDerivedMesh *cddm = cdDM_create(__func__);
|
||||
DerivedMesh *dm = &cddm->dm;
|
||||
|
@ -167,15 +165,14 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
|
|||
mesh->totloop,
|
||||
mesh->totpoly);
|
||||
|
||||
CustomData_merge(&mesh->vdata, &dm->vertData, cddata_masks.vmask, alloctype, mesh->totvert);
|
||||
CustomData_merge(&mesh->edata, &dm->edgeData, cddata_masks.emask, alloctype, mesh->totedge);
|
||||
CustomData_merge(&mesh->vdata, &dm->vertData, cddata_masks.vmask, mesh->totvert);
|
||||
CustomData_merge(&mesh->edata, &dm->edgeData, cddata_masks.emask, mesh->totedge);
|
||||
CustomData_merge(&mesh->fdata,
|
||||
&dm->faceData,
|
||||
cddata_masks.fmask | CD_MASK_ORIGINDEX,
|
||||
alloctype,
|
||||
0 /* `mesh->totface` */);
|
||||
CustomData_merge(&mesh->ldata, &dm->loopData, cddata_masks.lmask, alloctype, mesh->totloop);
|
||||
CustomData_merge(&mesh->pdata, &dm->polyData, cddata_masks.pmask, alloctype, mesh->totpoly);
|
||||
CustomData_merge(&mesh->ldata, &dm->loopData, cddata_masks.lmask, mesh->totloop);
|
||||
CustomData_merge(&mesh->pdata, &dm->polyData, cddata_masks.pmask, mesh->totpoly);
|
||||
|
||||
cddm->vert_positions = static_cast<float(*)[3]>(CustomData_get_layer_named_for_write(
|
||||
&dm->vertData, CD_PROP_FLOAT3, "position", mesh->totvert));
|
||||
|
@ -203,5 +200,5 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
|
|||
|
||||
DerivedMesh *CDDM_from_mesh(Mesh *mesh)
|
||||
{
|
||||
return cdDM_from_mesh_ex(mesh, CD_REFERENCE, &CD_MASK_MESH);
|
||||
return cdDM_from_mesh_ex(mesh, &CD_MASK_MESH);
|
||||
}
|
||||
|
|
|
@ -62,45 +62,18 @@ static void curves_init_data(ID *id)
|
|||
new (&curves->geometry) blender::bke::CurvesGeometry();
|
||||
}
|
||||
|
||||
static void curves_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int flag)
|
||||
static void curves_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int /*flag*/)
|
||||
{
|
||||
using namespace blender;
|
||||
|
||||
Curves *curves_dst = (Curves *)id_dst;
|
||||
const Curves *curves_src = (const Curves *)id_src;
|
||||
curves_dst->mat = static_cast<Material **>(MEM_dupallocN(curves_src->mat));
|
||||
|
||||
const bke::CurvesGeometry &src = curves_src->geometry.wrap();
|
||||
bke::CurvesGeometry &dst = curves_dst->geometry.wrap();
|
||||
|
||||
/* We need special handling here because the generic ID management code has already done a
|
||||
* shallow copy from the source to the destination, and because the copy-on-write functionality
|
||||
* isn't supported more generically yet. */
|
||||
|
||||
dst.point_num = src.point_num;
|
||||
dst.curve_num = src.curve_num;
|
||||
|
||||
const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
|
||||
CustomData_copy(&src.point_data, &dst.point_data, CD_MASK_ALL, alloc_type, dst.point_num);
|
||||
CustomData_copy(&src.curve_data, &dst.curve_data, CD_MASK_ALL, alloc_type, dst.curve_num);
|
||||
|
||||
dst.curve_offsets = static_cast<int *>(MEM_dupallocN(src.curve_offsets));
|
||||
new (&curves_dst->geometry) blender::bke::CurvesGeometry(curves_src->geometry.wrap());
|
||||
|
||||
if (curves_src->surface_uv_map != nullptr) {
|
||||
curves_dst->surface_uv_map = BLI_strdup(curves_src->surface_uv_map);
|
||||
}
|
||||
|
||||
dst.runtime = MEM_new<bke::CurvesGeometryRuntime>(__func__);
|
||||
|
||||
dst.runtime->type_counts = src.runtime->type_counts;
|
||||
dst.runtime->evaluated_offsets_cache = src.runtime->evaluated_offsets_cache;
|
||||
dst.runtime->nurbs_basis_cache = src.runtime->nurbs_basis_cache;
|
||||
dst.runtime->evaluated_position_cache = src.runtime->evaluated_position_cache;
|
||||
dst.runtime->bounds_cache = src.runtime->bounds_cache;
|
||||
dst.runtime->evaluated_length_cache = src.runtime->evaluated_length_cache;
|
||||
dst.runtime->evaluated_tangent_cache = src.runtime->evaluated_tangent_cache;
|
||||
dst.runtime->evaluated_normal_cache = src.runtime->evaluated_normal_cache;
|
||||
|
||||
curves_dst->batch_cache = nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -80,8 +80,8 @@ static void copy_curves_geometry(CurvesGeometry &dst, const CurvesGeometry &src)
|
|||
CustomData_free(&dst.curve_data, dst.curve_num);
|
||||
dst.point_num = src.point_num;
|
||||
dst.curve_num = src.curve_num;
|
||||
CustomData_copy(&src.point_data, &dst.point_data, CD_MASK_ALL, CD_DUPLICATE, dst.point_num);
|
||||
CustomData_copy(&src.curve_data, &dst.curve_data, CD_MASK_ALL, CD_DUPLICATE, dst.curve_num);
|
||||
CustomData_copy(&src.point_data, &dst.point_data, CD_MASK_ALL, dst.point_num);
|
||||
CustomData_copy(&src.curve_data, &dst.curve_data, CD_MASK_ALL, dst.curve_num);
|
||||
|
||||
MEM_SAFE_FREE(dst.curve_offsets);
|
||||
dst.curve_offsets = (int *)MEM_malloc_arrayN(dst.point_num + 1, sizeof(int), __func__);
|
||||
|
|
|
@ -101,11 +101,8 @@ void fill_points(const OffsetIndices<int> points_by_curve,
|
|||
bke::CurvesGeometry copy_only_curve_domain(const bke::CurvesGeometry &src_curves)
|
||||
{
|
||||
bke::CurvesGeometry dst_curves(0, src_curves.curves_num());
|
||||
CustomData_copy(&src_curves.curve_data,
|
||||
&dst_curves.curve_data,
|
||||
CD_MASK_ALL,
|
||||
CD_DUPLICATE,
|
||||
src_curves.curves_num());
|
||||
CustomData_copy(
|
||||
&src_curves.curve_data, &dst_curves.curve_data, CD_MASK_ALL, src_curves.curves_num());
|
||||
dst_curves.runtime->type_counts = src_curves.runtime->type_counts;
|
||||
return dst_curves;
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "data_transfer_intern.h"
|
||||
|
||||
using blender::float2;
|
||||
using blender::ImplicitSharingInfo;
|
||||
using blender::IndexRange;
|
||||
using blender::Set;
|
||||
using blender::Span;
|
||||
|
@ -1891,8 +1892,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
|||
{sizeof(float), "MFloatProperty", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
/* 45: CD_PROP_INT8 */
|
||||
{sizeof(int8_t), "MInt8Property", 1, N_("Int8"), nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
/* 46: CD_HAIRMAPPING */ /* UNUSED */
|
||||
{-1, "", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
/* 46: CD_PROP_INT32_2D */
|
||||
{sizeof(vec2i), "vec2i", 1, N_("Int 2D"), nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
/* 47: CD_PROP_COLOR */
|
||||
{sizeof(MPropCol),
|
||||
"MPropCol",
|
||||
|
@ -2158,12 +2159,14 @@ void customData_mask_layers__print(const CustomData_MeshMasks *mask)
|
|||
|
||||
static void customData_update_offsets(CustomData *data);
|
||||
|
||||
static CustomDataLayer *customData_add_layer__internal(CustomData *data,
|
||||
eCustomDataType type,
|
||||
eCDAllocType alloctype,
|
||||
void *layerdata,
|
||||
int totelem,
|
||||
const char *name);
|
||||
static CustomDataLayer *customData_add_layer__internal(
|
||||
CustomData *data,
|
||||
eCustomDataType type,
|
||||
std::optional<eCDAllocType> alloctype,
|
||||
void *layer_data_to_assign,
|
||||
const ImplicitSharingInfo *sharing_info_to_assign,
|
||||
int totelem,
|
||||
const char *name);
|
||||
|
||||
void CustomData_update_typemap(CustomData *data)
|
||||
{
|
||||
|
@ -2192,93 +2195,113 @@ static bool customdata_typemap_is_valid(const CustomData *data)
|
|||
}
|
||||
#endif
|
||||
|
||||
bool CustomData_merge(const CustomData *source,
|
||||
CustomData *dest,
|
||||
eCustomDataMask mask,
|
||||
eCDAllocType alloctype,
|
||||
int totelem)
|
||||
static void *copy_layer_data(const eCustomDataType type, const void *data, const int totelem)
|
||||
{
|
||||
const LayerTypeInfo &type_info = *layerType_getInfo(type);
|
||||
if (type_info.copy) {
|
||||
void *new_data = MEM_malloc_arrayN(size_t(totelem), type_info.size, __func__);
|
||||
type_info.copy(data, new_data, totelem);
|
||||
return new_data;
|
||||
}
|
||||
return MEM_dupallocN(data);
|
||||
}
|
||||
|
||||
static void free_layer_data(const eCustomDataType type, const void *data, const int totelem)
|
||||
{
|
||||
const LayerTypeInfo &type_info = *layerType_getInfo(type);
|
||||
if (type_info.free) {
|
||||
type_info.free(const_cast<void *>(data), totelem, type_info.size);
|
||||
}
|
||||
MEM_freeN(const_cast<void *>(data));
|
||||
}
|
||||
|
||||
static bool customdata_merge_internal(const CustomData *source,
|
||||
CustomData *dest,
|
||||
const eCustomDataMask mask,
|
||||
const std::optional<eCDAllocType> alloctype,
|
||||
const int totelem)
|
||||
{
|
||||
// const LayerTypeInfo *typeInfo;
|
||||
CustomDataLayer *layer, *newlayer;
|
||||
int lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0;
|
||||
int number = 0, maxnumber = -1;
|
||||
bool changed = false;
|
||||
|
||||
int last_type = -1;
|
||||
int last_active = 0;
|
||||
int last_render = 0;
|
||||
int last_clone = 0;
|
||||
int last_mask = 0;
|
||||
int current_type_layer_count = 0;
|
||||
int max_current_type_layer_count = -1;
|
||||
|
||||
for (int i = 0; i < source->totlayer; i++) {
|
||||
layer = &source->layers[i];
|
||||
// typeInfo = layerType_getInfo(eCustomDataType(layer->type)); /* UNUSED */
|
||||
const CustomDataLayer &src_layer = source->layers[i];
|
||||
const eCustomDataType type = eCustomDataType(src_layer.type);
|
||||
const int src_layer_flag = src_layer.flag;
|
||||
|
||||
const eCustomDataType type = eCustomDataType(layer->type);
|
||||
int flag = layer->flag;
|
||||
|
||||
if (type != lasttype) {
|
||||
number = 0;
|
||||
maxnumber = CustomData_layertype_layers_max(type);
|
||||
lastactive = layer->active;
|
||||
lastrender = layer->active_rnd;
|
||||
lastclone = layer->active_clone;
|
||||
lastmask = layer->active_mask;
|
||||
lasttype = type;
|
||||
if (type != last_type) {
|
||||
current_type_layer_count = 0;
|
||||
max_current_type_layer_count = CustomData_layertype_layers_max(type);
|
||||
last_active = src_layer.active;
|
||||
last_render = src_layer.active_rnd;
|
||||
last_clone = src_layer.active_clone;
|
||||
last_mask = src_layer.active_mask;
|
||||
last_type = type;
|
||||
}
|
||||
else {
|
||||
number++;
|
||||
current_type_layer_count++;
|
||||
}
|
||||
|
||||
if (flag & CD_FLAG_NOCOPY) {
|
||||
if (src_layer_flag & CD_FLAG_NOCOPY) {
|
||||
/* Don't merge this layer because it's not supposed to leave the source data. */
|
||||
continue;
|
||||
}
|
||||
if (!(mask & CD_TYPE_AS_MASK(type))) {
|
||||
/* Don't merge this layer because it does not match the type mask. */
|
||||
continue;
|
||||
}
|
||||
if ((maxnumber != -1) && (number >= maxnumber)) {
|
||||
if ((max_current_type_layer_count != -1) &&
|
||||
(current_type_layer_count >= max_current_type_layer_count)) {
|
||||
/* Don't merge this layer because the maximum amount of layers of this type is reached. */
|
||||
continue;
|
||||
}
|
||||
if (CustomData_get_named_layer_index(dest, type, layer->name) != -1) {
|
||||
if (CustomData_get_named_layer_index(dest, type, src_layer.name) != -1) {
|
||||
/* Don't merge this layer because it exists in the destination already. */
|
||||
continue;
|
||||
}
|
||||
|
||||
void *data;
|
||||
switch (alloctype) {
|
||||
case CD_ASSIGN:
|
||||
case CD_REFERENCE:
|
||||
case CD_DUPLICATE:
|
||||
data = layer->data;
|
||||
break;
|
||||
default:
|
||||
data = nullptr;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((alloctype == CD_ASSIGN) && (flag & CD_FLAG_NOFREE)) {
|
||||
newlayer = customData_add_layer__internal(
|
||||
dest, type, CD_REFERENCE, data, totelem, layer->name);
|
||||
}
|
||||
else {
|
||||
newlayer = customData_add_layer__internal(dest, type, alloctype, data, totelem, layer->name);
|
||||
}
|
||||
|
||||
if (newlayer) {
|
||||
newlayer->uid = layer->uid;
|
||||
|
||||
newlayer->active = lastactive;
|
||||
newlayer->active_rnd = lastrender;
|
||||
newlayer->active_clone = lastclone;
|
||||
newlayer->active_mask = lastmask;
|
||||
newlayer->flag |= flag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY);
|
||||
changed = true;
|
||||
|
||||
if (layer->anonymous_id != nullptr) {
|
||||
newlayer->anonymous_id = layer->anonymous_id;
|
||||
if (alloctype == CD_ASSIGN) {
|
||||
layer->anonymous_id = nullptr;
|
||||
void *layer_data_to_assign = nullptr;
|
||||
const ImplicitSharingInfo *sharing_info_to_assign = nullptr;
|
||||
if (!alloctype.has_value()) {
|
||||
if (src_layer.data != nullptr) {
|
||||
if (src_layer.sharing_info == nullptr) {
|
||||
/* Can't share the layer, duplicate it instead. */
|
||||
layer_data_to_assign = copy_layer_data(type, src_layer.data, totelem);
|
||||
}
|
||||
else {
|
||||
layer->anonymous_id->add_user();
|
||||
/* Share the layer. */
|
||||
layer_data_to_assign = src_layer.data;
|
||||
sharing_info_to_assign = src_layer.sharing_info;
|
||||
}
|
||||
}
|
||||
if (alloctype == CD_ASSIGN) {
|
||||
layer->data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
CustomDataLayer *new_layer = customData_add_layer__internal(dest,
|
||||
type,
|
||||
alloctype,
|
||||
layer_data_to_assign,
|
||||
sharing_info_to_assign,
|
||||
totelem,
|
||||
src_layer.name);
|
||||
|
||||
new_layer->uid = src_layer.uid;
|
||||
new_layer->flag |= src_layer_flag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY);
|
||||
new_layer->active = last_active;
|
||||
new_layer->active_rnd = last_render;
|
||||
new_layer->active_clone = last_clone;
|
||||
new_layer->active_mask = last_mask;
|
||||
changed = true;
|
||||
|
||||
if (src_layer.anonymous_id != nullptr) {
|
||||
new_layer->anonymous_id = src_layer.anonymous_id;
|
||||
new_layer->anonymous_id->add_user();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2286,6 +2309,23 @@ bool CustomData_merge(const CustomData *source,
|
|||
return changed;
|
||||
}
|
||||
|
||||
bool CustomData_merge(const CustomData *source,
|
||||
CustomData *dest,
|
||||
eCustomDataMask mask,
|
||||
int totelem)
|
||||
{
|
||||
return customdata_merge_internal(source, dest, mask, std::nullopt, totelem);
|
||||
}
|
||||
|
||||
bool CustomData_merge_layout(const CustomData *source,
|
||||
CustomData *dest,
|
||||
const eCustomDataMask mask,
|
||||
const eCDAllocType alloctype,
|
||||
const int totelem)
|
||||
{
|
||||
return customdata_merge_internal(source, dest, mask, alloctype, totelem);
|
||||
}
|
||||
|
||||
CustomData CustomData_shallow_copy_remove_non_bmesh_attributes(const CustomData *src,
|
||||
const eCustomDataMask mask)
|
||||
{
|
||||
|
@ -2311,28 +2351,91 @@ CustomData CustomData_shallow_copy_remove_non_bmesh_attributes(const CustomData
|
|||
return dst;
|
||||
}
|
||||
|
||||
/**
|
||||
* An #ImplicitSharingInfo that knows how to free the entire referenced custom data layer
|
||||
* (including potentially separately allocated chunks like for vertex groups).
|
||||
*/
|
||||
class CustomDataLayerImplicitSharing : public ImplicitSharingInfo {
|
||||
private:
|
||||
const void *data_;
|
||||
const int totelem_;
|
||||
const eCustomDataType type_;
|
||||
|
||||
public:
|
||||
CustomDataLayerImplicitSharing(const void *data, const int totelem, const eCustomDataType type)
|
||||
: ImplicitSharingInfo(1), data_(data), totelem_(totelem), type_(type)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
void delete_self_with_data() override
|
||||
{
|
||||
free_layer_data(type_, data_, totelem_);
|
||||
MEM_delete(this);
|
||||
}
|
||||
};
|
||||
|
||||
/** Create a #ImplicitSharingInfo that takes ownership of the data. */
|
||||
static ImplicitSharingInfo *make_implicit_sharing_info_for_layer(const eCustomDataType type,
|
||||
const void *data,
|
||||
const int totelem)
|
||||
{
|
||||
return MEM_new<CustomDataLayerImplicitSharing>(__func__, data, totelem, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the layer data is currently shared (hence it is immutable), create a copy that can be edited.
|
||||
*/
|
||||
static void ensure_layer_data_is_mutable(CustomDataLayer &layer, const int totelem)
|
||||
{
|
||||
if (layer.data == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (layer.sharing_info == nullptr) {
|
||||
/* Can not be shared without implicit-sharing data. */
|
||||
return;
|
||||
}
|
||||
if (layer.sharing_info->is_shared()) {
|
||||
const eCustomDataType type = eCustomDataType(layer.type);
|
||||
const void *old_data = layer.data;
|
||||
/* Copy the layer before removing the user because otherwise the data might be freed while
|
||||
* we're still copying from it here. */
|
||||
layer.data = copy_layer_data(type, old_data, totelem);
|
||||
layer.sharing_info->remove_user_and_delete_if_last();
|
||||
layer.sharing_info = make_implicit_sharing_info_for_layer(type, layer.data, totelem);
|
||||
}
|
||||
}
|
||||
|
||||
void CustomData_realloc(CustomData *data, const int old_size, const int new_size)
|
||||
{
|
||||
BLI_assert(new_size >= 0);
|
||||
for (int i = 0; i < data->totlayer; i++) {
|
||||
CustomDataLayer *layer = &data->layers[i];
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
|
||||
|
||||
const int64_t old_size_in_bytes = int64_t(old_size) * typeInfo->size;
|
||||
const int64_t new_size_in_bytes = int64_t(new_size) * typeInfo->size;
|
||||
if (layer->flag & CD_FLAG_NOFREE) {
|
||||
const void *old_data = layer->data;
|
||||
layer->data = MEM_malloc_arrayN(new_size, typeInfo->size, __func__);
|
||||
|
||||
void *new_layer_data = MEM_mallocN(new_size_in_bytes, __func__);
|
||||
/* Copy data to new array. */
|
||||
if (old_size_in_bytes) {
|
||||
if (typeInfo->copy) {
|
||||
typeInfo->copy(old_data, layer->data, std::min(old_size, new_size));
|
||||
typeInfo->copy(layer->data, new_layer_data, std::min(old_size, new_size));
|
||||
}
|
||||
else {
|
||||
std::memcpy(layer->data, old_data, std::min(old_size_in_bytes, new_size_in_bytes));
|
||||
BLI_assert(layer->data != nullptr);
|
||||
memcpy(new_layer_data, layer->data, std::min(old_size_in_bytes, new_size_in_bytes));
|
||||
}
|
||||
layer->flag &= ~CD_FLAG_NOFREE;
|
||||
}
|
||||
else {
|
||||
layer->data = MEM_reallocN(layer->data, new_size_in_bytes);
|
||||
/* Remove ownership of old array */
|
||||
if (layer->sharing_info) {
|
||||
layer->sharing_info->remove_user_and_delete_if_last();
|
||||
layer->sharing_info = nullptr;
|
||||
}
|
||||
/* Take ownership of new array. */
|
||||
layer->data = new_layer_data;
|
||||
if (layer->data) {
|
||||
layer->sharing_info = make_implicit_sharing_info_for_layer(
|
||||
eCustomDataType(layer->type), layer->data, new_size);
|
||||
}
|
||||
|
||||
if (new_size > old_size) {
|
||||
|
@ -2345,11 +2448,7 @@ void CustomData_realloc(CustomData *data, const int old_size, const int new_size
|
|||
}
|
||||
}
|
||||
|
||||
void CustomData_copy(const CustomData *source,
|
||||
CustomData *dest,
|
||||
eCustomDataMask mask,
|
||||
eCDAllocType alloctype,
|
||||
int totelem)
|
||||
void CustomData_copy(const CustomData *source, CustomData *dest, eCustomDataMask mask, int totelem)
|
||||
{
|
||||
CustomData_reset(dest);
|
||||
|
||||
|
@ -2357,28 +2456,40 @@ void CustomData_copy(const CustomData *source,
|
|||
dest->external = static_cast<CustomDataExternal *>(MEM_dupallocN(source->external));
|
||||
}
|
||||
|
||||
CustomData_merge(source, dest, mask, alloctype, totelem);
|
||||
CustomData_merge(source, dest, mask, totelem);
|
||||
}
|
||||
|
||||
void CustomData_copy_layout(const struct CustomData *source,
|
||||
struct CustomData *dest,
|
||||
eCustomDataMask mask,
|
||||
eCDAllocType alloctype,
|
||||
int totelem)
|
||||
{
|
||||
CustomData_reset(dest);
|
||||
|
||||
if (source->external) {
|
||||
dest->external = static_cast<CustomDataExternal *>(MEM_dupallocN(source->external));
|
||||
}
|
||||
|
||||
CustomData_merge_layout(source, dest, mask, alloctype, totelem);
|
||||
}
|
||||
|
||||
static void customData_free_layer__internal(CustomDataLayer *layer, const int totelem)
|
||||
{
|
||||
const LayerTypeInfo *typeInfo;
|
||||
|
||||
if (layer->anonymous_id != nullptr) {
|
||||
layer->anonymous_id->remove_user_and_delete_if_last();
|
||||
layer->anonymous_id = nullptr;
|
||||
}
|
||||
if (!(layer->flag & CD_FLAG_NOFREE) && layer->data) {
|
||||
typeInfo = layerType_getInfo(eCustomDataType(layer->type));
|
||||
|
||||
if (typeInfo->free) {
|
||||
typeInfo->free(layer->data, totelem, typeInfo->size);
|
||||
}
|
||||
|
||||
const eCustomDataType type = eCustomDataType(layer->type);
|
||||
if (layer->sharing_info == nullptr) {
|
||||
if (layer->data) {
|
||||
MEM_freeN(layer->data);
|
||||
free_layer_data(type, layer->data, totelem);
|
||||
}
|
||||
}
|
||||
else {
|
||||
layer->sharing_info->remove_user_and_delete_if_last();
|
||||
layer->sharing_info = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static void CustomData_external_free(CustomData *data)
|
||||
|
@ -2738,76 +2849,26 @@ static void customData_resize(CustomData *data, const int grow_amount)
|
|||
data->maxlayer += grow_amount;
|
||||
}
|
||||
|
||||
static CustomDataLayer *customData_add_layer__internal(CustomData *data,
|
||||
const eCustomDataType type,
|
||||
const eCDAllocType alloctype,
|
||||
void *layerdata,
|
||||
const int totelem,
|
||||
const char *name)
|
||||
static CustomDataLayer *customData_add_layer__internal(
|
||||
CustomData *data,
|
||||
const eCustomDataType type,
|
||||
const std::optional<eCDAllocType> alloctype,
|
||||
void *layer_data_to_assign,
|
||||
const ImplicitSharingInfo *sharing_info_to_assign,
|
||||
const int totelem,
|
||||
const char *name)
|
||||
{
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
||||
const LayerTypeInfo &type_info = *layerType_getInfo(type);
|
||||
int flag = 0;
|
||||
|
||||
/* Some layer types only support a single layer. */
|
||||
if (!typeInfo->defaultname && CustomData_has_layer(data, type)) {
|
||||
if (!type_info.defaultname && CustomData_has_layer(data, type)) {
|
||||
/* This function doesn't support dealing with existing layer data for these layer types when
|
||||
* the layer already exists. */
|
||||
BLI_assert(layerdata == nullptr);
|
||||
BLI_assert(layer_data_to_assign == nullptr);
|
||||
return &data->layers[CustomData_get_layer_index(data, type)];
|
||||
}
|
||||
|
||||
void *newlayerdata = nullptr;
|
||||
switch (alloctype) {
|
||||
case CD_SET_DEFAULT:
|
||||
if (totelem > 0) {
|
||||
if (typeInfo->set_default_value) {
|
||||
newlayerdata = MEM_malloc_arrayN(totelem, typeInfo->size, layerType_getName(type));
|
||||
typeInfo->set_default_value(newlayerdata, totelem);
|
||||
}
|
||||
else {
|
||||
newlayerdata = MEM_calloc_arrayN(totelem, typeInfo->size, layerType_getName(type));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CD_CONSTRUCT:
|
||||
if (totelem > 0) {
|
||||
newlayerdata = MEM_malloc_arrayN(totelem, typeInfo->size, layerType_getName(type));
|
||||
if (typeInfo->construct) {
|
||||
typeInfo->construct(newlayerdata, totelem);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CD_ASSIGN:
|
||||
if (totelem > 0) {
|
||||
BLI_assert(layerdata != nullptr);
|
||||
newlayerdata = layerdata;
|
||||
}
|
||||
else {
|
||||
MEM_SAFE_FREE(layerdata);
|
||||
}
|
||||
break;
|
||||
case CD_REFERENCE:
|
||||
if (totelem > 0) {
|
||||
BLI_assert(layerdata != nullptr);
|
||||
newlayerdata = layerdata;
|
||||
flag |= CD_FLAG_NOFREE;
|
||||
}
|
||||
break;
|
||||
case CD_DUPLICATE:
|
||||
if (totelem > 0) {
|
||||
newlayerdata = MEM_malloc_arrayN(totelem, typeInfo->size, layerType_getName(type));
|
||||
if (typeInfo->copy) {
|
||||
typeInfo->copy(layerdata, newlayerdata, totelem);
|
||||
}
|
||||
else {
|
||||
BLI_assert(layerdata != nullptr);
|
||||
BLI_assert(newlayerdata != nullptr);
|
||||
memcpy(newlayerdata, layerdata, totelem * typeInfo->size);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
int index = data->totlayer;
|
||||
if (index >= data->maxlayer) {
|
||||
customData_resize(data, CUSTOMDATA_GROW);
|
||||
|
@ -2815,7 +2876,7 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
|
|||
|
||||
data->totlayer++;
|
||||
|
||||
/* keep layers ordered by type */
|
||||
/* Keep layers ordered by type. */
|
||||
for (; index > 0 && data->layers[index - 1].type > type; index--) {
|
||||
data->layers[index] = data->layers[index - 1];
|
||||
}
|
||||
|
@ -2827,15 +2888,57 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
|
|||
* leaks into the new layer. */
|
||||
memset(&new_layer, 0, sizeof(CustomDataLayer));
|
||||
|
||||
if (alloctype.has_value()) {
|
||||
switch (*alloctype) {
|
||||
case CD_SET_DEFAULT: {
|
||||
if (totelem > 0) {
|
||||
if (type_info.set_default_value) {
|
||||
new_layer.data = MEM_malloc_arrayN(totelem, type_info.size, layerType_getName(type));
|
||||
type_info.set_default_value(new_layer.data, totelem);
|
||||
}
|
||||
else {
|
||||
new_layer.data = MEM_calloc_arrayN(totelem, type_info.size, layerType_getName(type));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CD_CONSTRUCT: {
|
||||
if (totelem > 0) {
|
||||
new_layer.data = MEM_malloc_arrayN(totelem, type_info.size, layerType_getName(type));
|
||||
if (type_info.construct) {
|
||||
type_info.construct(new_layer.data, totelem);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (totelem == 0 && sharing_info_to_assign == nullptr) {
|
||||
MEM_SAFE_FREE(layer_data_to_assign);
|
||||
}
|
||||
else {
|
||||
new_layer.data = layer_data_to_assign;
|
||||
new_layer.sharing_info = sharing_info_to_assign;
|
||||
if (new_layer.sharing_info) {
|
||||
new_layer.sharing_info->add_user();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (new_layer.data != nullptr && new_layer.sharing_info == nullptr) {
|
||||
/* Make layer data shareable. */
|
||||
new_layer.sharing_info = make_implicit_sharing_info_for_layer(type, new_layer.data, totelem);
|
||||
}
|
||||
|
||||
new_layer.type = type;
|
||||
new_layer.flag = flag;
|
||||
new_layer.data = newlayerdata;
|
||||
|
||||
/* Set default name if none exists. Note we only call DATA_() once
|
||||
* we know there is a default name, to avoid overhead of locale lookups
|
||||
* in the depsgraph. */
|
||||
if (!name && typeInfo->defaultname) {
|
||||
name = DATA_(typeInfo->defaultname);
|
||||
if (!name && type_info.defaultname) {
|
||||
name = DATA_(type_info.defaultname);
|
||||
}
|
||||
|
||||
if (name) {
|
||||
|
@ -2864,16 +2967,15 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
|
|||
return &data->layers[index];
|
||||
}
|
||||
|
||||
static void *customdata_add_layer(CustomData *data,
|
||||
const eCustomDataType type,
|
||||
eCDAllocType alloctype,
|
||||
void *layerdata,
|
||||
const int totelem)
|
||||
void *CustomData_add_layer(CustomData *data,
|
||||
const eCustomDataType type,
|
||||
eCDAllocType alloctype,
|
||||
const int totelem)
|
||||
{
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
||||
|
||||
CustomDataLayer *layer = customData_add_layer__internal(
|
||||
data, type, alloctype, layerdata, totelem, typeInfo->defaultname);
|
||||
data, type, alloctype, nullptr, nullptr, totelem, typeInfo->defaultname);
|
||||
CustomData_update_typemap(data);
|
||||
|
||||
if (layer) {
|
||||
|
@ -2883,31 +2985,16 @@ static void *customdata_add_layer(CustomData *data,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void *CustomData_add_layer(CustomData *data,
|
||||
const eCustomDataType type,
|
||||
const eCDAllocType alloctype,
|
||||
const int totelem)
|
||||
{
|
||||
return customdata_add_layer(data, type, alloctype, nullptr, totelem);
|
||||
}
|
||||
|
||||
const void *CustomData_add_layer_with_data(CustomData *data,
|
||||
const eCustomDataType type,
|
||||
void *layer_data,
|
||||
const int totelem)
|
||||
const int totelem,
|
||||
const ImplicitSharingInfo *sharing_info)
|
||||
{
|
||||
return customdata_add_layer(data, type, CD_ASSIGN, layer_data, totelem);
|
||||
}
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
||||
|
||||
static void *customdata_add_layer_named(CustomData *data,
|
||||
const eCustomDataType type,
|
||||
const eCDAllocType alloctype,
|
||||
void *layerdata,
|
||||
const int totelem,
|
||||
const char *name)
|
||||
{
|
||||
CustomDataLayer *layer = customData_add_layer__internal(
|
||||
data, type, alloctype, layerdata, totelem, name);
|
||||
data, type, std::nullopt, layer_data, sharing_info, totelem, typeInfo->defaultname);
|
||||
CustomData_update_typemap(data);
|
||||
|
||||
if (layer) {
|
||||
|
@ -2923,25 +3010,42 @@ void *CustomData_add_layer_named(CustomData *data,
|
|||
const int totelem,
|
||||
const char *name)
|
||||
{
|
||||
return customdata_add_layer_named(data, type, alloctype, nullptr, totelem, name);
|
||||
CustomDataLayer *layer = customData_add_layer__internal(
|
||||
data, type, alloctype, nullptr, nullptr, totelem, name);
|
||||
CustomData_update_typemap(data);
|
||||
|
||||
if (layer) {
|
||||
return layer->data;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const void *CustomData_add_layer_named_with_data(
|
||||
CustomData *data, const eCustomDataType type, void *layer_data, int totelem, const char *name)
|
||||
const void *CustomData_add_layer_named_with_data(CustomData *data,
|
||||
eCustomDataType type,
|
||||
void *layer_data,
|
||||
int totelem,
|
||||
const char *name,
|
||||
const ImplicitSharingInfo *sharing_info)
|
||||
{
|
||||
return customdata_add_layer_named(data, type, CD_ASSIGN, layer_data, totelem, name);
|
||||
CustomDataLayer *layer = customData_add_layer__internal(
|
||||
data, type, std::nullopt, layer_data, sharing_info, totelem, name);
|
||||
CustomData_update_typemap(data);
|
||||
|
||||
if (layer) {
|
||||
return layer->data;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void *CustomData_add_layer_anonymous(CustomData *data,
|
||||
const eCustomDataType type,
|
||||
const eCDAllocType alloctype,
|
||||
void *layerdata,
|
||||
const int totelem,
|
||||
const AnonymousAttributeIDHandle *anonymous_id)
|
||||
{
|
||||
const char *name = anonymous_id->name().c_str();
|
||||
CustomDataLayer *layer = customData_add_layer__internal(
|
||||
data, type, alloctype, layerdata, totelem, name);
|
||||
data, type, alloctype, nullptr, nullptr, totelem, name);
|
||||
CustomData_update_typemap(data);
|
||||
|
||||
if (layer == nullptr) {
|
||||
|
@ -2953,6 +3057,27 @@ void *CustomData_add_layer_anonymous(CustomData *data,
|
|||
return layer->data;
|
||||
}
|
||||
|
||||
const void *CustomData_add_layer_anonymous_with_data(
|
||||
CustomData *data,
|
||||
const eCustomDataType type,
|
||||
const AnonymousAttributeIDHandle *anonymous_id,
|
||||
const int totelem,
|
||||
void *layer_data,
|
||||
const ImplicitSharingInfo *sharing_info)
|
||||
{
|
||||
const char *name = anonymous_id->name().c_str();
|
||||
CustomDataLayer *layer = customData_add_layer__internal(
|
||||
data, type, std::nullopt, layer_data, sharing_info, totelem, name);
|
||||
CustomData_update_typemap(data);
|
||||
|
||||
if (layer == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
anonymous_id->add_user();
|
||||
layer->anonymous_id = anonymous_id;
|
||||
return layer->data;
|
||||
}
|
||||
|
||||
bool CustomData_free_layer(CustomData *data,
|
||||
const eCustomDataType type,
|
||||
const int totelem,
|
||||
|
@ -3081,47 +3206,6 @@ int CustomData_number_of_layers_typemask(const CustomData *data, const eCustomDa
|
|||
return number;
|
||||
}
|
||||
|
||||
static void *customData_duplicate_referenced_layer_index(CustomData *data,
|
||||
const int layer_index,
|
||||
const int totelem)
|
||||
{
|
||||
if (layer_index == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CustomDataLayer *layer = &data->layers[layer_index];
|
||||
|
||||
if (layer->flag & CD_FLAG_NOFREE) {
|
||||
/* MEM_dupallocN won't work in case of complex layers, like e.g.
|
||||
* CD_MDEFORMVERT, which has pointers to allocated data...
|
||||
* So in case a custom copy function is defined, use it!
|
||||
*/
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
|
||||
|
||||
if (typeInfo->copy) {
|
||||
void *dst_data = MEM_malloc_arrayN(
|
||||
size_t(totelem), typeInfo->size, "CD duplicate ref layer");
|
||||
typeInfo->copy(layer->data, dst_data, totelem);
|
||||
layer->data = dst_data;
|
||||
}
|
||||
else {
|
||||
layer->data = MEM_dupallocN(layer->data);
|
||||
}
|
||||
|
||||
layer->flag &= ~CD_FLAG_NOFREE;
|
||||
}
|
||||
|
||||
return layer->data;
|
||||
}
|
||||
|
||||
void CustomData_duplicate_referenced_layers(CustomData *data, const int totelem)
|
||||
{
|
||||
for (int i = 0; i < data->totlayer; i++) {
|
||||
CustomDataLayer *layer = &data->layers[i];
|
||||
layer->data = customData_duplicate_referenced_layer_index(data, i, totelem);
|
||||
}
|
||||
}
|
||||
|
||||
void CustomData_free_temporary(CustomData *data, const int totelem)
|
||||
{
|
||||
int i, j;
|
||||
|
@ -3299,14 +3383,12 @@ void CustomData_copy_layer_type_data(const CustomData *source,
|
|||
void CustomData_free_elem(CustomData *data, const int index, const int count)
|
||||
{
|
||||
for (int i = 0; i < data->totlayer; i++) {
|
||||
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
|
||||
|
||||
if (typeInfo->free) {
|
||||
size_t offset = size_t(index) * typeInfo->size;
|
||||
if (typeInfo->free) {
|
||||
size_t offset = size_t(index) * typeInfo->size;
|
||||
|
||||
typeInfo->free(POINTER_OFFSET(data->layers[i].data, offset), count, typeInfo->size);
|
||||
}
|
||||
typeInfo->free(POINTER_OFFSET(data->layers[i].data, offset), count, typeInfo->size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3476,7 +3558,12 @@ void *CustomData_get_layer_for_write(CustomData *data,
|
|||
const int totelem)
|
||||
{
|
||||
const int layer_index = CustomData_get_active_layer_index(data, type);
|
||||
return customData_duplicate_referenced_layer_index(data, layer_index, totelem);
|
||||
if (layer_index == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
CustomDataLayer &layer = data->layers[layer_index];
|
||||
ensure_layer_data_is_mutable(layer, totelem);
|
||||
return layer.data;
|
||||
}
|
||||
|
||||
const void *CustomData_get_layer_n(const CustomData *data, const eCustomDataType type, const int n)
|
||||
|
@ -3485,7 +3572,6 @@ const void *CustomData_get_layer_n(const CustomData *data, const eCustomDataType
|
|||
if (layer_index == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return data->layers[layer_index].data;
|
||||
}
|
||||
|
||||
|
@ -3495,7 +3581,12 @@ void *CustomData_get_layer_n_for_write(CustomData *data,
|
|||
const int totelem)
|
||||
{
|
||||
const int layer_index = CustomData_get_layer_index_n(data, type, n);
|
||||
return customData_duplicate_referenced_layer_index(data, layer_index, totelem);
|
||||
if (layer_index == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
CustomDataLayer &layer = data->layers[layer_index];
|
||||
ensure_layer_data_is_mutable(layer, totelem);
|
||||
return layer.data;
|
||||
}
|
||||
|
||||
const void *CustomData_get_layer_named(const CustomData *data,
|
||||
|
@ -3506,7 +3597,6 @@ const void *CustomData_get_layer_named(const CustomData *data,
|
|||
if (layer_index == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return data->layers[layer_index].data;
|
||||
}
|
||||
|
||||
|
@ -3516,7 +3606,12 @@ void *CustomData_get_layer_named_for_write(CustomData *data,
|
|||
const int totelem)
|
||||
{
|
||||
const int layer_index = CustomData_get_named_layer_index(data, type, name);
|
||||
return customData_duplicate_referenced_layer_index(data, layer_index, totelem);
|
||||
if (layer_index == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
CustomDataLayer &layer = data->layers[layer_index];
|
||||
ensure_layer_data_is_mutable(layer, totelem);
|
||||
return layer.data;
|
||||
}
|
||||
|
||||
int CustomData_get_offset(const CustomData *data, const eCustomDataType type)
|
||||
|
@ -3525,7 +3620,6 @@ int CustomData_get_offset(const CustomData *data, const eCustomDataType type)
|
|||
if (layer_index == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return data->layers[layer_index].offset;
|
||||
}
|
||||
|
||||
|
@ -3610,12 +3704,12 @@ void CustomData_bmesh_init_pool(CustomData *data, const int totelem, const char
|
|||
}
|
||||
}
|
||||
|
||||
bool CustomData_bmesh_merge(const CustomData *source,
|
||||
CustomData *dest,
|
||||
eCustomDataMask mask,
|
||||
eCDAllocType alloctype,
|
||||
BMesh *bm,
|
||||
const char htype)
|
||||
bool CustomData_bmesh_merge_layout(const CustomData *source,
|
||||
CustomData *dest,
|
||||
eCustomDataMask mask,
|
||||
eCDAllocType alloctype,
|
||||
BMesh *bm,
|
||||
const char htype)
|
||||
{
|
||||
|
||||
if (CustomData_number_of_layers_typemask(source, mask) == 0) {
|
||||
|
@ -3629,7 +3723,7 @@ bool CustomData_bmesh_merge(const CustomData *source,
|
|||
destold.layers = static_cast<CustomDataLayer *>(MEM_dupallocN(destold.layers));
|
||||
}
|
||||
|
||||
if (CustomData_merge(source, dest, mask, alloctype, 0) == false) {
|
||||
if (CustomData_merge_layout(source, dest, mask, alloctype, 0) == false) {
|
||||
if (destold.layers) {
|
||||
MEM_freeN(destold.layers);
|
||||
}
|
||||
|
@ -3709,13 +3803,11 @@ void CustomData_bmesh_free_block(CustomData *data, void **block)
|
|||
}
|
||||
|
||||
for (int i = 0; i < data->totlayer; i++) {
|
||||
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
|
||||
|
||||
if (typeInfo->free) {
|
||||
int offset = data->layers[i].offset;
|
||||
typeInfo->free(POINTER_OFFSET(*block, offset), 1, typeInfo->size);
|
||||
}
|
||||
if (typeInfo->free) {
|
||||
int offset = data->layers[i].offset;
|
||||
typeInfo->free(POINTER_OFFSET(*block, offset), 1, typeInfo->size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3732,12 +3824,10 @@ void CustomData_bmesh_free_block_data(CustomData *data, void *block)
|
|||
return;
|
||||
}
|
||||
for (int i = 0; i < data->totlayer; i++) {
|
||||
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
|
||||
if (typeInfo->free) {
|
||||
const size_t offset = data->layers[i].offset;
|
||||
typeInfo->free(POINTER_OFFSET(block, offset), 1, typeInfo->size);
|
||||
}
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
|
||||
if (typeInfo->free) {
|
||||
const size_t offset = data->layers[i].offset;
|
||||
typeInfo->free(POINTER_OFFSET(block, offset), 1, typeInfo->size);
|
||||
}
|
||||
}
|
||||
if (data->totsize) {
|
||||
|
@ -3770,10 +3860,8 @@ void CustomData_bmesh_free_block_data_exclude_by_type(CustomData *data,
|
|||
if ((CD_TYPE_AS_MASK(data->layers[i].type) & mask_exclude) == 0) {
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
|
||||
const size_t offset = data->layers[i].offset;
|
||||
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
|
||||
if (typeInfo->free) {
|
||||
typeInfo->free(POINTER_OFFSET(block, offset), 1, typeInfo->size);
|
||||
}
|
||||
if (typeInfo->free) {
|
||||
typeInfo->free(POINTER_OFFSET(block, offset), 1, typeInfo->size);
|
||||
}
|
||||
memset(POINTER_OFFSET(block, offset), 0, typeInfo->size);
|
||||
}
|
||||
|
@ -3951,11 +4039,9 @@ bool CustomData_has_math(const CustomData *data)
|
|||
bool CustomData_bmesh_has_free(const CustomData *data)
|
||||
{
|
||||
for (int i = 0; i < data->totlayer; i++) {
|
||||
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
|
||||
if (typeInfo->free) {
|
||||
return true;
|
||||
}
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
|
||||
if (typeInfo->free) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -3973,16 +4059,6 @@ bool CustomData_has_interp(const CustomData *data)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool CustomData_has_referenced(const CustomData *data)
|
||||
{
|
||||
for (int i = 0; i < data->totlayer; i++) {
|
||||
if (data->layers[i].flag & CD_FLAG_NOFREE) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CustomData_data_copy_value(const eCustomDataType type, const void *source, void *dest)
|
||||
{
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
||||
|
@ -5188,11 +5264,15 @@ void CustomData_blend_read(BlendDataReader *reader, CustomData *data, const int
|
|||
if (layer->flag & CD_FLAG_EXTERNAL) {
|
||||
layer->flag &= ~CD_FLAG_IN_MEMORY;
|
||||
}
|
||||
|
||||
layer->flag &= ~CD_FLAG_NOFREE;
|
||||
layer->sharing_info = nullptr;
|
||||
|
||||
if (CustomData_verify_versions(data, i)) {
|
||||
BLO_read_data_address(reader, &layer->data);
|
||||
if (layer->data != nullptr) {
|
||||
/* Make layer data shareable. */
|
||||
layer->sharing_info = make_implicit_sharing_info_for_layer(
|
||||
eCustomDataType(layer->type), layer->data, count);
|
||||
}
|
||||
if (CustomData_layer_ensure_data_exists(layer, count)) {
|
||||
/* Under normal operations, this shouldn't happen, but...
|
||||
* For a CD_PROP_BOOL example, see #84935.
|
||||
|
@ -5280,6 +5360,8 @@ const blender::CPPType *custom_data_type_to_cpp_type(const eCustomDataType type)
|
|||
return &CPPType::get<float3>();
|
||||
case CD_PROP_INT32:
|
||||
return &CPPType::get<int>();
|
||||
case CD_PROP_INT32_2D:
|
||||
return &CPPType::get<int2>();
|
||||
case CD_PROP_COLOR:
|
||||
return &CPPType::get<ColorGeometry4f>();
|
||||
case CD_PROP_BOOL:
|
||||
|
@ -5309,6 +5391,9 @@ eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
|
|||
if (type.is<int>()) {
|
||||
return CD_PROP_INT32;
|
||||
}
|
||||
if (type.is<int2>()) {
|
||||
return CD_PROP_INT32_2D;
|
||||
}
|
||||
if (type.is<ColorGeometry4f>()) {
|
||||
return CD_PROP_COLOR;
|
||||
}
|
||||
|
|
|
@ -649,7 +649,7 @@ bool BKE_gpencil_stroke_stretch(bGPDstroke *gps,
|
|||
if (!isfinite(used_percent_length)) {
|
||||
/* #used_percent_length must always be finite, otherwise a segfault occurs.
|
||||
* Since this function should never segfault, set #used_percent_length to a safe fallback. */
|
||||
/* NOTE: This fallback is used if gps->totpoints == 2, see MOD_gpencillength.c */
|
||||
/* NOTE: This fallback is used if gps->totpoints == 2, see MOD_gpencil_legacy_length.c */
|
||||
used_percent_length = 0.1f;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,8 +43,8 @@
|
|||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "MOD_gpencil_lineart.h"
|
||||
#include "MOD_gpencil_modifiertypes.h"
|
||||
#include "MOD_gpencil_legacy_lineart.h"
|
||||
#include "MOD_gpencil_legacy_modifiertypes.h"
|
||||
|
||||
#include "BLO_read_write.h"
|
||||
|
||||
|
@ -329,7 +329,7 @@ void BKE_gpencil_frame_active_set(Depsgraph *depsgraph, bGPdata *gpd)
|
|||
void BKE_gpencil_modifier_init(void)
|
||||
{
|
||||
/* Initialize modifier types */
|
||||
gpencil_modifier_type_init(modifier_gpencil_types); /* MOD_gpencil_util.c */
|
||||
gpencil_modifier_type_init(modifier_gpencil_types); /* MOD_gpencil_legacy_util.c */
|
||||
|
||||
#if 0
|
||||
/* Note that GPencil actually does not support these at the moment,
|
||||
|
|
|
@ -404,7 +404,7 @@ static int lib_id_expand_local_cb(LibraryIDLinkCallbackData *cb_data)
|
|||
return IDWALK_RET_NOP;
|
||||
}
|
||||
|
||||
if (cb_flag & IDWALK_CB_EMBEDDED) {
|
||||
if (cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_EMBEDDED_NOT_OWNING)) {
|
||||
/* Embedded data-blocks need to be made fully local as well.
|
||||
* Note however that in some cases (when owner ID had to be duplicated instead of being made
|
||||
* local directly), its embedded IDs should also have already been duplicated, and hence be
|
||||
|
@ -1494,12 +1494,11 @@ bool BKE_id_new_name_validate(
|
|||
return result;
|
||||
}
|
||||
|
||||
/* if no name given, use name of current ID
|
||||
* else make a copy (tname args can be const) */
|
||||
/* If no name given, use name of current ID. */
|
||||
if (tname == NULL) {
|
||||
tname = id->name + 2;
|
||||
}
|
||||
|
||||
/* Make a copy of given name (tname args can be const). */
|
||||
BLI_strncpy(name, tname, sizeof(name));
|
||||
|
||||
if (name[0] == '\0') {
|
||||
|
|
|
@ -696,7 +696,8 @@ static void lib_query_unused_ids_tag_recurse(Main *bmain,
|
|||
|
||||
/* An ID user is 'valid' (i.e. may affect the 'used'/'not used' status of the ID it uses) if it
|
||||
* does not match `ignored_usages`, and does match `required_usages`. */
|
||||
const int ignored_usages = (IDWALK_CB_LOOPBACK | IDWALK_CB_EMBEDDED);
|
||||
const int ignored_usages = (IDWALK_CB_LOOPBACK | IDWALK_CB_EMBEDDED |
|
||||
IDWALK_CB_EMBEDDED_NOT_OWNING);
|
||||
const int required_usages = (IDWALK_CB_USER | IDWALK_CB_USER_ONE);
|
||||
|
||||
/* This ID may be tagged as unused if none of its users are 'valid', as defined above.
|
||||
|
|
|
@ -157,7 +157,7 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data)
|
|||
{
|
||||
const int cb_flag = cb_data->cb_flag;
|
||||
|
||||
if (cb_flag & IDWALK_CB_EMBEDDED) {
|
||||
if (cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_EMBEDDED_NOT_OWNING)) {
|
||||
return IDWALK_RET_NOP;
|
||||
}
|
||||
|
||||
|
@ -857,7 +857,8 @@ static void libblock_relink_to_newid_prepare_data(Main *bmain,
|
|||
static int id_relink_to_newid_looper(LibraryIDLinkCallbackData *cb_data)
|
||||
{
|
||||
const int cb_flag = cb_data->cb_flag;
|
||||
if (cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) {
|
||||
if (cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_EMBEDDED_NOT_OWNING |
|
||||
IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) {
|
||||
return IDWALK_RET_NOP;
|
||||
}
|
||||
|
||||
|
|
|
@ -150,14 +150,13 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
|
|||
mesh_dst->default_color_attribute = static_cast<char *>(
|
||||
MEM_dupallocN(mesh_src->default_color_attribute));
|
||||
|
||||
const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
|
||||
CustomData_copy(&mesh_src->vdata, &mesh_dst->vdata, mask.vmask, alloc_type, mesh_dst->totvert);
|
||||
CustomData_copy(&mesh_src->edata, &mesh_dst->edata, mask.emask, alloc_type, mesh_dst->totedge);
|
||||
CustomData_copy(&mesh_src->ldata, &mesh_dst->ldata, mask.lmask, alloc_type, mesh_dst->totloop);
|
||||
CustomData_copy(&mesh_src->pdata, &mesh_dst->pdata, mask.pmask, alloc_type, mesh_dst->totpoly);
|
||||
CustomData_copy(&mesh_src->vdata, &mesh_dst->vdata, mask.vmask, mesh_dst->totvert);
|
||||
CustomData_copy(&mesh_src->edata, &mesh_dst->edata, mask.emask, mesh_dst->totedge);
|
||||
CustomData_copy(&mesh_src->ldata, &mesh_dst->ldata, mask.lmask, mesh_dst->totloop);
|
||||
CustomData_copy(&mesh_src->pdata, &mesh_dst->pdata, mask.pmask, mesh_dst->totpoly);
|
||||
mesh_dst->poly_offset_indices = static_cast<int *>(MEM_dupallocN(mesh_src->poly_offset_indices));
|
||||
if (do_tessface) {
|
||||
CustomData_copy(&mesh_src->fdata, &mesh_dst->fdata, mask.fmask, alloc_type, mesh_dst->totface);
|
||||
CustomData_copy(&mesh_src->fdata, &mesh_dst->fdata, mask.fmask, mesh_dst->totface);
|
||||
}
|
||||
else {
|
||||
mesh_tessface_clear_intern(mesh_dst, false);
|
||||
|
@ -617,6 +616,16 @@ static int customdata_compare(
|
|||
BLI_edgehash_free(eh, nullptr);
|
||||
break;
|
||||
}
|
||||
case CD_PROP_INT32_2D: {
|
||||
const blender::int2 *l1_data = static_cast<const blender::int2 *>(l1->data);
|
||||
const blender::int2 *l2_data = static_cast<const blender::int2 *>(l2->data);
|
||||
for (int i = 0; i < total_length; i++) {
|
||||
if (l1_data[i] != l2_data[i]) {
|
||||
return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CD_PROP_BYTE_COLOR: {
|
||||
MLoopCol *lp1 = (MLoopCol *)l1->data;
|
||||
MLoopCol *lp2 = (MLoopCol *)l2->data;
|
||||
|
@ -1102,12 +1111,13 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
|
|||
|
||||
BKE_mesh_copy_parameters_for_eval(me_dst, me_src);
|
||||
|
||||
CustomData_copy(&me_src->vdata, &me_dst->vdata, mask.vmask, CD_SET_DEFAULT, verts_len);
|
||||
CustomData_copy(&me_src->edata, &me_dst->edata, mask.emask, CD_SET_DEFAULT, edges_len);
|
||||
CustomData_copy(&me_src->ldata, &me_dst->ldata, mask.lmask, CD_SET_DEFAULT, loops_len);
|
||||
CustomData_copy(&me_src->pdata, &me_dst->pdata, mask.pmask, CD_SET_DEFAULT, polys_len);
|
||||
CustomData_copy_layout(&me_src->vdata, &me_dst->vdata, mask.vmask, CD_SET_DEFAULT, verts_len);
|
||||
CustomData_copy_layout(&me_src->edata, &me_dst->edata, mask.emask, CD_SET_DEFAULT, edges_len);
|
||||
CustomData_copy_layout(&me_src->ldata, &me_dst->ldata, mask.lmask, CD_SET_DEFAULT, loops_len);
|
||||
CustomData_copy_layout(&me_src->pdata, &me_dst->pdata, mask.pmask, CD_SET_DEFAULT, polys_len);
|
||||
if (do_tessface) {
|
||||
CustomData_copy(&me_src->fdata, &me_dst->fdata, mask.fmask, CD_SET_DEFAULT, tessface_len);
|
||||
CustomData_copy_layout(
|
||||
&me_src->fdata, &me_dst->fdata, mask.fmask, CD_SET_DEFAULT, tessface_len);
|
||||
}
|
||||
else {
|
||||
mesh_tessface_clear_intern(me_dst, false);
|
||||
|
@ -1384,7 +1394,7 @@ void BKE_mesh_orco_ensure(Object *ob, Mesh *mesh)
|
|||
/* Orcos are stored in normalized 0..1 range by convention. */
|
||||
float(*orcodata)[3] = BKE_mesh_orco_verts_get(ob);
|
||||
BKE_mesh_orco_verts_transform(mesh, orcodata, mesh->totvert, false);
|
||||
CustomData_add_layer_with_data(&mesh->vdata, CD_ORCO, orcodata, mesh->totvert);
|
||||
CustomData_add_layer_with_data(&mesh->vdata, CD_ORCO, orcodata, mesh->totvert, nullptr);
|
||||
}
|
||||
|
||||
Mesh *BKE_mesh_from_object(Object *ob)
|
||||
|
|
|
@ -656,15 +656,15 @@ static void merge_vertex_loop_poly_customdata_layers(Mesh *target, MeshesToIMesh
|
|||
for (int mesh_index = 1; mesh_index < mim.meshes.size(); ++mesh_index) {
|
||||
const Mesh *me = mim.meshes[mesh_index];
|
||||
if (me->totvert) {
|
||||
CustomData_merge(
|
||||
CustomData_merge_layout(
|
||||
&me->vdata, &target->vdata, CD_MASK_MESH.vmask, CD_SET_DEFAULT, target->totvert);
|
||||
}
|
||||
if (me->totloop) {
|
||||
CustomData_merge(
|
||||
CustomData_merge_layout(
|
||||
&me->ldata, &target->ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, target->totloop);
|
||||
}
|
||||
if (me->totpoly) {
|
||||
CustomData_merge(
|
||||
CustomData_merge_layout(
|
||||
&me->pdata, &target->pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, target->totpoly);
|
||||
}
|
||||
}
|
||||
|
@ -675,7 +675,7 @@ static void merge_edge_customdata_layers(Mesh *target, MeshesToIMeshInfo &mim)
|
|||
for (int mesh_index = 0; mesh_index < mim.meshes.size(); ++mesh_index) {
|
||||
const Mesh *me = mim.meshes[mesh_index];
|
||||
if (me->totedge) {
|
||||
CustomData_merge(
|
||||
CustomData_merge_layout(
|
||||
&me->edata, &target->edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, target->totedge);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -244,7 +244,7 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool keep_existing_edges, const bool select
|
|||
/* Free old CustomData and assign new one. */
|
||||
CustomData_free(&mesh->edata, mesh->totedge);
|
||||
CustomData_reset(&mesh->edata);
|
||||
CustomData_add_layer_with_data(&mesh->edata, CD_MEDGE, new_edges.data(), new_totedge);
|
||||
CustomData_add_layer_with_data(&mesh->edata, CD_MEDGE, new_edges.data(), new_totedge, nullptr);
|
||||
mesh->totedge = new_totedge;
|
||||
|
||||
if (select_new_edges) {
|
||||
|
|
|
@ -625,7 +625,7 @@ void BKE_pointcloud_from_mesh(const Mesh *me, PointCloud *pointcloud)
|
|||
{
|
||||
CustomData_free(&pointcloud->pdata, pointcloud->totpoint);
|
||||
pointcloud->totpoint = me->totvert;
|
||||
CustomData_merge(&me->vdata, &pointcloud->pdata, CD_MASK_PROP_ALL, CD_DUPLICATE, me->totvert);
|
||||
CustomData_merge(&me->vdata, &pointcloud->pdata, CD_MASK_PROP_ALL, me->totvert);
|
||||
}
|
||||
|
||||
void BKE_mesh_to_pointcloud(Main *bmain, Depsgraph *depsgraph, Scene * /*scene*/, Object *ob)
|
||||
|
@ -652,8 +652,7 @@ void BKE_mesh_to_pointcloud(Main *bmain, Depsgraph *depsgraph, Scene * /*scene*/
|
|||
void BKE_mesh_from_pointcloud(const PointCloud *pointcloud, Mesh *me)
|
||||
{
|
||||
me->totvert = pointcloud->totpoint;
|
||||
CustomData_merge(
|
||||
&pointcloud->pdata, &me->vdata, CD_MASK_PROP_ALL, CD_DUPLICATE, pointcloud->totpoint);
|
||||
CustomData_merge(&pointcloud->pdata, &me->vdata, CD_MASK_PROP_ALL, pointcloud->totpoint);
|
||||
}
|
||||
|
||||
void BKE_pointcloud_to_mesh(Main *bmain, Depsgraph *depsgraph, Scene * /*scene*/, Object *ob)
|
||||
|
@ -1116,13 +1115,6 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob)
|
|||
|
||||
BKE_mesh_clear_geometry_and_metadata(mesh_dst);
|
||||
|
||||
/* Make sure referenced layers have a single user so assigning them to the mesh in main doesn't
|
||||
* share them. "Referenced" layers are not expected to be shared between original meshes. */
|
||||
CustomData_duplicate_referenced_layers(&mesh_src->vdata, mesh_src->totvert);
|
||||
CustomData_duplicate_referenced_layers(&mesh_src->edata, mesh_src->totedge);
|
||||
CustomData_duplicate_referenced_layers(&mesh_src->pdata, mesh_src->totpoly);
|
||||
CustomData_duplicate_referenced_layers(&mesh_src->ldata, mesh_src->totloop);
|
||||
|
||||
const bool verts_num_changed = mesh_dst->totvert != mesh_src->totvert;
|
||||
mesh_dst->totvert = mesh_src->totvert;
|
||||
mesh_dst->totedge = mesh_src->totedge;
|
||||
|
@ -1131,10 +1123,10 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob)
|
|||
|
||||
/* Using #CD_MASK_MESH ensures that only data that should exist in Main meshes is moved. */
|
||||
const CustomData_MeshMasks mask = CD_MASK_MESH;
|
||||
CustomData_copy(&mesh_src->vdata, &mesh_dst->vdata, mask.vmask, CD_ASSIGN, mesh_src->totvert);
|
||||
CustomData_copy(&mesh_src->edata, &mesh_dst->edata, mask.emask, CD_ASSIGN, mesh_src->totedge);
|
||||
CustomData_copy(&mesh_src->pdata, &mesh_dst->pdata, mask.pmask, CD_ASSIGN, mesh_src->totpoly);
|
||||
CustomData_copy(&mesh_src->ldata, &mesh_dst->ldata, mask.lmask, CD_ASSIGN, mesh_src->totloop);
|
||||
CustomData_copy(&mesh_src->vdata, &mesh_dst->vdata, mask.vmask, mesh_src->totvert);
|
||||
CustomData_copy(&mesh_src->edata, &mesh_dst->edata, mask.emask, mesh_src->totedge);
|
||||
CustomData_copy(&mesh_src->pdata, &mesh_dst->pdata, mask.pmask, mesh_src->totpoly);
|
||||
CustomData_copy(&mesh_src->ldata, &mesh_dst->ldata, mask.lmask, mesh_src->totloop);
|
||||
std::swap(mesh_dst->poly_offset_indices, mesh_src->poly_offset_indices);
|
||||
|
||||
/* Make sure attribute names are moved. */
|
||||
|
|
|
@ -227,7 +227,7 @@ void BKE_mesh_calc_edges_legacy(Mesh *me)
|
|||
return;
|
||||
}
|
||||
|
||||
edges = (MEdge *)CustomData_add_layer_with_data(&me->edata, CD_MEDGE, edges, totedge);
|
||||
edges = (MEdge *)CustomData_add_layer_with_data(&me->edata, CD_MEDGE, edges, totedge, nullptr);
|
||||
me->totedge = totedge;
|
||||
|
||||
BKE_mesh_tag_topology_changed(me);
|
||||
|
@ -1149,11 +1149,11 @@ static int mesh_tessface_calc(Mesh &mesh,
|
|||
sizeof(*mface_to_poly_map) * size_t(totface));
|
||||
}
|
||||
|
||||
CustomData_add_layer_with_data(fdata, CD_MFACE, mface, totface);
|
||||
CustomData_add_layer_with_data(fdata, CD_MFACE, mface, totface, nullptr);
|
||||
|
||||
/* #CD_ORIGINDEX will contain an array of indices from tessellation-faces to the polygons
|
||||
* they are directly tessellated from. */
|
||||
CustomData_add_layer_with_data(fdata, CD_ORIGINDEX, mface_to_poly_map, totface);
|
||||
CustomData_add_layer_with_data(fdata, CD_ORIGINDEX, mface_to_poly_map, totface, nullptr);
|
||||
add_mface_layers(mesh, fdata, ldata, totface);
|
||||
|
||||
/* NOTE: quad detection issue - fourth vertex-index vs fourth loop-index:
|
||||
|
@ -1297,17 +1297,28 @@ void BKE_mesh_legacy_face_set_to_generic(Mesh *mesh)
|
|||
return;
|
||||
}
|
||||
void *faceset_data = nullptr;
|
||||
const ImplicitSharingInfo *faceset_sharing_info = nullptr;
|
||||
for (const int i : IndexRange(mesh->pdata.totlayer)) {
|
||||
if (mesh->pdata.layers[i].type == CD_SCULPT_FACE_SETS) {
|
||||
faceset_data = mesh->pdata.layers[i].data;
|
||||
mesh->pdata.layers[i].data = nullptr;
|
||||
CustomDataLayer &layer = mesh->pdata.layers[i];
|
||||
if (layer.type == CD_SCULPT_FACE_SETS) {
|
||||
faceset_data = layer.data;
|
||||
faceset_sharing_info = layer.sharing_info;
|
||||
layer.data = nullptr;
|
||||
layer.sharing_info = nullptr;
|
||||
CustomData_free_layer(&mesh->pdata, CD_SCULPT_FACE_SETS, mesh->totpoly, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (faceset_data != nullptr) {
|
||||
CustomData_add_layer_named_with_data(
|
||||
&mesh->pdata, CD_PROP_INT32, faceset_data, mesh->totpoly, ".sculpt_face_set");
|
||||
CustomData_add_layer_named_with_data(&mesh->pdata,
|
||||
CD_PROP_INT32,
|
||||
faceset_data,
|
||||
mesh->totpoly,
|
||||
".sculpt_face_set",
|
||||
faceset_sharing_info);
|
||||
}
|
||||
if (faceset_sharing_info != nullptr) {
|
||||
faceset_sharing_info->remove_user_and_delete_if_last();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1815,28 +1826,31 @@ void BKE_mesh_legacy_convert_uvs_to_generic(Mesh *mesh)
|
|||
uv_names[i] = new_name;
|
||||
|
||||
CustomData_add_layer_named_with_data(
|
||||
&mesh->ldata, CD_PROP_FLOAT2, coords, mesh->totloop, new_name);
|
||||
&mesh->ldata, CD_PROP_FLOAT2, coords, mesh->totloop, new_name, nullptr);
|
||||
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
|
||||
if (vert_selection) {
|
||||
CustomData_add_layer_named_with_data(&mesh->ldata,
|
||||
CD_PROP_BOOL,
|
||||
vert_selection,
|
||||
mesh->totloop,
|
||||
BKE_uv_map_vert_select_name_get(new_name, buffer));
|
||||
BKE_uv_map_vert_select_name_get(new_name, buffer),
|
||||
nullptr);
|
||||
}
|
||||
if (edge_selection) {
|
||||
CustomData_add_layer_named_with_data(&mesh->ldata,
|
||||
CD_PROP_BOOL,
|
||||
edge_selection,
|
||||
mesh->totloop,
|
||||
BKE_uv_map_edge_select_name_get(new_name, buffer));
|
||||
BKE_uv_map_edge_select_name_get(new_name, buffer),
|
||||
nullptr);
|
||||
}
|
||||
if (pin) {
|
||||
CustomData_add_layer_named_with_data(&mesh->ldata,
|
||||
CD_PROP_BOOL,
|
||||
pin,
|
||||
mesh->totloop,
|
||||
BKE_uv_map_pin_name_get(new_name, buffer));
|
||||
BKE_uv_map_pin_name_get(new_name, buffer),
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2272,7 +2286,8 @@ void BKE_mesh_legacy_convert_polys_to_offsets(Mesh *mesh)
|
|||
});
|
||||
CustomData old_poly_data = mesh->pdata;
|
||||
CustomData_reset(&mesh->pdata);
|
||||
CustomData_copy(&old_poly_data, &mesh->pdata, CD_MASK_MESH.pmask, CD_CONSTRUCT, mesh->totpoly);
|
||||
CustomData_copy_layout(
|
||||
&old_poly_data, &mesh->pdata, CD_MASK_MESH.pmask, CD_CONSTRUCT, mesh->totpoly);
|
||||
|
||||
int offset = 0;
|
||||
for (const int i : orig_indices.index_range()) {
|
||||
|
|
|
@ -224,6 +224,7 @@ void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
|
|||
mesh->runtime->subsurf_optimal_display_edges.clear_and_shrink();
|
||||
if (mesh->runtime->shrinkwrap_data) {
|
||||
BKE_shrinkwrap_boundary_data_free(mesh->runtime->shrinkwrap_data);
|
||||
mesh->runtime->shrinkwrap_data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,6 +241,7 @@ void BKE_mesh_tag_edges_split(struct Mesh *mesh)
|
|||
mesh->runtime->subsurf_optimal_display_edges.clear_and_shrink();
|
||||
if (mesh->runtime->shrinkwrap_data) {
|
||||
BKE_shrinkwrap_boundary_data_free(mesh->runtime->shrinkwrap_data);
|
||||
mesh->runtime->shrinkwrap_data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1952,9 +1952,11 @@ static void BKE_nlastrip_validate_autoblends(NlaTrack *nlt, NlaStrip *nls)
|
|||
}
|
||||
}
|
||||
|
||||
/* Ensure every transition's start/end properly set.
|
||||
/**
|
||||
* Ensure every transition's start/end properly set.
|
||||
* Strip will be removed / freed if it doesn't fit (invalid).
|
||||
* Return value indicates if passed strip is valid/fixed or invalid/removed. */
|
||||
* Return value indicates if passed strip is valid/fixed or invalid/removed.
|
||||
*/
|
||||
static bool nlastrip_validate_transition_start_end(NlaStrip *strip)
|
||||
{
|
||||
|
||||
|
|
|
@ -132,7 +132,8 @@ struct DupliContext {
|
|||
};
|
||||
|
||||
struct DupliGenerator {
|
||||
short type; /* Dupli Type, see members of #OB_DUPLI. */
|
||||
/** Duplicator Type, see members of #OB_DUPLI. */
|
||||
short type;
|
||||
void (*make_duplis)(const DupliContext *ctx);
|
||||
};
|
||||
|
||||
|
@ -1325,8 +1326,10 @@ static void make_duplis_faces(const DupliContext *ctx)
|
|||
}
|
||||
}
|
||||
|
||||
static const DupliGenerator gen_dupli_faces = {/*type*/ OB_DUPLIFACES,
|
||||
/*make_duplis*/ make_duplis_faces};
|
||||
static const DupliGenerator gen_dupli_faces = {
|
||||
/*type*/ OB_DUPLIFACES,
|
||||
/*make_duplis*/ make_duplis_faces,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
|
@ -1673,8 +1676,10 @@ static void make_duplis_particles(const DupliContext *ctx)
|
|||
}
|
||||
}
|
||||
|
||||
static const DupliGenerator gen_dupli_particles = {/*type*/ OB_DUPLIPARTS,
|
||||
/*make_duplis*/ make_duplis_particles};
|
||||
static const DupliGenerator gen_dupli_particles = {
|
||||
/*type*/ OB_DUPLIPARTS,
|
||||
/*make_duplis*/ make_duplis_particles,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -2171,11 +2171,10 @@ static PBVH *build_pbvh_for_dynamic_topology(Object *ob)
|
|||
return pbvh;
|
||||
}
|
||||
|
||||
static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool respect_hide)
|
||||
static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform)
|
||||
{
|
||||
Mesh *me = BKE_object_get_original_mesh(ob);
|
||||
PBVH *pbvh = BKE_pbvh_new(PBVH_FACES);
|
||||
BKE_pbvh_respect_hide_set(pbvh, respect_hide);
|
||||
|
||||
BKE_pbvh_build_mesh(pbvh, me);
|
||||
|
||||
|
@ -2188,12 +2187,11 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool
|
|||
return pbvh;
|
||||
}
|
||||
|
||||
static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg, bool respect_hide)
|
||||
static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg)
|
||||
{
|
||||
CCGKey key;
|
||||
BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
|
||||
PBVH *pbvh = BKE_pbvh_new(PBVH_GRIDS);
|
||||
BKE_pbvh_respect_hide_set(pbvh, respect_hide);
|
||||
|
||||
Mesh *base_mesh = BKE_mesh_from_object(ob);
|
||||
BKE_sculpt_sync_face_visibility_to_grids(base_mesh, subdiv_ccg);
|
||||
|
@ -2216,8 +2214,6 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
const bool respect_hide = true;
|
||||
|
||||
PBVH *pbvh = ob->sculpt->pbvh;
|
||||
if (pbvh != nullptr) {
|
||||
/* NOTE: It is possible that pointers to grids or other geometry data changed. Need to update
|
||||
|
@ -2258,11 +2254,11 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
|||
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
|
||||
Mesh *mesh_eval = static_cast<Mesh *>(object_eval->data);
|
||||
if (mesh_eval->runtime->subdiv_ccg != nullptr) {
|
||||
pbvh = build_pbvh_from_ccg(ob, mesh_eval->runtime->subdiv_ccg, respect_hide);
|
||||
pbvh = build_pbvh_from_ccg(ob, mesh_eval->runtime->subdiv_ccg);
|
||||
}
|
||||
else if (ob->type == OB_MESH) {
|
||||
Mesh *me_eval_deform = object_eval->runtime.mesh_deform_eval;
|
||||
pbvh = build_pbvh_from_regular_mesh(ob, me_eval_deform, respect_hide);
|
||||
pbvh = build_pbvh_from_regular_mesh(ob, me_eval_deform);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -335,10 +335,6 @@ static void build_mesh_leaf_node(PBVH *pbvh, PBVHNode *node)
|
|||
|
||||
node->face_vert_indices = (const int(*)[3])face_vert_indices;
|
||||
|
||||
if (pbvh->respect_hide == false) {
|
||||
has_visible = true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < totface; i++) {
|
||||
const MLoopTri *lt = &pbvh->looptri[node->prim_indices[i]];
|
||||
for (int j = 0; j < 3; j++) {
|
||||
|
@ -1042,7 +1038,6 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
|
|||
PBVH *BKE_pbvh_new(PBVHType type)
|
||||
{
|
||||
PBVH *pbvh = MEM_new<PBVH>(__func__);
|
||||
pbvh->respect_hide = true;
|
||||
pbvh->draw_cache_invalid = true;
|
||||
pbvh->header.type = type;
|
||||
|
||||
|
@ -2600,7 +2595,7 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh,
|
|||
const MLoopTri *lt = &pbvh->looptri[faces[i]];
|
||||
const int *face_verts = node->face_vert_indices[i];
|
||||
|
||||
if (pbvh->respect_hide && paint_is_face_hidden(lt, pbvh->hide_poly)) {
|
||||
if (paint_is_face_hidden(lt, pbvh->hide_poly)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2909,7 +2904,7 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh,
|
|||
const MLoopTri *lt = &pbvh->looptri[faces[i]];
|
||||
const int *face_verts = node->face_vert_indices[i];
|
||||
|
||||
if (pbvh->respect_hide && paint_is_face_hidden(lt, pbvh->hide_poly)) {
|
||||
if (paint_is_face_hidden(lt, pbvh->hide_poly)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -3425,12 +3420,6 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
|
|||
vi->vert_positions = nullptr;
|
||||
vi->vertex.i = 0LL;
|
||||
|
||||
vi->respect_hide = pbvh->respect_hide;
|
||||
if (pbvh->respect_hide == false) {
|
||||
/* The same value for all vertices. */
|
||||
vi->visible = true;
|
||||
}
|
||||
|
||||
BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, nullptr, &gridsize, &grids);
|
||||
BKE_pbvh_node_num_verts(pbvh, node, &uniq_verts, &totvert);
|
||||
const int *vert_indices = BKE_pbvh_node_get_vert_indices(node);
|
||||
|
@ -3586,11 +3575,6 @@ void BKE_pbvh_update_hide_attributes_from_mesh(PBVH *pbvh)
|
|||
}
|
||||
}
|
||||
|
||||
void BKE_pbvh_respect_hide_set(PBVH *pbvh, bool respect_hide)
|
||||
{
|
||||
pbvh->respect_hide = respect_hide;
|
||||
}
|
||||
|
||||
bool BKE_pbvh_is_drawing(const PBVH *pbvh)
|
||||
{
|
||||
return pbvh->is_drawing;
|
||||
|
|
|
@ -187,7 +187,6 @@ struct PBVH {
|
|||
|
||||
/* flag are verts/faces deformed */
|
||||
bool deformed;
|
||||
bool respect_hide;
|
||||
|
||||
/* Dynamic topology */
|
||||
float bm_max_edge_len;
|
||||
|
|
|
@ -64,25 +64,24 @@ static void pointcloud_init_data(ID *id)
|
|||
CustomData_reset(&pointcloud->pdata);
|
||||
CustomData_add_layer_named(&pointcloud->pdata,
|
||||
CD_PROP_FLOAT3,
|
||||
CD_SET_DEFAULT,
|
||||
CD_CONSTRUCT,
|
||||
pointcloud->totpoint,
|
||||
POINTCLOUD_ATTR_POSITION);
|
||||
|
||||
pointcloud->runtime = new blender::bke::PointCloudRuntime();
|
||||
}
|
||||
|
||||
static void pointcloud_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int flag)
|
||||
static void pointcloud_copy_data(Main * /*bmain*/,
|
||||
ID *id_dst,
|
||||
const ID *id_src,
|
||||
const int /*flag*/)
|
||||
{
|
||||
PointCloud *pointcloud_dst = (PointCloud *)id_dst;
|
||||
const PointCloud *pointcloud_src = (const PointCloud *)id_src;
|
||||
pointcloud_dst->mat = static_cast<Material **>(MEM_dupallocN(pointcloud_src->mat));
|
||||
|
||||
const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
|
||||
CustomData_copy(&pointcloud_src->pdata,
|
||||
&pointcloud_dst->pdata,
|
||||
CD_MASK_ALL,
|
||||
alloc_type,
|
||||
pointcloud_dst->totpoint);
|
||||
CustomData_copy(
|
||||
&pointcloud_src->pdata, &pointcloud_dst->pdata, CD_MASK_ALL, pointcloud_dst->totpoint);
|
||||
|
||||
pointcloud_dst->runtime = new blender::bke::PointCloudRuntime();
|
||||
pointcloud_dst->runtime->bounds_cache = pointcloud_src->runtime->bounds_cache;
|
||||
|
@ -203,21 +202,18 @@ static void pointcloud_random(PointCloud *pointcloud)
|
|||
RNG *rng = BLI_rng_new(0);
|
||||
|
||||
blender::bke::MutableAttributeAccessor attributes = pointcloud->attributes_for_write();
|
||||
blender::bke::SpanAttributeWriter positions =
|
||||
attributes.lookup_or_add_for_write_only_span<float3>(POINTCLOUD_ATTR_POSITION,
|
||||
ATTR_DOMAIN_POINT);
|
||||
blender::MutableSpan<float3> positions = pointcloud->positions_for_write();
|
||||
blender::bke::SpanAttributeWriter<float> radii =
|
||||
attributes.lookup_or_add_for_write_only_span<float>(POINTCLOUD_ATTR_RADIUS,
|
||||
ATTR_DOMAIN_POINT);
|
||||
|
||||
for (const int i : positions.span.index_range()) {
|
||||
positions.span[i] =
|
||||
float3(BLI_rng_get_float(rng), BLI_rng_get_float(rng), BLI_rng_get_float(rng)) * 2.0f -
|
||||
1.0f;
|
||||
for (const int i : positions.index_range()) {
|
||||
positions[i] = float3(BLI_rng_get_float(rng), BLI_rng_get_float(rng), BLI_rng_get_float(rng)) *
|
||||
2.0f -
|
||||
1.0f;
|
||||
radii.span[i] = 0.05f * BLI_rng_get_float(rng);
|
||||
}
|
||||
|
||||
positions.finish();
|
||||
radii.finish();
|
||||
|
||||
BLI_rng_free(rng);
|
||||
|
@ -259,27 +255,12 @@ void BKE_pointcloud_nomain_to_pointcloud(PointCloud *pointcloud_src,
|
|||
{
|
||||
BLI_assert(pointcloud_src->id.tag & LIB_TAG_NO_MAIN);
|
||||
|
||||
eCDAllocType alloctype = CD_DUPLICATE;
|
||||
|
||||
if (take_ownership) {
|
||||
bool has_any_referenced_layers = CustomData_has_referenced(&pointcloud_src->pdata);
|
||||
|
||||
if (!has_any_referenced_layers) {
|
||||
alloctype = CD_ASSIGN;
|
||||
}
|
||||
}
|
||||
|
||||
CustomData_free(&pointcloud_dst->pdata, pointcloud_dst->totpoint);
|
||||
|
||||
const int totpoint = pointcloud_dst->totpoint = pointcloud_src->totpoint;
|
||||
CustomData_copy(
|
||||
&pointcloud_src->pdata, &pointcloud_dst->pdata, CD_MASK_ALL, alloctype, totpoint);
|
||||
CustomData_copy(&pointcloud_src->pdata, &pointcloud_dst->pdata, CD_MASK_ALL, totpoint);
|
||||
|
||||
if (take_ownership) {
|
||||
if (alloctype == CD_ASSIGN) {
|
||||
/* Free the CustomData but keep the layers. */
|
||||
CustomData_free_typemask(&pointcloud_src->pdata, pointcloud_src->totpoint, 0);
|
||||
}
|
||||
BKE_id_free(nullptr, pointcloud_src);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -763,7 +763,7 @@ static void scene_foreach_layer_collection(LibraryForeachIDData *data, ListBase
|
|||
* anyway... */
|
||||
const int cb_flag = (lc->collection != nullptr &&
|
||||
(lc->collection->id.flag & LIB_EMBEDDED_DATA) != 0) ?
|
||||
IDWALK_CB_EMBEDDED :
|
||||
IDWALK_CB_EMBEDDED_NOT_OWNING :
|
||||
IDWALK_CB_NOP;
|
||||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, lc->collection, cb_flag | IDWALK_CB_DIRECT_WEAK_LINK);
|
||||
scene_foreach_layer_collection(data, &lc->layer_collections);
|
||||
|
|
|
@ -168,15 +168,17 @@ void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area
|
|||
|
||||
BKE_LIB_FOREACHID_PROCESS_ID(data, snode->id, IDWALK_CB_NOP);
|
||||
BKE_LIB_FOREACHID_PROCESS_ID(data, snode->from, IDWALK_CB_NOP);
|
||||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(
|
||||
data, snode->nodetree, is_private_nodetree ? IDWALK_CB_EMBEDDED : IDWALK_CB_USER_ONE);
|
||||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data,
|
||||
snode->nodetree,
|
||||
is_private_nodetree ? IDWALK_CB_EMBEDDED_NOT_OWNING :
|
||||
IDWALK_CB_USER_ONE);
|
||||
|
||||
LISTBASE_FOREACH (bNodeTreePath *, path, &snode->treepath) {
|
||||
if (path == snode->treepath.first) {
|
||||
/* first nodetree in path is same as snode->nodetree */
|
||||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data,
|
||||
path->nodetree,
|
||||
is_private_nodetree ? IDWALK_CB_EMBEDDED :
|
||||
is_private_nodetree ? IDWALK_CB_EMBEDDED_NOT_OWNING :
|
||||
IDWALK_CB_USER_ONE);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -221,11 +221,11 @@ static void vertex_interpolation_init(const SubdivMeshContext *ctx,
|
|||
else {
|
||||
vertex_interpolation->vertex_data = &vertex_interpolation->vertex_data_storage;
|
||||
/* Allocate storage for loops corresponding to ptex corners. */
|
||||
CustomData_copy(&ctx->coarse_mesh->vdata,
|
||||
&vertex_interpolation->vertex_data_storage,
|
||||
CD_MASK_EVERYTHING.vmask,
|
||||
CD_SET_DEFAULT,
|
||||
4);
|
||||
CustomData_copy_layout(&ctx->coarse_mesh->vdata,
|
||||
&vertex_interpolation->vertex_data_storage,
|
||||
CD_MASK_EVERYTHING.vmask,
|
||||
CD_SET_DEFAULT,
|
||||
4);
|
||||
/* Initialize indices. */
|
||||
vertex_interpolation->vertex_indices[0] = 0;
|
||||
vertex_interpolation->vertex_indices[1] = 1;
|
||||
|
@ -351,11 +351,11 @@ static void loop_interpolation_init(const SubdivMeshContext *ctx,
|
|||
else {
|
||||
loop_interpolation->loop_data = &loop_interpolation->loop_data_storage;
|
||||
/* Allocate storage for loops corresponding to ptex corners. */
|
||||
CustomData_copy(&ctx->coarse_mesh->ldata,
|
||||
&loop_interpolation->loop_data_storage,
|
||||
CD_MASK_EVERYTHING.lmask,
|
||||
CD_SET_DEFAULT,
|
||||
4);
|
||||
CustomData_copy_layout(&ctx->coarse_mesh->ldata,
|
||||
&loop_interpolation->loop_data_storage,
|
||||
CD_MASK_EVERYTHING.lmask,
|
||||
CD_SET_DEFAULT,
|
||||
4);
|
||||
/* Initialize indices. */
|
||||
loop_interpolation->loop_indices[0] = 0;
|
||||
loop_interpolation->loop_indices[1] = 1;
|
||||
|
|
|
@ -51,6 +51,10 @@ static int32_t float_to_int(const float &a)
|
|||
{
|
||||
return int32_t(a);
|
||||
}
|
||||
static int2 float_to_int2(const float &a)
|
||||
{
|
||||
return int2(a);
|
||||
}
|
||||
static bool float_to_bool(const float &a)
|
||||
{
|
||||
return a > 0.0f;
|
||||
|
@ -81,6 +85,10 @@ static int float2_to_int(const float2 &a)
|
|||
{
|
||||
return int32_t((a.x + a.y) / 2.0f);
|
||||
}
|
||||
static int2 float2_to_int2(const float2 &a)
|
||||
{
|
||||
return int2(a.x, a.y);
|
||||
}
|
||||
static bool float2_to_bool(const float2 &a)
|
||||
{
|
||||
return !math::is_zero(a);
|
||||
|
@ -114,6 +122,10 @@ static int float3_to_int(const float3 &a)
|
|||
{
|
||||
return int((a.x + a.y + a.z) / 3.0f);
|
||||
}
|
||||
static int2 float3_to_int2(const float3 &a)
|
||||
{
|
||||
return int2(a.x, a.y);
|
||||
}
|
||||
static float2 float3_to_float2(const float3 &a)
|
||||
{
|
||||
return float2(a);
|
||||
|
@ -136,6 +148,10 @@ static int8_t int_to_int8(const int32_t &a)
|
|||
return std::clamp(
|
||||
a, int(std::numeric_limits<int8_t>::min()), int(std::numeric_limits<int8_t>::max()));
|
||||
}
|
||||
static int2 int_to_int2(const int32_t &a)
|
||||
{
|
||||
return int2(a);
|
||||
}
|
||||
static float int_to_float(const int32_t &a)
|
||||
{
|
||||
return float(a);
|
||||
|
@ -157,6 +173,39 @@ static ColorGeometry4b int_to_byte_color(const int32_t &a)
|
|||
return int_to_color(a).encode();
|
||||
}
|
||||
|
||||
static bool int2_to_bool(const int2 &a)
|
||||
{
|
||||
return !math::is_zero(a);
|
||||
}
|
||||
static float2 int2_to_float2(const int2 &a)
|
||||
{
|
||||
return float2(a);
|
||||
}
|
||||
static int int2_to_int(const int2 &a)
|
||||
{
|
||||
return math::midpoint(a.x, a.y);
|
||||
}
|
||||
static int8_t int2_to_int8(const int2 &a)
|
||||
{
|
||||
return int_to_int8(int2_to_int(a));
|
||||
}
|
||||
static float int2_to_float(const int2 &a)
|
||||
{
|
||||
return float2_to_float(float2(a));
|
||||
}
|
||||
static float3 int2_to_float3(const int2 &a)
|
||||
{
|
||||
return float3(float(a.x), float(a.y), 0.0f);
|
||||
}
|
||||
static ColorGeometry4f int2_to_color(const int2 &a)
|
||||
{
|
||||
return ColorGeometry4f(float(a.x), float(a.y), 0.0f, 1.0f);
|
||||
}
|
||||
static ColorGeometry4b int2_to_byte_color(const int2 &a)
|
||||
{
|
||||
return int2_to_color(a).encode();
|
||||
}
|
||||
|
||||
static bool int8_to_bool(const int8_t &a)
|
||||
{
|
||||
return a > 0;
|
||||
|
@ -165,6 +214,10 @@ static int int8_to_int(const int8_t &a)
|
|||
{
|
||||
return int(a);
|
||||
}
|
||||
static int2 int8_to_int2(const int8_t &a)
|
||||
{
|
||||
return int2(a);
|
||||
}
|
||||
static float int8_to_float(const int8_t &a)
|
||||
{
|
||||
return float(a);
|
||||
|
@ -198,6 +251,10 @@ static int32_t bool_to_int(const bool &a)
|
|||
{
|
||||
return int32_t(a);
|
||||
}
|
||||
static int2 bool_to_int2(const bool &a)
|
||||
{
|
||||
return int2(a);
|
||||
}
|
||||
static float2 bool_to_float2(const bool &a)
|
||||
{
|
||||
return (a) ? float2(1.0f) : float2(0.0f);
|
||||
|
@ -227,6 +284,10 @@ static int32_t color_to_int(const ColorGeometry4f &a)
|
|||
{
|
||||
return int(rgb_to_grayscale(a));
|
||||
}
|
||||
static int2 color_to_int2(const ColorGeometry4f &a)
|
||||
{
|
||||
return int2(a.r, a.g);
|
||||
}
|
||||
static int8_t color_to_int8(const ColorGeometry4f &a)
|
||||
{
|
||||
return int_to_int8(color_to_int(a));
|
||||
|
@ -256,6 +317,10 @@ static int32_t byte_color_to_int(const ColorGeometry4b &a)
|
|||
{
|
||||
return color_to_int(a.decode());
|
||||
}
|
||||
static int2 byte_color_to_int2(const ColorGeometry4b &a)
|
||||
{
|
||||
return int2(a.r, a.g);
|
||||
}
|
||||
static int8_t byte_color_to_int8(const ColorGeometry4b &a)
|
||||
{
|
||||
return color_to_int8(a.decode());
|
||||
|
@ -280,6 +345,7 @@ static DataTypeConversions create_implicit_conversions()
|
|||
add_implicit_conversion<float, float2, float_to_float2>(conversions);
|
||||
add_implicit_conversion<float, float3, float_to_float3>(conversions);
|
||||
add_implicit_conversion<float, int32_t, float_to_int>(conversions);
|
||||
add_implicit_conversion<float, int2, float_to_int2>(conversions);
|
||||
add_implicit_conversion<float, bool, float_to_bool>(conversions);
|
||||
add_implicit_conversion<float, int8_t, float_to_int8>(conversions);
|
||||
add_implicit_conversion<float, ColorGeometry4f, float_to_color>(conversions);
|
||||
|
@ -288,6 +354,7 @@ static DataTypeConversions create_implicit_conversions()
|
|||
add_implicit_conversion<float2, float3, float2_to_float3>(conversions);
|
||||
add_implicit_conversion<float2, float, float2_to_float>(conversions);
|
||||
add_implicit_conversion<float2, int32_t, float2_to_int>(conversions);
|
||||
add_implicit_conversion<float2, int2, float2_to_int2>(conversions);
|
||||
add_implicit_conversion<float2, bool, float2_to_bool>(conversions);
|
||||
add_implicit_conversion<float2, int8_t, float2_to_int8>(conversions);
|
||||
add_implicit_conversion<float2, ColorGeometry4f, float2_to_color>(conversions);
|
||||
|
@ -297,20 +364,32 @@ static DataTypeConversions create_implicit_conversions()
|
|||
add_implicit_conversion<float3, int8_t, float3_to_int8>(conversions);
|
||||
add_implicit_conversion<float3, float, float3_to_float>(conversions);
|
||||
add_implicit_conversion<float3, int32_t, float3_to_int>(conversions);
|
||||
add_implicit_conversion<float3, int2, float3_to_int2>(conversions);
|
||||
add_implicit_conversion<float3, float2, float3_to_float2>(conversions);
|
||||
add_implicit_conversion<float3, ColorGeometry4f, float3_to_color>(conversions);
|
||||
add_implicit_conversion<float3, ColorGeometry4b, float3_to_byte_color>(conversions);
|
||||
|
||||
add_implicit_conversion<int32_t, bool, int_to_bool>(conversions);
|
||||
add_implicit_conversion<int32_t, int8_t, int_to_int8>(conversions);
|
||||
add_implicit_conversion<int32_t, int2, int_to_int2>(conversions);
|
||||
add_implicit_conversion<int32_t, float, int_to_float>(conversions);
|
||||
add_implicit_conversion<int32_t, float2, int_to_float2>(conversions);
|
||||
add_implicit_conversion<int32_t, float3, int_to_float3>(conversions);
|
||||
add_implicit_conversion<int32_t, ColorGeometry4f, int_to_color>(conversions);
|
||||
add_implicit_conversion<int32_t, ColorGeometry4b, int_to_byte_color>(conversions);
|
||||
|
||||
add_implicit_conversion<int2, bool, int2_to_bool>(conversions);
|
||||
add_implicit_conversion<int2, int8_t, int2_to_int8>(conversions);
|
||||
add_implicit_conversion<int2, int, int2_to_int>(conversions);
|
||||
add_implicit_conversion<int2, float, int2_to_float>(conversions);
|
||||
add_implicit_conversion<int2, float2, int2_to_float2>(conversions);
|
||||
add_implicit_conversion<int2, float3, int2_to_float3>(conversions);
|
||||
add_implicit_conversion<int2, ColorGeometry4f, int2_to_color>(conversions);
|
||||
add_implicit_conversion<int2, ColorGeometry4b, int2_to_byte_color>(conversions);
|
||||
|
||||
add_implicit_conversion<int8_t, bool, int8_to_bool>(conversions);
|
||||
add_implicit_conversion<int8_t, int32_t, int8_to_int>(conversions);
|
||||
add_implicit_conversion<int8_t, int2, int8_to_int2>(conversions);
|
||||
add_implicit_conversion<int8_t, float, int8_to_float>(conversions);
|
||||
add_implicit_conversion<int8_t, float2, int8_to_float2>(conversions);
|
||||
add_implicit_conversion<int8_t, float3, int8_to_float3>(conversions);
|
||||
|
@ -320,6 +399,7 @@ static DataTypeConversions create_implicit_conversions()
|
|||
add_implicit_conversion<bool, float, bool_to_float>(conversions);
|
||||
add_implicit_conversion<bool, int8_t, bool_to_int8>(conversions);
|
||||
add_implicit_conversion<bool, int32_t, bool_to_int>(conversions);
|
||||
add_implicit_conversion<bool, int2, bool_to_int2>(conversions);
|
||||
add_implicit_conversion<bool, float2, bool_to_float2>(conversions);
|
||||
add_implicit_conversion<bool, float3, bool_to_float3>(conversions);
|
||||
add_implicit_conversion<bool, ColorGeometry4f, bool_to_color>(conversions);
|
||||
|
@ -329,6 +409,7 @@ static DataTypeConversions create_implicit_conversions()
|
|||
add_implicit_conversion<ColorGeometry4f, int8_t, color_to_int8>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4f, float, color_to_float>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4f, int32_t, color_to_int>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4f, int2, color_to_int2>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4f, float2, color_to_float2>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4f, float3, color_to_float3>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4f, ColorGeometry4b, color_to_byte_color>(conversions);
|
||||
|
@ -337,6 +418,7 @@ static DataTypeConversions create_implicit_conversions()
|
|||
add_implicit_conversion<ColorGeometry4b, int8_t, byte_color_to_int8>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4b, float, byte_color_to_float>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4b, int32_t, byte_color_to_int>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4b, int2, byte_color_to_int2>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4b, float2, byte_color_to_float2>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4b, float3, byte_color_to_float3>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4b, ColorGeometry4f, byte_color_to_color>(conversions);
|
||||
|
|
|
@ -73,7 +73,7 @@ inline void gather(const VArray<T> &src,
|
|||
{
|
||||
BLI_assert(indices.size() == dst.size());
|
||||
threading::parallel_for(indices.index_range(), grain_size, [&](const IndexRange range) {
|
||||
src.materialize_compressed_to_uninitialized(indices.slice(range), dst.slice(range).data());
|
||||
src.materialize_compressed_to_uninitialized(indices.slice(range), dst.slice(range));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \file
|
||||
* \ingroup bli
|
||||
*
|
||||
* This file only exists to forward declare `blender::ImplicitSharingInfo` in C code.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace blender {
|
||||
class ImplicitSharingInfo;
|
||||
}
|
||||
using ImplicitSharingInfoHandle = blender::ImplicitSharingInfo;
|
||||
|
||||
#else
|
||||
|
||||
typedef struct ImplicitSharingInfoHandle ImplicitSharingInfoHandle;
|
||||
|
||||
#endif
|
|
@ -194,11 +194,22 @@ inline T interpolate(const T &a, const T &b, const FactorT &t)
|
|||
|
||||
template<typename T> inline T midpoint(const T &a, const T &b)
|
||||
{
|
||||
auto result = (a + b) * T(0.5);
|
||||
if constexpr (std::is_integral_v<T>) {
|
||||
result = std::round(result);
|
||||
/** See std::midpoint from C++20. */
|
||||
using Unsigned = std::make_unsigned_t<T>;
|
||||
int sign = 1;
|
||||
Unsigned smaller = a;
|
||||
Unsigned larger = b;
|
||||
if (a > b) {
|
||||
sign = -1;
|
||||
smaller = b;
|
||||
larger = a;
|
||||
}
|
||||
return a + sign * T(Unsigned(larger - smaller) / 2);
|
||||
}
|
||||
else {
|
||||
return (a + b) * T(0.5);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace blender::math
|
||||
|
|
|
@ -243,6 +243,7 @@ set(SRC
|
|||
BLI_hash_tables.hh
|
||||
BLI_heap.h
|
||||
BLI_heap_simple.h
|
||||
BLI_implicit_sharing.h
|
||||
BLI_implicit_sharing.hh
|
||||
BLI_implicit_sharing_ptr.hh
|
||||
BLI_index_mask.hh
|
||||
|
|
|
@ -104,6 +104,8 @@
|
|||
} \
|
||||
(void)0
|
||||
|
||||
#define TIMEIT_BLOCK_VALUE(id) (float)(_timeit_var_##id)
|
||||
|
||||
#define TIMEIT_BLOCK_STATS(id) \
|
||||
{ \
|
||||
printf("%s time (in seconds): %f\n", #id, _timeit_var_##id); \
|
||||
|
|
|
@ -52,6 +52,7 @@ BLI_CPP_TYPE_MAKE(blender::float4x4, CPPTypeFlags::BasicType)
|
|||
BLI_CPP_TYPE_MAKE(int8_t, CPPTypeFlags::BasicType)
|
||||
BLI_CPP_TYPE_MAKE(int16_t, CPPTypeFlags::BasicType)
|
||||
BLI_CPP_TYPE_MAKE(int32_t, CPPTypeFlags::BasicType)
|
||||
BLI_CPP_TYPE_MAKE(blender::int2, CPPTypeFlags::BasicType)
|
||||
BLI_CPP_TYPE_MAKE(int64_t, CPPTypeFlags::BasicType)
|
||||
|
||||
BLI_CPP_TYPE_MAKE(uint8_t, CPPTypeFlags::BasicType)
|
||||
|
@ -80,6 +81,7 @@ void register_cpp_types()
|
|||
BLI_CPP_TYPE_REGISTER(int8_t);
|
||||
BLI_CPP_TYPE_REGISTER(int16_t);
|
||||
BLI_CPP_TYPE_REGISTER(int32_t);
|
||||
BLI_CPP_TYPE_REGISTER(blender::int2);
|
||||
BLI_CPP_TYPE_REGISTER(int64_t);
|
||||
|
||||
BLI_CPP_TYPE_REGISTER(uint8_t);
|
||||
|
|
|
@ -2241,7 +2241,7 @@ static int lib_link_main_data_restore_cb(LibraryIDLinkCallbackData *cb_data)
|
|||
{
|
||||
const int cb_flag = cb_data->cb_flag;
|
||||
ID **id_pointer = cb_data->id_pointer;
|
||||
if (cb_flag & IDWALK_CB_EMBEDDED || *id_pointer == nullptr) {
|
||||
if (cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_EMBEDDED_NOT_OWNING) || *id_pointer == nullptr) {
|
||||
return IDWALK_RET_NOP;
|
||||
}
|
||||
|
||||
|
|
|
@ -273,19 +273,19 @@ static void customdata_version_242(Mesh *me)
|
|||
int a, mtfacen, mcoln;
|
||||
|
||||
if (!me->vdata.totlayer) {
|
||||
CustomData_add_layer_with_data(&me->vdata, CD_MVERT, me->mvert, me->totvert);
|
||||
CustomData_add_layer_with_data(&me->vdata, CD_MVERT, me->mvert, me->totvert, NULL);
|
||||
|
||||
if (me->dvert) {
|
||||
CustomData_add_layer_with_data(&me->vdata, CD_MDEFORMVERT, me->dvert, me->totvert);
|
||||
CustomData_add_layer_with_data(&me->vdata, CD_MDEFORMVERT, me->dvert, me->totvert, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (!me->edata.totlayer) {
|
||||
CustomData_add_layer_with_data(&me->edata, CD_MEDGE, me->medge, me->totedge);
|
||||
CustomData_add_layer_with_data(&me->edata, CD_MEDGE, me->medge, me->totedge, NULL);
|
||||
}
|
||||
|
||||
if (!me->fdata.totlayer) {
|
||||
CustomData_add_layer_with_data(&me->fdata, CD_MFACE, me->mface, me->totface);
|
||||
CustomData_add_layer_with_data(&me->fdata, CD_MFACE, me->mface, me->totface, NULL);
|
||||
|
||||
if (me->tface) {
|
||||
if (me->mcol) {
|
||||
|
@ -308,7 +308,7 @@ static void customdata_version_242(Mesh *me)
|
|||
me->tface = NULL;
|
||||
}
|
||||
else if (me->mcol) {
|
||||
CustomData_add_layer_with_data(&me->fdata, CD_MCOL, me->mcol, me->totface);
|
||||
CustomData_add_layer_with_data(&me->fdata, CD_MCOL, me->mcol, me->totface, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -517,16 +517,16 @@ void BM_mesh_copy_init_customdata_from_mesh_array(BMesh *bm_dst,
|
|||
&me_src->ldata, CD_MASK_BMESH.pmask);
|
||||
|
||||
if (i == 0) {
|
||||
CustomData_copy(&mesh_vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy(&mesh_edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy(&mesh_pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy(&mesh_ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy_layout(&mesh_vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy_layout(&mesh_edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy_layout(&mesh_pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy_layout(&mesh_ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
|
||||
}
|
||||
else {
|
||||
CustomData_merge(&mesh_vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
|
||||
CustomData_merge(&mesh_edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
|
||||
CustomData_merge(&mesh_pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
|
||||
CustomData_merge(&mesh_ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
|
||||
CustomData_merge_layout(&mesh_vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
|
||||
CustomData_merge_layout(&mesh_edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
|
||||
CustomData_merge_layout(&mesh_pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
|
||||
CustomData_merge_layout(&mesh_ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(mesh_vdata.layers);
|
||||
|
@ -554,10 +554,10 @@ void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const BMAllocTem
|
|||
allocsize = &bm_mesh_allocsize_default;
|
||||
}
|
||||
|
||||
CustomData_copy(&bm_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy(&bm_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy(&bm_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy(&bm_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy_layout(&bm_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy_layout(&bm_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy_layout(&bm_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy_layout(&bm_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
|
||||
|
||||
CustomData_bmesh_init_pool(&bm_dst->vdata, allocsize->totvert, BM_VERT);
|
||||
CustomData_bmesh_init_pool(&bm_dst->edata, allocsize->totedge, BM_EDGE);
|
||||
|
|
|
@ -268,10 +268,10 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
|
|||
if (me->totvert == 0) {
|
||||
if (is_new) {
|
||||
/* No verts? still copy custom-data layout. */
|
||||
CustomData_copy(&mesh_vdata, &bm->vdata, mask.vmask, CD_CONSTRUCT, 0);
|
||||
CustomData_copy(&mesh_edata, &bm->edata, mask.emask, CD_CONSTRUCT, 0);
|
||||
CustomData_copy(&mesh_pdata, &bm->pdata, mask.pmask, CD_CONSTRUCT, 0);
|
||||
CustomData_copy(&mesh_ldata, &bm->ldata, mask.lmask, CD_CONSTRUCT, 0);
|
||||
CustomData_copy_layout(&mesh_vdata, &bm->vdata, mask.vmask, CD_CONSTRUCT, 0);
|
||||
CustomData_copy_layout(&mesh_edata, &bm->edata, mask.emask, CD_CONSTRUCT, 0);
|
||||
CustomData_copy_layout(&mesh_pdata, &bm->pdata, mask.pmask, CD_CONSTRUCT, 0);
|
||||
CustomData_copy_layout(&mesh_ldata, &bm->ldata, mask.lmask, CD_CONSTRUCT, 0);
|
||||
|
||||
CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT);
|
||||
CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE);
|
||||
|
@ -287,16 +287,20 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
|
|||
}
|
||||
|
||||
if (is_new) {
|
||||
CustomData_copy(&mesh_vdata, &bm->vdata, mask.vmask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy(&mesh_edata, &bm->edata, mask.emask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy(&mesh_pdata, &bm->pdata, mask.pmask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy(&mesh_ldata, &bm->ldata, mask.lmask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy_layout(&mesh_vdata, &bm->vdata, mask.vmask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy_layout(&mesh_edata, &bm->edata, mask.emask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy_layout(&mesh_pdata, &bm->pdata, mask.pmask, CD_SET_DEFAULT, 0);
|
||||
CustomData_copy_layout(&mesh_ldata, &bm->ldata, mask.lmask, CD_SET_DEFAULT, 0);
|
||||
}
|
||||
else {
|
||||
CustomData_bmesh_merge(&mesh_vdata, &bm->vdata, mask.vmask, CD_SET_DEFAULT, bm, BM_VERT);
|
||||
CustomData_bmesh_merge(&mesh_edata, &bm->edata, mask.emask, CD_SET_DEFAULT, bm, BM_EDGE);
|
||||
CustomData_bmesh_merge(&mesh_pdata, &bm->pdata, mask.pmask, CD_SET_DEFAULT, bm, BM_FACE);
|
||||
CustomData_bmesh_merge(&mesh_ldata, &bm->ldata, mask.lmask, CD_SET_DEFAULT, bm, BM_LOOP);
|
||||
CustomData_bmesh_merge_layout(
|
||||
&mesh_vdata, &bm->vdata, mask.vmask, CD_SET_DEFAULT, bm, BM_VERT);
|
||||
CustomData_bmesh_merge_layout(
|
||||
&mesh_edata, &bm->edata, mask.emask, CD_SET_DEFAULT, bm, BM_EDGE);
|
||||
CustomData_bmesh_merge_layout(
|
||||
&mesh_pdata, &bm->pdata, mask.pmask, CD_SET_DEFAULT, bm, BM_FACE);
|
||||
CustomData_bmesh_merge_layout(
|
||||
&mesh_ldata, &bm->ldata, mask.lmask, CD_SET_DEFAULT, bm, BM_LOOP);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -1394,10 +1398,10 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
|
|||
{
|
||||
CustomData_MeshMasks mask = CD_MASK_MESH;
|
||||
CustomData_MeshMasks_update(&mask, ¶ms->cd_mask_extra);
|
||||
CustomData_copy(&bm->vdata, &me->vdata, mask.vmask, CD_SET_DEFAULT, me->totvert);
|
||||
CustomData_copy(&bm->edata, &me->edata, mask.emask, CD_SET_DEFAULT, me->totedge);
|
||||
CustomData_copy(&bm->ldata, &me->ldata, mask.lmask, CD_SET_DEFAULT, me->totloop);
|
||||
CustomData_copy(&bm->pdata, &me->pdata, mask.pmask, CD_SET_DEFAULT, me->totpoly);
|
||||
CustomData_copy_layout(&bm->vdata, &me->vdata, mask.vmask, CD_SET_DEFAULT, me->totvert);
|
||||
CustomData_copy_layout(&bm->edata, &me->edata, mask.emask, CD_SET_DEFAULT, me->totedge);
|
||||
CustomData_copy_layout(&bm->ldata, &me->ldata, mask.lmask, CD_SET_DEFAULT, me->totloop);
|
||||
CustomData_copy_layout(&bm->pdata, &me->pdata, mask.pmask, CD_SET_DEFAULT, me->totpoly);
|
||||
}
|
||||
|
||||
bool need_select_vert = false;
|
||||
|
@ -1609,10 +1613,10 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
|
|||
CustomData_MeshMasks_update(&mask, cd_mask_extra);
|
||||
}
|
||||
mask.vmask &= ~CD_MASK_SHAPEKEY;
|
||||
CustomData_merge(&bm->vdata, &me->vdata, mask.vmask, CD_CONSTRUCT, me->totvert);
|
||||
CustomData_merge(&bm->edata, &me->edata, mask.emask, CD_CONSTRUCT, me->totedge);
|
||||
CustomData_merge(&bm->ldata, &me->ldata, mask.lmask, CD_CONSTRUCT, me->totloop);
|
||||
CustomData_merge(&bm->pdata, &me->pdata, mask.pmask, CD_CONSTRUCT, me->totpoly);
|
||||
CustomData_merge_layout(&bm->vdata, &me->vdata, mask.vmask, CD_CONSTRUCT, me->totvert);
|
||||
CustomData_merge_layout(&bm->edata, &me->edata, mask.emask, CD_CONSTRUCT, me->totedge);
|
||||
CustomData_merge_layout(&bm->ldata, &me->ldata, mask.lmask, CD_CONSTRUCT, me->totloop);
|
||||
CustomData_merge_layout(&bm->pdata, &me->pdata, mask.pmask, CD_CONSTRUCT, me->totpoly);
|
||||
|
||||
me->runtime->deformed_only = true;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "bmesh.h"
|
||||
#include "intern/bmesh_private.h"
|
||||
|
||||
BMUVOffsets BM_uv_map_get_offsets_n(const BMesh *bm, const int layer)
|
||||
BMUVOffsets BM_uv_map_get_offsets_from_layer(const BMesh *bm, const int layer)
|
||||
{
|
||||
using namespace blender;
|
||||
using namespace blender::bke;
|
||||
|
@ -46,7 +46,8 @@ BMUVOffsets BM_uv_map_get_offsets_n(const BMesh *bm, const int layer)
|
|||
|
||||
BMUVOffsets BM_uv_map_get_offsets(const BMesh *bm)
|
||||
{
|
||||
return BM_uv_map_get_offsets_n(bm, CustomData_get_active_layer(&bm->ldata, CD_PROP_FLOAT2));
|
||||
const int layer = CustomData_get_active_layer(&bm->ldata, CD_PROP_FLOAT2);
|
||||
return BM_uv_map_get_offsets_from_layer(bm, layer);
|
||||
}
|
||||
|
||||
static void uv_aspect(const BMLoop *l,
|
||||
|
|
|
@ -11,11 +11,17 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
/**
|
||||
* Retrieve the custom data offsets for layers used for user interaction with a UV map, returns the
|
||||
* active uv map if layer is -1.
|
||||
* Retrieve the custom data offsets for the UV map.
|
||||
* \param layer: The layer index (where 0 is the first UV map).
|
||||
* \return The layer offsets or -1 when not found.
|
||||
*/
|
||||
BMUVOffsets BM_uv_map_get_offsets_from_layer(const BMesh *bm, int layer);
|
||||
|
||||
/**
|
||||
* Retrieve the custom data offsets for layers used for user interaction with the active UV map.
|
||||
* \return The layer offsets or -1 when not found.
|
||||
*/
|
||||
BMUVOffsets BM_uv_map_get_offsets(const BMesh *bm);
|
||||
BMUVOffsets BM_uv_map_get_offsets_n(const BMesh *bm, int layer);
|
||||
|
||||
float BM_loop_uv_calc_edge_length_squared(const BMLoop *l,
|
||||
int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "DRW_engine.h"
|
||||
#include "DRW_render.h"
|
||||
|
||||
#include "ED_gpencil.h"
|
||||
#include "ED_gpencil_legacy.h"
|
||||
#include "ED_view3d.h"
|
||||
|
||||
#include "DNA_gpencil_legacy_types.h"
|
||||
|
|
|
@ -77,8 +77,8 @@ GPU_SHADER_CREATE_INFO(workbench_next_resolve_curvature)
|
|||
GPU_SHADER_CREATE_INFO(workbench_next_resolve_cavity)
|
||||
.define("WORKBENCH_CAVITY")
|
||||
|
||||
/* TODO(@pragma37): GPU_SAMPLER_EXTEND_MODE_REPEAT is set in CavityEffect, it doesn't work
|
||||
here? */
|
||||
/* TODO(@pragma37): GPU_SAMPLER_EXTEND_MODE_REPEAT is set in CavityEffect,
|
||||
* it doesn't work here? */
|
||||
.sampler(8, ImageType::FLOAT_2D, "jitter_tx")
|
||||
|
||||
.uniform_buf(5, "vec4", "cavity_samples[512]");
|
||||
|
|
|
@ -766,12 +766,17 @@ class Texture : NonCopyable {
|
|||
return GPU_texture_height(tx_);
|
||||
}
|
||||
|
||||
int depth() const
|
||||
{
|
||||
return GPU_texture_depth(tx_);
|
||||
}
|
||||
|
||||
int pixel_count() const
|
||||
{
|
||||
return GPU_texture_width(tx_) * GPU_texture_height(tx_);
|
||||
}
|
||||
|
||||
bool depth() const
|
||||
bool is_depth() const
|
||||
{
|
||||
return GPU_texture_has_depth_format(tx_);
|
||||
}
|
||||
|
|
|
@ -80,9 +80,10 @@ bool drw_custom_data_match_attribute(const CustomData *custom_data,
|
|||
int *r_layer_index,
|
||||
eCustomDataType *r_type)
|
||||
{
|
||||
const eCustomDataType possible_attribute_types[8] = {
|
||||
const eCustomDataType possible_attribute_types[9] = {
|
||||
CD_PROP_BOOL,
|
||||
CD_PROP_INT8,
|
||||
CD_PROP_INT32_2D,
|
||||
CD_PROP_INT32,
|
||||
CD_PROP_FLOAT,
|
||||
CD_PROP_FLOAT2,
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "DRW_engine.h"
|
||||
#include "DRW_render.h"
|
||||
|
||||
#include "ED_gpencil.h"
|
||||
#include "ED_gpencil_legacy.h"
|
||||
#include "GPU_batch.h"
|
||||
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
|
|
@ -395,6 +395,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object,
|
|||
case CD_PROP_BOOL:
|
||||
case CD_PROP_INT8:
|
||||
case CD_PROP_INT32:
|
||||
case CD_PROP_INT32_2D:
|
||||
case CD_PROP_FLOAT:
|
||||
case CD_PROP_FLOAT2: {
|
||||
if (layer != -1 && domain.has_value()) {
|
||||
|
|
|
@ -250,7 +250,7 @@ static void pointcloud_extract_position_and_radius(const PointCloud &pointcloud,
|
|||
using namespace blender;
|
||||
|
||||
const bke::AttributeAccessor attributes = pointcloud.attributes();
|
||||
const VArraySpan<float3> positions = attributes.lookup<float3>("position", ATTR_DOMAIN_POINT);
|
||||
const Span<float3> positions = pointcloud.positions();
|
||||
const VArray<float> radii = attributes.lookup<float>("radius", ATTR_DOMAIN_POINT);
|
||||
static GPUVertFormat format = {0};
|
||||
if (format.attr_len == 0) {
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
#include "DNA_view3d_types.h"
|
||||
#include "DNA_world_types.h"
|
||||
|
||||
#include "ED_gpencil.h"
|
||||
#include "ED_gpencil_legacy.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_space_api.h"
|
||||
#include "ED_view3d.h"
|
||||
|
|
|
@ -100,6 +100,7 @@ static uint gpu_component_size_for_attribute_type(eCustomDataType type)
|
|||
* comment #extract_attr_init. */
|
||||
return 3;
|
||||
case CD_PROP_FLOAT2:
|
||||
case CD_PROP_INT32_2D:
|
||||
return 2;
|
||||
case CD_PROP_FLOAT3:
|
||||
return 3;
|
||||
|
@ -116,6 +117,7 @@ static GPUVertFetchMode get_fetch_mode_for_type(eCustomDataType type)
|
|||
switch (type) {
|
||||
case CD_PROP_INT8:
|
||||
case CD_PROP_INT32:
|
||||
case CD_PROP_INT32_2D:
|
||||
return GPU_FETCH_INT_TO_FLOAT;
|
||||
case CD_PROP_BYTE_COLOR:
|
||||
return GPU_FETCH_INT_TO_FLOAT_UNIT;
|
||||
|
@ -128,6 +130,7 @@ static GPUVertCompType get_comp_type_for_type(eCustomDataType type)
|
|||
{
|
||||
switch (type) {
|
||||
case CD_PROP_INT8:
|
||||
case CD_PROP_INT32_2D:
|
||||
case CD_PROP_INT32:
|
||||
return GPU_COMP_I32;
|
||||
case CD_PROP_BYTE_COLOR:
|
||||
|
@ -299,6 +302,9 @@ static void extract_attr(const MeshRenderData *mr,
|
|||
case CD_PROP_INT32:
|
||||
extract_attr_generic<int32_t, int3>(mr, vbo, request);
|
||||
break;
|
||||
case CD_PROP_INT32_2D:
|
||||
extract_attr_generic<int2>(mr, vbo, request);
|
||||
break;
|
||||
case CD_PROP_FLOAT:
|
||||
extract_attr_generic<float, float3>(mr, vbo, request);
|
||||
break;
|
||||
|
|
|
@ -12,7 +12,7 @@ if(WITH_BLENDER)
|
|||
add_subdirectory(curves)
|
||||
add_subdirectory(geometry)
|
||||
add_subdirectory(gizmo_library)
|
||||
add_subdirectory(gpencil)
|
||||
add_subdirectory(gpencil_legacy)
|
||||
add_subdirectory(interface)
|
||||
add_subdirectory(io)
|
||||
add_subdirectory(lattice)
|
||||
|
|
|
@ -746,7 +746,11 @@ void ANIM_frame_channel_y_extents(bContext *C, bAnimContext *ac)
|
|||
|
||||
rctf bounds = {.xmin = FLT_MAX, .xmax = -FLT_MAX, .ymin = FLT_MAX, .ymax = -FLT_MAX};
|
||||
const bool include_handles = false;
|
||||
const float frame_range[2] = {window_region->v2d.cur.xmin, window_region->v2d.cur.xmax};
|
||||
float frame_range[2] = {window_region->v2d.cur.xmin, window_region->v2d.cur.xmax};
|
||||
if (ac->scene->r.flag & SCER_PRV_RANGE) {
|
||||
frame_range[0] = ac->scene->r.psfra;
|
||||
frame_range[1] = ac->scene->r.pefra;
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
|
||||
rctf channel_bounds;
|
||||
|
|
|
@ -741,7 +741,7 @@ bool ANIM_driver_vars_paste(ReportList *reports, FCurve *fcu, bool replace)
|
|||
|
||||
/* sanity checks */
|
||||
if (BLI_listbase_is_empty(&driver_vars_copybuf)) {
|
||||
BKE_report(reports, RPT_ERROR, "No driver variables in clipboard to paste");
|
||||
BKE_report(reports, RPT_ERROR, "No driver variables in the internal clipboard to paste");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1257,7 +1257,7 @@ void ANIM_OT_paste_driver_button(wmOperatorType *ot)
|
|||
/* identifiers */
|
||||
ot->name = "Paste Driver";
|
||||
ot->idname = "ANIM_OT_paste_driver_button";
|
||||
ot->description = "Paste the driver in the clipboard to the highlighted button";
|
||||
ot->description = "Paste the driver in the internal clipboard to the highlighted button";
|
||||
|
||||
/* callbacks */
|
||||
ot->exec = paste_driver_button_exec;
|
||||
|
|
|
@ -123,7 +123,7 @@ static void poselib_keytag_pose(bContext *C, Scene *scene, PoseBlendData *pbd)
|
|||
}
|
||||
|
||||
bPose *pose = pbd->ob->pose;
|
||||
bAction *act = pbd->act;
|
||||
bAction *act = poselib_action_to_blend(pbd);
|
||||
|
||||
KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
|
||||
ListBase dsources = {NULL, NULL};
|
||||
|
|
|
@ -798,7 +798,7 @@ static int pose_copy_exec(bContext *C, wmOperator *op)
|
|||
BLI_listbase_clear(&temp_bmain->armatures);
|
||||
BKE_main_free(temp_bmain);
|
||||
/* We are all done! */
|
||||
BKE_report(op->reports, RPT_INFO, "Copied pose to buffer");
|
||||
BKE_report(op->reports, RPT_INFO, "Copied pose to internal clipboard");
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
|
@ -807,7 +807,7 @@ void POSE_OT_copy(wmOperatorType *ot)
|
|||
/* identifiers */
|
||||
ot->name = "Copy Pose";
|
||||
ot->idname = "POSE_OT_copy";
|
||||
ot->description = "Copies the current pose of the selected bones to copy/paste buffer";
|
||||
ot->description = "Copy the current pose of the selected bones to the internal clipboard";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = pose_copy_exec;
|
||||
|
@ -846,13 +846,13 @@ static int pose_paste_exec(bContext *C, wmOperator *op)
|
|||
|
||||
BLI_path_join(str, sizeof(str), BKE_tempdir_base(), "copybuffer_pose.blend");
|
||||
if (!BKE_copybuffer_read(tmp_bmain, str, op->reports, FILTER_ID_OB)) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Copy buffer is empty");
|
||||
BKE_report(op->reports, RPT_ERROR, "Internal clipboard is empty");
|
||||
BKE_main_free(tmp_bmain);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
/* Make sure data from this file is usable for pose paste. */
|
||||
if (BLI_listbase_count_at_most(&tmp_bmain->objects, 2) != 1) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Copy buffer is not from pose mode");
|
||||
BKE_report(op->reports, RPT_ERROR, "Internal clipboard is not from pose mode");
|
||||
BKE_main_free(tmp_bmain);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
@ -860,7 +860,7 @@ static int pose_paste_exec(bContext *C, wmOperator *op)
|
|||
Object *object_from = tmp_bmain->objects.first;
|
||||
bPose *pose_from = object_from->pose;
|
||||
if (pose_from == NULL) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Copy buffer has no pose");
|
||||
BKE_report(op->reports, RPT_ERROR, "Internal clipboard has no pose");
|
||||
BKE_main_free(tmp_bmain);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#define DIAL_RESOLUTION 48
|
||||
|
||||
/**
|
||||
* Data for common interactions. Used in gizmo_library_utils.c functions.
|
||||
*/
|
||||
|
@ -73,6 +75,13 @@ bool gizmo_window_project_2d(bContext *C,
|
|||
bool gizmo_window_project_3d(
|
||||
bContext *C, const struct wmGizmo *gz, const float mval[2], bool use_offset, float r_co[3]);
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Gizmo RNA Utils. */
|
||||
|
||||
struct wmGizmo *gizmo_find_from_properties(const struct IDProperty *properties,
|
||||
const int spacetype,
|
||||
const int regionid);
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Gizmo drawing */
|
||||
|
||||
|
|
|
@ -15,12 +15,15 @@
|
|||
#include "DNA_view3d_types.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_main.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "ED_screen.h"
|
||||
#include "ED_view3d.h"
|
||||
|
||||
#include "CLG_log.h"
|
||||
|
@ -245,3 +248,38 @@ bool gizmo_window_project_3d(
|
|||
copy_v2_v2(r_co, co);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name RNA Utils
|
||||
* \{ */
|
||||
|
||||
/* Based on 'rna_GizmoProperties_find_operator'. */
|
||||
wmGizmo *gizmo_find_from_properties(const struct IDProperty *properties,
|
||||
const int spacetype,
|
||||
const int regionid)
|
||||
{
|
||||
for (bScreen *screen = G_MAIN->screens.first; screen; screen = screen->id.next) {
|
||||
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
||||
if (!ELEM(spacetype, SPACE_TYPE_ANY, area->spacetype)) {
|
||||
continue;
|
||||
}
|
||||
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
|
||||
if (region->gizmo_map == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (!ELEM(regionid, RGN_TYPE_ANY, region->regiontype)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, WM_gizmomap_group_list(region->gizmo_map)) {
|
||||
LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
|
||||
if (gz->properties == properties) {
|
||||
return gz;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
#include "../gizmo_library_intern.h"
|
||||
|
||||
/* to use custom arrows exported to geom_arrow_gizmo.c */
|
||||
//#define USE_GIZMO_CUSTOM_ARROWS
|
||||
// #define USE_GIZMO_CUSTOM_ARROWS
|
||||
|
||||
/* Margin to add when selecting the arrow. */
|
||||
#define ARROW_SELECT_THRESHOLD_PX (5)
|
||||
|
@ -115,6 +115,29 @@ static void arrow_draw_geom(const ArrowGizmo3D *arrow,
|
|||
immUniform1f("lineWidth", arrow->gizmo.line_width * U.pixelsize);
|
||||
wm_gizmo_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GPU_PRIM_LINE_LOOP);
|
||||
}
|
||||
else if (draw_style == ED_GIZMO_ARROW_STYLE_PLANE) {
|
||||
const float scale = 0.1f;
|
||||
const float verts[4][3] = {
|
||||
{0, 0, 0},
|
||||
{scale, 0, scale},
|
||||
{0, 0, 2 * scale},
|
||||
{-scale, 0, scale},
|
||||
};
|
||||
|
||||
const float color_inner[4] = {UNPACK3(color), color[3] * 0.5f};
|
||||
|
||||
/* Translate to line end. */
|
||||
GPU_matrix_push();
|
||||
GPU_matrix_translate_3f(0.0f, 0.0f, arrow_length);
|
||||
|
||||
immUniform1f("lineWidth", arrow->gizmo.line_width * U.pixelsize);
|
||||
wm_gizmo_vec_draw(color, verts, ARRAY_SIZE(verts), pos, GPU_PRIM_LINE_LOOP);
|
||||
|
||||
immUnbindProgram();
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
wm_gizmo_vec_draw(color_inner, verts, ARRAY_SIZE(verts), pos, GPU_PRIM_TRI_FAN);
|
||||
GPU_matrix_pop();
|
||||
}
|
||||
else {
|
||||
#ifdef USE_GIZMO_CUSTOM_ARROWS
|
||||
wm_gizmo_geometryinfo_draw(&wm_gizmo_geom_data_arrow, select, color);
|
||||
|
@ -177,6 +200,19 @@ static void arrow_draw_geom(const ArrowGizmo3D *arrow,
|
|||
if (unbind_shader) {
|
||||
immUnbindProgram();
|
||||
}
|
||||
|
||||
if (draw_options & ED_GIZMO_ARROW_DRAW_FLAG_ORIGIN) {
|
||||
const float point_size = 10 * U.pixelsize;
|
||||
GPU_program_point_size(true);
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
|
||||
immUniform1f("size", point_size);
|
||||
immUniformColor4fv(color);
|
||||
immBegin(GPU_PRIM_POINTS, 1);
|
||||
immVertex3f(pos, 0.0f, 0.0f, 0.0f);
|
||||
immEnd();
|
||||
immUnbindProgram();
|
||||
GPU_program_point_size(false);
|
||||
}
|
||||
}
|
||||
|
||||
static void arrow_draw_intern(ArrowGizmo3D *arrow, const bool select, const bool highlight)
|
||||
|
@ -504,10 +540,12 @@ static void GIZMO_GT_arrow_3d(wmGizmoType *gzt)
|
|||
{ED_GIZMO_ARROW_STYLE_CROSS, "CROSS", 0, "Cross", ""},
|
||||
{ED_GIZMO_ARROW_STYLE_BOX, "BOX", 0, "Box", ""},
|
||||
{ED_GIZMO_ARROW_STYLE_CONE, "CONE", 0, "Cone", ""},
|
||||
{ED_GIZMO_ARROW_STYLE_PLANE, "PLANE", 0, "Plane", ""},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
static EnumPropertyItem rna_enum_draw_options_items[] = {
|
||||
{ED_GIZMO_ARROW_DRAW_FLAG_STEM, "STEM", 0, "Stem", ""},
|
||||
{ED_GIZMO_ARROW_DRAW_FLAG_ORIGIN, "ORIGIN", 0, "Origin", ""},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
static EnumPropertyItem rna_enum_transform_items[] = {
|
||||
|
|
|
@ -71,7 +71,6 @@ typedef struct DialInteraction {
|
|||
} DialInteraction;
|
||||
|
||||
#define DIAL_WIDTH 1.0f
|
||||
#define DIAL_RESOLUTION 48
|
||||
|
||||
/* Could make option, negative to clip more (don't show when view aligned). */
|
||||
#define DIAL_CLIP_BIAS 0.02
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "../gizmo_library_intern.h"
|
||||
|
||||
#define MVAL_MAX_PX_DIST 12.0f
|
||||
#define RING_2D_RESOLUTION 32
|
||||
|
||||
typedef struct MoveGizmo3D {
|
||||
wmGizmo gizmo;
|
||||
|
@ -78,8 +79,6 @@ typedef struct MoveInteraction {
|
|||
|
||||
} MoveInteraction;
|
||||
|
||||
#define DIAL_RESOLUTION 32
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static void move_geom_draw(const wmGizmo *gz,
|
||||
|
@ -116,10 +115,10 @@ static void move_geom_draw(const wmGizmo *gz,
|
|||
|
||||
if (draw_style == ED_GIZMO_MOVE_STYLE_RING_2D) {
|
||||
if (filled) {
|
||||
imm_draw_circle_fill_3d(pos, 0.0f, 0.0f, radius, DIAL_RESOLUTION);
|
||||
imm_draw_circle_fill_3d(pos, 0.0f, 0.0f, radius, RING_2D_RESOLUTION);
|
||||
}
|
||||
else {
|
||||
imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, radius, DIAL_RESOLUTION);
|
||||
imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, radius, RING_2D_RESOLUTION);
|
||||
}
|
||||
}
|
||||
else if (draw_style == ED_GIZMO_MOVE_STYLE_CROSS_2D) {
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
#include "BLI_math.h"
|
||||
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
|
@ -42,36 +44,135 @@ static float verts_plane[4][3] = {
|
|||
{-1, 1, 0},
|
||||
};
|
||||
|
||||
typedef struct PrimitiveGizmo3D {
|
||||
wmGizmo gizmo;
|
||||
|
||||
int draw_style;
|
||||
float arc_inner_factor;
|
||||
bool draw_inner;
|
||||
} PrimitiveGizmo3D;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name RNA callbacks */
|
||||
|
||||
static void gizmo_primitive_draw_geom(const float col_inner[4],
|
||||
const float col_outer[4],
|
||||
const int draw_style)
|
||||
static PrimitiveGizmo3D *gizmo_primitive_rna_find_operator(PointerRNA *ptr)
|
||||
{
|
||||
float(*verts)[3];
|
||||
uint vert_count = 0;
|
||||
|
||||
if (draw_style == ED_GIZMO_PRIMITIVE_STYLE_PLANE) {
|
||||
verts = verts_plane;
|
||||
vert_count = ARRAY_SIZE(verts_plane);
|
||||
}
|
||||
|
||||
if (vert_count > 0) {
|
||||
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
wm_gizmo_vec_draw(col_inner, verts, vert_count, pos, GPU_PRIM_TRI_FAN);
|
||||
wm_gizmo_vec_draw(col_outer, verts, vert_count, pos, GPU_PRIM_LINE_LOOP);
|
||||
immUnbindProgram();
|
||||
}
|
||||
return (PrimitiveGizmo3D *)gizmo_find_from_properties(ptr->data, SPACE_TYPE_ANY, RGN_TYPE_ANY);
|
||||
}
|
||||
|
||||
static void gizmo_primitive_draw_intern(wmGizmo *gz,
|
||||
const bool UNUSED(select),
|
||||
const bool highlight)
|
||||
static int gizmo_primitive_rna__draw_style_get_fn(struct PointerRNA *ptr,
|
||||
struct PropertyRNA *UNUSED(prop))
|
||||
{
|
||||
PrimitiveGizmo3D *gz_prim = gizmo_primitive_rna_find_operator(ptr);
|
||||
return gz_prim->draw_style;
|
||||
}
|
||||
|
||||
static void gizmo_primitive_rna__draw_style_set_fn(struct PointerRNA *ptr,
|
||||
struct PropertyRNA *UNUSED(prop),
|
||||
int value)
|
||||
{
|
||||
PrimitiveGizmo3D *gz_prim = gizmo_primitive_rna_find_operator(ptr);
|
||||
gz_prim->draw_style = value;
|
||||
}
|
||||
|
||||
static float gizmo_primitive_rna__arc_inner_factor_get_fn(struct PointerRNA *ptr,
|
||||
struct PropertyRNA *UNUSED(prop))
|
||||
{
|
||||
PrimitiveGizmo3D *gz_prim = gizmo_primitive_rna_find_operator(ptr);
|
||||
return gz_prim->arc_inner_factor;
|
||||
}
|
||||
|
||||
static void gizmo_primitive_rna__arc_inner_factor_set_fn(struct PointerRNA *ptr,
|
||||
struct PropertyRNA *UNUSED(prop),
|
||||
float value)
|
||||
{
|
||||
PrimitiveGizmo3D *gz_prim = gizmo_primitive_rna_find_operator(ptr);
|
||||
gz_prim->arc_inner_factor = value;
|
||||
}
|
||||
|
||||
static bool gizmo_primitive_rna__draw_inner_get_fn(struct PointerRNA *ptr,
|
||||
struct PropertyRNA *UNUSED(prop))
|
||||
{
|
||||
PrimitiveGizmo3D *gz_prim = gizmo_primitive_rna_find_operator(ptr);
|
||||
return gz_prim->draw_inner;
|
||||
}
|
||||
|
||||
static void gizmo_primitive_rna__draw_inner_set_fn(struct PointerRNA *ptr,
|
||||
struct PropertyRNA *UNUSED(prop),
|
||||
bool value)
|
||||
{
|
||||
PrimitiveGizmo3D *gz_prim = gizmo_primitive_rna_find_operator(ptr);
|
||||
gz_prim->draw_inner = value;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static void gizmo_primitive_draw_geom(PrimitiveGizmo3D *gz_prim,
|
||||
const float col_inner[4],
|
||||
const float col_outer[4],
|
||||
const int nsegments,
|
||||
const bool draw_inner)
|
||||
{
|
||||
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
const bool use_polyline_shader = gz_prim->gizmo.line_width > 1.0f;
|
||||
|
||||
if (draw_inner || !use_polyline_shader) {
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
}
|
||||
|
||||
if (draw_inner) {
|
||||
if (gz_prim->draw_style == ED_GIZMO_PRIMITIVE_STYLE_PLANE) {
|
||||
wm_gizmo_vec_draw(col_inner, verts_plane, ARRAY_SIZE(verts_plane), pos, GPU_PRIM_TRI_FAN);
|
||||
}
|
||||
else {
|
||||
immUniformColor4fv(col_inner);
|
||||
if (gz_prim->draw_style == ED_GIZMO_PRIMITIVE_STYLE_CIRCLE) {
|
||||
imm_draw_circle_fill_3d(pos, 0.0f, 0.0f, 1.0f, nsegments);
|
||||
}
|
||||
else {
|
||||
BLI_assert(gz_prim->draw_style == ED_GIZMO_PRIMITIVE_STYLE_ANNULUS);
|
||||
imm_draw_disk_partial_fill_3d(
|
||||
pos, 0.0f, 0.0f, 0.0f, gz_prim->arc_inner_factor, 1.0f, nsegments, 0.0f, 360.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw outline. */
|
||||
|
||||
if (use_polyline_shader) {
|
||||
if (draw_inner) {
|
||||
immUnbindProgram();
|
||||
}
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
|
||||
|
||||
float viewport[4];
|
||||
GPU_viewport_size_get_f(viewport);
|
||||
immUniform2fv("viewportSize", &viewport[2]);
|
||||
immUniform1f("lineWidth", gz_prim->gizmo.line_width * U.pixelsize);
|
||||
}
|
||||
|
||||
if (gz_prim->draw_style == ED_GIZMO_PRIMITIVE_STYLE_PLANE) {
|
||||
wm_gizmo_vec_draw(col_outer, verts_plane, ARRAY_SIZE(verts_plane), pos, GPU_PRIM_LINE_LOOP);
|
||||
}
|
||||
else {
|
||||
immUniformColor4fv(col_outer);
|
||||
if (gz_prim->draw_style == ED_GIZMO_PRIMITIVE_STYLE_CIRCLE) {
|
||||
imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, 1.0f, nsegments);
|
||||
}
|
||||
else {
|
||||
imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, gz_prim->arc_inner_factor, nsegments);
|
||||
imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, 1.0f, nsegments);
|
||||
}
|
||||
}
|
||||
immUnbindProgram();
|
||||
}
|
||||
|
||||
static void gizmo_primitive_draw_intern(wmGizmo *gz, const bool select, const bool highlight)
|
||||
{
|
||||
PrimitiveGizmo3D *gz_prim = (PrimitiveGizmo3D *)gz;
|
||||
|
||||
float color_inner[4], color_outer[4];
|
||||
float matrix_final[4][4];
|
||||
const int draw_style = RNA_enum_get(gz->ptr, "draw_style");
|
||||
|
||||
gizmo_color_get(gz, highlight, color_outer);
|
||||
copy_v4_v4(color_inner, color_outer);
|
||||
|
@ -79,12 +180,15 @@ static void gizmo_primitive_draw_intern(wmGizmo *gz,
|
|||
|
||||
WM_gizmo_calc_matrix_final(gz, matrix_final);
|
||||
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
GPU_matrix_push();
|
||||
GPU_matrix_mul(matrix_final);
|
||||
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
gizmo_primitive_draw_geom(color_inner, color_outer, draw_style);
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
gizmo_primitive_draw_geom(gz_prim,
|
||||
color_inner,
|
||||
color_outer,
|
||||
select ? 24 : DIAL_RESOLUTION,
|
||||
gz_prim->draw_inner || select);
|
||||
|
||||
GPU_matrix_pop();
|
||||
|
||||
|
@ -98,12 +202,12 @@ static void gizmo_primitive_draw_intern(wmGizmo *gz,
|
|||
GPU_matrix_push();
|
||||
GPU_matrix_mul(inter->init_matrix_final);
|
||||
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
gizmo_primitive_draw_geom(color_inner, color_outer, draw_style);
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
gizmo_primitive_draw_geom(
|
||||
gz_prim, color_inner, color_outer, DIAL_RESOLUTION, gz_prim->draw_inner);
|
||||
|
||||
GPU_matrix_pop();
|
||||
}
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
}
|
||||
|
||||
static void gizmo_primitive_draw_select(const bContext *UNUSED(C), wmGizmo *gz, int select_id)
|
||||
|
@ -120,6 +224,12 @@ static void gizmo_primitive_draw(const bContext *UNUSED(C), wmGizmo *gz)
|
|||
static void gizmo_primitive_setup(wmGizmo *gz)
|
||||
{
|
||||
gz->flag |= WM_GIZMO_DRAW_MODAL;
|
||||
|
||||
/* Default Values. */
|
||||
PrimitiveGizmo3D *gz_prim = (PrimitiveGizmo3D *)gz;
|
||||
gz_prim->draw_style = ED_GIZMO_PRIMITIVE_STYLE_PLANE;
|
||||
gz_prim->arc_inner_factor = true;
|
||||
gz_prim->draw_inner = true;
|
||||
}
|
||||
|
||||
static int gizmo_primitive_invoke(bContext *UNUSED(C), wmGizmo *gz, const wmEvent *UNUSED(event))
|
||||
|
@ -148,18 +258,35 @@ static void GIZMO_GT_primitive_3d(wmGizmoType *gzt)
|
|||
gzt->setup = gizmo_primitive_setup;
|
||||
gzt->invoke = gizmo_primitive_invoke;
|
||||
|
||||
gzt->struct_size = sizeof(wmGizmo);
|
||||
gzt->struct_size = sizeof(PrimitiveGizmo3D);
|
||||
|
||||
static EnumPropertyItem rna_enum_draw_style[] = {
|
||||
{ED_GIZMO_PRIMITIVE_STYLE_PLANE, "PLANE", 0, "Plane", ""},
|
||||
{ED_GIZMO_PRIMITIVE_STYLE_CIRCLE, "CIRCLE", 0, "Circle", ""},
|
||||
{ED_GIZMO_PRIMITIVE_STYLE_ANNULUS, "ANNULUS", 0, "Annulus", ""},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
RNA_def_enum(gzt->srna,
|
||||
"draw_style",
|
||||
rna_enum_draw_style,
|
||||
ED_GIZMO_PRIMITIVE_STYLE_PLANE,
|
||||
"Draw Style",
|
||||
"");
|
||||
|
||||
PropertyRNA *prop;
|
||||
prop = RNA_def_enum(gzt->srna,
|
||||
"draw_style",
|
||||
rna_enum_draw_style,
|
||||
ED_GIZMO_PRIMITIVE_STYLE_PLANE,
|
||||
"Draw Style",
|
||||
"");
|
||||
RNA_def_property_enum_funcs_runtime(
|
||||
prop, gizmo_primitive_rna__draw_style_get_fn, gizmo_primitive_rna__draw_style_set_fn, NULL);
|
||||
|
||||
prop = RNA_def_float_factor(
|
||||
gzt->srna, "arc_inner_factor", 0.0f, 0.0f, FLT_MAX, "Arc Inner Factor", "", 0.0f, 1.0f);
|
||||
RNA_def_property_float_funcs_runtime(prop,
|
||||
gizmo_primitive_rna__arc_inner_factor_get_fn,
|
||||
gizmo_primitive_rna__arc_inner_factor_set_fn,
|
||||
NULL);
|
||||
|
||||
prop = RNA_def_boolean(gzt->srna, "draw_inner", true, "Draw Inner", "");
|
||||
RNA_def_property_boolean_funcs_runtime(
|
||||
prop, gizmo_primitive_rna__draw_inner_get_fn, gizmo_primitive_rna__draw_inner_set_fn);
|
||||
}
|
||||
|
||||
void ED_gizmotypes_primitive_3d(void)
|
||||
|
|
|
@ -123,30 +123,9 @@ void ED_gizmotypes_snap_3d_data_get(const struct bContext *C,
|
|||
/** \name RNA callbacks
|
||||
* \{ */
|
||||
|
||||
/* Based on 'rna_GizmoProperties_find_operator'. */
|
||||
static SnapGizmo3D *gizmo_snap_rna_find_operator(PointerRNA *ptr)
|
||||
{
|
||||
IDProperty *properties = ptr->data;
|
||||
for (bScreen *screen = G_MAIN->screens.first; screen; screen = screen->id.next) {
|
||||
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
||||
if (area->spacetype != SPACE_VIEW3D) {
|
||||
continue;
|
||||
}
|
||||
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
|
||||
if (region->regiontype == RGN_TYPE_WINDOW && region->gizmo_map) {
|
||||
wmGizmoMap *gzmap = region->gizmo_map;
|
||||
LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, WM_gizmomap_group_list(gzmap)) {
|
||||
LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
|
||||
if (gz->properties == properties) {
|
||||
return (SnapGizmo3D *)gz;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return (SnapGizmo3D *)gizmo_find_from_properties(ptr->data, SPACE_VIEW3D, RGN_TYPE_WINDOW);
|
||||
}
|
||||
|
||||
static V3DSnapCursorState *gizmo_snap_state_from_rna_get(struct PointerRNA *ptr)
|
||||
|
|
|
@ -77,7 +77,7 @@ if(WITH_POTRACE)
|
|||
endif()
|
||||
|
||||
|
||||
blender_add_lib(bf_editor_gpencil "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
blender_add_lib(bf_editor_gpencil_legacy "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
||||
# RNA_prototypes.h
|
||||
add_dependencies(bf_editor_gpencil bf_rna)
|
||||
add_dependencies(bf_editor_gpencil_legacy bf_rna)
|
|
@ -41,7 +41,7 @@
|
|||
#include "GPU_matrix.h"
|
||||
#include "GPU_state.h"
|
||||
|
||||
#include "ED_gpencil.h"
|
||||
#include "ED_gpencil_legacy.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_space_api.h"
|
||||
#include "ED_view3d.h"
|
|
@ -39,7 +39,7 @@
|
|||
#include "UI_view2d.h"
|
||||
|
||||
#include "ED_clip.h"
|
||||
#include "ED_gpencil.h"
|
||||
#include "ED_gpencil_legacy.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_view3d.h"
|
||||
|
|
@ -52,7 +52,7 @@
|
|||
#include "GPU_state.h"
|
||||
#include "GPU_uniform_buffer.h"
|
||||
|
||||
#include "ED_gpencil.h"
|
||||
#include "ED_gpencil_legacy.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_space_api.h"
|
||||
#include "ED_view3d.h"
|
|
@ -24,7 +24,7 @@
|
|||
#include "BKE_report.h"
|
||||
|
||||
#include "ED_anim_api.h"
|
||||
#include "ED_gpencil.h"
|
||||
#include "ED_gpencil_legacy.h"
|
||||
#include "ED_keyframes_edit.h"
|
||||
#include "ED_markers.h"
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
||||
#include "ED_gpencil.h"
|
||||
#include "ED_gpencil_legacy.h"
|
||||
|
||||
/* Definition of the most important info from a color */
|
||||
typedef struct ColorTemplate {
|
|
@ -26,7 +26,7 @@
|
|||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "ED_gpencil.h"
|
||||
#include "ED_gpencil_legacy.h"
|
||||
|
||||
/* Definition of the most important info from a color */
|
||||
typedef struct ColorTemplate {
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
||||
#include "ED_gpencil.h"
|
||||
#include "ED_gpencil_legacy.h"
|
||||
|
||||
void ED_gpencil_stroke_init_data(bGPDstroke *gps,
|
||||
const float *array,
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
||||
#include "ED_gpencil.h"
|
||||
#include "ED_gpencil_legacy.h"
|
||||
|
||||
/* Definition of the most important info from a color */
|
||||
typedef struct ColorTemplate {
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue