Merge branch 'master' into sculpt-dev
This commit is contained in:
commit
58406eddb5
|
@ -951,7 +951,7 @@ class CPUDevice : public Device {
|
|||
SIMD_SET_FLUSH_TO_ZERO;
|
||||
|
||||
for (int sample = start_sample; sample < end_sample; sample++) {
|
||||
if (task.get_cancel() || task_pool.canceled()) {
|
||||
if (task.get_cancel() || TaskPool::canceled()) {
|
||||
if (task.need_finish_queue == false)
|
||||
break;
|
||||
}
|
||||
|
@ -1249,7 +1249,7 @@ class CPUDevice : public Device {
|
|||
|
||||
void thread_render(DeviceTask &task)
|
||||
{
|
||||
if (task_pool.canceled()) {
|
||||
if (TaskPool::canceled()) {
|
||||
if (task.need_finish_queue == false)
|
||||
return;
|
||||
}
|
||||
|
@ -1319,7 +1319,7 @@ class CPUDevice : public Device {
|
|||
|
||||
task.release_tile(tile);
|
||||
|
||||
if (task_pool.canceled()) {
|
||||
if (TaskPool::canceled()) {
|
||||
if (task.need_finish_queue == false)
|
||||
break;
|
||||
}
|
||||
|
@ -1416,7 +1416,7 @@ class CPUDevice : public Device {
|
|||
task.offset,
|
||||
sample);
|
||||
|
||||
if (task.get_cancel() || task_pool.canceled())
|
||||
if (task.get_cancel() || TaskPool::canceled())
|
||||
break;
|
||||
|
||||
task.update_progress(NULL);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <OSL/oslclosure.h>
|
||||
#include <OSL/oslexec.h>
|
||||
#include <OSL/rendererservices.h>
|
||||
|
||||
#ifdef WITH_PTEX
|
||||
class PtexCache;
|
||||
|
|
|
@ -62,7 +62,7 @@ void TaskPool::cancel()
|
|||
|
||||
bool TaskPool::canceled()
|
||||
{
|
||||
return tbb_group.is_canceling();
|
||||
return tbb::is_current_task_group_canceling();
|
||||
}
|
||||
|
||||
/* Task Scheduler */
|
||||
|
|
|
@ -61,7 +61,7 @@ class TaskPool {
|
|||
void wait_work(Summary *stats = NULL); /* work and wait until all tasks are done */
|
||||
void cancel(); /* cancel all tasks and wait until they are no longer executing */
|
||||
|
||||
bool canceled(); /* for worker threads, test if canceled */
|
||||
static bool canceled(); /* For worker threads, test if current task pool canceled. */
|
||||
|
||||
protected:
|
||||
tbb::task_group tbb_group;
|
||||
|
|
|
@ -49,12 +49,6 @@ set(LIB
|
|||
)
|
||||
|
||||
if(WIN32 AND NOT UNIX)
|
||||
list(APPEND SRC
|
||||
intern/mmap_win.c
|
||||
|
||||
mmap_win.h
|
||||
)
|
||||
|
||||
list(APPEND INC_SYS
|
||||
${PTHREADS_INC}
|
||||
)
|
||||
|
|
|
@ -1,294 +0,0 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2008 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup MEM
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
# include <errno.h>
|
||||
# include <io.h>
|
||||
# include <stdio.h>
|
||||
# include <sys/types.h>
|
||||
# include <windows.h>
|
||||
|
||||
# include "mmap_win.h"
|
||||
|
||||
# ifndef FILE_MAP_EXECUTE
|
||||
// not defined in earlier versions of the Platform SDK (before February 2003)
|
||||
# define FILE_MAP_EXECUTE 0x0020
|
||||
# endif
|
||||
|
||||
/* copied from BLI_utildefines.h, ugh */
|
||||
# ifdef __GNUC__
|
||||
# define UNUSED(x) UNUSED_##x __attribute__((__unused__))
|
||||
# else
|
||||
# define UNUSED(x) x
|
||||
# endif
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* local storage definitions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* all memory mapped chunks are put in linked lists */
|
||||
typedef struct mmapLink {
|
||||
struct mmapLink *next, *prev;
|
||||
} mmapLink;
|
||||
|
||||
typedef struct mmapListBase {
|
||||
void *first, *last;
|
||||
} mmapListBase;
|
||||
|
||||
typedef struct MemMap {
|
||||
struct MemMap *next, *prev;
|
||||
void *mmap;
|
||||
HANDLE fhandle;
|
||||
HANDLE maphandle;
|
||||
} MemMap;
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* local functions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static void mmap_addtail(volatile mmapListBase *listbase, void *vlink);
|
||||
static void mmap_remlink(volatile mmapListBase *listbase, void *vlink);
|
||||
static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr);
|
||||
|
||||
static int mmap_get_prot_flags(int flags);
|
||||
static int mmap_get_access_flags(int flags);
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* vars */
|
||||
/* --------------------------------------------------------------------- */
|
||||
volatile static struct mmapListBase _mmapbase;
|
||||
volatile static struct mmapListBase *mmapbase = &_mmapbase;
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* implementation */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* mmap for windows */
|
||||
void *mmap(void *UNUSED(start), size_t len, int prot, int flags, int fd, off_t offset)
|
||||
{
|
||||
HANDLE fhandle = INVALID_HANDLE_VALUE;
|
||||
HANDLE maphandle;
|
||||
int prot_flags = mmap_get_prot_flags(prot);
|
||||
int access_flags = mmap_get_access_flags(prot);
|
||||
MemMap *mm = NULL;
|
||||
void *ptr = NULL;
|
||||
|
||||
if (flags & MAP_FIXED) {
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
# if 0
|
||||
if (fd == -1) {
|
||||
_set_errno(EBADF);
|
||||
return MAP_FAILED;
|
||||
}
|
||||
# endif
|
||||
|
||||
if (fd != -1) {
|
||||
fhandle = (HANDLE)_get_osfhandle(fd);
|
||||
}
|
||||
if (fhandle == INVALID_HANDLE_VALUE) {
|
||||
if (!(flags & MAP_ANONYMOUS)) {
|
||||
errno = EBADF;
|
||||
return MAP_FAILED;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!DuplicateHandle(GetCurrentProcess(),
|
||||
fhandle,
|
||||
GetCurrentProcess(),
|
||||
&fhandle,
|
||||
0,
|
||||
FALSE,
|
||||
DUPLICATE_SAME_ACCESS)) {
|
||||
return MAP_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Split 64 bit size into low and high bits. */
|
||||
DWORD len_bits_high = len >> 32;
|
||||
DWORD len_bits_low = len & 0xFFFFFFFF;
|
||||
|
||||
maphandle = CreateFileMapping(fhandle, NULL, prot_flags, len_bits_high, len_bits_low, NULL);
|
||||
if (maphandle == 0) {
|
||||
errno = EBADF;
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
ptr = MapViewOfFile(maphandle, access_flags, 0, offset, 0);
|
||||
if (ptr == NULL) {
|
||||
DWORD dwLastErr = GetLastError();
|
||||
if (dwLastErr == ERROR_MAPPED_ALIGNMENT) {
|
||||
errno = EINVAL;
|
||||
}
|
||||
else {
|
||||
errno = EACCES;
|
||||
}
|
||||
CloseHandle(maphandle);
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
mm = (MemMap *)malloc(sizeof(MemMap));
|
||||
if (!mm) {
|
||||
errno = ENOMEM;
|
||||
}
|
||||
mm->fhandle = fhandle;
|
||||
mm->maphandle = maphandle;
|
||||
mm->mmap = ptr;
|
||||
mmap_addtail(mmapbase, mm);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* munmap for windows */
|
||||
intptr_t munmap(void *ptr, size_t UNUSED(size))
|
||||
{
|
||||
MemMap *mm = mmap_findlink(mmapbase, ptr);
|
||||
if (!mm) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
UnmapViewOfFile(mm->mmap);
|
||||
CloseHandle(mm->maphandle);
|
||||
CloseHandle(mm->fhandle);
|
||||
mmap_remlink(mmapbase, mm);
|
||||
free(mm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* local functions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static void mmap_addtail(volatile mmapListBase *listbase, void *vlink)
|
||||
{
|
||||
struct mmapLink *link = vlink;
|
||||
|
||||
if (link == NULL) {
|
||||
return;
|
||||
}
|
||||
if (listbase == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
link->next = 0;
|
||||
link->prev = listbase->last;
|
||||
|
||||
if (listbase->last) {
|
||||
((struct mmapLink *)listbase->last)->next = link;
|
||||
}
|
||||
if (listbase->first == NULL) {
|
||||
listbase->first = link;
|
||||
}
|
||||
listbase->last = link;
|
||||
}
|
||||
|
||||
static void mmap_remlink(volatile mmapListBase *listbase, void *vlink)
|
||||
{
|
||||
struct mmapLink *link = vlink;
|
||||
|
||||
if (link == NULL) {
|
||||
return;
|
||||
}
|
||||
if (listbase == NULL) {
|
||||
return;
|
||||
}
|
||||
if (link->next) {
|
||||
link->next->prev = link->prev;
|
||||
}
|
||||
if (link->prev) {
|
||||
link->prev->next = link->next;
|
||||
}
|
||||
|
||||
if (listbase->last == link) {
|
||||
listbase->last = link->prev;
|
||||
}
|
||||
if (listbase->first == link) {
|
||||
listbase->first = link->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr)
|
||||
{
|
||||
MemMap *mm;
|
||||
|
||||
if (ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (listbase == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mm = (MemMap *)listbase->first;
|
||||
while (mm) {
|
||||
if (mm->mmap == ptr) {
|
||||
return mm;
|
||||
}
|
||||
mm = mm->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int mmap_get_prot_flags(int flags)
|
||||
{
|
||||
int prot = PAGE_NOACCESS;
|
||||
|
||||
if ((flags & PROT_READ) == PROT_READ) {
|
||||
if ((flags & PROT_WRITE) == PROT_WRITE) {
|
||||
prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
|
||||
}
|
||||
else {
|
||||
prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READ : PAGE_READONLY;
|
||||
}
|
||||
}
|
||||
else if ((flags & PROT_WRITE) == PROT_WRITE) {
|
||||
prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READ : PAGE_WRITECOPY;
|
||||
}
|
||||
else if ((flags & PROT_EXEC) == PROT_EXEC) {
|
||||
prot = PAGE_EXECUTE_READ;
|
||||
}
|
||||
return prot;
|
||||
}
|
||||
|
||||
static int mmap_get_access_flags(int flags)
|
||||
{
|
||||
int access = 0;
|
||||
|
||||
if ((flags & PROT_READ) == PROT_READ) {
|
||||
if ((flags & PROT_WRITE) == PROT_WRITE) {
|
||||
access = FILE_MAP_WRITE;
|
||||
}
|
||||
else {
|
||||
access = (flags & PROT_EXEC) ? FILE_MAP_EXECUTE : FILE_MAP_READ;
|
||||
}
|
||||
}
|
||||
else if ((flags & PROT_WRITE) == PROT_WRITE) {
|
||||
access = FILE_MAP_COPY;
|
||||
}
|
||||
else if ((flags & PROT_EXEC) == PROT_EXEC) {
|
||||
access = FILE_MAP_EXECUTE;
|
||||
}
|
||||
return access;
|
||||
}
|
||||
|
||||
#endif // WIN32
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2008 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup MEM
|
||||
*/
|
||||
|
||||
#ifndef __MMAP_WIN_H__
|
||||
#define __MMAP_WIN_H__
|
||||
|
||||
#define PROT_NONE 0
|
||||
#define PROT_READ 1
|
||||
#define PROT_WRITE 2
|
||||
#define PROT_EXEC 4
|
||||
|
||||
#define MAP_FILE 0
|
||||
#define MAP_SHARED 1
|
||||
#define MAP_PRIVATE 2
|
||||
#define MAP_TYPE 0xF
|
||||
#define MAP_FIXED 0x10
|
||||
#define MAP_ANONYMOUS 0x20
|
||||
#define MAP_ANON MAP_ANONYMOUS
|
||||
|
||||
#define MAP_FAILED ((void *)-1)
|
||||
|
||||
/* needed for uintptr_t, exception, dont use BLI anywhere else in MEM_* */
|
||||
#include "../../source/blender/blenlib/BLI_sys_types.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
void *mmap(void *start, size_t len, int prot, int flags, int fd, off_t offset);
|
||||
intptr_t munmap(void *ptr, size_t size);
|
||||
|
||||
#endif
|
|
@ -678,16 +678,8 @@ class NODE_UL_interface_sockets(bpy.types.UIList):
|
|||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
||||
row = layout.row(align=True)
|
||||
|
||||
# inputs get icon on the left
|
||||
if not socket.is_output:
|
||||
row.template_node_socket(color=color)
|
||||
|
||||
row.template_node_socket(color=color)
|
||||
row.prop(socket, "name", text="", emboss=False, icon_value=icon)
|
||||
|
||||
# outputs get icon on the right
|
||||
if socket.is_output:
|
||||
row.template_node_socket(color=color)
|
||||
|
||||
elif self.layout_type == 'GRID':
|
||||
layout.alignment = 'CENTER'
|
||||
layout.template_node_socket(color=color)
|
||||
|
|
|
@ -212,8 +212,7 @@ struct NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(
|
|||
struct ListBase *cache,
|
||||
struct PointerRNA *ptr,
|
||||
struct AnimData *adt,
|
||||
const struct AnimationEvalContext *anim_eval_context,
|
||||
const bool flush_to_original);
|
||||
const struct AnimationEvalContext *anim_eval_context);
|
||||
bool BKE_animsys_nla_remap_keyframe_values(struct NlaKeyframingContext *context,
|
||||
struct PointerRNA *prop_ptr,
|
||||
struct PropertyRNA *prop,
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "BLI_color.hh"
|
||||
#include "BLI_float2.hh"
|
||||
#include "BLI_float3.hh"
|
||||
#include "DNA_customdata_types.h"
|
||||
|
||||
namespace blender::attribute_math {
|
||||
|
||||
/**
|
||||
* Utility function that simplifies calling a templated function based on a custom data type.
|
||||
*/
|
||||
template<typename Func>
|
||||
void convert_to_static_type(const CustomDataType data_type, const Func &func)
|
||||
{
|
||||
switch (data_type) {
|
||||
case CD_PROP_FLOAT:
|
||||
func(float());
|
||||
break;
|
||||
case CD_PROP_FLOAT2:
|
||||
func(float2());
|
||||
break;
|
||||
case CD_PROP_FLOAT3:
|
||||
func(float3());
|
||||
break;
|
||||
case CD_PROP_INT32:
|
||||
func(int());
|
||||
break;
|
||||
case CD_PROP_BOOL:
|
||||
func(bool());
|
||||
break;
|
||||
case CD_PROP_COLOR:
|
||||
func(Color4f());
|
||||
break;
|
||||
default:
|
||||
BLI_assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Interpolate between three values. */
|
||||
template<typename T> T mix3(const float3 &weights, const T &v0, const T &v1, const T &v2);
|
||||
|
||||
template<> inline bool mix3(const float3 &weights, const bool &v0, const bool &v1, const bool &v2)
|
||||
{
|
||||
return (weights.x * v0 + weights.y * v1 + weights.z * v2) >= 0.5f;
|
||||
}
|
||||
|
||||
template<> inline int mix3(const float3 &weights, const int &v0, const int &v1, const int &v2)
|
||||
{
|
||||
return static_cast<int>(weights.x * v0 + weights.y * v1 + weights.z * v2);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline float mix3(const float3 &weights, const float &v0, const float &v1, const float &v2)
|
||||
{
|
||||
return weights.x * v0 + weights.y * v1 + weights.z * v2;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline float2 mix3(const float3 &weights, const float2 &v0, const float2 &v1, const float2 &v2)
|
||||
{
|
||||
return weights.x * v0 + weights.y * v1 + weights.z * v2;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline float3 mix3(const float3 &weights, const float3 &v0, const float3 &v1, const float3 &v2)
|
||||
{
|
||||
return weights.x * v0 + weights.y * v1 + weights.z * v2;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline Color4f mix3(const float3 &weights, const Color4f &v0, const Color4f &v1, const Color4f &v2)
|
||||
{
|
||||
Color4f result;
|
||||
interp_v4_v4v4v4(result, v0, v1, v2, weights);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace blender::attribute_math
|
|
@ -242,7 +242,8 @@ class GeometryComponent {
|
|||
|
||||
/**
|
||||
* If an attribute with the given params exist, it is returned.
|
||||
* If no attribute with the given name exists, it is created and returned.
|
||||
* If no attribute with the given name exists, create it and
|
||||
* fill it with the default value if it is provided.
|
||||
* If an attribute with the given name but different domain or type exists, a temporary attribute
|
||||
* is created that has to be saved after the output has been computed. This avoids deleting
|
||||
* another attribute, before a computation is finished.
|
||||
|
@ -251,7 +252,8 @@ class GeometryComponent {
|
|||
*/
|
||||
OutputAttributePtr attribute_try_get_for_output(const blender::StringRef attribute_name,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type);
|
||||
const CustomDataType data_type,
|
||||
const void *default_value = nullptr);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -463,8 +463,8 @@ void ntreeSetOutput(struct bNodeTree *ntree);
|
|||
|
||||
void ntreeFreeCache(struct bNodeTree *ntree);
|
||||
|
||||
bool ntreeNodeExists(struct bNodeTree *ntree, struct bNode *testnode);
|
||||
bool ntreeOutputExists(struct bNode *node, struct bNodeSocket *testsock);
|
||||
bool ntreeNodeExists(const struct bNodeTree *ntree, const struct bNode *testnode);
|
||||
bool ntreeOutputExists(const struct bNode *node, const struct bNodeSocket *testsock);
|
||||
void ntreeNodeFlagSet(const bNodeTree *ntree, const int flag, const bool enable);
|
||||
struct bNodeTree *ntreeLocalize(struct bNodeTree *ntree);
|
||||
void ntreeLocalSync(struct bNodeTree *localtree, struct bNodeTree *ntree);
|
||||
|
@ -501,7 +501,7 @@ struct bNodeSocket *ntreeInsertSocketInterfaceFromSocket(struct bNodeTree *ntree
|
|||
struct bNodeSocket *from_sock);
|
||||
void ntreeRemoveSocketInterface(struct bNodeTree *ntree, struct bNodeSocket *sock);
|
||||
|
||||
struct StructRNA *ntreeInterfaceTypeGet(struct bNodeTree *ntree, int create);
|
||||
struct StructRNA *ntreeInterfaceTypeGet(struct bNodeTree *ntree, bool create);
|
||||
void ntreeInterfaceTypeFree(struct bNodeTree *ntree);
|
||||
void ntreeInterfaceTypeUpdate(struct bNodeTree *ntree);
|
||||
|
||||
|
@ -624,12 +624,12 @@ struct bNodeLink *nodeAddLink(struct bNodeTree *ntree,
|
|||
struct bNodeSocket *tosock);
|
||||
void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link);
|
||||
void nodeRemSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock);
|
||||
bool nodeLinkIsHidden(struct bNodeLink *link);
|
||||
bool nodeLinkIsHidden(const struct bNodeLink *link);
|
||||
void nodeInternalRelink(struct bNodeTree *ntree, struct bNode *node);
|
||||
|
||||
void nodeToView(struct bNode *node, float x, float y, float *rx, float *ry);
|
||||
void nodeFromView(struct bNode *node, float x, float y, float *rx, float *ry);
|
||||
bool nodeAttachNodeCheck(struct bNode *node, struct bNode *parent);
|
||||
void nodeToView(const struct bNode *node, float x, float y, float *rx, float *ry);
|
||||
void nodeFromView(const struct bNode *node, float x, float y, float *rx, float *ry);
|
||||
bool nodeAttachNodeCheck(const struct bNode *node, const struct bNode *parent);
|
||||
void nodeAttachNode(struct bNode *node, struct bNode *parent);
|
||||
void nodeDetachNode(struct bNode *node);
|
||||
|
||||
|
@ -661,9 +661,9 @@ void nodeChainIterBackwards(const bNodeTree *ntree,
|
|||
void nodeParentsIter(bNode *node, bool (*callback)(bNode *, void *), void *userdata);
|
||||
|
||||
struct bNodeLink *nodeFindLink(struct bNodeTree *ntree,
|
||||
struct bNodeSocket *from,
|
||||
struct bNodeSocket *to);
|
||||
int nodeCountSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock);
|
||||
const struct bNodeSocket *from,
|
||||
const struct bNodeSocket *to);
|
||||
int nodeCountSocketLinks(const struct bNodeTree *ntree, const struct bNodeSocket *sock);
|
||||
|
||||
void nodeSetSelected(struct bNode *node, bool select);
|
||||
void nodeSetActive(struct bNodeTree *ntree, struct bNode *node);
|
||||
|
@ -678,11 +678,11 @@ void nodeUpdate(struct bNodeTree *ntree, struct bNode *node);
|
|||
bool nodeUpdateID(struct bNodeTree *ntree, struct ID *id);
|
||||
void nodeUpdateInternalLinks(struct bNodeTree *ntree, struct bNode *node);
|
||||
|
||||
int nodeSocketIsHidden(struct bNodeSocket *sock);
|
||||
int nodeSocketIsHidden(const struct bNodeSocket *sock);
|
||||
void ntreeTagUsedSockets(struct bNodeTree *ntree);
|
||||
void nodeSetSocketAvailability(struct bNodeSocket *sock, bool is_available);
|
||||
|
||||
int nodeSocketLinkLimit(struct bNodeSocket *sock);
|
||||
int nodeSocketLinkLimit(const struct bNodeSocket *sock);
|
||||
|
||||
/* Node Clipboard */
|
||||
void BKE_node_clipboard_init(struct bNodeTree *ntree);
|
||||
|
@ -767,7 +767,7 @@ BLI_INLINE bool BKE_node_instance_hash_iterator_done(bNodeInstanceHashIterator *
|
|||
|
||||
/* Node Previews */
|
||||
|
||||
int BKE_node_preview_used(struct bNode *node);
|
||||
bool BKE_node_preview_used(const struct bNode *node);
|
||||
bNodePreview *BKE_node_preview_verify(
|
||||
struct bNodeInstanceHash *previews, bNodeInstanceKey key, int xsize, int ysize, bool create);
|
||||
bNodePreview *BKE_node_preview_copy(struct bNodePreview *preview);
|
||||
|
|
|
@ -275,6 +275,7 @@ set(SRC
|
|||
BKE_asset.h
|
||||
BKE_attribute.h
|
||||
BKE_attribute_access.hh
|
||||
BKE_attribute_math.hh
|
||||
BKE_autoexec.h
|
||||
BKE_blender.h
|
||||
BKE_blender_copybuffer.h
|
||||
|
|
|
@ -362,6 +362,20 @@ void BKE_keyingsets_blend_read_expand(BlendExpander *expander, ListBase *list)
|
|||
/* ***************************************** */
|
||||
/* Evaluation Data-Setting Backend */
|
||||
|
||||
static bool is_fcurve_evaluatable(FCurve *fcu)
|
||||
{
|
||||
if (fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) {
|
||||
return false;
|
||||
}
|
||||
if (fcu->grp != NULL && (fcu->grp->flag & AGRP_MUTED)) {
|
||||
return false;
|
||||
}
|
||||
if (BKE_fcurve_is_empty(fcu)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BKE_animsys_store_rna_setting(PointerRNA *ptr,
|
||||
/* typically 'fcu->rna_path', 'fcu->array_index' */
|
||||
const char *rna_path,
|
||||
|
@ -594,18 +608,11 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr,
|
|||
{
|
||||
/* Calculate then execute each curve. */
|
||||
LISTBASE_FOREACH (FCurve *, fcu, list) {
|
||||
/* Check if this F-Curve doesn't belong to a muted group. */
|
||||
if ((fcu->grp != NULL) && (fcu->grp->flag & AGRP_MUTED)) {
|
||||
continue;
|
||||
}
|
||||
/* Check if this curve should be skipped. */
|
||||
if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED))) {
|
||||
continue;
|
||||
}
|
||||
/* Skip empty curves, as if muted. */
|
||||
if (BKE_fcurve_is_empty(fcu)) {
|
||||
|
||||
if (!is_fcurve_evaluatable(fcu)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
PathResolvedRNA anim_rna;
|
||||
if (BKE_animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
|
||||
const float curval = calculate_fcurve(&anim_rna, fcu, anim_eval_context);
|
||||
|
@ -979,6 +986,19 @@ NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list,
|
|||
return nes;
|
||||
}
|
||||
|
||||
static NlaEvalStrip *nlastrips_ctime_get_strip_single(
|
||||
ListBase *dst_list,
|
||||
NlaStrip *single_strip,
|
||||
const AnimationEvalContext *anim_eval_context,
|
||||
const bool flush_to_original)
|
||||
{
|
||||
ListBase single_tracks_list;
|
||||
single_tracks_list.first = single_tracks_list.last = single_strip;
|
||||
|
||||
return nlastrips_ctime_get_strip(
|
||||
dst_list, &single_tracks_list, -1, anim_eval_context, flush_to_original);
|
||||
}
|
||||
|
||||
/* ---------------------- */
|
||||
|
||||
/* Initialize a valid mask, allocating memory if necessary. */
|
||||
|
@ -1152,7 +1172,7 @@ static void nlaeval_snapshot_free_data(NlaEvalSnapshot *snapshot)
|
|||
/* Free memory owned by this evaluation channel. */
|
||||
static void nlaevalchan_free_data(NlaEvalChannel *nec)
|
||||
{
|
||||
nlavalidmask_free(&nec->valid);
|
||||
nlavalidmask_free(&nec->domain);
|
||||
|
||||
if (nec->blend_snapshot != NULL) {
|
||||
nlaevalchan_snapshot_free(nec->blend_snapshot);
|
||||
|
@ -1353,7 +1373,7 @@ static NlaEvalChannel *nlaevalchan_verify_key(NlaEvalData *nlaeval,
|
|||
|
||||
nec->mix_mode = nlaevalchan_detect_mix_mode(key, length);
|
||||
|
||||
nlavalidmask_init(&nec->valid, length);
|
||||
nlavalidmask_init(&nec->domain, length);
|
||||
|
||||
nec->base_snapshot.channel = nec;
|
||||
nec->base_snapshot.length = length;
|
||||
|
@ -1682,14 +1702,6 @@ static bool nlaeval_blend_value(NlaBlendData *blend,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (nec->mix_mode == NEC_MIX_QUATERNION) {
|
||||
/* For quaternion properties, always output all sub-channels. */
|
||||
BLI_bitmap_set_all(nec->valid.ptr, true, 4);
|
||||
}
|
||||
else {
|
||||
BLI_BITMAP_ENABLE(nec->valid.ptr, array_index);
|
||||
}
|
||||
|
||||
NlaEvalChannelSnapshot *nec_snapshot = nlaeval_snapshot_ensure_channel(blend->snapshot, nec);
|
||||
float *p_value = &nec_snapshot->values[array_index];
|
||||
|
||||
|
@ -1889,16 +1901,8 @@ static void nlastrip_evaluate_actionclip(PointerRNA *ptr,
|
|||
/* Evaluate all the F-Curves in the action,
|
||||
* saving the relevant pointers to data that will need to be used. */
|
||||
for (fcu = strip->act->curves.first; fcu; fcu = fcu->next) {
|
||||
float value = 0.0f;
|
||||
|
||||
/* check if this curve should be skipped */
|
||||
if (fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) {
|
||||
continue;
|
||||
}
|
||||
if ((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) {
|
||||
continue;
|
||||
}
|
||||
if (BKE_fcurve_is_empty(fcu)) {
|
||||
if (!is_fcurve_evaluatable(fcu)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1906,7 +1910,7 @@ static void nlastrip_evaluate_actionclip(PointerRNA *ptr,
|
|||
* NOTE: we use the modified time here, since strip's F-Curve Modifiers
|
||||
* are applied on top of this.
|
||||
*/
|
||||
value = evaluate_fcurve(fcu, evaltime);
|
||||
float value = evaluate_fcurve(fcu, evaltime);
|
||||
|
||||
/* apply strip's F-Curve Modifiers on this value
|
||||
* NOTE: we apply the strip's original evaluation time not the modified one
|
||||
|
@ -2099,12 +2103,21 @@ void nladata_flush_channels(PointerRNA *ptr,
|
|||
|
||||
/* for each channel with accumulated values, write its value on the property it affects */
|
||||
LISTBASE_FOREACH (NlaEvalChannel *, nec, &channels->channels) {
|
||||
/**
|
||||
* The bitmask is set for all channels touched by NLA due to the domain() function.
|
||||
* Channels touched by current set of evaluated strips will have a snapshot channel directly
|
||||
* from the evaluation snapshot.
|
||||
*
|
||||
* This function falls back to the default value if the snapshot channel doesn't exist.
|
||||
* Thus channels, touched by NLA but not by the current set of evaluated strips, will be
|
||||
* reset to default. If channel not touched by NLA then it's value is unchanged.
|
||||
*/
|
||||
NlaEvalChannelSnapshot *nec_snapshot = nlaeval_snapshot_find_channel(snapshot, nec);
|
||||
|
||||
PathResolvedRNA rna = {nec->key.ptr, nec->key.prop, -1};
|
||||
|
||||
for (int i = 0; i < nec_snapshot->length; i++) {
|
||||
if (BLI_BITMAP_TEST(nec->valid.ptr, i)) {
|
||||
if (BLI_BITMAP_TEST(nec->domain.ptr, i)) {
|
||||
float value = nec_snapshot->values[i];
|
||||
if (nec->is_array) {
|
||||
rna.prop_index = i;
|
||||
|
@ -2131,13 +2144,7 @@ static void nla_eval_domain_action(PointerRNA *ptr,
|
|||
|
||||
LISTBASE_FOREACH (FCurve *, fcu, &act->curves) {
|
||||
/* check if this curve should be skipped */
|
||||
if (fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) {
|
||||
continue;
|
||||
}
|
||||
if ((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) {
|
||||
continue;
|
||||
}
|
||||
if (BKE_fcurve_is_empty(fcu)) {
|
||||
if (!is_fcurve_evaluatable(fcu)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2146,14 +2153,14 @@ static void nla_eval_domain_action(PointerRNA *ptr,
|
|||
if (nec != NULL) {
|
||||
/* For quaternion properties, enable all sub-channels. */
|
||||
if (nec->mix_mode == NEC_MIX_QUATERNION) {
|
||||
BLI_bitmap_set_all(nec->valid.ptr, true, 4);
|
||||
BLI_bitmap_set_all(nec->domain.ptr, true, 4);
|
||||
continue;
|
||||
}
|
||||
|
||||
int idx = nlaevalchan_validate_index(nec, fcu->array_index);
|
||||
|
||||
if (idx >= 0) {
|
||||
BLI_BITMAP_ENABLE(nec->valid.ptr, idx);
|
||||
BLI_BITMAP_ENABLE(nec->domain.ptr, idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2212,177 +2219,226 @@ static void animsys_evaluate_nla_domain(PointerRNA *ptr, NlaEvalData *channels,
|
|||
|
||||
/* ---------------------- */
|
||||
|
||||
/** Tweaked strip is evaluated differently from other strips. Adjacent strips are ignored
|
||||
* and includes a workaround for when user is not editing in place. */
|
||||
static void animsys_create_tweak_strip(const AnimData *adt,
|
||||
const bool keyframing_to_strip,
|
||||
NlaStrip *r_tweak_strip)
|
||||
|
||||
{
|
||||
/* Copy active strip so we can modify how it evaluates without affecting user data. */
|
||||
memcpy(r_tweak_strip, adt->actstrip, sizeof(NlaStrip));
|
||||
r_tweak_strip->next = r_tweak_strip->prev = NULL;
|
||||
|
||||
/* If tweaked strip is syncing action length, then evaluate using action length. */
|
||||
if (r_tweak_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH) {
|
||||
BKE_nlastrip_recalculate_bounds_sync_action(r_tweak_strip);
|
||||
}
|
||||
|
||||
/* Strips with a user-defined time curve don't get properly remapped for editing
|
||||
* at the moment, so mapping them just for display may be confusing. */
|
||||
const bool is_inplace_tweak = !(adt->flag & ADT_NLA_EDIT_NOMAP) &&
|
||||
!(adt->actstrip->flag & NLASTRIP_FLAG_USR_TIME);
|
||||
|
||||
if (!is_inplace_tweak) {
|
||||
/* Use Hold due to no proper remapping yet (the note above). */
|
||||
r_tweak_strip->extendmode = NLASTRIP_EXTEND_HOLD;
|
||||
|
||||
/* Disable range. */
|
||||
r_tweak_strip->flag |= NLASTRIP_FLAG_NO_TIME_MAP;
|
||||
}
|
||||
|
||||
/** Controls whether able to keyframe outside range of tweaked strip. */
|
||||
if (keyframing_to_strip) {
|
||||
r_tweak_strip->extendmode = (is_inplace_tweak &&
|
||||
!(r_tweak_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH)) ?
|
||||
NLASTRIP_EXTEND_NOTHING :
|
||||
NLASTRIP_EXTEND_HOLD;
|
||||
}
|
||||
}
|
||||
|
||||
/** Action track and strip are associated with the non-pushed action. */
|
||||
static void animsys_create_action_track_strip(const AnimData *adt,
|
||||
const bool keyframing_to_strip,
|
||||
NlaStrip *r_action_strip)
|
||||
{
|
||||
memset(r_action_strip, 0, sizeof(NlaStrip));
|
||||
|
||||
bAction *action = adt->action;
|
||||
|
||||
if ((adt->flag & ADT_NLA_EDIT_ON)) {
|
||||
action = adt->tmpact;
|
||||
}
|
||||
|
||||
/* Set settings of dummy NLA strip from AnimData settings. */
|
||||
r_action_strip->act = action;
|
||||
|
||||
/* Action range is calculated taking F-Modifiers into account
|
||||
* (which making new strips doesn't do due to the troublesome nature of that). */
|
||||
calc_action_range(r_action_strip->act, &r_action_strip->actstart, &r_action_strip->actend, 1);
|
||||
r_action_strip->start = r_action_strip->actstart;
|
||||
r_action_strip->end = (IS_EQF(r_action_strip->actstart, r_action_strip->actend)) ?
|
||||
(r_action_strip->actstart + 1.0f) :
|
||||
(r_action_strip->actend);
|
||||
|
||||
r_action_strip->blendmode = adt->act_blendmode;
|
||||
r_action_strip->extendmode = adt->act_extendmode;
|
||||
r_action_strip->influence = adt->act_influence;
|
||||
|
||||
/* NOTE: must set this, or else the default setting overrides,
|
||||
* and this setting doesn't work. */
|
||||
r_action_strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
|
||||
|
||||
/* Unless extendmode is Nothing (might be useful for flattening NLA evaluation), disable range.
|
||||
* Extendmode Nothing and Hold will behave as normal. Hold Forward will behave just like Hold.
|
||||
*/
|
||||
if (r_action_strip->extendmode != NLASTRIP_EXTEND_NOTHING) {
|
||||
r_action_strip->flag |= NLASTRIP_FLAG_NO_TIME_MAP;
|
||||
}
|
||||
|
||||
const bool tweaking = (adt->flag & ADT_NLA_EDIT_ON) != 0;
|
||||
const bool soloing = (adt->flag & ADT_NLA_SOLO_TRACK) != 0;
|
||||
const bool actionstrip_evaluated = r_action_strip->act && !soloing && !tweaking;
|
||||
if (!actionstrip_evaluated) {
|
||||
r_action_strip->flag |= NLASTRIP_FLAG_MUTED;
|
||||
}
|
||||
|
||||
/** If we're keyframing, then we must allow keyframing outside fcurve bounds. */
|
||||
if (keyframing_to_strip) {
|
||||
r_action_strip->extendmode = NLASTRIP_EXTEND_HOLD;
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_nlatrack_evaluatable(const AnimData *adt, const NlaTrack *nlt)
|
||||
{
|
||||
/* Skip disabled tracks unless it contains the tweaked strip. */
|
||||
const bool contains_tweak_strip = (adt->flag & ADT_NLA_EDIT_ON) &&
|
||||
(nlt->index == adt->act_track->index);
|
||||
if ((nlt->flag & NLATRACK_DISABLED) && !contains_tweak_strip) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Solo and muting are mutually exclusive. */
|
||||
if (adt->flag & ADT_NLA_SOLO_TRACK) {
|
||||
/* Skip if there is a solo track, but this isn't it. */
|
||||
if ((nlt->flag & NLATRACK_SOLO) == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Skip track if muted. */
|
||||
if (nlt->flag & NLATRACK_MUTED) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Check for special case of non-pushed action being evaluated with no NLA influence (off and no
|
||||
* strips evaluated) nor NLA interference (ensure NLA not soloing). */
|
||||
static bool is_action_track_evaluated_without_nla(const AnimData *adt,
|
||||
const bool any_strip_evaluated)
|
||||
{
|
||||
if (adt->action == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (any_strip_evaluated) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** NLA settings interference. */
|
||||
if ((adt->flag & (ADT_NLA_SOLO_TRACK | ADT_NLA_EDIT_ON)) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Allow action track to evaluate as if there isn't any NLA data. */
|
||||
return true;
|
||||
}
|
||||
|
||||
/** XXX Wayde Moss: BKE_nlatrack_find_tweaked() exists within nla.c, but it doesn't appear to
|
||||
* work as expected. From animsys_evaluate_nla_for_flush(), it returns NULL in tweak mode. I'm not
|
||||
* sure why. Preferably, it would be as simple as checking for (adt->act_Track == nlt) but that
|
||||
* doesn't work either, neither does comparing indices.
|
||||
*
|
||||
* This function is a temporary work around. The first disabled track is always the tweaked track.
|
||||
*/
|
||||
static NlaTrack *nlatrack_find_tweaked(const AnimData *adt)
|
||||
{
|
||||
NlaTrack *nlt;
|
||||
|
||||
if (adt == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Since the track itself gets disabled, we want the first disabled. */
|
||||
for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
|
||||
if (nlt->flag & NLATRACK_DISABLED) {
|
||||
return nlt;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* NLA Evaluation function - values are calculated and stored in temporary "NlaEvalChannels"
|
||||
*
|
||||
* \param[out] echannels: Evaluation channels with calculated values
|
||||
* \param[out] r_context: If not NULL,
|
||||
* data about the currently edited strip is stored here and excluded from value calculation.
|
||||
* \return false if NLA evaluation isn't actually applicable.
|
||||
*/
|
||||
static bool animsys_evaluate_nla(NlaEvalData *echannels,
|
||||
PointerRNA *ptr,
|
||||
AnimData *adt,
|
||||
const AnimationEvalContext *anim_eval_context,
|
||||
const bool flush_to_original,
|
||||
NlaKeyframingContext *r_context)
|
||||
static bool animsys_evaluate_nla_for_flush(NlaEvalData *echannels,
|
||||
PointerRNA *ptr,
|
||||
const AnimData *adt,
|
||||
const AnimationEvalContext *anim_eval_context,
|
||||
const bool flush_to_original)
|
||||
{
|
||||
NlaTrack *nlt;
|
||||
short track_index = 0;
|
||||
bool has_strips = false;
|
||||
|
||||
ListBase estrips = {NULL, NULL};
|
||||
NlaEvalStrip *nes;
|
||||
NlaStrip dummy_strip_buf;
|
||||
|
||||
/* dummy strip for active action */
|
||||
NlaStrip *dummy_strip = r_context ? &r_context->strip : &dummy_strip_buf;
|
||||
NlaStrip tweak_strip;
|
||||
|
||||
memset(dummy_strip, 0, sizeof(*dummy_strip));
|
||||
NlaTrack *tweaked_track = nlatrack_find_tweaked(adt);
|
||||
|
||||
/* 1. get the stack of strips to evaluate at current time (influence calculated here) */
|
||||
/* Get the stack of strips to evaluate at current time (influence calculated here). */
|
||||
for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next, track_index++) {
|
||||
/* stop here if tweaking is on and this strip is the tweaking track
|
||||
* (it will be the first one that's 'disabled')... */
|
||||
if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED)) {
|
||||
break;
|
||||
|
||||
if (!is_nlatrack_evaluatable(adt, nlt)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* solo and muting are mutually exclusive... */
|
||||
if (adt->flag & ADT_NLA_SOLO_TRACK) {
|
||||
/* skip if there is a solo track, but this isn't it */
|
||||
if ((nlt->flag & NLATRACK_SOLO) == 0) {
|
||||
continue;
|
||||
}
|
||||
/* else - mute doesn't matter */
|
||||
}
|
||||
else {
|
||||
/* no solo tracks - skip track if muted */
|
||||
if (nlt->flag & NLATRACK_MUTED) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* if this track has strips (but maybe they won't be suitable), set has_strips
|
||||
* - used for mainly for still allowing normal action evaluation...
|
||||
*/
|
||||
if (nlt->strips.first) {
|
||||
has_strips = true;
|
||||
}
|
||||
|
||||
/* otherwise, get strip to evaluate for this channel */
|
||||
nes = nlastrips_ctime_get_strip(
|
||||
&estrips, &nlt->strips, track_index, anim_eval_context, flush_to_original);
|
||||
/** Append strip to evaluate for this track. */
|
||||
if (nlt == tweaked_track) {
|
||||
/** Tweaked strip is evaluated differently. */
|
||||
animsys_create_tweak_strip(adt, false, &tweak_strip);
|
||||
nes = nlastrips_ctime_get_strip_single(
|
||||
&estrips, &tweak_strip, anim_eval_context, flush_to_original);
|
||||
}
|
||||
else {
|
||||
nes = nlastrips_ctime_get_strip(
|
||||
&estrips, &nlt->strips, track_index, anim_eval_context, flush_to_original);
|
||||
}
|
||||
if (nes) {
|
||||
nes->track = nlt;
|
||||
}
|
||||
}
|
||||
|
||||
/* add 'active' Action (may be tweaking track) as last strip to evaluate in NLA stack
|
||||
* - only do this if we're not exclusively evaluating the 'solo' NLA-track
|
||||
* - however, if the 'solo' track houses the current 'tweaking' strip,
|
||||
* then we should allow this to play, otherwise nothing happens
|
||||
*/
|
||||
if ((adt->action) && ((adt->flag & ADT_NLA_SOLO_TRACK) == 0 || (adt->flag & ADT_NLA_EDIT_ON))) {
|
||||
/* if there are strips, evaluate action as per NLA rules */
|
||||
if ((has_strips) || (adt->actstrip)) {
|
||||
/* make dummy NLA strip, and add that to the stack */
|
||||
ListBase dummy_trackslist;
|
||||
|
||||
dummy_trackslist.first = dummy_trackslist.last = dummy_strip;
|
||||
|
||||
/* Strips with a user-defined time curve don't get properly remapped for editing
|
||||
* at the moment, so mapping them just for display may be confusing. */
|
||||
bool is_inplace_tweak = (nlt) && !(adt->flag & ADT_NLA_EDIT_NOMAP) &&
|
||||
!(adt->actstrip->flag & NLASTRIP_FLAG_USR_TIME);
|
||||
|
||||
if (is_inplace_tweak) {
|
||||
/* edit active action in-place according to its active strip, so copy the data */
|
||||
memcpy(dummy_strip, adt->actstrip, sizeof(NlaStrip));
|
||||
/* Prevents nla eval from considering active strip's adj strips.
|
||||
* For user, this means entering tweak mode on a strip ignores evaluating adjacent strips
|
||||
* in the same track. */
|
||||
dummy_strip->next = dummy_strip->prev = NULL;
|
||||
|
||||
/* If tweaked strip is syncing action length, then evaluate using action length. */
|
||||
if (dummy_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH) {
|
||||
BKE_nlastrip_recalculate_bounds_sync_action(dummy_strip);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* set settings of dummy NLA strip from AnimData settings */
|
||||
dummy_strip->act = adt->action;
|
||||
|
||||
/* action range is calculated taking F-Modifiers into account
|
||||
* (which making new strips doesn't do due to the troublesome nature of that) */
|
||||
calc_action_range(dummy_strip->act, &dummy_strip->actstart, &dummy_strip->actend, 1);
|
||||
dummy_strip->start = dummy_strip->actstart;
|
||||
dummy_strip->end = (IS_EQF(dummy_strip->actstart, dummy_strip->actend)) ?
|
||||
(dummy_strip->actstart + 1.0f) :
|
||||
(dummy_strip->actend);
|
||||
|
||||
/* Always use the blend mode of the strip in tweak mode, even if not in-place. */
|
||||
if (nlt && adt->actstrip) {
|
||||
dummy_strip->blendmode = adt->actstrip->blendmode;
|
||||
dummy_strip->extendmode = NLASTRIP_EXTEND_HOLD;
|
||||
}
|
||||
else {
|
||||
dummy_strip->blendmode = adt->act_blendmode;
|
||||
dummy_strip->extendmode = adt->act_extendmode;
|
||||
}
|
||||
|
||||
/* Unless extend-mode is Nothing (might be useful for flattening NLA evaluation),
|
||||
* disable range. */
|
||||
if (dummy_strip->extendmode != NLASTRIP_EXTEND_NOTHING) {
|
||||
dummy_strip->flag |= NLASTRIP_FLAG_NO_TIME_MAP;
|
||||
}
|
||||
|
||||
dummy_strip->influence = adt->act_influence;
|
||||
|
||||
/* NOTE: must set this, or else the default setting overrides,
|
||||
* and this setting doesn't work. */
|
||||
dummy_strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
|
||||
}
|
||||
|
||||
/* add this to our list of evaluation strips */
|
||||
if (r_context == NULL) {
|
||||
nlastrips_ctime_get_strip(
|
||||
&estrips, &dummy_trackslist, -1, anim_eval_context, flush_to_original);
|
||||
}
|
||||
/* If computing the context for keyframing, store data there instead of the list. */
|
||||
else {
|
||||
/* The extend mode here effectively controls
|
||||
* whether it is possible to key-frame beyond the ends.*/
|
||||
dummy_strip->extendmode = (is_inplace_tweak &&
|
||||
!(dummy_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH)) ?
|
||||
NLASTRIP_EXTEND_NOTHING :
|
||||
NLASTRIP_EXTEND_HOLD;
|
||||
|
||||
r_context->eval_strip = nes = nlastrips_ctime_get_strip(
|
||||
NULL, &dummy_trackslist, -1, anim_eval_context, flush_to_original);
|
||||
|
||||
/* These setting combinations require no data from strips below, so exit immediately. */
|
||||
if ((nes == NULL) ||
|
||||
(dummy_strip->blendmode == NLASTRIP_MODE_REPLACE && dummy_strip->influence == 1.0f)) {
|
||||
BLI_freelistN(&estrips);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* special case - evaluate as if there isn't any NLA data */
|
||||
BLI_freelistN(&estrips);
|
||||
return false;
|
||||
}
|
||||
if (is_action_track_evaluated_without_nla(adt, has_strips)) {
|
||||
BLI_freelistN(&estrips);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* only continue if there are strips to evaluate */
|
||||
if (BLI_listbase_is_empty(&estrips)) {
|
||||
return true;
|
||||
}
|
||||
NlaStrip action_strip = {0};
|
||||
animsys_create_action_track_strip(adt, false, &action_strip);
|
||||
nlastrips_ctime_get_strip_single(&estrips, &action_strip, anim_eval_context, flush_to_original);
|
||||
|
||||
/* 2. for each strip, evaluate then accumulate on top of existing channels,
|
||||
* but don't set values yet. */
|
||||
/* Per strip, evaluate and accumulate on top of existing channels. */
|
||||
for (nes = estrips.first; nes; nes = nes->next) {
|
||||
nlastrip_evaluate(ptr,
|
||||
echannels,
|
||||
|
@ -2393,11 +2449,116 @@ static bool animsys_evaluate_nla(NlaEvalData *echannels,
|
|||
flush_to_original);
|
||||
}
|
||||
|
||||
/* 3. free temporary evaluation data that's not used elsewhere */
|
||||
/* Free temporary evaluation data that's not used elsewhere. */
|
||||
BLI_freelistN(&estrips);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Lower blended values are calculated and accumulated into r_context->lower_eval_data. */
|
||||
static void animsys_evaluate_nla_for_keyframing(PointerRNA *ptr,
|
||||
const AnimData *adt,
|
||||
const AnimationEvalContext *anim_eval_context,
|
||||
NlaKeyframingContext *r_context)
|
||||
{
|
||||
if (!r_context) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Early out. If NLA track is soloing and tweaked action isn't it, then don't allow keyframe
|
||||
* insertion. */
|
||||
if (adt->flag & ADT_NLA_SOLO_TRACK) {
|
||||
if (!(adt->act_track && (adt->act_track->flag & NLATRACK_SOLO))) {
|
||||
r_context->eval_strip = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NlaTrack *nlt;
|
||||
short track_index = 0;
|
||||
bool has_strips = false;
|
||||
|
||||
ListBase lower_estrips = {NULL, NULL};
|
||||
NlaEvalStrip *nes;
|
||||
|
||||
NlaTrack *tweaked_track = nlatrack_find_tweaked(adt);
|
||||
|
||||
/* Get the lower stack of strips to evaluate at current time (influence calculated here). */
|
||||
for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next, track_index++) {
|
||||
|
||||
if (!is_nlatrack_evaluatable(adt, nlt)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Tweaked strip effect should not be stored in any snapshot. */
|
||||
if (nlt == tweaked_track) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (nlt->strips.first) {
|
||||
has_strips = true;
|
||||
}
|
||||
|
||||
/* Get strip to evaluate for this channel. */
|
||||
nes = nlastrips_ctime_get_strip(
|
||||
&lower_estrips, &nlt->strips, track_index, anim_eval_context, false);
|
||||
if (nes) {
|
||||
nes->track = nlt;
|
||||
}
|
||||
}
|
||||
|
||||
/** Note: Although we early out, we can still keyframe to the non-pushed action since the
|
||||
* keyframe remap function detects (r_context->strip.act == NULL) and will keyframe without
|
||||
* remapping.
|
||||
*/
|
||||
if (is_action_track_evaluated_without_nla(adt, has_strips)) {
|
||||
BLI_freelistN(&lower_estrips);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Write r_context->eval_strip. */
|
||||
if (adt->flag & ADT_NLA_EDIT_ON) {
|
||||
|
||||
NlaStrip *tweak_strip = &r_context->strip;
|
||||
animsys_create_tweak_strip(adt, true, tweak_strip);
|
||||
r_context->eval_strip = nlastrips_ctime_get_strip_single(
|
||||
NULL, tweak_strip, anim_eval_context, false);
|
||||
}
|
||||
else {
|
||||
|
||||
NlaStrip *action_strip = &r_context->strip;
|
||||
animsys_create_action_track_strip(adt, true, action_strip);
|
||||
r_context->eval_strip = nlastrips_ctime_get_strip_single(
|
||||
NULL, action_strip, anim_eval_context, false);
|
||||
}
|
||||
|
||||
/* If NULL, then keyframing will fail. No need to do any more processing. */
|
||||
if (!r_context->eval_strip) {
|
||||
BLI_freelistN(&lower_estrips);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If tweak strip is full REPLACE, then lower strips not needed. */
|
||||
if (r_context->strip.blendmode == NLASTRIP_MODE_REPLACE &&
|
||||
IS_EQF(r_context->strip.influence, 1.0f)) {
|
||||
BLI_freelistN(&lower_estrips);
|
||||
return;
|
||||
}
|
||||
|
||||
/* For each strip, evaluate then accumulate on top of existing channels. */
|
||||
for (nes = lower_estrips.first; nes; nes = nes->next) {
|
||||
nlastrip_evaluate(ptr,
|
||||
&r_context->lower_eval_data,
|
||||
NULL,
|
||||
nes,
|
||||
&r_context->lower_eval_data.eval_snapshot,
|
||||
anim_eval_context,
|
||||
false);
|
||||
}
|
||||
|
||||
/* Free temporary evaluation data that's not used elsewhere. */
|
||||
BLI_freelistN(&lower_estrips);
|
||||
}
|
||||
|
||||
/* NLA Evaluation function (mostly for use through do_animdata)
|
||||
* - All channels that will be affected are not cleared anymore. Instead, we just evaluate into
|
||||
* some temp channels, where values can be accumulated in one go.
|
||||
|
@ -2412,7 +2573,7 @@ static void animsys_calculate_nla(PointerRNA *ptr,
|
|||
nlaeval_init(&echannels);
|
||||
|
||||
/* evaluate the NLA stack, obtaining a set of values to flush */
|
||||
if (animsys_evaluate_nla(&echannels, ptr, adt, anim_eval_context, flush_to_original, NULL)) {
|
||||
if (animsys_evaluate_nla_for_flush(&echannels, ptr, adt, anim_eval_context, flush_to_original)) {
|
||||
/* reset any channels touched by currently inactive actions to default value */
|
||||
animsys_evaluate_nla_domain(ptr, &echannels, adt);
|
||||
|
||||
|
@ -2448,8 +2609,7 @@ NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(
|
|||
struct ListBase *cache,
|
||||
struct PointerRNA *ptr,
|
||||
struct AnimData *adt,
|
||||
const AnimationEvalContext *anim_eval_context,
|
||||
const bool flush_to_original)
|
||||
const AnimationEvalContext *anim_eval_context)
|
||||
{
|
||||
/* No remapping needed if NLA is off or no action. */
|
||||
if ((adt == NULL) || (adt->action == NULL) || (adt->nla_tracks.first == NULL) ||
|
||||
|
@ -2472,8 +2632,7 @@ NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(
|
|||
ctx->adt = adt;
|
||||
|
||||
nlaeval_init(&ctx->lower_eval_data);
|
||||
animsys_evaluate_nla(
|
||||
&ctx->lower_eval_data, ptr, adt, anim_eval_context, flush_to_original, ctx);
|
||||
animsys_evaluate_nla_for_keyframing(ptr, adt, anim_eval_context, ctx);
|
||||
|
||||
BLI_assert(ELEM(ctx->strip.act, NULL, adt->action));
|
||||
BLI_addtail(cache, ctx);
|
||||
|
|
|
@ -526,6 +526,10 @@ static ReadAttributePtr read_attribute_from_custom_data(const CustomData &custom
|
|||
case CD_PROP_BOOL:
|
||||
return std::make_unique<ArrayReadAttribute<bool>>(
|
||||
domain, Span(static_cast<bool *>(layer.data), size));
|
||||
case CD_MLOOPUV:
|
||||
auto get_uv = [](const MLoopUV &uv) { return float2(uv.uv); };
|
||||
return std::make_unique<DerivedArrayReadAttribute<MLoopUV, float2, decltype(get_uv)>>(
|
||||
domain, Span(static_cast<MLoopUV *>(layer.data), size), get_uv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -570,6 +574,12 @@ static WriteAttributePtr write_attribute_from_custom_data(
|
|||
case CD_PROP_BOOL:
|
||||
return std::make_unique<ArrayWriteAttribute<bool>>(
|
||||
domain, MutableSpan(static_cast<bool *>(layer.data), size));
|
||||
case CD_MLOOPUV:
|
||||
auto get_uv = [](const MLoopUV &uv) { return float2(uv.uv); };
|
||||
auto set_uv = [](MLoopUV &uv, const float2 value) { copy_v2_v2(uv.uv, value); };
|
||||
return std::make_unique<
|
||||
DerivedArrayWriteAttribute<MLoopUV, float2, decltype(get_uv), decltype(set_uv)>>(
|
||||
domain, MutableSpan(static_cast<MLoopUV *>(layer.data), size), get_uv, set_uv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -597,8 +607,9 @@ static void get_custom_data_layer_attribute_names(const CustomData &custom_data,
|
|||
Set<std::string> &r_names)
|
||||
{
|
||||
for (const CustomDataLayer &layer : blender::Span(custom_data.layers, custom_data.totlayer)) {
|
||||
if (component.attribute_domain_with_type_supported(domain,
|
||||
static_cast<CustomDataType>(layer.type))) {
|
||||
const CustomDataType data_type = static_cast<CustomDataType>(layer.type);
|
||||
if (component.attribute_domain_with_type_supported(domain, data_type) ||
|
||||
ELEM(data_type, CD_MLOOPUV)) {
|
||||
r_names.add(layer.name);
|
||||
}
|
||||
}
|
||||
|
@ -814,7 +825,8 @@ blender::bke::ReadAttributePtr GeometryComponent::attribute_get_constant_for_rea
|
|||
|
||||
OutputAttributePtr GeometryComponent::attribute_try_get_for_output(const StringRef attribute_name,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type)
|
||||
const CustomDataType data_type,
|
||||
const void *default_value)
|
||||
{
|
||||
BLI_assert(this->attribute_domain_with_type_supported(domain, data_type));
|
||||
|
||||
|
@ -827,6 +839,11 @@ OutputAttributePtr GeometryComponent::attribute_try_get_for_output(const StringR
|
|||
if (!attribute) {
|
||||
this->attribute_try_create(attribute_name, domain, data_type);
|
||||
attribute = this->attribute_try_get_for_write(attribute_name);
|
||||
if (default_value != nullptr) {
|
||||
void *data = attribute->get_span_for_write_only().data();
|
||||
cpp_type->fill_initialized(default_value, data, attribute->size());
|
||||
attribute->apply_span();
|
||||
}
|
||||
return OutputAttributePtr(std::move(attribute));
|
||||
}
|
||||
|
||||
|
@ -1307,7 +1324,7 @@ Set<std::string> MeshComponent::attribute_names() const
|
|||
for (StringRef name : vertex_group_names_.keys()) {
|
||||
names.add(name);
|
||||
}
|
||||
get_custom_data_layer_attribute_names(mesh_->pdata, *this, ATTR_DOMAIN_CORNER, names);
|
||||
get_custom_data_layer_attribute_names(mesh_->ldata, *this, ATTR_DOMAIN_CORNER, names);
|
||||
get_custom_data_layer_attribute_names(mesh_->vdata, *this, ATTR_DOMAIN_POINT, names);
|
||||
get_custom_data_layer_attribute_names(mesh_->edata, *this, ATTR_DOMAIN_EDGE, names);
|
||||
get_custom_data_layer_attribute_names(mesh_->pdata, *this, ATTR_DOMAIN_POLYGON, names);
|
||||
|
|
|
@ -1261,10 +1261,17 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int ori
|
|||
|
||||
/* We may need our own flag to control that at some point, but for now 'no main' one should be
|
||||
* good enough. */
|
||||
if ((orig_flag & LIB_ID_CREATE_NO_MAIN) == 0 && ID_IS_OVERRIDE_LIBRARY(id)) {
|
||||
/* We do not want to copy existing override rules here, as they would break the proper
|
||||
* remapping between IDs. Proper overrides rules will be re-generated anyway. */
|
||||
BKE_lib_override_library_copy(new_id, id, false);
|
||||
if ((orig_flag & LIB_ID_CREATE_NO_MAIN) == 0) {
|
||||
if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
|
||||
/* We do not want to copy existing override rules here, as they would break the proper
|
||||
* remapping between IDs. Proper overrides rules will be re-generated anyway. */
|
||||
BKE_lib_override_library_copy(new_id, id, false);
|
||||
}
|
||||
else if (ID_IS_OVERRIDE_LIBRARY_VIRTUAL(id)) {
|
||||
/* Just ensure virtual overrides do get properly tagged, there is not actual override data to
|
||||
* copy here. */
|
||||
new_id->flag |= LIB_EMBEDDED_DATA_LIB_OVERRIDE;
|
||||
}
|
||||
}
|
||||
|
||||
if (id_can_have_animdata(new_id)) {
|
||||
|
|
|
@ -1922,7 +1922,9 @@ ID *BKE_lib_override_library_operations_store_start(Main *bmain,
|
|||
ID *local)
|
||||
{
|
||||
if (ID_IS_OVERRIDE_LIBRARY_TEMPLATE(local) || ID_IS_OVERRIDE_LIBRARY_VIRTUAL(local)) {
|
||||
/* This is actually purely local data with an override template, nothing to do here! */
|
||||
/* This is actually purely local data with an override template, or one of those embedded IDs
|
||||
* (root node trees, master collections or shapekeys) that cannot have their own override.
|
||||
* Nothing to do here! */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -2149,7 +2149,7 @@ void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
|
|||
ntree->update |= NTREE_UPDATE_LINKS;
|
||||
}
|
||||
|
||||
bool nodeLinkIsHidden(bNodeLink *link)
|
||||
bool nodeLinkIsHidden(const bNodeLink *link)
|
||||
{
|
||||
return nodeSocketIsHidden(link->fromsock) || nodeSocketIsHidden(link->tosock);
|
||||
}
|
||||
|
@ -2200,7 +2200,7 @@ void nodeInternalRelink(bNodeTree *ntree, bNode *node)
|
|||
}
|
||||
}
|
||||
|
||||
void nodeToView(bNode *node, float x, float y, float *rx, float *ry)
|
||||
void nodeToView(const bNode *node, float x, float y, float *rx, float *ry)
|
||||
{
|
||||
if (node->parent) {
|
||||
nodeToView(node->parent, x + node->locx, y + node->locy, rx, ry);
|
||||
|
@ -2211,7 +2211,7 @@ void nodeToView(bNode *node, float x, float y, float *rx, float *ry)
|
|||
}
|
||||
}
|
||||
|
||||
void nodeFromView(bNode *node, float x, float y, float *rx, float *ry)
|
||||
void nodeFromView(const bNode *node, float x, float y, float *rx, float *ry)
|
||||
{
|
||||
if (node->parent) {
|
||||
nodeFromView(node->parent, x, y, rx, ry);
|
||||
|
@ -2224,10 +2224,10 @@ void nodeFromView(bNode *node, float x, float y, float *rx, float *ry)
|
|||
}
|
||||
}
|
||||
|
||||
bool nodeAttachNodeCheck(bNode *node, bNode *parent)
|
||||
bool nodeAttachNodeCheck(const bNode *node, const bNode *parent)
|
||||
{
|
||||
for (bNode *parent_recurse = node; parent_recurse; parent_recurse = parent_recurse->parent) {
|
||||
if (parent_recurse == parent) {
|
||||
for (const bNode *parent_iter = node; parent_iter; parent_iter = parent_iter->parent) {
|
||||
if (parent_iter == parent) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -2317,8 +2317,6 @@ void nodePositionPropagate(bNode *node)
|
|||
|
||||
bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname)
|
||||
{
|
||||
bNodeTree *ntree;
|
||||
|
||||
/* trees are created as local trees for compositor, material or texture nodes,
|
||||
* node groups and other tree types are created as library data.
|
||||
*/
|
||||
|
@ -2327,7 +2325,7 @@ bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname)
|
|||
if (is_embedded) {
|
||||
flag |= LIB_ID_CREATE_NO_MAIN;
|
||||
}
|
||||
ntree = BKE_libblock_alloc(bmain, ID_NT, name, flag);
|
||||
bNodeTree *ntree = BKE_libblock_alloc(bmain, ID_NT, name, flag);
|
||||
if (is_embedded) {
|
||||
ntree->id.flag |= LIB_EMBEDDED_DATA;
|
||||
}
|
||||
|
@ -2362,7 +2360,7 @@ bNodeTree *ntreeCopyTree(Main *bmain, const bNodeTree *ntree)
|
|||
* using BKE_node_preview_init_tree to set up previews for a whole node tree in advance.
|
||||
* This should be left more to the individual node tree implementations.
|
||||
*/
|
||||
int BKE_node_preview_used(bNode *node)
|
||||
bool BKE_node_preview_used(const bNode *node)
|
||||
{
|
||||
/* XXX check for closed nodes? */
|
||||
return (node->typeinfo->flag & NODE_PREVIEW) != 0;
|
||||
|
@ -2959,9 +2957,9 @@ ID *BKE_node_tree_find_owner_ID(Main *bmain, struct bNodeTree *ntree)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool ntreeNodeExists(bNodeTree *ntree, bNode *testnode)
|
||||
bool ntreeNodeExists(const bNodeTree *ntree, const bNode *testnode)
|
||||
{
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
LISTBASE_FOREACH (const bNode *, node, &ntree->nodes) {
|
||||
if (node == testnode) {
|
||||
return true;
|
||||
}
|
||||
|
@ -2969,9 +2967,9 @@ bool ntreeNodeExists(bNodeTree *ntree, bNode *testnode)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ntreeOutputExists(bNode *node, bNodeSocket *testsock)
|
||||
bool ntreeOutputExists(const bNode *node, const bNodeSocket *testsock)
|
||||
{
|
||||
LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
|
||||
LISTBASE_FOREACH (const bNodeSocket *, sock, &node->outputs) {
|
||||
if (sock == testsock) {
|
||||
return true;
|
||||
}
|
||||
|
@ -3246,7 +3244,7 @@ static void ntree_interface_type_create(bNodeTree *ntree)
|
|||
}
|
||||
}
|
||||
|
||||
StructRNA *ntreeInterfaceTypeGet(bNodeTree *ntree, int create)
|
||||
StructRNA *ntreeInterfaceTypeGet(bNodeTree *ntree, bool create)
|
||||
{
|
||||
if (ntree->interface_type) {
|
||||
/* strings are generated from base string + ID name, sizes are sufficient */
|
||||
|
@ -3333,7 +3331,7 @@ bool ntreeHasTree(const bNodeTree *ntree, const bNodeTree *lookup)
|
|||
return false;
|
||||
}
|
||||
|
||||
bNodeLink *nodeFindLink(bNodeTree *ntree, bNodeSocket *from, bNodeSocket *to)
|
||||
bNodeLink *nodeFindLink(bNodeTree *ntree, const bNodeSocket *from, const bNodeSocket *to)
|
||||
{
|
||||
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
|
||||
if (link->fromsock == from && link->tosock == to) {
|
||||
|
@ -3346,10 +3344,10 @@ bNodeLink *nodeFindLink(bNodeTree *ntree, bNodeSocket *from, bNodeSocket *to)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int nodeCountSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
|
||||
int nodeCountSocketLinks(const bNodeTree *ntree, const bNodeSocket *sock)
|
||||
{
|
||||
int tot = 0;
|
||||
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
|
||||
LISTBASE_FOREACH (const bNodeLink *, link, &ntree->links) {
|
||||
if (link->fromsock == sock || link->tosock == sock) {
|
||||
tot++;
|
||||
}
|
||||
|
@ -3515,7 +3513,7 @@ void nodeSetActive(bNodeTree *ntree, bNode *node)
|
|||
}
|
||||
}
|
||||
|
||||
int nodeSocketIsHidden(bNodeSocket *sock)
|
||||
int nodeSocketIsHidden(const bNodeSocket *sock)
|
||||
{
|
||||
return ((sock->flag & (SOCK_HIDDEN | SOCK_UNAVAIL)) != 0);
|
||||
}
|
||||
|
@ -3530,7 +3528,7 @@ void nodeSetSocketAvailability(bNodeSocket *sock, bool is_available)
|
|||
}
|
||||
}
|
||||
|
||||
int nodeSocketLinkLimit(struct bNodeSocket *sock)
|
||||
int nodeSocketLinkLimit(const bNodeSocket *sock)
|
||||
{
|
||||
bNodeSocketType *stype = sock->typeinfo;
|
||||
if (stype != NULL && stype->use_link_limits_of_type) {
|
||||
|
|
|
@ -112,8 +112,8 @@ typedef struct NlaEvalChannel {
|
|||
struct NlaEvalChannel *next_blend;
|
||||
NlaEvalChannelSnapshot *blend_snapshot;
|
||||
|
||||
/* Mask of array items controlled by NLA. */
|
||||
NlaValidMask valid;
|
||||
/* Associated with the RNA property's value(s), marks which elements are affected by NLA. */
|
||||
NlaValidMask domain;
|
||||
|
||||
/* Base set of values. */
|
||||
NlaEvalChannelSnapshot base_snapshot;
|
||||
|
|
|
@ -29,6 +29,14 @@ struct float2 {
|
|||
{
|
||||
}
|
||||
|
||||
explicit float2(float value) : x(value), y(value)
|
||||
{
|
||||
}
|
||||
|
||||
explicit float2(int value) : x(value), y(value)
|
||||
{
|
||||
}
|
||||
|
||||
float2(float x, float y) : x(x), y(y)
|
||||
{
|
||||
}
|
||||
|
@ -52,6 +60,11 @@ struct float2 {
|
|||
return len_v2(*this);
|
||||
}
|
||||
|
||||
float length_squared() const
|
||||
{
|
||||
return len_squared_v2(*this);
|
||||
}
|
||||
|
||||
float2 &operator+=(const float2 &other)
|
||||
{
|
||||
x += other.x;
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2020 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \file
|
||||
* \ingroup bli
|
||||
*/
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Memory-mapped file IO that implements all the OS-specific details and error handling. */
|
||||
|
||||
struct BLI_mmap_file;
|
||||
|
||||
typedef struct BLI_mmap_file BLI_mmap_file;
|
||||
|
||||
/* Prepares an opened file for memory-mapped IO.
|
||||
* May return NULL if the operation fails.
|
||||
* Note that this seeks to the end of the file to determine its length. */
|
||||
BLI_mmap_file *BLI_mmap_open(int fd) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Reads length bytes from file at the given offset into dest.
|
||||
* Returns whether the operation was successful (may fail when reading beyond the file
|
||||
* end or when IO errors occur). */
|
||||
bool BLI_mmap_read(BLI_mmap_file *file, void *dest, size_t offset, size_t length)
|
||||
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
|
||||
|
||||
void *BLI_mmap_get_pointer(BLI_mmap_file *file) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
void BLI_mmap_free(BLI_mmap_file *file) ATTR_NONNULL(1);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -105,8 +105,10 @@ void BLI_task_pool_work_and_wait(TaskPool *pool);
|
|||
/* cancel all tasks, keep worker threads running */
|
||||
void BLI_task_pool_cancel(TaskPool *pool);
|
||||
|
||||
/* for worker threads, test if canceled */
|
||||
bool BLI_task_pool_canceled(TaskPool *pool);
|
||||
/* for worker threads, test if current task pool canceled. this function may
|
||||
* only be called from worker threads and pool must be the task pool that the
|
||||
* thread is currently executing a task from. */
|
||||
bool BLI_task_pool_current_canceled(TaskPool *pool);
|
||||
|
||||
/* optional userdata pointer to pass along to run function */
|
||||
void *BLI_task_pool_user_data(TaskPool *pool);
|
||||
|
|
|
@ -54,6 +54,7 @@ set(SRC
|
|||
intern/BLI_memblock.c
|
||||
intern/BLI_memiter.c
|
||||
intern/BLI_mempool.c
|
||||
intern/BLI_mmap.c
|
||||
intern/BLI_timer.c
|
||||
intern/DLRB_tree.c
|
||||
intern/array_store.c
|
||||
|
@ -243,6 +244,7 @@ set(SRC
|
|||
BLI_mempool.h
|
||||
BLI_mesh_boolean.hh
|
||||
BLI_mesh_intersect.hh
|
||||
BLI_mmap.h
|
||||
BLI_mpq2.hh
|
||||
BLI_mpq3.hh
|
||||
BLI_multi_value_map.hh
|
||||
|
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2020 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup bli
|
||||
*/
|
||||
|
||||
#include "BLI_mmap.h"
|
||||
#include "BLI_fileops.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifndef WIN32
|
||||
# include <stdlib.h>
|
||||
# include <signal.h>
|
||||
# include <sys/mman.h> // for mmap
|
||||
# include <unistd.h> // for read close
|
||||
#else
|
||||
# include "BLI_winstuff.h"
|
||||
# include <io.h> // for open close read
|
||||
#endif
|
||||
|
||||
struct BLI_mmap_file {
|
||||
/* The address to which the file was mapped. */
|
||||
char *memory;
|
||||
|
||||
/* The length of the file (and therefore the mapped region). */
|
||||
size_t length;
|
||||
|
||||
/* Platform-specific handle for the mapping. */
|
||||
void *handle;
|
||||
|
||||
/* Flag to indicate IO errors. Needs to be volatile since it's being set from
|
||||
* within the signal handler, which is not part of the normal execution flow. */
|
||||
volatile bool io_error;
|
||||
};
|
||||
|
||||
#ifndef WIN32
|
||||
/* When using memory-mapped files, any IO errors will result in a SIGBUS signal.
|
||||
* Therefore, we need to catch that signal and stop reading the file in question.
|
||||
* To do so, we keep a list of all current FileDatas that use memory-mapped files,
|
||||
* and if a SIGBUS is caught, we check if the failed address is inside one of the
|
||||
* mapped regions.
|
||||
* If it is, we set a flag to indicate a failed read and remap the memory in
|
||||
* question to a zero-backed region in order to avoid additional signals.
|
||||
* The code that actually reads the memory area has to check whether the flag was
|
||||
* set after it's done reading.
|
||||
* If the error occurred outside of a memory-mapped region, we call the previous
|
||||
* handler if one was configured and abort the process otherwise.
|
||||
*/
|
||||
|
||||
struct error_handler_data {
|
||||
ListBase open_mmaps;
|
||||
char configured;
|
||||
void (*next_handler)(int, siginfo_t *, void *);
|
||||
} error_handler = {0};
|
||||
|
||||
static void sigbus_handler(int sig, siginfo_t *siginfo, void *ptr)
|
||||
{
|
||||
/* We only handle SIGBUS here for now. */
|
||||
BLI_assert(sig == SIGBUS);
|
||||
|
||||
char *error_addr = (char *)siginfo->si_addr;
|
||||
/* Find the file that this error belongs to. */
|
||||
LISTBASE_FOREACH (LinkData *, link, &error_handler.open_mmaps) {
|
||||
BLI_mmap_file *file = link->data;
|
||||
|
||||
/* Is the address where the error occurred in this file's mapped range? */
|
||||
if (error_addr >= file->memory && error_addr < file->memory + file->length) {
|
||||
file->io_error = true;
|
||||
|
||||
/* Replace the mapped memory with zeroes. */
|
||||
mmap(file->memory, file->length, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fall back to other handler if there was one. */
|
||||
if (error_handler.next_handler) {
|
||||
error_handler.next_handler(sig, siginfo, ptr);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Unhandled SIGBUS caught\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensures that the error handler is set up and ready. */
|
||||
static bool sigbus_handler_setup(void)
|
||||
{
|
||||
if (!error_handler.configured) {
|
||||
struct sigaction newact = {0}, oldact = {0};
|
||||
|
||||
newact.sa_sigaction = sigbus_handler;
|
||||
newact.sa_flags = SA_SIGINFO;
|
||||
|
||||
if (sigaction(SIGBUS, &newact, &oldact)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Remember the previously configured handler to fall back to it if the error
|
||||
* does not belong to any of the mapped files. */
|
||||
error_handler.next_handler = oldact.sa_sigaction;
|
||||
error_handler.configured = 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Adds a file to the list that the error handler checks. */
|
||||
static void sigbus_handler_add(BLI_mmap_file *file)
|
||||
{
|
||||
BLI_addtail(&error_handler.open_mmaps, BLI_genericNodeN(file));
|
||||
}
|
||||
|
||||
/* Removes a file from the list that the error handler checks. */
|
||||
static void sigbus_handler_remove(BLI_mmap_file *file)
|
||||
{
|
||||
LinkData *link = BLI_findptr(&error_handler.open_mmaps, file, offsetof(LinkData, data));
|
||||
BLI_freelinkN(&error_handler.open_mmaps, link);
|
||||
}
|
||||
#endif
|
||||
|
||||
BLI_mmap_file *BLI_mmap_open(int fd)
|
||||
{
|
||||
void *memory, *handle = NULL;
|
||||
size_t length = BLI_lseek(fd, 0, SEEK_END);
|
||||
|
||||
#ifndef WIN32
|
||||
/* Ensure that the SIGBUS handler is configured. */
|
||||
if (!sigbus_handler_setup()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Map the given file to memory. */
|
||||
memory = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if (memory == MAP_FAILED) {
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
/* Convert the POSIX-style file descriptor to a Windows handle. */
|
||||
void *file_handle = (void *)_get_osfhandle(fd);
|
||||
/* Memory mapping on Windows is a two-step process - first we create a mapping,
|
||||
* then we create a view into that mapping.
|
||||
* In our case, one view that spans the entire file is enough. */
|
||||
handle = CreateFileMapping(file_handle, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if (handle == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memory = MapViewOfFile(handle, FILE_MAP_READ, 0, 0, 0);
|
||||
if (memory == NULL) {
|
||||
CloseHandle(handle);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now that the mapping was successful, allocate memory and set up the BLI_mmap_file. */
|
||||
BLI_mmap_file *file = MEM_callocN(sizeof(BLI_mmap_file), __func__);
|
||||
file->memory = memory;
|
||||
file->handle = handle;
|
||||
file->length = length;
|
||||
|
||||
#ifndef WIN32
|
||||
/* Register the file with the error handler. */
|
||||
sigbus_handler_add(file);
|
||||
#endif
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
bool BLI_mmap_read(BLI_mmap_file *file, void *dest, size_t offset, size_t length)
|
||||
{
|
||||
/* If a previous read has already failed or we try to read past the end,
|
||||
* don't even attempt to read any further. */
|
||||
if (file->io_error || (offset + length > file->length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
/* If an error occurs in this call, sigbus_handler will be called and will set
|
||||
* file->io_error to true. */
|
||||
memcpy(dest, file->memory + offset, length);
|
||||
#else
|
||||
/* On Windows, we use exception handling to be notified of errors. */
|
||||
__try {
|
||||
memcpy(dest, file->memory + offset, length);
|
||||
}
|
||||
__except (GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR ? EXCEPTION_EXECUTE_HANDLER :
|
||||
EXCEPTION_CONTINUE_SEARCH) {
|
||||
file->io_error = true;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return !file->io_error;
|
||||
}
|
||||
|
||||
void *BLI_mmap_get_pointer(BLI_mmap_file *file)
|
||||
{
|
||||
return file->memory;
|
||||
}
|
||||
|
||||
void BLI_mmap_free(BLI_mmap_file *file)
|
||||
{
|
||||
#ifndef WIN32
|
||||
munmap((void *)file->memory, file->length);
|
||||
sigbus_handler_remove(file);
|
||||
#else
|
||||
UnmapViewOfFile(file->memory);
|
||||
CloseHandle(file->handle);
|
||||
#endif
|
||||
|
||||
MEM_freeN(file);
|
||||
}
|
|
@ -6295,7 +6295,7 @@ float geodesic_distance_propagate_across_triangle(
|
|||
}
|
||||
}
|
||||
|
||||
/* Fall back to Dijsktra approximaton in trivial case, or if no valid source
|
||||
/* Fall back to Dijsktra approximation in trivial case, or if no valid source
|
||||
* point found that connects to v0 across the triangle. */
|
||||
return min_ff(dist1 + len_v3(v10), dist2 + len_v3v3(v0, v2));
|
||||
}
|
||||
|
|
|
@ -268,7 +268,7 @@ static bool tbb_task_pool_canceled(TaskPool *pool)
|
|||
{
|
||||
#ifdef WITH_TBB
|
||||
if (pool->use_threads) {
|
||||
return pool->tbb_group.is_canceling();
|
||||
return tbb::is_current_task_group_canceling();
|
||||
}
|
||||
#else
|
||||
UNUSED_VARS(pool);
|
||||
|
@ -520,7 +520,7 @@ void BLI_task_pool_cancel(TaskPool *pool)
|
|||
}
|
||||
}
|
||||
|
||||
bool BLI_task_pool_canceled(TaskPool *pool)
|
||||
bool BLI_task_pool_current_canceled(TaskPool *pool)
|
||||
{
|
||||
switch (pool->type) {
|
||||
case TASK_POOL_TBB:
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
#include "BLI_math.h"
|
||||
#include "BLI_memarena.h"
|
||||
#include "BLI_mempool.h"
|
||||
#include "BLI_mmap.h"
|
||||
#include "BLI_threads.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
@ -1179,6 +1180,53 @@ static ssize_t fd_read_from_memory(FileData *filedata,
|
|||
return readsize;
|
||||
}
|
||||
|
||||
/* Memory-mapped file reading.
|
||||
* By using mmap(), we can map a file so that it can be treated like normal memory,
|
||||
* meaning that we can just read from it with memcpy() etc.
|
||||
* This avoids system call overhead and can significantly speed up file loading.
|
||||
*/
|
||||
|
||||
static ssize_t fd_read_from_mmap(FileData *filedata,
|
||||
void *buffer,
|
||||
size_t size,
|
||||
bool *UNUSED(r_is_memchunck_identical))
|
||||
{
|
||||
/* don't read more bytes than there are available in the buffer */
|
||||
size_t readsize = MIN2(size, (size_t)(filedata->buffersize - filedata->file_offset));
|
||||
|
||||
if (!BLI_mmap_read(filedata->mmap_file, buffer, filedata->file_offset, readsize)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
filedata->file_offset += readsize;
|
||||
|
||||
return readsize;
|
||||
}
|
||||
|
||||
static off64_t fd_seek_from_mmap(FileData *filedata, off64_t offset, int whence)
|
||||
{
|
||||
off64_t new_pos;
|
||||
if (whence == SEEK_CUR) {
|
||||
new_pos = filedata->file_offset + offset;
|
||||
}
|
||||
else if (whence == SEEK_SET) {
|
||||
new_pos = offset;
|
||||
}
|
||||
else if (whence == SEEK_END) {
|
||||
new_pos = filedata->buffersize + offset;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (new_pos < 0 || new_pos > filedata->buffersize) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
filedata->file_offset = new_pos;
|
||||
return filedata->file_offset;
|
||||
}
|
||||
|
||||
/* MemFile reading. */
|
||||
|
||||
static ssize_t fd_read_from_memfile(FileData *filedata,
|
||||
|
@ -1306,6 +1354,8 @@ static FileData *blo_filedata_from_file_descriptor(const char *filepath,
|
|||
{
|
||||
FileDataReadFn *read_fn = NULL;
|
||||
FileDataSeekFn *seek_fn = NULL; /* Optional. */
|
||||
size_t buffersize = 0;
|
||||
BLI_mmap_file *mmap_file = NULL;
|
||||
|
||||
gzFile gzfile = (gzFile)Z_NULL;
|
||||
|
||||
|
@ -1322,14 +1372,21 @@ static FileData *blo_filedata_from_file_descriptor(const char *filepath,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
BLI_lseek(file, 0, SEEK_SET);
|
||||
|
||||
/* Regular file. */
|
||||
if (memcmp(header, "BLENDER", sizeof(header)) == 0) {
|
||||
read_fn = fd_read_data_from_file;
|
||||
seek_fn = fd_seek_data_from_file;
|
||||
|
||||
mmap_file = BLI_mmap_open(file);
|
||||
if (mmap_file != NULL) {
|
||||
read_fn = fd_read_from_mmap;
|
||||
seek_fn = fd_seek_from_mmap;
|
||||
buffersize = BLI_lseek(file, 0, SEEK_END);
|
||||
}
|
||||
}
|
||||
|
||||
BLI_lseek(file, 0, SEEK_SET);
|
||||
|
||||
/* Gzip file. */
|
||||
errno = 0;
|
||||
if ((read_fn == NULL) &&
|
||||
|
@ -1363,6 +1420,8 @@ static FileData *blo_filedata_from_file_descriptor(const char *filepath,
|
|||
|
||||
fd->read = read_fn;
|
||||
fd->seek = seek_fn;
|
||||
fd->mmap_file = mmap_file;
|
||||
fd->buffersize = buffersize;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
@ -1531,6 +1590,11 @@ void blo_filedata_free(FileData *fd)
|
|||
fd->buffer = NULL;
|
||||
}
|
||||
|
||||
if (fd->mmap_file) {
|
||||
BLI_mmap_free(fd->mmap_file);
|
||||
fd->mmap_file = NULL;
|
||||
}
|
||||
|
||||
/* Free all BHeadN data blocks */
|
||||
#ifndef NDEBUG
|
||||
BLI_freelistN(&fd->bhead_list);
|
||||
|
|
|
@ -41,6 +41,7 @@ struct Object;
|
|||
struct OldNewMap;
|
||||
struct ReportList;
|
||||
struct UserDef;
|
||||
struct BLI_mmap_file;
|
||||
|
||||
typedef struct IDNameLib_Map IDNameLib_Map;
|
||||
|
||||
|
@ -83,8 +84,9 @@ typedef struct FileData {
|
|||
/** Regular file reading. */
|
||||
int filedes;
|
||||
|
||||
/** Variables needed for reading from memory / stream. */
|
||||
/** Variables needed for reading from memory / stream / memory-mapped files. */
|
||||
const char *buffer;
|
||||
struct BLI_mmap_file *mmap_file;
|
||||
/** Variables needed for reading from memfile (undo). */
|
||||
struct MemFile *memfile;
|
||||
/** Whether we are undoing (< 0) or redoing (> 0), used to choose which 'unchanged' flag to use
|
||||
|
|
|
@ -55,7 +55,7 @@ class BokehImageOperation : public NodeOperation {
|
|||
NodeBokehImage *m_data;
|
||||
|
||||
/**
|
||||
* \brief precalced center of the image
|
||||
* \brief precalculate center of the image
|
||||
*/
|
||||
float m_center[2];
|
||||
|
||||
|
@ -87,7 +87,7 @@ class BokehImageOperation : public NodeOperation {
|
|||
/**
|
||||
* \brief determine the coordinate of a flap corner.
|
||||
*
|
||||
* \param r: result in bokehimage space are stored [x,y]
|
||||
* \param r: result in bokeh-image space are stored [x,y]
|
||||
* \param flapNumber: the flap number to calculate
|
||||
* \param distance: the lens distance is used to simulate lens shifts
|
||||
*/
|
||||
|
|
|
@ -39,7 +39,7 @@ void DotproductOperation::deinitExecution()
|
|||
this->m_input2Operation = nullptr;
|
||||
}
|
||||
|
||||
/** \todo: current implementation is the inverse of a dotproduct. not 'logically' correct
|
||||
/** \todo current implementation is the inverse of a dot-product. not 'logically' correct
|
||||
*/
|
||||
void DotproductOperation::executePixelSampled(float output[4],
|
||||
float x,
|
||||
|
|
|
@ -4710,7 +4710,7 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi
|
|||
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
|
||||
(float)CFRA);
|
||||
NlaKeyframingContext *nla_context = BKE_animsys_get_nla_keyframing_context(
|
||||
&nla_cache, &id_ptr, adt, &anim_eval_context, false);
|
||||
&nla_cache, &id_ptr, adt, &anim_eval_context);
|
||||
|
||||
/* get current frame and apply NLA-mapping to it (if applicable) */
|
||||
cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
|
||||
|
@ -4766,7 +4766,7 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi
|
|||
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
|
||||
(float)CFRA);
|
||||
NlaKeyframingContext *nla_context = BKE_animsys_get_nla_keyframing_context(
|
||||
&nla_cache, &id_ptr, key->adt, &anim_eval_context, false);
|
||||
&nla_cache, &id_ptr, key->adt, &anim_eval_context);
|
||||
|
||||
/* get current frame and apply NLA-mapping to it (if applicable) */
|
||||
const float remapped_frame = BKE_nla_tweakedit_remap(
|
||||
|
|
|
@ -1384,7 +1384,7 @@ static AnimationEvalContext nla_time_remap(const AnimationEvalContext *anim_eval
|
|||
if (adt && adt->action == act) {
|
||||
/* Get NLA context for value remapping. */
|
||||
*r_nla_context = BKE_animsys_get_nla_keyframing_context(
|
||||
nla_cache, id_ptr, adt, anim_eval_context, false);
|
||||
nla_cache, id_ptr, adt, anim_eval_context);
|
||||
|
||||
/* Apply NLA-mapping to frame. */
|
||||
const float remapped_frame = BKE_nla_tweakedit_remap(
|
||||
|
|
|
@ -231,7 +231,7 @@ struct View2D *UI_view2d_fromcontext(const struct bContext *C);
|
|||
struct View2D *UI_view2d_fromcontext_rwin(const struct bContext *C);
|
||||
|
||||
void UI_view2d_scroller_size_get(const struct View2D *v2d, float *r_x, float *r_y);
|
||||
void UI_view2d_scale_get(struct View2D *v2d, float *r_x, float *r_y);
|
||||
void UI_view2d_scale_get(const struct View2D *v2d, float *r_x, float *r_y);
|
||||
float UI_view2d_scale_get_x(const struct View2D *v2d);
|
||||
float UI_view2d_scale_get_y(const struct View2D *v2d);
|
||||
void UI_view2d_scale_get_inverse(const struct View2D *v2d, float *r_x, float *r_y);
|
||||
|
|
|
@ -1895,7 +1895,7 @@ void UI_view2d_scroller_size_get(const View2D *v2d, float *r_x, float *r_y)
|
|||
*
|
||||
* \param r_x, r_y: scale on each axis
|
||||
*/
|
||||
void UI_view2d_scale_get(View2D *v2d, float *r_x, float *r_y)
|
||||
void UI_view2d_scale_get(const View2D *v2d, float *r_x, float *r_y)
|
||||
{
|
||||
if (r_x) {
|
||||
*r_x = UI_view2d_scale_get_x(v2d);
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#include "BKE_duplilist.h"
|
||||
#include "BKE_effect.h"
|
||||
#include "BKE_font.h"
|
||||
#include "BKE_geometry_set.h"
|
||||
#include "BKE_gpencil_curve.h"
|
||||
#include "BKE_gpencil_geom.h"
|
||||
#include "BKE_hair.h"
|
||||
|
@ -2146,6 +2147,13 @@ static bool dupliobject_instancer_cmp(const void *a_, const void *b_)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool object_has_geometry_set_instances(const Object *object_eval)
|
||||
{
|
||||
struct GeometrySet *geometry_set = object_eval->runtime.geometry_set_eval;
|
||||
|
||||
return (geometry_set != NULL) && BKE_geometry_set_has_instances(geometry_set);
|
||||
}
|
||||
|
||||
static void make_object_duplilist_real(bContext *C,
|
||||
Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
|
@ -2157,13 +2165,19 @@ static void make_object_duplilist_real(bContext *C,
|
|||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
GHash *parent_gh = NULL, *instancer_gh = NULL;
|
||||
|
||||
if (!(base->object->transflag & OB_DUPLI)) {
|
||||
Object *object_eval = DEG_get_evaluated_object(depsgraph, base->object);
|
||||
|
||||
if (!(base->object->transflag & OB_DUPLI) && !object_has_geometry_set_instances(object_eval)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object *object_eval = DEG_get_evaluated_object(depsgraph, base->object);
|
||||
ListBase *lb_duplis = object_duplilist(depsgraph, scene, object_eval);
|
||||
|
||||
if (BLI_listbase_is_empty(lb_duplis)) {
|
||||
free_object_duplilist(lb_duplis);
|
||||
return;
|
||||
}
|
||||
|
||||
GHash *dupli_gh = BLI_ghash_ptr_new(__func__);
|
||||
if (use_hierarchy) {
|
||||
parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
|
||||
|
|
|
@ -35,9 +35,11 @@
|
|||
#include "DNA_userdef_types.h"
|
||||
#include "DNA_windowmanager_types.h"
|
||||
|
||||
#include "BKE_anim_data.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_curve.h"
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_nla.h"
|
||||
|
||||
#include "GPU_immediate.h"
|
||||
#include "GPU_matrix.h"
|
||||
|
@ -77,7 +79,12 @@ static float fcurve_display_alpha(FCurve *fcu)
|
|||
/* Envelope -------------- */
|
||||
|
||||
/* TODO: draw a shaded poly showing the region of influence too!!! */
|
||||
static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d)
|
||||
/**
|
||||
* \param adt_nla_remap: Send NULL if no NLA remapping necessary.
|
||||
*/
|
||||
static void draw_fcurve_modifier_controls_envelope(FModifier *fcm,
|
||||
View2D *v2d,
|
||||
AnimData *adt_nla_remap)
|
||||
{
|
||||
FMod_Envelope *env = (FMod_Envelope *)fcm->data;
|
||||
FCM_EnvelopeData *fed;
|
||||
|
@ -124,12 +131,15 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d)
|
|||
immBeginAtMost(GPU_PRIM_POINTS, env->totvert * 2);
|
||||
|
||||
for (i = 0, fed = env->data; i < env->totvert; i++, fed++) {
|
||||
const float env_scene_time = BKE_nla_tweakedit_remap(
|
||||
adt_nla_remap, fed->time, NLATIME_CONVERT_MAP);
|
||||
|
||||
/* only draw if visible
|
||||
* - min/max here are fixed, not relative
|
||||
*/
|
||||
if (IN_RANGE(fed->time, (v2d->cur.xmin - fac), (v2d->cur.xmax + fac))) {
|
||||
immVertex2f(shdr_pos, fed->time, fed->min);
|
||||
immVertex2f(shdr_pos, fed->time, fed->max);
|
||||
if (IN_RANGE(env_scene_time, (v2d->cur.xmin - fac), (v2d->cur.xmax + fac))) {
|
||||
immVertex2f(shdr_pos, env_scene_time, fed->min);
|
||||
immVertex2f(shdr_pos, env_scene_time, fed->max);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -572,7 +582,8 @@ static void draw_fcurve_samples(SpaceGraph *sipo, ARegion *region, FCurve *fcu)
|
|||
|
||||
/* Helper func - just draw the F-Curve by sampling the visible region
|
||||
* (for drawing curves with modifiers). */
|
||||
static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu_, View2D *v2d, uint pos)
|
||||
static void draw_fcurve_curve(
|
||||
bAnimContext *ac, ID *id, FCurve *fcu_, View2D *v2d, uint pos, const bool use_nla_remap)
|
||||
{
|
||||
SpaceGraph *sipo = (SpaceGraph *)ac->sl;
|
||||
short mapping_flag = ANIM_get_normalization_flags(ac);
|
||||
|
@ -646,9 +657,17 @@ static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu_, View2D *v2
|
|||
if (n > 0) {
|
||||
immBegin(GPU_PRIM_LINE_STRIP, (n + 1));
|
||||
|
||||
AnimData *adt = use_nla_remap ? BKE_animdata_from_id(id) : NULL;
|
||||
/* NLA remapping is linear so we don't have to remap per iteration. */
|
||||
const float eval_start = BKE_nla_tweakedit_remap(adt, stime, NLATIME_CONVERT_UNMAP);
|
||||
const float eval_freq = BKE_nla_tweakedit_remap(
|
||||
adt, stime + samplefreq, NLATIME_CONVERT_UNMAP) -
|
||||
eval_start;
|
||||
|
||||
for (int i = 0; i <= n; i++) {
|
||||
float ctime = stime + i * samplefreq;
|
||||
immVertex2f(pos, ctime, (evaluate_fcurve(&fcurve_for_draw, ctime) + offset) * unitFac);
|
||||
const float eval_time = eval_start + i * eval_freq;
|
||||
immVertex2f(pos, ctime, (evaluate_fcurve(&fcurve_for_draw, eval_time) + offset) * unitFac);
|
||||
}
|
||||
|
||||
immEnd();
|
||||
|
@ -1015,7 +1034,20 @@ static void draw_fcurve(bAnimContext *ac, SpaceGraph *sipo, ARegion *region, bAn
|
|||
/* draw a curve affected by modifiers or only allowed to have integer values
|
||||
* by sampling it at various small-intervals over the visible region
|
||||
*/
|
||||
draw_fcurve_curve(ac, ale->id, fcu, ®ion->v2d, shdr_pos);
|
||||
if (adt) {
|
||||
/** We have to do this mapping dance since the keyframes were remapped but the Fmodifier
|
||||
* evaluations are not.
|
||||
*
|
||||
* So we undo the keyframe remapping and instead remap the evaluation time when drawing the
|
||||
* curve itself. Afterward, we go back and redo the keyframe remapping so the controls are
|
||||
* drawn properly. */
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, true, false);
|
||||
draw_fcurve_curve(ac, ale->id, fcu, ®ion->v2d, shdr_pos, true);
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, false, false);
|
||||
}
|
||||
else {
|
||||
draw_fcurve_curve(ac, ale->id, fcu, ®ion->v2d, shdr_pos, false);
|
||||
}
|
||||
}
|
||||
else if (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)) {
|
||||
/* just draw curve based on defined data (i.e. no modifiers) */
|
||||
|
@ -1024,7 +1056,7 @@ static void draw_fcurve(bAnimContext *ac, SpaceGraph *sipo, ARegion *region, bAn
|
|||
draw_fcurve_curve_bezts(ac, ale->id, fcu, ®ion->v2d, shdr_pos);
|
||||
}
|
||||
else {
|
||||
draw_fcurve_curve(ac, ale->id, fcu, ®ion->v2d, shdr_pos);
|
||||
draw_fcurve_curve(ac, ale->id, fcu, ®ion->v2d, shdr_pos, false);
|
||||
}
|
||||
}
|
||||
else if (fcu->fpt) {
|
||||
|
@ -1050,7 +1082,7 @@ static void draw_fcurve(bAnimContext *ac, SpaceGraph *sipo, ARegion *region, bAn
|
|||
if ((fcu->flag & FCURVE_ACTIVE) && (fcm)) {
|
||||
switch (fcm->type) {
|
||||
case FMODIFIER_TYPE_ENVELOPE: /* envelope */
|
||||
draw_fcurve_modifier_controls_envelope(fcm, ®ion->v2d);
|
||||
draw_fcurve_modifier_controls_envelope(fcm, ®ion->v2d, adt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3817,9 +3817,9 @@ void draw_nodespace_back_pix(const bContext *C,
|
|||
}
|
||||
|
||||
/* return quadratic beziers points for a given nodelink and clip if v2d is not NULL. */
|
||||
static bool node_link_bezier_handles(View2D *v2d,
|
||||
SpaceNode *snode,
|
||||
bNodeLink *link,
|
||||
static bool node_link_bezier_handles(const View2D *v2d,
|
||||
const SpaceNode *snode,
|
||||
const bNodeLink *link,
|
||||
float vec[4][2])
|
||||
{
|
||||
float cursor[2] = {0.0f, 0.0f};
|
||||
|
@ -3912,8 +3912,11 @@ static bool node_link_bezier_handles(View2D *v2d,
|
|||
}
|
||||
|
||||
/* if v2d not NULL, it clips and returns 0 if not visible */
|
||||
bool node_link_bezier_points(
|
||||
View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol)
|
||||
bool node_link_bezier_points(const View2D *v2d,
|
||||
const SpaceNode *snode,
|
||||
const bNodeLink *link,
|
||||
float coord_array[][2],
|
||||
const int resol)
|
||||
{
|
||||
float vec[4][2];
|
||||
|
||||
|
@ -4076,7 +4079,7 @@ static char nodelink_get_color_id(int th_col)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void nodelink_batch_draw(SpaceNode *snode)
|
||||
static void nodelink_batch_draw(const SpaceNode *snode)
|
||||
{
|
||||
if (g_batch_link.count == 0) {
|
||||
return;
|
||||
|
@ -4116,7 +4119,7 @@ void nodelink_batch_end(SpaceNode *snode)
|
|||
g_batch_link.enabled = false;
|
||||
}
|
||||
|
||||
static void nodelink_batch_add_link(SpaceNode *snode,
|
||||
static void nodelink_batch_add_link(const SpaceNode *snode,
|
||||
const float p0[2],
|
||||
const float p1[2],
|
||||
const float p2[2],
|
||||
|
@ -4148,8 +4151,12 @@ static void nodelink_batch_add_link(SpaceNode *snode,
|
|||
}
|
||||
|
||||
/* don't do shadows if th_col3 is -1. */
|
||||
void node_draw_link_bezier(
|
||||
View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int th_col2, int th_col3)
|
||||
void node_draw_link_bezier(const View2D *v2d,
|
||||
const SpaceNode *snode,
|
||||
const bNodeLink *link,
|
||||
int th_col1,
|
||||
int th_col2,
|
||||
int th_col3)
|
||||
{
|
||||
float vec[4][2];
|
||||
|
||||
|
|
|
@ -317,14 +317,14 @@ static void node_uiblocks_init(const bContext *C, bNodeTree *ntree)
|
|||
}
|
||||
}
|
||||
|
||||
void node_to_view(struct bNode *node, float x, float y, float *rx, float *ry)
|
||||
void node_to_view(const bNode *node, float x, float y, float *rx, float *ry)
|
||||
{
|
||||
nodeToView(node, x, y, rx, ry);
|
||||
*rx *= UI_DPI_FAC;
|
||||
*ry *= UI_DPI_FAC;
|
||||
}
|
||||
|
||||
void node_to_updated_rect(struct bNode *node, rctf *r_rect)
|
||||
void node_to_updated_rect(const bNode *node, rctf *r_rect)
|
||||
{
|
||||
node_to_view(node, node->offsetx, node->offsety, &r_rect->xmin, &r_rect->ymax);
|
||||
node_to_view(node,
|
||||
|
@ -334,7 +334,7 @@ void node_to_updated_rect(struct bNode *node, rctf *r_rect)
|
|||
&r_rect->ymin);
|
||||
}
|
||||
|
||||
void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry)
|
||||
void node_from_view(const bNode *node, float x, float y, float *rx, float *ry)
|
||||
{
|
||||
x /= UI_DPI_FAC;
|
||||
y /= UI_DPI_FAC;
|
||||
|
@ -689,11 +689,11 @@ int node_get_colorid(bNode *node)
|
|||
/* note: in cmp_util.c is similar code, for node_compo_pass_on()
|
||||
* the same goes for shader and texture nodes. */
|
||||
/* note: in node_edit.c is similar code, for untangle node */
|
||||
static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node)
|
||||
static void node_draw_mute_line(const View2D *v2d, const SpaceNode *snode, const bNode *node)
|
||||
{
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
|
||||
LISTBASE_FOREACH (bNodeLink *, link, &node->internal_links) {
|
||||
LISTBASE_FOREACH (const bNodeLink *, link, &node->internal_links) {
|
||||
node_draw_link_bezier(v2d, snode, link, TH_REDALERT, TH_REDALERT, -1);
|
||||
}
|
||||
|
||||
|
@ -947,14 +947,14 @@ static void node_toggle_button_cb(struct bContext *C, void *node_argv, void *op_
|
|||
WM_operator_name_call(C, opname, WM_OP_INVOKE_DEFAULT, NULL);
|
||||
}
|
||||
|
||||
void node_draw_shadow(SpaceNode *snode, bNode *node, float radius, float alpha)
|
||||
void node_draw_shadow(const SpaceNode *snode, const bNode *node, float radius, float alpha)
|
||||
{
|
||||
rctf *rct = &node->totr;
|
||||
const rctf *rct = &node->totr;
|
||||
UI_draw_roundbox_corner_set(UI_CNR_ALL);
|
||||
ui_draw_dropshadow(rct, radius, snode->aspect, alpha, node->flag & SELECT);
|
||||
}
|
||||
|
||||
void node_draw_sockets(View2D *v2d,
|
||||
void node_draw_sockets(const View2D *v2d,
|
||||
const bContext *C,
|
||||
bNodeTree *ntree,
|
||||
bNode *node,
|
||||
|
@ -1118,8 +1118,8 @@ void node_draw_sockets(View2D *v2d,
|
|||
}
|
||||
|
||||
static void node_draw_basis(const bContext *C,
|
||||
ARegion *region,
|
||||
SpaceNode *snode,
|
||||
const View2D *v2d,
|
||||
const SpaceNode *snode,
|
||||
bNodeTree *ntree,
|
||||
bNode *node,
|
||||
bNodeInstanceKey key)
|
||||
|
@ -1127,8 +1127,6 @@ static void node_draw_basis(const bContext *C,
|
|||
/* float socket_size = NODE_SOCKSIZE*U.dpi/72; */ /* UNUSED */
|
||||
float iconbutw = 0.8f * UI_UNIT_X;
|
||||
|
||||
View2D *v2d = ®ion->v2d;
|
||||
|
||||
/* skip if out of view */
|
||||
if (BLI_rctf_isect(&node->totr, &v2d->cur, NULL) == false) {
|
||||
UI_block_end(C, node->block);
|
||||
|
@ -1343,8 +1341,8 @@ static void node_draw_basis(const bContext *C,
|
|||
}
|
||||
|
||||
static void node_draw_hidden(const bContext *C,
|
||||
ARegion *region,
|
||||
SpaceNode *snode,
|
||||
const View2D *v2d,
|
||||
const SpaceNode *snode,
|
||||
bNodeTree *ntree,
|
||||
bNode *node,
|
||||
bNodeInstanceKey UNUSED(key))
|
||||
|
@ -1353,8 +1351,6 @@ static void node_draw_hidden(const bContext *C,
|
|||
float centy = BLI_rctf_cent_y(rct);
|
||||
float hiddenrad = BLI_rctf_size_y(rct) / 2.0f;
|
||||
|
||||
View2D *v2d = ®ion->v2d;
|
||||
|
||||
float scale;
|
||||
UI_view2d_scale_get(v2d, &scale, NULL);
|
||||
|
||||
|
@ -1438,7 +1434,7 @@ static void node_draw_hidden(const bContext *C,
|
|||
|
||||
/* disable lines */
|
||||
if (node->flag & NODE_MUTED) {
|
||||
node_draw_mute_line(®ion->v2d, snode, node);
|
||||
node_draw_mute_line(v2d, snode, node);
|
||||
}
|
||||
|
||||
char showname[128]; /* 128 is used below */
|
||||
|
@ -1550,11 +1546,12 @@ void node_draw_default(const bContext *C,
|
|||
bNode *node,
|
||||
bNodeInstanceKey key)
|
||||
{
|
||||
const View2D *v2d = ®ion->v2d;
|
||||
if (node->flag & NODE_HIDDEN) {
|
||||
node_draw_hidden(C, region, snode, ntree, node, key);
|
||||
node_draw_hidden(C, v2d, snode, ntree, node, key);
|
||||
}
|
||||
else {
|
||||
node_draw_basis(C, region, snode, ntree, node, key);
|
||||
node_draw_basis(C, v2d, snode, ntree, node, key);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1607,8 +1604,7 @@ void node_draw_nodetree(const bContext *C,
|
|||
#endif
|
||||
|
||||
/* draw background nodes, last nodes in front */
|
||||
int a = 0;
|
||||
LISTBASE_FOREACH_INDEX (bNode *, node, &ntree->nodes, a) {
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
#ifdef USE_DRAW_TOT_UPDATE
|
||||
/* unrelated to background nodes, update the v2d->tot,
|
||||
* can be anywhere before we draw the scroll bars */
|
||||
|
@ -1635,8 +1631,7 @@ void node_draw_nodetree(const bContext *C,
|
|||
GPU_blend(GPU_BLEND_NONE);
|
||||
|
||||
/* draw foreground nodes, last nodes in front */
|
||||
a = 0;
|
||||
LISTBASE_FOREACH_INDEX (bNode *, node, &ntree->nodes, a) {
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (node->flag & NODE_BACKGROUND) {
|
||||
continue;
|
||||
}
|
||||
|
@ -1686,8 +1681,8 @@ static void draw_nodetree(const bContext *C,
|
|||
/* shade the parent node group and add a uiBlock to clip mouse events */
|
||||
static void draw_group_overlay(const bContext *C, ARegion *region)
|
||||
{
|
||||
View2D *v2d = ®ion->v2d;
|
||||
rctf rect = v2d->cur;
|
||||
const View2D *v2d = ®ion->v2d;
|
||||
const rctf rect = v2d->cur;
|
||||
float color[4];
|
||||
|
||||
/* shade node groups to separate them visually */
|
||||
|
|
|
@ -61,14 +61,17 @@ void space_node_group_offset(struct SpaceNode *snode, float *x, float *y);
|
|||
/* node_draw.c */
|
||||
int node_get_colorid(struct bNode *node);
|
||||
int node_get_resize_cursor(int directions);
|
||||
void node_draw_shadow(struct SpaceNode *snode, struct bNode *node, float radius, float alpha);
|
||||
void node_draw_shadow(const struct SpaceNode *snode,
|
||||
const struct bNode *node,
|
||||
float radius,
|
||||
float alpha);
|
||||
void node_draw_default(const struct bContext *C,
|
||||
struct ARegion *region,
|
||||
struct SpaceNode *snode,
|
||||
struct bNodeTree *ntree,
|
||||
struct bNode *node,
|
||||
bNodeInstanceKey key);
|
||||
void node_draw_sockets(struct View2D *v2d,
|
||||
void node_draw_sockets(const struct View2D *v2d,
|
||||
const struct bContext *C,
|
||||
struct bNodeTree *ntree,
|
||||
struct bNode *node,
|
||||
|
@ -92,9 +95,9 @@ void node_draw_space(const bContext *C, ARegion *region);
|
|||
|
||||
void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode, float cursor[2]);
|
||||
/* DPI scaled coords */
|
||||
void node_to_view(struct bNode *node, float x, float y, float *rx, float *ry);
|
||||
void node_to_updated_rect(struct bNode *node, rctf *r_rect);
|
||||
void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry);
|
||||
void node_to_view(const struct bNode *node, float x, float y, float *rx, float *ry);
|
||||
void node_to_updated_rect(const struct bNode *node, rctf *r_rect);
|
||||
void node_from_view(const struct bNode *node, float x, float y, float *rx, float *ry);
|
||||
|
||||
/* node_buttons.c */
|
||||
void node_buttons_register(struct ARegionType *art);
|
||||
|
@ -145,17 +148,17 @@ void nodelink_batch_start(struct SpaceNode *snode);
|
|||
void nodelink_batch_end(struct SpaceNode *snode);
|
||||
|
||||
void node_draw_link(struct View2D *v2d, struct SpaceNode *snode, struct bNodeLink *link);
|
||||
void node_draw_link_bezier(struct View2D *v2d,
|
||||
struct SpaceNode *snode,
|
||||
struct bNodeLink *link,
|
||||
void node_draw_link_bezier(const struct View2D *v2d,
|
||||
const struct SpaceNode *snode,
|
||||
const struct bNodeLink *link,
|
||||
int th_col1,
|
||||
int th_col2,
|
||||
int th_col3);
|
||||
bool node_link_bezier_points(struct View2D *v2d,
|
||||
struct SpaceNode *snode,
|
||||
struct bNodeLink *link,
|
||||
bool node_link_bezier_points(const struct View2D *v2d,
|
||||
const struct SpaceNode *snode,
|
||||
const struct bNodeLink *link,
|
||||
float coord_array[][2],
|
||||
int resol);
|
||||
const int resol);
|
||||
void draw_nodespace_back_pix(const struct bContext *C,
|
||||
struct ARegion *region,
|
||||
struct SpaceNode *snode,
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
|
||||
static bool ntree_has_drivers(bNodeTree *ntree)
|
||||
{
|
||||
AnimData *adt = BKE_animdata_from_id(&ntree->id);
|
||||
const AnimData *adt = BKE_animdata_from_id(&ntree->id);
|
||||
if (adt == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,23 @@
|
|||
*
|
||||
* \{ */
|
||||
|
||||
static void mesh_skin_transdata_create(TransDataBasic *td, BMEditMesh *em, BMVert *eve)
|
||||
static float *mesh_skin_transdata_center(const struct TransIslandData *island_data,
|
||||
const int island_index,
|
||||
BMVert *eve)
|
||||
{
|
||||
if (island_data->center && island_index != -1) {
|
||||
return island_data->center[island_index];
|
||||
}
|
||||
else {
|
||||
return eve->co;
|
||||
}
|
||||
}
|
||||
|
||||
static void mesh_skin_transdata_create(TransDataBasic *td,
|
||||
BMEditMesh *em,
|
||||
BMVert *eve,
|
||||
const struct TransIslandData *island_data,
|
||||
const int island_index)
|
||||
{
|
||||
BLI_assert(BM_elem_flag_test(eve, BM_ELEM_HIDDEN) == 0);
|
||||
MVertSkin *vs = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MVERT_SKIN);
|
||||
|
@ -65,6 +81,7 @@ static void mesh_skin_transdata_create(TransDataBasic *td, BMEditMesh *em, BMVer
|
|||
td->flag |= TD_SELECTED;
|
||||
}
|
||||
|
||||
copy_v3_v3(td->center, mesh_skin_transdata_center(island_data, island_index, eve));
|
||||
td->extra = eve;
|
||||
}
|
||||
|
||||
|
@ -188,8 +205,15 @@ void createTransMeshSkin(TransInfo *t)
|
|||
continue;
|
||||
}
|
||||
|
||||
int island_index = -1;
|
||||
if (island_data.island_vert_map) {
|
||||
const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a;
|
||||
island_index = island_data.island_vert_map[connected_index];
|
||||
}
|
||||
|
||||
if (mirror_data.vert_map && mirror_data.vert_map[a].index != -1) {
|
||||
mesh_skin_transdata_create((TransDataBasic *)td_mirror, em, eve);
|
||||
mesh_skin_transdata_create(
|
||||
(TransDataBasic *)td_mirror, em, eve, &island_data, island_index);
|
||||
|
||||
int elem_index = mirror_data.vert_map[a].index;
|
||||
BMVert *v_src = BM_vert_at_index(bm, elem_index);
|
||||
|
@ -200,7 +224,7 @@ void createTransMeshSkin(TransInfo *t)
|
|||
td_mirror++;
|
||||
}
|
||||
else if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
|
||||
mesh_skin_transdata_create((TransDataBasic *)td, em, eve);
|
||||
mesh_skin_transdata_create((TransDataBasic *)td, em, eve, &island_data, island_index);
|
||||
|
||||
if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
|
||||
createSpaceNormal(td->axismtx, eve->no);
|
||||
|
|
|
@ -80,10 +80,10 @@ typedef struct TransformInitContext {
|
|||
TransInfo *t;
|
||||
TransDataContainer *tc;
|
||||
|
||||
/* MOTE: There pointers will be nullptr during counting step.
|
||||
/* MOTE: There pointers will be `nullptr` during counting step.
|
||||
* This means, that the transformation data initialization functions are to increment
|
||||
* `tc->data_len` instead of filling in the transformation data when these pointers are nullptr.
|
||||
* For simplicitly, check the `current.td` against nullptr.
|
||||
* `tc->data_len` instead of filling in the transformation data when these pointers are
|
||||
* `nullptr`. For simplicity, check the `current.td` against `nullptr`.
|
||||
* Do not `tc->data_len` when filling in the transformation data. */
|
||||
struct {
|
||||
TransData *td;
|
||||
|
@ -619,8 +619,8 @@ static void cancelTransTracking(TransInfo *t)
|
|||
}
|
||||
else if (tdt->mode == transDataTracking_ModePlaneTracks) {
|
||||
MovieTrackingPlaneTrack *plane_track = tdt->plane_track;
|
||||
MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track,
|
||||
tdt->framenr);
|
||||
MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get_exact(plane_track,
|
||||
tdt->framenr);
|
||||
|
||||
BLI_assert(plane_marker != NULL);
|
||||
|
||||
|
|
|
@ -110,11 +110,11 @@ static bool dependsOnTime(GpencilModifierData *md)
|
|||
return (mmd->flag & GP_NOISE_USE_RANDOM) != 0;
|
||||
}
|
||||
|
||||
static float *noise_table(int len, int seed)
|
||||
static float *noise_table(int len, int offset, int seed)
|
||||
{
|
||||
float *table = MEM_callocN(sizeof(float) * len, __func__);
|
||||
for (int i = 0; i < len; i++) {
|
||||
table[i] = BLI_hash_int_01(BLI_hash_int_2d(seed, i + 1));
|
||||
table[i] = BLI_hash_int_01(BLI_hash_int_2d(seed, i + offset + 1));
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
@ -172,11 +172,19 @@ static void deformStroke(GpencilModifierData *md,
|
|||
/* Sanitize as it can create out of bound reads. */
|
||||
float noise_scale = clamp_f(mmd->noise_scale, 0.0f, 1.0f);
|
||||
|
||||
int len = ceilf(gps->totpoints * noise_scale) + 1;
|
||||
float *noise_table_position = (mmd->factor > 0.0f) ? noise_table(len, seed + 2) : NULL;
|
||||
float *noise_table_strength = (mmd->factor_strength > 0.0f) ? noise_table(len, seed + 3) : NULL;
|
||||
float *noise_table_thickness = (mmd->factor_thickness > 0.0f) ? noise_table(len, seed) : NULL;
|
||||
float *noise_table_uvs = (mmd->factor_uvs > 0.0f) ? noise_table(len, seed + 4) : NULL;
|
||||
int len = ceilf(gps->totpoints * noise_scale) + 2;
|
||||
float *noise_table_position = (mmd->factor > 0.0f) ?
|
||||
noise_table(len, (int)floor(mmd->noise_offset), seed + 2) :
|
||||
NULL;
|
||||
float *noise_table_strength = (mmd->factor_strength > 0.0f) ?
|
||||
noise_table(len, (int)floor(mmd->noise_offset), seed + 3) :
|
||||
NULL;
|
||||
float *noise_table_thickness = (mmd->factor_thickness > 0.0f) ?
|
||||
noise_table(len, (int)floor(mmd->noise_offset), seed) :
|
||||
NULL;
|
||||
float *noise_table_uvs = (mmd->factor_uvs > 0.0f) ?
|
||||
noise_table(len, (int)floor(mmd->noise_offset), seed + 4) :
|
||||
NULL;
|
||||
|
||||
/* Calculate stroke normal. */
|
||||
if (gps->totpoints > 2) {
|
||||
|
@ -225,24 +233,27 @@ static void deformStroke(GpencilModifierData *md,
|
|||
cross_v3_v3v3(vec2, vec1, normal);
|
||||
normalize_v3(vec2);
|
||||
|
||||
float noise = table_sample(noise_table_position, i * noise_scale);
|
||||
float noise = table_sample(noise_table_position,
|
||||
i * noise_scale + fractf(mmd->noise_offset));
|
||||
madd_v3_v3fl(&pt->x, vec2, (noise * 2.0f - 1.0f) * weight * mmd->factor * 0.1f);
|
||||
}
|
||||
|
||||
if (mmd->factor_thickness > 0.0f) {
|
||||
float noise = table_sample(noise_table_thickness, i * noise_scale);
|
||||
float noise = table_sample(noise_table_thickness,
|
||||
i * noise_scale + fractf(mmd->noise_offset));
|
||||
pt->pressure *= max_ff(1.0f + (noise * 2.0f - 1.0f) * weight * mmd->factor_thickness, 0.0f);
|
||||
CLAMP_MIN(pt->pressure, GPENCIL_STRENGTH_MIN);
|
||||
}
|
||||
|
||||
if (mmd->factor_strength > 0.0f) {
|
||||
float noise = table_sample(noise_table_strength, i * noise_scale);
|
||||
float noise = table_sample(noise_table_strength,
|
||||
i * noise_scale + fractf(mmd->noise_offset));
|
||||
pt->strength *= max_ff(1.0f - noise * weight * mmd->factor_strength, 0.0f);
|
||||
CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
|
||||
}
|
||||
|
||||
if (mmd->factor_uvs > 0.0f) {
|
||||
float noise = table_sample(noise_table_uvs, i * noise_scale);
|
||||
float noise = table_sample(noise_table_uvs, i * noise_scale + fractf(mmd->noise_offset));
|
||||
pt->uv_rot += (noise * 2.0f - 1.0f) * weight * mmd->factor_uvs * M_PI_2;
|
||||
CLAMP(pt->uv_rot, -M_PI_2, M_PI_2);
|
||||
}
|
||||
|
@ -292,6 +303,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
|
|||
uiItemR(col, ptr, "factor_thickness", 0, IFACE_("Thickness"), ICON_NONE);
|
||||
uiItemR(col, ptr, "factor_uvs", 0, IFACE_("UV"), ICON_NONE);
|
||||
uiItemR(col, ptr, "noise_scale", 0, NULL, ICON_NONE);
|
||||
uiItemR(col, ptr, "noise_offset", 0, NULL, ICON_NONE);
|
||||
uiItemR(col, ptr, "seed", 0, NULL, ICON_NONE);
|
||||
|
||||
gpencil_modifier_panel_end(layout, ptr);
|
||||
|
|
|
@ -32,7 +32,7 @@ struct ImBuf;
|
|||
void imb_refcounter_lock_init(void);
|
||||
void imb_refcounter_lock_exit(void);
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef WIN32
|
||||
void imb_mmap_lock_init(void);
|
||||
void imb_mmap_lock_exit(void);
|
||||
void imb_mmap_lock(void);
|
||||
|
|
|
@ -53,7 +53,7 @@ void imb_refcounter_lock_exit(void)
|
|||
BLI_spin_end(&refcounter_spin);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef WIN32
|
||||
static SpinLock mmap_spin;
|
||||
|
||||
void imb_mmap_lock_init(void)
|
||||
|
|
|
@ -23,13 +23,13 @@
|
|||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
# include "mmap_win.h"
|
||||
# include <io.h>
|
||||
# include <stddef.h>
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "BLI_fileops.h"
|
||||
#include "BLI_mmap.h"
|
||||
#include "BLI_path_util.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
@ -186,20 +186,19 @@ ImBuf *IMB_loadifffile(
|
|||
size = BLI_file_descriptor_size(file);
|
||||
|
||||
imb_mmap_lock();
|
||||
mem = mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0);
|
||||
BLI_mmap_file *mmap_file = BLI_mmap_open(file);
|
||||
imb_mmap_unlock();
|
||||
|
||||
if (mem == (unsigned char *)-1) {
|
||||
if (mmap_file == NULL) {
|
||||
fprintf(stderr, "%s: couldn't get mapping %s\n", __func__, descr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mem = BLI_mmap_get_pointer(mmap_file);
|
||||
|
||||
ibuf = IMB_ibImageFromMemory(mem, size, flags, colorspace, descr);
|
||||
|
||||
imb_mmap_lock();
|
||||
if (munmap(mem, size)) {
|
||||
fprintf(stderr, "%s: couldn't unmap file %s\n", __func__, descr);
|
||||
}
|
||||
BLI_mmap_free(mmap_file);
|
||||
imb_mmap_unlock();
|
||||
|
||||
return ibuf;
|
||||
|
@ -292,14 +291,15 @@ static void imb_loadtilefile(ImBuf *ibuf, int file, int tx, int ty, unsigned int
|
|||
size = BLI_file_descriptor_size(file);
|
||||
|
||||
imb_mmap_lock();
|
||||
mem = mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0);
|
||||
BLI_mmap_file *mmap_file = BLI_mmap_open(file);
|
||||
imb_mmap_unlock();
|
||||
|
||||
if (mem == (unsigned char *)-1) {
|
||||
if (mmap_file == NULL) {
|
||||
fprintf(stderr, "Couldn't get memory mapping for %s\n", ibuf->cachename);
|
||||
return;
|
||||
}
|
||||
|
||||
mem = BLI_mmap_get_pointer(mmap_file);
|
||||
|
||||
const ImFileType *type = IMB_file_type_from_ibuf(ibuf);
|
||||
if (type != NULL) {
|
||||
if (type->load_tile != NULL) {
|
||||
|
@ -308,9 +308,7 @@ static void imb_loadtilefile(ImBuf *ibuf, int file, int tx, int ty, unsigned int
|
|||
}
|
||||
|
||||
imb_mmap_lock();
|
||||
if (munmap(mem, size)) {
|
||||
fprintf(stderr, "Couldn't unmap memory for %s.\n", ibuf->cachename);
|
||||
}
|
||||
BLI_mmap_free(mmap_file);
|
||||
imb_mmap_unlock();
|
||||
}
|
||||
|
||||
|
|
|
@ -515,7 +515,7 @@ typedef enum ID_Type {
|
|||
((const ID *)(_id))->override_library->reference != NULL)
|
||||
|
||||
#define ID_IS_OVERRIDE_LIBRARY_VIRTUAL(_id) \
|
||||
((((const ID *)(_id))->flag & LIB_EMBEDDED_DATA_LIB_OVERRIDE) != 0)
|
||||
((((const ID *)(_id))->flag & (LIB_EMBEDDED_DATA_LIB_OVERRIDE | LIB_EMBEDDED_DATA)) != 0)
|
||||
|
||||
#define ID_IS_OVERRIDE_LIBRARY(_id) \
|
||||
(ID_IS_OVERRIDE_LIBRARY_REAL(_id) || ID_IS_OVERRIDE_LIBRARY_VIRTUAL(_id))
|
||||
|
|
|
@ -152,6 +152,7 @@
|
|||
.factor_thickness = 0.0f, \
|
||||
.factor_uvs = 0.0f, \
|
||||
.noise_scale = 0.0f, \
|
||||
.noise_offset = 0.0f, \
|
||||
.step = 4, \
|
||||
.layer_pass = 0, \
|
||||
.seed = 1, \
|
||||
|
|
|
@ -107,6 +107,8 @@ typedef struct NoiseGpencilModifierData {
|
|||
float factor_uvs;
|
||||
/** Noise Frequency scaling */
|
||||
float noise_scale;
|
||||
float noise_offset;
|
||||
char _pad[4];
|
||||
/** How many frames before recalculate randoms. */
|
||||
int step;
|
||||
/** Custom index for passes. */
|
||||
|
|
|
@ -48,12 +48,6 @@ set(SRC
|
|||
../../../../intern/guardedalloc/intern/mallocn_lockfree_impl.c
|
||||
)
|
||||
|
||||
if(WIN32 AND NOT UNIX)
|
||||
list(APPEND SRC
|
||||
../../../../intern/guardedalloc/intern/mmap_win.c
|
||||
)
|
||||
endif()
|
||||
|
||||
# SRC_DNA_INC is defined in the parent dir
|
||||
|
||||
add_cc_flags_custom_test(makesdna)
|
||||
|
|
|
@ -189,7 +189,6 @@ set(SRC
|
|||
../../../../intern/guardedalloc/intern/mallocn.c
|
||||
../../../../intern/guardedalloc/intern/mallocn_guarded_impl.c
|
||||
../../../../intern/guardedalloc/intern/mallocn_lockfree_impl.c
|
||||
../../../../intern/guardedalloc/intern/mmap_win.c
|
||||
|
||||
# Needed for defaults.
|
||||
../../../../release/datafiles/userdef/userdef_default.c
|
||||
|
|
|
@ -4758,8 +4758,14 @@ static const char *cpp_classes =
|
|||
"class CollectionIterator {\n"
|
||||
"public:\n"
|
||||
" CollectionIterator() : iter(), t(iter.ptr), init(false) { iter.valid = false; }\n"
|
||||
" CollectionIterator(const PointerRNA &ptr) : CollectionIterator() { this->begin(ptr); }\n"
|
||||
" ~CollectionIterator(void) { if (init) Tend(&iter); };\n"
|
||||
"\n"
|
||||
" CollectionIterator(const CollectionIterator &other) = delete;\n"
|
||||
" CollectionIterator(CollectionIterator &&other) = delete;\n"
|
||||
" CollectionIterator &operator=(const CollectionIterator &other) = delete;\n"
|
||||
" CollectionIterator &operator=(CollectionIterator &&other) = delete;\n"
|
||||
"\n"
|
||||
" operator bool(void)\n"
|
||||
" { return iter.valid != 0; }\n"
|
||||
" const CollectionIterator<T, Tbegin, Tnext, Tend>& operator++() { Tnext(&iter); t = "
|
||||
|
@ -4777,9 +4783,6 @@ static const char *cpp_classes =
|
|||
"true; }\n"
|
||||
"\n"
|
||||
"private:\n"
|
||||
" const CollectionIterator<T, Tbegin, Tnext, Tend>& operator = "
|
||||
"(const CollectionIterator<T, Tbegin, Tnext, Tend>& /*copy*/) {}\n"
|
||||
""
|
||||
" CollectionPropertyIterator iter;\n"
|
||||
" T t;\n"
|
||||
" bool init;\n"
|
||||
|
@ -4794,6 +4797,8 @@ static const char *cpp_classes =
|
|||
"\n"
|
||||
" void begin(CollectionIterator<T, Tbegin, Tnext, Tend>& iter)\n"
|
||||
" { iter.begin(ptr); }\n"
|
||||
" CollectionIterator<T, Tbegin, Tnext, Tend> begin()\n"
|
||||
" { return CollectionIterator<T, Tbegin, Tnext, Tend>(ptr); }\n"
|
||||
" CollectionIterator<T, Tbegin, Tnext, Tend> end()\n"
|
||||
" { return CollectionIterator<T, Tbegin, Tnext, Tend>(); } /* test */ \n"
|
||||
""
|
||||
|
|
|
@ -498,6 +498,13 @@ static void rna_def_modifier_gpencilnoise(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Noise Scale", "Scale the noise frequency");
|
||||
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "noise_offset", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "noise_offset");
|
||||
RNA_def_property_range(prop, 0.0, FLT_MAX);
|
||||
RNA_def_property_ui_range(prop, 0.0, 100.0, 0.1, 3);
|
||||
RNA_def_property_ui_text(prop, "Noise Offset", "Offset the noise along the strokes");
|
||||
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_custom_curve", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_NOISE_CUSTOM_CURVE);
|
||||
RNA_def_property_ui_text(
|
||||
|
|
|
@ -1279,12 +1279,22 @@ static int rna_property_override_diff_propptr(Main *bmain,
|
|||
0);
|
||||
|
||||
if (is_id) {
|
||||
/* For now, once we deal with nodetrees we'll want to get rid of that one. */
|
||||
// BLI_assert(no_ownership);
|
||||
/* Owned IDs (the ones we want to actually compare in depth, instead of just comparing pointer
|
||||
* values) should be always properly tagged as 'virtual' overrides. */
|
||||
ID *id = propptr_a->owner_id;
|
||||
if (id != NULL && !ID_IS_OVERRIDE_LIBRARY(id)) {
|
||||
id = propptr_b->owner_id;
|
||||
if (id != NULL && !ID_IS_OVERRIDE_LIBRARY(id)) {
|
||||
id = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BLI_assert(no_ownership || id == NULL || ID_IS_OVERRIDE_LIBRARY_VIRTUAL(id));
|
||||
UNUSED_VARS_NDEBUG(id);
|
||||
}
|
||||
|
||||
if (override) {
|
||||
if (no_ownership /* || is_id */ || is_null || is_type_diff || !is_valid_for_diffing) {
|
||||
if (no_ownership || is_null || is_type_diff || !is_valid_for_diffing) {
|
||||
/* In case this pointer prop does not own its data (or one is NULL), do not compare structs!
|
||||
* This is a quite safe path to infinite loop, among other nasty issues.
|
||||
* Instead, just compare pointers themselves. */
|
||||
|
@ -1468,7 +1478,6 @@ int rna_property_override_diff_default(Main *bmain,
|
|||
rna_path != NULL;
|
||||
|
||||
const bool no_ownership = (prop_a->rnaprop->flag & PROP_PTR_NO_OWNERSHIP) != 0;
|
||||
const bool no_prop_name = (prop_a->rnaprop->flag_override & PROPOVERRIDE_NO_PROP_NAME) != 0;
|
||||
|
||||
/* Note: we assume we only insert in ptr_a (i.e. we can only get new items in ptr_a),
|
||||
* and that we never remove anything. */
|
||||
|
@ -1724,6 +1733,11 @@ int rna_property_override_diff_default(Main *bmain,
|
|||
}
|
||||
|
||||
case PROP_POINTER: {
|
||||
/* Using property name check only makes sense for items of a collection, not for a single
|
||||
* pointer.
|
||||
* Doing this here avoids having to manually specify `PROPOVERRIDE_NO_PROP_NAME` to things
|
||||
* like ShapeKey pointers. */
|
||||
const bool no_prop_name = true;
|
||||
if (STREQ(prop_a->identifier, "rna_type")) {
|
||||
/* Dummy 'pass' answer, this is a meta-data and must be ignored... */
|
||||
return 0;
|
||||
|
@ -1752,6 +1766,8 @@ int rna_property_override_diff_default(Main *bmain,
|
|||
}
|
||||
|
||||
case PROP_COLLECTION: {
|
||||
const bool no_prop_name = (prop_a->rnaprop->flag_override & PROPOVERRIDE_NO_PROP_NAME) != 0;
|
||||
|
||||
bool equals = true;
|
||||
bool abort = false;
|
||||
int idx_a = 0;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_pointcloud_types.h"
|
||||
|
||||
#include "BKE_attribute_math.hh"
|
||||
#include "BKE_bvhutils.h"
|
||||
#include "BKE_deform.h"
|
||||
#include "BKE_mesh.h"
|
||||
|
@ -217,13 +218,141 @@ BLI_NOINLINE static void eliminate_points_based_on_mask(Span<bool> elimination_m
|
|||
}
|
||||
}
|
||||
|
||||
BLI_NOINLINE static void compute_special_attributes(const Mesh &mesh,
|
||||
Span<float3> bary_coords,
|
||||
Span<int> looptri_indices,
|
||||
MutableSpan<float3> r_normals,
|
||||
MutableSpan<int> r_ids,
|
||||
MutableSpan<float3> r_rotations)
|
||||
template<typename T>
|
||||
BLI_NOINLINE static void interpolate_attribute_point(const Mesh &mesh,
|
||||
const Span<float3> bary_coords,
|
||||
const Span<int> looptri_indices,
|
||||
const Span<T> data_in,
|
||||
MutableSpan<T> data_out)
|
||||
{
|
||||
BLI_assert(data_in.size() == mesh.totvert);
|
||||
Span<MLoopTri> looptris = get_mesh_looptris(mesh);
|
||||
|
||||
for (const int i : bary_coords.index_range()) {
|
||||
const int looptri_index = looptri_indices[i];
|
||||
const MLoopTri &looptri = looptris[looptri_index];
|
||||
const float3 &bary_coord = bary_coords[i];
|
||||
|
||||
const int v0_index = mesh.mloop[looptri.tri[0]].v;
|
||||
const int v1_index = mesh.mloop[looptri.tri[1]].v;
|
||||
const int v2_index = mesh.mloop[looptri.tri[2]].v;
|
||||
|
||||
const T &v0 = data_in[v0_index];
|
||||
const T &v1 = data_in[v1_index];
|
||||
const T &v2 = data_in[v2_index];
|
||||
|
||||
const T interpolated_value = attribute_math::mix3(bary_coord, v0, v1, v2);
|
||||
data_out[i] = interpolated_value;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BLI_NOINLINE static void interpolate_attribute_corner(const Mesh &mesh,
|
||||
const Span<float3> bary_coords,
|
||||
const Span<int> looptri_indices,
|
||||
const Span<T> data_in,
|
||||
MutableSpan<T> data_out)
|
||||
{
|
||||
BLI_assert(data_in.size() == mesh.totloop);
|
||||
Span<MLoopTri> looptris = get_mesh_looptris(mesh);
|
||||
|
||||
for (const int i : bary_coords.index_range()) {
|
||||
const int looptri_index = looptri_indices[i];
|
||||
const MLoopTri &looptri = looptris[looptri_index];
|
||||
const float3 &bary_coord = bary_coords[i];
|
||||
|
||||
const int loop_index_0 = looptri.tri[0];
|
||||
const int loop_index_1 = looptri.tri[1];
|
||||
const int loop_index_2 = looptri.tri[2];
|
||||
|
||||
const T &v0 = data_in[loop_index_0];
|
||||
const T &v1 = data_in[loop_index_1];
|
||||
const T &v2 = data_in[loop_index_2];
|
||||
|
||||
const T interpolated_value = attribute_math::mix3(bary_coord, v0, v1, v2);
|
||||
data_out[i] = interpolated_value;
|
||||
}
|
||||
}
|
||||
|
||||
BLI_NOINLINE static void interpolate_attribute(const Mesh &mesh,
|
||||
Span<float3> bary_coords,
|
||||
Span<int> looptri_indices,
|
||||
const StringRef attribute_name,
|
||||
const ReadAttribute &attribute_in,
|
||||
GeometryComponent &component)
|
||||
{
|
||||
const CustomDataType data_type = attribute_in.custom_data_type();
|
||||
const AttributeDomain domain = attribute_in.domain();
|
||||
if (!ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CORNER)) {
|
||||
/* Not supported currently. */
|
||||
return;
|
||||
}
|
||||
|
||||
OutputAttributePtr attribute_out = component.attribute_try_get_for_output(
|
||||
attribute_name, ATTR_DOMAIN_POINT, data_type);
|
||||
if (!attribute_out) {
|
||||
return;
|
||||
}
|
||||
|
||||
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
|
||||
Span data_in = attribute_in.get_span<T>();
|
||||
MutableSpan data_out = attribute_out->get_span_for_write_only<T>();
|
||||
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT: {
|
||||
interpolate_attribute_point<T>(mesh, bary_coords, looptri_indices, data_in, data_out);
|
||||
break;
|
||||
}
|
||||
case ATTR_DOMAIN_CORNER: {
|
||||
interpolate_attribute_corner<T>(mesh, bary_coords, looptri_indices, data_in, data_out);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
BLI_assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
attribute_out.apply_span_and_save();
|
||||
}
|
||||
|
||||
BLI_NOINLINE static void interpolate_existing_attributes(const MeshComponent &mesh_component,
|
||||
GeometryComponent &component,
|
||||
Span<float3> bary_coords,
|
||||
Span<int> looptri_indices)
|
||||
{
|
||||
const Mesh &mesh = *mesh_component.get_for_read();
|
||||
|
||||
Set<std::string> attribute_names = mesh_component.attribute_names();
|
||||
for (StringRefNull attribute_name : attribute_names) {
|
||||
if (ELEM(attribute_name, "position", "normal", "id")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ReadAttributePtr attribute_in = mesh_component.attribute_try_get_for_read(attribute_name);
|
||||
interpolate_attribute(
|
||||
mesh, bary_coords, looptri_indices, attribute_name, *attribute_in, component);
|
||||
}
|
||||
}
|
||||
|
||||
BLI_NOINLINE static void compute_special_attributes(const Mesh &mesh,
|
||||
GeometryComponent &component,
|
||||
Span<float3> bary_coords,
|
||||
Span<int> looptri_indices)
|
||||
{
|
||||
OutputAttributePtr id_attribute = component.attribute_try_get_for_output(
|
||||
"id", ATTR_DOMAIN_POINT, CD_PROP_INT32);
|
||||
OutputAttributePtr normal_attribute = component.attribute_try_get_for_output(
|
||||
"normal", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3);
|
||||
OutputAttributePtr rotation_attribute = component.attribute_try_get_for_output(
|
||||
"rotation", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3);
|
||||
|
||||
MutableSpan<int> ids = id_attribute->get_span_for_write_only<int>();
|
||||
MutableSpan<float3> normals = normal_attribute->get_span_for_write_only<float3>();
|
||||
MutableSpan<float3> rotations = rotation_attribute->get_span_for_write_only<float3>();
|
||||
|
||||
Span<MLoopTri> looptris = get_mesh_looptris(mesh);
|
||||
for (const int i : bary_coords.index_range()) {
|
||||
const int looptri_index = looptri_indices[i];
|
||||
|
@ -237,36 +366,26 @@ BLI_NOINLINE static void compute_special_attributes(const Mesh &mesh,
|
|||
const float3 v1_pos = mesh.mvert[v1_index].co;
|
||||
const float3 v2_pos = mesh.mvert[v2_index].co;
|
||||
|
||||
r_ids[i] = (int)(bary_coord.hash()) + looptri_index;
|
||||
normal_tri_v3(r_normals[i], v0_pos, v1_pos, v2_pos);
|
||||
r_rotations[i] = normal_to_euler_rotation(r_normals[i]);
|
||||
ids[i] = (int)(bary_coord.hash()) + looptri_index;
|
||||
normal_tri_v3(normals[i], v0_pos, v1_pos, v2_pos);
|
||||
rotations[i] = normal_to_euler_rotation(normals[i]);
|
||||
}
|
||||
}
|
||||
|
||||
BLI_NOINLINE static void add_remaining_point_attributes(const Mesh &mesh,
|
||||
GeometryComponent &component,
|
||||
Span<float3> bary_coords,
|
||||
Span<int> looptri_indices)
|
||||
{
|
||||
OutputAttributePtr id_attribute = component.attribute_try_get_for_output(
|
||||
"id", ATTR_DOMAIN_POINT, CD_PROP_INT32);
|
||||
OutputAttributePtr normal_attribute = component.attribute_try_get_for_output(
|
||||
"normal", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3);
|
||||
OutputAttributePtr rotation_attribute = component.attribute_try_get_for_output(
|
||||
"rotation", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3);
|
||||
|
||||
compute_special_attributes(mesh,
|
||||
bary_coords,
|
||||
looptri_indices,
|
||||
normal_attribute->get_span_for_write_only<float3>(),
|
||||
id_attribute->get_span_for_write_only<int>(),
|
||||
rotation_attribute->get_span_for_write_only<float3>());
|
||||
|
||||
id_attribute.apply_span_and_save();
|
||||
normal_attribute.apply_span_and_save();
|
||||
rotation_attribute.apply_span_and_save();
|
||||
}
|
||||
|
||||
BLI_NOINLINE static void add_remaining_point_attributes(const MeshComponent &mesh_component,
|
||||
GeometryComponent &component,
|
||||
Span<float3> bary_coords,
|
||||
Span<int> looptri_indices)
|
||||
{
|
||||
interpolate_existing_attributes(mesh_component, component, bary_coords, looptri_indices);
|
||||
compute_special_attributes(
|
||||
*mesh_component.get_for_read(), component, bary_coords, looptri_indices);
|
||||
}
|
||||
|
||||
static void sample_mesh_surface_with_minimum_distance(const Mesh &mesh,
|
||||
const float max_density,
|
||||
const float minimum_distance,
|
||||
|
@ -351,7 +470,7 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params)
|
|||
geometry_set_out.get_component_for_write<PointCloudComponent>();
|
||||
point_component.replace(pointcloud);
|
||||
|
||||
add_remaining_point_attributes(*mesh_in, point_component, bary_coords, looptri_indices);
|
||||
add_remaining_point_attributes(mesh_component, point_component, bary_coords, looptri_indices);
|
||||
|
||||
params.set_output("Geometry", std::move(geometry_set_out));
|
||||
}
|
||||
|
|
|
@ -34,8 +34,9 @@ namespace blender::nodes {
|
|||
|
||||
static void execute_on_component(GeoNodeExecParams params, GeometryComponent &component)
|
||||
{
|
||||
static const float3 scale_default = float3(1.0f);
|
||||
OutputAttributePtr scale_attribute = component.attribute_try_get_for_output(
|
||||
"scale", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3);
|
||||
"scale", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, &scale_default);
|
||||
ReadAttributePtr attribute = params.get_input_attribute(
|
||||
"Factor", component, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, nullptr);
|
||||
if (!attribute) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "FN_multi_function_network_evaluation.hh"
|
||||
|
||||
#include "BLI_color.hh"
|
||||
#include "BLI_float2.hh"
|
||||
#include "BLI_float3.hh"
|
||||
|
||||
namespace blender::nodes {
|
||||
|
@ -191,27 +192,57 @@ static void add_implicit_conversion(DataTypeConversions &conversions,
|
|||
static DataTypeConversions create_implicit_conversions()
|
||||
{
|
||||
DataTypeConversions conversions;
|
||||
add_implicit_conversion<float, int32_t>(conversions);
|
||||
add_implicit_conversion<float, float2>(conversions);
|
||||
add_implicit_conversion<float, float3>(conversions);
|
||||
add_implicit_conversion<int32_t, float>(conversions);
|
||||
add_implicit_conversion<float, int32_t>(conversions);
|
||||
add_implicit_conversion<float, bool>(conversions);
|
||||
add_implicit_conversion<bool, float>(conversions);
|
||||
add_implicit_conversion<float3, float>(
|
||||
conversions, "Vector Length", [](float3 a) { return a.length(); });
|
||||
add_implicit_conversion<int32_t, float3>(
|
||||
conversions, "int32 to float3", [](int32_t a) { return float3((float)a); });
|
||||
add_implicit_conversion<float3, Color4f>(
|
||||
conversions, "float3 to Color4f", [](float3 a) { return Color4f(a.x, a.y, a.z, 1.0f); });
|
||||
add_implicit_conversion<Color4f, float3>(
|
||||
conversions, "Color4f to float3", [](Color4f a) { return float3(a.r, a.g, a.b); });
|
||||
add_implicit_conversion<float, Color4f>(
|
||||
conversions, "float to Color4f", [](float a) { return Color4f(a, a, a, 1.0f); });
|
||||
add_implicit_conversion<Color4f, float>(
|
||||
conversions, "Color4f to float", [](Color4f a) { return rgb_to_grayscale(a); });
|
||||
|
||||
add_implicit_conversion<float2, float3>(conversions);
|
||||
add_implicit_conversion<float2, float>(
|
||||
conversions, "float2 to float", [](float2 a) { return a.length(); });
|
||||
add_implicit_conversion<float2, int32_t>(
|
||||
conversions, "float2 to int32_t", [](float2 a) { return (int32_t)a.length(); });
|
||||
add_implicit_conversion<float2, bool>(
|
||||
conversions, "float2 to bool", [](float2 a) { return a.length_squared() == 0.0f; });
|
||||
add_implicit_conversion<float2, Color4f>(
|
||||
conversions, "float2 to Color4f", [](float2 a) { return Color4f(a.x, a.y, 0.0f, 1.0f); });
|
||||
|
||||
add_implicit_conversion<float3, bool>(
|
||||
conversions, "float3 to boolean", [](float3 a) { return a.length_squared() == 0.0f; });
|
||||
add_implicit_conversion<float3, float>(
|
||||
conversions, "Vector Length", [](float3 a) { return a.length(); });
|
||||
add_implicit_conversion<float3, int32_t>(
|
||||
conversions, "float3 to int32_t", [](float3 a) { return (int)a.length(); });
|
||||
add_implicit_conversion<float3, float2>(conversions);
|
||||
add_implicit_conversion<float3, Color4f>(
|
||||
conversions, "float3 to Color4f", [](float3 a) { return Color4f(a.x, a.y, a.z, 1.0f); });
|
||||
|
||||
add_implicit_conversion<int32_t, bool>(conversions);
|
||||
add_implicit_conversion<int32_t, float>(conversions);
|
||||
add_implicit_conversion<int32_t, float2>(
|
||||
conversions, "int32 to float2", [](int32_t a) { return float2((float)a); });
|
||||
add_implicit_conversion<int32_t, float3>(
|
||||
conversions, "int32 to float3", [](int32_t a) { return float3((float)a); });
|
||||
|
||||
add_implicit_conversion<bool, float>(conversions);
|
||||
add_implicit_conversion<bool, int32_t>(conversions);
|
||||
add_implicit_conversion<bool, float2>(
|
||||
conversions, "boolean to float2", [](bool a) { return (a) ? float2(1.0f) : float2(0.0f); });
|
||||
add_implicit_conversion<bool, float3>(
|
||||
conversions, "boolean to float3", [](bool a) { return (a) ? float3(1.0f) : float3(0.0f); });
|
||||
add_implicit_conversion<bool, Color4f>(conversions, "boolean to Color4f", [](bool a) {
|
||||
return (a) ? Color4f(1.0f, 1.0f, 1.0f, 1.0f) : Color4f(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
});
|
||||
|
||||
add_implicit_conversion<Color4f, float>(
|
||||
conversions, "Color4f to float", [](Color4f a) { return rgb_to_grayscale(a); });
|
||||
add_implicit_conversion<Color4f, float2>(
|
||||
conversions, "Color4f to float2", [](Color4f a) { return float2(a.r, a.g); });
|
||||
add_implicit_conversion<Color4f, float3>(
|
||||
conversions, "Color4f to float3", [](Color4f a) { return float3(a.r, a.g, a.b); });
|
||||
|
||||
return conversions;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue