Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Montagne <b.mont29@gmail.com>2020-02-26 16:15:35 +0300
committerBastien Montagne <b.mont29@gmail.com>2020-02-26 17:02:20 +0300
commit76f381ff4211885a0069dc4e992fce5fd6b54164 (patch)
tree4389142419ffa757eac30af902674d60457dd98b
parenta5ddb3df3b57090799cb389462e9d1f0c8f4cf94 (diff)
parent28a16c4374df1bdca7e7bce3f4353dae088ab1bf (diff)
Ensure IDs get unique memory addresses withing q given editing session.
Disclaimer: this should be considered as an engeneering, explanatory patch. Rational: for undo work, we are now manipulating IDs from potentially many different 'memory realms' (in contrast to current undo system, where, since we always reallocate the whole main database at each undo step, we only ever have to deal with two, the old one from the memfile, and the new one from re-read data from that memfile). So far, new undo system has used ID names-based search to remap old to new pointers, but this is slower, less safe, and forces us to do full undo barrier e.g. when renaming an ID. Idea of this patch is instead to ensure that within a given editing session, we never ever allocate a data-block at the same address twice. That way, we can consider ID pointers as valid UIDs withing that scope, and use their values to handle remapping in udo steps even in case an ID has had several memory addresses in the history of the editing session. This patches does two things: # Add a way to ensure a newly allocated ID gets a memory address never used before for any ID. # Store the history of all memory addresses ever used by a given ID. Note that point 1 above is currently using a fairly simple and naive solution, but also quiet innefficient (just allocating again and again until we get a 'free' address), we can imagine a much more efficient solution if we go deeper in MEM_ allocator system itself. Not sure if it is worth it though, as with new undo system actual re-allocation of a same ID at a different address should be fairly rare (i.e. history of used/forbidden addresses should remain quiet short). Differential Revision: https://developer.blender.org/D6937
-rw-r--r--doc/python_api/sphinx_doc_gen.py4
-rw-r--r--intern/cycles/device/cuda/device_cuda.h5
-rw-r--r--intern/cycles/device/cuda/device_cuda_impl.cpp53
-rw-r--r--intern/cycles/kernel/kernel_film.h12
-rw-r--r--intern/cycles/render/session.cpp2
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp2
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py18
-rw-r--r--source/blender/alembic/intern/alembic_capi.cc1
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h14
-rw-r--r--source/blender/blenkernel/BKE_cdderivedmesh.h43
-rw-r--r--source/blender/blenkernel/BKE_mesh.h2
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h13
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c11
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c125
-rw-r--r--source/blender/blenkernel/intern/constraint.c196
-rw-r--r--source/blender/blenkernel/intern/displist.c9
-rw-r--r--source/blender/blenkernel/intern/editmesh.c3
-rw-r--r--source/blender/blenkernel/intern/lattice.c1
-rw-r--r--source/blender/blenkernel/intern/modifier.c1
-rw-r--r--source/blender/blenkernel/intern/particle.c1
-rw-r--r--source/blender/blenkernel/intern/pbvh.c137
-rw-r--r--source/blender/blenkernel/intern/subdiv_ccg.c4
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c4
-rw-r--r--source/blender/blenlib/BLI_fileops.h4
-rw-r--r--source/blender/blenlib/intern/delaunay_2d.c4
-rw-r--r--source/blender/blenlib/intern/storage.c57
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_relation.cc4
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c2
-rw-r--r--source/blender/editors/interface/view2d.c2
-rw-r--r--source/blender/editors/mesh/editmesh_knife_project.c1
-rw-r--r--source/blender/editors/object/object_constraint.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c5
-rw-r--r--source/blender/editors/space_file/fsmenu.c235
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c2
-rw-r--r--source/blender/makesdna/DNA_layer_types.h1
-rw-r--r--source/blender/makesrna/RNA_types.h2
-rw-r--r--source/blender/makesrna/intern/rna_access.c16
-rw-r--r--source/blender/makesrna/intern/rna_image.c4
-rw-r--r--source/blender/makesrna/intern/rna_scene.c2
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c4
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c1
-rw-r--r--source/blender/modifiers/intern/MOD_fluid.c1
-rw-r--r--source/blender/modifiers/intern/MOD_subsurf.c1
-rw-r--r--source/blender/modifiers/intern/MOD_weighted_normal.c3
-rw-r--r--tests/python/bl_constraints.py39
47 files changed, 609 insertions, 449 deletions
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py
index b74ad3c7dc2..60058d5d17f 100644
--- a/doc/python_api/sphinx_doc_gen.py
+++ b/doc/python_api/sphinx_doc_gen.py
@@ -223,6 +223,7 @@ else:
"aud",
"bgl",
"blf",
+ "imbuf",
"bmesh",
"bmesh.ops",
"bmesh.types",
@@ -1779,7 +1780,7 @@ def write_rst_contents(basepath):
standalone_modules = (
# submodules are added in parent page
- "mathutils", "freestyle", "bgl", "blf", "gpu", "gpu_extras",
+ "mathutils", "freestyle", "bgl", "blf", "imbuf", "gpu", "gpu_extras",
"aud", "bpy_extras", "idprop.types", "bmesh",
)
@@ -1886,6 +1887,7 @@ def write_rst_importable_modules(basepath):
# C_modules
"aud": "Audio System",
"blf": "Font Drawing",
+ "imbuf": "Image Buffer",
"gpu": "GPU Shader Module",
"gpu.types": "GPU Types",
"gpu.matrix": "GPU Matrix",
diff --git a/intern/cycles/device/cuda/device_cuda.h b/intern/cycles/device/cuda/device_cuda.h
index 5820b525fd6..a825bd6b128 100644
--- a/intern/cycles/device/cuda/device_cuda.h
+++ b/intern/cycles/device/cuda/device_cuda.h
@@ -82,11 +82,6 @@ class CUDADevice : public Device {
device_vector<TextureInfo> texture_info;
bool need_texture_info;
- CUdeviceptr cuda_device_ptr(device_ptr mem)
- {
- return (CUdeviceptr)mem;
- }
-
static bool have_precompiled_kernels();
virtual bool show_samples() const;
diff --git a/intern/cycles/device/cuda/device_cuda_impl.cpp b/intern/cycles/device/cuda/device_cuda_impl.cpp
index 5c25d7b0208..f6a4f93a690 100644
--- a/intern/cycles/device/cuda/device_cuda_impl.cpp
+++ b/intern/cycles/device/cuda/device_cuda_impl.cpp
@@ -829,18 +829,17 @@ CUDADevice::CUDAMem *CUDADevice::generic_alloc(device_memory &mem, size_t pitch_
void CUDADevice::generic_copy_to(device_memory &mem)
{
- if (mem.host_pointer && mem.device_pointer) {
- CUDAContextScope scope(this);
-
- /* If use_mapped_host of mem is false, the current device only
- * uses device memory allocated by cuMemAlloc regardless of
- * mem.host_pointer and mem.shared_pointer, and should copy
- * data from mem.host_pointer. */
+ if (!mem.host_pointer || !mem.device_pointer) {
+ return;
+ }
- if (cuda_mem_map[&mem].use_mapped_host == false || mem.host_pointer != mem.shared_pointer) {
- cuda_assert(
- cuMemcpyHtoD(cuda_device_ptr(mem.device_pointer), mem.host_pointer, mem.memory_size()));
- }
+ /* If use_mapped_host of mem is false, the current device only uses device memory allocated by
+ * cuMemAlloc regardless of mem.host_pointer and mem.shared_pointer, and should copy data from
+ * mem.host_pointer. */
+ if (!cuda_mem_map[&mem].use_mapped_host || mem.host_pointer != mem.shared_pointer) {
+ const CUDAContextScope scope(this);
+ cuda_assert(
+ cuMemcpyHtoD((CUdeviceptr)mem.device_pointer, mem.host_pointer, mem.memory_size()));
}
}
@@ -947,7 +946,7 @@ void CUDADevice::mem_zero(device_memory &mem)
* regardless of mem.host_pointer and mem.shared_pointer. */
if (!cuda_mem_map[&mem].use_mapped_host || mem.host_pointer != mem.shared_pointer) {
const CUDAContextScope scope(this);
- cuda_assert(cuMemsetD8(cuda_device_ptr(mem.device_pointer), 0, mem.memory_size()));
+ cuda_assert(cuMemsetD8((CUdeviceptr)mem.device_pointer, 0, mem.memory_size()));
}
else if (mem.host_pointer) {
memset(mem.host_pointer, 0, mem.memory_size());
@@ -1273,7 +1272,7 @@ bool CUDADevice::denoising_non_local_means(device_ptr image_ptr,
if (have_error())
return false;
- CUdeviceptr difference = cuda_device_ptr(task->buffer.temporary_mem.device_pointer);
+ CUdeviceptr difference = (CUdeviceptr)task->buffer.temporary_mem.device_pointer;
CUdeviceptr blurDifference = difference + sizeof(float) * pass_stride * num_shifts;
CUdeviceptr weightAccum = difference + 2 * sizeof(float) * pass_stride * num_shifts;
CUdeviceptr scale_ptr = 0;
@@ -1405,7 +1404,7 @@ bool CUDADevice::denoising_accumulate(device_ptr color_ptr,
if (have_error())
return false;
- CUdeviceptr difference = cuda_device_ptr(task->buffer.temporary_mem.device_pointer);
+ CUdeviceptr difference = (CUdeviceptr)task->buffer.temporary_mem.device_pointer;
CUdeviceptr blurDifference = difference + sizeof(float) * pass_stride * num_shifts;
CUfunction cuNLMCalcDifference, cuNLMBlur, cuNLMCalcWeight, cuNLMConstructGramian;
@@ -1703,7 +1702,7 @@ void CUDADevice::path_trace(DeviceTask &task,
wtile->h = rtile.h;
wtile->offset = rtile.offset;
wtile->stride = rtile.stride;
- wtile->buffer = (float *)cuda_device_ptr(rtile.buffer);
+ wtile->buffer = (float *)(CUdeviceptr)rtile.buffer;
/* Prepare work size. More step samples render faster, but for now we
* remain conservative for GPUs connected to a display to avoid driver
@@ -1727,7 +1726,7 @@ void CUDADevice::path_trace(DeviceTask &task,
wtile->num_samples = min(step_samples, end_sample - sample);
work_tiles.copy_to_device();
- CUdeviceptr d_work_tiles = cuda_device_ptr(work_tiles.device_pointer);
+ CUdeviceptr d_work_tiles = (CUdeviceptr)work_tiles.device_pointer;
uint total_work_size = wtile->w * wtile->h * wtile->num_samples;
uint num_blocks = divide_up(total_work_size, num_threads_per_block);
@@ -1762,7 +1761,7 @@ void CUDADevice::film_convert(DeviceTask &task,
CUfunction cuFilmConvert;
CUdeviceptr d_rgba = map_pixels((rgba_byte) ? rgba_byte : rgba_half);
- CUdeviceptr d_buffer = cuda_device_ptr(buffer);
+ CUdeviceptr d_buffer = (CUdeviceptr)buffer;
/* get kernel function */
if (rgba_half) {
@@ -1823,8 +1822,8 @@ void CUDADevice::shader(DeviceTask &task)
CUDAContextScope scope(this);
CUfunction cuShader;
- CUdeviceptr d_input = cuda_device_ptr(task.shader_input);
- CUdeviceptr d_output = cuda_device_ptr(task.shader_output);
+ CUdeviceptr d_input = (CUdeviceptr)task.shader_input;
+ CUdeviceptr d_output = (CUdeviceptr)task.shader_output;
/* get kernel function */
if (task.shader_eval_type >= SHADER_EVAL_BAKE) {
@@ -1907,7 +1906,7 @@ CUdeviceptr CUDADevice::map_pixels(device_ptr mem)
return buffer;
}
- return cuda_device_ptr(mem);
+ return (CUdeviceptr)mem;
}
void CUDADevice::unmap_pixels(device_ptr mem)
@@ -2347,7 +2346,7 @@ uint64_t CUDASplitKernel::state_buffer_size(device_memory & /*kg*/,
size_buffer.zero_to_device();
uint threads = num_threads;
- CUdeviceptr d_size = device->cuda_device_ptr(size_buffer.device_pointer);
+ CUdeviceptr d_size = (CUdeviceptr)size_buffer.device_pointer;
struct args_t {
uint *num_threads;
@@ -2382,13 +2381,13 @@ bool CUDASplitKernel::enqueue_split_kernel_data_init(const KernelDimensions &dim
{
CUDAContextScope scope(device);
- CUdeviceptr d_split_data = device->cuda_device_ptr(split_data.device_pointer);
- CUdeviceptr d_ray_state = device->cuda_device_ptr(ray_state.device_pointer);
- CUdeviceptr d_queue_index = device->cuda_device_ptr(queue_index.device_pointer);
- CUdeviceptr d_use_queues_flag = device->cuda_device_ptr(use_queues_flag.device_pointer);
- CUdeviceptr d_work_pool_wgs = device->cuda_device_ptr(work_pool_wgs.device_pointer);
+ CUdeviceptr d_split_data = (CUdeviceptr)split_data.device_pointer;
+ CUdeviceptr d_ray_state = (CUdeviceptr)ray_state.device_pointer;
+ CUdeviceptr d_queue_index = (CUdeviceptr)queue_index.device_pointer;
+ CUdeviceptr d_use_queues_flag = (CUdeviceptr)use_queues_flag.device_pointer;
+ CUdeviceptr d_work_pool_wgs = (CUdeviceptr)work_pool_wgs.device_pointer;
- CUdeviceptr d_buffer = device->cuda_device_ptr(rtile.buffer);
+ CUdeviceptr d_buffer = (CUdeviceptr)rtile.buffer;
int end_sample = rtile.start_sample + rtile.num_samples;
int queue_size = dim.global_size[0] * dim.global_size[1];
diff --git a/intern/cycles/kernel/kernel_film.h b/intern/cycles/kernel/kernel_film.h
index fc3a6152b79..3829426f261 100644
--- a/intern/cycles/kernel/kernel_film.h
+++ b/intern/cycles/kernel/kernel_film.h
@@ -40,15 +40,9 @@ ccl_device float4 film_get_pass_result(KernelGlobals *kg,
if (display_divide_pass_stride != -1) {
ccl_global float4 *divide_in = (ccl_global float4 *)(buffer + display_divide_pass_stride +
index * kernel_data.film.pass_stride);
- if (divide_in->x != 0.0f) {
- pass_result.x /= divide_in->x;
- }
- if (divide_in->y != 0.0f) {
- pass_result.y /= divide_in->y;
- }
- if (divide_in->z != 0.0f) {
- pass_result.z /= divide_in->z;
- }
+ float3 divided = safe_divide_even_color(float4_to_float3(pass_result),
+ float4_to_float3(*divide_in));
+ pass_result = make_float4(divided.x, divided.y, divided.z, pass_result.w);
}
if (kernel_data.film.use_display_exposure) {
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index ae0a2cf863a..f45e6d68c97 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -629,7 +629,7 @@ void Session::run_cpu()
}
/* Don't go in pause mode when preview kernels are used
- * When feature kernels become available the session will be resetted. */
+ * When feature kernels become available the session will be reset. */
else if (no_tiles && kernel_state == DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL) {
time_sleep(0.1);
}
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index 89a2578bd5a..60d08305621 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -1438,7 +1438,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
* around tablet surface */
window->GetTabletData().Active = xtablet.mode;
- /* Note: This event might be generated with incomplete dataset
+ /* Note: This event might be generated with incomplete data-set
* (don't exactly know why, looks like in some cases, if the value does not change,
* it is not included in subsequent XDeviceMotionEvent events).
* So we have to check which values this event actually contains!
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index e92490bcbdc..1dc5afe7c5e 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -4329,6 +4329,23 @@ class VIEW3D_MT_edit_font(Menu):
layout.operator("font.style_toggle", text="Toggle Underline", icon='UNDERLINE').style = 'UNDERLINE'
layout.operator("font.style_toggle", text="Toggle Small Caps", icon='SMALL_CAPS').style = 'SMALL_CAPS'
+ layout.menu("VIEW3D_MT_edit_font_kerning")
+
+
+class VIEW3D_MT_edit_font_kerning(Menu):
+ bl_label = "Kerning"
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.active_object
+ text = ob.data
+ kerning = text.edit_format.kerning
+
+ layout.operator("font.change_spacing", text="Decrease Kerning").delta = -1
+ layout.operator("font.change_spacing", text="Increase Kerning").delta = 1
+ layout.operator("font.change_spacing", text="Reset Kerning").delta = -kerning
+
class VIEW3D_MT_edit_text_chars(Menu):
bl_label = "Special Characters"
@@ -7105,6 +7122,7 @@ classes = (
VIEW3D_MT_edit_curve_showhide,
VIEW3D_MT_edit_surface,
VIEW3D_MT_edit_font,
+ VIEW3D_MT_edit_font_kerning,
VIEW3D_MT_edit_text_chars,
VIEW3D_MT_edit_meta,
VIEW3D_MT_edit_meta_showhide,
diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc
index 6c7ab4d4b87..c6f9e284d53 100644
--- a/source/blender/alembic/intern/alembic_capi.cc
+++ b/source/blender/alembic/intern/alembic_capi.cc
@@ -48,7 +48,6 @@ extern "C" {
#include "DNA_scene_types.h"
#include "BKE_cachefile.h"
-#include "BKE_cdderivedmesh.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_global.h"
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index a5226dfa947..575fdc4b8ff 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -116,11 +116,8 @@ struct DerivedMesh {
int numVertData, numEdgeData, numTessFaceData, numLoopData, numPolyData;
int needsFree; /* checked on ->release, is set to 0 for cached results */
int deformedOnly; /* set by modifier stack if only deformed from original */
- BVHCache *bvhCache;
DerivedMeshType type;
DMDirtyFlag dirty;
- int totmat; /* total materials. Will be valid only before object drawing. */
- struct Material **mat; /* material array. Will be valid only before object drawing */
/**
* \warning Typical access is done via #getLoopTriArray, #getNumLoopTri.
@@ -222,11 +219,6 @@ struct DerivedMesh {
CustomData *(*getLoopDataLayout)(DerivedMesh *dm);
CustomData *(*getPolyDataLayout)(DerivedMesh *dm);
- /** Copies all customdata for an element source into dst at index dest */
- void (*copyFromVertCData)(DerivedMesh *dm, int source, CustomData *dst, int dest);
- void (*copyFromEdgeCData)(DerivedMesh *dm, int source, CustomData *dst, int dest);
- void (*copyFromFaceCData)(DerivedMesh *dm, int source, CustomData *dst, int dest);
-
/** Optional grid access for subsurf */
int (*getNumGrids)(DerivedMesh *dm);
int (*getGridSize)(DerivedMesh *dm);
@@ -236,12 +228,6 @@ struct DerivedMesh {
DMFlagMat *(*getGridFlagMats)(DerivedMesh *dm);
unsigned int **(*getGridHidden)(DerivedMesh *dm);
- /** Iterate over all vertex points, calling DO_MINMAX with given args.
- *
- * Also called in Editmode
- */
- void (*getMinMax)(DerivedMesh *dm, float r_min[3], float r_max[3]);
-
/** Direct Access Operations
* - Can be undefined
* - Must be defined for modifiers that only deform however */
diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h
index d39850a162b..7b84f2f04ab 100644
--- a/source/blender/blenkernel/BKE_cdderivedmesh.h
+++ b/source/blender/blenkernel/BKE_cdderivedmesh.h
@@ -22,59 +22,24 @@
* \section aboutcdderivedmesh CDDerivedMesh interface
* CDDerivedMesh (CD = Custom Data) is a DerivedMesh backend which stores
* mesh elements (vertices, edges and faces) as layers of custom element data.
+ *
+ * \note This is deprecated & should eventually be removed.
*/
#ifndef __BKE_CDDERIVEDMESH_H__
#define __BKE_CDDERIVEDMESH_H__
-#include "BKE_DerivedMesh.h"
-#include "BKE_customdata.h"
-
-struct BMEditMesh;
-struct CustomData_MeshMasks;
struct DerivedMesh;
struct Mesh;
-/* creates a new CDDerivedMesh */
-struct DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces, int numLoops, int numPolys);
-
/* creates a CDDerivedMesh from the given Mesh, this will reference the
* original data in Mesh, but it is safe to apply vertex coordinates or
* calculate normals as those functions will automatically create new
- * data to not overwrite the original */
+ * data to not overwrite the original. */
struct DerivedMesh *CDDM_from_mesh(struct Mesh *mesh);
-/* creates a CDDerivedMesh from the given Mesh with custom allocation type. */
-struct DerivedMesh *CDDM_from_mesh_ex(struct Mesh *mesh,
- eCDAllocType alloctype,
- const struct CustomData_MeshMasks *mask);
-
/* Copies the given DerivedMesh with verts, faces & edges stored as
- * custom element data.
- */
+ * custom element data. */
struct DerivedMesh *CDDM_copy(struct DerivedMesh *dm);
-void CDDM_recalc_looptri(struct DerivedMesh *dm);
-
-/* vertex/edge/face access functions
- * should always succeed if index is within bounds
- * note these return pointers - any change modifies the internals of the mesh
- */
-struct MVert *CDDM_get_vert(struct DerivedMesh *dm, int index);
-struct MEdge *CDDM_get_edge(struct DerivedMesh *dm, int index);
-struct MFace *CDDM_get_tessface(struct DerivedMesh *dm, int index);
-struct MLoop *CDDM_get_loop(struct DerivedMesh *dm, int index);
-struct MPoly *CDDM_get_poly(struct DerivedMesh *dm, int index);
-
-/* vertex/edge/face array access functions - return the array holding the
- * desired data
- * should always succeed
- * note these return pointers - any change modifies the internals of the mesh
- */
-struct MVert *CDDM_get_verts(struct DerivedMesh *dm);
-struct MEdge *CDDM_get_edges(struct DerivedMesh *dm);
-struct MFace *CDDM_get_tessfaces(struct DerivedMesh *dm);
-struct MLoop *CDDM_get_loops(struct DerivedMesh *dm);
-struct MPoly *CDDM_get_polys(struct DerivedMesh *dm);
-
#endif
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index d6934e8a7da..1bc70101803 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -129,7 +129,7 @@ struct Mesh *BKE_mesh_new_nomain_from_template_ex(const struct Mesh *me_src,
int tessface_len,
int loops_len,
int polys_len,
- CustomData_MeshMasks mask);
+ struct CustomData_MeshMasks mask);
void BKE_mesh_eval_delete(struct Mesh *me_eval);
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 9eb10d296de..a26148d11bf 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -66,13 +66,14 @@ typedef enum {
PBVH_UpdateDrawBuffers = 1 << 4,
PBVH_UpdateRedraw = 1 << 5,
PBVH_UpdateMask = 1 << 6,
+ PBVH_UpdateVisibility = 1 << 8,
- PBVH_RebuildDrawBuffers = 1 << 7,
- PBVH_FullyHidden = 1 << 8,
- PBVH_FullyMasked = 1 << 9,
- PBVH_FullyUnmasked = 1 << 10,
+ PBVH_RebuildDrawBuffers = 1 << 9,
+ PBVH_FullyHidden = 1 << 10,
+ PBVH_FullyMasked = 1 << 11,
+ PBVH_FullyUnmasked = 1 << 12,
- PBVH_UpdateTopology = 1 << 11,
+ PBVH_UpdateTopology = 1 << 13,
} PBVHNodeFlags;
typedef struct PBVHFrustumPlanes {
@@ -246,6 +247,7 @@ void BKE_pbvh_node_mark_update_mask(PBVHNode *node);
void BKE_pbvh_node_mark_rebuild_draw(PBVHNode *node);
void BKE_pbvh_node_mark_redraw(PBVHNode *node);
void BKE_pbvh_node_mark_normals_update(PBVHNode *node);
+void BKE_pbvh_node_mark_visibility_update(PBVHNode *node);
void BKE_pbvh_node_mark_topology_update(PBVHNode *node);
void BKE_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden);
void BKE_pbvh_node_fully_masked_set(PBVHNode *node, int fully_masked);
@@ -286,6 +288,7 @@ void BKE_pbvh_bmesh_after_stroke(PBVH *bvh);
void BKE_pbvh_update_bounds(PBVH *bvh, int flags);
void BKE_pbvh_update_vertex_data(PBVH *bvh, int flags);
+void BKE_pbvh_update_visibility(PBVH *bvh);
void BKE_pbvh_update_normals(PBVH *bvh, struct SubdivCCG *subdiv_ccg);
void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3]);
void BKE_pbvh_get_grid_updates(PBVH *bvh, bool clear, void ***r_gridfaces, int *r_totface);
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index c04079bed22..3006ab76032 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -43,7 +43,7 @@
#include "BLI_linklist.h"
#include "BLI_task.h"
-#include "BKE_cdderivedmesh.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_colorband.h"
#include "BKE_editmesh.h"
#include "BKE_key.h"
@@ -317,8 +317,6 @@ void DM_init_funcs(DerivedMesh *dm)
dm->getTessFaceDataArray = DM_get_tessface_data_layer;
dm->getPolyDataArray = DM_get_poly_data_layer;
dm->getLoopDataArray = DM_get_loop_data_layer;
-
- dm->bvhCache = NULL;
}
/**
@@ -411,19 +409,12 @@ void DM_from_template(DerivedMesh *dm,
int DM_release(DerivedMesh *dm)
{
if (dm->needsFree) {
- bvhcache_free(&dm->bvhCache);
CustomData_free(&dm->vertData, dm->numVertData);
CustomData_free(&dm->edgeData, dm->numEdgeData);
CustomData_free(&dm->faceData, dm->numTessFaceData);
CustomData_free(&dm->loopData, dm->numLoopData);
CustomData_free(&dm->polyData, dm->numPolyData);
- if (dm->mat) {
- MEM_freeN(dm->mat);
- dm->mat = NULL;
- dm->totmat = 0;
- }
-
MEM_SAFE_FREE(dm->looptris.array);
dm->looptris.num = 0;
dm->looptris.num_alloc = 0;
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 5fc4e909fac..8d79d106145 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -29,6 +29,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_pbvh.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_mesh.h"
@@ -150,22 +151,6 @@ static void cdDM_copyPolyArray(DerivedMesh *dm, MPoly *r_poly)
memcpy(r_poly, cddm->mpoly, sizeof(*r_poly) * dm->numPolyData);
}
-static void cdDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3])
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
- int i;
-
- if (dm->numVertData) {
- for (i = 0; i < dm->numVertData; i++) {
- minmax_v3v3_v3(r_min, r_max, cddm->mvert[i].co);
- }
- }
- else {
- zero_v3(r_min);
- zero_v3(r_max);
- }
-}
-
static void cdDM_getVertCo(DerivedMesh *dm, int index, float r_co[3])
{
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
@@ -193,7 +178,7 @@ static const MeshElemMap *cdDM_getPolyMap(Object *ob, DerivedMesh *dm)
return cddm->pmap;
}
-void CDDM_recalc_looptri(DerivedMesh *dm)
+static void cdDM_recalc_looptri(DerivedMesh *dm)
{
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
const unsigned int totpoly = dm->numPolyData;
@@ -240,8 +225,6 @@ static CDDerivedMesh *cdDM_create(const char *desc)
cddm = MEM_callocN(sizeof(*cddm), desc);
dm = &cddm->dm;
- dm->getMinMax = cdDM_getMinMax;
-
dm->getNumVerts = cdDM_getNumVerts;
dm->getNumEdges = cdDM_getNumEdges;
dm->getNumTessFaces = cdDM_getNumTessFaces;
@@ -265,7 +248,7 @@ static CDDerivedMesh *cdDM_create(const char *desc)
dm->getEdgeDataArray = DM_get_edge_data_layer;
dm->getTessFaceDataArray = DM_get_tessface_data_layer;
- dm->recalcLoopTri = CDDM_recalc_looptri;
+ dm->recalcLoopTri = cdDM_recalc_looptri;
dm->getVertCo = cdDM_getVertCo;
dm->getVertNo = cdDM_getVertNo;
@@ -277,41 +260,9 @@ static CDDerivedMesh *cdDM_create(const char *desc)
return cddm;
}
-DerivedMesh *CDDM_new(int numVerts, int numEdges, int numTessFaces, int numLoops, int numPolys)
-{
- CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
- DerivedMesh *dm = &cddm->dm;
-
- DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numTessFaces, numLoops, numPolys);
-
- CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
- CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
- CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numTessFaces);
- CustomData_add_layer(&dm->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, numPolys);
-
- CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
- CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
- CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numTessFaces);
- CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops);
- CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys);
-
- cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
- cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
- cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
- cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
- cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
-
- return dm;
-}
-
-DerivedMesh *CDDM_from_mesh(Mesh *mesh)
-{
- return CDDM_from_mesh_ex(mesh, CD_REFERENCE, &CD_MASK_MESH);
-}
-
-DerivedMesh *CDDM_from_mesh_ex(Mesh *mesh,
- eCDAllocType alloctype,
- const CustomData_MeshMasks *mask)
+static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
+ eCDAllocType alloctype,
+ const CustomData_MeshMasks *mask)
{
CDDerivedMesh *cddm = cdDM_create(__func__);
DerivedMesh *dm = &cddm->dm;
@@ -370,6 +321,11 @@ DerivedMesh *CDDM_from_mesh_ex(Mesh *mesh,
return dm;
}
+DerivedMesh *CDDM_from_mesh(Mesh *mesh)
+{
+ return cdDM_from_mesh_ex(mesh, CD_REFERENCE, &CD_MASK_MESH);
+}
+
DerivedMesh *CDDM_copy(DerivedMesh *source)
{
CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
@@ -415,62 +371,3 @@ DerivedMesh *CDDM_copy(DerivedMesh *source)
return dm;
}
-
-/* #define DEBUG_CLNORS */
-#ifdef DEBUG_CLNORS
-# include "BLI_linklist.h"
-#endif
-
-/* mesh element access functions */
-
-MVert *CDDM_get_vert(DerivedMesh *dm, int index)
-{
- return &((CDDerivedMesh *)dm)->mvert[index];
-}
-
-MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
-{
- return &((CDDerivedMesh *)dm)->medge[index];
-}
-
-MFace *CDDM_get_tessface(DerivedMesh *dm, int index)
-{
- return &((CDDerivedMesh *)dm)->mface[index];
-}
-
-MLoop *CDDM_get_loop(DerivedMesh *dm, int index)
-{
- return &((CDDerivedMesh *)dm)->mloop[index];
-}
-
-MPoly *CDDM_get_poly(DerivedMesh *dm, int index)
-{
- return &((CDDerivedMesh *)dm)->mpoly[index];
-}
-
-/* array access functions */
-
-MVert *CDDM_get_verts(DerivedMesh *dm)
-{
- return ((CDDerivedMesh *)dm)->mvert;
-}
-
-MEdge *CDDM_get_edges(DerivedMesh *dm)
-{
- return ((CDDerivedMesh *)dm)->medge;
-}
-
-MFace *CDDM_get_tessfaces(DerivedMesh *dm)
-{
- return ((CDDerivedMesh *)dm)->mface;
-}
-
-MLoop *CDDM_get_loops(DerivedMesh *dm)
-{
- return ((CDDerivedMesh *)dm)->mloop;
-}
-
-MPoly *CDDM_get_polys(DerivedMesh *dm)
-{
- return ((CDDerivedMesh *)dm)->mpoly;
-}
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 42efd9a7057..8ba746e3493 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -855,95 +855,97 @@ static void childof_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
bConstraintTarget *ct = targets->first;
/* only evaluate if there is a target */
- if (VALID_CONS_TARGET(ct)) {
- float parmat[4][4];
+ if (!VALID_CONS_TARGET(ct)) {
+ return;
+ }
- /* simple matrix parenting */
- if (data->flag == CHILDOF_ALL) {
+ float parmat[4][4];
- /* multiply target (parent matrix) by offset (parent inverse) to get
- * the effect of the parent that will be exerted on the owner
- */
- mul_m4_m4m4(parmat, ct->matrix, data->invmat);
+ /* simple matrix parenting */
+ if (data->flag == CHILDOF_ALL) {
- /* now multiply the parent matrix by the owner matrix to get the
- * the effect of this constraint (i.e. owner is 'parented' to parent)
- */
- mul_m4_m4m4(cob->matrix, parmat, cob->matrix);
- }
- else {
- float invmat[4][4], tempmat[4][4];
- float loc[3], eul[3], size[3];
- float loco[3], eulo[3], sizo[3];
+ /* multiply target (parent matrix) by offset (parent inverse) to get
+ * the effect of the parent that will be exerted on the owner
+ */
+ mul_m4_m4m4(parmat, ct->matrix, data->invmat);
- /* get offset (parent-inverse) matrix */
- copy_m4_m4(invmat, data->invmat);
+ /* now multiply the parent matrix by the owner matrix to get the
+ * the effect of this constraint (i.e. owner is 'parented' to parent)
+ */
+ mul_m4_m4m4(cob->matrix, parmat, cob->matrix);
+ }
+ else {
+ float invmat[4][4], tempmat[4][4];
+ float loc[3], eul[3], size[3];
+ float loco[3], eulo[3], sizo[3];
- /* extract components of both matrices */
- copy_v3_v3(loc, ct->matrix[3]);
- mat4_to_eulO(eul, ct->rotOrder, ct->matrix);
- mat4_to_size(size, ct->matrix);
+ /* get offset (parent-inverse) matrix */
+ copy_m4_m4(invmat, data->invmat);
- copy_v3_v3(loco, invmat[3]);
- mat4_to_eulO(eulo, cob->rotOrder, invmat);
- mat4_to_size(sizo, invmat);
+ /* extract components of both matrices */
+ copy_v3_v3(loc, ct->matrix[3]);
+ mat4_to_eulO(eul, ct->rotOrder, ct->matrix);
+ mat4_to_size(size, ct->matrix);
- /* disable channels not enabled */
- if (!(data->flag & CHILDOF_LOCX)) {
- loc[0] = loco[0] = 0.0f;
- }
- if (!(data->flag & CHILDOF_LOCY)) {
- loc[1] = loco[1] = 0.0f;
- }
- if (!(data->flag & CHILDOF_LOCZ)) {
- loc[2] = loco[2] = 0.0f;
- }
- if (!(data->flag & CHILDOF_ROTX)) {
- eul[0] = eulo[0] = 0.0f;
- }
- if (!(data->flag & CHILDOF_ROTY)) {
- eul[1] = eulo[1] = 0.0f;
- }
- if (!(data->flag & CHILDOF_ROTZ)) {
- eul[2] = eulo[2] = 0.0f;
- }
- if (!(data->flag & CHILDOF_SIZEX)) {
- size[0] = sizo[0] = 1.0f;
- }
- if (!(data->flag & CHILDOF_SIZEY)) {
- size[1] = sizo[1] = 1.0f;
- }
- if (!(data->flag & CHILDOF_SIZEZ)) {
- size[2] = sizo[2] = 1.0f;
- }
+ copy_v3_v3(loco, invmat[3]);
+ mat4_to_eulO(eulo, cob->rotOrder, invmat);
+ mat4_to_size(sizo, invmat);
+
+ /* disable channels not enabled */
+ if (!(data->flag & CHILDOF_LOCX)) {
+ loc[0] = loco[0] = 0.0f;
+ }
+ if (!(data->flag & CHILDOF_LOCY)) {
+ loc[1] = loco[1] = 0.0f;
+ }
+ if (!(data->flag & CHILDOF_LOCZ)) {
+ loc[2] = loco[2] = 0.0f;
+ }
+ if (!(data->flag & CHILDOF_ROTX)) {
+ eul[0] = eulo[0] = 0.0f;
+ }
+ if (!(data->flag & CHILDOF_ROTY)) {
+ eul[1] = eulo[1] = 0.0f;
+ }
+ if (!(data->flag & CHILDOF_ROTZ)) {
+ eul[2] = eulo[2] = 0.0f;
+ }
+ if (!(data->flag & CHILDOF_SIZEX)) {
+ size[0] = sizo[0] = 1.0f;
+ }
+ if (!(data->flag & CHILDOF_SIZEY)) {
+ size[1] = sizo[1] = 1.0f;
+ }
+ if (!(data->flag & CHILDOF_SIZEZ)) {
+ size[2] = sizo[2] = 1.0f;
+ }
- /* make new target mat and offset mat */
- loc_eulO_size_to_mat4(ct->matrix, loc, eul, size, ct->rotOrder);
- loc_eulO_size_to_mat4(invmat, loco, eulo, sizo, cob->rotOrder);
+ /* make new target mat and offset mat */
+ loc_eulO_size_to_mat4(ct->matrix, loc, eul, size, ct->rotOrder);
+ loc_eulO_size_to_mat4(invmat, loco, eulo, sizo, cob->rotOrder);
- /* multiply target (parent matrix) by offset (parent inverse) to get
- * the effect of the parent that will be exerted on the owner
- */
- mul_m4_m4m4(parmat, ct->matrix, invmat);
+ /* multiply target (parent matrix) by offset (parent inverse) to get
+ * the effect of the parent that will be exerted on the owner
+ */
+ mul_m4_m4m4(parmat, ct->matrix, invmat);
- /* now multiply the parent matrix by the owner matrix to get the
- * the effect of this constraint (i.e. owner is 'parented' to parent)
- */
- copy_m4_m4(tempmat, cob->matrix);
- mul_m4_m4m4(cob->matrix, parmat, tempmat);
-
- /* without this, changes to scale and rotation can change location
- * of a parentless bone or a disconnected bone. Even though its set
- * to zero above. */
- if (!(data->flag & CHILDOF_LOCX)) {
- cob->matrix[3][0] = tempmat[3][0];
- }
- if (!(data->flag & CHILDOF_LOCY)) {
- cob->matrix[3][1] = tempmat[3][1];
- }
- if (!(data->flag & CHILDOF_LOCZ)) {
- cob->matrix[3][2] = tempmat[3][2];
- }
+ /* now multiply the parent matrix by the owner matrix to get the
+ * the effect of this constraint (i.e. owner is 'parented' to parent)
+ */
+ copy_m4_m4(tempmat, cob->matrix);
+ mul_m4_m4m4(cob->matrix, parmat, tempmat);
+
+ /* without this, changes to scale and rotation can change location
+ * of a parentless bone or a disconnected bone. Even though its set
+ * to zero above. */
+ if (!(data->flag & CHILDOF_LOCX)) {
+ cob->matrix[3][0] = tempmat[3][0];
+ }
+ if (!(data->flag & CHILDOF_LOCY)) {
+ cob->matrix[3][1] = tempmat[3][1];
+ }
+ if (!(data->flag & CHILDOF_LOCZ)) {
+ cob->matrix[3][2] = tempmat[3][2];
}
}
}
@@ -4877,37 +4879,35 @@ static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
if (data->flag & OBJECTSOLVER_ACTIVECLIP) {
clip = scene->clip;
}
-
if (!camob || !clip) {
return;
}
- if (clip) {
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *object;
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *object;
- object = BKE_tracking_object_get_named(tracking, data->object);
+ object = BKE_tracking_object_get_named(tracking, data->object);
+ if (!object) {
+ return;
+ }
- if (object) {
- float mat[4][4], obmat[4][4], imat[4][4], cammat[4][4], camimat[4][4], parmat[4][4];
- float ctime = DEG_get_ctime(depsgraph);
- float framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime);
+ float mat[4][4], obmat[4][4], imat[4][4], cammat[4][4], camimat[4][4], parmat[4][4];
+ float ctime = DEG_get_ctime(depsgraph);
+ float framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime);
- BKE_object_where_is_calc_mat4(camob, cammat);
+ BKE_object_where_is_calc_mat4(camob, cammat);
- BKE_tracking_camera_get_reconstructed_interpolate(tracking, object, framenr, mat);
+ BKE_tracking_camera_get_reconstructed_interpolate(tracking, object, framenr, mat);
- invert_m4_m4(camimat, cammat);
- mul_m4_m4m4(parmat, cammat, data->invmat);
+ invert_m4_m4(camimat, cammat);
+ mul_m4_m4m4(parmat, cammat, data->invmat);
- copy_m4_m4(cammat, camob->obmat);
- copy_m4_m4(obmat, cob->matrix);
+ copy_m4_m4(cammat, camob->obmat);
+ copy_m4_m4(obmat, cob->matrix);
- invert_m4_m4(imat, mat);
+ invert_m4_m4(imat, mat);
- mul_m4_series(cob->matrix, cammat, imat, camimat, parmat, obmat);
- }
- }
+ mul_m4_series(cob->matrix, cammat, imat, camimat, parmat, obmat);
}
static bConstraintTypeInfo CTI_OBJECTSOLVER = {
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index fc310ee720a..6d7d42b2293 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -33,15 +33,16 @@
#include "DNA_object_types.h"
#include "DNA_vfont_types.h"
-#include "BLI_blenlib.h"
-#include "BLI_memarena.h"
+#include "BLI_bitmap.h"
+#include "BLI_linklist.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "BLI_memarena.h"
#include "BLI_scanfill.h"
+#include "BLI_string.h"
#include "BLI_utildefines.h"
-#include "BLI_linklist.h"
#include "BKE_displist.h"
-#include "BKE_cdderivedmesh.h"
#include "BKE_object.h"
#include "BKE_lib_id.h"
#include "BKE_mball.h"
diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c
index 4c076256d9f..5f727c2d01e 100644
--- a/source/blender/blenkernel/intern/editmesh.c
+++ b/source/blender/blenkernel/intern/editmesh.c
@@ -27,10 +27,11 @@
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
+#include "BLI_bitmap.h"
#include "BLI_math.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_editmesh.h"
-#include "BKE_cdderivedmesh.h"
#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_mesh_iterators.h"
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index 02cf7f1cd45..5446640b2dd 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -45,7 +45,6 @@
#include "BKE_animsys.h"
#include "BKE_anim.h"
-#include "BKE_cdderivedmesh.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
#include "BKE_key.h"
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 2591edb502e..51c70406692 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -48,7 +48,6 @@
#include "BLT_translation.h"
#include "BKE_appdir.h"
-#include "BKE_cdderivedmesh.h"
#include "BKE_editmesh.h"
#include "BKE_global.h"
#include "BKE_idcode.h"
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 68df93d742a..0a5637c103b 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -68,7 +68,6 @@
#include "BKE_lib_id.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
-#include "BKE_cdderivedmesh.h" /* for weight_to_rgb() */
#include "BKE_pointcache.h"
#include "BKE_scene.h"
#include "BKE_deform.h"
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 141e93183fb..efe13fc8817 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -1378,6 +1378,138 @@ void BKE_pbvh_update_vertex_data(PBVH *bvh, int flag)
}
}
+static void pbvh_faces_node_visibility_update(PBVH *bvh, PBVHNode *node)
+{
+ MVert *mvert;
+ const int *vert_indices;
+ int totvert, i;
+ BKE_pbvh_node_num_verts(bvh, node, NULL, &totvert);
+ BKE_pbvh_node_get_verts(bvh, node, &vert_indices, &mvert);
+
+ for (i = 0; i < totvert; i++) {
+ MVert *v = &mvert[vert_indices[i]];
+ if (!(v->flag & ME_HIDE)) {
+ BKE_pbvh_node_fully_hidden_set(node, false);
+ return;
+ }
+ }
+
+ BKE_pbvh_node_fully_hidden_set(node, true);
+}
+
+static void pbvh_grids_node_visibility_update(PBVH *bvh, PBVHNode *node)
+{
+ CCGElem **grids;
+ BLI_bitmap **grid_hidden;
+ int *grid_indices, totgrid, i;
+
+ BKE_pbvh_node_get_grids(bvh, node, &grid_indices, &totgrid, NULL, NULL, &grids);
+ grid_hidden = BKE_pbvh_grid_hidden(bvh);
+ CCGKey key = *BKE_pbvh_get_grid_key(bvh);
+
+ for (i = 0; i < totgrid; i++) {
+ int g = grid_indices[i], x, y;
+ BLI_bitmap *gh = grid_hidden[g];
+
+ if (!gh) {
+ BKE_pbvh_node_fully_hidden_set(node, false);
+ return;
+ }
+
+ for (y = 0; y < key.grid_size; y++) {
+ for (x = 0; x < key.grid_size; x++) {
+ if (!BLI_BITMAP_TEST(gh, y * key.grid_size + x)) {
+ BKE_pbvh_node_fully_hidden_set(node, false);
+ return;
+ }
+ }
+ }
+ }
+ BKE_pbvh_node_fully_hidden_set(node, true);
+}
+
+static void pbvh_bmesh_node_visibility_update(PBVHNode *node)
+{
+ GSet *unique, *other;
+
+ unique = BKE_pbvh_bmesh_node_unique_verts(node);
+ other = BKE_pbvh_bmesh_node_other_verts(node);
+
+ GSetIterator gs_iter;
+
+ GSET_ITER (gs_iter, unique) {
+ BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
+ if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
+ BKE_pbvh_node_fully_hidden_set(node, false);
+ return;
+ }
+ }
+
+ GSET_ITER (gs_iter, other) {
+ BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
+ if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
+ BKE_pbvh_node_fully_hidden_set(node, false);
+ return;
+ }
+ }
+
+ BKE_pbvh_node_fully_hidden_set(node, true);
+}
+
+static void pbvh_update_visibility_task_cb(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+
+ PBVHUpdateData *data = userdata;
+ PBVH *bvh = data->bvh;
+ PBVHNode *node = data->nodes[n];
+ if (node->flag & PBVH_UpdateMask) {
+ switch (BKE_pbvh_type(bvh)) {
+ case PBVH_FACES:
+ pbvh_faces_node_visibility_update(bvh, node);
+ break;
+ case PBVH_GRIDS:
+ pbvh_grids_node_visibility_update(bvh, node);
+ break;
+ case PBVH_BMESH:
+ pbvh_bmesh_node_visibility_update(node);
+ break;
+ }
+ node->flag &= ~PBVH_UpdateMask;
+ }
+}
+
+static void pbvh_update_visibility(PBVH *bvh, PBVHNode **nodes, int totnode)
+{
+ PBVHUpdateData data = {
+ .bvh = bvh,
+ .nodes = nodes,
+ };
+
+ PBVHParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, true, totnode);
+ BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_visibility_task_cb, &settings);
+}
+
+void BKE_pbvh_update_visibility(PBVH *bvh)
+{
+ if (!bvh->nodes) {
+ return;
+ }
+
+ PBVHNode **nodes;
+ int totnode;
+
+ BKE_pbvh_search_gather(
+ bvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateVisibility), &nodes, &totnode);
+ pbvh_update_visibility(bvh, nodes, totnode);
+
+ if (nodes) {
+ MEM_freeN(nodes);
+ }
+}
+
void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3])
{
PBVHIter iter;
@@ -1533,6 +1665,11 @@ void BKE_pbvh_node_mark_normals_update(PBVHNode *node)
node->flag |= PBVH_UpdateNormals;
}
+void BKE_pbvh_node_mark_visibility_update(PBVHNode *node)
+{
+ node->flag |= PBVH_UpdateVisibility;
+}
+
void BKE_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden)
{
BLI_assert(node->flag & PBVH_Leaf);
diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c
index 8654c50a783..3c1a9c4d3d6 100644
--- a/source/blender/blenkernel/intern/subdiv_ccg.c
+++ b/source/blender/blenkernel/intern/subdiv_ccg.c
@@ -623,9 +623,9 @@ void BKE_subdiv_ccg_destroy(SubdivCCG *subdiv_ccg)
MEM_SAFE_FREE(subdiv_ccg->grid_flag_mats);
if (subdiv_ccg->grid_hidden != NULL) {
for (int grid_index = 0; grid_index < num_grids; grid_index++) {
- MEM_freeN(subdiv_ccg->grid_hidden[grid_index]);
+ MEM_SAFE_FREE(subdiv_ccg->grid_hidden[grid_index]);
}
- MEM_freeN(subdiv_ccg->grid_hidden);
+ MEM_SAFE_FREE(subdiv_ccg->grid_hidden);
}
if (subdiv_ccg->subdiv != NULL) {
BKE_subdiv_free(subdiv_ccg->subdiv);
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 33a9875151a..da3c03cf705 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -838,7 +838,8 @@ static void minmax_v3_v3v3(const float vec[3], float min[3], float max[3])
}
}
-static void ccgDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3])
+/* UNUSED, keep since this functionality may be useful in the future. */
+static void UNUSED_FUNCTION(ccgDM_getMinMax)(DerivedMesh *dm, float r_min[3], float r_max[3])
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
CCGSubSurf *ss = ccgdm->ss;
@@ -2042,7 +2043,6 @@ static void ccgDM_recalcLoopTri(DerivedMesh *dm)
static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm)
{
- ccgdm->dm.getMinMax = ccgDM_getMinMax;
ccgdm->dm.getNumVerts = ccgDM_getNumVerts;
ccgdm->dm.getNumEdges = ccgDM_getNumEdges;
ccgdm->dm.getNumLoops = ccgDM_getNumLoops;
diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h
index 3ee22e4ad0a..74e6c32b288 100644
--- a/source/blender/blenlib/BLI_fileops.h
+++ b/source/blender/blenlib/BLI_fileops.h
@@ -158,6 +158,10 @@ bool BLI_file_older(const char *file1, const char *file2) ATTR_WARN_UNUSED_RESUL
/* read ascii file as lines, empty list if reading fails */
struct LinkNode *BLI_file_read_as_lines(const char *file) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void *BLI_file_read_text_as_mem(const char *filepath, size_t pad_bytes, size_t *r_size);
+void *BLI_file_read_text_as_mem_with_newline_as_nil(const char *filepath,
+ bool trim_trailing_space,
+ size_t pad_bytes,
+ size_t *r_size);
void *BLI_file_read_binary_as_mem(const char *filepath, size_t pad_bytes, size_t *r_size);
void BLI_file_free_lines(struct LinkNode *lines);
diff --git a/source/blender/blenlib/intern/delaunay_2d.c b/source/blender/blenlib/intern/delaunay_2d.c
index 0a2addff6d1..c222ed06aaa 100644
--- a/source/blender/blenlib/intern/delaunay_2d.c
+++ b/source/blender/blenlib/intern/delaunay_2d.c
@@ -3524,8 +3524,8 @@ static void exactinit(void)
* Sets h = e + f. See the long version of my paper for details.
*
* If round-to-even is used (as with IEEE 754), maintains the strongly
- * nonoverlapping property. (That is, if e is strongly nonoverlapping, h
- * will be also.) Does NOT maintain the nonoverlapping or nonadjacent
+ * non-overlapping property. (That is, if e is strongly non-overlapping, h
+ * will be also.) Does NOT maintain the non-overlapping or non-adjacent
* properties.
*/
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index d1d8c4fa2e0..e267c061b2b 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -449,6 +449,63 @@ void *BLI_file_read_binary_as_mem(const char *filepath, size_t pad_bytes, size_t
}
/**
+ * Return the text file data with:
+
+ * - Newlines replaced with '\0'.
+ * - Optionally trim whitespace, replacing trailing ' ' & '\t' with '\0'.
+ *
+ * This is an alternative to using #BLI_file_read_as_lines,
+ * allowing us to loop over lines without converting it into a linked list
+ * with individual allocations.
+ *
+ * \param trim_trailing_space: Replace trailing spaces & tabs with nil.
+ * This arguments prevents the caller from counting blank lines (if that's important).
+ * \param pad_bytes: When this is non-zero, the first byte is set to nil,
+ * to simplify parsing the file.
+ * It's recommended to pass in 1, so all text is nil terminated.
+ *
+ * Example looping over lines:
+ *
+ * \code{.c}
+ * size_t data_len;
+ * char *data = BLI_file_read_text_as_mem_with_newline_as_nil(filepath, true, 1, &data_len);
+ * char *data_end = data + data_len;
+ * for (char *line = data; line != data_end; line = strlen(line) + 1) {
+ * printf("line='%s'\n", line);
+ * }
+ * \endcode
+ */
+void *BLI_file_read_text_as_mem_with_newline_as_nil(const char *filepath,
+ bool trim_trailing_space,
+ size_t pad_bytes,
+ size_t *r_size)
+{
+ char *mem = BLI_file_read_text_as_mem(filepath, pad_bytes, r_size);
+ if (mem != NULL) {
+ char *mem_end = mem + *r_size;
+ if (pad_bytes != 0) {
+ *mem_end = '\0';
+ }
+ for (char *p = mem, *p_next; p != mem_end; p = p_next) {
+ p_next = memchr(p, '\n', mem_end - p);
+ if (p_next != NULL) {
+ if (trim_trailing_space) {
+ for (char *p_trim = p_next - 1; p_trim > p && ELEM(*p_trim, ' ', '\t'); p_trim--) {
+ *p_trim = '\0';
+ }
+ }
+ *p_next = '\0';
+ p_next++;
+ }
+ else {
+ p_next = mem_end;
+ }
+ }
+ }
+ return mem;
+}
+
+/**
* Reads the contents of a text file and returns the lines in a linked list.
*/
LinkNode *BLI_file_read_as_lines(const char *name)
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index 334cb7c3db4..ff618142bfa 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -25,6 +25,7 @@
#include "DNA_listBase.h"
#include "DNA_scene_types.h"
+#include "BLI_bitmap.h"
#include "BLI_linklist_stack.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
@@ -32,7 +33,6 @@
#include "BLI_task.h"
#include "BLI_utildefines.h"
-#include "BKE_cdderivedmesh.h"
#include "BKE_editmesh.h"
#include "BKE_mesh.h"
#include "BKE_multires.h"
diff --git a/source/blender/depsgraph/intern/depsgraph_relation.cc b/source/blender/depsgraph/intern/depsgraph_relation.cc
index 1b2de2cc807..cff62540ca8 100644
--- a/source/blender/depsgraph/intern/depsgraph_relation.cc
+++ b/source/blender/depsgraph/intern/depsgraph_relation.cc
@@ -42,7 +42,7 @@ Relation::Relation(Node *from, Node *to, const char *description)
/* Hook it up to the nodes which use it.
*
* NOTE: We register relation in the nodes which this link connects to here
- * in constructor but we don't unregister it in the destructor.
+ * in constructor but we don't un-register it in the destructor.
*
* Reasoning:
*
@@ -50,7 +50,7 @@ Relation::Relation(Node *from, Node *to, const char *description)
* real need in avoiding dangling pointers, all the memory is to be freed
* anyway.
*
- * - Unregistering relation is not a cheap operation, so better to have it
+ * - Un-registering relation is not a cheap operation, so better to have it
* as an explicit call if we need this. */
from->outlinks.push_back(this);
to->inlinks.push_back(this);
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index 0c9efeb0a16..7661dfb41a5 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -124,7 +124,8 @@ extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
~EEVEE_RENDER_PASS_ENVIRONMENT; \
if (__filtered_##render_pass_index_ != 0) { \
int render_pass_index_ = 1; \
- for (int bit_##render_pass_ = 0; bit_##render_pass_ < 32; bit_##render_pass_++) { \
+ for (int bit_##render_pass_ = 0; bit_##render_pass_ < EEVEE_RENDER_PASS_MAX_BIT; \
+ bit_##render_pass_++) { \
eViewLayerEEVEEPassType render_pass_ = (1 << bit_##render_pass_); \
if ((__filtered_##render_pass_index_ & render_pass_) != 0) {
#define RENDER_PASS_ITER_END(render_pass_index_) \
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 456673c92fa..d11e93bbc3f 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -442,8 +442,6 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texcoloc, 1);
DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texcosize, 1);
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 517d8ca51a3..ac65ce2a28e 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -1607,7 +1607,7 @@ void UI_view2d_scrollers_draw(View2D *v2d, View2DScrollers *vs)
* - slider bubble is large enough (no overdraw confusion)
* - scale is shown on the scroller
* (workaround to make sure that button windows don't show these,
- * and only the time-grids with their zoomability can do so)
+ * and only the time-grids with their zoom-ability can do so).
*/
if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 && (v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES) &&
(BLI_rcti_size_x(&slider) > V2D_SCROLL_HANDLE_SIZE_HOTSPOT)) {
diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c
index 2e175cb156c..8d5c1469694 100644
--- a/source/blender/editors/mesh/editmesh_knife_project.c
+++ b/source/blender/editors/mesh/editmesh_knife_project.c
@@ -31,7 +31,6 @@
#include "BKE_mesh.h"
#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_cdderivedmesh.h"
#include "BKE_editmesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 454d3c07fff..906a9e44870 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -1292,6 +1292,7 @@ void CONSTRAINT_OT_objectsolver_set_inverse(wmOperatorType *ot)
static int objectsolver_clear_inverse_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
bObjectSolverConstraint *data = (con) ? (bObjectSolverConstraint *)con->data : NULL;
@@ -1304,6 +1305,7 @@ static int objectsolver_clear_inverse_exec(bContext *C, wmOperator *op)
/* simply clear the matrix */
unit_m4(data->invmat);
+ ED_object_constraint_update(bmain, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index cd34e2c6f99..bc4ed0bf7bf 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -80,6 +80,7 @@ static void update_cb(PBVHNode *node, void *rebuild)
BKE_pbvh_node_mark_update_mask(node);
if (*((bool *)rebuild)) {
BKE_pbvh_node_mark_rebuild_draw(node);
+ BKE_pbvh_node_mark_visibility_update(node);
}
BKE_pbvh_node_fully_hidden_set(node, 0);
}
@@ -641,6 +642,10 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
tag_update |= true;
}
+ if (update_visibility) {
+ BKE_pbvh_update_visibility(ss->pbvh);
+ }
+
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && update_visibility) {
Mesh *mesh = ob->data;
BKE_mesh_flush_hidden_from_verts(mesh);
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index eaabd907f23..94747e79c84 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -30,6 +30,7 @@
#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
#include "BLT_translation.h"
@@ -102,6 +103,107 @@ struct FSMenuEntry *ED_fsmenu_get_category(struct FSMenu *fsmenu, FSMenuCategory
return fsm_head;
}
+/* -------------------------------------------------------------------- */
+/** \name XDG User Directory Support (Unix)
+ *
+ * Generic Unix, Use XDG when available, otherwise fallback to the home directory.
+ * \{ */
+
+/**
+ * Look for `user-dirs.dirs`, where localized or custom user folders are defined,
+ * and store their paths in a GHash.
+ */
+static GHash *fsmenu_xdg_user_dirs_parse(const char *home)
+{
+ size_t data_len;
+ char *data;
+
+ /* Check if the config file exists. */
+ {
+ char filepath[FILE_MAX];
+ const char *xdg_config_home = getenv("XDG_CONFIG_HOME");
+ if (xdg_config_home != NULL) {
+ BLI_path_join(filepath, sizeof(filepath), xdg_config_home, "user-dirs.dirs", NULL);
+ }
+ else {
+ BLI_path_join(filepath, sizeof(filepath), home, ".config", "user-dirs.dirs", NULL);
+ }
+ data = BLI_file_read_text_as_mem_with_newline_as_nil(filepath, true, 1, &data_len);
+ if (data == NULL) {
+ return NULL;
+ }
+ }
+ /* By default there are 8 paths. */
+ GHash *xdg_map = BLI_ghash_str_new_ex(__func__, 8);
+ char *data_end = data + data_len;
+ uint l_len;
+ for (char *l = data; l != data_end; l += l_len + 1) {
+ l_len = strlen(l);
+
+ /* Avoid inserting invalid values. */
+ if (STRPREFIX(l, "XDG_")) {
+ char *l_value = strchr(l, '=');
+ if (l_value != NULL) {
+ *l_value = '\0';
+ l_value++;
+ if (*l_value == '"' && l[l_len - 1] == '"') {
+ l_value++;
+ l[l_len - 1] = '\0';
+
+ char l_value_expanded[FILE_MAX];
+ char *l_value_final = l_value;
+
+ /* This is currently the only variable used.
+ * Based on the 'user-dirs.dirs' man page,
+ * there is no need to resolve arbitrary environment variables. */
+ if (STRPREFIX(l_value, "$HOME" SEP_STR)) {
+ BLI_path_join(l_value_expanded, sizeof(l_value_expanded), home, l_value + 6, NULL);
+ l_value_final = l_value_expanded;
+ }
+
+ BLI_ghash_insert(xdg_map, BLI_strdup(l), BLI_strdup(l_value_final));
+ }
+ }
+ }
+ }
+ MEM_freeN(data);
+ return xdg_map;
+}
+
+static void fsmenu_xdg_user_dirs_free(GHash *xdg_map)
+{
+ if (xdg_map != NULL) {
+ BLI_ghash_free(xdg_map, MEM_freeN, MEM_freeN);
+ }
+}
+
+/**
+ * Add fsmenu entry for system folders on linux.
+ * - Check if a path is stored in the GHash generated from user-dirs.dirs
+ * - If not, check for a default path in $HOME
+ *
+ * \param key: Use `user-dirs.dirs` format "XDG_EXAMPLE_DIR"
+ * \param default_path: Directory name to check in $HOME, also used for the menu entry name.
+ */
+static void fsmenu_xdg_insert_entry(GHash *xdg_map,
+ struct FSMenu *fsmenu,
+ const char *key,
+ const char *default_path,
+ int icon,
+ const char *home)
+{
+ char xdg_path_buf[FILE_MAXDIR];
+ const char *xdg_path = xdg_map ? BLI_ghash_lookup(xdg_map, key) : NULL;
+ if (xdg_path == NULL) {
+ BLI_path_join(xdg_path_buf, sizeof(xdg_path_buf), home, default_path, NULL);
+ xdg_path = xdg_path_buf;
+ }
+ fsmenu_insert_entry(
+ fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, xdg_path, IFACE_(default_path), icon, FS_INSERT_LAST);
+}
+
+/** \} */
+
void ED_fsmenu_set_category(struct FSMenu *fsmenu, FSMenuCategory category, FSMenuEntry *fsm_head)
{
switch (category) {
@@ -275,6 +377,12 @@ void fsmenu_insert_entry(struct FSMenu *fsmenu,
int icon,
FSMenuInsert flag)
{
+ const uint path_len = strlen(path);
+ BLI_assert(path_len > 0);
+ if (path_len == 0) {
+ return;
+ }
+ const bool has_trailing_slash = (path[path_len - 1] == SEP);
FSMenuEntry *fsm_prev;
FSMenuEntry *fsm_iter;
FSMenuEntry *fsm_head;
@@ -284,8 +392,9 @@ void fsmenu_insert_entry(struct FSMenu *fsmenu,
for (fsm_iter = fsm_head; fsm_iter; fsm_prev = fsm_iter, fsm_iter = fsm_iter->next) {
if (fsm_iter->path) {
- const int cmp_ret = BLI_path_cmp(path, fsm_iter->path);
- if (cmp_ret == 0) {
+ /* Compare, with/without the trailing slash in 'path'. */
+ const int cmp_ret = BLI_path_ncmp(path, fsm_iter->path, path_len);
+ if (cmp_ret == 0 && STREQ(fsm_iter->path + path_len, has_trailing_slash ? "" : SEP_STR)) {
if (flag & FS_INSERT_FIRST) {
if (fsm_iter != fsm_head) {
fsm_prev->next = fsm_iter->next;
@@ -310,7 +419,14 @@ void fsmenu_insert_entry(struct FSMenu *fsmenu,
}
fsm_iter = MEM_mallocN(sizeof(*fsm_iter), "fsme");
- fsm_iter->path = BLI_strdup(path);
+ if (has_trailing_slash) {
+ fsm_iter->path = BLI_strdup(path);
+ }
+ else {
+ fsm_iter->path = BLI_strdupn(path, path_len + 1);
+ fsm_iter->path[path_len] = SEP;
+ fsm_iter->path[path_len + 1] = '\0';
+ }
fsm_iter->save = (flag & FS_INSERT_SAVE) != 0;
/* If entry is also in another list, use that icon and maybe name. */
@@ -503,7 +619,6 @@ static void fsmenu_add_windows_folder(struct FSMenu *fsmenu,
if (SHGetKnownFolderPath(rfid, 0, NULL, &pPath) == S_OK) {
BLI_strncpy_wchar_as_utf8(line, pPath, FILE_MAXDIR);
CoTaskMemFree(pPath);
- BLI_add_slash(line);
fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, name, icon, flag);
}
}
@@ -640,9 +755,6 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
CFRelease(localKey);
}
- /* Add end slash for consistency with other platforms */
- BLI_add_slash(defPath);
-
fsmenu_insert_entry(
fsmenu, FS_CATEGORY_SYSTEM, defPath, name[0] ? name : NULL, icon, FS_INSERT_SORTED);
}
@@ -681,9 +793,6 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
/* Exclude "all my files" as it makes no sense in blender fileselector */
/* Exclude "airdrop" if wlan not active as it would show "" ) */
if (!strstr(line, "myDocuments.cannedSearch") && (*line != '\0')) {
- /* Add end slash for consistency with other platforms */
- BLI_add_slash(line);
-
fsmenu_insert_entry(
fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, ICON_FILE_FOLDER, FS_INSERT_LAST);
}
@@ -703,75 +812,31 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
if (read_bookmarks && home) {
- BLI_snprintf(line, sizeof(line), "%s/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(
- fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, IFACE_("Home"), ICON_HOME, FS_INSERT_LAST);
- }
+ fsmenu_insert_entry(
+ fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, home, IFACE_("Home"), ICON_HOME, FS_INSERT_LAST);
/* Follow the XDG spec, check if these are available. */
-
- /* TODO: parse "$XDG_CONFIG_HOME/user-dirs.dirs" for localized paths. */
-
- BLI_snprintf(line, sizeof(line), "%s/Desktop/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu,
- FS_CATEGORY_SYSTEM_BOOKMARKS,
- line,
- IFACE_("Desktop"),
- ICON_DESKTOP,
- FS_INSERT_LAST);
+ GHash *xdg_map = fsmenu_xdg_user_dirs_parse(home);
+
+ struct {
+ const char *key;
+ const char *default_path;
+ BIFIconID icon;
+ } xdg_items[] = {
+ {"XDG_DESKTOP_DIR", "Desktop", ICON_DESKTOP},
+ {"XDG_DOCUMENTS_DIR", "Documents", ICON_DOCUMENTS},
+ {"XDG_DOWNLOAD_DIR", "Downloads", ICON_IMPORT},
+ {"XDG_VIDEOS_DIR", "Videos", ICON_FILE_MOVIE},
+ {"XDG_PICTURES_DIR", "Pictures", ICON_FILE_IMAGE},
+ {"XDG_MUSIC_DIR", "Music", ICON_FILE_SOUND},
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(xdg_items); i++) {
+ fsmenu_xdg_insert_entry(
+ xdg_map, fsmenu, xdg_items[i].key, xdg_items[i].default_path, xdg_items[i].icon, home);
}
- BLI_snprintf(line, sizeof(line), "%s/Documents/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu,
- FS_CATEGORY_SYSTEM_BOOKMARKS,
- line,
- IFACE_("Documents"),
- ICON_DOCUMENTS,
- FS_INSERT_LAST);
- }
-
- BLI_snprintf(line, sizeof(line), "%s/Downloads/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu,
- FS_CATEGORY_SYSTEM_BOOKMARKS,
- line,
- IFACE_("Downloads"),
- ICON_IMPORT,
- FS_INSERT_LAST);
- }
-
- BLI_snprintf(line, sizeof(line), "%s/Videos/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu,
- FS_CATEGORY_SYSTEM_BOOKMARKS,
- line,
- IFACE_("Videos"),
- ICON_FILE_MOVIE,
- FS_INSERT_LAST);
- }
-
- BLI_snprintf(line, sizeof(line), "%s/Pictures/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu,
- FS_CATEGORY_SYSTEM_BOOKMARKS,
- line,
- IFACE_("Pictures"),
- ICON_FILE_IMAGE,
- FS_INSERT_LAST);
- }
-
- BLI_snprintf(line, sizeof(line), "%s/Music/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu,
- FS_CATEGORY_SYSTEM_BOOKMARKS,
- line,
- IFACE_("Music"),
- ICON_FILE_SOUND,
- FS_INSERT_LAST);
- }
+ fsmenu_xdg_user_dirs_free(xdg_map);
}
{
@@ -779,7 +844,6 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
# ifdef __linux__
/* loop over mount points */
struct mntent *mnt;
- int len;
FILE *fp;
fp = setmntent(MOUNTED, "r");
@@ -801,16 +865,8 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
continue;
}
- len = strlen(mnt->mnt_dir);
- if (len && mnt->mnt_dir[len - 1] != '/') {
- BLI_snprintf(line, sizeof(line), "%s/", mnt->mnt_dir);
- fsmenu_insert_entry(
- fsmenu, FS_CATEGORY_SYSTEM, line, NULL, ICON_DISK_DRIVE, FS_INSERT_SORTED);
- }
- else {
- fsmenu_insert_entry(
- fsmenu, FS_CATEGORY_SYSTEM, mnt->mnt_dir, NULL, ICON_DISK_DRIVE, FS_INSERT_SORTED);
- }
+ fsmenu_insert_entry(
+ fsmenu, FS_CATEGORY_SYSTEM, mnt->mnt_dir, NULL, ICON_DISK_DRIVE, FS_INSERT_SORTED);
found = 1;
}
@@ -838,7 +894,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
const char *label_test = label + 6;
label = *label_test ? label_test : dirname;
}
- BLI_snprintf(line, sizeof(line), "%s%s/", name, dirname);
+ BLI_snprintf(line, sizeof(line), "%s%s", name, dirname);
fsmenu_insert_entry(
fsmenu, FS_CATEGORY_SYSTEM, line, label, ICON_NETWORK_DRIVE, FS_INSERT_SORTED);
found = 1;
@@ -858,6 +914,11 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
}
# endif
#endif
+
+#if defined(WIN32) || defined(__APPLE__)
+ /* Quiet warnings. */
+ UNUSED_VARS(fsmenu_xdg_insert_entry, fsmenu_xdg_user_dirs_parse, fsmenu_xdg_user_dirs_free);
+#endif
}
static void fsmenu_free_category(struct FSMenu *fsmenu, FSMenuCategory category)
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 49acf0ca3a4..eb568acc0dd 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -504,7 +504,7 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene,
{
Mesh *me_from_em = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, NULL, ob->data);
- initialDerived = CDDM_from_mesh_ex(me_from_em, CD_REFERENCE, &CD_MASK_MESH);
+ initialDerived = CDDM_from_mesh(me_from_em);
derivedMesh = subsurf_make_derived_from_derived(
initialDerived, &smd, scene, NULL, SUBSURF_IN_EDIT_MODE);
diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h
index 09d02e9a375..62ae5768879 100644
--- a/source/blender/makesdna/DNA_layer_types.h
+++ b/source/blender/makesdna/DNA_layer_types.h
@@ -47,6 +47,7 @@ typedef enum eViewLayerEEVEEPassType {
EEVEE_RENDER_PASS_AO = (1 << 13),
EEVEE_RENDER_PASS_BLOOM = (1 << 14),
} eViewLayerEEVEEPassType;
+#define EEVEE_RENDER_PASS_MAX_BIT 15
typedef struct Base {
struct Base *next, *prev;
diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h
index 32f2b55ca54..7a85f5c372f 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -293,7 +293,7 @@ typedef enum PropertyOverrideFlag {
* Forbid usage of this property in comparison (& hence override) code.
* Useful e.g. for collections of data like mesh's geometry, particles, etc.
* Also for runtime data that should never be considered as part of actual Blend data (e.g.
- * dpesgraph from ViewLayers...).
+ * depsgraph from ViewLayers...).
*/
PROPOVERRIDE_NO_COMPARISON = (1 << 1),
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index df9d9918192..8dd6e6982dd 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -2263,10 +2263,22 @@ static void rna_property_update(
}
if (!is_rna || (prop->flag & PROP_IDPROPERTY)) {
- /* WARNING! This is so property drivers update the display!
- * not especially nice */
+
+ /* Disclaimer: this logic is not applied consistently, causing some confusing behavior.
+ *
+ * - When animated (which skips update functions).
+ * - When ID-properties are edited via Python (since RNA properties aren't used in this case).
+ *
+ * Adding updates will add a lot of overhead in the case of animation.
+ * For Python it may cause unexpected slow-downs for developers using ID-properties
+ * for data storage. Further, the root ID isn't available with nested data-structures.
+ *
+ * So editing custom properties only causes updates in the UI,
+ * keep this exception because it happens to be useful for driving settings.
+ * Python developers on the other hand will need to manually 'update_tag', see: T74000. */
DEG_id_tag_update(ptr->owner_id,
ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_PARAMETERS);
+
WM_main_add_notifier(NC_WINDOW, NULL);
/* Not nice as well, but the only way to make sure material preview
* is updated with custom nodes.
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index 94b5786665c..b8174f094ec 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -193,7 +193,9 @@ static char *rna_ImageUser_path(PointerRNA *ptr)
return BLI_strdup("");
}
-static void rna_Image_gpu_texture_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Image_gpu_texture_update(Main *UNUSED(bmain),
+ Scene *UNUSED(scene),
+ PointerRNA *ptr)
{
Image *ima = (Image *)ptr->owner_id;
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 599b8fd91c8..a427267926d 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -1045,7 +1045,7 @@ static void rna_Scene_active_keying_set_set(PointerRNA *ptr,
/* get KeyingSet index stuff for list of Keying Sets editing UI
* - active_keyingset-1 since 0 is reserved for 'none'
- * - don't clamp, otherwise can never set builtins types as active...
+ * - don't clamp, otherwise can never set builtin's types as active...
*/
static int rna_Scene_active_keying_set_index_get(PointerRNA *ptr)
{
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 34f4fd45b9c..3e223d613b8 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -3094,7 +3094,6 @@ static void rna_def_userdef_theme_space_seq(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Marker Line Selected", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
-
prop = RNA_def_property(srna, "keyframe", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "vertex_select");
RNA_def_property_array(prop, 3);
@@ -3173,7 +3172,6 @@ static void rna_def_userdef_theme_space_action(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Marker Line Selected", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
-
prop = RNA_def_property(srna, "value_sliders", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "face");
RNA_def_property_array(prop, 3);
@@ -3493,7 +3491,6 @@ static void rna_def_userdef_theme_space_nla(BlenderRNA *brna)
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Marker Line Selected", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
-
}
static void rna_def_userdef_theme_colorset(BlenderRNA *brna)
@@ -3624,7 +3621,6 @@ static void rna_def_userdef_theme_space_clip(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Marker Line Selected", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
-
prop = RNA_def_property(srna, "strips", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "strip");
RNA_def_property_array(prop, 3);
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index 26a353b4235..7dfa16ae909 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -977,7 +977,6 @@ static Mesh *explodeMesh(ExplodeModifierData *emd,
explode = BKE_mesh_new_nomain_from_template(mesh, totdup, 0, totface - delface, 0, 0);
mtface = CustomData_get_layer_named(&explode->fdata, CD_MTFACE, emd->uvname);
- /*dupvert = CDDM_get_verts(explode);*/
/* getting back to object space */
invert_m4_m4(imat, ctx->object->obmat);
diff --git a/source/blender/modifiers/intern/MOD_fluid.c b/source/blender/modifiers/intern/MOD_fluid.c
index 9347c54b0ac..16dfe5ffc40 100644
--- a/source/blender/modifiers/intern/MOD_fluid.c
+++ b/source/blender/modifiers/intern/MOD_fluid.c
@@ -34,7 +34,6 @@
#include "DNA_object_force_types.h"
#include "DNA_mesh_types.h"
-#include "BKE_cdderivedmesh.h"
#include "BKE_layer.h"
#include "BKE_lib_query.h"
#include "BKE_modifier.h"
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c
index 4a5887c3122..5fcd9622c5d 100644
--- a/source/blender/modifiers/intern/MOD_subsurf.c
+++ b/source/blender/modifiers/intern/MOD_subsurf.c
@@ -31,7 +31,6 @@
#include "DNA_scene_types.h"
#include "DNA_mesh_types.h"
-#include "BKE_cdderivedmesh.h"
#include "BKE_scene.h"
#include "BKE_subdiv.h"
#include "BKE_subdiv_ccg.h"
diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c
index 92055119298..1d6767a8077 100644
--- a/source/blender/modifiers/intern/MOD_weighted_normal.c
+++ b/source/blender/modifiers/intern/MOD_weighted_normal.c
@@ -20,14 +20,15 @@
#include "MEM_guardedalloc.h"
+#include "BLI_bitmap.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "BKE_cdderivedmesh.h"
#include "BKE_deform.h"
#include "BKE_lib_id.h"
#include "BKE_mesh.h"
diff --git a/tests/python/bl_constraints.py b/tests/python/bl_constraints.py
index 2a48ffe35ea..42f81bddce6 100644
--- a/tests/python/bl_constraints.py
+++ b/tests/python/bl_constraints.py
@@ -31,9 +31,19 @@ from mathutils import Matrix
class AbstractConstraintTests(unittest.TestCase):
"""Useful functionality for constraint tests."""
+ layer_collection = '' # When set, this layer collection will be enabled.
+
def setUp(self):
bpy.ops.wm.open_mainfile(filepath=str(args.testdir / "constraints.blend"))
+ # This allows developers to disable layer collections and declutter the
+ # 3D Viewport while working in constraints.blend, without influencing
+ # the actual unit tests themselves.
+ if self.layer_collection:
+ top_collection = bpy.context.view_layer.layer_collection
+ collection = top_collection.children[self.layer_collection]
+ collection.exclude = False
+
def assert_matrix(self, actual_matrix, expect_matrix, object_name: str, places=6, delta=None):
"""Asserts that the matrices almost equal."""
self.assertEqual(len(actual_matrix), 4, 'Expected a 4x4 matrix')
@@ -76,6 +86,8 @@ class AbstractConstraintTests(unittest.TestCase):
class ChildOfTest(AbstractConstraintTests):
+ layer_collection = 'Child Of'
+
def test_object_simple_parent(self):
"""Child Of: simple evaluation of object parent."""
initial_matrix = Matrix((
@@ -176,6 +188,33 @@ class ChildOfTest(AbstractConstraintTests):
bpy.ops.constraint.childof_clear_inverse(context, constraint='Child Of')
self.matrix_test('Child Of.armature.owner', initial_matrix)
+
+class ObjectSolverTest(AbstractConstraintTests):
+ layer_collection = 'Object Solver'
+
+ def test_simple_parent(self):
+ """Object Solver: simple evaluation of parent."""
+ initial_matrix = Matrix((
+ (-0.970368504524231, 0.03756079450249672, -0.23869234323501587, -0.681557297706604),
+ (-0.24130365252494812, -0.2019258439540863, 0.9492092132568359, 6.148940086364746),
+ (-0.012545102275907993, 0.9786801934242249, 0.20500603318214417, 2.2278831005096436),
+ (0.0, 0.0, 0.0, 1.0),
+ ))
+ self.matrix_test('Object Solver.owner', initial_matrix)
+
+ context = self.constraint_context('Object Solver')
+ bpy.ops.constraint.objectsolver_set_inverse(context, constraint='Object Solver')
+ self.matrix_test('Object Solver.owner', Matrix((
+ (0.9992386102676392, 0.019843988120555878, -0.03359176218509674, 0.10000000149011612),
+ (-0.017441775649785995, 0.997369647026062, 0.0703534483909607, 0.20000000298023224),
+ (0.03489949554204941, -0.06971397995948792, 0.9969563484191895, 0.30000001192092896),
+ (0.0, 0.0, 0.0, 1.0),
+ )))
+
+ bpy.ops.constraint.objectsolver_clear_inverse(context, constraint='Object Solver')
+ self.matrix_test('Object Solver.owner', initial_matrix)
+
+
def main():
global args
import argparse