Merge branch 'master' into blender2.8
This commit is contained in:
commit
70fdf0fe37
|
@ -22,6 +22,7 @@ if(WITH_CYCLES_NATIVE_ONLY)
|
|||
-DWITH_KERNEL_NATIVE
|
||||
)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
|
||||
set(CYCLES_KERNEL_FLAGS "-march=native")
|
||||
elseif(NOT WITH_CPU_SSE)
|
||||
set(CXX_HAS_SSE FALSE)
|
||||
set(CXX_HAS_AVX FALSE)
|
||||
|
@ -59,10 +60,13 @@ elseif(WIN32 AND MSVC)
|
|||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Ox")
|
||||
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /Ox")
|
||||
|
||||
set(CYCLES_KERNEL_FLAGS "/fp:fast -D_CRT_SECURE_NO_WARNINGS /GS-")
|
||||
elseif(CMAKE_COMPILER_IS_GNUCC)
|
||||
check_cxx_compiler_flag(-msse CXX_HAS_SSE)
|
||||
check_cxx_compiler_flag(-mavx CXX_HAS_AVX)
|
||||
check_cxx_compiler_flag(-mavx2 CXX_HAS_AVX2)
|
||||
set(CYCLES_KERNEL_FLAGS "-ffast-math")
|
||||
if(CXX_HAS_SSE)
|
||||
set(CYCLES_SSE2_KERNEL_FLAGS "-ffast-math -msse -msse2 -mfpmath=sse")
|
||||
set(CYCLES_SSE3_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse")
|
||||
|
@ -79,6 +83,7 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
|||
check_cxx_compiler_flag(-msse CXX_HAS_SSE)
|
||||
check_cxx_compiler_flag(-mavx CXX_HAS_AVX)
|
||||
check_cxx_compiler_flag(-mavx2 CXX_HAS_AVX2)
|
||||
set(CYCLES_KERNEL_FLAGS "-ffast-math")
|
||||
if(CXX_HAS_SSE)
|
||||
set(CYCLES_SSE2_KERNEL_FLAGS "-ffast-math -msse -msse2")
|
||||
set(CYCLES_SSE3_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3")
|
||||
|
|
|
@ -67,7 +67,7 @@ BVH *BVH::create(const BVHParams& params, const vector<Object*>& objects)
|
|||
if(params.use_qbvh)
|
||||
return new QBVH(params, objects);
|
||||
else
|
||||
return new RegularBVH(params, objects);
|
||||
return new BinaryBVH(params, objects);
|
||||
}
|
||||
|
||||
/* Building */
|
||||
|
@ -427,13 +427,13 @@ static bool node_bvh_is_unaligned(const BVHNode *node)
|
|||
return node0->is_unaligned || node1->is_unaligned;
|
||||
}
|
||||
|
||||
RegularBVH::RegularBVH(const BVHParams& params_, const vector<Object*>& objects_)
|
||||
BinaryBVH::BinaryBVH(const BVHParams& params_, const vector<Object*>& objects_)
|
||||
: BVH(params_, objects_)
|
||||
{
|
||||
}
|
||||
|
||||
void RegularBVH::pack_leaf(const BVHStackEntry& e,
|
||||
const LeafNode *leaf)
|
||||
void BinaryBVH::pack_leaf(const BVHStackEntry& e,
|
||||
const LeafNode *leaf)
|
||||
{
|
||||
assert(e.idx + BVH_NODE_LEAF_SIZE <= pack.leaf_nodes.size());
|
||||
float4 data[BVH_NODE_LEAF_SIZE];
|
||||
|
@ -456,9 +456,9 @@ void RegularBVH::pack_leaf(const BVHStackEntry& e,
|
|||
memcpy(&pack.leaf_nodes[e.idx], data, sizeof(float4)*BVH_NODE_LEAF_SIZE);
|
||||
}
|
||||
|
||||
void RegularBVH::pack_inner(const BVHStackEntry& e,
|
||||
const BVHStackEntry& e0,
|
||||
const BVHStackEntry& e1)
|
||||
void BinaryBVH::pack_inner(const BVHStackEntry& e,
|
||||
const BVHStackEntry& e0,
|
||||
const BVHStackEntry& e1)
|
||||
{
|
||||
if(e0.node->is_unaligned || e1.node->is_unaligned) {
|
||||
pack_unaligned_inner(e, e0, e1);
|
||||
|
@ -467,9 +467,9 @@ void RegularBVH::pack_inner(const BVHStackEntry& e,
|
|||
}
|
||||
}
|
||||
|
||||
void RegularBVH::pack_aligned_inner(const BVHStackEntry& e,
|
||||
const BVHStackEntry& e0,
|
||||
const BVHStackEntry& e1)
|
||||
void BinaryBVH::pack_aligned_inner(const BVHStackEntry& e,
|
||||
const BVHStackEntry& e0,
|
||||
const BVHStackEntry& e1)
|
||||
{
|
||||
pack_aligned_node(e.idx,
|
||||
e0.node->bounds, e1.node->bounds,
|
||||
|
@ -477,11 +477,11 @@ void RegularBVH::pack_aligned_inner(const BVHStackEntry& e,
|
|||
e0.node->visibility, e1.node->visibility);
|
||||
}
|
||||
|
||||
void RegularBVH::pack_aligned_node(int idx,
|
||||
const BoundBox& b0,
|
||||
const BoundBox& b1,
|
||||
int c0, int c1,
|
||||
uint visibility0, uint visibility1)
|
||||
void BinaryBVH::pack_aligned_node(int idx,
|
||||
const BoundBox& b0,
|
||||
const BoundBox& b1,
|
||||
int c0, int c1,
|
||||
uint visibility0, uint visibility1)
|
||||
{
|
||||
assert(idx + BVH_NODE_SIZE <= pack.nodes.size());
|
||||
assert(c0 < 0 || c0 < pack.nodes.size());
|
||||
|
@ -508,9 +508,9 @@ void RegularBVH::pack_aligned_node(int idx,
|
|||
memcpy(&pack.nodes[idx], data, sizeof(int4)*BVH_NODE_SIZE);
|
||||
}
|
||||
|
||||
void RegularBVH::pack_unaligned_inner(const BVHStackEntry& e,
|
||||
const BVHStackEntry& e0,
|
||||
const BVHStackEntry& e1)
|
||||
void BinaryBVH::pack_unaligned_inner(const BVHStackEntry& e,
|
||||
const BVHStackEntry& e0,
|
||||
const BVHStackEntry& e1)
|
||||
{
|
||||
pack_unaligned_node(e.idx,
|
||||
e0.node->get_aligned_space(),
|
||||
|
@ -521,13 +521,13 @@ void RegularBVH::pack_unaligned_inner(const BVHStackEntry& e,
|
|||
e0.node->visibility, e1.node->visibility);
|
||||
}
|
||||
|
||||
void RegularBVH::pack_unaligned_node(int idx,
|
||||
const Transform& aligned_space0,
|
||||
const Transform& aligned_space1,
|
||||
const BoundBox& bounds0,
|
||||
const BoundBox& bounds1,
|
||||
int c0, int c1,
|
||||
uint visibility0, uint visibility1)
|
||||
void BinaryBVH::pack_unaligned_node(int idx,
|
||||
const Transform& aligned_space0,
|
||||
const Transform& aligned_space1,
|
||||
const BoundBox& bounds0,
|
||||
const BoundBox& bounds1,
|
||||
int c0, int c1,
|
||||
uint visibility0, uint visibility1)
|
||||
{
|
||||
assert(idx + BVH_UNALIGNED_NODE_SIZE <= pack.nodes.size());
|
||||
assert(c0 < 0 || c0 < pack.nodes.size());
|
||||
|
@ -553,7 +553,7 @@ void RegularBVH::pack_unaligned_node(int idx,
|
|||
memcpy(&pack.nodes[idx], data, sizeof(float4)*BVH_UNALIGNED_NODE_SIZE);
|
||||
}
|
||||
|
||||
void RegularBVH::pack_nodes(const BVHNode *root)
|
||||
void BinaryBVH::pack_nodes(const BVHNode *root)
|
||||
{
|
||||
const size_t num_nodes = root->getSubtreeSize(BVH_STAT_NODE_COUNT);
|
||||
const size_t num_leaf_nodes = root->getSubtreeSize(BVH_STAT_LEAF_COUNT);
|
||||
|
@ -630,7 +630,7 @@ void RegularBVH::pack_nodes(const BVHNode *root)
|
|||
pack.root_index = (root->is_leaf())? -1: 0;
|
||||
}
|
||||
|
||||
void RegularBVH::refit_nodes()
|
||||
void BinaryBVH::refit_nodes()
|
||||
{
|
||||
assert(!params.top_level);
|
||||
|
||||
|
@ -639,7 +639,7 @@ void RegularBVH::refit_nodes()
|
|||
refit_node(0, (pack.root_index == -1)? true: false, bbox, visibility);
|
||||
}
|
||||
|
||||
void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
|
||||
void BinaryBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
|
||||
{
|
||||
if(leaf) {
|
||||
assert(idx + BVH_NODE_LEAF_SIZE <= pack.leaf_nodes.size());
|
||||
|
|
|
@ -110,15 +110,15 @@ protected:
|
|||
virtual void refit_nodes() = 0;
|
||||
};
|
||||
|
||||
/* Regular BVH
|
||||
/* Binary BVH
|
||||
*
|
||||
* Typical BVH with each node having two children. */
|
||||
|
||||
class RegularBVH : public BVH {
|
||||
class BinaryBVH : public BVH {
|
||||
protected:
|
||||
/* constructor */
|
||||
friend class BVH;
|
||||
RegularBVH(const BVHParams& params, const vector<Object*>& objects);
|
||||
BinaryBVH(const BVHParams& params, const vector<Object*>& objects);
|
||||
|
||||
/* pack */
|
||||
void pack_nodes(const BVHNode *root);
|
||||
|
|
|
@ -300,8 +300,8 @@ public:
|
|||
{
|
||||
const int cuda_version = cuewCompilerVersion();
|
||||
const int machine = system_cpu_bits();
|
||||
const string kernel_path = path_get("source/kernel");
|
||||
const string include = path_dirname(kernel_path);
|
||||
const string source_path = path_get("source");
|
||||
const string include_path = source_path;
|
||||
string cflags = string_printf("-m%d "
|
||||
"--ptxas-options=\"-v\" "
|
||||
"--use_fast_math "
|
||||
|
@ -310,7 +310,7 @@ public:
|
|||
"-I\"%s\"",
|
||||
machine,
|
||||
cuda_version,
|
||||
include.c_str());
|
||||
include_path.c_str());
|
||||
if(use_adaptive_compilation()) {
|
||||
cflags += " " + requested_features.get_build_options();
|
||||
}
|
||||
|
@ -382,8 +382,8 @@ public:
|
|||
compile_kernel_get_common_cflags(requested_features, split);
|
||||
|
||||
/* Try to use locally compiled kernel. */
|
||||
const string kernel_path = path_get("source/kernel");
|
||||
const string kernel_md5 = path_files_md5_hash(kernel_path);
|
||||
const string source_path = path_get("source");
|
||||
const string kernel_md5 = path_files_md5_hash(source_path);
|
||||
|
||||
/* We include cflags into md5 so changing cuda toolkit or changing other
|
||||
* compiler command line arguments makes sure cubin gets re-built.
|
||||
|
@ -424,9 +424,10 @@ public:
|
|||
return "";
|
||||
}
|
||||
const char *nvcc = cuewCompilerPath();
|
||||
const string kernel = path_join(kernel_path,
|
||||
path_join("kernels",
|
||||
path_join("cuda", split ? "kernel_split.cu" : "kernel.cu")));
|
||||
const string kernel = path_join(
|
||||
path_join(source_path, "kernel"),
|
||||
path_join("kernels",
|
||||
path_join("cuda", split ? "kernel_split.cu" : "kernel.cu")));
|
||||
double starttime = time_dt();
|
||||
printf("Compiling CUDA kernel ...\n");
|
||||
|
||||
|
|
|
@ -235,7 +235,7 @@ string OpenCLCache::get_kernel_md5()
|
|||
thread_scoped_lock lock(self.kernel_md5_lock);
|
||||
|
||||
if(self.kernel_md5.empty()) {
|
||||
self.kernel_md5 = path_files_md5_hash(path_get("source/kernel"));
|
||||
self.kernel_md5 = path_files_md5_hash(path_get("source"));
|
||||
}
|
||||
return self.kernel_md5;
|
||||
}
|
||||
|
@ -443,8 +443,8 @@ void OpenCLDeviceBase::OpenCLProgram::load()
|
|||
add_log(string("OpenCL program ") + program_name + " not found in cache.", true);
|
||||
|
||||
/* need to create source to get md5 */
|
||||
string source = "#include \"kernels/opencl/" + kernel_file + "\"\n";
|
||||
source = path_source_replace_includes(source, path_get("source/kernel"));
|
||||
string source = "#include \"kernel/kernels/opencl/" + kernel_file + "\"\n";
|
||||
source = path_source_replace_includes(source, path_get("source"));
|
||||
|
||||
string basename = "cycles_kernel_" + program_name + "_" + device_md5 + "_" + util_md5_string(source);
|
||||
basename = path_cache_get(path_join("kernels", basename));
|
||||
|
|
|
@ -347,6 +347,9 @@ endif()
|
|||
include_directories(${INC})
|
||||
include_directories(SYSTEM ${INC_SYS})
|
||||
|
||||
set_source_files_properties(kernels/cpu/kernel.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_KERNEL_FLAGS}")
|
||||
set_source_files_properties(kernels/cpu/kernel_split.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_KERNEL_FLAGS}")
|
||||
|
||||
if(CXX_HAS_SSE)
|
||||
list(APPEND SRC
|
||||
kernels/cpu/kernel_sse2.cpp
|
||||
|
|
|
@ -320,17 +320,18 @@ static char *path_specials(const string& sub)
|
|||
{
|
||||
static bool env_init = false;
|
||||
static char *env_shader_path;
|
||||
static char *env_kernel_path;
|
||||
static char *env_source_path;
|
||||
if(!env_init) {
|
||||
env_shader_path = getenv("CYCLES_SHADER_PATH");
|
||||
env_kernel_path = getenv("CYCLES_KERNEL_PATH");
|
||||
/* NOTE: It is KERNEL in env variable for compatibility reasons. */
|
||||
env_source_path = getenv("CYCLES_KERNEL_PATH");
|
||||
env_init = true;
|
||||
}
|
||||
if(env_shader_path != NULL && sub == "shader") {
|
||||
return env_shader_path;
|
||||
}
|
||||
else if(env_shader_path != NULL && sub == "kernel") {
|
||||
return env_kernel_path;
|
||||
else if(env_shader_path != NULL && sub == "source") {
|
||||
return env_source_path;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -2092,7 +2092,7 @@ class WM_OT_addon_install(Operator):
|
|||
|
||||
# print message
|
||||
msg = (
|
||||
tip_("Modules Installed (%s) from %r into %r (%s)") %
|
||||
tip_("Modules Installed (%s) from %r into %r") %
|
||||
(", ".join(sorted(addons_new)), pyfile, path_addons)
|
||||
)
|
||||
print(msg)
|
||||
|
|
|
@ -569,6 +569,14 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
|||
col.prop(md, "use_mirror_u", text="U")
|
||||
col.prop(md, "use_mirror_v", text="V")
|
||||
|
||||
col = layout.column(align=True)
|
||||
|
||||
if md.use_mirror_u:
|
||||
col.prop(md, "mirror_offset_u")
|
||||
|
||||
if md.use_mirror_v:
|
||||
col.prop(md, "mirror_offset_v")
|
||||
|
||||
col = layout.column()
|
||||
|
||||
if md.use_mirror_merge is True:
|
||||
|
|
|
@ -130,18 +130,22 @@ void IDP_FreeIDPArray(IDProperty *prop)
|
|||
MEM_freeN(prop->data.pointer);
|
||||
}
|
||||
|
||||
/*shallow copies item*/
|
||||
/* shallow copies item */
|
||||
void IDP_SetIndexArray(IDProperty *prop, int index, IDProperty *item)
|
||||
{
|
||||
IDProperty *old;
|
||||
|
||||
BLI_assert(prop->type == IDP_IDPARRAY);
|
||||
|
||||
if (index >= prop->len || index < 0)
|
||||
return;
|
||||
|
||||
old = GETPROP(prop, index);
|
||||
if (index >= prop->len || index < 0) return;
|
||||
if (item != old) IDP_FreeProperty(old);
|
||||
|
||||
memcpy(GETPROP(prop, index), item, sizeof(IDProperty));
|
||||
if (item != old) {
|
||||
IDP_FreeProperty(old);
|
||||
|
||||
memcpy(old, item, sizeof(IDProperty));
|
||||
}
|
||||
}
|
||||
|
||||
IDProperty *IDP_GetIndexArray(IDProperty *prop, int index)
|
||||
|
|
|
@ -1512,23 +1512,6 @@ int BM_mesh_elem_count(BMesh *bm, const char htype)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Special case: Python uses custom-data layers to hold PyObject references.
|
||||
* These have to be kept in-place, else the PyObject's we point to, wont point back to us.
|
||||
*
|
||||
* \note ``ele_src`` Is a duplicate, so we don't need to worry about getting in a feedback loop.
|
||||
*
|
||||
* \note If there are other customdata layers which need this functionality, it should be generalized.
|
||||
* However #BM_mesh_remap is currently the only place where this is done.
|
||||
*/
|
||||
static void bm_mesh_remap_cd_update(
|
||||
BMHeader *ele_dst, BMHeader *ele_src,
|
||||
const int cd_elem_pyptr)
|
||||
{
|
||||
void **pyptr_dst_p = BM_ELEM_CD_GET_VOID_P(((BMElem *)ele_dst), cd_elem_pyptr);
|
||||
void **pyptr_src_p = BM_ELEM_CD_GET_VOID_P(((BMElem *)ele_src), cd_elem_pyptr);
|
||||
*pyptr_dst_p = *pyptr_src_p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remaps the vertices, edges and/or faces of the bmesh as indicated by vert/edge/face_idx arrays
|
||||
|
@ -1570,6 +1553,8 @@ void BM_mesh_remap(
|
|||
BMVert **verts_pool, *verts_copy, **vep;
|
||||
int i, totvert = bm->totvert;
|
||||
const unsigned int *new_idx;
|
||||
/* Special case: Python uses custom - data layers to hold PyObject references.
|
||||
* These have to be kept in - place, else the PyObject's we point to, wont point back to us. */
|
||||
const int cd_vert_pyptr = CustomData_get_offset(&bm->vdata, CD_BM_ELEM_PYPTR);
|
||||
|
||||
/* Init the old-to-new vert pointers mapping */
|
||||
|
@ -1578,9 +1563,14 @@ void BM_mesh_remap(
|
|||
/* Make a copy of all vertices. */
|
||||
verts_pool = bm->vtable;
|
||||
verts_copy = MEM_mallocN(sizeof(BMVert) * totvert, "BM_mesh_remap verts copy");
|
||||
void **pyptrs = (cd_vert_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totvert, __func__) : NULL;
|
||||
for (i = totvert, ve = verts_copy + totvert - 1, vep = verts_pool + totvert - 1; i--; ve--, vep--) {
|
||||
*ve = **vep;
|
||||
/* printf("*vep: %p, verts_pool[%d]: %p\n", *vep, i, verts_pool[i]);*/
|
||||
if (cd_vert_pyptr != -1) {
|
||||
void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)ve), cd_vert_pyptr);
|
||||
pyptrs[i] = *pyptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy back verts to their new place, and update old2new pointers mapping. */
|
||||
|
@ -1593,13 +1583,17 @@ void BM_mesh_remap(
|
|||
/* printf("mapping vert from %d to %d (%p/%p to %p)\n", i, *new_idx, *vep, verts_pool[i], new_vep);*/
|
||||
BLI_ghash_insert(vptr_map, *vep, new_vep);
|
||||
if (cd_vert_pyptr != -1) {
|
||||
bm_mesh_remap_cd_update(&(*vep)->head, &new_vep->head, cd_vert_pyptr);
|
||||
void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_vep), cd_vert_pyptr);
|
||||
*pyptr = pyptrs[*new_idx];
|
||||
}
|
||||
}
|
||||
bm->elem_index_dirty |= BM_VERT;
|
||||
bm->elem_table_dirty |= BM_VERT;
|
||||
|
||||
MEM_freeN(verts_copy);
|
||||
if (pyptrs) {
|
||||
MEM_freeN(pyptrs);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remap Edges */
|
||||
|
@ -1607,6 +1601,8 @@ void BM_mesh_remap(
|
|||
BMEdge **edges_pool, *edges_copy, **edp;
|
||||
int i, totedge = bm->totedge;
|
||||
const unsigned int *new_idx;
|
||||
/* Special case: Python uses custom - data layers to hold PyObject references.
|
||||
* These have to be kept in - place, else the PyObject's we point to, wont point back to us. */
|
||||
const int cd_edge_pyptr = CustomData_get_offset(&bm->edata, CD_BM_ELEM_PYPTR);
|
||||
|
||||
/* Init the old-to-new vert pointers mapping */
|
||||
|
@ -1615,8 +1611,13 @@ void BM_mesh_remap(
|
|||
/* Make a copy of all vertices. */
|
||||
edges_pool = bm->etable;
|
||||
edges_copy = MEM_mallocN(sizeof(BMEdge) * totedge, "BM_mesh_remap edges copy");
|
||||
void **pyptrs = (cd_edge_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totedge, __func__) : NULL;
|
||||
for (i = totedge, ed = edges_copy + totedge - 1, edp = edges_pool + totedge - 1; i--; ed--, edp--) {
|
||||
*ed = **edp;
|
||||
if (cd_edge_pyptr != -1) {
|
||||
void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)ed), cd_edge_pyptr);
|
||||
pyptrs[i] = *pyptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy back verts to their new place, and update old2new pointers mapping. */
|
||||
|
@ -1629,13 +1630,17 @@ void BM_mesh_remap(
|
|||
BLI_ghash_insert(eptr_map, *edp, new_edp);
|
||||
/* printf("mapping edge from %d to %d (%p/%p to %p)\n", i, *new_idx, *edp, edges_pool[i], new_edp);*/
|
||||
if (cd_edge_pyptr != -1) {
|
||||
bm_mesh_remap_cd_update(&(*edp)->head, &new_edp->head, cd_edge_pyptr);
|
||||
void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_edp), cd_edge_pyptr);
|
||||
*pyptr = pyptrs[*new_idx];
|
||||
}
|
||||
}
|
||||
bm->elem_index_dirty |= BM_EDGE;
|
||||
bm->elem_table_dirty |= BM_EDGE;
|
||||
|
||||
MEM_freeN(edges_copy);
|
||||
if (pyptrs) {
|
||||
MEM_freeN(pyptrs);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remap Faces */
|
||||
|
@ -1643,6 +1648,8 @@ void BM_mesh_remap(
|
|||
BMFace **faces_pool, *faces_copy, **fap;
|
||||
int i, totface = bm->totface;
|
||||
const unsigned int *new_idx;
|
||||
/* Special case: Python uses custom - data layers to hold PyObject references.
|
||||
* These have to be kept in - place, else the PyObject's we point to, wont point back to us. */
|
||||
const int cd_poly_pyptr = CustomData_get_offset(&bm->pdata, CD_BM_ELEM_PYPTR);
|
||||
|
||||
/* Init the old-to-new vert pointers mapping */
|
||||
|
@ -1651,8 +1658,13 @@ void BM_mesh_remap(
|
|||
/* Make a copy of all vertices. */
|
||||
faces_pool = bm->ftable;
|
||||
faces_copy = MEM_mallocN(sizeof(BMFace) * totface, "BM_mesh_remap faces copy");
|
||||
void **pyptrs = (cd_poly_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totface, __func__) : NULL;
|
||||
for (i = totface, fa = faces_copy + totface - 1, fap = faces_pool + totface - 1; i--; fa--, fap--) {
|
||||
*fa = **fap;
|
||||
if (cd_poly_pyptr != -1) {
|
||||
void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)fa), cd_poly_pyptr);
|
||||
pyptrs[i] = *pyptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy back verts to their new place, and update old2new pointers mapping. */
|
||||
|
@ -1664,7 +1676,8 @@ void BM_mesh_remap(
|
|||
*new_fap = *fa;
|
||||
BLI_ghash_insert(fptr_map, *fap, new_fap);
|
||||
if (cd_poly_pyptr != -1) {
|
||||
bm_mesh_remap_cd_update(&(*fap)->head, &new_fap->head, cd_poly_pyptr);
|
||||
void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_fap), cd_poly_pyptr);
|
||||
*pyptr = pyptrs[*new_idx];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1672,6 +1685,9 @@ void BM_mesh_remap(
|
|||
bm->elem_table_dirty |= BM_FACE;
|
||||
|
||||
MEM_freeN(faces_copy);
|
||||
if (pyptrs) {
|
||||
MEM_freeN(pyptrs);
|
||||
}
|
||||
}
|
||||
|
||||
/* And now, fix all vertices/edges/faces/loops pointers! */
|
||||
|
|
|
@ -77,28 +77,8 @@ static bool check_object_needs_evaluation(Object *object)
|
|||
return false;
|
||||
}
|
||||
|
||||
void deg_graph_build_finalize(Depsgraph *graph)
|
||||
void deg_graph_build_flush_layers(Depsgraph *graph)
|
||||
{
|
||||
/* STEP 1: Make sure new invisible dependencies are ready for use.
|
||||
*
|
||||
* TODO(sergey): This might do a bit of extra tagging, but it's kinda nice
|
||||
* to do it ahead of a time and don't spend time on flushing updates on
|
||||
* every frame change.
|
||||
*/
|
||||
GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash)
|
||||
{
|
||||
if (id_node->layers == 0) {
|
||||
ID *id = id_node->id;
|
||||
if (GS(id->name) == ID_OB) {
|
||||
Object *object = (Object *)id;
|
||||
if (check_object_needs_evaluation(object)) {
|
||||
id_node->tag_update(graph);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
GHASH_FOREACH_END();
|
||||
/* STEP 2: Flush visibility layers from children to parent. */
|
||||
std::stack<OperationDepsNode *> stack;
|
||||
foreach (OperationDepsNode *node, graph->operations) {
|
||||
IDDepsNode *id_node = node->owner->owner;
|
||||
|
@ -143,6 +123,31 @@ void deg_graph_build_finalize(Depsgraph *graph)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deg_graph_build_finalize(Depsgraph *graph)
|
||||
{
|
||||
/* STEP 1: Make sure new invisible dependencies are ready for use.
|
||||
*
|
||||
* TODO(sergey): This might do a bit of extra tagging, but it's kinda nice
|
||||
* to do it ahead of a time and don't spend time on flushing updates on
|
||||
* every frame change.
|
||||
*/
|
||||
GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash)
|
||||
{
|
||||
if (id_node->layers == 0) {
|
||||
ID *id = id_node->id;
|
||||
if (GS(id->name) == ID_OB) {
|
||||
Object *object = (Object *)id;
|
||||
if (check_object_needs_evaluation(object)) {
|
||||
id_node->tag_update(graph);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
GHASH_FOREACH_END();
|
||||
/* STEP 2: Flush visibility layers from children to parent. */
|
||||
deg_graph_build_flush_layers(graph);
|
||||
/* STEP 3: Re-tag IDs for update if it was tagged before the relations
|
||||
* update tag.
|
||||
*/
|
||||
|
|
|
@ -42,5 +42,6 @@ struct Depsgraph;
|
|||
string deg_fcurve_id_name(const FCurve *fcu);
|
||||
|
||||
void deg_graph_build_finalize(struct Depsgraph *graph);
|
||||
void deg_graph_build_flush_layers(struct Depsgraph *graph);
|
||||
|
||||
} // namespace DEG
|
||||
|
|
|
@ -56,8 +56,8 @@ extern "C" {
|
|||
#include "DEG_depsgraph.h"
|
||||
} /* extern "C" */
|
||||
|
||||
#include "intern/builder/deg_builder.h"
|
||||
#include "intern/eval/deg_eval_flush.h"
|
||||
|
||||
#include "intern/nodes/deg_node.h"
|
||||
#include "intern/nodes/deg_node_component.h"
|
||||
#include "intern/nodes/deg_node_operation.h"
|
||||
|
@ -348,6 +348,18 @@ void DEG_graph_on_visible_update(Main *bmain, Scene *scene)
|
|||
GHASH_FOREACH_END();
|
||||
}
|
||||
scene->lay_updated |= graph->layers;
|
||||
/* Special trick to get local view to work. */
|
||||
LINKLIST_FOREACH (Base *, base, &scene->base) {
|
||||
Object *object = base->object;
|
||||
DEG::IDDepsNode *node = graph->find_id_node(&object->id);
|
||||
node->layers = 0;
|
||||
}
|
||||
LINKLIST_FOREACH (Base *, base, &scene->base) {
|
||||
Object *object = base->object;
|
||||
DEG::IDDepsNode *node = graph->find_id_node(&object->id);
|
||||
node->layers |= base->lay;
|
||||
}
|
||||
DEG::deg_graph_build_flush_layers(graph);
|
||||
}
|
||||
|
||||
void DEG_on_visible_update(Main *bmain, const bool UNUSED(do_time))
|
||||
|
|
|
@ -424,7 +424,7 @@ typedef void (*uiBlockCancelFunc)(struct bContext *C, void *arg1);
|
|||
|
||||
void UI_popup_block_invoke(struct bContext *C, uiBlockCreateFunc func, void *arg);
|
||||
void UI_popup_block_invoke_ex(struct bContext *C, uiBlockCreateFunc func, void *arg, const char *opname, int opcontext);
|
||||
void UI_popup_block_ex(struct bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg);
|
||||
void UI_popup_block_ex(struct bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg, struct wmOperator *op);
|
||||
/* void uiPupBlockOperator(struct bContext *C, uiBlockCreateFunc func, struct wmOperator *op, int opcontext); */ /* UNUSED */
|
||||
|
||||
void UI_popup_block_close(struct bContext *C, struct wmWindow *win, uiBlock *block);
|
||||
|
|
|
@ -87,6 +87,7 @@
|
|||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
#include "wm_event_system.h"
|
||||
|
||||
#ifdef WITH_INPUT_IME
|
||||
# include "wm_window.h"
|
||||
|
@ -381,6 +382,7 @@ typedef struct uiAfterFunc {
|
|||
void *butm_func_arg;
|
||||
int a2;
|
||||
|
||||
wmOperator *popup_op;
|
||||
wmOperatorType *optype;
|
||||
int opcontext;
|
||||
PointerRNA *opptr;
|
||||
|
@ -636,13 +638,24 @@ PointerRNA *ui_handle_afterfunc_add_operator(wmOperatorType *ot, int opcontext,
|
|||
return ptr;
|
||||
}
|
||||
|
||||
static void popup_check(bContext *C, wmOperator *op)
|
||||
{
|
||||
if (op && op->type->check && op->type->check(C, op)) {
|
||||
/* check for popup and re-layout buttons */
|
||||
ARegion *ar_menu = CTX_wm_menu(C);
|
||||
if (ar_menu)
|
||||
ED_region_tag_refresh_ui(ar_menu);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a #uiAfterFunc is needed for this button.
|
||||
*/
|
||||
static bool ui_afterfunc_check(const uiBlock *block, const uiBut *but)
|
||||
{
|
||||
return (but->func || but->funcN || but->rename_func || but->optype || but->rnaprop || block->handle_func ||
|
||||
(but->type == UI_BTYPE_BUT_MENU && block->butm_func));
|
||||
(but->type == UI_BTYPE_BUT_MENU && block->butm_func) ||
|
||||
(block->handle && block->handle->popup_op));
|
||||
}
|
||||
|
||||
static void ui_apply_but_func(bContext *C, uiBut *but)
|
||||
|
@ -683,6 +696,9 @@ static void ui_apply_but_func(bContext *C, uiBut *but)
|
|||
after->butm_func_arg = block->butm_func_arg;
|
||||
after->a2 = but->a2;
|
||||
}
|
||||
|
||||
if (block->handle)
|
||||
after->popup_op = block->handle->popup_op;
|
||||
|
||||
after->optype = but->optype;
|
||||
after->opcontext = but->opcontext;
|
||||
|
@ -767,6 +783,9 @@ static void ui_apply_but_funcs_after(bContext *C)
|
|||
if (after.context)
|
||||
CTX_store_set(C, after.context);
|
||||
|
||||
if (after.popup_op)
|
||||
popup_check(C, after.popup_op);
|
||||
|
||||
if (after.opptr) {
|
||||
/* free in advance to avoid leak on exit */
|
||||
opptr = *after.opptr;
|
||||
|
@ -6660,7 +6679,7 @@ static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
|
|||
static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
|
||||
{
|
||||
uiBut *but = (uiBut *)arg1;
|
||||
UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but);
|
||||
UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -10177,6 +10196,25 @@ void UI_popup_handlers_add(bContext *C, ListBase *handlers, uiPopupBlockHandle *
|
|||
|
||||
void UI_popup_handlers_remove(ListBase *handlers, uiPopupBlockHandle *popup)
|
||||
{
|
||||
wmEventHandler *handler;
|
||||
|
||||
for (handler = handlers->first; handler; handler = handler->next) {
|
||||
if (handler->ui_handle == ui_popup_handler &&
|
||||
handler->ui_remove == ui_popup_handler_remove &&
|
||||
handler->ui_userdata == popup)
|
||||
{
|
||||
/* tag refresh parent popup */
|
||||
if (handler->next &&
|
||||
handler->next->ui_handle == ui_popup_handler &&
|
||||
handler->next->ui_remove == ui_popup_handler_remove)
|
||||
{
|
||||
uiPopupBlockHandle *parent_popup = handler->next->ui_userdata;
|
||||
ED_region_tag_refresh_ui(parent_popup->region);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WM_event_remove_ui_handler(handlers, ui_popup_handler, ui_popup_handler_remove, popup, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -557,6 +557,7 @@ struct uiPopupBlockHandle {
|
|||
struct uiKeyNavLock keynav_state;
|
||||
|
||||
/* for operator popups */
|
||||
struct wmOperator *popup_op;
|
||||
struct wmOperatorType *optype;
|
||||
ScrArea *ctx_area;
|
||||
ARegion *ctx_region;
|
||||
|
|
|
@ -3317,7 +3317,7 @@ void UI_popup_block_invoke(bContext *C, uiBlockCreateFunc func, void *arg)
|
|||
UI_popup_block_invoke_ex(C, func, arg, NULL, WM_OP_INVOKE_DEFAULT);
|
||||
}
|
||||
|
||||
void UI_popup_block_ex(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg)
|
||||
void UI_popup_block_ex(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg, wmOperator *op)
|
||||
{
|
||||
wmWindow *window = CTX_wm_window(C);
|
||||
uiPopupBlockHandle *handle;
|
||||
|
@ -3326,6 +3326,7 @@ void UI_popup_block_ex(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc po
|
|||
handle->popup = true;
|
||||
handle->retvalue = 1;
|
||||
|
||||
handle->popup_op = op;
|
||||
handle->popup_arg = arg;
|
||||
handle->popup_func = popup_func;
|
||||
handle->cancel_func = cancel_func;
|
||||
|
|
|
@ -127,12 +127,10 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
|
|||
break;
|
||||
case PROP_POINTER:
|
||||
{
|
||||
PointerRNA pptr;
|
||||
|
||||
pptr = RNA_property_pointer_get(ptr, prop);
|
||||
if (!pptr.type)
|
||||
pptr.type = RNA_property_pointer_type(ptr, prop);
|
||||
icon = RNA_struct_ui_icon(pptr.type);
|
||||
if (icon == 0) {
|
||||
PointerRNA pptr = RNA_property_pointer_get(ptr, prop);
|
||||
icon = RNA_struct_ui_icon(pptr.type ? pptr.type : RNA_property_pointer_type(ptr, prop));
|
||||
}
|
||||
if (icon == ICON_DOT)
|
||||
icon = 0;
|
||||
|
||||
|
|
|
@ -1400,6 +1400,8 @@ static bool view3d_localview_init(
|
|||
}
|
||||
}
|
||||
|
||||
DAG_on_visible_update(bmain, false);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
|
|
@ -277,6 +277,7 @@ typedef struct MirrorModifierData {
|
|||
short axis DNA_DEPRECATED; /* deprecated, use flag instead */
|
||||
short flag;
|
||||
float tolerance;
|
||||
float uv_offset[2];
|
||||
struct Object *mirror_ob;
|
||||
} MirrorModifierData;
|
||||
|
||||
|
|
|
@ -1526,6 +1526,20 @@ static void rna_def_modifier_mirror(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Mirror V", "Mirror the V texture coordinate around the 0.5 point");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "mirror_offset_u", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "uv_offset[0]");
|
||||
RNA_def_property_range(prop, -1, 1);
|
||||
RNA_def_property_ui_range(prop, -1, 1, 2, 4);
|
||||
RNA_def_property_ui_text(prop, "U Offset", "Amount to offset mirrored UVs from the 0.5 point on the U axis");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "mirror_offset_v", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "uv_offset[1]");
|
||||
RNA_def_property_range(prop, -1, 1);
|
||||
RNA_def_property_ui_range(prop, -1, 1, 2, 4);
|
||||
RNA_def_property_ui_text(prop, "V Offset", "Amount to offset mirrored UVs from the 0.5 point on the V axis");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "merge_threshold", PROP_FLOAT, PROP_DISTANCE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "tolerance");
|
||||
RNA_def_property_range(prop, 0, FLT_MAX);
|
||||
|
|
|
@ -259,8 +259,8 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
|
|||
int j = maxLoops;
|
||||
dmloopuv += j; /* second set of loops only */
|
||||
for (; j-- > 0; dmloopuv++) {
|
||||
if (do_mirr_u) dmloopuv->uv[0] = 1.0f - dmloopuv->uv[0];
|
||||
if (do_mirr_v) dmloopuv->uv[1] = 1.0f - dmloopuv->uv[1];
|
||||
if (do_mirr_u) dmloopuv->uv[0] = 1.0f - dmloopuv->uv[0] + mmd->uv_offset[0];
|
||||
if (do_mirr_v) dmloopuv->uv[1] = 1.0f - dmloopuv->uv[1] + mmd->uv_offset[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1562,6 +1562,11 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op)
|
|||
RNA_property_string_get(op->ptr, prop_app_template, app_template_buf);
|
||||
app_template = app_template_buf;
|
||||
}
|
||||
else if (!use_factory_settings) {
|
||||
/* TODO: dont reset prefs on 'New File' */
|
||||
BLI_strncpy(app_template_buf, U.app_template, sizeof(app_template_buf));
|
||||
app_template = app_template_buf;
|
||||
}
|
||||
else {
|
||||
app_template = NULL;
|
||||
}
|
||||
|
|
|
@ -1432,20 +1432,6 @@ static void dialog_exec_cb(bContext *C, void *arg1, void *arg2)
|
|||
}
|
||||
}
|
||||
|
||||
static void popup_check_cb(bContext *C, void *op_ptr, void *UNUSED(arg))
|
||||
{
|
||||
wmOperator *op = op_ptr;
|
||||
if (op->type->check) {
|
||||
if (op->type->check(C, op)) {
|
||||
/* check for popup and re-layout buttons */
|
||||
ARegion *ar_menu = CTX_wm_menu(C);
|
||||
if (ar_menu) {
|
||||
ED_region_tag_refresh_ui(ar_menu);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Dialogs are popups that require user verification (click OK) before exec */
|
||||
static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData)
|
||||
{
|
||||
|
@ -1464,8 +1450,6 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData)
|
|||
|
||||
layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style);
|
||||
|
||||
UI_block_func_set(block, popup_check_cb, op, NULL);
|
||||
|
||||
uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE);
|
||||
|
||||
/* clear so the OK button is left alone */
|
||||
|
@ -1504,8 +1488,6 @@ static uiBlock *wm_operator_ui_create(bContext *C, ARegion *ar, void *userData)
|
|||
|
||||
layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style);
|
||||
|
||||
UI_block_func_set(block, popup_check_cb, op, NULL);
|
||||
|
||||
/* since ui is defined the auto-layout args are not used */
|
||||
uiLayoutOperatorButs(C, layout, op, NULL, 'V', 0);
|
||||
|
||||
|
@ -1552,7 +1534,7 @@ int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height)
|
|||
data->width = width;
|
||||
data->height = height;
|
||||
data->free_op = true; /* if this runs and gets registered we may want not to free it */
|
||||
UI_popup_block_ex(C, wm_operator_ui_create, NULL, wm_operator_ui_popup_cancel, data);
|
||||
UI_popup_block_ex(C, wm_operator_ui_create, NULL, wm_operator_ui_popup_cancel, data, op);
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
|
@ -1582,7 +1564,7 @@ static int wm_operator_props_popup_ex(bContext *C, wmOperator *op,
|
|||
if (!do_redo || !(U.uiflag & USER_GLOBALUNDO))
|
||||
return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, UI_UNIT_Y);
|
||||
|
||||
UI_popup_block_ex(C, wm_block_create_redo, NULL, wm_block_redo_cancel_cb, op);
|
||||
UI_popup_block_ex(C, wm_block_create_redo, NULL, wm_block_redo_cancel_cb, op, op);
|
||||
|
||||
if (do_call)
|
||||
wm_block_redo_cb(C, op, 0);
|
||||
|
@ -1624,7 +1606,7 @@ int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width, int h
|
|||
data->free_op = true; /* if this runs and gets registered we may want not to free it */
|
||||
|
||||
/* op is not executed until popup OK but is clicked */
|
||||
UI_popup_block_ex(C, wm_block_dialog_create, wm_operator_ui_popup_ok, wm_operator_ui_popup_cancel, data);
|
||||
UI_popup_block_ex(C, wm_block_dialog_create, wm_operator_ui_popup_ok, wm_operator_ui_popup_cancel, data, op);
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue