WIP: Vulkan: Initial Immediate Mode Support. #106954

Closed
Jeroen Bakker wants to merge 27 commits from Jeroen-Bakker:vulkan-immediate into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
111 changed files with 1951 additions and 953 deletions
Showing only changes of commit 6c407c94f4 - Show all commits

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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();

View File

@ -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)

View File

@ -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

View File

@ -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.
***************************************************************************************/

View File

@ -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();

View File

@ -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>(

View File

@ -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.

View File

@ -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
* \{ */

View File

@ -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.

View File

@ -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))

View File

@ -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)

View File

@ -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...")

View File

@ -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;

View File

@ -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

View File

@ -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]]; \

View File

@ -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);

View File

@ -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;

View File

@ -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)) {

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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__);

View File

@ -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;
}

View File

@ -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.

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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. */

View File

@ -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()) {

View File

@ -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;
}
}

View File

@ -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)
{

View File

@ -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,
};
/** \} */

View File

@ -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);
}
}

View File

@ -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;

View File

@ -187,7 +187,6 @@ struct PBVH {
/* flag are verts/faces deformed */
bool deformed;
bool respect_hide;
/* Dynamic topology */
float bm_max_edge_len;

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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));
});
}

View File

@ -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

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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, &params->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;

View File

@ -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,

View File

@ -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

View File

@ -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]");

View File

@ -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_);
}

View File

@ -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) {

View File

@ -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 */

View File

@ -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;
}

View File

@ -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[] = {

View File

@ -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

View File

@ -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) {

View File

@ -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)

View File

@ -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)

View File

@ -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,
};
/* -------------------------------------------------------------------- */

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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 *>(

View File

@ -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

View File

@ -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;

View File

@ -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 {

View File

@ -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));
}

View File

@ -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);

View File

@ -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
* \{ */

View File

@ -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);

View File

@ -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++) {

View File

@ -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,

View File

@ -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)

View File

@ -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);

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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.
*/

View File

@ -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();

View File

@ -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];

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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)) {

View File

@ -14,12 +14,11 @@ set(INC
../../makesrna
../../nodes
../../windowmanager
../../../../extern/fast_float
../../../../intern/guardedalloc
)
set(INC_SYS
../../../../extern/fast_float
)
set(SRC

View File

@ -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;

View File

@ -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 */

View 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();

View File

@ -696,7 +696,7 @@ ModifierTypeInfo modifierType_Ocean = {
/*icon*/ ICON_MOD_OCEAN,
/*copyData*/ copyData,
/*deformMatrices*/ nullptr,
/*deformVerts*/ nullptr,
/*deformMatrices*/ nullptr,
/*deformVertsEM*/ nullptr,

View File

@ -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);

View File

@ -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);

View File

@ -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)};

View File

@ -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;

View File

@ -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));
}

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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