WIP: Vulkan: Initial Immediate Mode Support. #106954
|
@ -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...")
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -201,13 +201,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 +233,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 +283,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 +575,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 +659,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)) {
|
||||
|
|
|
@ -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;
|
||||
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
@ -1102,12 +1101,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 +1384,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -64,6 +64,7 @@ enum {
|
|||
ED_GIZMO_ARROW_STYLE_CROSS = 1,
|
||||
ED_GIZMO_ARROW_STYLE_BOX = 2,
|
||||
ED_GIZMO_ARROW_STYLE_CONE = 3,
|
||||
ED_GIZMO_ARROW_STYLE_PLANE = 4,
|
||||
};
|
||||
|
||||
/* transform */
|
||||
|
@ -78,6 +79,7 @@ enum {
|
|||
enum {
|
||||
/* Show arrow stem. */
|
||||
ED_GIZMO_ARROW_DRAW_FLAG_STEM = (1 << 0),
|
||||
ED_GIZMO_ARROW_DRAW_FLAG_ORIGIN = (1 << 1),
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -233,6 +235,8 @@ enum {
|
|||
|
||||
enum {
|
||||
ED_GIZMO_PRIMITIVE_STYLE_PLANE = 0,
|
||||
ED_GIZMO_PRIMITIVE_STYLE_CIRCLE,
|
||||
ED_GIZMO_PRIMITIVE_STYLE_ANNULUS,
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -116,18 +116,18 @@ static void ui_popup_block_position(wmWindow *window,
|
|||
const int center_x = (block->direction & UI_DIR_CENTER_X) ? size_x / 2 : 0;
|
||||
const int center_y = (block->direction & UI_DIR_CENTER_Y) ? size_y / 2 : 0;
|
||||
|
||||
const int win_x = WM_window_pixels_x(window);
|
||||
const int win_y = WM_window_pixels_y(window);
|
||||
|
||||
/* Take into account maximum size so we don't have to flip on refresh. */
|
||||
const float max_size_x = max_ff(size_x, handle->max_size_x);
|
||||
const float max_size_y = max_ff(size_y, handle->max_size_y);
|
||||
|
||||
short dir1 = 0, dir2 = 0;
|
||||
|
||||
if (!handle->refresh) {
|
||||
bool left = false, right = false, top = false, down = false;
|
||||
|
||||
const int win_x = WM_window_pixels_x(window);
|
||||
const int win_y = WM_window_pixels_y(window);
|
||||
|
||||
/* Take into account maximum size so we don't have to flip on refresh. */
|
||||
const float max_size_x = max_ff(size_x, handle->max_size_x);
|
||||
const float max_size_y = max_ff(size_y, handle->max_size_y);
|
||||
|
||||
/* check if there's space at all */
|
||||
if (butrct.xmin - max_size_x + center_x > 0.0f) {
|
||||
left = true;
|
||||
|
@ -237,6 +237,15 @@ static void ui_popup_block_position(wmWindow *window,
|
|||
}
|
||||
else if (dir1 == UI_DIR_UP) {
|
||||
offset_y = (butrct.ymax - block->rect.ymin) - offset_overlap;
|
||||
|
||||
if (but->type == UI_BTYPE_COLOR && block->rect.ymax + offset_y > win_y - UI_POPUP_MENU_TOP) {
|
||||
/* Shift this down, aligning the top edge close to the window top. */
|
||||
offset_y = win_y - block->rect.ymax - UI_POPUP_MENU_TOP;
|
||||
/* All four corners should be rounded since this no longer button-aligned. */
|
||||
block->direction = UI_DIR_CENTER_Y;
|
||||
dir1 = UI_DIR_CENTER_Y;
|
||||
}
|
||||
|
||||
if (dir2 == UI_DIR_RIGHT) {
|
||||
offset_x = butrct.xmax - block->rect.xmax + center_x;
|
||||
}
|
||||
|
@ -251,6 +260,15 @@ static void ui_popup_block_position(wmWindow *window,
|
|||
}
|
||||
else if (dir1 == UI_DIR_DOWN) {
|
||||
offset_y = (butrct.ymin - block->rect.ymax) + offset_overlap;
|
||||
|
||||
if (but->type == UI_BTYPE_COLOR && block->rect.ymin + offset_y < UI_SCREEN_MARGIN) {
|
||||
/* Shift this up, aligning the bottom edge close to the window bottom. */
|
||||
offset_y = -block->rect.ymin + UI_SCREEN_MARGIN;
|
||||
/* All four corners should be rounded since this no longer button-aligned. */
|
||||
block->direction = UI_DIR_CENTER_Y;
|
||||
dir1 = UI_DIR_CENTER_Y;
|
||||
}
|
||||
|
||||
if (dir2 == UI_DIR_RIGHT) {
|
||||
offset_x = butrct.xmax - block->rect.xmax + center_x;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BLI_array_utils.h"
|
||||
#include "BLI_implicit_sharing.hh"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_task.hh"
|
||||
|
||||
|
@ -273,8 +274,18 @@ static void um_arraystore_cd_compact(CustomData *cdata,
|
|||
}
|
||||
|
||||
if (layer->data) {
|
||||
if (layer->sharing_info) {
|
||||
/* This assumes that the layer is not shared, which it is not here because it has just
|
||||
* been created in #BM_mesh_bm_to_me. The situation is a bit tricky here, because the
|
||||
* layer data may be freed partially below for e.g. vertex groups. A potentially better
|
||||
* solution might be to not pass "dynamic" layers (see `layer_type_is_dynamic`) to the
|
||||
* array store at all. */
|
||||
BLI_assert(layer->sharing_info->is_mutable());
|
||||
MEM_delete(layer->sharing_info);
|
||||
}
|
||||
MEM_freeN(layer->data);
|
||||
layer->data = nullptr;
|
||||
layer->sharing_info = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -278,7 +278,8 @@ int ED_mesh_uv_add(
|
|||
CD_PROP_FLOAT2,
|
||||
MEM_dupallocN(CustomData_get_layer(&me->ldata, CD_PROP_FLOAT2)),
|
||||
me->totloop,
|
||||
unique_name);
|
||||
unique_name,
|
||||
nullptr);
|
||||
|
||||
is_init = true;
|
||||
}
|
||||
|
@ -1143,7 +1144,7 @@ static void mesh_add_verts(Mesh *mesh, int len)
|
|||
|
||||
int totvert = mesh->totvert + len;
|
||||
CustomData vdata;
|
||||
CustomData_copy(&mesh->vdata, &vdata, CD_MASK_MESH.vmask, CD_SET_DEFAULT, totvert);
|
||||
CustomData_copy_layout(&mesh->vdata, &vdata, CD_MASK_MESH.vmask, CD_SET_DEFAULT, totvert);
|
||||
CustomData_copy_data(&mesh->vdata, &vdata, 0, 0, mesh->totvert);
|
||||
|
||||
if (!CustomData_get_layer_named(&vdata, CD_PROP_FLOAT3, "position")) {
|
||||
|
@ -1177,7 +1178,7 @@ static void mesh_add_edges(Mesh *mesh, int len)
|
|||
totedge = mesh->totedge + len;
|
||||
|
||||
/* Update custom-data. */
|
||||
CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, totedge);
|
||||
CustomData_copy_layout(&mesh->edata, &edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, totedge);
|
||||
CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge);
|
||||
|
||||
if (!CustomData_has_layer(&edata, CD_MEDGE)) {
|
||||
|
@ -1210,7 +1211,7 @@ static void mesh_add_loops(Mesh *mesh, int len)
|
|||
totloop = mesh->totloop + len; /* new face count */
|
||||
|
||||
/* update customdata */
|
||||
CustomData_copy(&mesh->ldata, &ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, totloop);
|
||||
CustomData_copy_layout(&mesh->ldata, &ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, totloop);
|
||||
CustomData_copy_data(&mesh->ldata, &ldata, 0, 0, mesh->totloop);
|
||||
|
||||
if (!CustomData_get_layer_named(&ldata, CD_PROP_INT32, ".corner_vert")) {
|
||||
|
@ -1247,7 +1248,7 @@ static void mesh_add_polys(Mesh *mesh, int len)
|
|||
totpoly = mesh->totpoly + len; /* new face count */
|
||||
|
||||
/* update customdata */
|
||||
CustomData_copy(&mesh->pdata, &pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, totpoly);
|
||||
CustomData_copy_layout(&mesh->pdata, &pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, totpoly);
|
||||
CustomData_copy_data(&mesh->pdata, &pdata, 0, 0, mesh->totpoly);
|
||||
|
||||
mesh->poly_offset_indices = static_cast<int *>(
|
||||
|
|
|
@ -105,7 +105,7 @@ static void join_mesh_single(Depsgraph *depsgraph,
|
|||
|
||||
if (me->totvert) {
|
||||
/* standard data */
|
||||
CustomData_merge(&me->vdata, vdata, CD_MASK_MESH.vmask, CD_SET_DEFAULT, totvert);
|
||||
CustomData_merge_layout(&me->vdata, vdata, CD_MASK_MESH.vmask, CD_SET_DEFAULT, totvert);
|
||||
CustomData_copy_data_named(&me->vdata, vdata, 0, *vertofs, me->totvert);
|
||||
|
||||
/* vertex groups */
|
||||
|
@ -205,7 +205,7 @@ static void join_mesh_single(Depsgraph *depsgraph,
|
|||
}
|
||||
|
||||
if (me->totedge) {
|
||||
CustomData_merge(&me->edata, edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, totedge);
|
||||
CustomData_merge_layout(&me->edata, edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, totedge);
|
||||
CustomData_copy_data_named(&me->edata, edata, 0, *edgeofs, me->totedge);
|
||||
|
||||
for (a = 0; a < me->totedge; a++, edge++) {
|
||||
|
@ -226,7 +226,7 @@ static void join_mesh_single(Depsgraph *depsgraph,
|
|||
}
|
||||
}
|
||||
|
||||
CustomData_merge(&me->ldata, ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, totloop);
|
||||
CustomData_merge_layout(&me->ldata, ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, totloop);
|
||||
CustomData_copy_data_named(&me->ldata, ldata, 0, *loopofs, me->totloop);
|
||||
|
||||
for (a = 0; a < me->totloop; a++) {
|
||||
|
@ -250,7 +250,7 @@ static void join_mesh_single(Depsgraph *depsgraph,
|
|||
}
|
||||
}
|
||||
|
||||
CustomData_merge(&me->pdata, pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, totpoly);
|
||||
CustomData_merge_layout(&me->pdata, pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, totpoly);
|
||||
CustomData_copy_data_named(&me->pdata, pdata, 0, *polyofs, me->totpoly);
|
||||
|
||||
/* Apply matmap. In case we don't have material indices yet, create them if more than one
|
||||
|
|
|
@ -731,7 +731,7 @@ static void add_shapekey_layers(Mesh &mesh_dest, const Mesh &mesh_src)
|
|||
}
|
||||
|
||||
CustomData_add_layer_named_with_data(
|
||||
&mesh_dest.vdata, CD_SHAPEKEY, array, mesh_dest.totvert, kb->name);
|
||||
&mesh_dest.vdata, CD_SHAPEKEY, array, mesh_dest.totvert, kb->name, nullptr);
|
||||
const int ci = CustomData_get_layer_index_n(&mesh_dest.vdata, CD_SHAPEKEY, i);
|
||||
|
||||
mesh_dest.vdata.layers[ci].uid = kb->uid;
|
||||
|
|
|
@ -157,14 +157,10 @@ static void SCULPT_dynamic_topology_disable_ex(
|
|||
me->totpoly = geometry->totpoly;
|
||||
me->totedge = geometry->totedge;
|
||||
me->totface = 0;
|
||||
CustomData_copy(
|
||||
&geometry->vdata, &me->vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, geometry->totvert);
|
||||
CustomData_copy(
|
||||
&geometry->edata, &me->edata, CD_MASK_MESH.emask, CD_DUPLICATE, geometry->totedge);
|
||||
CustomData_copy(
|
||||
&geometry->ldata, &me->ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, geometry->totloop);
|
||||
CustomData_copy(
|
||||
&geometry->pdata, &me->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, geometry->totpoly);
|
||||
CustomData_copy(&geometry->vdata, &me->vdata, CD_MASK_MESH.vmask, geometry->totvert);
|
||||
CustomData_copy(&geometry->edata, &me->edata, CD_MASK_MESH.emask, geometry->totedge);
|
||||
CustomData_copy(&geometry->ldata, &me->ldata, CD_MASK_MESH.lmask, geometry->totloop);
|
||||
CustomData_copy(&geometry->pdata, &me->pdata, CD_MASK_MESH.pmask, geometry->totpoly);
|
||||
me->poly_offset_indices = static_cast<int *>(MEM_dupallocN(geometry->poly_offset_indices));
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -745,10 +745,10 @@ static void sculpt_undo_geometry_store_data(SculptUndoNodeGeometry *geometry, Ob
|
|||
BLI_assert(!geometry->is_initialized);
|
||||
geometry->is_initialized = true;
|
||||
|
||||
CustomData_copy(&mesh->vdata, &geometry->vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, mesh->totvert);
|
||||
CustomData_copy(&mesh->edata, &geometry->edata, CD_MASK_MESH.emask, CD_DUPLICATE, mesh->totedge);
|
||||
CustomData_copy(&mesh->ldata, &geometry->ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, mesh->totloop);
|
||||
CustomData_copy(&mesh->pdata, &geometry->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, mesh->totpoly);
|
||||
CustomData_copy(&mesh->vdata, &geometry->vdata, CD_MASK_MESH.vmask, mesh->totvert);
|
||||
CustomData_copy(&mesh->edata, &geometry->edata, CD_MASK_MESH.emask, mesh->totedge);
|
||||
CustomData_copy(&mesh->ldata, &geometry->ldata, CD_MASK_MESH.lmask, mesh->totloop);
|
||||
CustomData_copy(&mesh->pdata, &geometry->pdata, CD_MASK_MESH.pmask, mesh->totpoly);
|
||||
geometry->poly_offset_indices = static_cast<int *>(MEM_dupallocN(mesh->poly_offset_indices));
|
||||
|
||||
geometry->totvert = mesh->totvert;
|
||||
|
@ -771,14 +771,10 @@ static void sculpt_undo_geometry_restore_data(SculptUndoNodeGeometry *geometry,
|
|||
mesh->totpoly = geometry->totpoly;
|
||||
mesh->totface = 0;
|
||||
|
||||
CustomData_copy(
|
||||
&geometry->vdata, &mesh->vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, geometry->totvert);
|
||||
CustomData_copy(
|
||||
&geometry->edata, &mesh->edata, CD_MASK_MESH.emask, CD_DUPLICATE, geometry->totedge);
|
||||
CustomData_copy(
|
||||
&geometry->ldata, &mesh->ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, geometry->totloop);
|
||||
CustomData_copy(
|
||||
&geometry->pdata, &mesh->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, geometry->totpoly);
|
||||
CustomData_copy(&geometry->vdata, &mesh->vdata, CD_MASK_MESH.vmask, geometry->totvert);
|
||||
CustomData_copy(&geometry->edata, &mesh->edata, CD_MASK_MESH.emask, geometry->totedge);
|
||||
CustomData_copy(&geometry->ldata, &mesh->ldata, CD_MASK_MESH.lmask, geometry->totloop);
|
||||
CustomData_copy(&geometry->pdata, &mesh->pdata, CD_MASK_MESH.pmask, geometry->totpoly);
|
||||
mesh->poly_offset_indices = static_cast<int *>(MEM_dupallocN(geometry->poly_offset_indices));
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,8 @@ void IMAGE_OT_save_sequence(struct wmOperatorType *ot);
|
|||
void IMAGE_OT_save_all_modified(struct wmOperatorType *ot);
|
||||
void IMAGE_OT_pack(struct wmOperatorType *ot);
|
||||
void IMAGE_OT_unpack(struct wmOperatorType *ot);
|
||||
void IMAGE_OT_clipboard_copy(struct wmOperatorType *ot);
|
||||
void IMAGE_OT_clipboard_paste(struct wmOperatorType *ot);
|
||||
|
||||
void IMAGE_OT_flip(struct wmOperatorType *ot);
|
||||
void IMAGE_OT_invert(struct wmOperatorType *ot);
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
#include "ED_screen.h"
|
||||
#include "ED_space_api.h"
|
||||
#include "ED_util.h"
|
||||
#include "ED_undo.h"
|
||||
#include "ED_util_imbuf.h"
|
||||
#include "ED_uvedit.h"
|
||||
|
||||
|
@ -2834,6 +2835,125 @@ void IMAGE_OT_flip(wmOperatorType *ot)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Clipboard Copy Operator
|
||||
* \{ */
|
||||
|
||||
static int image_clipboard_copy_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Image *ima = image_from_context(C);
|
||||
if (ima == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (G.is_rendering && ima->source == IMA_SRC_VIEWER) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Images cannot be copied while rendering");
|
||||
return false;
|
||||
}
|
||||
|
||||
ImageUser *iuser = image_user_from_context(C);
|
||||
WM_cursor_set(CTX_wm_window(C), WM_CURSOR_WAIT);
|
||||
|
||||
void *lock;
|
||||
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
|
||||
if (ibuf == NULL) {
|
||||
BKE_image_release_ibuf(ima, ibuf, lock);
|
||||
WM_cursor_set(CTX_wm_window(C), WM_CURSOR_DEFAULT);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
WM_clipboard_image_set(ibuf);
|
||||
BKE_image_release_ibuf(ima, ibuf, lock);
|
||||
WM_cursor_set(CTX_wm_window(C), WM_CURSOR_DEFAULT);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static bool image_clipboard_copy_poll(bContext *C)
|
||||
{
|
||||
if (!image_from_context_has_data_poll(C)) {
|
||||
CTX_wm_operator_poll_msg_set(C, "No images available");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void IMAGE_OT_clipboard_copy(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Copy Image";
|
||||
ot->idname = "IMAGE_OT_clipboard_copy";
|
||||
ot->description = "Copy the image to the clipboard";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = image_clipboard_copy_exec;
|
||||
ot->poll = image_clipboard_copy_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Clipboard Paste Operator
|
||||
* \{ */
|
||||
|
||||
static int image_clipboard_paste_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
|
||||
WM_cursor_set(CTX_wm_window(C), WM_CURSOR_WAIT);
|
||||
|
||||
ImBuf *ibuf = WM_clipboard_image_get();
|
||||
if (!ibuf) {
|
||||
WM_cursor_set(CTX_wm_window(C), WM_CURSOR_DEFAULT);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
ED_undo_push_op(C, op);
|
||||
|
||||
Main *bmain = CTX_data_main(C);
|
||||
SpaceImage *sima = CTX_wm_space_image(C);
|
||||
Image *ima = BKE_image_add_from_imbuf(bmain, ibuf, "Clipboard");
|
||||
IMB_freeImBuf(ibuf);
|
||||
|
||||
ED_space_image_set(bmain, sima, ima, false);
|
||||
BKE_image_signal(bmain, ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_USER_NEW_IMAGE);
|
||||
WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
|
||||
|
||||
WM_cursor_set(CTX_wm_window(C), WM_CURSOR_DEFAULT);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static bool image_clipboard_paste_poll(bContext *C)
|
||||
{
|
||||
if (!WM_clipboard_image_available()) {
|
||||
CTX_wm_operator_poll_msg_set(C, "No compatible images are on the clipboard");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void IMAGE_OT_clipboard_paste(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Paste Image";
|
||||
ot->idname = "IMAGE_OT_clipboard_paste";
|
||||
ot->description = "Paste new image from the clipboard";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = image_clipboard_paste_exec;
|
||||
ot->poll = image_clipboard_paste_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Invert Operators
|
||||
* \{ */
|
||||
|
|
|
@ -216,6 +216,8 @@ static void image_operatortypes(void)
|
|||
WM_operatortype_append(IMAGE_OT_save_all_modified);
|
||||
WM_operatortype_append(IMAGE_OT_pack);
|
||||
WM_operatortype_append(IMAGE_OT_unpack);
|
||||
WM_operatortype_append(IMAGE_OT_clipboard_copy);
|
||||
WM_operatortype_append(IMAGE_OT_clipboard_paste);
|
||||
|
||||
WM_operatortype_append(IMAGE_OT_flip);
|
||||
WM_operatortype_append(IMAGE_OT_invert);
|
||||
|
|
|
@ -194,7 +194,8 @@ static void nlastrip_flag_overlaps(NlaStrip *strip)
|
|||
}
|
||||
}
|
||||
|
||||
/** Check the Transformation data for the given Strip, and fix any overlap. Then
|
||||
/**
|
||||
* Check the Transformation data for the given Strip, and fix any overlap. Then
|
||||
* apply the Transformation.
|
||||
*/
|
||||
static void nlastrip_fix_overlapping(TransInfo *t, TransDataNla *tdn, NlaStrip *strip)
|
||||
|
@ -202,8 +203,7 @@ static void nlastrip_fix_overlapping(TransInfo *t, TransDataNla *tdn, NlaStrip *
|
|||
/* firstly, check if the proposed transform locations would overlap with any neighboring
|
||||
* strips (barring transitions) which are absolute barriers since they are not being moved
|
||||
*
|
||||
* this is done as a iterative procedure (done 5 times max for now)
|
||||
*/
|
||||
* this is done as a iterative procedure (done 5 times max for now). */
|
||||
short iter_max = 4;
|
||||
NlaStrip *prev = BKE_nlastrip_prev_in_track(strip, true);
|
||||
NlaStrip *next = BKE_nlastrip_next_in_track(strip, true);
|
||||
|
@ -215,9 +215,8 @@ static void nlastrip_fix_overlapping(TransInfo *t, TransDataNla *tdn, NlaStrip *
|
|||
const bool n_exceeded = (next != NULL) && (tdn->h2[0] > next->start);
|
||||
|
||||
if ((p_exceeded && n_exceeded) || (iter == iter_max)) {
|
||||
/* both endpoints exceeded (or iteration ping-pong'd meaning that we need a
|
||||
* compromise)
|
||||
* - Simply crop strip to fit within the bounds of the strips bounding it
|
||||
/* Both endpoints exceeded (or iteration ping-pong'd meaning that we need a compromise).
|
||||
* - Simply crop strip to fit within the bounds of the strips bounding it.
|
||||
* - If there were no neighbors, clear the transforms
|
||||
* (make it default to the strip's current values).
|
||||
*/
|
||||
|
@ -250,16 +249,14 @@ static void nlastrip_fix_overlapping(TransInfo *t, TransDataNla *tdn, NlaStrip *
|
|||
}
|
||||
|
||||
/* Use RNA to write the values to ensure that constraints on these are obeyed
|
||||
* (e.g. for transition strips, the values are taken from the neighbors)
|
||||
*/
|
||||
* (e.g. for transition strips, the values are taken from the neighbors). */
|
||||
RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
|
||||
|
||||
switch (t->mode) {
|
||||
case TFM_TIME_EXTEND:
|
||||
case TFM_TIME_SCALE: {
|
||||
/* The final scale is the product of the original strip scale (from before the
|
||||
* transform operation started) and the current scale value of this transform
|
||||
* operation. */
|
||||
* transform operation started) and the current scale value of this transform operation. */
|
||||
const float originalStripScale = tdn->h1[2];
|
||||
const float newStripScale = originalStripScale * t->values_final[0];
|
||||
applyTransformNLA_timeScale(&strip_ptr, newStripScale);
|
||||
|
@ -380,18 +377,18 @@ static void createTransNlaData(bContext *C, TransInfo *t)
|
|||
/* transition strips can't get directly transformed */
|
||||
if (strip->type != NLASTRIP_TYPE_TRANSITION) {
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT) {
|
||||
/* our transform data is constructed as follows:
|
||||
* - only the handles on the right side of the current-frame get included
|
||||
* - td structs are transform-elements operated on by the transform system
|
||||
* and represent a single handle. The storage/pointer used (val or loc) depends
|
||||
* on whether we're scaling or transforming. Ultimately though, the handles the td
|
||||
* writes to will simply be a dummy in tdn
|
||||
* - for each strip being transformed, a single tdn struct is used, so in some
|
||||
* cases, there will need to be 1 of these tdn elements in the array skipped...
|
||||
/* Our transform data is constructed as follows:
|
||||
* - Only the handles on the right side of the current-frame get included.
|
||||
* - `td` structs are transform-elements operated on by the transform system and
|
||||
* represent a single handle. The storage/pointer used (`val` or `loc`) depends
|
||||
* on whether we're scaling or transforming. Ultimately though, the handles the `td`
|
||||
* writes to will simply be a dummy in `tdn`.
|
||||
* - For each strip being transformed, a single `tdn` struct is used, so in some
|
||||
* cases, there will need to be 1 of these `tdn` elements in the array skipped.
|
||||
*/
|
||||
float center[3], yval;
|
||||
|
||||
/* firstly, init tdn settings */
|
||||
/* Firstly, initialize `tdn` settings. */
|
||||
tdn->id = ale->id;
|
||||
tdn->oldTrack = tdn->nlt = nlt;
|
||||
tdn->strip = strip;
|
||||
|
@ -648,14 +645,12 @@ typedef struct IDGroupedTransData {
|
|||
/** horizontally translate (shuffle) the transformed strip to a non-overlapping state. */
|
||||
static void nlastrip_shuffle_transformed(TransDataContainer *tc, TransDataNla *first_trans_data)
|
||||
{
|
||||
/* Element: (IDGroupedTransData*) */
|
||||
/* Element: #IDGroupedTransData. */
|
||||
ListBase grouped_trans_datas = {NULL, NULL};
|
||||
|
||||
/* Flag all non-library-override transformed strips so we can distinguish them when
|
||||
* shuffling.
|
||||
/* Flag all non-library-override transformed strips so we can distinguish them when shuffling.
|
||||
*
|
||||
* Group trans_datas by ID so shuffling is unique per ID.
|
||||
*/
|
||||
* Group trans_datas by ID so shuffling is unique per ID. */
|
||||
{
|
||||
TransDataNla *tdn = first_trans_data;
|
||||
for (int i = 0; i < tc->data_len; i++, tdn++) {
|
||||
|
|
|
@ -1227,9 +1227,7 @@ static void gizmo_3d_dial_matrixbasis_calc(const ARegion *region,
|
|||
* \{ */
|
||||
|
||||
/** Scale of the two-axis planes. */
|
||||
#define MAN_AXIS_SCALE_PLANE_SCALE 0.07f
|
||||
/** Offset of the two-axis planes, depends on the gizmos scale. Define to avoid repeating. */
|
||||
#define MAN_AXIS_SCALE_PLANE_OFFSET 7.0f
|
||||
#define MAN_AXIS_SCALE_PLANE_SCALE 0.7f
|
||||
|
||||
static void rotation_get_fn(const wmGizmo * /*gz*/, wmGizmoProperty *gz_prop, void *value)
|
||||
{
|
||||
|
@ -1273,21 +1271,21 @@ static void gizmo_3d_setup_default_matrix(wmGizmo *axis, const int axis_idx)
|
|||
|
||||
case MAN_AXIS_TRANS_XY:
|
||||
case MAN_AXIS_SCALE_XY:
|
||||
copy_v3_fl3(matrix[0], MAN_AXIS_SCALE_PLANE_SCALE, 0.0f, 0.0f);
|
||||
copy_v3_fl3(matrix[1], 0.0f, MAN_AXIS_SCALE_PLANE_SCALE, 0.0f);
|
||||
copy_v3_fl3(matrix[2], 0.0f, 0.0f, MAN_AXIS_SCALE_PLANE_SCALE);
|
||||
copy_v3_fl3(matrix[0], -M_SQRT1_2, M_SQRT1_2, 0.0f);
|
||||
copy_v3_fl3(matrix[1], 0.0f, 0.0f, 1.0f);
|
||||
copy_v3_fl3(matrix[2], M_SQRT1_2, M_SQRT1_2, 0.0f);
|
||||
break;
|
||||
case MAN_AXIS_TRANS_YZ:
|
||||
case MAN_AXIS_SCALE_YZ:
|
||||
copy_v3_fl3(matrix[0], 0.0f, 0.0f, MAN_AXIS_SCALE_PLANE_SCALE);
|
||||
copy_v3_fl3(matrix[1], 0.0f, MAN_AXIS_SCALE_PLANE_SCALE, 0.0f);
|
||||
copy_v3_fl3(matrix[2], -MAN_AXIS_SCALE_PLANE_SCALE, 0.0f, 0.0f);
|
||||
copy_v3_fl3(matrix[0], 0.0f, -M_SQRT1_2, M_SQRT1_2);
|
||||
copy_v3_fl3(matrix[1], 1.0f, 0.0f, 0.0f);
|
||||
copy_v3_fl3(matrix[2], 0, M_SQRT1_2, M_SQRT1_2);
|
||||
break;
|
||||
case MAN_AXIS_TRANS_ZX:
|
||||
case MAN_AXIS_SCALE_ZX:
|
||||
copy_v3_fl3(matrix[0], MAN_AXIS_SCALE_PLANE_SCALE, 0.0f, 0.0f);
|
||||
copy_v3_fl3(matrix[1], 0.0f, 0.0f, MAN_AXIS_SCALE_PLANE_SCALE);
|
||||
copy_v3_fl3(matrix[2], 0.0f, -MAN_AXIS_SCALE_PLANE_SCALE, 0.0f);
|
||||
case MAN_AXIS_TRANS_ZX:
|
||||
copy_v3_fl3(matrix[0], M_SQRT1_2, 0.0f, -M_SQRT1_2);
|
||||
copy_v3_fl3(matrix[1], 0.0f, 1.0f, 0.0f);
|
||||
copy_v3_fl3(matrix[2], M_SQRT1_2, 0.0f, M_SQRT1_2);
|
||||
break;
|
||||
|
||||
case MAN_AXIS_TRANS_C:
|
||||
|
@ -1299,22 +1297,6 @@ static void gizmo_3d_setup_default_matrix(wmGizmo *axis, const int axis_idx)
|
|||
}
|
||||
|
||||
copy_m4_m3(axis->matrix_offset, matrix);
|
||||
|
||||
switch (axis_idx) {
|
||||
case MAN_AXIS_TRANS_XY:
|
||||
case MAN_AXIS_TRANS_YZ:
|
||||
case MAN_AXIS_TRANS_ZX:
|
||||
case MAN_AXIS_SCALE_XY:
|
||||
case MAN_AXIS_SCALE_YZ:
|
||||
case MAN_AXIS_SCALE_ZX: {
|
||||
float offs[3];
|
||||
add_v3_v3v3(offs, axis->matrix_offset[0], axis->matrix_offset[1]);
|
||||
mul_v3_fl(offs, MAN_AXIS_SCALE_PLANE_OFFSET);
|
||||
WM_gizmo_set_matrix_offset_location(axis, offs);
|
||||
} break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void gizmo_3d_setup_draw_default(wmGizmo *axis, const int axis_idx)
|
||||
|
@ -1334,38 +1316,39 @@ static void gizmo_3d_setup_draw_default(wmGizmo *axis, const int axis_idx)
|
|||
RNA_enum_set(axis->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_BOX);
|
||||
RNA_enum_set(axis->ptr, "draw_options", ED_GIZMO_ARROW_DRAW_FLAG_STEM);
|
||||
break;
|
||||
|
||||
/* Primitive. */
|
||||
case MAN_AXIS_TRANS_XY:
|
||||
case MAN_AXIS_TRANS_YZ:
|
||||
case MAN_AXIS_TRANS_ZX:
|
||||
case MAN_AXIS_SCALE_XY:
|
||||
case MAN_AXIS_SCALE_YZ:
|
||||
case MAN_AXIS_SCALE_ZX:
|
||||
RNA_enum_set(axis->ptr, "draw_style", ED_GIZMO_PRIMITIVE_STYLE_PLANE);
|
||||
WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_OFFSET_SCALE, true);
|
||||
RNA_enum_set(axis->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_PLANE);
|
||||
RNA_enum_set(axis->ptr, "draw_options", 0);
|
||||
RNA_float_set(axis->ptr, "length", MAN_AXIS_SCALE_PLANE_SCALE);
|
||||
break;
|
||||
|
||||
/* Dial. */
|
||||
/* Primitive. */
|
||||
case MAN_AXIS_TRANS_C:
|
||||
RNA_enum_set(axis->ptr, "draw_options", ED_GIZMO_DIAL_DRAW_FLAG_FILL_SELECT);
|
||||
WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_MODAL, true);
|
||||
RNA_enum_set(axis->ptr, "draw_style", ED_GIZMO_PRIMITIVE_STYLE_CIRCLE);
|
||||
RNA_boolean_set(axis->ptr, "draw_inner", false);
|
||||
WM_gizmo_set_scale(axis, 0.2f);
|
||||
|
||||
/* Prevent axis gizmos overlapping the center point, see: #63744. */
|
||||
axis->select_bias = 2.0f;
|
||||
break;
|
||||
case MAN_AXIS_SCALE_C:
|
||||
RNA_enum_set(axis->ptr, "draw_options", ED_GIZMO_DIAL_DRAW_FLAG_FILL_SELECT);
|
||||
RNA_enum_set(axis->ptr, "draw_style", ED_GIZMO_PRIMITIVE_STYLE_ANNULUS);
|
||||
RNA_boolean_set(axis->ptr, "draw_inner", false);
|
||||
|
||||
/* Use 1/6 since this is '0.2' if the main scale is 1.2. */
|
||||
RNA_float_set(axis->ptr, "arc_inner_factor", 1.0 / 6.0);
|
||||
WM_gizmo_set_scale(axis, 1.2f);
|
||||
/* Use 6 since this is '1.2' if the main scale is 0.2. */
|
||||
RNA_float_set(axis->ptr, "arc_inner_factor", 6.0f);
|
||||
WM_gizmo_set_scale(axis, 0.2f);
|
||||
|
||||
/* Prevent axis gizmos overlapping the center point, see: #63744. */
|
||||
axis->select_bias = -2.0f;
|
||||
break;
|
||||
|
||||
/* Dial. */
|
||||
case MAN_AXIS_ROT_X:
|
||||
case MAN_AXIS_ROT_Y:
|
||||
case MAN_AXIS_ROT_Z:
|
||||
|
@ -1385,11 +1368,12 @@ static void gizmo_3d_setup_draw_default(wmGizmo *axis, const int axis_idx)
|
|||
}
|
||||
|
||||
switch (axis_idx) {
|
||||
case MAN_AXIS_ROT_X:
|
||||
case MAN_AXIS_ROT_Y:
|
||||
case MAN_AXIS_ROT_Z:
|
||||
/* Increased line width for better display. */
|
||||
WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH + 1.0f);
|
||||
case MAN_AXIS_TRANS_X:
|
||||
case MAN_AXIS_TRANS_Y:
|
||||
case MAN_AXIS_TRANS_Z:
|
||||
case MAN_AXIS_SCALE_X:
|
||||
case MAN_AXIS_SCALE_Y:
|
||||
WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH);
|
||||
break;
|
||||
case MAN_AXIS_TRANS_XY:
|
||||
case MAN_AXIS_TRANS_YZ:
|
||||
|
@ -1399,6 +1383,12 @@ static void gizmo_3d_setup_draw_default(wmGizmo *axis, const int axis_idx)
|
|||
case MAN_AXIS_SCALE_ZX:
|
||||
WM_gizmo_set_line_width(axis, 1.0f);
|
||||
break;
|
||||
case MAN_AXIS_ROT_X:
|
||||
case MAN_AXIS_ROT_Y:
|
||||
case MAN_AXIS_ROT_Z:
|
||||
/* Increased line width for better display. */
|
||||
WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH + 1.0f);
|
||||
break;
|
||||
default:
|
||||
WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH);
|
||||
break;
|
||||
|
@ -1462,9 +1452,42 @@ static void gizmo_3d_setup_draw_from_twtype(wmGizmo *axis, const int axis_idx, c
|
|||
}
|
||||
}
|
||||
|
||||
static void gizmo_3d_setup_draw_modal(wmGizmo *axis, const int axis_idx)
|
||||
static void gizmo_3d_setup_draw_modal(wmGizmo *axis, const int axis_idx, const int twtype)
|
||||
{
|
||||
const short axis_type = gizmo_get_axis_type(axis_idx);
|
||||
switch (axis_idx) {
|
||||
case MAN_AXIS_TRANS_X:
|
||||
case MAN_AXIS_TRANS_Y:
|
||||
case MAN_AXIS_TRANS_Z:
|
||||
case MAN_AXIS_SCALE_X:
|
||||
case MAN_AXIS_SCALE_Y:
|
||||
case MAN_AXIS_SCALE_Z: {
|
||||
|
||||
float end, start_co[3] = {0.0f, 0.0f, 0.0f};
|
||||
gizmo_line_range(twtype, axis_type, NULL, &end);
|
||||
RNA_float_set(axis->ptr, "length", end);
|
||||
RNA_enum_set(axis->ptr,
|
||||
"draw_options",
|
||||
ED_GIZMO_ARROW_DRAW_FLAG_STEM | ED_GIZMO_ARROW_DRAW_FLAG_ORIGIN);
|
||||
WM_gizmo_set_matrix_offset_location(axis, start_co);
|
||||
WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_OFFSET_SCALE, false);
|
||||
break;
|
||||
}
|
||||
case MAN_AXIS_TRANS_XY:
|
||||
case MAN_AXIS_TRANS_YZ:
|
||||
case MAN_AXIS_TRANS_ZX:
|
||||
case MAN_AXIS_SCALE_XY:
|
||||
case MAN_AXIS_SCALE_YZ:
|
||||
case MAN_AXIS_SCALE_ZX:
|
||||
RNA_enum_set(axis->ptr, "draw_options", ED_GIZMO_ARROW_DRAW_FLAG_ORIGIN);
|
||||
break;
|
||||
case MAN_AXIS_SCALE_C:
|
||||
RNA_enum_set(axis->ptr, "draw_style", ED_GIZMO_PRIMITIVE_STYLE_CIRCLE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (axis_type) {
|
||||
case MAN_AXES_ROTATE: {
|
||||
PropertyRNA *prop = RNA_struct_find_property(axis->ptr, "draw_options");
|
||||
|
@ -1510,15 +1533,15 @@ static GizmoGroup *gizmogroup_init(wmGizmoGroup *gzgroup)
|
|||
/* add/init widgets - order matters! */
|
||||
GIZMO_NEW_DIAL(MAN_AXIS_ROT_T);
|
||||
|
||||
GIZMO_NEW_DIAL(MAN_AXIS_SCALE_C);
|
||||
GIZMO_NEW_PRIM(MAN_AXIS_SCALE_C);
|
||||
|
||||
GIZMO_NEW_ARROW(MAN_AXIS_SCALE_X);
|
||||
GIZMO_NEW_ARROW(MAN_AXIS_SCALE_Y);
|
||||
GIZMO_NEW_ARROW(MAN_AXIS_SCALE_Z);
|
||||
|
||||
GIZMO_NEW_PRIM(MAN_AXIS_SCALE_XY);
|
||||
GIZMO_NEW_PRIM(MAN_AXIS_SCALE_YZ);
|
||||
GIZMO_NEW_PRIM(MAN_AXIS_SCALE_ZX);
|
||||
GIZMO_NEW_ARROW(MAN_AXIS_SCALE_XY);
|
||||
GIZMO_NEW_ARROW(MAN_AXIS_SCALE_YZ);
|
||||
GIZMO_NEW_ARROW(MAN_AXIS_SCALE_ZX);
|
||||
|
||||
GIZMO_NEW_DIAL(MAN_AXIS_ROT_X);
|
||||
GIZMO_NEW_DIAL(MAN_AXIS_ROT_Y);
|
||||
|
@ -1527,15 +1550,15 @@ static GizmoGroup *gizmogroup_init(wmGizmoGroup *gzgroup)
|
|||
/* init screen aligned widget last here, looks better, behaves better */
|
||||
GIZMO_NEW_DIAL(MAN_AXIS_ROT_C);
|
||||
|
||||
GIZMO_NEW_DIAL(MAN_AXIS_TRANS_C);
|
||||
GIZMO_NEW_PRIM(MAN_AXIS_TRANS_C);
|
||||
|
||||
GIZMO_NEW_ARROW(MAN_AXIS_TRANS_X);
|
||||
GIZMO_NEW_ARROW(MAN_AXIS_TRANS_Y);
|
||||
GIZMO_NEW_ARROW(MAN_AXIS_TRANS_Z);
|
||||
|
||||
GIZMO_NEW_PRIM(MAN_AXIS_TRANS_XY);
|
||||
GIZMO_NEW_PRIM(MAN_AXIS_TRANS_YZ);
|
||||
GIZMO_NEW_PRIM(MAN_AXIS_TRANS_ZX);
|
||||
GIZMO_NEW_ARROW(MAN_AXIS_TRANS_XY);
|
||||
GIZMO_NEW_ARROW(MAN_AXIS_TRANS_YZ);
|
||||
GIZMO_NEW_ARROW(MAN_AXIS_TRANS_ZX);
|
||||
|
||||
MAN_ITER_AXES_BEGIN (axis, axis_idx) {
|
||||
gizmo_3d_setup_draw_default(axis, axis_idx);
|
||||
|
@ -1763,11 +1786,9 @@ static void gizmo_refresh_from_matrix(wmGizmo *axis,
|
|||
case MAN_AXIS_SCALE_ZX:
|
||||
copy_m4_m4(axis->matrix_basis, twmat);
|
||||
if (scale) {
|
||||
float offs[3];
|
||||
add_v3_v3v3(offs, axis->matrix_offset[0], axis->matrix_offset[1]);
|
||||
mul_v3_fl(offs, MAN_AXIS_SCALE_PLANE_OFFSET);
|
||||
mul_v3_v3(offs, scale);
|
||||
WM_gizmo_set_matrix_offset_location(axis, offs);
|
||||
RNA_float_set(axis->ptr,
|
||||
"length",
|
||||
MAN_AXIS_SCALE_PLANE_SCALE * scale[aidx_norm == 2 ? 0 : aidx_norm + 1]);
|
||||
}
|
||||
break;
|
||||
case MAN_AXIS_SCALE_X:
|
||||
|
@ -1775,23 +1796,29 @@ static void gizmo_refresh_from_matrix(wmGizmo *axis,
|
|||
case MAN_AXIS_SCALE_Z:
|
||||
copy_m4_m4(axis->matrix_basis, twmat);
|
||||
if (scale) {
|
||||
float start, end;
|
||||
gizmo_line_range(twtype, axis_type, &start, &end);
|
||||
RNA_float_set(axis->ptr, "length", (end - start) * scale[aidx_norm]);
|
||||
float end;
|
||||
gizmo_line_range(twtype, axis_type, NULL, &end);
|
||||
RNA_float_set(axis->ptr, "length", end * scale[aidx_norm]);
|
||||
}
|
||||
|
||||
break;
|
||||
case MAN_AXIS_TRANS_X:
|
||||
case MAN_AXIS_TRANS_Y:
|
||||
case MAN_AXIS_TRANS_Z:
|
||||
copy_m4_m4(axis->matrix_basis, twmat);
|
||||
break;
|
||||
case MAN_AXIS_SCALE_C:
|
||||
WM_gizmo_set_matrix_location(axis, twmat[3]);
|
||||
if (scale) {
|
||||
WM_gizmo_set_scale(axis, 0.2f * scale[0]);
|
||||
}
|
||||
break;
|
||||
case MAN_AXIS_ROT_X:
|
||||
case MAN_AXIS_ROT_Y:
|
||||
case MAN_AXIS_ROT_Z:
|
||||
copy_m4_m4(axis->matrix_basis, twmat);
|
||||
orthogonalize_m4(axis->matrix_basis, aidx_norm);
|
||||
break;
|
||||
case MAN_AXIS_SCALE_C:
|
||||
case MAN_AXIS_ROT_C:
|
||||
case MAN_AXIS_ROT_T:
|
||||
default:
|
||||
|
@ -1971,66 +1998,43 @@ static void gizmo_3d_draw_invoke(wmGizmoGroup *gzgroup,
|
|||
wmGizmo *axis_active = ggd->gizmos[axis_idx_active];
|
||||
|
||||
const short axis_active_type = gizmo_get_axis_type(axis_idx_active);
|
||||
if (axis_active_type == MAN_AXES_ROTATE) {
|
||||
/* Hide other gizmos except the active one and #MAN_AXIS_ROT_C.
|
||||
* #MAN_AXIS_ROT_C was displayed before and remains visible by convention. */
|
||||
gizmogroup_hide_all(ggd);
|
||||
WM_gizmo_set_flag(axis_active, WM_GIZMO_HIDDEN, false);
|
||||
WM_gizmo_set_flag(ggd->gizmos[MAN_AXIS_ROT_C], WM_GIZMO_HIDDEN, false);
|
||||
}
|
||||
else {
|
||||
/* We switch from a modal gizmo to another. So make sure the gizmos are visible and have the
|
||||
* default properties. */
|
||||
|
||||
const int twtype_expected = (axis_active_type == MAN_AXES_TRANSLATE ?
|
||||
V3D_GIZMO_SHOW_OBJECT_TRANSLATE :
|
||||
V3D_GIZMO_SHOW_OBJECT_SCALE);
|
||||
/* Display only the active gizmo. */
|
||||
gizmogroup_hide_all(ggd);
|
||||
WM_gizmo_set_flag(axis_active, WM_GIZMO_HIDDEN, false);
|
||||
gizmo_refresh_from_matrix(axis_active, axis_idx_active, ggd->twtype, rv3d->twmat, nullptr);
|
||||
|
||||
const int twtype = (ggd->twtype & twtype_expected) ? ggd->twtype : twtype_expected;
|
||||
|
||||
float idot[3];
|
||||
gizmo_get_idot(rv3d, idot);
|
||||
MAN_ITER_AXES_BEGIN (axis, axis_idx) {
|
||||
const short axis_type = gizmo_get_axis_type(axis_idx);
|
||||
if (gizmo_is_axis_visible(rv3d, twtype, idot, axis_type, axis_idx)) {
|
||||
WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, false);
|
||||
gizmo_3d_setup_draw_default(axis, axis_idx);
|
||||
gizmo_3d_setup_draw_from_twtype(axis, axis_idx, twtype);
|
||||
}
|
||||
else {
|
||||
WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, true);
|
||||
}
|
||||
}
|
||||
MAN_ITER_AXES_END;
|
||||
if (ELEM(axis_idx_active, MAN_AXIS_TRANS_C, MAN_AXIS_SCALE_C, MAN_AXIS_ROT_C, MAN_AXIS_ROT_T)) {
|
||||
WM_gizmo_set_matrix_rotation_from_z_axis(axis_active, rv3d->viewinv[2]);
|
||||
}
|
||||
|
||||
MAN_ITER_AXES_BEGIN (axis, axis_idx) {
|
||||
if (axis->flag & WM_GIZMO_HIDDEN) {
|
||||
continue;
|
||||
}
|
||||
gizmo_refresh_from_matrix(axis, axis_idx, ggd->twtype, rv3d->twmat, nullptr);
|
||||
gizmo_3d_setup_draw_modal(axis_active, axis_idx_active, ggd->twtype);
|
||||
|
||||
if (ELEM(axis_idx, MAN_AXIS_TRANS_C, MAN_AXIS_SCALE_C, MAN_AXIS_ROT_C, MAN_AXIS_ROT_T)) {
|
||||
WM_gizmo_set_matrix_rotation_from_z_axis(axis, rv3d->viewinv[2]);
|
||||
}
|
||||
|
||||
if (axis == axis_active) {
|
||||
if (axis_active_type == MAN_AXES_ROTATE && axis_idx_active != MAN_AXIS_ROT_T) {
|
||||
float mat[3][3];
|
||||
mul_m3_m4m4(mat, axis_active->matrix_basis, axis_active->matrix_offset);
|
||||
gizmo_3d_dial_matrixbasis_calc(
|
||||
region, mat[2], axis_active->matrix_basis[3], mval, axis_active->matrix_offset);
|
||||
|
||||
copy_m3_m4(mat, axis_active->matrix_basis);
|
||||
invert_m3(mat);
|
||||
mul_m4_m3m4(axis_active->matrix_offset, mat, axis_active->matrix_offset);
|
||||
zero_v3(axis_active->matrix_offset[3]);
|
||||
if (axis_active_type == MAN_AXES_TRANSLATE) {
|
||||
/* Arrows are used for visual reference, so keep all visible. */
|
||||
for (int axis_idx = MAN_AXIS_TRANS_X; axis_idx <= MAN_AXIS_TRANS_Z; axis_idx++) {
|
||||
if (axis_idx == axis_idx_active) {
|
||||
continue;
|
||||
}
|
||||
|
||||
gizmo_3d_setup_draw_modal(axis_active, axis_idx);
|
||||
wmGizmo *axis = ggd->gizmos[axis_idx];
|
||||
WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, false);
|
||||
gizmo_refresh_from_matrix(axis, axis_idx, ggd->twtype, rv3d->twmat, nullptr);
|
||||
gizmo_3d_setup_draw_default(axis, axis_idx);
|
||||
gizmo_3d_setup_draw_from_twtype(axis, axis_idx, ggd->twtype);
|
||||
RNA_enum_set(axis->ptr, "draw_options", ED_GIZMO_ARROW_DRAW_FLAG_STEM);
|
||||
}
|
||||
}
|
||||
MAN_ITER_AXES_END;
|
||||
else if (axis_active_type == MAN_AXES_ROTATE && axis_idx_active != MAN_AXIS_ROT_T) {
|
||||
float mat[3][3];
|
||||
mul_m3_m4m4(mat, axis_active->matrix_basis, axis_active->matrix_offset);
|
||||
gizmo_3d_dial_matrixbasis_calc(
|
||||
region, mat[2], axis_active->matrix_basis[3], mval, axis_active->matrix_offset);
|
||||
|
||||
copy_m3_m4(mat, axis_active->matrix_basis);
|
||||
invert_m3(mat);
|
||||
mul_m4_m3m4(axis_active->matrix_offset, mat, axis_active->matrix_offset);
|
||||
zero_v3(axis_active->matrix_offset[3]);
|
||||
}
|
||||
}
|
||||
|
||||
static void WIDGETGROUP_gizmo_invoke_prepare(const bContext *C,
|
||||
|
|
|
@ -44,10 +44,13 @@ class UV_ClipboardBuffer {
|
|||
~UV_ClipboardBuffer();
|
||||
|
||||
void append(UvElementMap *element_map, const int cd_loop_uv_offset);
|
||||
/**
|
||||
* \return True when found.
|
||||
*/
|
||||
bool find_isomorphism(UvElementMap *dest_element_map,
|
||||
int island_index,
|
||||
blender::Vector<int> &r_label,
|
||||
int cd_loop_uv_offset,
|
||||
blender::Vector<int> &r_label,
|
||||
bool *r_search_abandoned);
|
||||
|
||||
void write_uvs(UvElementMap *element_map,
|
||||
|
@ -196,12 +199,15 @@ void UV_ClipboardBuffer::write_uvs(UvElementMap *element_map,
|
|||
BLI_assert(unique_uv == label.size());
|
||||
}
|
||||
|
||||
/* Call the external isomorphism solver. */
|
||||
/**
|
||||
* Call the external isomorphism solver.
|
||||
* \return True when found.
|
||||
*/
|
||||
static bool find_isomorphism(UvElementMap *dest,
|
||||
const int dest_island_index,
|
||||
GraphISO *graph_source,
|
||||
const int cd_loop_uv_offset,
|
||||
blender::Vector<int> &r_label,
|
||||
int cd_loop_uv_offset,
|
||||
bool *r_search_abandoned)
|
||||
{
|
||||
|
||||
|
@ -215,12 +221,12 @@ static bool find_isomorphism(UvElementMap *dest,
|
|||
|
||||
int(*solution)[2] = (int(*)[2])MEM_mallocN(graph_source->n * sizeof(*solution), __func__);
|
||||
int solution_length = 0;
|
||||
const bool result = ED_uvedit_clipboard_maximum_common_subgraph(
|
||||
const bool found = ED_uvedit_clipboard_maximum_common_subgraph(
|
||||
graph_source, graph_dest, solution, &solution_length, r_search_abandoned);
|
||||
|
||||
/* Todo: Implement "Best Effort" / "Nearest Match" paste functionality here. */
|
||||
|
||||
if (result) {
|
||||
if (found) {
|
||||
BLI_assert(solution_length == dest->island_total_unique_uvs[dest_island_index]);
|
||||
for (int i = 0; i < solution_length; i++) {
|
||||
int index_s = solution[i][0];
|
||||
|
@ -233,21 +239,21 @@ static bool find_isomorphism(UvElementMap *dest,
|
|||
|
||||
MEM_SAFE_FREE(solution);
|
||||
delete graph_dest;
|
||||
return result;
|
||||
return found;
|
||||
}
|
||||
|
||||
bool UV_ClipboardBuffer::find_isomorphism(UvElementMap *dest_element_map,
|
||||
int dest_island_index,
|
||||
const int dest_island_index,
|
||||
const int cd_loop_uv_offset,
|
||||
blender::Vector<int> &r_label,
|
||||
int cd_loop_uv_offset,
|
||||
bool *r_search_abandoned)
|
||||
{
|
||||
for (const int64_t source_island_index : graph.index_range()) {
|
||||
if (::find_isomorphism(dest_element_map,
|
||||
dest_island_index,
|
||||
graph[source_island_index],
|
||||
r_label,
|
||||
cd_loop_uv_offset,
|
||||
r_label,
|
||||
r_search_abandoned)) {
|
||||
const int island_total_unique_uvs =
|
||||
dest_element_map->island_total_unique_uvs[dest_island_index];
|
||||
|
@ -311,7 +317,7 @@ static int uv_paste_exec(bContext *C, wmOperator *op)
|
|||
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
|
||||
scene, view_layer, ((View3D *)nullptr), &objects_len);
|
||||
|
||||
int result = OPERATOR_CANCELLED; /* Assume no changes. */
|
||||
bool changed_multi = false;
|
||||
int complicated_search = 0;
|
||||
int total_search = 0;
|
||||
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||
|
@ -328,12 +334,14 @@ static int uv_paste_exec(bContext *C, wmOperator *op)
|
|||
continue;
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
|
||||
for (int i = 0; i < dest_element_map->total_islands; i++) {
|
||||
total_search++;
|
||||
blender::Vector<int> label;
|
||||
bool search_abandoned = false;
|
||||
const bool found = uv_clipboard->find_isomorphism(
|
||||
dest_element_map, i, label, cd_loop_uv_offset, &search_abandoned);
|
||||
dest_element_map, i, cd_loop_uv_offset, label, &search_abandoned);
|
||||
if (!found) {
|
||||
if (search_abandoned) {
|
||||
complicated_search++;
|
||||
|
@ -342,12 +350,17 @@ static int uv_paste_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
|
||||
uv_clipboard->write_uvs(dest_element_map, i, cd_loop_uv_offset, label);
|
||||
result = OPERATOR_FINISHED; /* UVs were moved. */
|
||||
changed = true; /* UVs were moved. */
|
||||
}
|
||||
|
||||
BM_uv_element_map_free(dest_element_map);
|
||||
DEG_id_tag_update(static_cast<ID *>(ob->data), 0);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
|
||||
|
||||
if (changed) {
|
||||
changed_multi = true;
|
||||
|
||||
DEG_id_tag_update(static_cast<ID *>(ob->data), 0);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
|
||||
}
|
||||
}
|
||||
|
||||
if (complicated_search) {
|
||||
|
@ -360,7 +373,7 @@ static int uv_paste_exec(bContext *C, wmOperator *op)
|
|||
|
||||
MEM_freeN(objects);
|
||||
|
||||
return result;
|
||||
return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
void UV_OT_copy(wmOperatorType *ot)
|
||||
|
|
|
@ -31,8 +31,10 @@ class GraphISO {
|
|||
void calculate_degrees() const;
|
||||
};
|
||||
|
||||
/* Find the maximum common subgraph between two graphs.
|
||||
/**
|
||||
* Find the maximum common subgraph between two graphs.
|
||||
* (Can be used to find graph ismorphism.)
|
||||
* \return True when found.
|
||||
*/
|
||||
bool ED_uvedit_clipboard_maximum_common_subgraph(
|
||||
GraphISO *, GraphISO *, int solution[][2], int *solution_length, bool *r_search_abandoned);
|
||||
|
|
|
@ -138,7 +138,8 @@ static void add_new_edges(Mesh &mesh,
|
|||
mesh.edges_for_write().copy_from(new_edges);
|
||||
|
||||
if (new_orig_indices != nullptr) {
|
||||
CustomData_add_layer_with_data(&mesh.edata, CD_ORIGINDEX, new_orig_indices, mesh.totedge);
|
||||
CustomData_add_layer_with_data(
|
||||
&mesh.edata, CD_ORIGINDEX, new_orig_indices, mesh.totedge, nullptr);
|
||||
}
|
||||
|
||||
for (NewAttributeData &new_data : dst_attributes) {
|
||||
|
|
|
@ -19,8 +19,7 @@ PointCloud *point_merge_by_distance(const PointCloud &src_points,
|
|||
const bke::AnonymousAttributePropagationInfo &propagation_info)
|
||||
{
|
||||
const bke::AttributeAccessor src_attributes = src_points.attributes();
|
||||
VArraySpan<float3> positions = src_attributes.lookup_or_default<float3>(
|
||||
"position", ATTR_DOMAIN_POINT, float3(0));
|
||||
const Span<float3> positions = src_points.positions();
|
||||
const int src_size = positions.size();
|
||||
|
||||
/* Create the KD tree based on only the selected points, to speed up merge detection and
|
||||
|
|
|
@ -1185,12 +1185,12 @@ void PackIsland::build_transformation(const float scale,
|
|||
r_matrix[0][1] = -sin_angle * scale * aspect_y;
|
||||
r_matrix[1][0] = sin_angle * scale / aspect_y;
|
||||
r_matrix[1][1] = cos_angle * scale;
|
||||
/*
|
||||
#if 0
|
||||
if (reflect) {
|
||||
r_matrix[0][0] *= -1.0f;
|
||||
r_matrix[0][1] *= -1.0f;
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
|
||||
void PackIsland::build_inverse_transformation(const float scale,
|
||||
|
@ -1204,12 +1204,12 @@ void PackIsland::build_inverse_transformation(const float scale,
|
|||
r_matrix[0][1] = sin_angle / scale * aspect_y;
|
||||
r_matrix[1][0] = -sin_angle / scale / aspect_y;
|
||||
r_matrix[1][1] = cos_angle / scale;
|
||||
/*
|
||||
#if 0
|
||||
if (reflect) {
|
||||
r_matrix[0][0] *= -1.0f;
|
||||
r_matrix[1][0] *= -1.0f;
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace blender::geometry
|
||||
|
|
|
@ -940,6 +940,12 @@ int GPU_texture_width(const GPUTexture *texture);
|
|||
*/
|
||||
int GPU_texture_height(const GPUTexture *texture);
|
||||
|
||||
/**
|
||||
* Return the depth of \a tex . Correspond to number of layers for 2D array texture.
|
||||
* NOTE: return 0 for 1D & 2D textures.
|
||||
*/
|
||||
int GPU_texture_depth(const GPUTexture *texture);
|
||||
|
||||
/**
|
||||
* Return the number of layers of \a tex . Return 1 if the texture is not layered.
|
||||
*/
|
||||
|
|
|
@ -716,6 +716,11 @@ int GPU_texture_height(const GPUTexture *tex)
|
|||
return reinterpret_cast<const Texture *>(tex)->height_get();
|
||||
}
|
||||
|
||||
int GPU_texture_depth(const GPUTexture *tex)
|
||||
{
|
||||
return reinterpret_cast<const Texture *>(tex)->depth_get();
|
||||
}
|
||||
|
||||
int GPU_texture_layer_count(const GPUTexture *tex)
|
||||
{
|
||||
return reinterpret_cast<const Texture *>(tex)->layer_count();
|
||||
|
|
|
@ -497,7 +497,7 @@ id<MTLBuffer> MTLContext::get_null_buffer()
|
|||
null_buffer_ = [this->device newBufferWithLength:null_buffer_size
|
||||
options:MTLResourceStorageModeManaged];
|
||||
[null_buffer_ retain];
|
||||
uint32_t *null_data = (uint32_t *)calloc(0, null_buffer_size);
|
||||
uint32_t *null_data = (uint32_t *)calloc(1, null_buffer_size);
|
||||
memcpy([null_buffer_ contents], null_data, null_buffer_size);
|
||||
[null_buffer_ didModifyRange:NSMakeRange(0, null_buffer_size)];
|
||||
free(null_data);
|
||||
|
@ -2191,16 +2191,6 @@ void present(MTLRenderPassDescriptor *blit_descriptor,
|
|||
id<MTLCommandBuffer> cmdbuf = [ctx->queue commandBuffer];
|
||||
MTLCommandBufferManager::num_active_cmd_bufs++;
|
||||
|
||||
if (MTLCommandBufferManager::sync_event != nil) {
|
||||
/* Release synchronization primitive for current frame to avoid cross-frame dependencies.
|
||||
* We require MTLEvents to ensure correct ordering of workload submissions within a frame,
|
||||
* however, we should not create long chains of dependencies spanning several drawables as any
|
||||
* temporary stalls can then trigger erroneous GPU timeouts in non-dependent submissions. */
|
||||
[MTLCommandBufferManager::sync_event release];
|
||||
MTLCommandBufferManager::sync_event = nil;
|
||||
MTLCommandBufferManager::event_signal_val = 0;
|
||||
}
|
||||
|
||||
/* Do Present Call and final Blit to MTLDrawable. */
|
||||
id<MTLRenderCommandEncoder> enc = [cmdbuf renderCommandEncoderWithDescriptor:blit_descriptor];
|
||||
[enc setRenderPipelineState:blit_pso];
|
||||
|
|
|
@ -607,6 +607,19 @@ void MTLFence::wait()
|
|||
return;
|
||||
}
|
||||
|
||||
/* Note(#106431 #106704): `sync_event` is a global cross-context synchronization primitive used
|
||||
* to ensure GPU workloads execute in the correct order across contexts.
|
||||
*
|
||||
* To prevent unexpected GPU stalls, this needs to be reset when used along side explicit
|
||||
* synchronization. Previously this was handled during frame boundaries, however, to eliminate
|
||||
* situational flickering (#106704), only reset this during the cases where we are waiting on
|
||||
* synchronization primitives. */
|
||||
if (MTLCommandBufferManager::sync_event != nil) {
|
||||
[MTLCommandBufferManager::sync_event release];
|
||||
MTLCommandBufferManager::sync_event = nil;
|
||||
MTLCommandBufferManager::event_signal_val = 0;
|
||||
}
|
||||
|
||||
if (signalled_) {
|
||||
MTLContext *ctx = MTLContext::get();
|
||||
BLI_assert(ctx);
|
||||
|
|
|
@ -299,9 +299,10 @@ void VKFrameBuffer::render_pass_create()
|
|||
std::array<VkAttachmentDescription, GPU_FB_MAX_ATTACHMENT> attachment_descriptions;
|
||||
std::array<VkImageView, GPU_FB_MAX_ATTACHMENT> image_views;
|
||||
std::array<VkAttachmentReference, GPU_FB_MAX_ATTACHMENT> attachment_references;
|
||||
/*Vector<VkAttachmentReference> color_attachments;
|
||||
#if 0
|
||||
Vector<VkAttachmentReference> color_attachments;
|
||||
VkAttachmentReference depth_attachment = {};
|
||||
*/
|
||||
#endif
|
||||
bool has_depth_attachment = false;
|
||||
bool found_attachment = false;
|
||||
int depth_location = -1;
|
||||
|
|
|
@ -225,8 +225,6 @@ typedef struct ImBuf {
|
|||
char name[IMB_FILENAME_SIZE];
|
||||
|
||||
/* memory cache limiter */
|
||||
/** handle for cache limiter */
|
||||
struct MEM_CacheLimiterHandle_s *c_handle;
|
||||
/** reference counter for multiple users */
|
||||
int refcounter;
|
||||
|
||||
|
|
|
@ -585,7 +585,6 @@ ImBuf *IMB_dupImBuf(const ImBuf *ibuf1)
|
|||
|
||||
/* set malloc flag */
|
||||
tbuf.mall = ibuf2->mall;
|
||||
tbuf.c_handle = NULL;
|
||||
tbuf.refcounter = 0;
|
||||
|
||||
/* for now don't duplicate metadata */
|
||||
|
@ -631,31 +630,3 @@ size_t IMB_get_size_in_memory(ImBuf *ibuf)
|
|||
|
||||
return size;
|
||||
}
|
||||
|
||||
#if 0 /* remove? - campbell */
|
||||
/* support for cache limiting */
|
||||
|
||||
static void imbuf_cache_destructor(void *data)
|
||||
{
|
||||
ImBuf *ibuf = (ImBuf *)data;
|
||||
|
||||
imb_freerectImBuf(ibuf);
|
||||
imb_freerectfloatImBuf(ibuf);
|
||||
IMB_freezbufImBuf(ibuf);
|
||||
IMB_freezbuffloatImBuf(ibuf);
|
||||
freeencodedbufferImBuf(ibuf);
|
||||
|
||||
ibuf->c_handle = NULL;
|
||||
}
|
||||
|
||||
static MEM_CacheLimiterC **get_imbuf_cache_limiter(void)
|
||||
{
|
||||
static MEM_CacheLimiterC *c = NULL;
|
||||
|
||||
if (!c) {
|
||||
c = new_MEM_CacheLimiter(imbuf_cache_destructor, NULL);
|
||||
}
|
||||
|
||||
return &c;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -550,7 +550,7 @@ void MeshImporter::mesh_add_edges(Mesh *mesh, int len)
|
|||
totedge = mesh->totedge + len;
|
||||
|
||||
/* Update custom-data. */
|
||||
CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, totedge);
|
||||
CustomData_copy_layout(&mesh->edata, &edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, totedge);
|
||||
CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge);
|
||||
|
||||
if (!CustomData_has_layer(&edata, CD_MEDGE)) {
|
||||
|
|
|
@ -14,12 +14,11 @@ set(INC
|
|||
../../makesrna
|
||||
../../nodes
|
||||
../../windowmanager
|
||||
../../../../extern/fast_float
|
||||
../../../../intern/guardedalloc
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
|
||||
../../../../extern/fast_float
|
||||
)
|
||||
|
||||
set(SRC
|
||||
|
|
|
@ -808,8 +808,10 @@ typedef enum eNlaStrip_Flag {
|
|||
// NLASTRIP_FLAG_SELECT_L = (1 << 2), /* left handle selected. */
|
||||
// NLASTRIP_FLAG_SELECT_R = (1 << 3), /* right handle selected. */
|
||||
|
||||
/** NLA strip uses the same action that the action being tweaked uses
|
||||
* (not set for the tweaking one though). */
|
||||
/**
|
||||
* NLA strip uses the same action that the action being tweaked uses
|
||||
* (not set for the tweaking one though).
|
||||
*/
|
||||
NLASTRIP_FLAG_TWEAKUSER = (1 << 4),
|
||||
|
||||
/* controls driven by local F-Curves */
|
||||
|
@ -833,9 +835,11 @@ typedef enum eNlaStrip_Flag {
|
|||
|
||||
/* temporary editing flags */
|
||||
|
||||
/** When transforming strips, this flag is set when the strip is placed in an invalid location
|
||||
/**
|
||||
* When transforming strips, this flag is set when the strip is placed in an invalid location
|
||||
* such as overlapping another strip or moved to a locked track. In such cases, the strip's
|
||||
* location must be corrected after the transform operator is done. */
|
||||
* location must be corrected after the transform operator is done.
|
||||
*/
|
||||
NLASTRIP_FLAG_INVALID_LOCATION = (1 << 28),
|
||||
/** NLA strip should ignore frame range and hold settings, and evaluate at global time. */
|
||||
NLASTRIP_FLAG_NO_TIME_MAP = (1 << 29),
|
||||
|
@ -1031,9 +1035,11 @@ typedef enum eInsertKeyFlags {
|
|||
INSERTKEY_XYZ2RGB = (1 << 5),
|
||||
/** ignore user-prefs (needed for predictable API use) */
|
||||
INSERTKEY_NO_USERPREF = (1 << 6),
|
||||
/** Allow to make a full copy of new key into existing one, if any,
|
||||
/**
|
||||
* Allow to make a full copy of new key into existing one, if any,
|
||||
* instead of 'reusing' existing handles.
|
||||
* Used by copy/paste code. */
|
||||
* Used by copy/paste code.
|
||||
*/
|
||||
INSERTKEY_OVERWRITE_FULL = (1 << 7),
|
||||
/** for driver FCurves, use driver's "input" value - for easier corrective driver setup */
|
||||
INSERTKEY_DRIVER = (1 << 8),
|
||||
|
@ -1089,11 +1095,13 @@ typedef struct AnimOverride {
|
|||
typedef struct AnimData {
|
||||
/**
|
||||
* Active action - acts as the 'tweaking track' for the NLA.
|
||||
* Either use BKE_animdata_set_action() to set this, or call BKE_animdata_action_ensure_idroot()
|
||||
* after setting. */
|
||||
* Either use BKE_animdata_set_action() to set this, or call
|
||||
* #BKE_animdata_action_ensure_idroot() after setting.
|
||||
*/
|
||||
bAction *action;
|
||||
|
||||
/** temp-storage for the 'real' active action (i.e. the one used before the tweaking-action
|
||||
/**
|
||||
* Temp-storage for the 'real' active action (i.e. the one used before the tweaking-action
|
||||
* took over to be edited in the Animation Editors)
|
||||
*/
|
||||
bAction *tmpact;
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include "DNA_defs.h"
|
||||
|
||||
#include "BLI_implicit_sharing.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -53,6 +55,11 @@ typedef struct CustomDataLayer {
|
|||
* attribute was created.
|
||||
*/
|
||||
const AnonymousAttributeIDHandle *anonymous_id;
|
||||
/**
|
||||
* Run-time data that allows sharing `data` with other entities (mostly custom data layers on
|
||||
* other geometries).
|
||||
*/
|
||||
const ImplicitSharingInfoHandle *sharing_info;
|
||||
} CustomDataLayer;
|
||||
|
||||
#define MAX_CUSTOMDATA_LAYER_NAME 68
|
||||
|
@ -241,8 +248,7 @@ typedef struct CustomData_MeshMasks {
|
|||
enum {
|
||||
/* Indicates layer should not be copied by CustomData_from_template or CustomData_copy_data */
|
||||
CD_FLAG_NOCOPY = (1 << 0),
|
||||
/* Indicates layer should not be freed (for layers backed by external data) */
|
||||
CD_FLAG_NOFREE = (1 << 1),
|
||||
CD_FLAG_UNUSED = (1 << 1),
|
||||
/* Indicates the layer is only temporary, also implies no copy */
|
||||
CD_FLAG_TEMPORARY = ((1 << 2) | CD_FLAG_NOCOPY),
|
||||
/* Indicates the layer is stored in an external file */
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#ifdef __cplusplus
|
||||
# include "BLI_math_vector_types.hh"
|
||||
# include "BLI_span.hh"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -51,6 +52,9 @@ typedef struct PointCloud {
|
|||
short _pad3[3];
|
||||
|
||||
#ifdef __cplusplus
|
||||
blender::Span<blender::float3> positions() const;
|
||||
blender::MutableSpan<blender::float3> positions_for_write();
|
||||
|
||||
blender::bke::AttributeAccessor attributes() const;
|
||||
blender::bke::MutableAttributeAccessor attributes_for_write();
|
||||
|
||||
|
|
|
@ -696,7 +696,7 @@ ModifierTypeInfo modifierType_Ocean = {
|
|||
/*icon*/ ICON_MOD_OCEAN,
|
||||
|
||||
/*copyData*/ copyData,
|
||||
/*deformMatrices*/ nullptr,
|
||||
/*deformVerts*/ nullptr,
|
||||
|
||||
/*deformMatrices*/ nullptr,
|
||||
/*deformVertsEM*/ nullptr,
|
||||
|
|
|
@ -243,14 +243,11 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
|
||||
PointCloud *pointcloud = BKE_pointcloud_new_nomain(positions.size());
|
||||
bke::MutableAttributeAccessor point_attributes = pointcloud->attributes_for_write();
|
||||
bke::SpanAttributeWriter<float3> point_positions =
|
||||
point_attributes.lookup_or_add_for_write_only_span<float3>("position", ATTR_DOMAIN_POINT);
|
||||
pointcloud->positions_for_write().copy_from(positions);
|
||||
bke::SpanAttributeWriter<float> point_radii =
|
||||
point_attributes.lookup_or_add_for_write_only_span<float>("radius", ATTR_DOMAIN_POINT);
|
||||
|
||||
point_positions.span.copy_from(positions);
|
||||
point_radii.span.fill(0.05f);
|
||||
point_positions.finish();
|
||||
point_radii.finish();
|
||||
|
||||
geometry_set.replace_pointcloud(pointcloud);
|
||||
|
|
|
@ -539,13 +539,10 @@ static void point_distribution_calculate(GeometrySet &geometry_set,
|
|||
|
||||
PointCloud *pointcloud = BKE_pointcloud_new_nomain(positions.size());
|
||||
bke::MutableAttributeAccessor point_attributes = pointcloud->attributes_for_write();
|
||||
bke::SpanAttributeWriter<float3> point_positions =
|
||||
point_attributes.lookup_or_add_for_write_only_span<float3>("position", ATTR_DOMAIN_POINT);
|
||||
bke::SpanAttributeWriter<float> point_radii =
|
||||
point_attributes.lookup_or_add_for_write_only_span<float>("radius", ATTR_DOMAIN_POINT);
|
||||
point_positions.span.copy_from(positions);
|
||||
pointcloud->positions_for_write().copy_from(positions);
|
||||
point_radii.span.fill(0.05f);
|
||||
point_positions.finish();
|
||||
point_radii.finish();
|
||||
|
||||
geometry_set.replace_pointcloud(pointcloud);
|
||||
|
|
|
@ -119,7 +119,7 @@ static void expand_mesh(Mesh &mesh,
|
|||
}
|
||||
}
|
||||
|
||||
static CustomData &get_customdata(Mesh &mesh, const eAttrDomain domain)
|
||||
static CustomData &mesh_custom_data_for_domain(Mesh &mesh, const eAttrDomain domain)
|
||||
{
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
|
@ -142,7 +142,7 @@ static CustomData &get_customdata(Mesh &mesh, const eAttrDomain domain)
|
|||
static MutableSpan<int> get_orig_index_layer(Mesh &mesh, const eAttrDomain domain)
|
||||
{
|
||||
const bke::AttributeAccessor attributes = mesh.attributes();
|
||||
CustomData &custom_data = get_customdata(mesh, domain);
|
||||
CustomData &custom_data = mesh_custom_data_for_domain(mesh, domain);
|
||||
if (int *orig_indices = static_cast<int *>(CustomData_get_layer_for_write(
|
||||
&custom_data, CD_ORIGINDEX, attributes.domain_size(domain)))) {
|
||||
return {orig_indices, attributes.domain_size(domain)};
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_array_utils.hh"
|
||||
|
||||
#include "DNA_pointcloud_types.h"
|
||||
|
||||
#include "BKE_attribute_math.hh"
|
||||
|
@ -26,7 +28,7 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||
static void convert_instances_to_points(GeometrySet &geometry_set,
|
||||
Field<float3> position_field,
|
||||
Field<float> radius_field,
|
||||
const Field<bool> selection_field,
|
||||
Field<bool> selection_field,
|
||||
const AnonymousAttributePropagationInfo &propagation_info)
|
||||
{
|
||||
const bke::Instances &instances = *geometry_set.get_instances_for_read();
|
||||
|
@ -41,22 +43,17 @@ static void convert_instances_to_points(GeometrySet &geometry_set,
|
|||
if (selection.is_empty()) {
|
||||
return;
|
||||
}
|
||||
const VArray<float3> &positions = evaluator.get_evaluated<float3>(0);
|
||||
const VArray<float3> positions = evaluator.get_evaluated<float3>(0);
|
||||
const VArray<float> radii = evaluator.get_evaluated<float>(1);
|
||||
|
||||
PointCloud *pointcloud = BKE_pointcloud_new_nomain(selection.size());
|
||||
geometry_set.replace_pointcloud(pointcloud);
|
||||
array_utils::gather(positions, selection, pointcloud->positions_for_write());
|
||||
|
||||
bke::MutableAttributeAccessor point_attributes = pointcloud->attributes_for_write();
|
||||
|
||||
bke::SpanAttributeWriter<float3> point_positions =
|
||||
point_attributes.lookup_or_add_for_write_only_span<float3>("position", ATTR_DOMAIN_POINT);
|
||||
bke::SpanAttributeWriter<float> point_radii =
|
||||
point_attributes.lookup_or_add_for_write_only_span<float>("radius", ATTR_DOMAIN_POINT);
|
||||
|
||||
positions.materialize_compressed_to_uninitialized(selection, point_positions.span);
|
||||
radii.materialize_compressed_to_uninitialized(selection, point_radii.span);
|
||||
point_positions.finish();
|
||||
array_utils::gather(radii, selection, point_radii.span);
|
||||
point_radii.finish();
|
||||
|
||||
Map<AttributeIDRef, AttributeKind> attributes_to_propagate;
|
||||
|
|
|
@ -71,18 +71,15 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
|
||||
PointCloud *points = BKE_pointcloud_new_nomain(count);
|
||||
MutableAttributeAccessor attributes = points->attributes_for_write();
|
||||
AttributeWriter<float3> output_position = attributes.lookup_or_add_for_write<float3>(
|
||||
"position", ATTR_DOMAIN_POINT);
|
||||
AttributeWriter<float> output_radii = attributes.lookup_or_add_for_write<float>(
|
||||
"radius", ATTR_DOMAIN_POINT);
|
||||
|
||||
PointsFieldContext context{count};
|
||||
fn::FieldEvaluator evaluator{context, count};
|
||||
evaluator.add_with_destination(position_field, output_position.varray);
|
||||
evaluator.add_with_destination(position_field, points->positions_for_write());
|
||||
evaluator.add_with_destination(radius_field, output_radii.varray);
|
||||
evaluator.evaluate();
|
||||
|
||||
output_position.finish();
|
||||
output_radii.finish();
|
||||
params.set_output("Geometry", GeometrySet::create_with_pointcloud(points));
|
||||
}
|
||||
|
|
|
@ -3332,14 +3332,14 @@ static PySequenceMethods bpy_bmelemseq_as_sequence = {
|
|||
};
|
||||
|
||||
static PyMappingMethods bpy_bmelemseq_as_mapping = {
|
||||
/*mp_len*/ (lenfunc)bpy_bmelemseq_length,
|
||||
/*mp_length*/ (lenfunc)bpy_bmelemseq_length,
|
||||
/*mp_subscript*/ (binaryfunc)bpy_bmelemseq_subscript,
|
||||
/*mp_ass_subscript*/ (objobjargproc)NULL,
|
||||
};
|
||||
|
||||
/* for customdata access */
|
||||
static PyMappingMethods bpy_bm_elem_as_mapping = {
|
||||
/*mp_len*/ (lenfunc)NULL, /* Keep this empty, messes up `if elem: ...` test. */
|
||||
/*mp_length*/ (lenfunc)NULL, /* Keep this empty, messes up `if elem: ...` test. */
|
||||
/*mp_subscript*/ (binaryfunc)bpy_bmelem_subscript,
|
||||
/*mp_ass_subscript*/ (objobjargproc)bpy_bmelem_ass_subscript,
|
||||
};
|
||||
|
|
|
@ -899,7 +899,7 @@ static PySequenceMethods bpy_bmlayercollection_as_sequence = {
|
|||
};
|
||||
|
||||
static PyMappingMethods bpy_bmlayercollection_as_mapping = {
|
||||
/*mp_len*/ (lenfunc)bpy_bmlayercollection_length,
|
||||
/*mp_length*/ (lenfunc)bpy_bmlayercollection_length,
|
||||
/*mp_subscript*/ (binaryfunc)bpy_bmlayercollection_subscript,
|
||||
/*mp_ass_subscript*/ (objobjargproc)NULL,
|
||||
};
|
||||
|
|
|
@ -213,7 +213,7 @@ PyObject *BPy_BMLoopUV_CreatePyObject(struct BMesh *bm, BMLoop *loop, int layer)
|
|||
{
|
||||
BPy_BMLoopUV *self = PyObject_New(BPy_BMLoopUV, &BPy_BMLoopUV_Type);
|
||||
|
||||
const BMUVOffsets offsets = BM_uv_map_get_offsets_n(bm, layer);
|
||||
const BMUVOffsets offsets = BM_uv_map_get_offsets_from_layer(bm, layer);
|
||||
|
||||
self->uv = BM_ELEM_CD_GET_FLOAT_P(loop, offsets.uv);
|
||||
self->vert_select = offsets.select_vert >= 0 ? BM_ELEM_CD_GET_BOOL_P(loop, offsets.select_vert) :
|
||||
|
@ -588,7 +588,7 @@ static PySequenceMethods bpy_bmdeformvert_as_sequence = {
|
|||
};
|
||||
|
||||
static PyMappingMethods bpy_bmdeformvert_as_mapping = {
|
||||
/*mp_len*/ (lenfunc)bpy_bmdeformvert_len,
|
||||
/*mp_length*/ (lenfunc)bpy_bmdeformvert_len,
|
||||
/*mp_subscript*/ (binaryfunc)bpy_bmdeformvert_subscript,
|
||||
/*mp_ass_subscript*/ (objobjargproc)bpy_bmdeformvert_ass_subscript,
|
||||
};
|
||||
|
|
|
@ -305,7 +305,7 @@ static PySequenceMethods bpy_bmeditselseq_as_sequence = {
|
|||
};
|
||||
|
||||
static PyMappingMethods bpy_bmeditselseq_as_mapping = {
|
||||
/*mp_len*/ (lenfunc)bpy_bmeditselseq_length,
|
||||
/*mp_length*/ (lenfunc)bpy_bmeditselseq_length,
|
||||
/*mp_subscript*/ (binaryfunc)bpy_bmeditselseq_subscript,
|
||||
/*mp_ass_subscript*/ (objobjargproc)NULL,
|
||||
};
|
||||
|
|
|
@ -557,7 +557,7 @@ static PySequenceMethods Buffer_SeqMethods = {
|
|||
};
|
||||
|
||||
static PyMappingMethods Buffer_AsMapping = {
|
||||
/*mp_len*/ (lenfunc)Buffer_len,
|
||||
/*mp_length*/ (lenfunc)Buffer_len,
|
||||
/*mp_subscript*/ (binaryfunc)Buffer_subscript,
|
||||
/*mp_ass_subscript*/ (objobjargproc)Buffer_ass_subscript,
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue