diff options
author | Lukas Stockner <lukas.stockner@freenet.de> | 2018-07-27 22:42:50 +0300 |
---|---|---|
committer | Lukas Stockner <lukas.stockner@freenet.de> | 2018-07-27 22:42:50 +0300 |
commit | e704c78d8799172aa0f5a9122c0ff72642db0203 (patch) | |
tree | 5610b07c0c489663c24809c88da967ba261c90c4 | |
parent | 3c643440a3348e1fc8ddc79fcdbd3933e1245562 (diff) | |
parent | 48759580839aa4e2ad2541ff4c19baaaf751721d (diff) |
Merge remote-tracking branch 'origin/blender2.8' into udimtemp-udim-images
163 files changed, 3343 insertions, 1524 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 2961aafe908..0d79ab2ed90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1555,7 +1555,11 @@ if(WITH_PYTHON) endif() if(WITH_CXX11) - if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if( + CMAKE_COMPILER_IS_GNUCC OR + CMAKE_C_COMPILER_ID MATCHES "Clang" OR + CMAKE_C_COMPILER_ID MATCHES "Intel" + ) # TODO(sergey): Do we want c++11 or gnu-c++11 here? set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") elseif(MSVC) diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index 5c52a8bcce9..476cf975737 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -52,7 +52,9 @@ def _workaround_buggy_drivers(): def _configure_argument_parser(): import argparse - parser = argparse.ArgumentParser(description="Cycles Addon argument parser") + # No help because it conflicts with general Python scripts argument parsing + parser = argparse.ArgumentParser(description="Cycles Addon argument parser", + add_help=False) parser.add_argument("--cycles-resumable-num-chunks", help="Number of chunks to split sample range into", default=None) @@ -65,6 +67,9 @@ def _configure_argument_parser(): parser.add_argument("--cycles-resumable-end-chunk", help="End chunk to render", default=None) + parser.add_argument("--cycles-print-stats", + help="Print rendering statistics to stderr", + action='store_true') return parser @@ -93,6 +98,9 @@ def _parse_command_line(): int(args.cycles_resumable_start_chunk), int(args.cycles_resumable_end_chunk), ) + if args.cycles_print_stats: + import _cycles + _cycles.enable_print_stats() def init(): @@ -168,7 +176,7 @@ def reset(engine, data, depsgraph): import bpy if bpy.app.debug_value == 256: - _cycles.debug_flags_update(depsgraph.scene) + _cycles.debug_flags_update(depsgraph.scene.as_pointer()) else: _cycles.debug_flags_reset() diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 3d5ed6b9b44..a1941ce6176 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -883,14 +883,9 @@ class CYCLES_CAMERA_PT_dof_viewport(CyclesButtonsPanel, Panel): cam = context.camera dof_options = cam.gpu_dof - hq_support = dof_options.is_hq_supported sub = flow.column(align=True) - subhq = sub.column() - subhq.active = hq_support - subhq.prop(dof_options, "use_high_quality") sub.prop(dof_options, "fstop") - if dof_options.use_high_quality and hq_support: - sub.prop(dof_options, "blades") + sub.prop(dof_options, "blades") class CYCLES_PT_context_material(CyclesButtonsPanel, Panel): diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index edb6d04f0bb..34f559674fa 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -1081,27 +1081,18 @@ Mesh *BlenderSync::sync_mesh(BL::Depsgraph& b_depsgraph, /* test if we can instance or if the object is modified */ BL::ID b_ob_data = b_ob.data(); BL::ID key = (BKE_object_is_modified(b_ob))? b_ob_instance: b_ob_data; - BL::Material material_override = view_layer.material_override; /* find shader indices */ vector<Shader*> used_shaders; BL::Object::material_slots_iterator slot; for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) { - if(material_override) { - find_shader(material_override, used_shaders, scene->default_surface); - } - else { - BL::ID b_material(slot->material()); - find_shader(b_material, used_shaders, scene->default_surface); - } + BL::ID b_material(slot->material()); + find_shader(b_material, used_shaders, scene->default_surface); } if(used_shaders.size() == 0) { - if(material_override) - find_shader(material_override, used_shaders, scene->default_surface); - else - used_shaders.push_back(scene->default_surface); + used_shaders.push_back(scene->default_surface); } /* test if we need to sync */ diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index ed01d728931..a1f39d0848f 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -291,8 +291,8 @@ void BlenderSync::sync_background_light(bool use_portal) /* Object */ Object *BlenderSync::sync_object(BL::Depsgraph& b_depsgraph, + BL::ViewLayer& b_view_layer, BL::DepsgraphObjectInstance& b_instance, - uint layer_flag, float motion_time, bool hide_tris, BlenderObjectCulling& culling, @@ -314,10 +314,13 @@ Object *BlenderSync::sync_object(BL::Depsgraph& b_depsgraph, } /* light is handled separately */ - if(object_is_light(b_ob)) { - /* don't use lights for excluded layers used as mask layer */ - if(!motion && !((layer_flag & view_layer.holdout_layer) && - (layer_flag & view_layer.exclude_layer))) + if(!motion && object_is_light(b_ob)) { + /* TODO: don't use lights for excluded layers used as mask layer, + * when dynamic overrides are back. */ +#if 0 + if(!((layer_flag & view_layer.holdout_layer) && + (layer_flag & view_layer.exclude_layer))) +#endif { sync_light(b_parent, persistent_id, @@ -343,21 +346,24 @@ Object *BlenderSync::sync_object(BL::Depsgraph& b_depsgraph, /* Visibility flags for both parent and child. */ PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles"); - bool use_holdout = (layer_flag & view_layer.holdout_layer) != 0 || - get_boolean(cobject, "is_holdout"); + bool use_holdout = get_boolean(cobject, "is_holdout") || + b_parent.holdout_get(b_view_layer); uint visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL_VISIBILITY; if(b_parent.ptr.data != b_ob.ptr.data) { visibility &= object_ray_visibility(b_parent); } - /* Make holdout objects on excluded layer invisible for non-camera rays. */ + /* TODO: make holdout objects on excluded layer invisible for non-camera rays. */ +#if 0 if(use_holdout && (layer_flag & view_layer.exclude_layer)) { visibility &= ~(PATH_RAY_ALL_VISIBILITY - PATH_RAY_CAMERA); } +#endif - /* Hide objects not on render layer from camera rays. */ - if(!(layer_flag & view_layer.layer)) { + /* Clear camera visibility for indirect only objects. */ + bool use_indirect_only = b_parent.indirect_only_get(b_view_layer); + if(use_indirect_only) { visibility &= ~PATH_RAY_CAMERA; } @@ -583,6 +589,7 @@ void BlenderSync::sync_objects(BL::Depsgraph& b_depsgraph, float motion_time) bool cancel = false; bool use_portal = false; + BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval(); BL::Depsgraph::mode_enum depsgraph_mode = b_depsgraph.mode(); BL::Depsgraph::object_instances_iterator b_instance_iter; @@ -604,8 +611,8 @@ void BlenderSync::sync_objects(BL::Depsgraph& b_depsgraph, float motion_time) if(!object_render_hide(b_ob, true, true, hide_tris, depsgraph_mode)) { /* object itself */ sync_object(b_depsgraph, + b_view_layer, b_instance, - ~(0), /* until we get rid of layers */ motion_time, hide_tris, culling, diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index 4c199f4838f..a79c28e43aa 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -738,6 +738,12 @@ static PyObject *set_resumable_chunk_range_func(PyObject * /*self*/, PyObject *a Py_RETURN_NONE; } +static PyObject *enable_print_stats_func(PyObject * /*self*/, PyObject * /*args*/) +{ + BlenderSession::print_render_stats = true; + Py_RETURN_NONE; +} + static PyObject *get_device_types_func(PyObject * /*self*/, PyObject * /*args*/) { vector<DeviceInfo>& devices = Device::available_devices(); @@ -776,6 +782,9 @@ static PyMethodDef methods[] = { {"debug_flags_update", debug_flags_update_func, METH_VARARGS, ""}, {"debug_flags_reset", debug_flags_reset_func, METH_NOARGS, ""}, + /* Statistics. */ + {"enable_print_stats", enable_print_stats_func, METH_NOARGS, ""}, + /* Resumable render */ {"set_resumable_chunk", set_resumable_chunk_func, METH_VARARGS, ""}, {"set_resumable_chunk_range", set_resumable_chunk_range_func, METH_VARARGS, ""}, diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 1f5d67e4064..2c5ecc02e6d 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -28,6 +28,7 @@ #include "render/scene.h" #include "render/session.h" #include "render/shader.h" +#include "render/stats.h" #include "util/util_color.h" #include "util/util_foreach.h" @@ -48,6 +49,7 @@ int BlenderSession::num_resumable_chunks = 0; int BlenderSession::current_resumable_chunk = 0; int BlenderSession::start_resumable_chunk = 0; int BlenderSession::end_resumable_chunk = 0; +bool BlenderSession::print_render_stats = false; BlenderSession::BlenderSession(BL::RenderEngine& b_engine, BL::UserPreferences& b_userpref, @@ -461,15 +463,13 @@ void BlenderSession::render(BL::Depsgraph& b_depsgraph_) scene->integrator->tag_update(scene); } - /* Update number of samples per layer. */ - int samples = sync->get_layer_samples(); - bool bound_samples = sync->get_layer_bound_samples(); - int effective_layer_samples; + int effective_layer_samples = session_params.samples; + /* TODO: Update number of samples per layer. */ +#if 0 if(samples != 0 && (!bound_samples || (samples < session_params.samples))) effective_layer_samples = samples; - else - effective_layer_samples = session_params.samples; +#endif /* Update tile manager if we're doing resumable render. */ update_resumable_tile_manager(effective_layer_samples); @@ -481,6 +481,12 @@ void BlenderSession::render(BL::Depsgraph& b_depsgraph_) session->start(); session->wait(); + if(!b_engine.is_preview() && background && print_render_stats) { + RenderStats stats; + session->scene->collect_statistics(&stats); + printf("Render statistics:\n%s\n", stats.full_report().c_str()); + } + if(session->progress.get_cancel()) break; } diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index 614da496081..250b8ca9967 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -145,6 +145,8 @@ public: static int start_resumable_chunk; static int end_resumable_chunk; + static bool print_render_stats; + protected: void do_write_update_render_result(BL::RenderResult& b_rr, BL::RenderLayer& b_rlay, diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index e7b6a570131..d19eed0ea6b 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -365,28 +365,11 @@ void BlenderSync::sync_film() void BlenderSync::sync_view_layer(BL::SpaceView3D& /*b_v3d*/, BL::ViewLayer& b_view_layer) { /* render layer */ - uint layer_override = get_layer(b_engine.layer_override()); - uint view_layers = layer_override ? layer_override : get_layer(b_scene.layers()); - view_layer.name = b_view_layer.name(); - - view_layer.holdout_layer = 0; - view_layer.exclude_layer = 0; - - view_layer.view_layer = view_layers & ~view_layer.exclude_layer; - view_layer.view_layer |= view_layer.exclude_layer & view_layer.holdout_layer; - - view_layer.layer = (1 << 20) - 1; - view_layer.layer |= view_layer.holdout_layer; - - view_layer.material_override = PointerRNA_NULL; view_layer.use_background_shader = b_view_layer.use_sky(); view_layer.use_background_ao = b_view_layer.use_ao(); view_layer.use_surfaces = b_view_layer.use_solid(); view_layer.use_hair = b_view_layer.use_strand(); - - view_layer.bound_samples = false; - view_layer.samples = 0; } /* Images */ diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 0465f703c51..e63ef9e5e47 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -78,8 +78,6 @@ public: void sync_view(BL::SpaceView3D& b_v3d, BL::RegionView3D& b_rv3d, int width, int height); - inline int get_layer_samples() { return view_layer.samples; } - inline int get_layer_bound_samples() { return view_layer.bound_samples; } /* get parameters */ static SceneParams get_scene_params(BL::Scene& b_scene, @@ -126,8 +124,8 @@ private: bool motion, int motion_step = 0); Object *sync_object(BL::Depsgraph& b_depsgraph, + BL::ViewLayer& b_view_layer, BL::DepsgraphObjectInstance& b_instance, - uint layer_flag, float motion_time, bool hide_tris, BlenderObjectCulling& culling, @@ -191,28 +189,18 @@ private: struct RenderLayerInfo { RenderLayerInfo() - : view_layer(0), layer(0), - holdout_layer(0), exclude_layer(0), - material_override(PointerRNA_NULL), - use_background_shader(true), + : use_background_shader(true), use_background_ao(true), use_surfaces(true), - use_hair(true), - samples(0), bound_samples(false) + use_hair(true) {} string name; uint view_layer; - uint layer; /* This can be safely removed from Cycles. */ - uint holdout_layer; /* This can be safely removed from Cycles. */ - uint exclude_layer; /* This can be safely removed from Cycles. */ - BL::Material material_override; /* This can be safely removed from Cycles. */ bool use_background_shader; bool use_background_ao; bool use_surfaces; bool use_hair; - int samples; /* This can be safely removed from Cycles. */ - bool bound_samples; /* This can be safely removed from Cycles. */ } view_layer; Progress &progress; diff --git a/intern/cycles/graph/node.cpp b/intern/cycles/graph/node.cpp index 45ffc8d7d6b..5960d9aa7d5 100644 --- a/intern/cycles/graph/node.cpp +++ b/intern/cycles/graph/node.cpp @@ -425,20 +425,22 @@ bool Node::equals(const Node& other) const /* Hash */ +namespace { + template<typename T> -static void value_hash(const Node *node, const SocketType& socket, MD5Hash& md5) +void value_hash(const Node *node, const SocketType& socket, MD5Hash& md5) { md5.append(((uint8_t*)node) + socket.struct_offset, socket.size()); } -static void float3_hash(const Node *node, const SocketType& socket, MD5Hash& md5) +void float3_hash(const Node *node, const SocketType& socket, MD5Hash& md5) { /* Don't compare 4th element used for padding. */ md5.append(((uint8_t*)node) + socket.struct_offset, sizeof(float) * 3); } template<typename T> -static void array_hash(const Node *node, const SocketType& socket, MD5Hash& md5) +void array_hash(const Node *node, const SocketType& socket, MD5Hash& md5) { const array<T>& a = *(const array<T>*)(((char*)node) + socket.struct_offset); for (size_t i = 0; i < a.size(); i++) { @@ -446,7 +448,7 @@ static void array_hash(const Node *node, const SocketType& socket, MD5Hash& md5) } } -static void float3_array_hash(const Node *node, const SocketType& socket, MD5Hash& md5) +void float3_array_hash(const Node *node, const SocketType& socket, MD5Hash& md5) { /* Don't compare 4th element used for padding. */ const array<float3>& a = *(const array<float3>*)(((char*)node) + socket.struct_offset); @@ -455,6 +457,8 @@ static void float3_array_hash(const Node *node, const SocketType& socket, MD5Has } } +} // namespace + void Node::hash(MD5Hash& md5) { md5.append(type->name.string()); @@ -495,4 +499,77 @@ void Node::hash(MD5Hash& md5) } } +namespace { + +template<typename T> +size_t array_size_in_bytes(const Node *node, const SocketType& socket) +{ + const array<T>& a = *(const array<T>*)(((char*)node) + socket.struct_offset); + return a.size() * sizeof(T); +} + +} // namespace + +size_t Node::get_total_size_in_bytes() const +{ + size_t total_size = 0; + foreach(const SocketType& socket, type->inputs) { + switch(socket.type) { + case SocketType::BOOLEAN: + case SocketType::FLOAT: + case SocketType::INT: + case SocketType::UINT: + case SocketType::COLOR: + case SocketType::VECTOR: + case SocketType::POINT: + case SocketType::NORMAL: + case SocketType::POINT2: + case SocketType::CLOSURE: + case SocketType::STRING: + case SocketType::ENUM: + case SocketType::TRANSFORM: + case SocketType::NODE: + total_size += socket.size(); + break; + + case SocketType::BOOLEAN_ARRAY: + total_size += array_size_in_bytes<bool>(this, socket); + break; + case SocketType::FLOAT_ARRAY: + total_size += array_size_in_bytes<float>(this, socket); + break; + case SocketType::INT_ARRAY: + total_size += array_size_in_bytes<int>(this, socket); + break; + case SocketType::COLOR_ARRAY: + total_size += array_size_in_bytes<float3>(this, socket); + break; + case SocketType::VECTOR_ARRAY: + total_size += array_size_in_bytes<float3>(this, socket); + break; + case SocketType::POINT_ARRAY: + total_size += array_size_in_bytes<float3>(this, socket); + break; + case SocketType::NORMAL_ARRAY: + total_size += array_size_in_bytes<float3>(this, socket); + break; + case SocketType::POINT2_ARRAY: + total_size += array_size_in_bytes<float2>(this, socket); + break; + case SocketType::STRING_ARRAY: + total_size += array_size_in_bytes<ustring>(this, socket); + break; + case SocketType::TRANSFORM_ARRAY: + total_size += array_size_in_bytes<Transform>(this, socket); + break; + case SocketType::NODE_ARRAY: + total_size += array_size_in_bytes<void*>(this, socket); + break; + + case SocketType::UNDEFINED: break; + } + } + return total_size; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/graph/node.h b/intern/cycles/graph/node.h index a738bfe197e..11695a8631d 100644 --- a/intern/cycles/graph/node.h +++ b/intern/cycles/graph/node.h @@ -92,6 +92,9 @@ struct Node /* compute hash of node and its socket values */ void hash(MD5Hash& md5); + /* Get total size of this node. */ + size_t get_total_size_in_bytes() const; + ustring name; const NodeType *type; }; diff --git a/intern/cycles/graph/node_type.cpp b/intern/cycles/graph/node_type.cpp index 671ae2d815a..e045777e969 100644 --- a/intern/cycles/graph/node_type.cpp +++ b/intern/cycles/graph/node_type.cpp @@ -134,7 +134,7 @@ NodeType::~NodeType() void NodeType::register_input(ustring name, ustring ui_name, SocketType::Type type, int struct_offset, const void *default_value, const NodeEnum *enum_values, - const NodeType **node_type, int flags, int extra_flags) + const NodeType **node_type, int flags, int extra_flags) { SocketType socket; socket.name = name; diff --git a/intern/cycles/graph/node_type.h b/intern/cycles/graph/node_type.h index d4e2dbceff6..1d565794b27 100644 --- a/intern/cycles/graph/node_type.h +++ b/intern/cycles/graph/node_type.h @@ -114,9 +114,9 @@ struct NodeType void register_input(ustring name, ustring ui_name, SocketType::Type type, int struct_offset, const void *default_value, - const NodeEnum *enum_values = NULL, - const NodeType **node_type = NULL, - int flags = 0, int extra_flags = 0); + const NodeEnum *enum_values = NULL, + const NodeType **node_type = NULL, + int flags = 0, int extra_flags = 0); void register_output(ustring name, ustring ui_name, SocketType::Type type); const SocketType *find_input(ustring name) const; diff --git a/intern/cycles/kernel/kernel_montecarlo.h b/intern/cycles/kernel/kernel_montecarlo.h index 49dc1f08cc1..09a3fe8f23d 100644 --- a/intern/cycles/kernel/kernel_montecarlo.h +++ b/intern/cycles/kernel/kernel_montecarlo.h @@ -184,6 +184,35 @@ ccl_device float2 regular_polygon_sample(float corners, float rotation, float u, return make_float2(cr*p.x - sr*p.y, sr*p.x + cr*p.y); } +ccl_device float3 ensure_valid_reflection(float3 Ng, float3 I, float3 N) +{ + float3 R = 2*dot(N, I)*N - I; + if(dot(Ng, R) >= 0.05f) { + return N; + } + + /* Form coordinate system with Ng as the Z axis and N inside the X-Z-plane. + * The X axis is found by normalizing the component of N that's orthogonal to Ng. + * The Y axis isn't actually needed. + */ + float3 X = normalize(N - dot(N, Ng)*Ng); + + /* Calculate N.z and N.x in the local coordinate system. */ + float Iz = dot(I, Ng); + float Ix2 = sqr(dot(I, X)), Iz2 = sqr(Iz); + float Ix2Iz2 = Ix2 + Iz2; + + float a = sqrtf(Ix2*(Ix2Iz2 - sqr(0.05f))); + float b = Iz*0.05f + Ix2Iz2; + float c = (a + b > 0.0f)? (a + b) : (-a + b); + + float Nz = sqrtf(0.5f * c * (1.0f / Ix2Iz2)); + float Nx = sqrtf(1.0f - sqr(Nz)); + + /* Transform back into global coordinates. */ + return Nx*X + Nz*Ng; +} + CCL_NAMESPACE_END #endif /* __KERNEL_MONTECARLO_CL__ */ diff --git a/intern/cycles/kernel/shaders/node_bump.osl b/intern/cycles/kernel/shaders/node_bump.osl index 7f01cf2ca91..a2a4468d5f3 100644 --- a/intern/cycles/kernel/shaders/node_bump.osl +++ b/intern/cycles/kernel/shaders/node_bump.osl @@ -64,5 +64,7 @@ surface node_bump( if (use_object_space) { NormalOut = normalize(transform("object", "world", NormalOut)); } + + NormalOut = ensure_valid_reflection(Ng, I, NormalOut); } diff --git a/intern/cycles/kernel/shaders/node_normal_map.osl b/intern/cycles/kernel/shaders/node_normal_map.osl index 41bcac4fb10..fda6f12a5da 100644 --- a/intern/cycles/kernel/shaders/node_normal_map.osl +++ b/intern/cycles/kernel/shaders/node_normal_map.osl @@ -88,5 +88,7 @@ shader node_normal_map( if (Strength != 1.0) Normal = normalize(NormalIn + (Normal - NormalIn) * max(Strength, 0.0)); + + Normal = ensure_valid_reflection(Ng, I, Normal); } diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h index df9c2010872..4a8378796ba 100644 --- a/intern/cycles/kernel/shaders/stdosl.h +++ b/intern/cycles/kernel/shaders/stdosl.h @@ -282,6 +282,36 @@ point rotate (point p, float angle, point a, point b) return transform (M, p-a) + a; } +normal ensure_valid_reflection(normal Ng, vector I, normal N) +{ + float sqr(float x) { return x*x; } + + vector R = 2*dot(N, I)*N - I; + if (dot(Ng, R) >= 0.05) { + return N; + } + + /* Form coordinate system with Ng as the Z axis and N inside the X-Z-plane. + * The X axis is found by normalizing the component of N that's orthogonal to Ng. + * The Y axis isn't actually needed. + */ + vector X = normalize(N - dot(N, Ng)*Ng); + + /* Calculate N.z and N.x in the local coordinate system. */ + float Ix = dot(I, X), Iz = dot(I, Ng); + float Ix2 = sqr(dot(I, X)), Iz2 = sqr(dot(I, Ng)); + float Ix2Iz2 = Ix2 + Iz2; + + float a = sqrt(Ix2*(Ix2Iz2 - sqr(0.05))); + float b = Iz*0.05 + Ix2Iz2; + float c = (a + b > 0.0)? (a + b) : (-a + b); + + float Nz = sqrt(0.5 * c * (1.0 / Ix2Iz2)); + float Nx = sqrt(1.0 - sqr(Nz)); + + /* Transform back into global coordinates. */ + return Nx*X + Nz*Ng; +} // Color functions diff --git a/intern/cycles/kernel/svm/svm_displace.h b/intern/cycles/kernel/svm/svm_displace.h index b85eb9c0458..0f5b3abef87 100644 --- a/intern/cycles/kernel/svm/svm_displace.h +++ b/intern/cycles/kernel/svm/svm_displace.h @@ -75,6 +75,8 @@ ccl_device void svm_node_set_bump(KernelGlobals *kg, ShaderData *sd, float *stac object_normal_transform(kg, sd, &normal_out); } + normal_out = ensure_valid_reflection(sd->Ng, sd->I, normal_out); + stack_store_float3(stack, node.w, normal_out); #endif } diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h index 7c207083929..45c38d64763 100644 --- a/intern/cycles/kernel/svm/svm_tex_coord.h +++ b/intern/cycles/kernel/svm/svm_tex_coord.h @@ -345,6 +345,8 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st N = safe_normalize(sd->N + (N - sd->N)*strength); } + N = ensure_valid_reflection(sd->Ng, sd->I, N); + if(is_zero(N)) { N = sd->N; } diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt index b7248354abd..7d2220f37f9 100644 --- a/intern/cycles/render/CMakeLists.txt +++ b/intern/cycles/render/CMakeLists.txt @@ -33,6 +33,7 @@ set(SRC session.cpp shader.cpp sobol.cpp + stats.cpp svm.cpp tables.cpp tile.cpp @@ -60,6 +61,7 @@ set(SRC_HEADERS session.h shader.h sobol.h + stats.h svm.h tables.h tile.h diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 94f3f38ec7a..bead0118a02 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -17,6 +17,7 @@ #include "device/device.h" #include "render/image.h" #include "render/scene.h" +#include "render/stats.h" #include "util/util_foreach.h" #include "util/util_logging.h" @@ -30,20 +31,58 @@ CCL_NAMESPACE_BEGIN +namespace { + /* Some helpers to silence warning in templated function. */ -static bool isfinite(uchar /*value*/) +bool isfinite(uchar /*value*/) { return true; } -static bool isfinite(half /*value*/) +bool isfinite(half /*value*/) { return true; } -static bool isfinite(uint16_t /*value*/) +bool isfinite(uint16_t /*value*/) { return true; } +/* The lower three bits of a device texture slot number indicate its type. + * These functions convert the slot ids from ImageManager "images" ones + * to device ones and vice verse. + */ +int type_index_to_flattened_slot(int slot, ImageDataType type) +{ + return (slot << IMAGE_DATA_TYPE_SHIFT) | (type); +} + +int flattened_slot_to_type_index(int flat_slot, ImageDataType *type) +{ + *type = (ImageDataType)(flat_slot & IMAGE_DATA_TYPE_MASK); + return flat_slot >> IMAGE_DATA_TYPE_SHIFT; +} + +const char* name_from_type(ImageDataType type) +{ + switch(type) { + case IMAGE_DATA_TYPE_FLOAT4: return "float4"; + case IMAGE_DATA_TYPE_BYTE4: return "byte4"; + case IMAGE_DATA_TYPE_HALF4: return "half4"; + case IMAGE_DATA_TYPE_FLOAT: return "float"; + case IMAGE_DATA_TYPE_BYTE: return "byte"; + case IMAGE_DATA_TYPE_HALF: return "half"; + case IMAGE_DATA_TYPE_USHORT4: return "ushort4"; + case IMAGE_DATA_TYPE_USHORT: return "ushort"; + case IMAGE_DATA_NUM_TYPES: + assert(!"System enumerator type, should never be used"); + return ""; + } + assert(!"Unhandled image data type"); + return ""; +} + +} // namespace + ImageManager::ImageManager(const DeviceInfo& info) { need_update = true; @@ -90,12 +129,12 @@ bool ImageManager::set_animation_frame_update(int frame) device_memory *ImageManager::image_memory(int flat_slot) { - ImageDataType type; - int slot = flattened_slot_to_type_index(flat_slot, &type); + ImageDataType type; + int slot = flattened_slot_to_type_index(flat_slot, &type); - Image *img = images[type][slot]; + Image *img = images[type][slot]; - return img->mem; + return img->mem; } bool ImageManager::get_image_metadata(int flat_slot, @@ -133,10 +172,12 @@ bool ImageManager::get_image_metadata(const string& filename, if(metadata.is_float) { metadata.is_linear = true; - metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT; + metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 + : IMAGE_DATA_TYPE_FLOAT; } else { - metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE; + metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4 + : IMAGE_DATA_TYPE_BYTE; } return true; @@ -148,7 +189,8 @@ bool ImageManager::get_image_metadata(const string& filename, return false; } if(path_is_directory(filename)) { - VLOG(1) << "File '" << filename << "' is a directory, can't use as image."; + VLOG(1) << "File '" << filename + << "' is a directory, can't use as image."; return false; } @@ -211,16 +253,20 @@ bool ImageManager::get_image_metadata(const string& filename, metadata.channels = spec.nchannels; if(metadata.is_half) { - metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_HALF4 : IMAGE_DATA_TYPE_HALF; + metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_HALF4 + : IMAGE_DATA_TYPE_HALF; } else if(metadata.is_float) { - metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT; + metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 + : IMAGE_DATA_TYPE_FLOAT; } else if(spec.format == TypeDesc::USHORT) { - metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_USHORT4 : IMAGE_DATA_TYPE_USHORT; + metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_USHORT4 + : IMAGE_DATA_TYPE_USHORT; } else { - metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE; + metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4 + : IMAGE_DATA_TYPE_BYTE; } in->close(); @@ -229,50 +275,6 @@ bool ImageManager::get_image_metadata(const string& filename, return true; } -int ImageManager::max_flattened_slot(ImageDataType type) -{ - if(tex_num_images[type] == 0) { - /* No textures for the type, no slots needs allocation. */ - return 0; - } - return type_index_to_flattened_slot(tex_num_images[type], type); -} - -/* The lower three bits of a device texture slot number indicate its type. - * These functions convert the slot ids from ImageManager "images" ones - * to device ones and vice verse. - */ -int ImageManager::type_index_to_flattened_slot(int slot, ImageDataType type) -{ - return (slot << IMAGE_DATA_TYPE_SHIFT) | (type); -} - -int ImageManager::flattened_slot_to_type_index(int flat_slot, ImageDataType *type) -{ - *type = (ImageDataType)(flat_slot & IMAGE_DATA_TYPE_MASK); - return flat_slot >> IMAGE_DATA_TYPE_SHIFT; -} - -string ImageManager::name_from_type(int type) -{ - if(type == IMAGE_DATA_TYPE_FLOAT4) - return "float4"; - else if(type == IMAGE_DATA_TYPE_FLOAT) - return "float"; - else if(type == IMAGE_DATA_TYPE_BYTE) - return "byte"; - else if(type == IMAGE_DATA_TYPE_HALF4) - return "half4"; - else if(type == IMAGE_DATA_TYPE_HALF) - return "half"; - else if(type == IMAGE_DATA_TYPE_USHORT) - return "ushort"; - else if(type == IMAGE_DATA_TYPE_USHORT4) - return "ushort4"; - else - return "byte4"; -} - static bool image_equals(ImageManager::Image *image, const string& filename, void *builtin_data, @@ -348,14 +350,16 @@ int ImageManager::add_image(const string& filename, } /* Count if we're over the limit. - * Very unlikely, since max_num_images is insanely big. But better safe than sorry. */ + * Very unlikely, since max_num_images is insanely big. But better safe + * than sorry. + */ int tex_count = 0; for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) { tex_count += tex_num_images[type]; } if(tex_count > max_num_images) { - printf("ImageManager::add_image: Reached image limit (%d), skipping '%s'\n", - max_num_images, filename.c_str()); + printf("ImageManager::add_image: Reached image limit (%d), " + "skipping '%s'\n", max_num_images, filename.c_str()); return -1; } @@ -743,7 +747,8 @@ void ImageManager::device_load_image(Device *device, /* Slot assignment */ int flat_slot = type_index_to_flattened_slot(slot, type); - img->mem_name = string_printf("__tex_image_%s_%03d", name_from_type(type).c_str(), flat_slot); + img->mem_name = string_printf("__tex_image_%s_%03d", + name_from_type(type), flat_slot); /* Free previous texture in slot. */ if(img->mem) { @@ -1082,4 +1087,15 @@ void ImageManager::device_free(Device *device) } } +void ImageManager::collect_statistics(RenderStats *stats) +{ + for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) { + foreach(const Image *image, images[type]) { + stats->image.textures.add_entry( + NamedSizeEntry(path_filename(image->filename), + image->mem->memory_size())); + } + } +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 5039abaa67e..c8996b70b38 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -29,6 +29,7 @@ CCL_NAMESPACE_BEGIN class Device; class Progress; +class RenderStats; class Scene; class ImageMetaData { @@ -96,6 +97,8 @@ public: device_memory *image_memory(int flat_slot); + void collect_statistics(RenderStats *stats); + bool need_update; /* NOTE: Here pixels_size is a size of storage, which equals to @@ -159,16 +162,11 @@ private: int texture_limit, device_vector<DeviceType>& tex_img); - int max_flattened_slot(ImageDataType type); - int type_index_to_flattened_slot(int slot, ImageDataType type); - int flattened_slot_to_type_index(int flat_slot, ImageDataType *type); - string name_from_type(int type); - void device_load_image(Device *device, Scene *scene, ImageDataType type, int slot, - Progress *progess); + Progress *progress); void device_free_image(Device *device, ImageDataType type, int slot); diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 787814dba6b..3b85186948e 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -27,6 +27,7 @@ #include "render/nodes.h" #include "render/object.h" #include "render/scene.h" +#include "render/stats.h" #include "kernel/osl/osl_globals.h" @@ -2069,8 +2070,8 @@ void MeshManager::device_update_displacement_images(Device *device, } void MeshManager::device_update_volume_images(Device *device, - Scene *scene, - Progress& progress) + Scene *scene, + Progress& progress) { progress.set_status("Updating Volume Images"); TaskPool pool; @@ -2097,11 +2098,11 @@ void MeshManager::device_update_volume_images(Device *device, foreach(int slot, volume_images) { pool.push(function_bind(&ImageManager::device_update_slot, - image_manager, - device, - scene, - slot, - &progress)); + image_manager, + device, + scene, + slot, + &progress)); } pool.wait_work(); } @@ -2330,6 +2331,15 @@ void MeshManager::tag_update(Scene *scene) scene->object_manager->need_update = true; } +void MeshManager::collect_statistics(const Scene *scene, RenderStats *stats) +{ + foreach(Mesh *mesh, scene->meshes) { + stats->mesh.geometry.add_entry( + NamedSizeEntry(string(mesh->name.c_str()), + mesh->get_total_size_in_bytes())); + } +} + bool Mesh::need_attribute(Scene *scene, AttributeStandard std) { if(std == ATTR_STD_NONE) diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index e73291afaa3..0cd3919a49c 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -38,6 +38,7 @@ class Device; class DeviceScene; class Mesh; class Progress; +class RenderStats; class Scene; class SceneParams; class AttributeRequest; @@ -353,6 +354,8 @@ public: void create_volume_mesh(Scene *scene, Mesh *mesh, Progress &progress); + void collect_statistics(const Scene *scene, RenderStats *stats); + protected: /* Calculate verts/triangles/curves offsets in global arrays. */ void mesh_calc_offset(Scene *scene); @@ -383,8 +386,8 @@ protected: Progress& progress); void device_update_volume_images(Device *device, - Scene *scene, - Progress& progress); + Scene *scene, + Progress& progress); }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 1d65ef65980..9f93fed139c 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -379,4 +379,10 @@ void Scene::device_free() free_memory(false); } +void Scene::collect_statistics(RenderStats *stats) +{ + mesh_manager->collect_statistics(this, stats); + image_manager->collect_statistics(stats); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index c4597c0e455..c107a0b073d 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -56,6 +56,7 @@ class ShaderManager; class Progress; class BakeManager; class BakeData; +class RenderStats; /* Scene Device Data */ @@ -257,6 +258,8 @@ public: void reset(); void device_free(); + void collect_statistics(RenderStats *stats); + protected: /* Check if some heavy data worth logging was updated. * Mainly used to suppress extra annoying logging. diff --git a/intern/cycles/render/stats.cpp b/intern/cycles/render/stats.cpp new file mode 100644 index 00000000000..101d33fcf65 --- /dev/null +++ b/intern/cycles/render/stats.cpp @@ -0,0 +1,119 @@ +/* + * Copyright 2011-2018 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "render/stats.h" +#include "util/util_algorithm.h" +#include "util/util_foreach.h" +#include "util/util_string.h" + +CCL_NAMESPACE_BEGIN + +static int kIndentNumSpaces = 2; + +/* Named size entry. */ + +namespace { + +bool namedSizeEntryComparator(const NamedSizeEntry& a, const NamedSizeEntry& b) +{ + /* We sort in descending order. */ + return a.size > b.size; +} + +} // namespace + +NamedSizeEntry::NamedSizeEntry() + : name(""), + size(0) { +} + +NamedSizeEntry::NamedSizeEntry(const string& name, size_t size) + : name(name), + size(size) { +} + +/* Named size statistics. */ + +NamedSizeStats::NamedSizeStats() + : total_size(0) { +} + +void NamedSizeStats::add_entry(const NamedSizeEntry& entry) { + total_size += entry.size; + entries.push_back(entry); +} + +string NamedSizeStats::full_report(int indent_level) +{ + const string indent(indent_level * kIndentNumSpaces, ' '); + const string double_indent = indent + indent; + string result = ""; + result += string_printf("%sTotal memory: %s (%s)\n", + indent.c_str(), + string_human_readable_size(total_size).c_str(), + string_human_readable_number(total_size).c_str()); + sort(entries.begin(), entries.end(), namedSizeEntryComparator); + foreach(const NamedSizeEntry& entry, entries) { + result += string_printf( + "%s%-32s %s (%s)\n", + double_indent.c_str(), + entry.name.c_str(), + string_human_readable_size(entry.size).c_str(), + string_human_readable_number(entry.size).c_str()); + } + return result; +} + +/* Mesh statistics. */ + +MeshStats::MeshStats() { +} + +string MeshStats::full_report(int indent_level) +{ + const string indent(indent_level * kIndentNumSpaces, ' '); + string result = ""; + result += indent + "Geometry:\n" + geometry.full_report(indent_level + 1); + return result; +} + +/* Image statistics. */ + +ImageStats::ImageStats() { +} + +string ImageStats::full_report(int indent_level) +{ + const string indent(indent_level * kIndentNumSpaces, ' '); + string result = ""; + result += indent + "Textures:\n" + textures.full_report(indent_level + 1); + return result; +} + +/* Overall statistics. */ + +RenderStats::RenderStats() { +} + +string RenderStats::full_report() +{ + string result = ""; + result += "Mesh statistics:\n" + mesh.full_report(1); + result += "Image statistics:\n" + image.full_report(1); + return result; +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/render/stats.h b/intern/cycles/render/stats.h new file mode 100644 index 00000000000..72d5f1dd93d --- /dev/null +++ b/intern/cycles/render/stats.h @@ -0,0 +1,104 @@ +/* + * Copyright 2011-2018 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __RENDER_STATS_H__ +#define __RENDER_STATS_H__ + +#include "util/util_string.h" +#include "util/util_vector.h" + +CCL_NAMESPACE_BEGIN + +/* Named statistics entry, which corresponds to a size. There is no real + * semantic around the units of size, it just should be the same for all + * entries. + * + * This is a generic entry foi all size-related statistics, which helps + * avoiding duplicating code for things like sorting. + */ +class NamedSizeEntry { +public: + NamedSizeEntry(); + NamedSizeEntry(const string& name, size_t size); + + string name; + size_t size; +}; + +/* Container of named size entries. Used, for example, to store per-mesh memory + * usage statistics. But also keeps track of overall memory usage of the + * container. + */ +class NamedSizeStats { +public: + NamedSizeStats(); + + /* Add entry to the statistics. */ + void add_entry(const NamedSizeEntry& entry); + + /* Generate full human-readable report. */ + string full_report(int indent_level = 0); + + /* Total size of all entries. */ + size_t total_size; + + /* NOTE: Is fine to read directly, but for adding use add_entry(), which + * makes sure all accumulating values are properly updated. + */ + vector<NamedSizeEntry> entries; +}; + +/* Statistics about mesh in the render database. */ +class MeshStats { +public: + MeshStats(); + + /* Generate full human-readable report. */ + string full_report(int indent_level = 0); + + /* Input geometry statistics, this is what is coming as an input to render + * from. say, Blender. This does not include runtime or engine specific + * memory like BVH. + */ + NamedSizeStats geometry; +}; + +/* Statistics about images held in memory. */ +class ImageStats { +public: + ImageStats(); + + /* Generate full human-readable report. */ + string full_report(int indent_level = 0); + + NamedSizeStats textures; +}; + +/* Render process statistics. */ +class RenderStats { +public: + RenderStats(); + + /* Return full report as string. */ + string full_report(); + + MeshStats mesh; + ImageStats image; +}; + +CCL_NAMESPACE_END + +#endif /* __RENDER_STATS_H__ */ diff --git a/intern/ghost/intern/GHOST_ContextSDL.cpp b/intern/ghost/intern/GHOST_ContextSDL.cpp index 1ba591bd0b2..3b3cf7a2962 100644 --- a/intern/ghost/intern/GHOST_ContextSDL.cpp +++ b/intern/ghost/intern/GHOST_ContextSDL.cpp @@ -55,6 +55,7 @@ GHOST_ContextSDL::GHOST_ContextSDL( int contextResetNotificationStrategy) : GHOST_Context(stereoVisual, numOfAASamples), m_window(window), + m_hidden_window(NULL), m_contextProfileMask(contextProfileMask), m_contextMajorVersion(contextMajorVersion), m_contextMinorVersion(contextMinorVersion), @@ -62,7 +63,7 @@ GHOST_ContextSDL::GHOST_ContextSDL( m_contextResetNotificationStrategy(contextResetNotificationStrategy), m_context(NULL) { - assert(m_window != NULL); + // assert(m_window != NULL); } @@ -70,7 +71,7 @@ GHOST_ContextSDL::~GHOST_ContextSDL() { if (m_context != NULL) { if (m_window != NULL && m_context == SDL_GL_GetCurrentContext()) - SDL_GL_MakeCurrent(m_window, m_context); + SDL_GL_MakeCurrent(m_window, NULL); if (m_context != s_sharedContext || s_sharedCount == 1) { assert(s_sharedCount > 0); @@ -82,6 +83,9 @@ GHOST_ContextSDL::~GHOST_ContextSDL() SDL_GL_DeleteContext(m_context); } + + if (m_hidden_window != NULL) + SDL_DestroyWindow(m_hidden_window); } } @@ -160,6 +164,18 @@ GHOST_TSuccess GHOST_ContextSDL::initializeDrawingContext() SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, m_numOfAASamples); } + if (m_window == NULL) { + m_hidden_window = SDL_CreateWindow( + "Offscreen Context Windows", + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + 1, 1, + SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_HIDDEN + ); + + m_window = m_hidden_window; + } + m_context = SDL_GL_CreateContext(m_window); GHOST_TSuccess success; diff --git a/intern/ghost/intern/GHOST_ContextSDL.h b/intern/ghost/intern/GHOST_ContextSDL.h index 681d24bb7c6..1829819300c 100644 --- a/intern/ghost/intern/GHOST_ContextSDL.h +++ b/intern/ghost/intern/GHOST_ContextSDL.h @@ -120,6 +120,7 @@ public: private: SDL_Window *m_window; + SDL_Window *m_hidden_window; const int m_contextProfileMask; const int m_contextMajorVersion; diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index 0629eacc3ff..c3fd87c65af 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -297,7 +297,9 @@ GHOST_TSuccess GHOST_System::getButtonState(GHOST_TButtonMask mask, bool& isDown #ifdef WITH_INPUT_NDOF void GHOST_System::setNDOFDeadZone(float deadzone) { - this->m_ndofManager->setDeadZone(deadzone); + if (this->m_ndofManager) { + this->m_ndofManager->setDeadZone(deadzone); + } } #endif diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp index d7860577338..094cbe76cb2 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.cpp +++ b/intern/ghost/intern/GHOST_SystemSDL.cpp @@ -26,6 +26,7 @@ #include <assert.h> +#include "GHOST_ContextSDL.h" #include "GHOST_SystemSDL.h" #include "GHOST_WindowSDL.h" @@ -149,6 +150,34 @@ GHOST_SystemSDL::getNumDisplays() const return SDL_GetNumVideoDisplays(); } +GHOST_IContext * +GHOST_SystemSDL::createOffscreenContext() +{ + GHOST_Context *context = new GHOST_ContextSDL( + 0, + 0, + NULL, + 0, // profile bit + 3, 3, + GHOST_OPENGL_SDL_CONTEXT_FLAGS, + GHOST_OPENGL_SDL_RESET_NOTIFICATION_STRATEGY); + + if (context->initializeDrawingContext()) + return context; + else + delete context; + + return NULL; +} + +GHOST_TSuccess +GHOST_SystemSDL::disposeContext(GHOST_IContext *context) +{ + delete context; + + return GHOST_kSuccess; +} + GHOST_TSuccess GHOST_SystemSDL::getModifierKeys(GHOST_ModifierKeys& keys) const { diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h index 41f110ed15d..0610a80ea5f 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.h +++ b/intern/ghost/intern/GHOST_SystemSDL.h @@ -95,6 +95,12 @@ public: getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const; + GHOST_IContext * + createOffscreenContext(); + + GHOST_TSuccess + disposeContext(GHOST_IContext *context); + /** * Informs if the system provides native dialogs (eg. confirm quit) */ diff --git a/intern/ghost/intern/GHOST_WindowSDL.cpp b/intern/ghost/intern/GHOST_WindowSDL.cpp index aeb6188daef..9c41087bd59 100644 --- a/intern/ghost/intern/GHOST_WindowSDL.cpp +++ b/intern/ghost/intern/GHOST_WindowSDL.cpp @@ -93,7 +93,7 @@ GHOST_WindowSDL::newDrawingContext(GHOST_TDrawingContextType type) m_wantNumOfAASamples, m_sdl_win, 0, // profile bit - 0, 0, + 3, 3, GHOST_OPENGL_SDL_CONTEXT_FLAGS, GHOST_OPENGL_SDL_RESET_NOTIFICATION_STRATEGY); diff --git a/intern/rigidbody/RBI_api.h b/intern/rigidbody/RBI_api.h index 556ca959e64..eec94bcea50 100644 --- a/intern/rigidbody/RBI_api.h +++ b/intern/rigidbody/RBI_api.h @@ -268,6 +268,7 @@ rbConstraint *RB_constraint_new_slider(float pivot[3], float orn[4], rbRigidBody rbConstraint *RB_constraint_new_piston(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2); rbConstraint *RB_constraint_new_6dof(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2); rbConstraint *RB_constraint_new_6dof_spring(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2); +rbConstraint *RB_constraint_new_6dof_spring2(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2); rbConstraint *RB_constraint_new_motor(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2); /* ............ */ @@ -299,12 +300,18 @@ void RB_constraint_set_limits_piston(rbConstraint *con, float lin_lower, float l void RB_constraint_set_limits_6dof(rbConstraint *con, int axis, float lower, float upper); /* 6dof spring specific */ -void RB_constraint_set_limits_6dof_spring(rbConstraint *con, int axis, float lower, float upper); void RB_constraint_set_stiffness_6dof_spring(rbConstraint *con, int axis, float stiffness); void RB_constraint_set_damping_6dof_spring(rbConstraint *con, int axis, float damping); void RB_constraint_set_spring_6dof_spring(rbConstraint *con, int axis, int enable); void RB_constraint_set_equilibrium_6dof_spring(rbConstraint *con); +/* 6dof spring 2 specific */ +void RB_constraint_set_limits_6dof_spring2(rbConstraint *con, int axis, float lower, float upper); +void RB_constraint_set_stiffness_6dof_spring2(rbConstraint *con, int axis, float stiffness); +void RB_constraint_set_damping_6dof_spring2(rbConstraint *con, int axis, float damping); +void RB_constraint_set_spring_6dof_spring2(rbConstraint *con, int axis, int enable); +void RB_constraint_set_equilibrium_6dof_spring2(rbConstraint *con); + /* motors */ void RB_constraint_set_enable_motor(rbConstraint *con, int enable_lin, int enable_ang); void RB_constraint_set_max_impulse_motor(rbConstraint *con, float max_impulse_lin, float max_impulse_ang); diff --git a/intern/rigidbody/rb_bullet_api.cpp b/intern/rigidbody/rb_bullet_api.cpp index a9fbcb28529..6a50c5c93ee 100644 --- a/intern/rigidbody/rb_bullet_api.cpp +++ b/intern/rigidbody/rb_bullet_api.cpp @@ -954,11 +954,25 @@ rbConstraint *RB_constraint_new_6dof_spring(float pivot[3], float orn[4], rbRigi make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn); - btTypedConstraint *con = new btGeneric6DofSpring2Constraint(*body1, *body2, transform1, transform2); + btTypedConstraint *con = new btGeneric6DofSpringConstraint(*body1, *body2, transform1, transform2, true); return (rbConstraint *)con; } +rbConstraint *RB_constraint_new_6dof_spring2(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2) +{ + btRigidBody *body1 = rb1->body; + btRigidBody *body2 = rb2->body; + btTransform transform1; + btTransform transform2; + + make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn); + + btTypedConstraint *con = new btGeneric6DofSpring2Constraint(*body1, *body2, transform1, transform2); + + return (rbConstraint *)con; +} + rbConstraint *RB_constraint_new_motor(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2) { btRigidBody *body1 = rb1->body; @@ -1034,7 +1048,7 @@ void RB_constraint_set_limits_6dof(rbConstraint *con, int axis, float lower, flo constraint->setLimit(axis, lower, upper); } -void RB_constraint_set_limits_6dof_spring(rbConstraint *con, int axis, float lower, float upper) +void RB_constraint_set_limits_6dof_spring2(rbConstraint *con, int axis, float lower, float upper) { btGeneric6DofSpring2Constraint *constraint = reinterpret_cast<btGeneric6DofSpring2Constraint*>(con); @@ -1043,27 +1057,58 @@ void RB_constraint_set_limits_6dof_spring(rbConstraint *con, int axis, float low void RB_constraint_set_stiffness_6dof_spring(rbConstraint *con, int axis, float stiffness) { - btGeneric6DofSpring2Constraint *constraint = reinterpret_cast<btGeneric6DofSpring2Constraint*>(con); + btGeneric6DofSpringConstraint *constraint = reinterpret_cast<btGeneric6DofSpringConstraint*>(con); constraint->setStiffness(axis, stiffness); } void RB_constraint_set_damping_6dof_spring(rbConstraint *con, int axis, float damping) { - btGeneric6DofSpring2Constraint *constraint = reinterpret_cast<btGeneric6DofSpring2Constraint*>(con); + btGeneric6DofSpringConstraint *constraint = reinterpret_cast<btGeneric6DofSpringConstraint*>(con); + + // invert damping range so that 0 = no damping + damping = (damping > 1.0f) ? 0.0f : 1.0f - damping; constraint->setDamping(axis, damping); } void RB_constraint_set_spring_6dof_spring(rbConstraint *con, int axis, int enable) { - btGeneric6DofSpring2Constraint *constraint = reinterpret_cast<btGeneric6DofSpring2Constraint*>(con); + btGeneric6DofSpringConstraint *constraint = reinterpret_cast<btGeneric6DofSpringConstraint*>(con); constraint->enableSpring(axis, enable); } void RB_constraint_set_equilibrium_6dof_spring(rbConstraint *con) { + btGeneric6DofSpringConstraint *constraint = reinterpret_cast<btGeneric6DofSpringConstraint*>(con); + + constraint->setEquilibriumPoint(); +} + +void RB_constraint_set_stiffness_6dof_spring2(rbConstraint *con, int axis, float stiffness) +{ + btGeneric6DofSpring2Constraint *constraint = reinterpret_cast<btGeneric6DofSpring2Constraint*>(con); + + constraint->setStiffness(axis, stiffness); +} + +void RB_constraint_set_damping_6dof_spring2(rbConstraint *con, int axis, float damping) +{ + btGeneric6DofSpring2Constraint *constraint = reinterpret_cast<btGeneric6DofSpring2Constraint*>(con); + + constraint->setDamping(axis, damping); +} + +void RB_constraint_set_spring_6dof_spring2(rbConstraint *con, int axis, int enable) +{ + btGeneric6DofSpring2Constraint *constraint = reinterpret_cast<btGeneric6DofSpring2Constraint*>(con); + + constraint->enableSpring(axis, enable); +} + +void RB_constraint_set_equilibrium_6dof_spring2(rbConstraint *con) +{ btGeneric6DofSpring2Constraint *constraint = reinterpret_cast<btGeneric6DofSpring2Constraint*>(con); constraint->setEquilibriumPoint(); diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py index 7719e2f6e30..fff73a4285a 100644 --- a/release/scripts/modules/bpy_extras/object_utils.py +++ b/release/scripts/modules/bpy_extras/object_utils.py @@ -166,7 +166,7 @@ def object_data_add(context, obdata, operator=None, name=None): obj_act.select_set(action='SELECT') scene.update() # apply location - # scene.objects.active = obj_new + # layer.objects.active = obj_new # Match up UV layers, this is needed so adding an object with UV's # doesn't create new layers when there happens to be a naming mis-match. diff --git a/release/scripts/startup/bl_operators/clip.py b/release/scripts/startup/bl_operators/clip.py index 2717a4f62a3..a94076ab61b 100644 --- a/release/scripts/startup/bl_operators/clip.py +++ b/release/scripts/startup/bl_operators/clip.py @@ -238,7 +238,7 @@ class CLIP_OT_track_to_empty(Operator): ob = bpy.data.objects.new(name=track.name, object_data=None) ob.select_set(action='SELECT') context.scene.objects.link(ob) - context.scene.objects.active = ob + context.view_layer.objects.active = ob for con in ob.constraints: if con.type == 'FOLLOW_TRACK': @@ -314,7 +314,7 @@ class CLIP_OT_bundles_to_mesh(Operator): ob.matrix_world = matrix context.scene.objects.link(ob) ob.select = True - context.scene.objects.active = ob + context.view_layer.objects.active = ob else: self.report({'WARNING'}, "No usable tracks selected") diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py index 530194e5bb7..fe09fada297 100644 --- a/release/scripts/startup/bl_operators/presets.py +++ b/release/scripts/startup/bl_operators/presets.py @@ -257,7 +257,7 @@ class PresetMenu(Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'HEADER' bl_label = "Presets" - path_menu: Menu.path_menu + path_menu = Menu.path_menu @classmethod def draw_panel_header(cls, layout): diff --git a/release/scripts/startup/bl_operators/rigidbody.py b/release/scripts/startup/bl_operators/rigidbody.py index 36150a63895..6b76fb96b62 100644 --- a/release/scripts/startup/bl_operators/rigidbody.py +++ b/release/scripts/startup/bl_operators/rigidbody.py @@ -60,7 +60,7 @@ class CopyRigidbodySettings(Operator): def execute(self, context): obj_act = context.object - scene = context.scene + view_layer = context.view_layer # deselect all but mesh objects for o in context.selected_objects: @@ -68,9 +68,9 @@ class CopyRigidbodySettings(Operator): o.select_set(action='DESELECT') elif o.rigid_body is None: # Add rigidbody to object! - scene.objects.active = o + view_layer.objects.active = o bpy.ops.rigidbody.object_add() - scene.objects.active = obj_act + view_layer.objects.active = obj_act objects = context.selected_objects if objects: @@ -265,7 +265,7 @@ class ConnectRigidBodies(Operator): ob = bpy.data.objects.new("Constraint", object_data=None) ob.location = loc context.scene.objects.link(ob) - context.scene.objects.active = ob + context.view_layer.objects.active = ob ob.select_set(action='SELECT') bpy.ops.rigidbody.constraint_add() @@ -278,7 +278,7 @@ class ConnectRigidBodies(Operator): con.object2 = object2 def execute(self, context): - scene = context.scene + view_layer = context.view_layer objects = context.selected_objects obj_act = context.active_object change = False @@ -312,7 +312,7 @@ class ConnectRigidBodies(Operator): bpy.ops.object.select_all(action='DESELECT') for obj in objects: obj.select_set(action='SELECT') - scene.objects.active = obj_act + view_layer.objects.active = obj_act return {'FINISHED'} else: self.report({'WARNING'}, "No other objects selected") diff --git a/release/scripts/startup/bl_operators/uvcalc_lightmap.py b/release/scripts/startup/bl_operators/uvcalc_lightmap.py index 95a3d18304b..b866fb1ce40 100644 --- a/release/scripts/startup/bl_operators/uvcalc_lightmap.py +++ b/release/scripts/startup/bl_operators/uvcalc_lightmap.py @@ -579,7 +579,7 @@ def unwrap(operator, context, **kwargs): # define list of meshes meshes = [] if PREF_ACT_ONLY: - obj = context.scene.objects.active + obj = context.view_layer.objects.active if obj and obj.type == 'MESH': meshes = [obj.data] else: diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py index f66419a7f8e..cc0bde46189 100644 --- a/release/scripts/startup/bl_ui/properties_data_camera.py +++ b/release/scripts/startup/bl_ui/properties_data_camera.py @@ -88,7 +88,7 @@ class DATA_PT_lens(CameraButtonsPanel, Panel): if cam.lens_unit == 'MILLIMETERS': col.prop(cam, "lens") elif cam.lens_unit == 'FOV': - row.prop(cam, "angle") + col.prop(cam, "angle") col.prop(cam, "lens_unit") elif cam.type == 'ORTHO': @@ -250,15 +250,10 @@ class DATA_PT_camera_dof_aperture(CameraButtonsPanel, Panel): col.prop(dof_options, "rotation") col.prop(dof_options, "ratio") else: - hq_support = dof_options.is_hq_supported col = flow.column() col.label("Viewport") - sub = col.column() - sub.active = hq_support - sub.prop(dof_options, "use_high_quality") col.prop(dof_options, "fstop") - if dof_options.use_high_quality and hq_support: - col.prop(dof_options, "blades") + col.prop(dof_options, "blades") class DATA_PT_camera_background_image(CameraButtonsPanel, Panel): diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py index 214852cc826..f096ff83957 100644 --- a/release/scripts/startup/bl_ui/properties_data_mesh.py +++ b/release/scripts/startup/bl_ui/properties_data_mesh.py @@ -152,6 +152,7 @@ class DATA_PT_context_mesh(MeshButtonsPanel, Panel): class DATA_PT_normals(MeshButtonsPanel, Panel): bl_label = "Normals" + bl_options = {'DEFAULT_CLOSED'} COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} def draw(self, context): @@ -239,6 +240,7 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel): class DATA_PT_face_maps(MeshButtonsPanel, Panel): bl_label = "Face Maps" + bl_options = {'DEFAULT_CLOSED'} COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} @classmethod @@ -450,13 +452,13 @@ classes = ( MESH_UL_shape_keys, MESH_UL_uvmaps_vcols, DATA_PT_context_mesh, - DATA_PT_normals, - DATA_PT_texture_space, DATA_PT_vertex_groups, - DATA_PT_face_maps, DATA_PT_shape_keys, DATA_PT_uv_texture, DATA_PT_vertex_colors, + DATA_PT_face_maps, + DATA_PT_normals, + DATA_PT_texture_space, DATA_PT_customdata, DATA_PT_custom_props_mesh, ) diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py index a2ccfb4f1b8..55b798d103a 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -728,7 +728,7 @@ class GPENCIL_MT_snap(Menu): layout.operator("gpencil.snap_to_grid", text="Selection to Grid") layout.operator("gpencil.snap_to_cursor", text="Selection to Cursor").use_offset = False - layout.operator("gpencil.snap_to_cursor", text="Selection to Cursor (Offset)").use_offset = True + layout.operator("gpencil.snap_to_cursor", text="Selection to Cursor (Keep Offset)").use_offset = True layout.separator() diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py index 9d891a07989..75b2d76d9c4 100644 --- a/release/scripts/startup/bl_ui/properties_particle.py +++ b/release/scripts/startup/bl_ui/properties_particle.py @@ -662,164 +662,336 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel): if part.physics_type == 'FLUID': fluid = part.fluid - col.label(text="Fluid") + col.separator() col.prop(fluid, "solver") col.prop(fluid, "stiffness", text="Stiffness") col.prop(fluid, "linear_viscosity", text="Viscosity") col.prop(fluid, "buoyancy", text="Buoyancy", slider=True) - col.label(text="Advanced") + elif part.physics_type == 'KEYED': + + sub = col.column() + sub.active = not psys.use_keyed_timing + sub.prop(part, "keyed_loops", text="Loops") + if psys: + col.prop(psys, "use_keyed_timing", text="Use Timing") + + col.label(text="Keys") + + +class PARTICLE_PT_physics_fluid_advanced(ParticleButtonsPanel, Panel): + bl_label = "Advanced" + bl_parent_id = "PARTICLE_PT_physics" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} - if fluid.solver == 'DDR': - sub = col.column() - sub.prop(fluid, "repulsion", slider=fluid.factor_repulsion) - sub.prop(fluid, "factor_repulsion") + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + fluid = part.fluid + if part.physics_type == 'FLUID': + return True + else: + return False - sub.prop(fluid, "stiff_viscosity", slider=fluid.factor_stiff_viscosity) - sub.prop(fluid, "factor_stiff_viscosity") + def draw(self, context): + layout = self.layout + layout.use_property_split = True + psys = context.particle_system + part = particle_get_settings(context) + fluid = part.fluid + + col = layout.column() + + if fluid.solver == 'DDR': sub = col.column() - sub.prop(fluid, "fluid_radius", slider=fluid.factor_radius) - sub.prop(fluid, "factor_radius") + sub.prop(fluid, "repulsion", slider=fluid.factor_repulsion) + sub.prop(fluid, "factor_repulsion") - sub.prop(fluid, "rest_density", slider=fluid.use_factor_density) - sub.prop(fluid, "use_factor_density") + sub.prop(fluid, "stiff_viscosity", slider=fluid.factor_stiff_viscosity) + sub.prop(fluid, "factor_stiff_viscosity") - if fluid.solver == 'CLASSICAL': - # With the classical solver, it is possible to calculate the - # spacing between particles when the fluid is at rest. This - # makes it easier to set stable initial conditions. - particle_volume = part.mass / fluid.rest_density - spacing = pow(particle_volume, 1.0 / 3.0) + sub = col.column() + sub.prop(fluid, "fluid_radius", slider=fluid.factor_radius) + sub.prop(fluid, "factor_radius") - sub.label(text="Spacing: %g" % spacing) + sub.prop(fluid, "rest_density", slider=fluid.use_factor_density) + sub.prop(fluid, "use_factor_density") - elif fluid.solver == 'DDR': + if fluid.solver == 'CLASSICAL': + # With the classical solver, it is possible to calculate the + # spacing between particles when the fluid is at rest. This + # makes it easier to set stable initial conditions. + particle_volume = part.mass / fluid.rest_density + spacing = pow(particle_volume, 1.0 / 3.0) - col.label(text="Springs") - col.prop(fluid, "spring_force", text="Force") - col.prop(fluid, "use_viscoelastic_springs") + sub.label(text="Spacing: %g" % spacing) - sub = col.column() - sub.active = fluid.use_viscoelastic_springs - sub.prop(fluid, "yield_ratio", slider=True) - sub.prop(fluid, "plasticity", slider=True) - col.label(text="Advanced") - sub = col.column() - sub.prop(fluid, "rest_length", slider=fluid.factor_rest_length) - sub.prop(fluid, "factor_rest_length", text="") +class PARTICLE_PT_physics_fluid_springs(ParticleButtonsPanel, Panel): + bl_label = "Springs" + bl_parent_id = "PARTICLE_PT_physics" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} - sub = col.column() - sub.active = fluid.use_viscoelastic_springs - sub.prop(fluid, "use_initial_rest_length") - sub.prop(fluid, "spring_frames", text="Frames") + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + fluid = part.fluid + if part.physics_type == 'FLUID' and fluid.solver == 'DDR': + return True + else: + return False - elif part.physics_type == 'KEYED': + def draw(self, context): + layout = self.layout + layout.use_property_split = True - sub = col.column() - sub.active = not psys.use_keyed_timing - sub.prop(part, "keyed_loops", text="Loops") - if psys: - col.prop(psys, "use_keyed_timing", text="Use Timing") + psys = context.particle_system + part = particle_get_settings(context) + fluid = part.fluid - col.label(text="Keys") + col = layout.column() - elif part.physics_type == 'BOIDS': - boids = part.boids + col.prop(fluid, "spring_force", text="Force") - row = layout.row() - row.prop(boids, "use_flight") - row.prop(boids, "use_land") - row.prop(boids, "use_climb") - - split = layout.split() - - col = split.column(align=True) - col.active = boids.use_flight - col.prop(boids, "air_speed_max") - col.prop(boids, "air_speed_min", slider=True) - col.prop(boids, "air_acc_max", slider=True) - col.prop(boids, "air_ave_max", slider=True) - col.prop(boids, "air_personal_space") - row = col.row(align=True) - row.active = (boids.use_land or boids.use_climb) and boids.use_flight - row.prop(boids, "land_smooth") - - col = split.column(align=True) - col.active = boids.use_land or boids.use_climb - col.prop(boids, "land_speed_max") - col.prop(boids, "land_jump_speed") - col.prop(boids, "land_acc_max", slider=True) - col.prop(boids, "land_ave_max", slider=True) - col.prop(boids, "land_personal_space") - col.prop(boids, "land_stick_force") - - layout.prop(part, "collision_group") - - split = layout.split() - - col = split.column(align=True) - col.label(text="Battle:") - col.prop(boids, "health") - col.prop(boids, "strength") - col.prop(boids, "aggression") - col.prop(boids, "accuracy") - col.prop(boids, "range") - col = split.column() - col.label(text="Misc:") - col.prop(boids, "bank", slider=True) - col.prop(boids, "pitch", slider=True) - col.prop(boids, "height", slider=True) - - if psys and part.physics_type in {'KEYED', 'BOIDS', 'FLUID'}: - if part.physics_type == 'BOIDS': - layout.label(text="Relations:") +class PARTICLE_PT_physics_fluid_springs_viscoelastic(ParticleButtonsPanel, Panel): + bl_label = "Viscoelastic Springs" + bl_parent_id = "PARTICLE_PT_physics_fluid_springs" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} + + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + fluid = part.fluid + if part.physics_type == 'FLUID' and fluid.solver == 'DDR': + return True + else: + return False + + def draw_header(self, context): + psys = context.particle_system + part = particle_get_settings(context) + fluid = part.fluid + + self.layout.prop(fluid, "use_viscoelastic_springs", text="") + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + psys = context.particle_system + part = particle_get_settings(context) + fluid = part.fluid + + col = layout.column() + col.active = fluid.use_viscoelastic_springs + col.prop(fluid, "yield_ratio", slider=True) + col.prop(fluid, "plasticity", slider=True) + + col.separator() + + col.prop(fluid, "use_initial_rest_length") + col.prop(fluid, "spring_frames", text="Frames") + + +class PARTICLE_PT_physics_fluid_springs_advanced(ParticleButtonsPanel, Panel): + bl_label = "Advanced" + bl_parent_id = "PARTICLE_PT_physics_fluid_springs" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} + + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + fluid = part.fluid + if part.physics_type == 'FLUID' and fluid.solver == 'DDR': + return True + else: + return False + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + psys = context.particle_system + part = particle_get_settings(context) + fluid = part.fluid + + sub = layout.column() + sub.prop(fluid, "rest_length", slider=fluid.factor_rest_length) + sub.prop(fluid, "factor_rest_length") + + +class PARTICLE_PT_physics_boids_movement(ParticleButtonsPanel, Panel): + bl_label = "Movement" + bl_parent_id = "PARTICLE_PT_physics" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} + + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.physics_type in {'BOIDS'} + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + psys = context.particle_system + part = particle_get_settings(context) + boids = part.boids + + col=layout.column() + + col.prop(boids, "use_flight") + col.prop(boids, "use_land") + col.prop(boids, "use_climb") + + col=layout.column() + + col.active = boids.use_flight + sub = col.column() + sub.prop(boids, "air_speed_max") + sub.prop(boids, "air_speed_min", slider=True) + col.prop(boids, "air_acc_max", slider=True) + col.prop(boids, "air_ave_max", slider=True) + col.prop(boids, "air_personal_space") + row = col.row(align=True) + row.active = (boids.use_land or boids.use_climb) and boids.use_flight + row.prop(boids, "land_smooth") + + layout.separator() + + col=layout.column() + col.active = boids.use_land or boids.use_climb + col.prop(boids, "land_speed_max") + col.prop(boids, "land_jump_speed") + col.prop(boids, "land_acc_max", slider=True) + col.prop(boids, "land_ave_max", slider=True) + col.prop(boids, "land_personal_space") + col.prop(boids, "land_stick_force") + + layout.separator() + + layout.prop(part, "collision_group") + +class PARTICLE_PT_physics_boids_battle(ParticleButtonsPanel, Panel): + bl_label = "Battle" + bl_parent_id = "PARTICLE_PT_physics" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} + + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.physics_type in {'BOIDS'} + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + psys = context.particle_system + part = particle_get_settings(context) + boids = part.boids + + col=layout.column() + + col.prop(boids, "health") + col.prop(boids, "strength") + col.prop(boids, "aggression") + col.prop(boids, "accuracy") + col.prop(boids, "range") + +class PARTICLE_PT_physics_boids_misc(ParticleButtonsPanel, Panel): + bl_label = "Misc" + bl_parent_id = "PARTICLE_PT_physics" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} + + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.physics_type in {'BOIDS'} + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + psys = context.particle_system + part = particle_get_settings(context) + boids = part.boids + + col=layout.column() + + col.prop(boids, "bank", slider=True) + col.prop(boids, "pitch", slider=True) + col.prop(boids, "height", slider=True) + + +class PARTICLE_PT_physics_relations(ParticleButtonsPanel, Panel): + bl_label = "Relations" + bl_parent_id = "PARTICLE_PT_physics" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} + + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.physics_type in {'KEYED', 'BOIDS', 'FLUID'} + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + psys = context.particle_system + part = particle_get_settings(context) + + + row = layout.row() + row.template_list("UI_UL_list", "particle_targets", psys, "targets", + psys, "active_particle_target_index", rows=4) + + col = row.column() + sub = col.row() + subsub = sub.column(align=True) + subsub.operator("particle.new_target", icon='ZOOMIN', text="") + subsub.operator("particle.target_remove", icon='ZOOMOUT', text="") + sub = col.row() + subsub = sub.column(align=True) + subsub.operator("particle.target_move_up", icon='TRIA_UP', text="") + subsub.operator("particle.target_move_down", icon='TRIA_DOWN', text="") + + key = psys.active_particle_target + + if key: + if part.physics_type == 'KEYED': + col = layout.column() + # doesn't work yet + #col.alert = key.valid + col.prop(key, "object") + col.prop(key, "system", text="System") + + col.active = psys.use_keyed_timing + col.prop(key, "time") + col.prop(key, "duration") + elif part.physics_type == 'BOIDS': + sub = layout.column() + # doesn't work yet + #sub.alert = key.valid + sub.prop(key, "object") + sub.prop(key, "system", text="System") + layout.prop(key, "alliance") elif part.physics_type == 'FLUID': - layout.label(text="Fluid Interaction:") + sub = layout.column() + # doesn't work yet + #sub.alert = key.valid + sub.prop(key, "object") + sub.prop(key, "system", text="System") - row = layout.row() - row.template_list("UI_UL_list", "particle_targets", psys, "targets", - psys, "active_particle_target_index", rows=4) - - col = row.column() - sub = col.row() - subsub = sub.column(align=True) - subsub.operator("particle.new_target", icon='ZOOMIN', text="") - subsub.operator("particle.target_remove", icon='ZOOMOUT', text="") - sub = col.row() - subsub = sub.column(align=True) - subsub.operator("particle.target_move_up", icon='TRIA_UP', text="") - subsub.operator("particle.target_move_down", icon='TRIA_DOWN', text="") - - key = psys.active_particle_target - if key: - row = layout.row() - if part.physics_type == 'KEYED': - col = row.column() - # doesn't work yet - #col.alert = key.valid - col.prop(key, "object", text="") - col.prop(key, "system", text="System") - col = row.column() - col.active = psys.use_keyed_timing - col.prop(key, "time") - col.prop(key, "duration") - elif part.physics_type == 'BOIDS': - sub = row.row() - # doesn't work yet - #sub.alert = key.valid - sub.prop(key, "object", text="") - sub.prop(key, "system", text="System") - - layout.row().prop(key, "alliance", expand=True) - elif part.physics_type == 'FLUID': - sub = row.row() - # doesn't work yet - #sub.alert = key.valid - sub.prop(key, "object", text="") - sub.prop(key, "system", text="System") class PARTICLE_PT_physics_deflection(ParticleButtonsPanel, Panel): @@ -911,6 +1083,9 @@ class PARTICLE_PT_physics_integration(ParticleButtonsPanel, Panel): class PARTICLE_PT_boidbrain(ParticleButtonsPanel, Panel): bl_label = "Boid Brain" + bl_options = {'DEFAULT_CLOSED'} + bl_parent_id = "PARTICLE_PT_physics" + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} @classmethod @@ -1941,9 +2116,17 @@ classes = ( PARTICLE_PT_rotation, PARTICLE_PT_rotation_angular_velocity, PARTICLE_PT_physics, + PARTICLE_PT_physics_fluid_springs, + PARTICLE_PT_physics_fluid_springs_viscoelastic, + PARTICLE_PT_physics_fluid_springs_advanced, + PARTICLE_PT_physics_fluid_advanced, + PARTICLE_PT_physics_boids_movement, + PARTICLE_PT_physics_boids_battle, + PARTICLE_PT_physics_boids_misc, PARTICLE_PT_physics_forces, PARTICLE_PT_physics_deflection, PARTICLE_PT_physics_integration, + PARTICLE_PT_physics_relations, PARTICLE_PT_boidbrain, PARTICLE_PT_render, PARTICLE_PT_render_line, diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py index 7775722784b..0a7318864a3 100644 --- a/release/scripts/startup/bl_ui/properties_physics_cloth.py +++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py @@ -17,8 +17,11 @@ # ##### END GPL LICENSE BLOCK ##### # <pep8 compliant> + import bpy -from bpy.types import Menu, Panel +from bpy.types import ( + Panel, +) from bl_operators.presets import PresetMenu from .properties_physics_common import ( @@ -58,6 +61,7 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True md = context.cloth ob = context.object @@ -65,64 +69,82 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel): layout.active = cloth_panel_enabled(md) - split = layout.split(percentage=0.25) - - split.label(text="Quality:") - split.prop(cloth, "quality", text="Steps") - - split = layout.split(percentage=0.25) + flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True) - split.label(text="Speed:") - split.prop(cloth, "time_scale", text="Multiplier") + col = flow.column() + col.prop(cloth, "quality", text="Quality Steps") + col.prop(cloth, "time_scale", text="Speed Multiplier") - split = layout.split() + col.separator() - col = split.column() - - col.label(text="Material:") - col.prop(cloth, "mass") + col = flow.column() + col.prop(cloth, "mass", text="Material Mass") col.prop(cloth, "structural_stiffness", text="Structural") col.prop(cloth, "bending_stiffness", text="Bending") - col = split.column() + col.separator() - col.label(text="Damping:") - col.prop(cloth, "spring_damping", text="Spring") + col = flow.column() + col.prop(cloth, "spring_damping", text="Damping Spring") col.prop(cloth, "air_damping", text="Air") col.prop(cloth, "vel_damping", text="Velocity") - split = layout.split() + col = flow.column() + col.prop(cloth, "use_dynamic_mesh", text="Dynamic Mesh") - col = split.column() + key = ob.data.shape_keys - col.prop(cloth, "use_pin_cloth", text="Pinning:") - sub = col.column() - sub.active = cloth.use_pin_cloth - sub.prop_search(cloth, "vertex_group_mass", ob, "vertex_groups", text="") - sub.prop(cloth, "pin_stiffness", text="Stiffness") + if key: + # Note: TODO prop_search doesn't align on the right. + row = col.row(align=True) + row.active = not cloth.use_dynamic_mesh + row.prop_search(cloth, "rest_shape_key", key, "key_blocks", text="Rest Shape Key") + row.label(text="", icon='BLANK1') - # Disabled for now - """ - if cloth.vertex_group_mass: - layout.label(text="Goal:") - col = layout.column_flow() - col.prop(cloth, "goal_default", text="Default") - col.prop(cloth, "goal_spring", text="Stiffness") - col.prop(cloth, "goal_friction", text="Friction") - """ +class PHYSICS_PT_cloth_pinning(PhysicButtonsPanel, Panel): + bl_label = "Pinning" + bl_parent_id = 'PHYSICS_PT_cloth' + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} - col = split.column() + def draw_header(self, context): + md = context.cloth + cloth = md.settings - col.prop(cloth, "use_dynamic_mesh", text="Dynamic Mesh") + self.layout.active = cloth_panel_enabled(md) and cloth.use_pin_cloth + self.layout.prop(cloth, "use_pin_cloth", text="") - key = ob.data.shape_keys + def draw(self, context): + layout = self.layout + layout.use_property_split = True - if key: - sub = col.column() - sub.active = not cloth.use_dynamic_mesh - sub.label(text="Rest Shape Key:") - sub.prop_search(cloth, "rest_shape_key", key, "key_blocks", text="") + md = context.cloth + ob = context.object + cloth = md.settings + + layout.active = cloth_panel_enabled(md) and cloth.use_pin_cloth + + flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True) + + col = flow.column() + + # Note: TODO prop_search doesn't align on the right. + row = col.row(align=True) + row.prop_search(cloth, "vertex_group_mass", ob, "vertex_groups", text="Mass Group") + row.label(text="", icon='BLANK1') + + col = flow.column() + col.prop(cloth, "pin_stiffness", text="Stiffness") + + # Disabled for now. + """ + if cloth.vertex_group_mass: + col = flow.column() + col.prop(cloth, "goal_default", text="Goal Default") + col.prop(cloth, "goal_spring", text="Stiffness") + col.prop(cloth, "goal_friction", text="Friction") + """ class PHYSICS_PT_cloth_cache(PhysicButtonsPanel, Panel): @@ -150,31 +172,59 @@ class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True cloth = context.cloth.collision_settings md = context.cloth - ob = context.object layout.active = cloth.use_collision and cloth_panel_enabled(md) - split = layout.split() + flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True) - col = split.column() + col = flow.column() col.prop(cloth, "collision_quality", text="Quality") col.prop(cloth, "distance_min", slider=True, text="Distance") col.prop(cloth, "repel_force", slider=True, text="Repel") + + col = flow.column() col.prop(cloth, "distance_repel", slider=True, text="Repel Distance") col.prop(cloth, "friction") + col.prop(cloth, "group") - col = split.column() - col.prop(cloth, "use_self_collision", text="Self Collision") - sub = col.column() - sub.active = cloth.use_self_collision - sub.prop(cloth, "self_collision_quality", text="Quality") - sub.prop(cloth, "self_distance_min", slider=True, text="Distance") - sub.prop_search(cloth, "vertex_group_self_collisions", ob, "vertex_groups", text="") - layout.prop(cloth, "group") +class PHYSICS_PT_cloth_self_collision(PhysicButtonsPanel, Panel): + bl_label = "Self Collision" + bl_parent_id = 'PHYSICS_PT_cloth_collision' + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} + + def draw_header(self, context): + cloth = context.cloth.collision_settings + + self.layout.active = cloth_panel_enabled(context.cloth) and cloth.use_self_collision + self.layout.prop(cloth, "use_self_collision", text="") + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + cloth = context.cloth.collision_settings + md = context.cloth + ob = context.object + + layout.active = cloth.use_collision and cloth_panel_enabled(md) and cloth.use_self_collision + + flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True) + + col = flow.column() + col.prop(cloth, "self_collision_quality", text="Quality") + col.prop(cloth, "self_distance_min", slider=True, text="Distance") + + col = flow.column() + # Note: TODO prop_search doesn't align on the right. + row = col.row(align=True) + row.prop_search(cloth, "vertex_group_self_collisions", ob, "vertex_groups", text="Vertex Group") + row.label(text="", icon='BLANK1') class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel, Panel): @@ -191,6 +241,7 @@ class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True md = context.cloth ob = context.object @@ -198,16 +249,27 @@ class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel, Panel): layout.active = (cloth.use_stiffness_scale and cloth_panel_enabled(md)) - split = layout.split() + flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True) - col = split.column() - col.label(text="Structural Stiffness:") - col.prop_search(cloth, "vertex_group_structural_stiffness", ob, "vertex_groups", text="") + col = flow.column() + # Note: TODO prop_search doesn't align on the right. + row = col.row(align=True) + row.prop_search( + cloth, "vertex_group_structural_stiffness", ob, "vertex_groups", + text="Structural Group" + ) + row.label(text="", icon='BLANK1') col.prop(cloth, "structural_stiffness_max", text="Max") - col = split.column() - col.label(text="Bending Stiffness:") - col.prop_search(cloth, "vertex_group_bending", ob, "vertex_groups", text="") + col.separator() + + col = flow.column() + row = col.row(align=True) + row.prop_search( + cloth, "vertex_group_bending", ob, "vertex_groups", + text="Bending Group" + ) + row.label(text="", icon='BLANK1') col.prop(cloth, "bending_stiffness_max", text="Max") @@ -225,23 +287,27 @@ class PHYSICS_PT_cloth_sewing(PhysicButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True md = context.cloth ob = context.object cloth = context.cloth.settings layout.active = (cloth.use_sewing_springs and cloth_panel_enabled(md)) + flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True) - layout.prop(cloth, "sewing_force_max", text="Sewing Force") + col = flow.column() + col.prop(cloth, "sewing_force_max", text="Sewing Force") - split = layout.split() + col.separator() - col = split.column(align=True) - col.label(text="Shrinking:") - col.prop_search(cloth, "vertex_group_shrink", ob, "vertex_groups", text="") + col = col.column() + # Note: TODO prop_search doesn't align on the right. + row = col.row(align=True) + row.prop_search(cloth, "vertex_group_shrink", ob, "vertex_groups", text="Shrinking Group") + row.label(text="", icon='BLANK1') - col = split.column(align=True) - col.label() + col = flow.column(align=True) col.prop(cloth, "shrink_min", text="Min") col.prop(cloth, "shrink_max", text="Max") @@ -262,6 +328,8 @@ classes = ( PHYSICS_PT_cloth, PHYSICS_PT_cloth_cache, PHYSICS_PT_cloth_collision, + PHYSICS_PT_cloth_self_collision, + PHYSICS_PT_cloth_pinning, PHYSICS_PT_cloth_stiffness, PHYSICS_PT_cloth_sewing, PHYSICS_PT_cloth_field_weights, diff --git a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py index 611f477a31b..44d07ff53e6 100644 --- a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py +++ b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py @@ -87,24 +87,22 @@ class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, Panel): col.operator("dpaint.surface_slot_add", icon='ZOOMIN', text="") col.operator("dpaint.surface_slot_remove", icon='ZOOMOUT', text="") + layout.use_property_split = True + if surface: layout.prop(surface, "surface_format") col = layout.column() if surface.surface_format != 'VERTEX': - col.label(text="Quality:") col.prop(surface, "image_resolution") col.prop(surface, "use_antialiasing") - col = layout.column() - col.label(text="Frames:") - split = col.split() - col = split.column(align=True) - col.prop(surface, "frame_start", text="Start") - col.prop(surface, "frame_end", text="End") + sub = col.column(align=True) + sub.prop(surface, "frame_start", text="Frame Start") + sub.prop(surface, "frame_end", text="End") - split.prop(surface, "frame_substeps") + col.prop(surface, "frame_substeps") elif md.ui_type == 'BRUSH': brush = md.brush_settings @@ -114,16 +112,14 @@ class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, Panel): else: layout.operator("dpaint.type_toggle", text="Remove Brush", icon='X').type = 'BRUSH' - split = layout.split() + layout.use_property_split = True - col = split.column() + col = layout.column() + col.prop(brush, "paint_color") + col.prop(brush, "paint_alpha", text="Alpha", slider=True) + col.prop(brush, "paint_wetness", text="Wetness", slider=True) col.prop(brush, "use_absolute_alpha") col.prop(brush, "use_paint_erase") - col.prop(brush, "paint_wetness", text="Wetness") - - col = split.column() - col.prop(brush, "paint_color", text="") - col.prop(brush, "paint_alpha", text="Alpha") class PHYSICS_PT_dp_advanced_canvas(PhysicButtonsPanel, Panel): @@ -141,65 +137,113 @@ class PHYSICS_PT_dp_advanced_canvas(PhysicButtonsPanel, Panel): canvas = context.dynamic_paint.canvas_settings surface = canvas.canvas_surfaces.active - surface_type = surface.surface_type + layout.use_property_split = True + layout.prop(surface, "surface_type") + layout.separator() - # dissolve - if surface_type == 'PAINT': - split = layout.split(percentage=0.35) - split.prop(surface, "use_drying", text="Dry:") - - col = split.column() - col.active = surface.use_drying - split = col.split(percentage=0.7) - col = split.column(align=True) - col.prop(surface, "dry_speed", text="Time") - col.prop(surface, "color_dry_threshold") - split.prop(surface, "use_dry_log", text="Slow") - - if surface_type != 'WAVE': - split = layout.split(percentage=0.35) - col = split.column() - if surface_type == 'WEIGHT': - col.prop(surface, "use_dissolve", text="Fade:") - else: - col.prop(surface, "use_dissolve", text="Dissolve:") - col = split.column() - col.active = surface.use_dissolve - split = col.split(percentage=0.7) - split.prop(surface, "dissolve_speed", text="Time") - split.prop(surface, "use_dissolve_log", text="Slow") + col = layout.column() # per type settings if surface_type == 'DISPLACE': - layout.prop(surface, "use_incremental_displace") + col.prop(surface, "use_incremental_displace") if surface.surface_format == 'VERTEX': - row = layout.row() - row.prop(surface, "depth_clamp") - row.prop(surface, "displace_factor") - - elif surface_type == 'WAVE': - layout.prop(surface, "use_wave_open_border") + col.prop(surface, "depth_clamp") + col.prop(surface, "displace_factor") - split = layout.split() + col.separator() - col = split.column(align=True) + elif surface_type == 'WAVE': + col.prop(surface, "use_wave_open_border") col.prop(surface, "wave_timescale") col.prop(surface, "wave_speed") - - col = split.column(align=True) col.prop(surface, "wave_damping") col.prop(surface, "wave_spring") col.prop(surface, "wave_smoothness") - layout.separator() - layout.prop(surface, "brush_group") - row = layout.row() - row.prop(surface, "brush_influence_scale") - row.prop(surface, "brush_radius_scale") + col.separator() + + col.prop(surface, "brush_group") + col.prop(surface, "brush_influence_scale") + col.prop(surface, "brush_radius_scale") + + +class PHYSICS_PT_dp_advanced_canvas_paint_dry(PhysicButtonsPanel, Panel): + bl_label = "Dry" + bl_parent_id = "PHYSICS_PT_dp_advanced_canvas" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} + + @classmethod + def poll(cls, context): + md = context.dynamic_paint + canvas = context.dynamic_paint.canvas_settings + surface = canvas.canvas_surfaces.active + surface_type = surface.surface_type + + return md and md.ui_type == 'CANVAS' and md.canvas_settings and md.canvas_settings.canvas_surfaces.active and surface_type == 'PAINT' and context.engine in cls.COMPAT_ENGINES + + def draw_header(self, context): + canvas = context.dynamic_paint.canvas_settings + surface = canvas.canvas_surfaces.active + self.layout.prop(surface, "use_drying", text="") + + def draw(self, context): + layout = self.layout + + canvas = context.dynamic_paint.canvas_settings + surface = canvas.canvas_surfaces.active + surface_type = surface.surface_type + + layout.use_property_split = True + + layout.active = surface.use_drying + + col = layout.column() + col.prop(surface, "dry_speed", text="Time") + col.prop(surface, "color_dry_threshold") + col.prop(surface, "use_dry_log", text="Slow") + + +class PHYSICS_PT_dp_advanced_canvas_paint_dissolve(PhysicButtonsPanel, Panel): + bl_label = "Dissolve" + bl_parent_id = "PHYSICS_PT_dp_advanced_canvas" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} + + @classmethod + def poll(cls, context): + md = context.dynamic_paint + canvas = context.dynamic_paint.canvas_settings + surface = canvas.canvas_surfaces.active + surface_type = surface.surface_type + + return md and md.ui_type == 'CANVAS' and md.canvas_settings and md.canvas_settings.canvas_surfaces.active and surface_type != 'WAVE' and context.engine in cls.COMPAT_ENGINES + + def draw_header(self, context): + canvas = context.dynamic_paint.canvas_settings + surface = canvas.canvas_surfaces.active + self.layout.prop(surface, "use_dissolve", text="") + + + def draw(self, context): + layout = self.layout + + canvas = context.dynamic_paint.canvas_settings + surface = canvas.canvas_surfaces.active + surface_type = surface.surface_type + + layout.use_property_split = True + + layout.active = surface.use_dissolve + + col = layout.column() + + col.prop(surface, "dissolve_speed", text="Time") + col.prop(surface, "use_dissolve_log", text="Slow") class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, Panel): @@ -220,6 +264,7 @@ class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True canvas = context.dynamic_paint.canvas_settings surface = canvas.canvas_surfaces.active @@ -317,6 +362,8 @@ class PHYSICS_PT_dp_canvas_initial_color(PhysicButtonsPanel, Panel): surface = canvas.canvas_surfaces.active ob = context.object + layout.use_property_split = True + layout.prop(surface, "init_color_type", expand=False) if surface.init_color_type != 'NONE': layout.separator() @@ -350,37 +397,86 @@ class PHYSICS_PT_dp_effects(PhysicButtonsPanel, Panel): def draw(self, context): layout = self.layout + + +class PHYSICS_PT_dp_effects_spread(PhysicButtonsPanel, Panel): + bl_label = "Spread" + bl_parent_id = "PHYSICS_PT_dp_effects" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} + + def draw_header(self, context): canvas = context.dynamic_paint.canvas_settings surface = canvas.canvas_surfaces.active - layout.row().prop(surface, "effect_ui", expand=True) + self.layout.prop(surface, "use_spread", text="") - if surface.effect_ui == 'SPREAD': - layout.prop(surface, "use_spread") + def draw(self, context): + layout = self.layout - row = layout.row() - row.active = surface.use_spread - row.prop(surface, "spread_speed") - row.prop(surface, "color_spread_speed") + layout.use_property_split = True - elif surface.effect_ui == 'DRIP': - layout.prop(surface, "use_drip") + canvas = context.dynamic_paint.canvas_settings + surface = canvas.canvas_surfaces.active + layout.active = surface.use_spread - col = layout.column() - col.active = surface.use_drip - effector_weights_ui(self, context, surface.effector_weights, 'DYNAMIC_PAINT') + col = layout.column() - layout.label(text="Surface Movement:") - row = layout.row() - row.prop(surface, "drip_velocity", slider=True) - row.prop(surface, "drip_acceleration", slider=True) + col.prop(surface, "spread_speed") + col.prop(surface, "color_spread_speed") - elif surface.effect_ui == 'SHRINK': - layout.prop(surface, "use_shrink") - row = layout.row() - row.active = surface.use_shrink - row.prop(surface, "shrink_speed") +class PHYSICS_PT_dp_effects_drip(PhysicButtonsPanel, Panel): + bl_label = "Drip" + bl_parent_id = "PHYSICS_PT_dp_effects" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} + + def draw_header(self, context): + canvas = context.dynamic_paint.canvas_settings + surface = canvas.canvas_surfaces.active + + self.layout.prop(surface, "use_drip", text="") + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + canvas = context.dynamic_paint.canvas_settings + surface = canvas.canvas_surfaces.active + + layout.active = surface.use_drip + + col = layout.column() + col.prop(surface, "drip_velocity", slider=True) + col.prop(surface, "drip_acceleration", slider=True) + + col.separator() + + effector_weights_ui(self, context, surface.effector_weights, 'DYNAMIC_PAINT') + +class PHYSICS_PT_dp_effects_shrink(PhysicButtonsPanel, Panel): + bl_label = "Shrink" + bl_parent_id = "PHYSICS_PT_dp_effects" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} + + def draw_header(self, context): + canvas = context.dynamic_paint.canvas_settings + surface = canvas.canvas_surfaces.active + + self.layout.prop(surface, "use_shrink", text="") + + def draw(self, context): + layout = self.layout + + layout.use_property_split = True + + canvas = context.dynamic_paint.canvas_settings + surface = canvas.canvas_surfaces.active + layout.active = surface.use_shrink + + layout.prop(surface, "shrink_speed") class PHYSICS_PT_dp_cache(PhysicButtonsPanel, Panel): @@ -418,6 +514,7 @@ class PHYSICS_PT_dp_brush_source(PhysicButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True brush = context.dynamic_paint.brush_settings ob = context.object @@ -427,7 +524,7 @@ class PHYSICS_PT_dp_brush_source(PhysicButtonsPanel, Panel): col.prop(brush, "paint_source") if brush.paint_source == 'PARTICLE_SYSTEM': - col.prop_search(brush, "particle_system", ob, "particle_systems", text="") + col.prop_search(brush, "particle_system", ob, "particle_systems") if brush.particle_system: col.label(text="Particle Effect:") sub = col.column() @@ -438,22 +535,19 @@ class PHYSICS_PT_dp_brush_source(PhysicButtonsPanel, Panel): if brush.paint_source in {'DISTANCE', 'VOLUME_DISTANCE', 'POINT'}: col.prop(brush, "paint_distance", text="Paint Distance") - split = layout.row().split(percentage=0.4) - sub = split.column() + if brush.paint_source in {'DISTANCE', 'VOLUME_DISTANCE'}: - sub.prop(brush, "use_proximity_project") + col.prop(brush, "use_proximity_project") if brush.paint_source == 'VOLUME_DISTANCE': - sub.prop(brush, "invert_proximity") - sub.prop(brush, "use_negative_volume") - - sub = split.column() + col.prop(brush, "invert_proximity") + col.prop(brush, "use_negative_volume") if brush.paint_source in {'DISTANCE', 'VOLUME_DISTANCE'}: - column = sub.column() - column.active = brush.use_proximity_project - column.prop(brush, "ray_direction") - sub.prop(brush, "proximity_falloff") + sub = col.column() + sub.active = brush.use_proximity_project + sub.prop(brush, "ray_direction") + col.prop(brush, "proximity_falloff") if brush.proximity_falloff == 'RAMP': - col = layout.row().column() + col.separator() col.prop(brush, "use_proximity_ramp_alpha", text="Only Use Alpha") col.template_color_ramp(brush, "paint_ramp", expand=True) @@ -472,28 +566,45 @@ class PHYSICS_PT_dp_brush_velocity(PhysicButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True brush = context.dynamic_paint.brush_settings - split = layout.split() - - col = split.column() + col = layout.column() col.prop(brush, "use_velocity_alpha") col.prop(brush, "use_velocity_color") - - split.prop(brush, "use_velocity_depth") + col.prop(brush, "use_velocity_depth") col = layout.column() col.active = (brush.use_velocity_alpha or brush.use_velocity_color or brush.use_velocity_depth) col.prop(brush, "velocity_max") col.template_color_ramp(brush, "velocity_ramp", expand=True) - layout.separator() - row = layout.row() - row.prop(brush, "use_smudge") - sub = row.row() - sub.active = brush.use_smudge - sub.prop(brush, "smudge_strength") + +class PHYSICS_PT_dp_brush_velocity_smudge(PhysicButtonsPanel, Panel): + bl_label = "Smudge" + bl_parent_id = "PHYSICS_PT_dp_brush_velocity" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} + + @classmethod + def poll(cls, context): + md = context.dynamic_paint + return md and md.ui_type == 'BRUSH' and md.brush_settings and (context.engine in cls.COMPAT_ENGINES) + + def draw_header(self, context): + brush = context.dynamic_paint.brush_settings + + self.layout.prop(brush, "use_smudge", text="") + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + brush = context.dynamic_paint.brush_settings + + layout.active = brush.use_smudge + layout.prop(brush, "smudge_strength", slider=True) class PHYSICS_PT_dp_brush_wave(PhysicButtonsPanel, Panel): @@ -509,26 +620,33 @@ class PHYSICS_PT_dp_brush_wave(PhysicButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True brush = context.dynamic_paint.brush_settings layout.prop(brush, "wave_type") if brush.wave_type != 'REFLECT': - row = layout.row() - row.prop(brush, "wave_factor") - row.prop(brush, "wave_clamp") + col = layout.column() + col.prop(brush, "wave_factor") + col.prop(brush, "wave_clamp") classes = ( PHYSICS_UL_dynapaint_surfaces, PHYSICS_PT_dynamic_paint, PHYSICS_PT_dp_advanced_canvas, + PHYSICS_PT_dp_advanced_canvas_paint_dry, + PHYSICS_PT_dp_advanced_canvas_paint_dissolve, PHYSICS_PT_dp_canvas_output, PHYSICS_PT_dp_canvas_initial_color, PHYSICS_PT_dp_effects, + PHYSICS_PT_dp_effects_spread, + PHYSICS_PT_dp_effects_drip, + PHYSICS_PT_dp_effects_shrink, PHYSICS_PT_dp_cache, PHYSICS_PT_dp_brush_source, PHYSICS_PT_dp_brush_velocity, + PHYSICS_PT_dp_brush_velocity_smudge, PHYSICS_PT_dp_brush_wave, ) diff --git a/release/scripts/startup/bl_ui/properties_physics_rigidbody.py b/release/scripts/startup/bl_ui/properties_physics_rigidbody.py index 013822793de..00733e2fb12 100644 --- a/release/scripts/startup/bl_ui/properties_physics_rigidbody.py +++ b/release/scripts/startup/bl_ui/properties_physics_rigidbody.py @@ -39,20 +39,23 @@ class PHYSICS_PT_rigid_body(PHYSICS_PT_rigidbody_panel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True
ob = context.object rbo = ob.rigid_body if rbo is not None: layout.prop(rbo, "type", text="Type") - row = layout.row() - if rbo.type == 'ACTIVE': - row.prop(rbo, "enabled", text="Dynamic") - row.prop(rbo, "kinematic", text="Animated") if rbo.type == 'ACTIVE': layout.prop(rbo, "mass") + col = layout.column()
+ if rbo.type == 'ACTIVE':
+ col.prop(rbo, "enabled", text="Dynamic")
+ col.prop(rbo, "kinematic", text="Animated")
+
+
class PHYSICS_PT_rigid_body_collisions(PHYSICS_PT_rigidbody_panel, Panel): bl_label = "Collisions" @@ -70,6 +73,7 @@ class PHYSICS_PT_rigid_body_collisions(PHYSICS_PT_rigidbody_panel, Panel): ob = context.object rbo = ob.rigid_body + layout.use_property_split = True
layout.prop(rbo, "collision_shape", text="Shape") @@ -79,15 +83,51 @@ class PHYSICS_PT_rigid_body_collisions(PHYSICS_PT_rigidbody_panel, Panel): if rbo.collision_shape == 'MESH' and rbo.mesh_source == 'DEFORM': layout.prop(rbo, "use_deform", text="Deforming") - split = layout.split() - col = split.column() - col.label(text="Surface Response:") +class PHYSICS_PT_rigid_body_collisions_surface(PHYSICS_PT_rigidbody_panel, Panel):
+ bl_label = "Surface Response"
+ bl_parent_id = 'PHYSICS_PT_rigid_body_collisions'
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.object
+ return (obj and obj.rigid_body and
+ (context.engine in cls.COMPAT_ENGINES))
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ rbo = ob.rigid_body
+ layout.use_property_split = True
+
+ col = layout.column()
col.prop(rbo, "friction") col.prop(rbo, "restitution", text="Bounciness") - col = split.column() - col.label(text="Sensitivity:") +class PHYSICS_PT_rigid_body_collisions_sensitivity(PHYSICS_PT_rigidbody_panel, Panel):
+ bl_label = "Sensitivity"
+ bl_parent_id = 'PHYSICS_PT_rigid_body_collisions'
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.object
+ return (obj and obj.rigid_body and
+ (context.engine in cls.COMPAT_ENGINES))
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ rbo = ob.rigid_body
+ layout.use_property_split = True
+
+ col = layout.column()
+
if rbo.collision_shape in {'MESH', 'CONE'}: col.prop(rbo, "collision_margin", text="Margin") else: @@ -96,7 +136,25 @@ class PHYSICS_PT_rigid_body_collisions(PHYSICS_PT_rigidbody_panel, Panel): sub.active = rbo.use_margin sub.prop(rbo, "collision_margin", text="Margin") - layout.prop(rbo, "collision_groups") +class PHYSICS_PT_rigid_body_collisions_collections(PHYSICS_PT_rigidbody_panel, Panel):
+ bl_label = "Collision Collections"
+ bl_parent_id = 'PHYSICS_PT_rigid_body_collisions'
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.object
+ return (obj and obj.rigid_body and
+ (context.engine in cls.COMPAT_ENGINES))
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ rbo = ob.rigid_body
+
+ layout.prop(rbo, "collision_groups", text="")
class PHYSICS_PT_rigid_body_dynamics(PHYSICS_PT_rigidbody_panel, Panel): @@ -114,6 +172,7 @@ class PHYSICS_PT_rigid_body_dynamics(PHYSICS_PT_rigidbody_panel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True
ob = context.object rbo = ob.rigid_body @@ -122,28 +181,53 @@ class PHYSICS_PT_rigid_body_dynamics(PHYSICS_PT_rigidbody_panel, Panel): # col.label(text="Activation:") # XXX: settings such as activate on collison/etc. - split = layout.split() - - col = split.column() - col.label(text="Deactivation:") - col.prop(rbo, "use_deactivation") - sub = col.column() - sub.active = rbo.use_deactivation - sub.prop(rbo, "use_start_deactivated") - sub.prop(rbo, "deactivate_linear_velocity", text="Linear Vel") - sub.prop(rbo, "deactivate_angular_velocity", text="Angular Vel") - # TODO: other params such as time? - - col = split.column() - col.label(text="Damping:") - col.prop(rbo, "linear_damping", text="Translation") - col.prop(rbo, "angular_damping", text="Rotation") + col = layout.column()
+ col.prop(rbo, "linear_damping", text="Translation Damping")
+ col.prop(rbo, "angular_damping", text="Rotation Damping")
+ + +class PHYSICS_PT_rigid_body_dynamics_deactivation(PHYSICS_PT_rigidbody_panel, Panel):
+ bl_label = "Deactivation"
+ bl_parent_id = 'PHYSICS_PT_rigid_body_dynamics'
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.object
+ return (obj and obj.rigid_body and
+ obj.rigid_body.type == 'ACTIVE' and
+ (context.engine in cls.COMPAT_ENGINES))
+
+ def draw_header(self, context):
+ ob = context.object
+ rbo = ob.rigid_body
+ self.layout.prop(rbo, "use_deactivation", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ ob = context.object
+ rbo = ob.rigid_body
+
+ layout.active = rbo.use_deactivation
+
+ col = layout.column()
+ col.prop(rbo, "use_start_deactivated")
+ col.prop(rbo, "deactivate_linear_velocity", text="Linear Velocity")
+ col.prop(rbo, "deactivate_angular_velocity", text="Angular Velocity")
+ # TODO: other params such as time?
classes = ( PHYSICS_PT_rigid_body, PHYSICS_PT_rigid_body_collisions, + PHYSICS_PT_rigid_body_collisions_surface,
+ PHYSICS_PT_rigid_body_collisions_sensitivity,
+ PHYSICS_PT_rigid_body_collisions_collections,
PHYSICS_PT_rigid_body_dynamics, + PHYSICS_PT_rigid_body_dynamics_deactivation,
) if __name__ == "__main__": # only for live edit. diff --git a/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py b/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py index 69491f36c63..5e67caadc90 100644 --- a/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py +++ b/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py @@ -139,6 +139,11 @@ class PHYSICS_PT_rigid_body_constraint(PHYSICS_PT_rigidbody_constraint_panel, Pa sub.prop(rbc, "motor_ang_max_impulse", text="Max Impulse") elif rbc.type in {'GENERIC', 'GENERIC_SPRING'}: + if rbc.type == 'GENERIC_SPRING': + row = layout.row() + row.label("Spring Type:") + row.prop(rbc, "spring_type", text="") + col = layout.column(align=True) col.label("Limits:") diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index b1c5edf97e7..83d31ae6114 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -594,8 +594,6 @@ class RENDER_PT_eevee_volumetric(RenderButtonsPanel, Panel): sub = col.column() sub.active = props.use_volumetric_shadows sub.prop(props, "volumetric_shadow_samples", text="Shadow Samples") - col.separator() - col.prop(props, "use_volumetric_colored_transmittance") class RENDER_PT_eevee_subsurface_scattering(RenderButtonsPanel, Panel): diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py index d937f2470b8..a4f6f753669 100644 --- a/release/scripts/startup/bl_ui/properties_texture.py +++ b/release/scripts/startup/bl_ui/properties_texture.py @@ -17,19 +17,21 @@ # ##### END GPL LICENSE BLOCK ##### # <pep8 compliant> -import bpy -from bpy.types import Menu, Panel, UIList +import bpy +from bpy.types import ( + Menu, + Panel, + UIList, +) from bpy.types import ( Brush, FreestyleLineStyle, - Object, ParticleSettings, Texture, ) from rna_prop_ui import PropertyPanel - from .properties_paint_common import brush_texture_settings @@ -47,9 +49,9 @@ class TEXTURE_MT_specials(Menu): class TEXTURE_UL_texslots(UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): - ma = data slot = item tex = slot.texture if slot else None + if self.layout_type in {'DEFAULT', 'COMPACT'}: if tex: layout.prop(tex, "name", text="", emboss=False, icon_value=icon) @@ -131,18 +133,18 @@ class TEXTURE_PT_context(TextureButtonsPanel, Panel): if not pin_id: col.template_texture_user() - col.separator() - if user or pin_id: + col.separator() + if pin_id: col.template_ID(space, "pin_id") else: propname = context.texture_user_property.identifier col.template_ID(user, propname, new="texture.new") - col.separator() - if tex: + col.separator() + split = col.split(percentage=0.2) split.label(text="Type") split.prop(tex, "type", text="") @@ -179,25 +181,35 @@ class TEXTURE_PT_node_mapping(TextureButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False # No animation. + + flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) node = context.texture_node mapping = node.texture_mapping - layout.prop(mapping, "vector_type", expand=True) + col = flow.column() + col.prop(mapping, "vector_type") + + col.separator() + + col = col.column(align=True) + col.prop(mapping, "mapping_x", text="Projection X") + col.prop(mapping, "mapping_y", text="Y") + col.prop(mapping, "mapping_z", text="Z") - row = layout.row() + col.separator() - row.column().prop(mapping, "translation") - row.column().prop(mapping, "rotation") - row.column().prop(mapping, "scale") + col = flow.column() + col.column().prop(mapping, "translation") - layout.label(text="Projection:") + col = flow.column() + col.column().prop(mapping, "rotation") - row = layout.row() - row.prop(mapping, "mapping_x", text="") - row.prop(mapping, "mapping_y", text="") - row.prop(mapping, "mapping_z", text="") + col = flow.column() + col.column().prop(mapping, "scale") class TextureTypePanel(TextureButtonsPanel): @@ -216,21 +228,29 @@ class TEXTURE_PT_clouds(TextureTypePanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True) tex = context.texture - layout.row().prop(tex, "cloud_type", expand=True) - layout.label(text="Noise:") - layout.row().prop(tex, "noise_type", text="Type", expand=True) - layout.prop(tex, "noise_basis", text="Basis") + col = flow.column() + col.prop(tex, "noise_basis", text="Noise Basis") + + col.separator() + + col.prop(tex, "noise_type", text="Type") + + col.separator() - split = layout.split() + col = flow.column() + col.prop(tex, "cloud_type") - col = split.column() + col.separator() + + col = flow.column() col.prop(tex, "noise_scale", text="Size") col.prop(tex, "noise_depth", text="Depth") - - split.prop(tex, "nabla", text="Nabla") + col.prop(tex, "nabla", text="Nabla") class TEXTURE_PT_wood(TextureTypePanel, Panel): @@ -240,26 +260,34 @@ class TEXTURE_PT_wood(TextureTypePanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=False) tex = context.texture - layout.row().prop(tex, "noise_basis_2", expand=True) - layout.row().prop(tex, "wood_type", expand=True) + col = flow.column() + col.prop(tex, "noise_basis", text="Noise Basis") - col = layout.column() - col.active = tex.wood_type in {'RINGNOISE', 'BANDNOISE'} - col.label(text="Noise:") - col.row().prop(tex, "noise_type", text="Type", expand=True) - layout.prop(tex, "noise_basis", text="Basis") + col.separator() - split = layout.split() - split.active = tex.wood_type in {'RINGNOISE', 'BANDNOISE'} + col.prop(tex, "wood_type") - col = split.column() - col.prop(tex, "noise_scale", text="Size") - col.prop(tex, "turbulence") + col.separator() - split.prop(tex, "nabla") + col = flow.column() + col.prop(tex, "noise_basis_2", text="Second Basis") + + col = col.column() + col.active = tex.wood_type in {'RINGNOISE', 'BANDNOISE'} + col.prop(tex, "noise_type", text="Type") + + col.separator() + + sub = flow.column() + sub.active = tex.wood_type in {'RINGNOISE', 'BANDNOISE'} + sub.prop(tex, "noise_scale", text="Size") + sub.prop(tex, "turbulence") + sub.prop(tex, "nabla") class TEXTURE_PT_marble(TextureTypePanel, Panel): @@ -269,22 +297,29 @@ class TEXTURE_PT_marble(TextureTypePanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True) tex = context.texture - layout.row().prop(tex, "marble_type", expand=True) - layout.row().prop(tex, "noise_basis_2", expand=True) - layout.label(text="Noise:") - layout.row().prop(tex, "noise_type", text="Type", expand=True) - layout.prop(tex, "noise_basis", text="Basis") + col = flow.column() + col.prop(tex, "noise_basis", text="Noise Basis") + + col.separator() + + col.prop(tex, "marble_type") - split = layout.split() + col.separator() - col = split.column() + col = flow.column() + col.prop(tex, "noise_basis_2", text="Second Basis") + col.prop(tex, "noise_type", text="Type") + + col.separator() + + col = flow.column() col.prop(tex, "noise_scale", text="Size") col.prop(tex, "noise_depth", text="Depth") - - col = split.column() col.prop(tex, "turbulence") col.prop(tex, "nabla") @@ -296,12 +331,16 @@ class TEXTURE_PT_magic(TextureTypePanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) tex = context.texture - row = layout.row() - row.prop(tex, "noise_depth", text="Depth") - row.prop(tex, "turbulence") + col = flow.column() + col.prop(tex, "noise_depth", text="Depth") + + col = flow.column() + col.prop(tex, "turbulence") class TEXTURE_PT_blend(TextureTypePanel, Panel): @@ -311,15 +350,19 @@ class TEXTURE_PT_blend(TextureTypePanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True) tex = context.texture - layout.prop(tex, "progression") + col = flow.column() + col.prop(tex, "progression") - sub = layout.row() + col.separator() - sub.active = (tex.progression in {'LINEAR', 'QUADRATIC', 'EASING', 'RADIAL'}) - sub.prop(tex, "use_flip_axis", expand=True) + col = flow.column() + col.active = (tex.progression in {'LINEAR', 'QUADRATIC', 'EASING', 'RADIAL'}) + col.prop(tex, "use_flip_axis", text="Orientation") class TEXTURE_PT_stucci(TextureTypePanel, Panel): @@ -329,17 +372,28 @@ class TEXTURE_PT_stucci(TextureTypePanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) tex = context.texture - layout.row().prop(tex, "stucci_type", expand=True) - layout.label(text="Noise:") - layout.row().prop(tex, "noise_type", text="Type", expand=True) - layout.prop(tex, "noise_basis", text="Basis") + col = flow.column() + col.prop(tex, "noise_basis", text="Noise Basis") + + col.separator() - row = layout.row() - row.prop(tex, "noise_scale", text="Size") - row.prop(tex, "turbulence") + col.row().prop(tex, "stucci_type") + + col.separator() + + col = flow.column() + col.prop(tex, "noise_type", text="Type") + + col.separator() + + col = flow.column() + col.prop(tex, "noise_scale", text="Size") + col.prop(tex, "turbulence") class TEXTURE_PT_image(TextureTypePanel, Panel): @@ -348,6 +402,18 @@ class TEXTURE_PT_image(TextureTypePanel, Panel): COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} def draw(self, context): + # TODO: maybe expose the template_ID from the template image here. + layout = self.layout + del layout + + +class TEXTURE_PT_image_settings(TextureTypePanel, Panel): + bl_label = "Settings" + bl_parent_id = 'TEXTURE_PT_image' + tex_type = 'IMAGE' + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} + + def draw(self, context): layout = self.layout tex = context.texture @@ -356,11 +422,13 @@ class TEXTURE_PT_image(TextureTypePanel, Panel): def texture_filter_common(tex, layout): layout.prop(tex, "filter_type", text="Filter Type") + if tex.use_mipmap and tex.filter_type in {'AREA', 'EWA', 'FELINE'}: + col = layout.column() if tex.filter_type == 'FELINE': - layout.prop(tex, "filter_lightprobes", text="Light Probes") + col.prop(tex, "filter_lightprobes", text="Light Probes") else: - layout.prop(tex, "filter_eccentricity", text="Eccentricity") + col.prop(tex, "filter_eccentricity", text="Eccentricity") layout.prop(tex, "filter_size", text="Size") layout.prop(tex, "use_filter_size_min", text="Minimum Size") @@ -376,14 +444,11 @@ class TEXTURE_PT_image_sampling(TextureTypePanel, Panel): def draw(self, context): layout = self.layout layout.use_property_split = True - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) + flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True) - idblock = context_tex_datablock(context) tex = context.texture - slot = getattr(context, "texture_slot", None) col = flow.column() - col.prop(tex, "use_flip_axis", text="Flip X/Y Axis") col.prop(tex, "use_interpolation") col.separator() @@ -396,8 +461,7 @@ class TEXTURE_PT_image_sampling(TextureTypePanel, Panel): col.separator() - col = flow.column() - texture_filter_common(tex, col) + texture_filter_common(tex, flow) class TEXTURE_PT_image_alpha(TextureTypePanel, Panel): @@ -433,43 +497,70 @@ class TEXTURE_PT_image_mapping(TextureTypePanel, Panel): def draw(self, context): layout = self.layout layout.use_property_split = True - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) tex = context.texture - col = flow.column() - col.prop(tex, "extension") + col = layout.column() + col.prop(tex, "use_flip_axis", text="Flip Axes") + + col.separator() + + subcol = layout.column() + subcol.prop(tex, "extension") # use layout, to keep the same location in case of button cycling. + + flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True) if tex.extension == 'REPEAT': + + col = flow.column() sub = col.column(align=True) sub.prop(tex, "repeat_x", text="Repeat X") sub.prop(tex, "repeat_y", text="Y") + col = flow.column() sub = col.column() - sub.prop(tex, "use_mirror_x", text="Mirror X") sub.active = (tex.repeat_x > 1) + sub.prop(tex, "use_mirror_x", text="Mirror X") sub = col.column() - sub.prop(tex, "use_mirror_y", text="Y") sub.active = (tex.repeat_y > 1) + sub.prop(tex, "use_mirror_y", text="Y") elif tex.extension == 'CHECKER': - col = layout.column(align=True) - col.prop(tex, "use_checker_even", text="Even") - col.prop(tex, "use_checker_odd", text="Odd") + subcol.separator() - col = layout.column() + col = flow.column() col.prop(tex, "checker_distance", text="Distance") - col = flow.column() - sub = col.column(align=True) + col = flow.column() + col.prop(tex, "use_checker_even", text="Tiles Even") + col.prop(tex, "use_checker_odd", text="Odd") + else: + del flow + + +class TEXTURE_PT_image_mapping_crop(TextureTypePanel, Panel): + bl_label = "Crop" + bl_options = {'DEFAULT_CLOSED'} + bl_parent_id = 'TEXTURE_PT_image_mapping' + tex_type = 'IMAGE' + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'} + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) + + tex = context.texture + + col = flow.column(align=True) # col.prop(tex, "crop_rectangle") - sub.prop(tex, "crop_min_x", text="Crop Minimum X") - sub.prop(tex, "crop_min_y", text="Y") + col.prop(tex, "crop_min_x", text="Minimum X") + col.prop(tex, "crop_min_y", text="Y") - sub = col.column(align=True) - sub.prop(tex, "crop_max_x", text="Crop Maximum X") - sub.prop(tex, "crop_max_y", text="Y") + col = flow.column(align=True) + col.prop(tex, "crop_max_x", text="Maximum X") + col.prop(tex, "crop_max_y", text="Y") class TEXTURE_PT_musgrave(TextureTypePanel, Panel): @@ -479,34 +570,43 @@ class TEXTURE_PT_musgrave(TextureTypePanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True) tex = context.texture - layout.prop(tex, "musgrave_type") + col = flow.column() + col.prop(tex, "noise_basis", text="Noise Basis") + + col.separator() + + col.prop(tex, "musgrave_type") + + col.separator() + + col.prop(tex, "noise_scale", text="Size") + col.prop(tex, "nabla") - split = layout.split() + col.separator() - col = split.column() + col = flow.column() col.prop(tex, "dimension_max", text="Dimension") col.prop(tex, "lacunarity") col.prop(tex, "octaves") + col.separator() + musgrave_type = tex.musgrave_type - col = split.column() + + col = flow.column() + if musgrave_type in {'HETERO_TERRAIN', 'RIDGED_MULTIFRACTAL', 'HYBRID_MULTIFRACTAL'}: col.prop(tex, "offset") col.prop(tex, "noise_intensity", text="Intensity") + if musgrave_type in {'RIDGED_MULTIFRACTAL', 'HYBRID_MULTIFRACTAL'}: col.prop(tex, "gain") - layout.label(text="Noise:") - - layout.prop(tex, "noise_basis", text="Basis") - - row = layout.row() - row.prop(tex, "noise_scale", text="Size") - row.prop(tex, "nabla") - class TEXTURE_PT_voronoi(TextureTypePanel, Panel): bl_label = "Voronoi" @@ -515,33 +615,51 @@ class TEXTURE_PT_voronoi(TextureTypePanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) tex = context.texture - split = layout.split() + col = flow.column() + col.prop(tex, "distance_metric") - col = split.column() - col.label(text="Distance Metric:") - col.prop(tex, "distance_metric", text="") sub = col.column() sub.active = tex.distance_metric == 'MINKOVSKY' sub.prop(tex, "minkovsky_exponent", text="Exponent") - col.label(text="Coloring:") - col.prop(tex, "color_mode", text="") + + sub.separator() + + col = flow.column() + col.prop(tex, "color_mode") col.prop(tex, "noise_intensity", text="Intensity") - col = split.column() - sub = col.column(align=True) - sub.label(text="Feature Weights:") - sub.prop(tex, "weight_1", text="1", slider=True) - sub.prop(tex, "weight_2", text="2", slider=True) - sub.prop(tex, "weight_3", text="3", slider=True) - sub.prop(tex, "weight_4", text="4", slider=True) + col.separator() + + col = flow.column() + col.prop(tex, "noise_scale", text="Size") + col.prop(tex, "nabla") + + +class TEXTURE_PT_voronoi_feature_weights(TextureTypePanel, Panel): + bl_label = "Feature Weights" + bl_parent_id = "TEXTURE_PT_voronoi" + tex_type = 'VORONOI' + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True) + + tex = context.texture - layout.label(text="Noise:") - row = layout.row() - row.prop(tex, "noise_scale", text="Size") - row.prop(tex, "nabla") + col = flow.column(align=True) + col.prop(tex, "weight_1", text="First", slider=True) + col.prop(tex, "weight_2", text="Second", slider=True) + + sub = flow.column(align=True) + sub.prop(tex, "weight_3", text="Third", slider=True) + sub.prop(tex, "weight_4", text="Fourth", slider=True) class TEXTURE_PT_distortednoise(TextureTypePanel, Panel): @@ -551,19 +669,24 @@ class TEXTURE_PT_distortednoise(TextureTypePanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True) tex = context.texture - layout.prop(tex, "noise_distortion") - layout.prop(tex, "noise_basis", text="Basis") + col = flow.column() + col.prop(tex, "noise_basis", text="Noise Basis") - split = layout.split() + col.separator() - col = split.column() - col.prop(tex, "distortion", text="Distortion") - col.prop(tex, "noise_scale", text="Size") + col.prop(tex, "noise_distortion", text="Distortion") - split.prop(tex, "nabla") + col.separator() + + col = flow.column() + col.prop(tex, "distortion", text="Amount") + col.prop(tex, "noise_scale", text="Size") + col.prop(tex, "nabla") class TextureSlotPanel(TextureButtonsPanel): @@ -595,68 +718,64 @@ class TEXTURE_PT_mapping(TextureSlotPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True) idblock = context_tex_datablock(context) tex = context.texture_slot - if not isinstance(idblock, Brush): - split = layout.split(percentage=0.3) - col = split.column() - col.label(text="Coordinates:") - col = split.column() - col.prop(tex, "texture_coords", text="") + if isinstance(idblock, Brush): + if context.sculpt_object or context.image_paint_object: + brush_texture_settings(layout, idblock, context.sculpt_object) + else: + col = flow.column() - if tex.texture_coords == 'ORCO': - """ - ob = context.object - if ob and ob.type == 'MESH': - split = layout.split(percentage=0.3) - split.label(text="Mesh:") - split.prop(ob.data, "texco_mesh", text="") - """ - elif tex.texture_coords == 'UV': - split = layout.split(percentage=0.3) - split.label(text="Map:") + col.prop(tex, "texture_coords", text="Coordinates") + + # Note: the ORCO case used to call ob.data, "texco_mesh" prop. + if tex.texture_coords == 'UV': ob = context.object + if ob and ob.type == 'MESH': - split.prop_search(tex, "uv_layer", ob.data, "uv_layers", text="") + # Note: TODO prop_search doesn't align on the right. + row = col.row(align=True) + row.prop_search(tex, "uv_layer", ob.data, "uv_layers", text="Map") + row.label(text="", icon='BLANK1') else: - split.prop(tex, "uv_layer", text="") + col.prop(tex, "uv_layer", text="Map") elif tex.texture_coords == 'OBJECT': - split = layout.split(percentage=0.3) - split.label(text="Object:") - split.prop(tex, "object", text="") + col.prop(tex, "object", text="Object") elif tex.texture_coords == 'ALONG_STROKE': - split = layout.split(percentage=0.3) - split.label(text="Use Tips:") - split.prop(tex, "use_tips", text="") + col.prop(tex, "use_tips", text="Use Tips") + + col.separator() - if isinstance(idblock, Brush): - if context.sculpt_object or context.image_paint_object: - brush_texture_settings(layout, idblock, context.sculpt_object) - else: if isinstance(idblock, FreestyleLineStyle): - split = layout.split(percentage=0.3) - split.label(text="Projection:") - split.prop(tex, "mapping", text="") + col = flow.column() + col.prop(tex, "mapping", text="Projection") + + col.separator() + + col = flow.column() + col.prop(tex, "mapping_x", text="Mapping X") + col.prop(tex, "mapping_y", text="Y") + col.prop(tex, "mapping_z", text="Z") - split = layout.split(percentage=0.3) - split.separator() - row = split.row() - row.prop(tex, "mapping_x", text="") - row.prop(tex, "mapping_y", text="") - row.prop(tex, "mapping_z", text="") + col.separator() - row = layout.row() - row.column().prop(tex, "offset") - row.column().prop(tex, "scale") + col = flow.column(align=True) + col.column().prop(tex, "offset") + + col = flow.column(align=True) + col.column().prop(tex, "scale") class TEXTURE_PT_influence(TextureSlotPanel, Panel): bl_label = "Influence" + bl_options = {'DEFAULT_CLOSED'} COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} @classmethod @@ -672,107 +791,126 @@ class TEXTURE_PT_influence(TextureSlotPanel, Panel): return (engine in cls.COMPAT_ENGINES) def draw(self, context): - layout = self.layout + layout.use_property_split = True + flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=False) idblock = context_tex_datablock(context) - tex = context.texture_slot def factor_but(layout, toggle, factor, name): row = layout.row(align=True) - row.prop(tex, toggle, text="") + row.active = getattr(tex, toggle) + + row.prop(tex, factor, text=name, slider=True) sub = row.row(align=True) - sub.active = getattr(tex, toggle) - sub.prop(tex, factor, text=name, slider=True) + sub.prop(tex, toggle, text="") return sub # XXX, temp. use_map_normal needs to override. if isinstance(idblock, ParticleSettings): - split = layout.split() - - col = split.column() - col.label(text="General:") - factor_but(col, "use_map_time", "time_factor", "Time") + col = flow.column() + factor_but(col, "use_map_time", "time_factor", "General Time") factor_but(col, "use_map_life", "life_factor", "Lifetime") factor_but(col, "use_map_density", "density_factor", "Density") factor_but(col, "use_map_size", "size_factor", "Size") - col = split.column() - col.label(text="Physics:") - factor_but(col, "use_map_velocity", "velocity_factor", "Velocity") + col.separator() + + col = flow.column() + factor_but(col, "use_map_velocity", "velocity_factor", "Physics Velocity") factor_but(col, "use_map_damp", "damp_factor", "Damp") factor_but(col, "use_map_gravity", "gravity_factor", "Gravity") factor_but(col, "use_map_field", "field_factor", "Force Fields") - layout.label(text="Hair:") - - split = layout.split() + col.separator() - col = split.column() - factor_but(col, "use_map_length", "length_factor", "Length") + col = flow.column() + factor_but(col, "use_map_length", "length_factor", "Hair Length") factor_but(col, "use_map_clump", "clump_factor", "Clump") factor_but(col, "use_map_twist", "twist_factor", "Twist") - col = split.column() + col = flow.column() factor_but(col, "use_map_kink_amp", "kink_amp_factor", "Kink Amplitude") factor_but(col, "use_map_kink_freq", "kink_freq_factor", "Kink Frequency") factor_but(col, "use_map_rough", "rough_factor", "Rough") elif isinstance(idblock, FreestyleLineStyle): - split = layout.split() - - col = split.column() + col = flow.column() factor_but(col, "use_map_color_diffuse", "diffuse_color_factor", "Color") - col = split.column() factor_but(col, "use_map_alpha", "alpha_factor", "Alpha") - layout.separator() - if not isinstance(idblock, ParticleSettings): - split = layout.split() + col = flow.column() - col = split.column() col.prop(tex, "blend_type", text="Blend") col.prop(tex, "use_rgb_to_intensity") + # color is used on gray-scale textures even when use_rgb_to_intensity is disabled. col.prop(tex, "color", text="") - col = split.column() + col = flow.column() col.prop(tex, "invert", text="Negative") col.prop(tex, "use_stencil") -class TEXTURE_PT_colors(TextureButtonsPanel, Panel): - bl_label = "Colors" - bl_options = {'DEFAULT_CLOSED'} - COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} - +class TextureColorsPoll: @classmethod def poll(cls, context): tex = context.texture return tex and (tex.type != 'NONE' or tex.use_nodes) and (context.engine in cls.COMPAT_ENGINES) + +class TEXTURE_PT_colors(TextureButtonsPanel, TextureColorsPoll, Panel): + bl_label = "Colors" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} + def draw(self, context): layout = self.layout layout.use_property_split = True + flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=False) tex = context.texture - col = layout.column() - sub = col.column(align=True) - sub.prop(tex, "factor_red", text="Multiply R") - sub.prop(tex, "factor_green", text="G") - sub.prop(tex, "factor_blue", text="B") + col = flow.column() + col.prop(tex, "use_clamp", text="Clamp") + + col = flow.column(align=True) + col.prop(tex, "factor_red", text="Multiply R") + col.prop(tex, "factor_green", text="G") + col.prop(tex, "factor_blue", text="B") + col.separator() + + col = flow.column() col.prop(tex, "intensity") col.prop(tex, "contrast") col.prop(tex, "saturation") - col.prop(tex, "use_clamp", text="Clamp") - col.prop(tex, "use_color_ramp", text="Ramp") - if tex.use_color_ramp: - layout.use_property_split = False + +class TEXTURE_PT_colors_ramp(TextureButtonsPanel, TextureColorsPoll, Panel): + bl_label = "Color Ramp" + bl_options = {'DEFAULT_CLOSED'} + bl_parent_id = 'TEXTURE_PT_colors' + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} + + def draw_header(self, context): + tex = context.texture + self.layout.prop(tex, "use_color_ramp", text="") + + def draw(self, context): + layout = self.layout + + tex = context.texture + + # Note: TODO after creation of a new texture, the template_color_ramp will be blank. + # Possibly needs to be fixed in the template itself. + is_active = bool(tex and tex.use_color_ramp) + if is_active: layout.template_color_ramp(tex, "color_ramp", expand=True) + else: + layout.alignment = 'RIGHT' + layout.label("Please enable the Color Ramp first") class TEXTURE_PT_custom_props(TextureButtonsPanel, PropertyPanel, Panel): @@ -792,8 +930,6 @@ classes = ( TEXTURE_PT_context, TEXTURE_PT_node, TEXTURE_PT_node_mapping, - TEXTURE_PT_mapping, - TEXTURE_PT_influence, TEXTURE_PT_clouds, TEXTURE_PT_wood, TEXTURE_PT_marble, @@ -801,13 +937,19 @@ classes = ( TEXTURE_PT_blend, TEXTURE_PT_stucci, TEXTURE_PT_image, + TEXTURE_PT_image_settings, TEXTURE_PT_image_alpha, - TEXTURE_PT_image_sampling, TEXTURE_PT_image_mapping, + TEXTURE_PT_image_mapping_crop, + TEXTURE_PT_image_sampling, TEXTURE_PT_musgrave, TEXTURE_PT_voronoi, + TEXTURE_PT_voronoi_feature_weights, TEXTURE_PT_distortednoise, + TEXTURE_PT_influence, + TEXTURE_PT_mapping, TEXTURE_PT_colors, + TEXTURE_PT_colors_ramp, TEXTURE_PT_custom_props, ) diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py index 9d903829bbb..a85dd591b2f 100644 --- a/release/scripts/startup/bl_ui/space_filebrowser.py +++ b/release/scripts/startup/bl_ui/space_filebrowser.py @@ -56,6 +56,8 @@ class FILEBROWSER_HT_header(Header): layout.separator_spacer() + layout.template_running_jobs() + if params: layout.prop(params, "use_filter", text="", icon='FILTER') @@ -86,8 +88,6 @@ class FILEBROWSER_HT_header(Header): row.separator() row.prop(params, "filter_search", text="", icon='VIEWZOOM') - layout.template_running_jobs() - class FILEBROWSER_UL_dir(UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index 9d8c14ba9c3..45343c09b27 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -364,7 +364,6 @@ class NODE_PT_active_node_generic(Panel): bl_space_type = 'NODE_EDITOR' bl_region_type = 'UI' bl_label = "Node" -# bl_options = {'HIDE_HEADER'} @classmethod def poll(cls, context): @@ -383,6 +382,7 @@ class NODE_PT_active_node_color(Panel): bl_region_type = 'UI' bl_label = "Color" bl_options = {'DEFAULT_CLOSED'} + bl_parent_id = 'NODE_PT_active_node_generic' @classmethod def poll(cls, context): @@ -410,6 +410,8 @@ class NODE_PT_active_node_properties(Panel): bl_space_type = 'NODE_EDITOR' bl_region_type = 'UI' bl_label = "Properties" + bl_options = {'DEFAULT_CLOSED'} + bl_parent_id = 'NODE_PT_active_node_generic' @classmethod def poll(cls, context): @@ -453,18 +455,22 @@ class NODE_PT_backdrop(Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True snode = context.space_data layout.active = snode.show_backdrop - layout.prop(snode, "backdrop_channels", text="") - layout.prop(snode, "backdrop_zoom", text="Zoom") - col = layout.column(align=True) - col.label(text="Offset:") - col.prop(snode, "backdrop_offset", text="") - col.operator("node.backimage_move", text="Move") + col = layout.column() + + col.prop(snode, "backdrop_channels", text="Channels") + col.prop(snode, "backdrop_zoom", text="Zoom") - layout.operator("node.backimage_fit", text="Fit") + col.prop(snode, "backdrop_offset", text="Offset") + + col.separator() + + col.operator("node.backimage_move", text="Move") + col.operator("node.backimage_fit", text="Fit") class NODE_PT_quality(bpy.types.Panel): @@ -479,6 +485,7 @@ class NODE_PT_quality(bpy.types.Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True snode = context.space_data tree = snode.node_tree @@ -522,6 +529,7 @@ class NODE_UL_interface_sockets(bpy.types.UIList): class NODE_PT_grease_pencil(GreasePencilDataPanel, Panel): bl_space_type = 'NODE_EDITOR' bl_region_type = 'UI' + bl_options = {'DEFAULT_CLOSED'} # NOTE: this is just a wrapper around the generic GP Panel diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py index 8f722c4d3ce..20ef5ae0c53 100644 --- a/release/scripts/startup/bl_ui/space_outliner.py +++ b/release/scripts/startup/bl_ui/space_outliner.py @@ -142,8 +142,15 @@ class OUTLINER_MT_collection_view_layer(Menu): space = context.space_data - layout.operator("outliner.collection_exclude_set", text="Exclude") - layout.operator("outliner.collection_include_set", text="Include") + layout.operator("outliner.collection_exclude_set") + layout.operator("outliner.collection_exclude_clear") + + if context.engine == 'CYCLES': + layout.operator("outliner.collection_indirect_only_set") + layout.operator("outliner.collection_indirect_only_clear") + + layout.operator("outliner.collection_holdout_set") + layout.operator("outliner.collection_holdout_clear") class OUTLINER_MT_collection(Menu): diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py index 96ef2e51e60..55129aa0ce1 100644 --- a/release/scripts/startup/bl_ui/space_topbar.py +++ b/release/scripts/startup/bl_ui/space_topbar.py @@ -265,8 +265,8 @@ class INFO_MT_file(Menu): layout.separator() layout.operator_context = 'INVOKE_AREA' - layout.operator("wm.link", text="Link", icon='LINK_BLEND') - layout.operator("wm.append", text="Append", icon='APPEND_BLEND') + layout.operator("wm.link", text="Link...", icon='LINK_BLEND') + layout.operator("wm.append", text="Append...", icon='APPEND_BLEND') layout.menu("INFO_MT_file_previews") layout.separator() @@ -495,12 +495,26 @@ class INFO_MT_help(Menu): def draw(self, context): layout = self.layout + show_developer = context.user_preferences.view.show_developer_ui + layout.operator( "wm.url_open", text="Manual", icon='HELP', ).url = "https://docs.blender.org/manual/en/dev/" + + layout.operator( - "wm.url_open", text="Release Log", icon='URL', - ).url = "http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/%d.%d" % bpy.app.version[:2] + "wm.url_open", text="Report a Bug", icon='URL', + ).url = "https://developer.blender.org/maniphest/task/edit/form/1" + + layout.separator() + + layout.operator( + "wm.url_open", text="User Communities", icon='URL', + ).url = "https://www.blender.org/community/" + layout.operator( + "wm.url_open", text="Developer Community", icon='URL', + ).url = "https://www.blender.org/get-involved/developers/" + layout.separator() layout.operator( @@ -509,24 +523,22 @@ class INFO_MT_help(Menu): layout.operator( "wm.url_open", text="Blender Store", icon='URL', ).url = "https://store.blender.org" + layout.operator( - "wm.url_open", text="Developer Community", icon='URL', - ).url = "https://www.blender.org/get-involved/" - layout.operator( - "wm.url_open", text="User Community", icon='URL', - ).url = "https://www.blender.org/support/user-community" - layout.separator() - layout.operator( - "wm.url_open", text="Report a Bug", icon='URL', - ).url = "https://developer.blender.org/maniphest/task/edit/form/1" + "wm.url_open", text="Release Notes", icon='URL', + ).url = "https://www.blender.org/download/releases/%d-%d/" % bpy.app.version[:2] + layout.separator() - layout.operator( - "wm.url_open", text="Python API Reference", icon='URL', - ).url = bpy.types.WM_OT_doc_view._prefix + if show_developer: + layout.operator( + "wm.url_open", text="Python API Reference", icon='URL', + ).url = bpy.types.WM_OT_doc_view._prefix + + layout.operator("wm.operator_cheat_sheet", icon='TEXT') + + layout.operator("wm.sysinfo") - layout.operator("wm.operator_cheat_sheet", icon='TEXT') - layout.operator("wm.sysinfo", icon='TEXT') layout.separator() layout.operator("wm.splash", icon='BLENDER') @@ -539,8 +551,13 @@ class TOPBAR_MT_file_specials(Menu): layout = self.layout layout.operator_context = 'INVOKE_AREA' - layout.operator("wm.link", text="Link", icon='LINK_BLEND') - layout.operator("wm.append", text="Append", icon='APPEND_BLEND') + layout.operator("wm.read_homefile", text="New", icon='NEW') + layout.operator("wm.open_mainfile", text="Open...", icon='FILE_FOLDER') + + layout.separator() + + layout.operator("wm.link", text="Link...", icon='LINK_BLEND') + layout.operator("wm.append", text="Append...", icon='APPEND_BLEND') layout.separator() diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index e8c640721c8..e6d8b1ec2a7 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -453,7 +453,7 @@ class VIEW3D_MT_snap(Menu): layout.operator("view3d.snap_selected_to_grid", text="Selection to Grid") layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor").use_offset = False - layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor (Offset)").use_offset = True + layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor (Keep Offset)").use_offset = True layout.operator("view3d.snap_selected_to_active", text="Selection to Active") layout.separator() @@ -3839,10 +3839,14 @@ class VIEW3D_PT_shading_color(Panel): shading = VIEW3D_PT_shading.get_shading(context) - layout.row().prop(shading, "color_type", expand=True) - + layout.row().prop(shading, 'color_type', expand=True) if shading.color_type == 'SINGLE': - layout.row().prop(shading, "single_color", text="") + layout.row().prop(shading, 'single_color', text="") + + layout.row().label("Background") + layout.row().prop(shading, 'background_type', expand=True) + if shading.background_type == 'VIEWPORT': + layout.row().prop(shading, "background_color", text="") class VIEW3D_PT_shading_options(Panel): @@ -3912,10 +3916,6 @@ class VIEW3D_PT_shading_options(Panel): if not shading.light == 'MATCAP': col.prop(shading, "show_specular_highlight") - view = context.space_data - if view.type == 'VIEW_3D': - col.prop(view, "show_world") - class VIEW3D_PT_shading_options_shadow(Panel): bl_label = "Shadow Settings" diff --git a/release/scripts/templates_py/batch_export.py b/release/scripts/templates_py/batch_export.py index 1463915886a..a07491742ec 100644 --- a/release/scripts/templates_py/batch_export.py +++ b/release/scripts/templates_py/batch_export.py @@ -9,9 +9,9 @@ basedir = os.path.dirname(bpy.data.filepath) if not basedir: raise Exception("Blend file is not saved") -scene = bpy.context.scene +view_layer = bpy.context.view_layer -obj_active = scene.objects.active +obj_active = view_layer.objects.active selection = bpy.context.selected_objects bpy.ops.object.select_all(action='DESELECT') @@ -21,7 +21,7 @@ for obj in selection: obj.select_set(action='SELECT') # some exporters only use the active object - scene.objects.active = obj + view_layer.objects.active = obj name = bpy.path.clean_name(obj.name) fn = os.path.join(basedir, name) @@ -36,7 +36,7 @@ for obj in selection: print("written:", fn) -scene.objects.active = obj_active +view_layer.objects.active = obj_active for obj in selection: obj.select_set(action='SELECT') diff --git a/release/scripts/templates_py/operator_modal_view3d_raycast.py b/release/scripts/templates_py/operator_modal_view3d_raycast.py index e3b63813fc4..613501143f7 100644 --- a/release/scripts/templates_py/operator_modal_view3d_raycast.py +++ b/release/scripts/templates_py/operator_modal_view3d_raycast.py @@ -68,7 +68,7 @@ def main(context, event): # we could do lots of stuff but for the example just select. if best_obj is not None: best_obj.select_set(action='SELECT') - context.scene.objects.active = best_obj + context.view_layer.objects.active = best_obj class ViewOperatorRayCast(bpy.types.Operator): diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index ea81106e60f..f7a926275a9 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -133,7 +133,8 @@ void blf_batch_draw_begin(FontBLF *font) if (simple_shader) { /* Offset is applied to each glyph. */ - copy_v2_v2(g_batch.ofs, font->pos); + g_batch.ofs[0] = floorf(font->pos[0]); + g_batch.ofs[1] = floorf(font->pos[1]); } else { /* Offset is baked in modelview mat. */ diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c index 99be8539d24..f7f1e10a480 100644 --- a/source/blender/blenfont/intern/blf_glyph.c +++ b/source/blender/blenfont/intern/blf_glyph.c @@ -244,7 +244,7 @@ static void blf_glyph_cache_texture(FontBLF *font, GlyphCacheBLF *gc) gc->textures[gc->texture_current] = tex; GPU_texture_bind(tex, 0); GPU_texture_wrap_mode(tex, false); - GPU_texture_filters(tex, GPU_NEAREST, GPU_NEAREST); + GPU_texture_filters(tex, GPU_NEAREST, GPU_LINEAR); GPU_texture_unbind(tex); } @@ -427,8 +427,8 @@ static void blf_glyph_calc_rect(rctf *rect, GlyphBLF *g, float x, float y) { rect->xmin = floorf(x + g->pos_x); rect->xmax = rect->xmin + (float)g->width; - rect->ymin = y + g->pos_y; - rect->ymax = y + g->pos_y - (float)g->height; + rect->ymin = floorf(y + g->pos_y); + rect->ymax = rect->ymin - (float)g->height; } void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y) diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 8707fe3e11b..79ae904c73d 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -28,7 +28,7 @@ * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 280 -#define BLENDER_SUBVERSION 20 +#define BLENDER_SUBVERSION 21 /* Several breakages with 280, e.g. collections vs layers */ #define BLENDER_MINVERSION 280 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h index d79a7eae53e..a0780a5be54 100644 --- a/source/blender/blenkernel/BKE_bvhutils.h +++ b/source/blender/blenkernel/BKE_bvhutils.h @@ -102,7 +102,7 @@ typedef struct BVHTreeFromMesh { */ BVHTree *bvhtree_from_editmesh_verts( BVHTreeFromEditMesh *data, struct BMEditMesh *em, - float epsilon, int tree_type, int axis); + float epsilon, int tree_type, int axis, BVHCache **bvh_cache); BVHTree *bvhtree_from_editmesh_verts_ex( BVHTreeFromEditMesh *data, struct BMEditMesh *em, const BLI_bitmap *mask, int verts_num_active, @@ -115,7 +115,7 @@ BVHTree *bvhtree_from_mesh_verts_ex( BVHTree *bvhtree_from_editmesh_edges( BVHTreeFromEditMesh *data, struct BMEditMesh *em, - float epsilon, int tree_type, int axis); + float epsilon, int tree_type, int axis, BVHCache **bvh_cache); BVHTree *bvhtree_from_editmesh_edges_ex( BVHTreeFromEditMesh *data, struct BMEditMesh *em, const BLI_bitmap *edges_mask, int edges_num_active, @@ -190,7 +190,9 @@ enum { BVHTREE_FROM_LOOSEVERTS = 4, BVHTREE_FROM_LOOSEEDGES = 5, - BVHTREE_FROM_EM_LOOPTRI = 6, + BVHTREE_FROM_EM_VERTS = 6, + BVHTREE_FROM_EM_EDGES = 7, + BVHTREE_FROM_EM_LOOPTRI = 8, }; diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 51f61c8352c..00fd4ded8c6 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -395,7 +395,7 @@ typedef struct SeqLoadInfo { /* seq_dupli' flags */ -#define SEQ_DUPE_UNIQUE_NAME (1 << 0) +#define SEQ_DUPE_UNIQUE_NAME (1 << 0) /* WARNING: does NOT work when duplicating Meta strips! */ #define SEQ_DUPE_CONTEXT (1 << 1) #define SEQ_DUPE_ANIM (1 << 2) #define SEQ_DUPE_ALL (1 << 3) /* otherwise only selected are copied */ diff --git a/source/blender/blenkernel/BKE_subdiv.h b/source/blender/blenkernel/BKE_subdiv.h index a1792866255..003dc7a37d3 100644 --- a/source/blender/blenkernel/BKE_subdiv.h +++ b/source/blender/blenkernel/BKE_subdiv.h @@ -94,26 +94,6 @@ typedef struct Subdiv { */ SubdivSettings settings; - /* Total number of ptex faces on subdivision level 0. - * - * Ptex face is what is internally used by OpenSubdiv for evaluator. It is - * a quad face, which corresponds to Blender's legacy Catmull Clark grids. - * - * Basically, here is a correspondence between polygons and ptex faces: - * - Triangle consists of 3 PTex faces. - * - Quad is a single PTex face. - * - N-gon is N PTex faces. - * - * This value is initialized in BKE_subdiv_new_from_FOO() and is read-only - * after this. - */ - int num_ptex_faces; - - /* Indexed by base face index, element indicates total number of ptex faces - * created for preceding base faces. - */ - int *face_ptex_offset; - /* Topology refiner includes all the glue logic to feed Blender side * topology to OpenSubdiv. It can be shared by both evaluator and GL mesh * drawer. diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index eed8943cd5b..a867accfe44 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -99,6 +99,8 @@ void animviz_settings_init(bAnimVizSettings *avs) avs->path_viewflag = (MOTIONPATH_VIEW_KFRAS | MOTIONPATH_VIEW_KFNOS); avs->path_step = 1; + + avs->path_bakeflag |= MOTIONPATH_BAKE_HEADS; } /* ------------------- */ diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index 1a7c4e2a4a0..19ac81b4bb7 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -495,12 +495,39 @@ BVHTree *bvhtree_from_editmesh_verts_ex( BVHTree *bvhtree_from_editmesh_verts( BVHTreeFromEditMesh *data, BMEditMesh *em, - float epsilon, int tree_type, int axis) + float epsilon, int tree_type, int axis, BVHCache **bvh_cache) { - return bvhtree_from_editmesh_verts_ex( - data, em, - NULL, -1, - epsilon, tree_type, axis); + if (bvh_cache) { + BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); + data->cached = bvhcache_find(*bvh_cache, BVHTREE_FROM_EM_VERTS, &data->tree); + BLI_rw_mutex_unlock(&cache_rwlock); + + if (data->cached == false) { + BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); + data->cached = bvhcache_find( + *bvh_cache, BVHTREE_FROM_EM_VERTS, &data->tree); + if (data->cached == false) { + data->tree = bvhtree_from_editmesh_verts_ex( + data, em, + NULL, -1, + epsilon, tree_type, axis); + + /* Save on cache for later use */ + /* printf("BVHTree built and saved on cache\n"); */ + bvhcache_insert( + bvh_cache, data->tree, BVHTREE_FROM_EM_VERTS); + } + BLI_rw_mutex_unlock(&cache_rwlock); + } + } + else { + data->tree = bvhtree_from_editmesh_verts_ex( + data, em, + NULL, -1, + epsilon, tree_type, axis); + } + + return data->tree; } /** @@ -649,12 +676,39 @@ BVHTree *bvhtree_from_editmesh_edges_ex( BVHTree *bvhtree_from_editmesh_edges( BVHTreeFromEditMesh *data, BMEditMesh *em, - float epsilon, int tree_type, int axis) + float epsilon, int tree_type, int axis, BVHCache **bvh_cache) { - return bvhtree_from_editmesh_edges_ex( - data, em, - NULL, -1, - epsilon, tree_type, axis); + if (bvh_cache) { + BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); + data->cached = bvhcache_find(*bvh_cache, BVHTREE_FROM_EM_EDGES, &data->tree); + BLI_rw_mutex_unlock(&cache_rwlock); + + if (data->cached == false) { + BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); + data->cached = bvhcache_find( + *bvh_cache, BVHTREE_FROM_EM_EDGES, &data->tree); + if (data->cached == false) { + data->tree = bvhtree_from_editmesh_edges_ex( + data, em, + NULL, -1, + epsilon, tree_type, axis); + + /* Save on cache for later use */ + /* printf("BVHTree built and saved on cache\n"); */ + bvhcache_insert( + bvh_cache, data->tree, BVHTREE_FROM_EM_EDGES); + } + BLI_rw_mutex_unlock(&cache_rwlock); + } + } + else { + data->tree = bvhtree_from_editmesh_edges_ex( + data, em, + NULL, -1, + epsilon, tree_type, axis); + } + + return data->tree; } /** @@ -1407,6 +1461,11 @@ BVHTree *BKE_bvhtree_from_mesh_get( BLI_rw_mutex_unlock(&cache_rwlock); } break; + case BVHTREE_FROM_EM_VERTS: + case BVHTREE_FROM_EM_EDGES: + case BVHTREE_FROM_EM_LOOPTRI: + BLI_assert(false); + break; } if (data_cp.tree != NULL) { diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 4203e0455f8..1b5995de4f0 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -70,12 +70,15 @@ void BKE_camera_init(Camera *cam) cam->sensor_x = DEFAULT_SENSOR_WIDTH; cam->sensor_y = DEFAULT_SENSOR_HEIGHT; cam->clipsta = 0.1f; - cam->clipend = 100.0f; + cam->clipend = 1000.0f; cam->drawsize = 0.5f; cam->ortho_scale = 6.0; cam->flag |= CAM_SHOWPASSEPARTOUT; cam->passepartalpha = 0.5f; + cam->gpu_dof.fstop = 128.0f; + cam->gpu_dof.ratio = 1.0f; + /* stereoscopy 3d */ cam->stereo.interocular_distance = 0.065f; cam->stereo.convergence_distance = 30.f * 0.065f; diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index 2f5c8e7817e..1396ad1f97c 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -715,6 +715,14 @@ static int layer_collection_sync( lc->runtime_flag |= LAYER_COLLECTION_HAS_VISIBLE_OBJECTS; } + /* Holdout and indirect only */ + if (lc->flag & LAYER_COLLECTION_HOLDOUT) { + base->flag |= BASE_HOLDOUT; + } + if (lc->flag & LAYER_COLLECTION_INDIRECT_ONLY) { + base->flag |= BASE_INDIRECT_ONLY; + } + lc->runtime_flag |= LAYER_COLLECTION_HAS_OBJECTS; } @@ -750,7 +758,13 @@ void BKE_layer_collection_sync(const Scene *scene, ViewLayer *view_layer) /* Clear visible and selectable flags to be reset. */ for (Base *base = view_layer->object_bases.first; base; base = base->next) { - base->flag &= ~(BASE_VISIBLE | BASE_ENABLED | BASE_SELECTABLE | BASE_ENABLED_VIEWPORT | BASE_ENABLED_RENDER); + base->flag &= ~(BASE_VISIBLE | + BASE_ENABLED | + BASE_SELECTABLE | + BASE_ENABLED_VIEWPORT | + BASE_ENABLED_RENDER | + BASE_HOLDOUT | + BASE_INDIRECT_ONLY); } view_layer->runtime_flag = 0; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 33ea13c9a38..1d6b23ce7f7 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1204,7 +1204,6 @@ void BKE_object_copy_data(Main *bmain, Object *ob_dst, const Object *ob_src, con ob_dst->derivedDeform = NULL; ob_dst->derivedFinal = NULL; - BLI_listbase_clear(&ob_dst->gpulamp); BLI_listbase_clear((ListBase *)&ob_dst->drawdata); BLI_listbase_clear(&ob_dst->pc_ids); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 35c8761f671..cee1c9147b5 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2941,7 +2941,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons skip = 1; /* only hair, keyed and baked stuff can have paths */ else if (part->ren_as != PART_DRAW_PATH && !(part->type==PART_HAIR && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR))) skip = 1; /* particle visualization must be set as path */ - else { + else if (DEG_get_mode(sim->depsgraph) != DAG_EVAL_RENDER) { if (part->draw_as != PART_DRAW_REND) skip = 1; /* draw visualization */ else if (psys->pointcache->flag & PTCACHE_BAKING) diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 59847b28785..e6b8312734f 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -716,6 +716,35 @@ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool /* --------------------- */ +static void rigidbody_constraint_init_spring( + RigidBodyCon *rbc, void (*set_spring)(rbConstraint*,int,int), + void (*set_stiffness)(rbConstraint*,int,float), void (*set_damping)(rbConstraint*,int,float) +) { + set_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->flag & RBC_FLAG_USE_SPRING_X); + set_stiffness(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_stiffness_x); + set_damping(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_damping_x); + + set_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->flag & RBC_FLAG_USE_SPRING_Y); + set_stiffness(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_stiffness_y); + set_damping(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_damping_y); + + set_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->flag & RBC_FLAG_USE_SPRING_Z); + set_stiffness(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_stiffness_z); + set_damping(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_damping_z); + + set_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->flag & RBC_FLAG_USE_SPRING_ANG_X); + set_stiffness(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->spring_stiffness_ang_x); + set_damping(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->spring_damping_ang_x); + + set_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->flag & RBC_FLAG_USE_SPRING_ANG_Y); + set_stiffness(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->spring_stiffness_ang_y); + set_damping(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->spring_damping_ang_y); + + set_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->flag & RBC_FLAG_USE_SPRING_ANG_Z); + set_stiffness(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->spring_stiffness_ang_z); + set_damping(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->spring_damping_ang_z); +} + static void rigidbody_constraint_set_limits( RigidBodyCon *rbc, void (*set_limits)(rbConstraint *, int, float, float)) { @@ -841,35 +870,24 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b RB_constraint_set_limits_piston(rbc->physics_constraint, lin_lower, lin_upper, ang_lower, ang_upper); break; case RBC_TYPE_6DOF_SPRING: - rbc->physics_constraint = RB_constraint_new_6dof_spring(loc, rot, rb1, rb2); - - RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->flag & RBC_FLAG_USE_SPRING_X); - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_stiffness_x); - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_damping_x); - - RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->flag & RBC_FLAG_USE_SPRING_Y); - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_stiffness_y); - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_damping_y); + if (rbc->spring_type == RBC_SPRING_TYPE2) { + rbc->physics_constraint = RB_constraint_new_6dof_spring2(loc, rot, rb1, rb2); - RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->flag & RBC_FLAG_USE_SPRING_Z); - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_stiffness_z); - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_damping_z); + rigidbody_constraint_init_spring(rbc, RB_constraint_set_spring_6dof_spring2, RB_constraint_set_stiffness_6dof_spring2, RB_constraint_set_damping_6dof_spring2); - RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->flag & RBC_FLAG_USE_SPRING_ANG_X); - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->spring_stiffness_ang_x); - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->spring_damping_ang_x); + RB_constraint_set_equilibrium_6dof_spring2(rbc->physics_constraint); - RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->flag & RBC_FLAG_USE_SPRING_ANG_Y); - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->spring_stiffness_ang_y); - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->spring_damping_ang_y); + rigidbody_constraint_set_limits(rbc, RB_constraint_set_limits_6dof_spring2); + } + else { + rbc->physics_constraint = RB_constraint_new_6dof_spring(loc, rot, rb1, rb2); - RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->flag & RBC_FLAG_USE_SPRING_ANG_Z); - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->spring_stiffness_ang_z); - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->spring_damping_ang_z); + rigidbody_constraint_init_spring(rbc, RB_constraint_set_spring_6dof_spring, RB_constraint_set_stiffness_6dof_spring, RB_constraint_set_damping_6dof_spring); - RB_constraint_set_equilibrium_6dof_spring(rbc->physics_constraint); + RB_constraint_set_equilibrium_6dof_spring(rbc->physics_constraint); - rigidbody_constraint_set_limits(rbc, RB_constraint_set_limits_6dof_spring); + rigidbody_constraint_set_limits(rbc, RB_constraint_set_limits_6dof); + } break; case RBC_TYPE_6DOF: rbc->physics_constraint = RB_constraint_new_6dof(loc, rot, rb1, rb2); @@ -1094,6 +1112,8 @@ RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short ty rbc->flag |= RBC_FLAG_ENABLED; rbc->flag |= RBC_FLAG_DISABLE_COLLISIONS; + rbc->spring_type = RBC_SPRING_TYPE2; + rbc->breaking_threshold = 10.0f; /* no good default here, just use 10 for now */ rbc->num_solver_iterations = 10; /* 10 is Bullet default */ diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 3650fa21c1c..0574eef1a0f 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -878,7 +878,6 @@ void BKE_scene_init(Scene *sce) sce->eevee.flag = SCE_EEVEE_VOLUMETRIC_LIGHTS | - SCE_EEVEE_VOLUMETRIC_COLORED | SCE_EEVEE_GTAO_BENT_NORMALS | SCE_EEVEE_GTAO_BOUNCE | SCE_EEVEE_TAA_REPROJECTION | diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index f8d926a13ed..c107bb04e6e 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -869,6 +869,7 @@ void BKE_screen_view3d_shading_init(View3DShading *shading) shading->cavity_valley_factor = 1.0f; shading->cavity_ridge_factor = 1.0f; copy_v3_fl(shading->single_color, 0.8f); + copy_v3_fl(shading->background_color, 0.05f); } /* magic zoom calculation, no idea what diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index d857db7e276..b5b4ec5cd41 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -5530,6 +5530,7 @@ static Sequence *seq_dupli(const Scene *scene_src, Scene *scene_dst, Sequence *s if (scene_src == scene_dst) { if (dupe_flag & SEQ_DUPE_UNIQUE_NAME) { + /* TODO this is broken in case of Meta strips recursive duplication... Not trivial to fix. */ BKE_sequence_base_unique_name_recursive(&scene_dst->ed->seqbase, seqn); } diff --git a/source/blender/blenkernel/intern/subdiv.c b/source/blender/blenkernel/intern/subdiv.c index 794da2d3477..d8e0c517d91 100644 --- a/source/blender/blenkernel/intern/subdiv.c +++ b/source/blender/blenkernel/intern/subdiv.c @@ -42,23 +42,6 @@ # include "opensubdiv_topology_refiner_capi.h" #endif -#ifdef WITH_OPENSUBDIV -static void update_subdiv_after_topology_change(Subdiv *subdiv) -{ - /* Count ptex faces. */ - subdiv->num_ptex_faces = subdiv->topology_refiner->getNumPtexFaces( - subdiv->topology_refiner); - /* Initialize offset of base faces in ptex indices. */ - MEM_SAFE_FREE(subdiv->face_ptex_offset); - subdiv->face_ptex_offset = MEM_malloc_arrayN(subdiv->num_ptex_faces, - sizeof(int), - "subdiv ptex offset"); - subdiv->topology_refiner->fillFacePtexIndexOffset( - subdiv->topology_refiner, - subdiv->face_ptex_offset); -} -#endif - Subdiv *BKE_subdiv_new_from_converter(const SubdivSettings *settings, struct OpenSubdiv_Converter *converter) { @@ -79,7 +62,6 @@ Subdiv *BKE_subdiv_new_from_converter(const SubdivSettings *settings, subdiv->settings = *settings; subdiv->topology_refiner = osd_topology_refiner; subdiv->evaluator = NULL; - update_subdiv_after_topology_change(subdiv); BKE_subdiv_stats_end(&stats, SUBDIV_STATS_TOPOLOGY_REFINER_CREATION_TIME); subdiv->stats = stats; return subdiv; @@ -113,7 +95,8 @@ void BKE_subdiv_free(Subdiv *subdiv) if (subdiv->topology_refiner != NULL) { openSubdiv_deleteTopologyRefiner(subdiv->topology_refiner); } - MEM_SAFE_FREE(subdiv->face_ptex_offset); MEM_freeN(subdiv); +#else + UNUSED_VARS(subdiv); #endif } diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c b/source/blender/blenkernel/intern/subdiv_mesh.c index 83f2069ea0f..76f41d512bc 100644 --- a/source/blender/blenkernel/intern/subdiv_mesh.c +++ b/source/blender/blenkernel/intern/subdiv_mesh.c @@ -38,27 +38,40 @@ #include "BKE_mesh.h" -/* TODO(sergey): Somehow move this to subdiv code? */ -static int mpoly_ptex_faces_count_get(const MPoly *mp) +#include "MEM_guardedalloc.h" + +/* ============================================================================= + * General helpers. + */ + +/* Number of ptex faces for a given polygon. */ +BLI_INLINE int num_ptex_faces_per_poly_get(const MPoly *poly) { - if (mp->totloop == 4) { - return 1; - } - else { - return mp->totloop; - } + return (poly->totloop == 4) ? 1 : poly->totloop; } -static int num_edges_per_ptex_get(const int resolution) +BLI_INLINE int num_edges_per_ptex_face_get(const int resolution) { return 2 * (resolution - 1) * resolution; } -static int num_polys_per_ptex_get(const int resolution) +/* Number of subdivision polygons per ptex face. */ +BLI_INLINE int num_polys_per_ptex_get(const int resolution) { return (resolution - 1) * (resolution - 1); } +/* Subdivision resolution per given polygon's ptex faces. */ +BLI_INLINE int ptex_face_resolution_get(const MPoly *poly, int resolution) +{ + return (poly->totloop == 4) ? (resolution) + : ((resolution >> 1) + 1); +} + +/* ============================================================================= + * Mesh subdivision context. + */ + typedef struct SubdivMeshContext { const Mesh *coarse_mesh; Subdiv *subdiv; @@ -72,8 +85,127 @@ typedef struct SubdivMeshContext { /* UV layers interpolation. */ int num_uv_layers; MLoopUV *uv_layers[MAX_MTFACE]; + + /* Indexed by coarse polygon index, indicates offset in subdivided mesh + * vertices, edges and polygons arrays, where first element of the poly + * begins. + */ + int *subdiv_vertex_offset; + int *subdiv_edge_offset; + int *subdiv_polygon_offset; + /* Indexed by base face index, element indicates total number of ptex faces + * created for preceding base faces. + */ + int *face_ptex_offset; + + /* Counters of geometry in subdivided mesh, initialized as a part of + * offsets calculation. + */ + int num_subdiv_vertices; + int num_subdiv_edges; + int num_subdiv_loops; + int num_subdiv_polygons; } SubdivMeshContext; +static void subdiv_mesh_ctx_cache_uv_layers(SubdivMeshContext *ctx) +{ + Mesh *subdiv_mesh = ctx->subdiv_mesh; + ctx->num_uv_layers = + CustomData_number_of_layers(&subdiv_mesh->ldata, CD_MLOOPUV); + for (int layer_index = 0; layer_index < ctx->num_uv_layers; ++layer_index) { + ctx->uv_layers[layer_index] = CustomData_get_layer_n( + &subdiv_mesh->ldata, CD_MLOOPUV, layer_index); + } +} + +static void subdiv_mesh_ctx_cache_custom_data_layers(SubdivMeshContext *ctx) +{ + Mesh *subdiv_mesh = ctx->subdiv_mesh; + /* Pointers to original indices layers. */ + ctx->vert_origindex = CustomData_get_layer( + &subdiv_mesh->vdata, CD_ORIGINDEX); + ctx->edge_origindex = CustomData_get_layer( + &subdiv_mesh->edata, CD_ORIGINDEX); + ctx->loop_origindex = CustomData_get_layer( + &subdiv_mesh->ldata, CD_ORIGINDEX); + ctx->poly_origindex = CustomData_get_layer( + &subdiv_mesh->pdata, CD_ORIGINDEX); + /* UV layers interpolation. */ + subdiv_mesh_ctx_cache_uv_layers(ctx); +} + +static void subdiv_mesh_ctx_init_offsets(SubdivMeshContext *ctx) +{ + const Mesh *coarse_mesh = ctx->coarse_mesh; + const MPoly *coarse_mpoly = coarse_mesh->mpoly; + /* Allocate memory. */ + ctx->subdiv_vertex_offset = MEM_malloc_arrayN( + coarse_mesh->totpoly, + sizeof(*ctx->subdiv_vertex_offset), + "vertex_offset"); + ctx->subdiv_edge_offset = MEM_malloc_arrayN( + coarse_mesh->totpoly, + sizeof(*ctx->subdiv_edge_offset), + "subdiv_edge_offset"); + ctx->subdiv_polygon_offset = MEM_malloc_arrayN( + coarse_mesh->totpoly, + sizeof(*ctx->subdiv_polygon_offset), + "subdiv_polygon_offset"); + ctx->face_ptex_offset = MEM_malloc_arrayN(coarse_mesh->totpoly, + sizeof(*ctx->face_ptex_offset), + "face_ptex_offset"); + /* Fill in offsets. */ + int vertex_offset = 0; + int edge_offset = 0; + int polygon_offset = 0; + int face_ptex_offset = 0; + for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) { + const MPoly *coarse_poly = &coarse_mpoly[poly_index]; + const int ptex_face_resolution = ptex_face_resolution_get( + coarse_poly, ctx->settings->resolution); + const int ptex_face_resolution2 = + ptex_face_resolution * ptex_face_resolution; + const int num_ptex_faces_per_poly = + num_ptex_faces_per_poly_get(coarse_poly); + ctx->subdiv_vertex_offset[poly_index] = vertex_offset; + ctx->subdiv_edge_offset[poly_index] = edge_offset; + ctx->subdiv_polygon_offset[poly_index] = polygon_offset; + ctx->face_ptex_offset[poly_index] = face_ptex_offset; + vertex_offset += num_ptex_faces_per_poly * ptex_face_resolution2; + edge_offset += num_ptex_faces_per_poly * + num_edges_per_ptex_face_get(ptex_face_resolution); + polygon_offset += + num_ptex_faces_per_poly * + num_polys_per_ptex_get(ptex_face_resolution); + face_ptex_offset += num_ptex_faces_per_poly; + } + ctx->num_subdiv_vertices = vertex_offset; + ctx->num_subdiv_edges = edge_offset; + ctx->num_subdiv_polygons = polygon_offset; + ctx->num_subdiv_loops = 4 * ctx->num_subdiv_polygons; +} + +static void subdiv_mesh_ctx_init(SubdivMeshContext *ctx) +{ + subdiv_mesh_ctx_init_offsets(ctx); +} + +static void subdiv_mesh_ctx_init_result(SubdivMeshContext *ctx) +{ + subdiv_mesh_ctx_cache_custom_data_layers(ctx); +} + +static void subdiv_mesh_ctx_free(SubdivMeshContext *ctx) +{ + MEM_freeN(ctx->subdiv_vertex_offset); + MEM_freeN(ctx->subdiv_edge_offset); + MEM_freeN(ctx->face_ptex_offset); +} + +/* ============================================================================= + * Loop custom data copy helpers. + */ + typedef struct LoopsOfPtex { /* First loop of the ptex, starts at ptex (0, 0) and goes in u direction. */ const MLoop *first_loop; @@ -112,6 +244,10 @@ static void loops_of_ptex_get( } } +/* ============================================================================= + * Edge custom data copy helpers. + */ + typedef struct EdgesOfPtex { /* First edge of the ptex, starts at ptex (0, 0) and goes in u direction. */ const MEdge *first_edge; @@ -145,6 +281,10 @@ static void edges_of_ptex_get( } } +/* ============================================================================= + * Vertex custom data interpolation helpers. + */ + /* TODO(sergey): Somehow de-duplicate with loops storage, without too much * exception cases all over the code. */ @@ -215,7 +355,7 @@ static void vertex_interpolation_init( int *indices = BLI_array_alloca(indices, coarse_poly->totloop); for (int i = 0; i < coarse_poly->totloop; ++i) { weights[i] = weight; - indices[i] = coarse_poly->loopstart + i; + indices[i] = coarse_mloop[coarse_poly->loopstart + i].v; } CustomData_interp(&coarse_mesh->vdata, &vertex_interpolation->vertex_data_storage, @@ -255,13 +395,15 @@ static void vertex_interpolation_from_ptex( * iteration. */ const float weights[2] = {0.5f, 0.5f}; + const int first_loop_index = loops_of_ptex.first_loop - coarse_mloop; + const int last_loop_index = loops_of_ptex.last_loop - coarse_mloop; const int first_indices[2] = { - coarse_mloop[loops_of_ptex.first_loop - coarse_mloop].v, - coarse_mloop[(loops_of_ptex.first_loop + 1 - coarse_mloop) % - coarse_poly->totloop].v}; - const int last_indices[2] = { - coarse_mloop[loops_of_ptex.last_loop - coarse_mloop].v, - coarse_mloop[loops_of_ptex.first_loop - coarse_mloop].v}; + coarse_mloop[first_loop_index].v, + coarse_mloop[coarse_poly->loopstart + + (first_loop_index - coarse_poly->loopstart + 1) % + coarse_poly->totloop].v}; + const int last_indices[2] = {coarse_mloop[first_loop_index].v, + coarse_mloop[last_loop_index].v}; CustomData_interp(vertex_data, &vertex_interpolation->vertex_data_storage, first_indices, @@ -285,6 +427,10 @@ static void vertex_interpolation_end( } } +/* ============================================================================= + * Loop custom data interpolation helpers. + */ + typedef struct LoopsForInterpolation { /* This field points to a loop data which is to be used for interpolation. * The idea is to avoid unnecessary allocations for regular faces, where @@ -413,13 +559,17 @@ static void loop_interpolation_end(LoopsForInterpolation *loop_interpolation) } } +/* ============================================================================= + * Vertex subdivision process. + */ + static void subdiv_copy_vertex_data( const SubdivMeshContext *ctx, MVert *subdiv_vertex, - const Mesh *coarse_mesh, + const Mesh *UNUSED(coarse_mesh), const MPoly *coarse_poly, const VerticesForInterpolation *vertex_interpolation, - const int ptex_of_poly_index, + const int UNUSED(ptex_of_poly_index), const float u, const float v) { const int subdiv_vertex_index = subdiv_vertex - ctx->subdiv_mesh->mvert; @@ -437,27 +587,33 @@ static void subdiv_copy_vertex_data( ctx->vert_origindex[subdiv_vertex_index] = ORIGINDEX_NONE; if (coarse_poly->totloop == 4) { if (u == 0.0f && v == 0.0f) { - ctx->vert_origindex[subdiv_vertex_index] = - vertex_interpolation->vertex_indices[0]; + // ctx->vert_origindex[subdiv_vertex_index] = + // vertex_interpolation->vertex_indices[0]; } else if (u == 1.0f && v == 0.0f) { - ctx->vert_origindex[subdiv_vertex_index] = - vertex_interpolation->vertex_indices[1]; + // ctx->vert_origindex[subdiv_vertex_index] = + // vertex_interpolation->vertex_indices[1]; } else if (u == 1.0f && v == 1.0f) { - ctx->vert_origindex[subdiv_vertex_index] = - vertex_interpolation->vertex_indices[2]; + // ctx->vert_origindex[subdiv_vertex_index] = + // vertex_interpolation->vertex_indices[2]; } else if (u == 0.0f && v == 1.0f) { - ctx->vert_origindex[subdiv_vertex_index] = - vertex_interpolation->vertex_indices[3]; + // ctx->vert_origindex[subdiv_vertex_index] = + // vertex_interpolation->vertex_indices[3]; + } + else { + ctx->vert_origindex[subdiv_vertex_index] = ORIGINDEX_NONE; } } else { if (u == 0.0f && v == 0.0f) { - const MLoop *coarse_mloop = coarse_mesh->mloop; - ctx->vert_origindex[subdiv_vertex_index] = - coarse_mloop[coarse_poly->loopstart + - ptex_of_poly_index].v; + // const MLoop *coarse_mloop = coarse_mesh->mloop; + // ctx->vert_origindex[subdiv_vertex_index] = + // coarse_mloop[coarse_poly->loopstart + + // ptex_of_poly_index].v; + } + else { + ctx->vert_origindex[subdiv_vertex_index] = ORIGINDEX_NONE; } } } @@ -468,23 +624,26 @@ static void subdiv_evaluate_vertices(SubdivMeshContext *ctx, { Subdiv *subdiv = ctx->subdiv; const int resolution = ctx->settings->resolution; - const int resolution2 = resolution * resolution; - const float inv_resolution_1 = 1.0f / (float)(resolution - 1); + const int start_vertex_index = ctx->subdiv_vertex_offset[poly_index]; /* Base/coarse mesh information. */ const Mesh *coarse_mesh = ctx->coarse_mesh; - const MPoly *coarse_polyoly = coarse_mesh->mpoly; - const MPoly *coarse_poly = &coarse_polyoly[poly_index]; - const int num_poly_ptex_faces = mpoly_ptex_faces_count_get(coarse_poly); + const MPoly *coarse_mpoly = coarse_mesh->mpoly; + const MPoly *coarse_poly = &coarse_mpoly[poly_index]; + const int num_ptex_faces_per_poly = + num_ptex_faces_per_poly_get(coarse_poly); + const int ptex_resolution = + ptex_face_resolution_get(coarse_poly, resolution); + const float inv_ptex_resolution_1 = 1.0f / (float)(ptex_resolution - 1); /* Hi-poly subdivided mesh. */ Mesh *subdiv_mesh = ctx->subdiv_mesh; MVert *subdiv_vertex = subdiv_mesh->mvert; - const int ptex_face_index = subdiv->face_ptex_offset[poly_index]; + MVert *subdiv_vert = &subdiv_vertex[start_vertex_index]; /* Actual evaluation. */ VerticesForInterpolation vertex_interpolation; vertex_interpolation_init(ctx, &vertex_interpolation, coarse_poly); - MVert *subdiv_vert = &subdiv_vertex[ptex_face_index * resolution2]; + const int ptex_face_index = ctx->face_ptex_offset[poly_index]; for (int ptex_of_poly_index = 0; - ptex_of_poly_index < num_poly_ptex_faces; + ptex_of_poly_index < num_ptex_faces_per_poly; ptex_of_poly_index++) { vertex_interpolation_from_ptex(ctx, @@ -496,13 +655,13 @@ static void subdiv_evaluate_vertices(SubdivMeshContext *ctx, BKE_subdiv_eval_limit_patch_resolution_point_and_short_normal( subdiv, current_ptex_face_index, - resolution, + ptex_resolution, subdiv_vert, offsetof(MVert, co), sizeof(MVert), subdiv_vert, offsetof(MVert, no), sizeof(MVert)); - for (int y = 0; y < resolution; y++) { - const float v = y * inv_resolution_1; - for (int x = 0; x < resolution; x++, subdiv_vert++) { - const float u = x * inv_resolution_1; + for (int y = 0; y < ptex_resolution; y++) { + const float v = y * inv_ptex_resolution_1; + for (int x = 0; x < ptex_resolution; x++, subdiv_vert++) { + const float u = x * inv_ptex_resolution_1; subdiv_copy_vertex_data(ctx, subdiv_vert, coarse_mesh, @@ -516,6 +675,10 @@ static void subdiv_evaluate_vertices(SubdivMeshContext *ctx, vertex_interpolation_end(&vertex_interpolation); } +/* ============================================================================= + * Edge subdivision process. + */ + static void subdiv_copy_edge_data( SubdivMeshContext *ctx, MEdge *subdiv_edge, @@ -590,22 +753,22 @@ static MEdge *subdiv_create_edges_column(SubdivMeshContext *ctx, static void subdiv_create_edges(SubdivMeshContext *ctx, int poly_index) { - Subdiv *subdiv = ctx->subdiv; - const int resolution = ctx->settings->resolution; - const int resolution2 = resolution * resolution; - const int ptex_face_index = subdiv->face_ptex_offset[poly_index]; - const int num_edges_per_ptex = num_edges_per_ptex_get(resolution); - const int start_edge_index = ptex_face_index * num_edges_per_ptex; + const int start_vertex_index = ctx->subdiv_vertex_offset[poly_index]; + const int start_edge_index = ctx->subdiv_edge_offset[poly_index]; /* Base/coarse mesh information. */ const Mesh *coarse_mesh = ctx->coarse_mesh; - const MPoly *coarse_polyoly = coarse_mesh->mpoly; - const MPoly *coarse_poly = &coarse_polyoly[poly_index]; - const int num_poly_ptex_faces = mpoly_ptex_faces_count_get(coarse_poly); + const MPoly *coarse_mpoly = coarse_mesh->mpoly; + const MPoly *coarse_poly = &coarse_mpoly[poly_index]; + const int num_ptex_faces_per_poly = + num_ptex_faces_per_poly_get(coarse_poly); + const int ptex_face_resolution = ptex_face_resolution_get( + coarse_poly, ctx->settings->resolution); + const int ptex_face_resolution2 = + ptex_face_resolution * ptex_face_resolution; /* Hi-poly subdivided mesh. */ Mesh *subdiv_mesh = ctx->subdiv_mesh; MEdge *subdiv_medge = subdiv_mesh->medge; MEdge *subdiv_edge = &subdiv_medge[start_edge_index]; - const int start_poly_vertex_index = ptex_face_index * resolution2; /* Consider a subdivision of base face at level 1: * * y @@ -619,22 +782,25 @@ static void subdiv_create_edges(SubdivMeshContext *ctx, int poly_index) * * This is illustrate which parts of geometry is created by code below. */ - for (int i = 0; i < num_poly_ptex_faces; i++) { + for (int ptex_of_poly_index = 0; + ptex_of_poly_index < num_ptex_faces_per_poly; + ptex_of_poly_index++) + { const int start_ptex_face_vertex_index = - start_poly_vertex_index + i * resolution2; + start_vertex_index + ptex_of_poly_index * ptex_face_resolution2; EdgesOfPtex edges_of_ptex; - edges_of_ptex_get(ctx, &edges_of_ptex, coarse_poly, i); + edges_of_ptex_get(ctx, &edges_of_ptex, coarse_poly, ptex_of_poly_index); /* Create bottom row of edges (0-1, 1-2). */ subdiv_edge = subdiv_create_edges_row( ctx, subdiv_edge, edges_of_ptex.first_edge, start_ptex_face_vertex_index, - resolution); + ptex_face_resolution); /* Create remaining edges. */ - for (int row = 0; row < resolution - 1; row++) { + for (int row = 0; row < ptex_face_resolution - 1; row++) { const int start_row_vertex_index = - start_ptex_face_vertex_index + row * resolution; + start_ptex_face_vertex_index + row * ptex_face_resolution; /* Create vertical columns. * * At first iteration it will be edges (0-3. 1-4, 2-5), then it @@ -646,7 +812,7 @@ static void subdiv_create_edges(SubdivMeshContext *ctx, int poly_index) edges_of_ptex.last_edge, edges_of_ptex.second_edge, start_row_vertex_index, - resolution); + ptex_face_resolution); /* Create horizontal edge row. * * At first iteration it will be edges (3-4, 4-5), then it will be @@ -655,14 +821,18 @@ static void subdiv_create_edges(SubdivMeshContext *ctx, int poly_index) subdiv_edge = subdiv_create_edges_row( ctx, subdiv_edge, - (row == resolution - 2) ? edges_of_ptex.third_edge - : NULL, - start_row_vertex_index + resolution, - resolution); + (row == ptex_face_resolution - 2) ? edges_of_ptex.third_edge + : NULL, + start_row_vertex_index + ptex_face_resolution, + ptex_face_resolution); } } } +/* ============================================================================= + * Loops creation/interpolation. + */ + static void subdiv_copy_loop_data( const SubdivMeshContext *ctx, MLoop *subdiv_loop, @@ -723,24 +893,25 @@ static void subdiv_eval_uv_layer(SubdivMeshContext *ctx, static void subdiv_create_loops(SubdivMeshContext *ctx, int poly_index) { - Subdiv *subdiv = ctx->subdiv; const int resolution = ctx->settings->resolution; - const int resolution2 = resolution * resolution; - const float inv_resolution_1 = 1.0f / (float)(resolution - 1); - const int ptex_face_index = subdiv->face_ptex_offset[poly_index]; - const int num_edges_per_ptex = num_edges_per_ptex_get(resolution); - const int start_edge_index = ptex_face_index * num_edges_per_ptex; - const int num_polys_per_ptex = num_polys_per_ptex_get(resolution); - const int start_poly_index = ptex_face_index * num_polys_per_ptex; - const int start_loop_index = 4 * start_poly_index; - const int start_vert_index = ptex_face_index * resolution2; - const float du = inv_resolution_1; - const float dv = inv_resolution_1; + const int ptex_face_index = ctx->face_ptex_offset[poly_index]; + const int start_vertex_index = ctx->subdiv_vertex_offset[poly_index]; + const int start_edge_index = ctx->subdiv_edge_offset[poly_index]; + const int start_poly_index = ctx->subdiv_polygon_offset[poly_index]; /* Base/coarse mesh information. */ const Mesh *coarse_mesh = ctx->coarse_mesh; - const MPoly *coarse_polyoly = coarse_mesh->mpoly; - const MPoly *coarse_poly = &coarse_polyoly[poly_index]; - const int num_poly_ptex_faces = mpoly_ptex_faces_count_get(coarse_poly); + const MPoly *coarse_mpoly = coarse_mesh->mpoly; + const MPoly *coarse_poly = &coarse_mpoly[poly_index]; + const int num_ptex_faces_per_poly = + num_ptex_faces_per_poly_get(coarse_poly); + const int ptex_resolution = + ptex_face_resolution_get(coarse_poly, resolution); + const int ptex_resolution2 = ptex_resolution * ptex_resolution; + const float inv_ptex_resolution_1 = 1.0f / (float)(ptex_resolution - 1); + const int num_edges_per_ptex = num_edges_per_ptex_face_get(ptex_resolution); + const int start_loop_index = 4 * start_poly_index; + const float du = inv_ptex_resolution_1; + const float dv = inv_ptex_resolution_1; /* Hi-poly subdivided mesh. */ Mesh *subdiv_mesh = ctx->subdiv_mesh; MLoop *subdiv_loopoop = subdiv_mesh->mloop; @@ -748,7 +919,7 @@ static void subdiv_create_loops(SubdivMeshContext *ctx, int poly_index) LoopsForInterpolation loop_interpolation; loop_interpolation_init(ctx, &loop_interpolation, coarse_poly); for (int ptex_of_poly_index = 0; - ptex_of_poly_index < num_poly_ptex_faces; + ptex_of_poly_index < num_ptex_faces_per_poly; ptex_of_poly_index++) { loop_interpolation_from_ptex(ctx, @@ -757,24 +928,24 @@ static void subdiv_create_loops(SubdivMeshContext *ctx, int poly_index) ptex_of_poly_index); const int current_ptex_face_index = ptex_face_index + ptex_of_poly_index; - for (int y = 0; y < resolution - 1; y++) { - const float v = y * inv_resolution_1; - for (int x = 0; x < resolution - 1; x++, subdiv_loop += 4) { - const float u = x * inv_resolution_1; + for (int y = 0; y < ptex_resolution - 1; y++) { + const float v = y * inv_ptex_resolution_1; + for (int x = 0; x < ptex_resolution - 1; x++, subdiv_loop += 4) { + const float u = x * inv_ptex_resolution_1; /* Vertex indicies ordered counter-clockwise. */ - const int v0 = start_vert_index + - (ptex_of_poly_index * resolution2) + - (y * resolution + x); + const int v0 = start_vertex_index + + (ptex_of_poly_index * ptex_resolution2) + + (y * ptex_resolution + x); const int v1 = v0 + 1; - const int v2 = v0 + resolution + 1; - const int v3 = v0 + resolution; + const int v2 = v0 + ptex_resolution + 1; + const int v3 = v0 + ptex_resolution; /* Edge indicies ordered counter-clockwise. */ const int e0 = start_edge_index + (ptex_of_poly_index * num_edges_per_ptex) + - (y * (2 * resolution - 1) + x); - const int e1 = e0 + resolution; - const int e2 = e0 + (2 * resolution - 1); - const int e3 = e0 + resolution - 1; + (y * (2 * ptex_resolution - 1) + x); + const int e1 = e0 + ptex_resolution; + const int e2 = e0 + (2 * ptex_resolution - 1); + const int e3 = e0 + ptex_resolution - 1; /* Initialize 4 loops of corresponding hi-poly poly. */ /* TODO(sergey): For ptex boundaries we should use loops from * coarse mesh. @@ -808,13 +979,17 @@ static void subdiv_create_loops(SubdivMeshContext *ctx, int poly_index) subdiv_loop, current_ptex_face_index, u, v, - inv_resolution_1); + inv_ptex_resolution_1); } } } loop_interpolation_end(&loop_interpolation); } +/* ============================================================================= + * Polygons subdivision process. + */ + static void subdiv_copy_poly_data(const SubdivMeshContext *ctx, MPoly *subdiv_poly, const MPoly *coarse_poly) @@ -827,30 +1002,31 @@ static void subdiv_copy_poly_data(const SubdivMeshContext *ctx, subdiv_poly_index, 1); if (ctx->poly_origindex != NULL) { - ctx->poly_origindex[subdiv_poly_index] = coarse_poly_index; + // ctx->poly_origindex[subdiv_poly_index] = coarse_poly_index; } } static void subdiv_create_polys(SubdivMeshContext *ctx, int poly_index) { - Subdiv *subdiv = ctx->subdiv; const int resolution = ctx->settings->resolution; - const int ptex_face_index = subdiv->face_ptex_offset[poly_index]; - const int num_polys_per_ptex = num_polys_per_ptex_get(resolution); - const int num_loops_per_ptex = 4 * num_polys_per_ptex; - const int start_poly_index = ptex_face_index * num_polys_per_ptex; - const int start_loop_index = 4 * start_poly_index; + const int start_poly_index = ctx->subdiv_polygon_offset[poly_index]; /* Base/coarse mesh information. */ const Mesh *coarse_mesh = ctx->coarse_mesh; - const MPoly *coarse_polyoly = coarse_mesh->mpoly; - const MPoly *coarse_poly = &coarse_polyoly[poly_index]; - const int num_poly_ptex_faces = mpoly_ptex_faces_count_get(coarse_poly); + const MPoly *coarse_mpoly = coarse_mesh->mpoly; + const MPoly *coarse_poly = &coarse_mpoly[poly_index]; + const int num_ptex_faces_per_poly = + num_ptex_faces_per_poly_get(coarse_poly); + const int ptex_resolution = + ptex_face_resolution_get(coarse_poly, resolution); + const int num_polys_per_ptex = num_polys_per_ptex_get(ptex_resolution); + const int num_loops_per_ptex = 4 * num_polys_per_ptex; + const int start_loop_index = 4 * start_poly_index; /* Hi-poly subdivided mesh. */ Mesh *subdiv_mesh = ctx->subdiv_mesh; MPoly *subdiv_mpoly = subdiv_mesh->mpoly; MPoly *subdiv_mp = &subdiv_mpoly[start_poly_index]; for (int ptex_of_poly_index = 0; - ptex_of_poly_index < num_poly_ptex_faces; + ptex_of_poly_index < num_ptex_faces_per_poly; ptex_of_poly_index++) { for (int subdiv_poly_index = 0; @@ -866,6 +1042,10 @@ static void subdiv_create_polys(SubdivMeshContext *ctx, int poly_index) } } +/* ============================================================================= + * Subdivision process entry points. + */ + static void subdiv_eval_task( void *__restrict userdata, const int poly_index, @@ -880,33 +1060,6 @@ static void subdiv_eval_task( subdiv_create_polys(data, poly_index); } -static void cache_uv_layers(SubdivMeshContext *ctx) -{ - Mesh *subdiv_mesh = ctx->subdiv_mesh; - ctx->num_uv_layers = - CustomData_number_of_layers(&subdiv_mesh->ldata, CD_MLOOPUV); - for (int layer_index = 0; layer_index < ctx->num_uv_layers; ++layer_index) { - ctx->uv_layers[layer_index] = CustomData_get_layer_n( - &subdiv_mesh->ldata, CD_MLOOPUV, layer_index); - } -} - -static void cache_custom_data_layers(SubdivMeshContext *ctx) -{ - Mesh *subdiv_mesh = ctx->subdiv_mesh; - /* Pointers to original indices layers. */ - ctx->vert_origindex = CustomData_get_layer( - &subdiv_mesh->vdata, CD_ORIGINDEX); - ctx->edge_origindex = CustomData_get_layer( - &subdiv_mesh->edata, CD_ORIGINDEX); - ctx->loop_origindex = CustomData_get_layer( - &subdiv_mesh->ldata, CD_ORIGINDEX); - ctx->poly_origindex = CustomData_get_layer( - &subdiv_mesh->pdata, CD_ORIGINDEX); - /* UV layers interpolation. */ - cache_uv_layers(ctx); -} - Mesh *BKE_subdiv_to_mesh( Subdiv *subdiv, const SubdivToMeshSettings *settings, @@ -917,29 +1070,20 @@ Mesh *BKE_subdiv_to_mesh( * is is refined for the new positions of coarse vertices. */ BKE_subdiv_eval_update_from_mesh(subdiv, coarse_mesh); - const int resolution = settings->resolution; - const int resolution2 = resolution * resolution; - const int num_result_verts = subdiv->num_ptex_faces * resolution2; - const int num_result_edges = - subdiv->num_ptex_faces * num_edges_per_ptex_get(resolution); - const int num_result_polys = - subdiv->num_ptex_faces * num_polys_per_ptex_get(resolution); - const int num_result_loops = 4 * num_result_polys; - /* Create mesh and its arrays. */ + SubdivMeshContext ctx = {0}; + ctx.coarse_mesh = coarse_mesh; + ctx.subdiv = subdiv; + ctx.settings = settings; + subdiv_mesh_ctx_init(&ctx); Mesh *result = BKE_mesh_new_nomain_from_template( coarse_mesh, - num_result_verts, - num_result_edges, + ctx.num_subdiv_vertices, + ctx.num_subdiv_edges, 0, - num_result_loops, - num_result_polys); - /* Evaluate subdivisions of base faces in threads. */ - SubdivMeshContext ctx; - ctx.coarse_mesh = coarse_mesh; - ctx.subdiv = subdiv; + ctx.num_subdiv_loops, + ctx.num_subdiv_polygons); ctx.subdiv_mesh = result; - ctx.settings = settings; - cache_custom_data_layers(&ctx); + subdiv_mesh_ctx_init_result(&ctx); /* Multi-threaded evaluation. */ ParallelRangeSettings parallel_range_settings; BLI_parallel_range_settings_defaults(¶llel_range_settings); @@ -947,6 +1091,8 @@ Mesh *BKE_subdiv_to_mesh( &ctx, subdiv_eval_task, ¶llel_range_settings); + subdiv_mesh_ctx_free(&ctx); + // BKE_mesh_validate(result, true, true); BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH); return result; } diff --git a/source/blender/blenlib/intern/BLI_kdtree.c b/source/blender/blenlib/intern/BLI_kdtree.c index 700000b7717..80a2957d907 100644 --- a/source/blender/blenlib/intern/BLI_kdtree.c +++ b/source/blender/blenlib/intern/BLI_kdtree.c @@ -774,7 +774,12 @@ int BLI_kdtree_calc_duplicates_fast( if (ELEM(duplicates[index], -1, index)) { p.search = index; copy_v3_v3(p.search_co, tree->nodes[node_index].co); + int found_prev = found; deduplicate_recursive(&p, tree->root); + if (found != found_prev) { + /* Prevent chains of doubles. */ + duplicates[index] = index; + } } } MEM_freeN(order); @@ -786,7 +791,12 @@ int BLI_kdtree_calc_duplicates_fast( if (ELEM(duplicates[index], -1, index)) { p.search = index; copy_v3_v3(p.search_co, tree->nodes[node_index].co); + int found_prev = found; deduplicate_recursive(&p, tree->root); + if (found != found_prev) { + /* Prevent chains of doubles. */ + duplicates[index] = index; + } } } } diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index b89647d5b9b..9425931133a 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -2763,9 +2763,11 @@ bool isect_ray_aabb_v3( return true; } -/* - * Test a bounding box (AABB) for ray intersection - * assumes the ray is already local to the boundbox space +/** + * Test a bounding box (AABB) for ray intersection. + * Assumes the ray is already local to the boundbox space. + * + * \note: \a direction should be normalized if you intend to use the \a tmin or \a tmax distance results! */ bool isect_ray_aabb_v3_simple( const float orig[3], const float dir[3], @@ -2774,19 +2776,25 @@ bool isect_ray_aabb_v3_simple( { double t[7]; float hit_dist[2]; - t[1] = (double)(bb_min[0] - orig[0]) / dir[0]; - t[2] = (double)(bb_max[0] - orig[0]) / dir[0]; - t[3] = (double)(bb_min[1] - orig[1]) / dir[1]; - t[4] = (double)(bb_max[1] - orig[1]) / dir[1]; - t[5] = (double)(bb_min[2] - orig[2]) / dir[2]; - t[6] = (double)(bb_max[2] - orig[2]) / dir[2]; + const double invdirx = (dir[0] > 1e-35f || dir[0] < -1e-35f) ? 1.0 / (double)dir[0] : DBL_MAX; + const double invdiry = (dir[1] > 1e-35f || dir[1] < -1e-35f) ? 1.0 / (double)dir[1] : DBL_MAX; + const double invdirz = (dir[2] > 1e-35f || dir[2] < -1e-35f) ? 1.0 / (double)dir[2] : DBL_MAX; + t[1] = (double)(bb_min[0] - orig[0]) * invdirx; + t[2] = (double)(bb_max[0] - orig[0]) * invdirx; + t[3] = (double)(bb_min[1] - orig[1]) * invdiry; + t[4] = (double)(bb_max[1] - orig[1]) * invdiry; + t[5] = (double)(bb_min[2] - orig[2]) * invdirz; + t[6] = (double)(bb_max[2] - orig[2]) * invdirz; hit_dist[0] = (float)fmax(fmax(fmin(t[1], t[2]), fmin(t[3], t[4])), fmin(t[5], t[6])); hit_dist[1] = (float)fmin(fmin(fmax(t[1], t[2]), fmax(t[3], t[4])), fmax(t[5], t[6])); - if ((hit_dist[1] < 0 || hit_dist[0] > hit_dist[1])) + if ((hit_dist[1] < 0.0f || hit_dist[0] > hit_dist[1])) { return false; + } else { - if (tmin) *tmin = hit_dist[0]; - if (tmax) *tmax = hit_dist[1]; + if (tmin) + *tmin = hit_dist[0]; + if (tmax) + *tmax = hit_dist[1]; return true; } } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 5ddba2aa282..91abcdf7a89 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5561,7 +5561,6 @@ static void direct_link_object(FileData *fd, Object *ob) ob->derivedDeform = NULL; ob->derivedFinal = NULL; BKE_object_runtime_reset(ob); - BLI_listbase_clear(&ob->gpulamp); link_list(fd, &ob->pc_ids); /* Runtime curve data */ diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index 973591c49da..4b628bf816a 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -545,20 +545,6 @@ static void do_version_constraints_radians_degrees_250(ListBase *lb) } } -/* NOTE: this version patch is intended for versions < 2.52.2, but was initially introduced in 2.27 already */ -static void do_versions_seq_unique_name_all_strips(Scene *sce, ListBase *seqbasep) -{ - Sequence * seq = seqbasep->first; - - while (seq) { - BKE_sequence_base_unique_name_recursive(&sce->ed->seqbase, seq); - if (seq->seqbase.first) { - do_versions_seq_unique_name_all_strips(sce, &seq->seqbase); - } - seq = seq->next; - } -} - static void do_version_bone_roll_256(Bone *bone) { Bone *child; @@ -1029,10 +1015,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain) if (sce->r.frame_step == 0) sce->r.frame_step = 1; - if (sce->ed && sce->ed->seqbase.first) { - do_versions_seq_unique_name_all_strips(sce, &sce->ed->seqbase); - } - sce = sce->id.next; } } diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 487e0e8b9ec..d10e9ff294a 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -70,6 +70,7 @@ #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" +#include "BKE_sequencer.h" #include "BKE_studiolight.h" #include "BKE_workspace.h" @@ -486,27 +487,15 @@ static void do_version_layers_to_collections(Main *bmain, Scene *scene) nlc->flag |= LAYER_COLLECTION_EXCLUDE; } } - else if ((scene->lay & srl->lay & ~(srl->lay_exclude) & (1 << layer)) || - (srl->lay_zmask & (scene->lay | srl->lay_exclude) & (1 << layer))) - { + else { if (srl->lay_zmask & (1 << layer)) { have_override = true; - - BKE_override_layer_collection_boolean_add( - lc, - ID_OB, - "cycles.is_holdout", - true); + lc->flag |= LAYER_COLLECTION_HOLDOUT; } if ((srl->lay & (1 << layer)) == 0) { have_override = true; - - BKE_override_layer_collection_boolean_add( - lc, - ID_OB, - "cycles_visibility.camera", - false); + lc->flag |= LAYER_COLLECTION_INDIRECT_ONLY; } } } @@ -753,6 +742,18 @@ void do_versions_after_linking_280(Main *bmain) #endif } +/* NOTE: this version patch is intended for versions < 2.52.2, but was initially introduced in 2.27 already. + * But in 2.79 another case generating non-unique names was discovered (see T55668, involving Meta strips)... */ +static void do_versions_seq_unique_name_all_strips(Scene *sce, ListBase *seqbasep) +{ + for (Sequence *seq = seqbasep->first; seq != NULL; seq = seq->next) { + BKE_sequence_base_unique_name_recursive(&sce->ed->seqbase, seq); + if (seq->seqbase.first != NULL) { + do_versions_seq_unique_name_all_strips(sce, &seq->seqbase); + } + } +} + void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) { bool use_collection_compat_28 = true; @@ -1200,7 +1201,6 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) scene->eevee.flag = SCE_EEVEE_VOLUMETRIC_LIGHTS | - SCE_EEVEE_VOLUMETRIC_COLORED | SCE_EEVEE_GTAO_BENT_NORMALS | SCE_EEVEE_GTAO_BOUNCE | SCE_EEVEE_TAA_REPROJECTION | @@ -1258,7 +1258,6 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) EEVEE_GET_BOOL(props, volumetric_enable, SCE_EEVEE_VOLUMETRIC_ENABLED); EEVEE_GET_BOOL(props, volumetric_lights, SCE_EEVEE_VOLUMETRIC_LIGHTS); EEVEE_GET_BOOL(props, volumetric_shadows, SCE_EEVEE_VOLUMETRIC_SHADOWS); - EEVEE_GET_BOOL(props, volumetric_colored_transmittance, SCE_EEVEE_VOLUMETRIC_COLORED); EEVEE_GET_BOOL(props, gtao_enable, SCE_EEVEE_GTAO_ENABLED); EEVEE_GET_BOOL(props, gtao_use_bent_normals, SCE_EEVEE_GTAO_BENT_NORMALS); EEVEE_GET_BOOL(props, gtao_bounce, SCE_EEVEE_GTAO_BOUNCE); @@ -1525,7 +1524,13 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } - { + if (!MAIN_VERSION_ATLEAST(bmain, 280, 21)) { + for (Scene *sce = bmain->scene.first; sce != NULL; sce = sce->id.next) { + if (sce->ed != NULL && sce->ed->seqbase.first != NULL) { + do_versions_seq_unique_name_all_strips(sce, &sce->ed->seqbase); + } + } + if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "float", "texture_paint_mode_opacity")) { for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) { for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { @@ -1542,6 +1547,20 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } + if (!DNA_struct_elem_find(fd->filesdna, "View3DShadeing", "short", "background_type")) { + for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) { + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_VIEW3D) { + View3D *v3d = (View3D *)sl; + v3d->shading.background_type = (v3d->flag3 & V3D_SHOW_WORLD)? V3D_SHADING_BACKGROUND_WORLD: V3D_SHADING_BACKGROUND_THEME; + copy_v3_fl(v3d->shading.background_color, 0.05f); + } + } + } + } + } + if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "float", "gi_cubemap_draw_size")) { for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) { scene->eevee.gi_irradiance_draw_size = 0.1f; @@ -1645,4 +1664,5 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 24ac0737e27..ce2362dacc8 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1147,7 +1147,7 @@ static void write_nodetree_nolib(WriteData *wd, bNodeTree *ntree) */ static void current_screen_compat( Main *mainvar, bool use_active_win, - bScreen **r_screen, Scene **r_scene, ViewLayer **r_render_layer) + bScreen **r_screen, Scene **r_scene, ViewLayer **r_view_layer) { wmWindowManager *wm; wmWindow *window = NULL; @@ -1177,7 +1177,7 @@ static void current_screen_compat( *r_screen = (window) ? BKE_workspace_active_screen_get(window->workspace_hook) : NULL; *r_scene = (window) ? window->scene : NULL; - *r_render_layer = (window && *r_scene) ? BKE_view_layer_find(*r_scene, window->view_layer_name) : NULL; + *r_view_layer = (window && *r_scene) ? BKE_view_layer_find(*r_scene, window->view_layer_name) : NULL; } typedef struct RenderInfo { @@ -1193,11 +1193,11 @@ static void write_renderinfo(WriteData *wd, Main *mainvar) { bScreen *curscreen; Scene *sce, *curscene = NULL; - ViewLayer *render_layer; + ViewLayer *view_layer; RenderInfo data; /* XXX in future, handle multiple windows with multiple screens? */ - current_screen_compat(mainvar, false, &curscreen, &curscene, &render_layer); + current_screen_compat(mainvar, false, &curscreen, &curscene, &view_layer); for (sce = mainvar->scene.first; sce; sce = sce->id.next) { if (sce->id.lib == NULL && (sce == curscene || (sce->r.scemode & R_BG_RENDER))) { @@ -3688,7 +3688,7 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar) FileGlobal fg; bScreen *screen; Scene *scene; - ViewLayer *render_layer; + ViewLayer *view_layer; char subvstr[8]; /* prevent mem checkers from complaining */ @@ -3697,12 +3697,12 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar) memset(fg.build_hash, 0, sizeof(fg.build_hash)); fg.pad1 = NULL; - current_screen_compat(mainvar, is_undo, &screen, &scene, &render_layer); + current_screen_compat(mainvar, is_undo, &screen, &scene, &view_layer); /* XXX still remap G */ fg.curscreen = screen; fg.curscene = scene; - fg.cur_view_layer = render_layer; + fg.cur_view_layer = view_layer; /* prevent to save this, is not good convention, and feature with concerns... */ fg.fileflags = (fileflags & ~G_FILE_FLAGS_RUNTIME); diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc index 4cbc7700947..8f5925a5ce3 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder.cc @@ -67,6 +67,12 @@ void deg_graph_build_finalize(Main *bmain, Depsgraph *graph) } if (!deg_copy_on_write_is_expanded(id_node->id_cow)) { flag |= DEG_TAG_COPY_ON_WRITE; + /* This means ID is being added to the dependency graph first + * time, which is similar to "ob-visible-change" + */ + if (GS(id->name) == ID_OB) { + flag |= OB_RECALC_OB | OB_RECALC_DATA; + } } if (flag != 0) { DEG_graph_id_tag_update(bmain, diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c index 96e784b524c..636e532555f 100644 --- a/source/blender/draw/engines/eevee/eevee_data.c +++ b/source/blender/draw/engines/eevee/eevee_data.c @@ -30,7 +30,7 @@ #include "eevee_private.h" #include "eevee_lightcache.h" -static void eevee_view_layer_data_free(void *storage) +void EEVEE_view_layer_data_free(void *storage) { EEVEE_ViewLayerData *sldata = (EEVEE_ViewLayerData *)storage; @@ -77,7 +77,7 @@ EEVEE_ViewLayerData *EEVEE_view_layer_data_get(void) EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure_ex(struct ViewLayer *view_layer) { EEVEE_ViewLayerData **sldata = (EEVEE_ViewLayerData **)DRW_view_layer_engine_data_ensure_ex( - view_layer, &draw_engine_eevee_type, &eevee_view_layer_data_free); + view_layer, &draw_engine_eevee_type, &EEVEE_view_layer_data_free); if (*sldata == NULL) { *sldata = MEM_callocN(sizeof(**sldata), "EEVEE_ViewLayerData"); @@ -89,7 +89,7 @@ EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure_ex(struct ViewLayer *view_laye EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure(void) { EEVEE_ViewLayerData **sldata = (EEVEE_ViewLayerData **)DRW_view_layer_engine_data_ensure( - &draw_engine_eevee_type, &eevee_view_layer_data_free); + &draw_engine_eevee_type, &EEVEE_view_layer_data_free); if (*sldata == NULL) { *sldata = MEM_callocN(sizeof(**sldata), "EEVEE_ViewLayerData"); diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c index 4f5ad5159cf..b0b66ee50dc 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.c +++ b/source/blender/draw/engines/eevee/eevee_lightcache.c @@ -93,6 +93,7 @@ typedef struct EEVEE_LightBake { LightCache *lcache; Scene *scene; struct Main *bmain; + EEVEE_ViewLayerData *sldata; LightProbe **probe; /* Current probe being rendered. */ GPUTexture *rt_color; /* Target cube color texture. */ @@ -597,6 +598,12 @@ static void eevee_lightbake_delete_resources(EEVEE_LightBake *lbake) lbake->lcache = NULL; } + /* XXX Free the resources contained in the viewlayer data + * to be able to free the context before deleting the depsgraph. */ + if (lbake->sldata) { + EEVEE_view_layer_data_free(lbake->sldata); + } + DRW_TEXTURE_FREE_SAFE(lbake->rt_depth); DRW_TEXTURE_FREE_SAFE(lbake->rt_color); DRW_TEXTURE_FREE_SAFE(lbake->grid_prev); @@ -633,6 +640,8 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); Scene *scene_eval = DEG_get_evaluated_scene(lbake->depsgraph); + lbake->sldata = sldata; + /* Disable all effects BUT high bitdepth shadows. */ scene_eval->eevee.flag &= SCE_EEVEE_SHADOW_HIGH_BITDEPTH; scene_eval->eevee.taa_samples = 1; diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 5aa331a9b99..349a27a1765 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -777,6 +777,7 @@ typedef struct EEVEE_PrivateData { } EEVEE_PrivateData; /* Transient data */ /* eevee_data.c */ +void EEVEE_view_layer_data_free(void *sldata); EEVEE_ViewLayerData *EEVEE_view_layer_data_get(void); EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure_ex(struct ViewLayer *view_layer); EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure(void); diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c index 5c3ab5f6688..24eb0f38a46 100644 --- a/source/blender/draw/engines/workbench/workbench_data.c +++ b/source/blender/draw/engines/workbench/workbench_data.c @@ -45,10 +45,16 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd) wd->matcap_orientation = (wpd->shading.flag & V3D_SHADING_MATCAP_FLIP_X) != 0; wd->background_alpha = (v3d || scene->r.alphamode == R_ADDSKY) ? 1.0f : 0.0f; - if (!v3d || ((v3d->flag3 & V3D_SHOW_WORLD) && (scene->world != NULL))) { + if (!v3d || ((v3d->shading.background_type & V3D_SHADING_BACKGROUND_WORLD) && + (scene->world != NULL))) + { copy_v3_v3(wd->background_color_low, &scene->world->horr); copy_v3_v3(wd->background_color_high, &scene->world->horr); } + else if (v3d->shading.background_type & V3D_SHADING_BACKGROUND_VIEWPORT) { + copy_v3_v3(wd->background_color_low, v3d->shading.background_color); + copy_v3_v3(wd->background_color_high, v3d->shading.background_color); + } else if (v3d) { UI_GetThemeColor3fv(UI_GetThemeValue(TH_SHOW_BACK_GRAD) ? TH_LOW_GRAD : TH_HIGH_GRAD, wd->background_color_low); UI_GetThemeColor3fv(TH_HIGH_GRAD, wd->background_color_high); diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index 2bf55e6313d..4692b026d76 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -143,9 +143,12 @@ static char *workbench_build_prepass_frag(void) return str; } -static char *workbench_build_prepass_vert(void) +static char *workbench_build_prepass_vert(bool is_hair) { char *str = NULL; + if (!is_hair) { + return BLI_strdup(datatoc_workbench_prepass_vert_glsl); + } DynStr *ds = BLI_dynstr_new(); @@ -177,7 +180,7 @@ static void ensure_deferred_shaders(WORKBENCH_PrivateData *wpd, int index, bool if (e_data.prepass_sh_cache[index] == NULL) { char *defines = workbench_material_build_defines(wpd, use_textures, is_hair); char *composite_frag = workbench_build_composite_frag(wpd); - char *prepass_vert = workbench_build_prepass_vert(); + char *prepass_vert = workbench_build_prepass_vert(is_hair); char *prepass_frag = workbench_build_prepass_frag(); e_data.prepass_sh_cache[index] = DRW_shader_create( prepass_vert, NULL, diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index 6c9353cc132..e4a9c8abe26 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -81,9 +81,12 @@ extern char datatoc_workbench_common_lib_glsl[]; extern char datatoc_workbench_world_light_lib_glsl[]; /* static functions */ -static char *workbench_build_forward_vert(void) +static char *workbench_build_forward_vert(bool is_hair) { char *str = NULL; + if (!is_hair) { + return BLI_strdup(datatoc_workbench_prepass_vert_glsl); + } DynStr *ds = BLI_dynstr_new(); @@ -211,7 +214,7 @@ static void ensure_forward_shaders(WORKBENCH_PrivateData *wpd, int index, bool u if (e_data.transparent_accum_sh_cache[index] == NULL) { char *defines = workbench_material_build_defines(wpd, use_textures, is_hair); - char *transparent_accum_vert = workbench_build_forward_vert(); + char *transparent_accum_vert = workbench_build_forward_vert(is_hair); char *transparent_accum_frag = workbench_build_forward_transparent_accum_frag(); e_data.transparent_accum_sh_cache[index] = DRW_shader_create( transparent_accum_vert, NULL, @@ -272,7 +275,8 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) char *defines = workbench_material_build_defines(wpd, false, false); char *defines_texture = workbench_material_build_defines(wpd, true, false); char *defines_hair = workbench_material_build_defines(wpd, false, true); - char *forward_vert = workbench_build_forward_vert(); + char *forward_vert = workbench_build_forward_vert(false); + char *forward_hair_vert = workbench_build_forward_vert(true); e_data.object_outline_sh = DRW_shader_create( forward_vert, NULL, datatoc_workbench_forward_depth_frag_glsl, defines); @@ -280,12 +284,13 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) forward_vert, NULL, datatoc_workbench_forward_depth_frag_glsl, defines_texture); e_data.object_outline_hair_sh = DRW_shader_create( - forward_vert, NULL, + forward_hair_vert, NULL, datatoc_workbench_forward_depth_frag_glsl, defines_hair); e_data.checker_depth_sh = DRW_shader_create_fullscreen( datatoc_workbench_checkerboard_depth_frag_glsl, NULL); + MEM_freeN(forward_hair_vert); MEM_freeN(forward_vert); MEM_freeN(defines); MEM_freeN(defines_texture); diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c index b0aec4a7600..b85e6267687 100644 --- a/source/blender/draw/intern/draw_manager_shader.c +++ b/source/blender/draw/intern/draw_manager_shader.c @@ -72,6 +72,7 @@ typedef struct DRWShaderCompiler { ThreadMutex compilation_lock; void *gl_context; + bool own_context; int shaders_done; /* To compute progress. */ } DRWShaderCompiler; @@ -146,7 +147,7 @@ static void drw_deferred_shader_compilation_free(void *custom_data) BLI_spin_end(&comp->list_lock); BLI_mutex_end(&comp->compilation_lock); - if (comp->gl_context) { + if (comp->own_context) { /* Only destroy if the job owns the context. */ WM_opengl_context_dispose(comp->gl_context); } @@ -189,8 +190,11 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred) BLI_movelisttolist(&comp->queue, &old_comp->queue); BLI_spin_unlock(&old_comp->list_lock); /* Do not recreate context, just pass ownership. */ - comp->gl_context = old_comp->gl_context; - old_comp->gl_context = NULL; + if (old_comp->gl_context) { + comp->gl_context = old_comp->gl_context; + old_comp->own_context = false; + comp->own_context = true; + } } BLI_addtail(&comp->queue, dsh); @@ -199,6 +203,7 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred) if (comp->gl_context == NULL) { comp->gl_context = WM_opengl_context_create(); WM_opengl_context_activate(DST.gl_context); + comp->own_context = true; } WM_jobs_customdata_set(wm_job, comp, drw_deferred_shader_compilation_free); diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c index 05aecea1d7a..95835a691a3 100644 --- a/source/blender/draw/intern/draw_view.c +++ b/source/blender/draw/intern/draw_view.c @@ -561,21 +561,12 @@ void DRW_draw_grid(void) void DRW_draw_background(void) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - /* Just to make sure */ glDepthMask(GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glStencilMask(0xFF); - if ((draw_ctx->v3d->flag3 & V3D_SHOW_WORLD) && - (draw_ctx->scene->world != NULL)) - { - const World *world = draw_ctx->scene->world; - glClearColor(world->horr, world->horg, world->horb, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - } - else if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) { + if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) { float m[4][4]; unit_m4(m); diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c index a9ba8c405ba..3ae578279ca 100644 --- a/source/blender/editors/armature/pose_edit.c +++ b/source/blender/editors/armature/pose_edit.c @@ -287,7 +287,8 @@ void POSE_OT_paths_calculate(wmOperatorType *ot) RNA_def_int(ot->srna, "end_frame", 250, MINAFRAME, MAXFRAME, "End", "Last frame to calculate bone paths on", MINFRAME, MAXFRAME / 2.0); - RNA_def_enum(ot->srna, "bake_location", rna_enum_motionpath_bake_location_items, 0, + RNA_def_enum(ot->srna, "bake_location", rna_enum_motionpath_bake_location_items, + MOTIONPATH_BAKE_HEADS, "Bake Location", "Which point on the bones is used when calculating paths"); } diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index ccdbcba71f9..79bfc5149ba 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -1382,8 +1382,9 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static bool gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop) +static bool gp_convert_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop) { + PointerRNA *ptr = op->ptr; const char *prop_id = RNA_property_identifier(prop); const bool link_strokes = RNA_boolean_get(ptr, "use_link_strokes"); int timing_mode = RNA_enum_get(ptr, "timing_mode"); @@ -1446,18 +1447,6 @@ static bool gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop) return false; } -static void gp_convert_ui(bContext *C, wmOperator *op) -{ - uiLayout *layout = op->layout; - wmWindowManager *wm = CTX_wm_manager(C); - PointerRNA ptr; - - RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); - - /* Main auto-draw call */ - uiDefAutoButsRNA(layout, &ptr, gp_convert_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false); -} - void GPENCIL_OT_convert(wmOperatorType *ot) { PropertyRNA *prop; @@ -1471,7 +1460,7 @@ void GPENCIL_OT_convert(wmOperatorType *ot) ot->invoke = WM_menu_invoke; ot->exec = gp_convert_layer_exec; ot->poll = gp_convert_poll; - ot->ui = gp_convert_ui; + ot->poll_property = gp_convert_poll_property; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 38545137740..9fd5cc99073 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -112,6 +112,7 @@ void ED_keymap_proportional_obmode(struct wmKeyConfig *keyconf, struct wmKeyMap void ED_keymap_proportional_maskmode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap); void ED_keymap_proportional_editmode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap, const bool do_connected); +void ED_keymap_editmesh_elem_mode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap); void ED_object_base_select(struct Base *base, eObjectSelect_Mode mode); void ED_object_base_activate(struct bContext *C, struct Base *base); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 087e0c4ab7b..b4756eaed0f 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -772,7 +772,7 @@ typedef enum { uiBut *uiDefAutoButR(uiBlock *block, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, const char *name, int icon, int x1, int y1, int x2, int y2); eAutoPropButsReturn uiDefAutoButsRNA( uiLayout *layout, struct PointerRNA *ptr, - bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *), + bool (*check_prop)(struct PointerRNA *ptr, struct PropertyRNA *prop, void *user_data), void *user_data, eButLabelAlign label_align, const bool compact); /* use inside searchfunc to add items */ @@ -935,6 +935,7 @@ enum { UI_TEMPLATE_OP_PROPS_SHOW_TITLE = (1 << 0), UI_TEMPLATE_OP_PROPS_SHOW_EMPTY = (1 << 1), UI_TEMPLATE_OP_PROPS_COMPACT = (1 << 2), + UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED = (1 << 3), }; /* used for transp checkers */ @@ -1085,7 +1086,6 @@ void UI_but_func_operator_search(uiBut *but); void uiTemplateOperatorSearch(uiLayout *layout); eAutoPropButsReturn uiTemplateOperatorPropertyButs( const struct bContext *C, uiLayout *layout, struct wmOperator *op, - bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *), const eButLabelAlign label_align, const short flag); void uiTemplateHeader3D_mode(uiLayout *layout, struct bContext *C); void uiTemplateHeader3D(uiLayout *layout, struct bContext *C); diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index 651081c46bb..a34c4938b86 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -59,7 +59,7 @@ typedef struct IconFile { /* * Resizable Icons for Blender */ -void UI_icons_init(int first_dyn_id); +void UI_icons_init(void); int UI_icon_get_width(int icon_id); int UI_icon_get_height(int icon_id); diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 22b82898288..7255640bedc 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -934,9 +934,8 @@ int UI_icon_get_height(int icon_id) return 0; } -void UI_icons_init(int first_dyn_id) +void UI_icons_init() { - BKE_icons_init(first_dyn_id); #ifndef WITH_HEADLESS init_iconfile_list(&iconfilelist); init_internal_icons(); diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 59fdf7e672d..aa67d58fd57 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -454,9 +454,9 @@ static void ui_offset_panel_block(uiBlock *block) /* triangle 'icon' for panel header */ void UI_draw_icon_tri(float x, float y, char dir, const float color[4]) { - float f3 = 0.15 * U.widget_unit; - float f5 = 0.25 * U.widget_unit; - float f7 = 0.35 * U.widget_unit; + float f3 = 0.05 * U.widget_unit; + float f5 = 0.15 * U.widget_unit; + float f7 = 0.25 * U.widget_unit; if (dir == 'h') { UI_draw_anti_tria(x - f3, y - f5, x - f3, y + f5, x + f7, y, color); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 2dcc18af4ea..131ffbca377 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1542,11 +1542,6 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr) /************************ Redo Buttons Template *************************/ -static bool template_operator_redo_property_buts_poll(PointerRNA *UNUSED(ptr), PropertyRNA *prop) -{ - return (RNA_property_tags(prop) & OP_PROP_TAG_ADVANCED) == 0; -} - static void template_operator_redo_property_buts_draw( const bContext *C, wmOperator *op, uiLayout *layout, int layout_flags, @@ -1560,8 +1555,9 @@ static void template_operator_redo_property_buts_draw( else { /* Might want to make label_align adjustable somehow. */ eAutoPropButsReturn return_info = uiTemplateOperatorPropertyButs( - C, layout, op, r_has_advanced ? template_operator_redo_property_buts_poll : NULL, - UI_BUT_LABEL_ALIGN_NONE, layout_flags); + C, layout, op, + UI_BUT_LABEL_ALIGN_NONE, + layout_flags); if (return_info & UI_PROP_BUTS_ANY_FAILED_CHECK) { if (r_has_advanced) { *r_has_advanced = true; @@ -3948,13 +3944,30 @@ static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C), void *op_pt, } #endif +struct uiTemplateOperatorPropertyPollParam { + const bContext *C; + wmOperator *op; + short flag; +}; + +static bool ui_layout_operator_buts_poll_property( + struct PointerRNA *UNUSED(ptr), struct PropertyRNA *prop, void *user_data) +{ + struct uiTemplateOperatorPropertyPollParam *params = user_data; + if ((params->flag & UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED) && + (RNA_property_tags(prop) & OP_PROP_TAG_ADVANCED)) + { + return false; + } + return params->op->type->poll_property(params->C, params->op, prop); +} + /** * Draw Operator property buttons for redoing execution with different settings. * This function does not initialize the layout, functions can be called on the layout before and after. */ eAutoPropButsReturn uiTemplateOperatorPropertyButs( const bContext *C, uiLayout *layout, wmOperator *op, - bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *), const eButLabelAlign label_align, const short flag) { uiBlock *block = uiLayoutGetBlock(layout); @@ -4013,13 +4026,32 @@ eAutoPropButsReturn uiTemplateOperatorPropertyButs( else { wmWindowManager *wm = CTX_wm_manager(C); PointerRNA ptr; + struct uiTemplateOperatorPropertyPollParam user_data = {.C = C, .op = op, .flag = flag}; + + + +#if 0 +static bool template_operator_redo_property_buts_poll(PointerRNA *UNUSED(ptr), PropertyRNA *prop) +{ +} +#endif + + + + + + RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); uiLayoutSetPropSep(layout, true); /* main draw call */ - return_info = uiDefAutoButsRNA(layout, &ptr, check_prop, label_align, (flag & UI_TEMPLATE_OP_PROPS_COMPACT)); + return_info = uiDefAutoButsRNA( + layout, &ptr, + op->type->poll_property ? ui_layout_operator_buts_poll_property : NULL, + op->type->poll_property ? &user_data : NULL, + label_align, (flag & UI_TEMPLATE_OP_PROPS_COMPACT)); if ((return_info & UI_PROP_BUTS_NONE_ADDED) && (flag & UI_TEMPLATE_OP_PROPS_SHOW_EMPTY)) { uiItemL(layout, IFACE_("No Properties"), ICON_NONE); diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index d080397c488..60aa79e1093 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -159,7 +159,7 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind */ eAutoPropButsReturn uiDefAutoButsRNA( uiLayout *layout, PointerRNA *ptr, - bool (*check_prop)(PointerRNA *, PropertyRNA *), + bool (*check_prop)(PointerRNA *ptr, PropertyRNA *prop, void *user_data), void *user_data, const eButLabelAlign label_align, const bool compact) { eAutoPropButsReturn return_info = UI_PROP_BUTS_NONE_ADDED; @@ -174,7 +174,7 @@ eAutoPropButsReturn uiDefAutoButsRNA( if (flag & PROP_HIDDEN) { continue; } - if (check_prop && check_prop(ptr, prop) == 0) { + if (check_prop && check_prop(ptr, prop, user_data) == 0) { return_info |= UI_PROP_BUTS_ANY_FAILED_CHECK; continue; } diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 47d664eaeb2..3cb8a277e9a 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -83,7 +83,7 @@ static struct bThemeState g_theme_state = { void ui_resources_init(void) { - UI_icons_init(BIFICONID_LAST); + UI_icons_init(); } void ui_resources_free(void) diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 99756269c1f..61f55451b17 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -1048,14 +1048,15 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void GPU_matrix_push(); GPU_matrix_mul(kcd->ob->obmat); + if (kcd->mode == MODE_DRAGGING && kcd->is_angle_snapping) { + knifetool_draw_angle_snapping(kcd); + } + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); if (kcd->mode == MODE_DRAGGING) { - if (kcd->is_angle_snapping) - knifetool_draw_angle_snapping(kcd); - immUniformColor3ubv(kcd->colors.line); GPU_line_width(2.0); diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 2e7cf1fc76f..cdb8981801a 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -1462,6 +1462,18 @@ static int edbm_select_mode_exec(bContext *C, wmOperator *op) static int edbm_select_mode_invoke(bContext *C, wmOperator *op, const wmEvent *event) { + /* Bypass when in UV non sync-select mode, fall through to keymap that edits. */ + if (CTX_wm_space_image(C)) { + ToolSettings *ts = CTX_data_tool_settings(C); + if ((ts->uv_flag & UV_SYNC_SELECTION) == 0) { + return OPERATOR_PASS_THROUGH; + } + /* Bypass when no action is needed. */ + if (!RNA_struct_property_is_set(op->ptr, "type")) { + return OPERATOR_CANCELLED; + } + } + /* detecting these options based on shift/ctrl here is weak, but it's done * to make this work when clicking buttons or menus */ if (!RNA_struct_property_is_set(op->ptr, "use_extend")) diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index d7617a14ff3..b2a2291f4f6 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -6001,10 +6001,10 @@ static int edbm_sort_elements_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static bool edbm_sort_elements_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop) +static bool edbm_sort_elements_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop) { const char *prop_id = RNA_property_identifier(prop); - const int action = RNA_enum_get(ptr, "type"); + const int action = RNA_enum_get(op->ptr, "type"); /* Only show seed for randomize action! */ if (STREQ(prop_id, "seed")) { @@ -6025,18 +6025,6 @@ static bool edbm_sort_elements_draw_check_prop(PointerRNA *ptr, PropertyRNA *pro return true; } -static void edbm_sort_elements_ui(bContext *C, wmOperator *op) -{ - uiLayout *layout = op->layout; - wmWindowManager *wm = CTX_wm_manager(C); - PointerRNA ptr; - - RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); - - /* Main auto-draw call. */ - uiDefAutoButsRNA(layout, &ptr, edbm_sort_elements_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false); -} - void MESH_OT_sort_elements(wmOperatorType *ot) { static const EnumPropertyItem type_items[] = { @@ -6072,7 +6060,7 @@ void MESH_OT_sort_elements(wmOperatorType *ot) ot->invoke = WM_menu_invoke; ot->exec = edbm_sort_elements_exec; ot->poll = ED_operator_editmesh; - ot->ui = edbm_sort_elements_ui; + ot->poll_property = edbm_sort_elements_poll_property; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 0fcc5ada854..79c8f5c0b09 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -335,22 +335,8 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "MESH_OT_bevel", BKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "vertex_only", true); - /* selecting */ - for (int i = 0; i < 4; i++) { - const bool is_extend = (i & 1); - const bool is_expand = (i & 2); - const int key_modifier = (is_extend ? KM_SHIFT : 0) | (is_expand ? KM_CTRL : 0); - for (int j = 0; j < 3; j++) { - kmi = WM_keymap_add_item(keymap, "MESH_OT_select_mode", ONEKEY + j, KM_PRESS, key_modifier, 0); - RNA_enum_set(kmi->ptr, "type", SCE_SELECT_VERTEX << j); - if (is_extend) { - RNA_boolean_set(kmi->ptr, "use_extend", true); - } - if (is_expand) { - RNA_boolean_set(kmi->ptr, "use_expand", true); - } - } - } + /* Selec Vert/Edge/Face. */ + ED_keymap_editmesh_elem_mode(keyconf, keymap); /* standard mouse selection goes via space_view3d */ kmi = WM_keymap_add_item(keymap, "MESH_OT_loop_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0); diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index b456342f8f0..1d93d664a5a 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -49,6 +49,7 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_image.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_material.h" @@ -360,17 +361,24 @@ static bool is_noncolor_pass(eScenePassType pass_type) } /* if all is good tag image and return true */ -static bool bake_object_check(Scene *scene, Object *ob, ReportList *reports) +static bool bake_object_check(ViewLayer *view_layer, Object *ob, ReportList *reports) { Image *image; + Base *base = BKE_view_layer_base_find(view_layer, ob); void *lock; int i; - if ((ob->lay & scene->lay) == 0) { - BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not on a scene layer", ob->id.name + 2); + if (base == NULL) { + BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not in view layer", ob->id.name + 2); return false; } + if (!(base->flag & BASE_ENABLED_RENDER)) { + BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not enabled for rendering", ob->id.name + 2); + return false; + } + + if (ob->type != OB_MESH) { BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not a mesh", ob->id.name + 2); return false; @@ -500,7 +508,7 @@ static bool bake_pass_filter_check(eScenePassType pass_type, const int pass_filt } /* before even getting in the bake function we check for some basic errors */ -static bool bake_objects_check(Main *bmain, Scene *scene, Object *ob, ListBase *selected_objects, +static bool bake_objects_check(Main *bmain, ViewLayer *view_layer, Object *ob, ListBase *selected_objects, ReportList *reports, const bool is_selected_to_active) { CollectionPointerLink *link; @@ -511,7 +519,7 @@ static bool bake_objects_check(Main *bmain, Scene *scene, Object *ob, ListBase * if (is_selected_to_active) { int tot_objects = 0; - if (!bake_object_check(scene, ob, reports)) + if (!bake_object_check(view_layer, ob, reports)) return false; for (link = selected_objects->first; link; link = link->next) { @@ -539,7 +547,7 @@ static bool bake_objects_check(Main *bmain, Scene *scene, Object *ob, ListBase * } for (link = selected_objects->first; link; link = link->next) { - if (!bake_object_check(scene, link->ptr.data, reports)) + if (!bake_object_check(view_layer, link->ptr.data, reports)) return false; } } @@ -1207,7 +1215,7 @@ static int bake_exec(bContext *C, wmOperator *op) goto finally; } - if (!bake_objects_check(bkr.main, bkr.scene, bkr.ob, &bkr.selected_objects, bkr.reports, bkr.is_selected_to_active)) { + if (!bake_objects_check(bkr.main, bkr.view_layer, bkr.ob, &bkr.selected_objects, bkr.reports, bkr.is_selected_to_active)) { goto finally; } @@ -1266,7 +1274,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa return; } - if (!bake_objects_check(bkr->main, bkr->scene, bkr->ob, &bkr->selected_objects, bkr->reports, bkr->is_selected_to_active)) { + if (!bake_objects_check(bkr->main, bkr->view_layer, bkr->ob, &bkr->selected_objects, bkr->reports, bkr->is_selected_to_active)) { bkr->result = OPERATOR_CANCELLED; return; } diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index f56fd560946..ad0b091ede9 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -450,8 +450,9 @@ static bool data_transfer_poll(bContext *C) } /* Used by both OBJECT_OT_data_transfer and OBJECT_OT_datalayout_transfer */ -static bool data_transfer_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop) +static bool data_transfer_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop) { + PointerRNA *ptr = op->ptr; PropertyRNA *prop_other; const char *prop_id = RNA_property_identifier(prop); @@ -512,19 +513,6 @@ static bool data_transfer_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop) return true; } -/* Used by both OBJECT_OT_data_transfer and OBJECT_OT_datalayout_transfer */ -static void data_transfer_ui(bContext *C, wmOperator *op) -{ - uiLayout *layout = op->layout; - wmWindowManager *wm = CTX_wm_manager(C); - PointerRNA ptr; - - RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); - - /* Main auto-draw call */ - uiDefAutoButsRNA(layout, &ptr, data_transfer_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false); -} - /* transfers weight from active to selected */ void OBJECT_OT_data_transfer(wmOperatorType *ot) { @@ -537,10 +525,10 @@ void OBJECT_OT_data_transfer(wmOperatorType *ot) /* API callbacks.*/ ot->poll = data_transfer_poll; + ot->poll_property = data_transfer_poll_property; ot->invoke = WM_menu_invoke; ot->exec = data_transfer_exec; ot->check = data_transfer_check; - ot->ui = data_transfer_ui; /* Flags.*/ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -700,10 +688,10 @@ void OBJECT_OT_datalayout_transfer(wmOperatorType *ot) ot->idname = "OBJECT_OT_datalayout_transfer"; ot->poll = datalayout_transfer_poll; + ot->poll_property = data_transfer_poll_property; ot->invoke = datalayout_transfer_invoke; ot->exec = datalayout_transfer_exec; ot->check = data_transfer_check; - ot->ui = data_transfer_ui; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c index 53cabe3759e..72c5fde2955 100644 --- a/source/blender/editors/object/object_group.c +++ b/source/blender/editors/object/object_group.c @@ -411,6 +411,9 @@ static int collection_add_exec(bContext *C, wmOperator *UNUSED(op)) id_fake_user_set(&collection->id); BKE_collection_object_add(bmain, collection, ob); + DEG_id_tag_update(&collection->id, DEG_TAG_COPY_ON_WRITE); + DEG_relations_tag_update(bmain); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); return OPERATOR_FINISHED; @@ -460,6 +463,9 @@ static int collection_link_exec(bContext *C, wmOperator *op) BKE_collection_object_add(bmain, collection, ob); + DEG_id_tag_update(&collection->id, DEG_TAG_COPY_ON_WRITE); + DEG_relations_tag_update(bmain); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); return OPERATOR_FINISHED; @@ -500,6 +506,9 @@ static int collection_remove_exec(bContext *C, wmOperator *UNUSED(op)) BKE_collection_object_remove(bmain, collection, ob, false); + DEG_id_tag_update(&collection->id, DEG_TAG_COPY_ON_WRITE); + DEG_relations_tag_update(bmain); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); return OPERATOR_FINISHED; @@ -531,6 +540,8 @@ static int collection_unlink_exec(bContext *C, wmOperator *UNUSED(op)) BKE_libblock_delete(bmain, collection); + DEG_relations_tag_update(bmain); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); return OPERATOR_FINISHED; diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 5a83d085aee..7b6c1156874 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -40,6 +40,7 @@ #include "BKE_context.h" #include "RNA_access.h" +#include "RNA_enum_types.h" #include "WM_api.h" #include "WM_types.h" @@ -490,3 +491,26 @@ void ED_keymap_proportional_editmode(struct wmKeyConfig *UNUSED(keyconf), struct RNA_string_set(kmi->ptr, "value_2", "CONNECTED"); } } + +/** + * Map 1..3 to Vert/Edge/Face. + */ +void ED_keymap_editmesh_elem_mode(struct wmKeyConfig *UNUSED(keyconf), struct wmKeyMap *keymap) +{ + for (int i = 0; i < 4; i++) { + const bool is_extend = (i & 1); + const bool is_expand = (i & 2); + const int key_modifier = (is_extend ? KM_SHIFT : 0) | (is_expand ? KM_CTRL : 0); + for (int j = 0; j < 3; j++) { + wmKeyMapItem *kmi = WM_keymap_add_item( + keymap, "MESH_OT_select_mode", ONEKEY + j, KM_PRESS, key_modifier, 0); + RNA_enum_set(kmi->ptr, "type", SCE_SELECT_VERTEX << j); + if (is_extend) { + RNA_boolean_set(kmi->ptr, "use_extend", true); + } + if (is_expand) { + RNA_boolean_set(kmi->ptr, "use_expand", true); + } + } + } +} diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 2c3ff8b6afe..4745a484475 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -947,13 +947,13 @@ static int parent_set_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent return OPERATOR_INTERFACE; } -static bool parent_set_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop) +static bool parent_set_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop) { const char *prop_id = RNA_property_identifier(prop); - const int type = RNA_enum_get(ptr, "type"); /* Only show XMirror for PAR_ARMATURE_ENVELOPE and PAR_ARMATURE_AUTO! */ if (STREQ(prop_id, "xmirror")) { + const int type = RNA_enum_get(op->ptr, "type"); if (ELEM(type, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO)) return true; else @@ -963,18 +963,6 @@ static bool parent_set_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop) return true; } -static void parent_set_ui(bContext *C, wmOperator *op) -{ - uiLayout *layout = op->layout; - wmWindowManager *wm = CTX_wm_manager(C); - PointerRNA ptr; - - RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); - - /* Main auto-draw call. */ - uiDefAutoButsRNA(layout, &ptr, parent_set_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false); -} - void OBJECT_OT_parent_set(wmOperatorType *ot) { /* identifiers */ @@ -986,7 +974,7 @@ void OBJECT_OT_parent_set(wmOperatorType *ot) ot->invoke = parent_set_invoke; ot->exec = parent_set_exec; ot->poll = ED_operator_object_active; - ot->ui = parent_set_ui; + ot->poll_property = parent_set_poll_property; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -2329,6 +2317,7 @@ static int make_override_static_exec(bContext *C, wmOperator *op) if (new_ob != NULL && new_ob->id.override_static != NULL) { if ((base = BKE_view_layer_base_find(view_layer, new_ob)) == NULL) { BKE_collection_object_add_from(bmain, scene, obcollection, new_ob); + base = BKE_view_layer_base_find(view_layer, new_ob); DEG_id_tag_update_ex(bmain, &new_ob->id, DEG_TAG_TRANSFORM | DEG_TAG_BASE_FLAGS_UPDATE); } /* parent to 'collection' empty */ diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index afaad3963d5..9c0c59a7160 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -247,7 +247,7 @@ static void screenshot_cancel(bContext *UNUSED(C), wmOperator *op) screenshot_data_free(op); } -static bool screenshot_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop) +static bool screenshot_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop, void *UNUSED(user_data)) { const char *prop_id = RNA_property_identifier(prop); @@ -266,7 +266,7 @@ static void screenshot_draw(bContext *UNUSED(C), wmOperator *op) /* main draw call */ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); - uiDefAutoButsRNA(layout, &ptr, screenshot_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false); + uiDefAutoButsRNA(layout, &ptr, screenshot_draw_check_prop, NULL, UI_BUT_LABEL_ALIGN_NONE, false); } static bool screenshot_poll(bContext *C) diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index 3fc68a50057..15f688549a8 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -482,7 +482,7 @@ static int sound_mixdown_invoke(bContext *C, wmOperator *op, const wmEvent *even #ifdef WITH_AUDASPACE -static bool sound_mixdown_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop) +static bool sound_mixdown_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop, void *UNUSED(user_data)) { const char *prop_id = RNA_property_identifier(prop); return !(STREQ(prop_id, "filepath") || @@ -635,7 +635,7 @@ static void sound_mixdown_draw(bContext *C, wmOperator *op) RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); /* main draw call */ - uiDefAutoButsRNA(layout, &ptr, sound_mixdown_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false); + uiDefAutoButsRNA(layout, &ptr, sound_mixdown_draw_check_prop, NULL, UI_BUT_LABEL_ALIGN_NONE, false); } #endif // WITH_AUDASPACE diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c index 812a671ff33..abe9f173b09 100644 --- a/source/blender/editors/space_file/file_panels.c +++ b/source/blender/editors/space_file/file_panels.c @@ -43,6 +43,7 @@ #include "MEM_guardedalloc.h" #include "RNA_access.h" +#include "RNA_define.h" #include "ED_fileselect.h" @@ -71,25 +72,28 @@ static void file_panel_operator_header(const bContext *C, Panel *pa) BLI_strncpy(pa->drawname, RNA_struct_ui_name(op->type->srna), sizeof(pa->drawname)); } -static bool file_panel_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop) -{ - const char *prop_id = RNA_property_identifier(prop); - return !(STREQ(prop_id, "filepath") || - STREQ(prop_id, "directory") || - STREQ(prop_id, "filename") - ); -} - static void file_panel_operator(const bContext *C, Panel *pa) { SpaceFile *sfile = CTX_wm_space_file(C); wmOperator *op = sfile->op; - // int empty = 1, flag; UI_block_func_set(uiLayoutGetBlock(pa->layout), file_draw_check_cb, NULL, NULL); - uiTemplateOperatorPropertyButs(C, pa->layout, op, file_panel_check_prop, UI_BUT_LABEL_ALIGN_NONE, - UI_TEMPLATE_OP_PROPS_SHOW_EMPTY); + /* Hack: temporary hide.*/ + const char *hide[3] = {"filepath", "directory", "filename"}; + for (int i = 0; i < ARRAY_SIZE(hide); i++) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "filepath"); + RNA_def_property_flag(prop, PROP_HIDDEN); + } + + uiTemplateOperatorPropertyButs( + C, pa->layout, op, UI_BUT_LABEL_ALIGN_NONE, + UI_TEMPLATE_OP_PROPS_SHOW_EMPTY); + + for (int i = 0; i < ARRAY_SIZE(hide); i++) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "filepath"); + RNA_def_property_clear_flag(prop, PROP_HIDDEN); + } UI_block_func_set(uiLayoutGetBlock(pa->layout), NULL, NULL, NULL); } diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index f1012c46f2f..bcbfa1342d5 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1487,7 +1487,7 @@ static int image_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED( return OPERATOR_RUNNING_MODAL; } -static bool image_open_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop) +static bool image_open_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop, void *UNUSED(user_data)) { const char *prop_id = RNA_property_identifier(prop); @@ -1506,7 +1506,7 @@ static void image_open_draw(bContext *UNUSED(C), wmOperator *op) /* main draw call */ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); - uiDefAutoButsRNA(layout, &ptr, image_open_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false); + uiDefAutoButsRNA(layout, &ptr, image_open_draw_check_prop, NULL, UI_BUT_LABEL_ALIGN_NONE, false); /* image template */ RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr); @@ -2243,7 +2243,7 @@ static void image_save_as_cancel(bContext *UNUSED(C), wmOperator *op) image_save_as_free(op); } -static bool image_save_as_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop) +static bool image_save_as_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop, void *UNUSED(user_data)) { const char *prop_id = RNA_property_identifier(prop); @@ -2268,7 +2268,7 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op) /* main draw call */ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); - uiDefAutoButsRNA(layout, &ptr, image_save_as_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false); + uiDefAutoButsRNA(layout, &ptr, image_save_as_draw_check_prop, NULL, UI_BUT_LABEL_ALIGN_NONE, false); /* multiview template */ if (is_multiview) diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 4b3a3abc642..bba46771674 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -951,18 +951,18 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN /* open/close entirely? */ { uiBut *but; - int but_size = UI_UNIT_X * 0.6f; + int but_size = UI_UNIT_X * 1.2f; /* XXX button uses a custom triangle draw below, so make it invisible without icon */ UI_block_emboss_set(node->block, UI_EMBOSS_NONE); but = uiDefBut(node->block, UI_BTYPE_BUT_TOGGLE, B_REDR, "", - rct->xmin + 0.5f * U.widget_unit - but_size / 2, rct->ymax - NODE_DY / 2.0f - but_size / 2, + rct->xmin + 0.6f * U.widget_unit - but_size / 2, rct->ymax - NODE_DY / 2.2f - but_size / 2, but_size, but_size, NULL, 0, 0, 0, 0, ""); UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_hide_toggle"); UI_block_emboss_set(node->block, UI_EMBOSS); UI_GetThemeColor4fv(TH_TEXT, color); /* custom draw function for this button */ - UI_draw_icon_tri(rct->xmin + 0.5f * U.widget_unit, rct->ymax - NODE_DY / 2.0f, 'v', color); + UI_draw_icon_tri(rct->xmin + 0.6f * U.widget_unit, rct->ymax - NODE_DY / 2.2f, 'v', color); } nodeLabel(ntree, node, showname, sizeof(showname)); @@ -1071,7 +1071,7 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b /* open entirely icon */ { uiBut *but; - int but_size = UI_UNIT_X * 0.6f; + int but_size = UI_UNIT_X * 1.2f; /* XXX button uses a custom triangle draw below, so make it invisible without icon */ UI_block_emboss_set(node->block, UI_EMBOSS_NONE); but = uiDefBut(node->block, UI_BTYPE_BUT_TOGGLE, B_REDR, "", diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index ed7379acca9..3644c8d09e6 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -238,7 +238,7 @@ extern const char *node_context_dir[]; // nodes draw without dpi - the view zoom is flexible #define HIDDEN_RAD (0.75f * U.widget_unit) -#define BASIS_RAD (0.4f * U.widget_unit) +#define BASIS_RAD (0.2f * U.widget_unit) #define NODE_DYS (U.widget_unit / 2) #define NODE_DY U.widget_unit #define NODE_SOCKDY (0.08f * U.widget_unit) diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c index ad94615a0d2..e480cac2dcc 100644 --- a/source/blender/editors/space_outliner/outliner_collections.c +++ b/source/blender/editors/space_outliner/outliner_collections.c @@ -574,7 +574,7 @@ static TreeTraversalAction layer_collection_find_data_to_edit(TreeElement *te, v return TRAVERSE_CONTINUE; } -static bool collections_view_layer_poll(bContext *C, bool include) +static bool collections_view_layer_poll(bContext *C, bool clear, int flag) { /* Poll function so the right click menu show current state of selected collections. */ SpaceOops *soops = CTX_wm_space_outliner(C); @@ -593,10 +593,10 @@ static bool collections_view_layer_poll(bContext *C, bool include) GSET_ITER(collections_to_edit_iter, data.collections_to_edit) { LayerCollection *lc = BLI_gsetIterator_getKey(&collections_to_edit_iter); - if (include && (lc->flag & LAYER_COLLECTION_EXCLUDE)) { + if (clear && (lc->flag & flag)) { result = true; } - else if (!include && !(lc->flag & LAYER_COLLECTION_EXCLUDE)) { + else if (!clear && !(lc->flag & flag)) { result = true; } } @@ -605,27 +605,47 @@ static bool collections_view_layer_poll(bContext *C, bool include) return result; } -static bool collections_exclude_poll(bContext *C) +static bool collections_exclude_set_poll(bContext *C) { - return collections_view_layer_poll(C, false); + return collections_view_layer_poll(C, false, LAYER_COLLECTION_EXCLUDE); } -static bool collections_include_poll(bContext *C) +static bool collections_exclude_clear_poll(bContext *C) { - return collections_view_layer_poll(C, true); + return collections_view_layer_poll(C, true, LAYER_COLLECTION_EXCLUDE); } -static void layer_collection_exclude_recursive_set(LayerCollection *lc) +static bool collections_holdout_set_poll(bContext *C) +{ + return collections_view_layer_poll(C, false, LAYER_COLLECTION_HOLDOUT); +} + +static bool collections_holdout_clear_poll(bContext *C) +{ + return collections_view_layer_poll(C, true, LAYER_COLLECTION_HOLDOUT); +} + +static bool collections_indirect_only_set_poll(bContext *C) +{ + return collections_view_layer_poll(C, false, LAYER_COLLECTION_INDIRECT_ONLY); +} + +static bool collections_indirect_only_clear_poll(bContext *C) +{ + return collections_view_layer_poll(C, true, LAYER_COLLECTION_INDIRECT_ONLY); +} + +static void layer_collection_flag_recursive_set(LayerCollection *lc, int flag) { for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) { - if (lc->flag & LAYER_COLLECTION_EXCLUDE) { - nlc->flag |= LAYER_COLLECTION_EXCLUDE; + if (lc->flag & flag) { + nlc->flag |= flag; } else { - nlc->flag &= ~LAYER_COLLECTION_EXCLUDE; + nlc->flag &= ~flag; } - layer_collection_exclude_recursive_set(nlc); + layer_collection_flag_recursive_set(nlc, flag); } } @@ -636,7 +656,10 @@ static int collection_view_layer_exec(bContext *C, wmOperator *op) ViewLayer *view_layer = CTX_data_view_layer(C); SpaceOops *soops = CTX_wm_space_outliner(C); struct CollectionEditData data = {.scene = scene, .soops = soops}; - bool include = STREQ(op->idname, "OUTLINER_OT_collection_include_set"); + bool clear = strstr(op->idname, "clear") != NULL; + int flag = strstr(op->idname, "holdout") ? LAYER_COLLECTION_HOLDOUT : + strstr(op->idname, "indirect_only") ? LAYER_COLLECTION_INDIRECT_ONLY : + LAYER_COLLECTION_EXCLUDE; data.collections_to_edit = BLI_gset_ptr_new(__func__); @@ -647,14 +670,14 @@ static int collection_view_layer_exec(bContext *C, wmOperator *op) LayerCollection *lc = BLI_gsetIterator_getKey(&collections_to_edit_iter); if (!(lc->collection->flag & COLLECTION_IS_MASTER)) { - if (include) { - lc->flag &= ~LAYER_COLLECTION_EXCLUDE; + if (clear) { + lc->flag &= ~flag; } else { - lc->flag |= LAYER_COLLECTION_EXCLUDE; + lc->flag |= flag; } - layer_collection_exclude_recursive_set(lc); + layer_collection_flag_recursive_set(lc, flag); } } @@ -671,28 +694,88 @@ static int collection_view_layer_exec(bContext *C, wmOperator *op) void OUTLINER_OT_collection_exclude_set(wmOperatorType *ot) { /* identifiers */ - ot->name = "Exclude from View Layer"; + ot->name = "Set Exclude"; ot->idname = "OUTLINER_OT_collection_exclude_set"; ot->description = "Exclude collection from the active view layer"; /* api callbacks */ ot->exec = collection_view_layer_exec; - ot->poll = collections_exclude_poll; + ot->poll = collections_exclude_set_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -void OUTLINER_OT_collection_include_set(wmOperatorType *ot) +void OUTLINER_OT_collection_exclude_clear(wmOperatorType *ot) { /* identifiers */ - ot->name = "Include in View Layer"; - ot->idname = "OUTLINER_OT_collection_include_set"; + ot->name = "Clear Exclude"; + ot->idname = "OUTLINER_OT_collection_exclude_clear"; ot->description = "Include collection in the active view layer"; /* api callbacks */ ot->exec = collection_view_layer_exec; - ot->poll = collections_include_poll; + ot->poll = collections_exclude_clear_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +void OUTLINER_OT_collection_holdout_set(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Set Holdout"; + ot->idname = "OUTLINER_OT_collection_holdout_set"; + ot->description = "Mask collection in the active view layer"; + + /* api callbacks */ + ot->exec = collection_view_layer_exec; + ot->poll = collections_holdout_set_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +void OUTLINER_OT_collection_holdout_clear(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Clear Holdout"; + ot->idname = "OUTLINER_OT_collection_holdout_clear"; + ot->description = "Clear masking of collection in the active view layer"; + + /* api callbacks */ + ot->exec = collection_view_layer_exec; + ot->poll = collections_holdout_clear_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +void OUTLINER_OT_collection_indirect_only_set(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Set Indirect Only"; + ot->idname = "OUTLINER_OT_collection_indirect_only_set"; + ot->description = "Set collection to only contribute indirectly (through shadows and reflections) in the view layer"; + + /* api callbacks */ + ot->exec = collection_view_layer_exec; + ot->poll = collections_indirect_only_set_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +void OUTLINER_OT_collection_indirect_only_clear(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Clear Indirect Only"; + ot->idname = "OUTLINER_OT_collection_indirect_only_clear"; + ot->description = "Clear collection contributing only indirectly in the view layer"; + + /* api callbacks */ + ot->exec = collection_view_layer_exec; + ot->poll = collections_indirect_only_clear_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 783a03f3993..e1049d02e37 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1341,16 +1341,9 @@ static void tselem_draw_icon( static void outliner_draw_iconrow_number( const uiFontStyle *fstyle, int offsx, int ys, - const eOLDrawState active, const int num_elements) { - float color[4] = {0.4f, 0.4f, 0.4f, 0.9f}; - copy_v3_fl(color, 0.2f); - if (active != OL_DRAWSEL_NONE) { - copy_v3_fl(color, 0.65f); - color[3] = 1.0f; - } - + float color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; float ufac = 0.25f * UI_UNIT_X; float offset_x = (float) offsx + UI_UNIT_X * 0.35f; @@ -1414,13 +1407,13 @@ static void outliner_draw_iconrow_doit( } /* No inlined icon should be clickable. */ - tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.5f * alpha_fac, false); + tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.8f * alpha_fac, false); te->xs = *offsx; te->ys = ys; te->xend = (short)*offsx + UI_UNIT_X; if (num_elements > 1) { - outliner_draw_iconrow_number(fstyle, *offsx, ys, active, num_elements); + outliner_draw_iconrow_number(fstyle, *offsx, ys, num_elements); } (*offsx) += UI_UNIT_X; } diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index 093ad9361c2..461d4bd7c56 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -358,7 +358,11 @@ void OUTLINER_OT_collection_objects_deselect(struct wmOperatorType *ot); void OUTLINER_OT_collection_link(struct wmOperatorType *ot); void OUTLINER_OT_collection_instance(struct wmOperatorType *ot); void OUTLINER_OT_collection_exclude_set(struct wmOperatorType *ot); -void OUTLINER_OT_collection_include_set(struct wmOperatorType *ot); +void OUTLINER_OT_collection_exclude_clear(struct wmOperatorType *ot); +void OUTLINER_OT_collection_holdout_set(struct wmOperatorType *ot); +void OUTLINER_OT_collection_holdout_clear(struct wmOperatorType *ot); +void OUTLINER_OT_collection_indirect_only_set(struct wmOperatorType *ot); +void OUTLINER_OT_collection_indirect_only_clear(struct wmOperatorType *ot); /* outliner_utils.c ---------------------------------------------- */ diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index 0dd492839c9..576038979d3 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -457,7 +457,11 @@ void outliner_operatortypes(void) WM_operatortype_append(OUTLINER_OT_collection_link); WM_operatortype_append(OUTLINER_OT_collection_instance); WM_operatortype_append(OUTLINER_OT_collection_exclude_set); - WM_operatortype_append(OUTLINER_OT_collection_include_set); + WM_operatortype_append(OUTLINER_OT_collection_exclude_clear); + WM_operatortype_append(OUTLINER_OT_collection_holdout_set); + WM_operatortype_append(OUTLINER_OT_collection_holdout_clear); + WM_operatortype_append(OUTLINER_OT_collection_indirect_only_set); + WM_operatortype_append(OUTLINER_OT_collection_indirect_only_clear); } static wmKeyMap *outliner_item_drag_drop_modal_keymap(wmKeyConfig *keyconf) @@ -570,6 +574,9 @@ void outliner_keymap(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "OBJECT_OT_move_to_collection", MKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "OBJECT_OT_link_to_collection", MKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "OUTLINER_OT_collection_exclude_set", EKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "OUTLINER_OT_collection_exclude_clear", EKEY, KM_PRESS, KM_ALT, 0); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0); RNA_boolean_set(kmi->ptr, "select", false); kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 5d2ceced904..3cd5bfc3e58 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -627,7 +627,7 @@ static void sequencer_add_cancel(bContext *UNUSED(C), wmOperator *op) op->customdata = NULL; } -static bool sequencer_add_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop) +static bool sequencer_add_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop, void *UNUSED(user_data)) { const char *prop_id = RNA_property_identifier(prop); @@ -693,7 +693,7 @@ static void sequencer_add_draw(bContext *UNUSED(C), wmOperator *op) /* main draw call */ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); - uiDefAutoButsRNA(layout, &ptr, sequencer_add_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false); + uiDefAutoButsRNA(layout, &ptr, sequencer_add_draw_check_prop, NULL, UI_BUT_LABEL_ALIGN_NONE, false); /* image template */ RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr); diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index cefc6cdd814..199ff06cc8b 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -739,7 +739,7 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe) if (!skip_dup) { /* Duplicate AFTER the first change */ - seqn = BKE_sequence_dupli_recursive(scene, scene, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM); + seqn = BKE_sequence_dupli_recursive(scene, scene, seq, SEQ_DUPE_ANIM); } if (seqn) { @@ -848,7 +848,7 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe) if (!skip_dup) { /* Duplicate AFTER the first change */ - seqn = BKE_sequence_dupli_recursive(scene, scene, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM); + seqn = BKE_sequence_dupli_recursive(scene, scene, seq, SEQ_DUPE_ANIM); } if (seqn) { @@ -2091,6 +2091,7 @@ static int sequencer_cut_exec(bContext *C, wmOperator *op) SEQP_BEGIN (ed, seq) { + BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq); if (seq->seq1 || seq->seq2 || seq->seq3) { BKE_sequence_calc(scene, seq); } diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 71bdd2e20c2..2577077002e 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -1406,7 +1406,7 @@ static void space_view3d_listener( switch (wmn->data) { case ND_WORLD_DRAW: case ND_WORLD: - if (v3d->flag3 & V3D_SHOW_WORLD) + if (v3d->shading.background_type & V3D_SHADING_BACKGROUND_WORLD) ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW); break; } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 552d84ebb39..941f9262694 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1599,7 +1599,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple( v3d.flag2 |= V3D_SOLID_TEX; } - v3d.flag3 |= V3D_SHOW_WORLD; + v3d.shading.background_type = V3D_SHADING_BACKGROUND_WORLD; if (draw_flags & V3D_OFSDRAW_USE_CAMERA_DOF) { if (camera->type == OB_CAMERA) { diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index 7799854db49..6a8589f5468 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -72,6 +72,7 @@ static bool snap_calc_active_center(bContext *C, const bool select_only, float r /* *********************** operators ******************** */ +/** Snaps every individual object center to its nearest point on the grid. **/ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) { Depsgraph *depsgraph = CTX_data_depsgraph(C); @@ -212,7 +213,7 @@ void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot) { /* identifiers */ ot->name = "Snap Selection to Grid"; - ot->description = "Snap selected item(s) to nearest grid division"; + ot->description = "Snap selected item(s) to their nearest grid division"; ot->idname = "VIEW3D_OT_snap_selected_to_grid"; /* api callbacks */ @@ -225,6 +226,12 @@ void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot) /* *************************************************** */ +/** Snaps the selection as a whole (use_offset=true) or each selected object to the given location. + * + * \param snap_target_global: a location in global space to snap to (eg. 3D cursor or active object). + * \param use_offset: if the selected objects should maintain their relative offsets and be snapped by the selection + * pivot point (median, active), or if every object origin should be snapped to the given location. +**/ static int snap_selected_to_location(bContext *C, const float snap_target_global[3], const bool use_offset) { Depsgraph *depsgraph = CTX_data_depsgraph(C); @@ -434,7 +441,7 @@ void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot) { /* identifiers */ ot->name = "Snap Selection to Cursor"; - ot->description = "Snap selected item(s) to cursor"; + ot->description = "Snap selected item(s) to the 3D cursor"; ot->idname = "VIEW3D_OT_snap_selected_to_cursor"; /* api callbacks */ @@ -445,9 +452,13 @@ void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* rna */ - RNA_def_boolean(ot->srna, "use_offset", 1, "Offset", ""); + RNA_def_boolean(ot->srna, "use_offset", 1, "Offset", + "If the selection should be snapped as a whole or by each object center"); } +/* *************************************************** */ + +/** Snaps each selected object to the location of the active selected object. **/ static int snap_selected_to_active_exec(bContext *C, wmOperator *op) { float snap_target_global[3]; @@ -478,6 +489,7 @@ void VIEW3D_OT_snap_selected_to_active(wmOperatorType *ot) /* *************************************************** */ +/** Snaps the 3D cursor location to its nearest point on the grid. **/ static int snap_curs_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); @@ -502,7 +514,7 @@ void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot) { /* identifiers */ ot->name = "Snap Cursor to Grid"; - ot->description = "Snap cursor to nearest grid division"; + ot->description = "Snap 3D cursor to the nearest grid division"; ot->idname = "VIEW3D_OT_snap_cursor_to_grid"; /* api callbacks */ @@ -515,7 +527,8 @@ void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot) /* **************************************************** */ -static void bundle_midpoint(Depsgraph *depsgraph, Scene *scene, Object *ob, float vec[3]) +/** Returns the center position of a tracking marker visible on the viewport (useful to snap to). **/ +static void bundle_midpoint(Depsgraph *depsgraph, Scene *scene, Object *ob, float r_vec[3]) { MovieClip *clip = BKE_object_movieclip_get(scene, ob, false); MovieTracking *tracking; @@ -563,10 +576,11 @@ static void bundle_midpoint(Depsgraph *depsgraph, Scene *scene, Object *ob, floa } if (ok) { - mid_v3_v3v3(vec, min, max); + mid_v3_v3v3(r_vec, min, max); } } +/** Snaps the 3D cursor location to the median point of the selection. **/ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3]) { Depsgraph *depsgraph = CTX_data_depsgraph(C); @@ -690,7 +704,7 @@ void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot) { /* identifiers */ ot->name = "Snap Cursor to Selected"; - ot->description = "Snap cursor to center of selected item(s)"; + ot->description = "Snap 3D cursor to the middle of the selected item(s)"; ot->idname = "VIEW3D_OT_snap_cursor_to_selected"; /* api callbacks */ @@ -703,9 +717,11 @@ void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot) /* ********************************************** */ -/* this could be exported to be a generic function - * see: calculateCenterActive */ - +/** Calculates the center position of the active object in global space. + * + * Note: this could be exported to be a generic function. + * see: calculateCenterActive +**/ static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3]) { const Depsgraph *depsgraph = CTX_data_depsgraph(C); @@ -770,7 +786,7 @@ void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot) { /* identifiers */ ot->name = "Snap Cursor to Active"; - ot->description = "Snap cursor to active item"; + ot->description = "Snap 3D cursor to the active item"; ot->idname = "VIEW3D_OT_snap_cursor_to_active"; /* api callbacks */ @@ -782,7 +798,8 @@ void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot) } /* **************************************************** */ -/*New Code - Snap Cursor to Center -*/ + +/** Snaps the 3D cursor location to the origin. **/ static int snap_curs_to_center_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); @@ -802,7 +819,7 @@ void VIEW3D_OT_snap_cursor_to_center(wmOperatorType *ot) { /* identifiers */ ot->name = "Snap Cursor to Center"; - ot->description = "Snap cursor to world origin"; + ot->description = "Snap 3D cursor to the world origin"; ot->idname = "VIEW3D_OT_snap_cursor_to_center"; /* api callbacks */ @@ -815,23 +832,22 @@ void VIEW3D_OT_snap_cursor_to_center(wmOperatorType *ot) /* **************************************************** */ - -bool ED_view3d_minmax_verts(Object *obedit, float min[3], float max[3]) +/** Calculates the bounding box corners (min and max) for \a obedit. The returned values are in global space. **/ +bool ED_view3d_minmax_verts(Object *obedit, float r_min[3], float r_max[3]) { TransVertStore tvs = {NULL}; TransVert *tv; float centroid[3], vec[3], bmat[3][3]; - int a; - /* metaballs are an exception */ + /* Metaballs are an exception. */ if (obedit->type == OB_MBALL) { float ob_min[3], ob_max[3]; bool changed; changed = BKE_mball_minmax_ex(obedit->data, ob_min, ob_max, obedit->obmat, SELECT); if (changed) { - minmax_v3v3_v3(min, max, ob_min); - minmax_v3v3_v3(min, max, ob_max); + minmax_v3v3_v3(r_min, r_max, ob_min); + minmax_v3v3_v3(r_min, r_max, ob_max); } return changed; } @@ -845,12 +861,12 @@ bool ED_view3d_minmax_verts(Object *obedit, float min[3], float max[3]) copy_m3_m4(bmat, obedit->obmat); tv = tvs.transverts; - for (a = 0; a < tvs.transverts_tot; a++, tv++) { + for (int a = 0; a < tvs.transverts_tot; a++, tv++) { copy_v3_v3(vec, (tv->flag & TX_VERT_USE_MAPLOC) ? tv->maploc : tv->loc); mul_m3_v3(bmat, vec); add_v3_v3(vec, obedit->obmat[3]); add_v3_v3(centroid, vec); - minmax_v3v3_v3(min, max, vec); + minmax_v3v3_v3(r_min, r_max, vec); } ED_transverts_free(&tvs); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index dab53c04806..07ef6b9a819 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -2153,7 +2153,11 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) } } - RNA_property_boolean_set_array(op->ptr, prop, constraint_axis); + /* Only set if needed, so we can hide in the UI when nothing is set. + * See 'transform_poll_property'. */ + if (ELEM(true, UNPACK3(constraint_axis))) { + RNA_property_boolean_set_array(op->ptr, prop, constraint_axis); + } } { diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index c9a97c8530c..580bae71cc8 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -507,6 +507,36 @@ static int transform_invoke(bContext *C, wmOperator *op, const wmEvent *event) } } +static bool transform_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop) +{ + const char *prop_id = RNA_property_identifier(prop); + + /* Orientation/Constraints. */ + { + /* Hide orientation axis if no constraints are set, since it wont be used. */ + PropertyRNA *prop_con = RNA_struct_find_property(op->ptr, "constraint_axis"); + if (prop_con && !RNA_property_is_set(op->ptr, prop_con)) { + if (STRPREFIX(prop_id, "constraint")) { + return false; + } + } + } + + /* Proportional Editing. */ + { + PropertyRNA *prop_pet = RNA_struct_find_property(op->ptr, "proportional"); + if (prop_pet && (prop_pet != prop) && + (RNA_property_enum_get(op->ptr, prop_pet) == PROP_EDIT_OFF)) + { + if (STRPREFIX(prop_id, "proportional")) { + return false; + } + } + } + + return true; +} + void Transform_Properties(struct wmOperatorType *ot, int flags) { PropertyRNA *prop; @@ -615,6 +645,7 @@ static void TRANSFORM_OT_translate(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; + ot->poll_property = transform_poll_property; RNA_def_float_vector_xyz(ot->srna, "value", 3, NULL, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX); @@ -640,6 +671,7 @@ static void TRANSFORM_OT_resize(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; + ot->poll_property = transform_poll_property; RNA_def_float_vector(ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX); @@ -673,6 +705,7 @@ static void TRANSFORM_OT_skin_resize(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = skin_resize_poll; + ot->poll_property = transform_poll_property; RNA_def_float_vector(ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX); @@ -695,6 +728,7 @@ static void TRANSFORM_OT_trackball(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; + ot->poll_property = transform_poll_property; /* Maybe we could use float_vector_xyz here too? */ RNA_def_float_rotation(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX); @@ -718,6 +752,7 @@ static void TRANSFORM_OT_rotate(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; + ot->poll_property = transform_poll_property; RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2); @@ -744,6 +779,7 @@ static void TRANSFORM_OT_tilt(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_editcurve_3d; + ot->poll_property = transform_poll_property; RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2); @@ -766,6 +802,7 @@ static void TRANSFORM_OT_bend(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_region_view3d_active; + ot->poll_property = transform_poll_property; RNA_def_float_rotation(ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2); @@ -788,6 +825,7 @@ static void TRANSFORM_OT_shear(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; + ot->poll_property = transform_poll_property; RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX); @@ -811,6 +849,7 @@ static void TRANSFORM_OT_push_pull(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; + ot->poll_property = transform_poll_property; RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Distance", "", -FLT_MAX, FLT_MAX); @@ -833,6 +872,7 @@ static void TRANSFORM_OT_shrink_fatten(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_editmesh; + ot->poll_property = transform_poll_property; RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX); @@ -858,6 +898,7 @@ static void TRANSFORM_OT_tosphere(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; + ot->poll_property = transform_poll_property; RNA_def_float_factor(ot->srna, "value", 0, 0, 1, "Factor", "", 0, 1); @@ -880,6 +921,7 @@ static void TRANSFORM_OT_mirror(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; + ot->poll_property = transform_poll_property; Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_GPENCIL_EDIT | P_CENTER); } @@ -900,6 +942,7 @@ static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_editmesh_region_view3d; + ot->poll_property = transform_poll_property; RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f); @@ -932,6 +975,7 @@ static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_editmesh_region_view3d; + ot->poll_property = transform_poll_property; RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f); RNA_def_boolean(ot->srna, "use_even", false, "Even", @@ -961,6 +1005,7 @@ static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_editmesh; + ot->poll_property = transform_poll_property; RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f); @@ -1050,6 +1095,7 @@ static void TRANSFORM_OT_transform(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; + ot->poll_property = transform_poll_property; prop = RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", ""); RNA_def_property_flag(prop, PROP_HIDDEN); diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index b67fd22dbff..54253e36351 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -1462,7 +1462,7 @@ void snapSequenceBounds(TransInfo *t, const int mval[2]) float xmouse, ymouse; int frame; int mframe; - TransSeq *ts = t->custom.type.data; + TransSeq *ts = TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->custom.type.data; /* reuse increment, strictly speaking could be another snap mode, but leave as is */ if (!(t->modifiers & MOD_SNAP_INVERT)) return; diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index e19320fa220..a6e857c4a60 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -111,6 +111,10 @@ typedef struct SnapObjectData_EditMesh { SnapObjectData sd; BVHTreeFromEditMesh *bvh_trees[3]; + /* It's like a boundbox. It is tested first to avoid + * to create a bvhtree for all the edited objects. */ + float min[3], max[3]; + } SnapObjectData_EditMesh; struct SnapObjectContext { @@ -156,6 +160,39 @@ struct SnapObjectContext { typedef void(*IterSnapObjsCallback)(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data); +static void min_max_from_bmesh( + BMesh *bm, float r_min[3], float r_max[3]) +{ + BMIter iter; + BMVert *eve; + + INIT_MINMAX(r_min, r_max); + BM_ITER_MESH(eve, &iter, bm, BM_VERTS_OF_MESH) { + minmax_v3v3_v3(r_min, r_max, eve->co); + } +} + +static SnapObjectData_Mesh *snap_object_data_mesh_create(SnapObjectContext *sctx) +{ + SnapObjectData_Mesh *sod = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + sod->sd.type = SNAP_MESH; + /* start assuming that it has each of these element types */ + sod->has_looptris = true; + sod->has_loose_edge = true; + sod->has_loose_vert = true; + + return sod; +} + +static SnapObjectData_EditMesh *snap_object_data_editmesh_create(SnapObjectContext *sctx, BMesh *bm) +{ + SnapObjectData_EditMesh *sod = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + sod->sd.type = SNAP_EDIT_MESH; + min_max_from_bmesh(bm, sod->min, sod->max); + + return sod; +} + /** * Walks through all objects in the scene to create the list of objets to snap. * @@ -169,9 +206,9 @@ static void iter_snap_objects( IterSnapObjsCallback sob_callback, void *data) { - ViewLayer *view_layer = DEG_get_evaluated_view_layer(sctx->depsgraph); - Object *obedit = params->use_object_edit_cage ? OBEDIT_FROM_VIEW_LAYER(view_layer) : NULL; + ViewLayer *view_layer = DEG_get_input_view_layer(sctx->depsgraph); const eSnapSelect snap_select = params->snap_select; + const bool use_object_edit_cage = params->use_object_edit_cage; Base *base_act = view_layer->basact; for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) { @@ -179,20 +216,17 @@ static void iter_snap_objects( !((snap_select == SNAP_NOT_SELECTED && ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) || (snap_select == SNAP_NOT_ACTIVE && base == base_act))) { - bool use_obedit; - Object *obj = base->object; - if (obj->transflag & OB_DUPLI) { + Object *obj_eval = DEG_get_evaluated_object(sctx->depsgraph, base->object); + if (obj_eval->transflag & OB_DUPLI) { DupliObject *dupli_ob; - ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj); + ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj_eval); for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { - use_obedit = obedit && dupli_ob->ob->data == obedit->data; - sob_callback(sctx, use_obedit, use_obedit ? obedit : dupli_ob->ob, dupli_ob->mat, data); + sob_callback(sctx, use_object_edit_cage, dupli_ob->ob, dupli_ob->mat, data); } free_object_duplilist(lb); } - use_obedit = obedit && obj->data == obedit->data; - sob_callback(sctx, use_obedit, use_obedit ? obedit : obj, obj->obmat, data); + sob_callback(sctx, use_object_edit_cage, obj_eval, obj_eval->obmat, data); } } } @@ -372,13 +406,12 @@ static bool raycastMesh( sod = *sod_p; } else { - sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); - sod->sd.type = SNAP_MESH; + sod = *sod_p = snap_object_data_mesh_create(sctx); } BVHTreeFromMesh *treedata = &sod->treedata; - /* The tree is owned by the DM and may have been freed since we last used. */ + /* The tree is owned by the Mesh and may have been freed since we last used. */ if (treedata->tree) { BLI_assert(treedata->cached); if (!bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) { @@ -502,14 +535,30 @@ static bool raycastEditMesh( SnapObjectData_EditMesh *sod = NULL; BVHTreeFromEditMesh *treedata = NULL; + Object *em_ob = em->ob; + + BLI_assert(em_ob->data == BKE_object_get_pre_modified_mesh(ob)); void **sod_p; - if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { + /* Use `em->ob` as the key in ghash since the editmesh is used + * to create bvhtree and is the same for each linked object. */ + if (BLI_ghash_ensure_p(sctx->cache.object_map, em_ob, &sod_p)) { sod = *sod_p; } else { - sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); - sod->sd.type = SNAP_EDIT_MESH; + sod = *sod_p = snap_object_data_editmesh_create(sctx, em->bm); + } + + { + float min[3], max[3]; + mul_v3_m4v3(min, obmat, sod->min); + mul_v3_m4v3(max, obmat, sod->max); + + if (!isect_ray_aabb_v3_simple( + ray_start, ray_dir, min, max, NULL, NULL)) + { + return retval; + } } if (sod->bvh_trees[2] == NULL) { @@ -517,7 +566,17 @@ static bool raycastEditMesh( } treedata = sod->bvh_trees[2]; + BVHCache *em_bvh_cache = ((Mesh *)em_ob->data)->runtime.bvh_cache; + + if (sctx->callbacks.edit_mesh.test_face_fn == NULL) { + /* The tree is owned by the Mesh and may have been freed since we last used! */ + if (!bvhcache_has_tree(em_bvh_cache, treedata->tree)) { + free_bvhtree_from_editmesh(treedata); + } + } + if (treedata->tree == NULL) { + BVHCache **bvh_cache = NULL; BLI_bitmap *elem_mask = NULL; int looptri_num_active = -1; @@ -527,7 +586,15 @@ static bool raycastEditMesh( em->bm, elem_mask, sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data); } - bvhtree_from_editmesh_looptri_ex(treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, NULL); + else { + /* Only cache if bvhtree is created without a mask. + * This helps keep a standardized bvhtree in cache. */ + bvh_cache = &em_bvh_cache; + } + + bvhtree_from_editmesh_looptri_ex( + treedata, em, elem_mask, looptri_num_active, + 0.0f, 4, 6, bvh_cache); if (elem_mask) { MEM_freeN(elem_mask); @@ -669,7 +736,7 @@ static bool raycastObj( switch (ob->type) { case OB_MESH: - if (use_obedit) { + if (use_obedit && BKE_object_is_in_editmode(ob)) { BMEditMesh *em = BKE_editmesh_from_object(ob); retval = raycastEditMesh( sctx, @@ -718,7 +785,7 @@ struct RaycastObjUserData { bool ret; }; -static void raycast_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data) +static void raycast_obj_cb(SnapObjectContext *sctx, bool use_obedit, Object *ob, float obmat[4][4], void *data) { struct RaycastObjUserData *dt = data; @@ -726,7 +793,7 @@ static void raycast_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, sctx, dt->ray_start, dt->ray_dir, ob, obmat, dt->ob_index++, - is_obedit, dt->use_occlusion_test, + use_obedit, dt->use_occlusion_test, dt->ray_depth, dt->r_loc, dt->r_no, dt->r_index, dt->r_ob, dt->r_obmat, @@ -1118,6 +1185,13 @@ static short snap_mesh_polygon( }; SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob); + if (sod == NULL) { + /* The object is in edit mode, and the key used + * was the object referenced in BMEditMesh */ + BMEditMesh *em = BKE_editmesh_from_object(ob); + sod = BLI_ghash_lookup(sctx->cache.object_map, em->ob); + } + BLI_assert(sod != NULL); if (sod->type == SNAP_MESH) { @@ -1335,6 +1409,8 @@ static short snapArmature( dist_squared_to_projected_aabb_precalc( &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval); + use_obedit = use_obedit && BKE_object_is_in_editmode(ob); + if (use_obedit == false) { /* Test BoundBox */ BoundBox *bb = BKE_armature_boundbox_get(ob); @@ -1469,6 +1545,8 @@ static short snapCurve( dist_squared_to_projected_aabb_precalc( &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval); + use_obedit = use_obedit && BKE_object_is_in_editmode(ob); + if (use_obedit == false) { /* Test BoundBox */ BoundBox *bb = BKE_curve_boundbox_get(ob); @@ -1779,12 +1857,7 @@ static short snapMesh( sod = *sod_p; } else { - sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); - sod->sd.type = SNAP_MESH; - /* start assuming that it has each of these element types */ - sod->has_looptris = true; - sod->has_loose_edge = true; - sod->has_loose_vert = true; + sod = *sod_p = snap_object_data_mesh_create(sctx); } BVHTreeFromMesh *treedata, dummy_treedata; @@ -1792,7 +1865,7 @@ static short snapMesh( treedata = &sod->treedata; bvhtree = sod->bvhtree; - /* the tree is owned by the DM and may have been freed since we last used! */ + /* The tree is owned by the Mesh and may have been freed since we last used! */ if ((sod->has_looptris && treedata->tree && !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) || (sod->has_loose_edge && bvhtree[0] && !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[0])) || (sod->has_loose_vert && bvhtree[1] && !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1]))) @@ -1982,21 +2055,57 @@ static short snapEditMesh( SnapObjectData_EditMesh *sod = NULL; BVHTreeFromEditMesh *treedata_vert = NULL, *treedata_edge = NULL; + Object *em_ob = em->ob; + + BLI_assert(em_ob->data == BKE_object_get_pre_modified_mesh(ob)); + UNUSED_VARS_NDEBUG(ob); void **sod_p; - if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { + /* Use `em->ob` as the key in ghash since the editmesh is used + * to create bvhtree and is the same for each linked object. */ + if (BLI_ghash_ensure_p(sctx->cache.object_map, em_ob, &sod_p)) { sod = *sod_p; } else { - sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); - sod->sd.type = SNAP_EDIT_MESH; + sod = *sod_p = snap_object_data_editmesh_create(sctx, em->bm); + } + + float dist_px_sq = SQUARE(*dist_px); + + { + float min[3], max[3]; + mul_v3_m4v3(min, obmat, sod->min); + mul_v3_m4v3(max, obmat, sod->max); + + /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */ + struct DistProjectedAABBPrecalc data_precalc; + dist_squared_to_projected_aabb_precalc( + &data_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval); + + bool dummy[3]; + float bb_dist_px_sq = dist_squared_to_projected_aabb( + &data_precalc, min, max, dummy); + + if (bb_dist_px_sq > dist_px_sq) { + return 0; + } } + BVHCache *em_bvh_cache = ((Mesh *)em_ob->data)->runtime.bvh_cache; + if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) { if (sod->bvh_trees[0] == NULL) { sod->bvh_trees[0] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees)); } treedata_vert = sod->bvh_trees[0]; + + if (sctx->callbacks.edit_mesh.test_vert_fn == NULL) { + /* The tree is owned by the Mesh and may have been freed since we last used! */ + if (!bvhcache_has_tree(em_bvh_cache, treedata_vert->tree)) { + free_bvhtree_from_editmesh(treedata_vert); + } + } + if (treedata_vert->tree == NULL) { BLI_bitmap *verts_mask = NULL; int verts_num_active = -1; @@ -2006,9 +2115,13 @@ static short snapEditMesh( BM_VERTS_OF_MESH, em->bm, verts_mask, (bool(*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn, sctx->callbacks.edit_mesh.user_data); + + bvhtree_from_editmesh_verts_ex(treedata_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6); + MEM_freeN(verts_mask); + } + else { + bvhtree_from_editmesh_verts(treedata_vert, em, 0.0f, 2, 6, &em_bvh_cache); } - bvhtree_from_editmesh_verts_ex(treedata_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6); - MEM_SAFE_FREE(verts_mask); } } @@ -2017,6 +2130,14 @@ static short snapEditMesh( sod->bvh_trees[1] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees)); } treedata_edge = sod->bvh_trees[1]; + + if (sctx->callbacks.edit_mesh.test_edge_fn == NULL) { + /* The tree is owned by the Mesh and may have been freed since we last used! */ + if (!bvhcache_has_tree(em_bvh_cache, treedata_edge->tree)) { + free_bvhtree_from_editmesh(treedata_edge); + } + } + if (treedata_edge->tree == NULL) { BLI_bitmap *edges_mask = NULL; int edges_num_active = -1; @@ -2027,9 +2148,12 @@ static short snapEditMesh( (bool(*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn, sctx->callbacks.edit_mesh.user_data); + bvhtree_from_editmesh_edges_ex(treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6); + MEM_freeN(edges_mask); + } + else { + bvhtree_from_editmesh_edges(treedata_edge, em, 0.0f, 2, 6, &em_bvh_cache); } - bvhtree_from_editmesh_edges_ex(treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6); - MEM_SAFE_FREE(edges_mask); } } @@ -2043,7 +2167,7 @@ static short snapEditMesh( BVHTreeNearest nearest = { .index = -1, - .dist_sq = SQUARE(*dist_px), + .dist_sq = dist_px_sq, }; int last_index = nearest.index; short elem = SCE_SNAP_MODE_VERTEX; @@ -2119,7 +2243,7 @@ static short snapObject( switch (ob->type) { case OB_MESH: - if (use_obedit) { + if (use_obedit && BKE_object_is_in_editmode(ob)) { BMEditMesh *em = BKE_editmesh_from_object(ob); retval = snapEditMesh( sctx, snapdata, ob, em, obmat, diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 51e2c1b6334..32bf32b03ab 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -80,6 +80,7 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "RNA_enum_types.h" #include "WM_api.h" #include "WM_types.h" @@ -4404,6 +4405,15 @@ void ED_keymap_uvedit(wmKeyConfig *keyconf) RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_uv_sculpt"); #endif + /* Select Element (Sync Select: on) */ + ED_keymap_editmesh_elem_mode(keyconf, keymap); + /* Hack to prevent fall-through, when the button isn't visible. */ + WM_keymap_add_item(keymap, "MESH_OT_select_mode", FOURKEY, KM_PRESS, 0, 0); + /* Select Element (Sync Select: off) */ + WM_keymap_add_context_enum_set_items( + keymap, rna_enum_mesh_select_mode_uv_items, "tool_settings.uv_select_mode", + ONEKEY, KM_PRESS, 0, 0); + /* Mark edge seam */ WM_keymap_add_item(keymap, "UV_OT_mark_seam", EKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index d36b0ea15be..f435be7fb34 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -42,6 +42,7 @@ bool GPU_full_non_power_of_two_support(void); bool GPU_bicubic_bump_support(void); int GPU_max_texture_size(void); +int GPU_max_texture_layers(void); int GPU_max_textures(void); float GPU_max_texture_anisotropy(void); int GPU_max_color_texture_samples(void); diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index b3e56c3640a..d8132e7c088 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -55,7 +55,6 @@ struct GPUNodeStack; struct GPUMaterial; struct GPUTexture; struct GPUUniformBuffer; -struct GPULamp; struct PreviewImage; struct World; struct bNode; diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index dff6cfb74a8..43081154e89 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -66,6 +66,7 @@ static struct GPUGlobal { GLint maxtexsize; + GLint maxtexlayers; GLint maxcubemapsize; GLint maxtextures; GLint maxubosize; @@ -96,6 +97,11 @@ int GPU_max_texture_size(void) return GG.maxtexsize; } +int GPU_max_texture_layers(void) +{ + return GG.maxtexlayers; +} + int GPU_max_textures(void) { return GG.maxtextures; @@ -142,6 +148,7 @@ void gpu_extensions_init(void) glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &GG.maxtextures); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GG.maxtexsize); + glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &GG.maxtexlayers); glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GG.maxcubemapsize); if (GLEW_EXT_texture_filter_anisotropic) diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index 5ac746ec9c1..a5dfb6a6b73 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -160,6 +160,8 @@ static int gpu_get_component_count(GPUTextureFormat format) /* Definitely not complete, edit according to the gl specification. */ static void gpu_validate_data_format(GPUTextureFormat tex_format, GPUDataFormat data_format) { + (void)data_format; + if (ELEM(tex_format, GPU_DEPTH_COMPONENT24, GPU_DEPTH_COMPONENT16, @@ -432,6 +434,11 @@ static bool gpu_texture_try_alloc( glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, data_format, data_type, NULL); break; case GL_PROXY_TEXTURE_2D_ARRAY: + /* HACK: Some driver wrongly check GL_PROXY_TEXTURE_2D_ARRAY as a GL_PROXY_TEXTURE_3D + * checking all dimensions against GPU_max_texture_layers (see T55888). */ + return (tex->w > 0) && (tex->w <= GPU_max_texture_size()) && + (tex->h > 0) && (tex->h <= GPU_max_texture_size()) && + (tex->d > 0) && (tex->d <= GPU_max_texture_layers()); case GL_PROXY_TEXTURE_3D: glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, data_format, data_type, NULL); break; diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h index bfdd21807b8..e6b1bda7cf5 100644 --- a/source/blender/makesdna/DNA_layer_types.h +++ b/source/blender/makesdna/DNA_layer_types.h @@ -104,6 +104,8 @@ enum { BASE_ENABLED_VIEWPORT = (1 << 6), /* Object is enabled in viewport. */ BASE_ENABLED_RENDER = (1 << 7), /* Object is enabled in final render */ BASE_ENABLED = (1 << 9), /* Object is enabled. */ + BASE_HOLDOUT = (1 << 10), /* Object masked out from render */ + BASE_INDIRECT_ONLY = (1 << 11), /* Object only contributes indirectly to render */ }; /* LayerCollection->flag */ @@ -113,6 +115,8 @@ enum { /* LAYER_COLLECTION_DEPRECATED2 = (1 << 2), */ /* LAYER_COLLECTION_DEPRECATED3 = (1 << 3), */ LAYER_COLLECTION_EXCLUDE = (1 << 4), + LAYER_COLLECTION_HOLDOUT = (1 << 5), + LAYER_COLLECTION_INDIRECT_ONLY = (1 << 6), }; /* Layer Collection->runtime_flag */ diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 999ebe0ccc3..edc87c492a6 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -283,7 +283,6 @@ typedef struct Object { /* Runtime valuated curve-specific data, not stored in the file */ struct CurveCache *curve_cache; - ListBase gpulamp; /* runtime, for glsl lamp display only */ ListBase pc_ids; struct RigidBodyOb *rigidbody_object; /* settings for Bullet rigid body */ diff --git a/source/blender/makesdna/DNA_rigidbody_types.h b/source/blender/makesdna/DNA_rigidbody_types.h index 693707b8b7a..a99d5b409be 100644 --- a/source/blender/makesdna/DNA_rigidbody_types.h +++ b/source/blender/makesdna/DNA_rigidbody_types.h @@ -220,7 +220,8 @@ typedef struct RigidBodyCon { int flag; /* (eRigidBodyCon_Flag) */ float breaking_threshold; /* breaking impulse threshold */ - float pad; + char spring_type; /* spring implementation to use */ + char pad[3]; /* limits */ /* translation limits */ @@ -290,9 +291,15 @@ typedef enum eRigidBodyCon_Type { /* Simplified spring constraint with only once axis that's automatically placed between the connected bodies */ RBC_TYPE_SPRING, /* dirves bodies by applying linear and angular forces */ - RBC_TYPE_MOTOR + RBC_TYPE_MOTOR, } eRigidBodyCon_Type; +/* Spring implementation type for RigidBodyOb */ +typedef enum eRigidBodyCon_SpringType { + RBC_SPRING_TYPE1 = 0, /* btGeneric6DofSpringConstraint */ + RBC_SPRING_TYPE2, /* btGeneric6DofSpring2Constraint */ +} eRigidBodyCon_SpringType; + /* Flags for RigidBodyCon */ typedef enum eRigidBodyCon_Flag { /* constraint influences rigid body motion */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 16c8d8875c7..a4235a07ed5 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -2096,7 +2096,7 @@ enum { SCE_EEVEE_VOLUMETRIC_ENABLED = (1 << 0), SCE_EEVEE_VOLUMETRIC_LIGHTS = (1 << 1), SCE_EEVEE_VOLUMETRIC_SHADOWS = (1 << 2), - SCE_EEVEE_VOLUMETRIC_COLORED = (1 << 3), +// SCE_EEVEE_VOLUMETRIC_COLORED = (1 << 3), /* Unused */ SCE_EEVEE_GTAO_ENABLED = (1 << 4), SCE_EEVEE_GTAO_BENT_NORMALS = (1 << 5), SCE_EEVEE_GTAO_BOUNCE = (1 << 6), diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index fedc604f120..bbbaf8bb957 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -142,7 +142,9 @@ typedef struct View3DShading { short color_type; short light; - short pad[3]; + short background_type; + short pad2[2]; + char studio_light[256]; /* FILE_MAXFILE */ char matcap[256]; /* FILE_MAXFILE */ @@ -157,6 +159,10 @@ typedef struct View3DShading { float cavity_valley_factor; float cavity_ridge_factor; + + float background_color[3]; + int pad; + } View3DShading; /* 3D Viewport Overlay setings */ @@ -349,7 +355,7 @@ typedef struct View3D { /* View3d->flag3 (short) */ -#define V3D_SHOW_WORLD (1 << 0) +#define V3D_SHOW_WORLD (1 << 0) /* LEGACY replaced by V3D_SHADING_BACKGROUND_WORLD */ /* View3DShading->light */ enum { @@ -378,6 +384,13 @@ enum { V3D_SHADING_TEXTURE_COLOR = 3, }; +/* View3DShading->background_type */ +enum { + V3D_SHADING_BACKGROUND_THEME = 0, + V3D_SHADING_BACKGROUND_WORLD = 1, + V3D_SHADING_BACKGROUND_VIEWPORT = 2, +}; + /* View3DOverlay->flag */ enum { V3D_OVERLAY_FACE_ORIENTATION = (1 << 0), diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index f66c80beeab..cb5e2e61f9a 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -800,7 +800,7 @@ bool RNA_struct_bl_idname_ok_or_report(struct ReportList *reports, const char *i /* Property Information */ -const char *RNA_property_identifier(PropertyRNA *prop); +const char *RNA_property_identifier(const PropertyRNA *prop); const char *RNA_property_description(PropertyRNA *prop); PropertyType RNA_property_type(PropertyRNA *prop); diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index bafb2bf5753..043375a066a 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -54,6 +54,7 @@ extern const EnumPropertyItem rna_enum_snap_element_items[]; extern const EnumPropertyItem rna_enum_snap_node_element_items[]; extern const EnumPropertyItem rna_enum_curve_fit_method_items[]; extern const EnumPropertyItem rna_enum_mesh_select_mode_items[]; +extern const EnumPropertyItem rna_enum_mesh_select_mode_uv_items[]; extern const EnumPropertyItem rna_enum_mesh_delimit_mode_items[]; extern const EnumPropertyItem rna_enum_space_graph_mode_items[]; extern const EnumPropertyItem rna_enum_space_type_items[]; diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 7228f4a4683..a0c34afa7ed 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -975,7 +975,7 @@ bool RNA_struct_bl_idname_ok_or_report(ReportList *reports, const char *identifi /* Property Information */ -const char *RNA_property_identifier(PropertyRNA *prop) +const char *RNA_property_identifier(const PropertyRNA *prop) { return rna_ensure_property_identifier(prop); } diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c index 146a8e2738d..8ca45e6dd2d 100644 --- a/source/blender/makesrna/intern/rna_camera.c +++ b/source/blender/makesrna/intern/rna_camera.c @@ -428,6 +428,7 @@ void RNA_def_camera(BlenderRNA *brna) prop = RNA_def_property(srna, "passepartout_alpha", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "passepartalpha"); + RNA_def_property_float_default(prop, 0.5f); RNA_def_property_ui_text(prop, "Passepartout Alpha", "Opacity (alpha) of the darkened overlay in Camera view"); RNA_def_property_update(prop, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, NULL); @@ -454,6 +455,7 @@ void RNA_def_camera(BlenderRNA *brna) prop = RNA_def_property(srna, "clip_start", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "clipsta"); + RNA_def_property_float_default(prop, 0.1f); RNA_def_property_range(prop, 1e-6f, FLT_MAX); RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3); RNA_def_property_ui_text(prop, "Clip Start", "Camera near clipping distance"); @@ -461,6 +463,7 @@ void RNA_def_camera(BlenderRNA *brna) prop = RNA_def_property(srna, "clip_end", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "clipend"); + RNA_def_property_float_default(prop, 1000.0f); RNA_def_property_range(prop, 1e-6f, FLT_MAX); RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3); RNA_def_property_ui_text(prop, "Clip End", "Camera far clipping distance"); @@ -468,6 +471,7 @@ void RNA_def_camera(BlenderRNA *brna) prop = RNA_def_property(srna, "lens", PROP_FLOAT, PROP_DISTANCE_CAMERA); RNA_def_property_float_sdna(prop, NULL, "lens"); + RNA_def_property_float_default(prop, 50.0f); RNA_def_property_range(prop, 1.0f, FLT_MAX); RNA_def_property_ui_range(prop, 1.0f, 5000.0f, 1, 2); RNA_def_property_ui_text(prop, "Focal Length", "Perspective Camera lens value in millimeters"); @@ -475,6 +479,7 @@ void RNA_def_camera(BlenderRNA *brna) prop = RNA_def_property(srna, "sensor_width", PROP_FLOAT, PROP_DISTANCE_CAMERA); RNA_def_property_float_sdna(prop, NULL, "sensor_x"); + RNA_def_property_float_default(prop, 36.0f); RNA_def_property_range(prop, 1.0f, FLT_MAX); RNA_def_property_ui_range(prop, 1.0f, 100.f, 1, 2); RNA_def_property_ui_text(prop, "Sensor Width", "Horizontal size of the image sensor area in millimeters"); @@ -482,6 +487,7 @@ void RNA_def_camera(BlenderRNA *brna) prop = RNA_def_property(srna, "sensor_height", PROP_FLOAT, PROP_DISTANCE_CAMERA); RNA_def_property_float_sdna(prop, NULL, "sensor_y"); + RNA_def_property_float_default(prop, 34.0f); RNA_def_property_range(prop, 1.0f, FLT_MAX); RNA_def_property_ui_range(prop, 1.0f, 100.f, 1, 2); RNA_def_property_ui_text(prop, "Sensor Height", "Vertical size of the image sensor area in millimeters"); @@ -489,6 +495,7 @@ void RNA_def_camera(BlenderRNA *brna) prop = RNA_def_property(srna, "ortho_scale", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "ortho_scale"); + RNA_def_property_float_default(prop, 6.0f); RNA_def_property_range(prop, FLT_MIN, FLT_MAX); RNA_def_property_ui_range(prop, 0.001f, 10000.0f, 10, 3); RNA_def_property_ui_text(prop, "Orthographic Scale", "Orthographic Camera scale (similar to zoom)"); @@ -496,6 +503,7 @@ void RNA_def_camera(BlenderRNA *brna) prop = RNA_def_property(srna, "draw_size", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "drawsize"); + RNA_def_property_float_default(prop, 1.0f); RNA_def_property_range(prop, 0.01f, 1000.0f); RNA_def_property_ui_range(prop, 0.01, 100, 1, 2); RNA_def_property_ui_text(prop, "Draw Size", "Apparent size of the Camera object in the 3D View"); @@ -542,6 +550,7 @@ void RNA_def_camera(BlenderRNA *brna) prop = RNA_def_property(srna, "show_passepartout", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_SHOWPASSEPARTOUT); + RNA_def_property_boolean_default(prop, true); RNA_def_property_ui_text(prop, "Show Passepartout", "Show a darkened overlay outside the image area in Camera view"); RNA_def_property_update(prop, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, NULL); diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c index 7d770a99c0c..d425534fe53 100644 --- a/source/blender/makesrna/intern/rna_layer.c +++ b/source/blender/makesrna/intern/rna_layer.c @@ -230,6 +230,18 @@ static void rna_def_layer_collection(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Exclude", "Exclude collection from view layer"); RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_LayerCollection_use_update"); + + prop = RNA_def_property(srna, "holdout", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", LAYER_COLLECTION_HOLDOUT); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Holdout", "Mask out objects in collection from view layer"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_LayerCollection_use_update"); + + prop = RNA_def_property(srna, "indirect_only", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", LAYER_COLLECTION_INDIRECT_ONLY); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Indirect Only", "Objects in collection only contribute indirectly (through shadows and reflections) in the view layer"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_LayerCollection_use_update"); } static void rna_def_layer_collections(BlenderRNA *brna, PropertyRNA *cprop) diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 1a2b3854668..3adf9f790d9 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -128,11 +128,11 @@ static bool rna_Object_select_get(Object *ob, bContext *C, ReportList *reports) Base *base = BKE_view_layer_base_find(view_layer, ob); if (!base) { - BKE_reportf(reports, RPT_ERROR, "Object '%s' not in Render Layer '%s'!", ob->id.name + 2, view_layer->name); - return -1; + BKE_reportf(reports, RPT_ERROR, "Object '%s' not in View Layer '%s'!", ob->id.name + 2, view_layer->name); + return false; } - return ((base->flag & BASE_SELECTED) != 0) ? 1 : 0; + return ((base->flag & BASE_SELECTED) != 0); } static bool rna_Object_visible_get(Object *ob, bContext *C, ReportList *reports) @@ -141,11 +141,35 @@ static bool rna_Object_visible_get(Object *ob, bContext *C, ReportList *reports) Base *base = BKE_view_layer_base_find(view_layer, ob); if (!base) { - BKE_reportf(reports, RPT_ERROR, "Object '%s' not in Render Layer '%s'!", ob->id.name + 2, view_layer->name); - return -1; + BKE_reportf(reports, RPT_ERROR, "Object '%s' not in View Layer '%s'!", ob->id.name + 2, view_layer->name); + return false; + } + + return ((base->flag & BASE_VISIBLE) != 0); +} + +static bool rna_Object_holdout_get(Object *ob, ReportList *reports, ViewLayer *view_layer) +{ + Base *base = BKE_view_layer_base_find(view_layer, ob); + + if (!base) { + BKE_reportf(reports, RPT_ERROR, "Object '%s' not in View Layer '%s'!", ob->id.name + 2, view_layer->name); + return false; } - return ((base->flag & BASE_VISIBLE) != 0) ? 1 : 0; + return ((base->flag & BASE_HOLDOUT) != 0); +} + +static bool rna_Object_indirect_only_get(Object *ob, ReportList *reports, ViewLayer *view_layer) +{ + Base *base = BKE_view_layer_base_find(view_layer, ob); + + if (!base) { + BKE_reportf(reports, RPT_ERROR, "Object '%s' not in View Layer '%s'!", ob->id.name + 2, view_layer->name); + return false; + } + + return ((base->flag & BASE_INDIRECT_ONLY) != 0); } /* Convert a given matrix from a space to another (using the object and/or a bone as reference). */ @@ -309,8 +333,10 @@ static void rna_Object_ray_cast( /* Test BoundBox first (efficiency) */ BoundBox *bb = BKE_object_boundbox_get(ob); float distmin; - if (!bb || (isect_ray_aabb_v3_simple(origin, direction, bb->vec[0], bb->vec[6], &distmin, NULL) && distmin <= distance)) { - + normalize_v3(direction); /* Needed for valid distance check from isect_ray_aabb_v3_simple() call. */ + if (!bb || + (isect_ray_aabb_v3_simple(origin, direction, bb->vec[0], bb->vec[6], &distmin, NULL) && distmin <= distance)) + { BVHTreeFromMesh treeData = {NULL}; /* no need to managing allocation or freeing of the BVH data. this is generated and freed as needed */ @@ -323,9 +349,6 @@ static void rna_Object_ray_cast( hit.index = -1; hit.dist = distance; - normalize_v3(direction); - - if (BLI_bvhtree_ray_cast(treeData.tree, origin, direction, 0.0f, &hit, treeData.raycast_callback, &treeData) != -1) { @@ -470,31 +493,47 @@ void RNA_api_object(StructRNA *srna) #endif static EnumPropertyItem object_select_items[] = { - {0, "SELECT", 0, "Select", "Select object from the active render layer"}, - {1, "DESELECT", 0, "Deselect", "Deselect object from the active render layer"}, - {2, "TOGGLE", 0, "Toggle", "Toggle object selection from the active render layer"}, + {0, "SELECT", 0, "Select", "Select object from the active view layer"}, + {1, "DESELECT", 0, "Deselect", "Deselect object from the active view layer"}, + {2, "TOGGLE", 0, "Toggle", "Toggle object selection from the active view layer"}, {0, NULL, 0, NULL, NULL} }; /* Special wrapper to access the base selection value */ func = RNA_def_function(srna, "select_set", "rna_Object_select_set"); - RNA_def_function_ui_description(func, "Select the object (for the active render layer)"); + RNA_def_function_ui_description(func, "Select the object (for the active view layer)"); RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS); parm = RNA_def_enum(func, "action", object_select_items, 0, "Action", "Select mode"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); func = RNA_def_function(srna, "select_get", "rna_Object_select_get"); - RNA_def_function_ui_description(func, "Get the object selection for the active render layer"); + RNA_def_function_ui_description(func, "Get the object selection for the active view layer"); RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS); parm = RNA_def_boolean(func, "result", 0, "", "Object selected"); RNA_def_function_return(func, parm); func = RNA_def_function(srna, "visible_get", "rna_Object_visible_get"); - RNA_def_function_ui_description(func, "Get the object visibility for the active render layer"); + RNA_def_function_ui_description(func, "Get the object visibility for the active view layer"); RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS); parm = RNA_def_boolean(func, "result", 0, "", "Object visible"); RNA_def_function_return(func, parm); + func = RNA_def_function(srna, "holdout_get", "rna_Object_holdout_get"); + RNA_def_function_ui_description(func, "Test if object is masked in the view layer"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "view_layer", "ViewLayer", "", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_boolean(func, "result", 0, "", "Object holdout"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "indirect_only_get", "rna_Object_indirect_only_get"); + RNA_def_function_ui_description(func, "Test if object is set to contribute only indirectly (through shadows and reflections) in the view layer"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "view_layer", "ViewLayer", "", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_boolean(func, "result", 0, "", "Object indirect only"); + RNA_def_function_return(func, parm); + /* Matrix space conversion */ func = RNA_def_function(srna, "convert_space", "rna_Object_mat_convert_space"); RNA_def_function_ui_description(func, "Convert (transform) the given matrix from one space to another"); diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 4b8299b9245..979e5d433e7 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -1132,6 +1132,9 @@ static void rna_ParticleDupliWeight_active_index_set(struct PointerRNA *ptr, int static void rna_ParticleDupliWeight_name_get(PointerRNA *ptr, char *str) { + ParticleSettings *part = (ParticleSettings *)ptr->id.data; + psys_find_group_weights(part); + ParticleDupliWeight *dw = ptr->data; if (dw->ob) diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c index 592f8ee38c0..47075d0d4f7 100644 --- a/source/blender/makesrna/intern/rna_rigidbody.c +++ b/source/blender/makesrna/intern/rna_rigidbody.c @@ -76,6 +76,12 @@ const EnumPropertyItem rna_enum_rigidbody_constraint_type_items[] = { {RBC_TYPE_MOTOR, "MOTOR", ICON_NONE, "Motor", "Drive rigid body around or along an axis"}, {0, NULL, 0, NULL, NULL}}; +/* bullet spring type */ +const EnumPropertyItem rna_enum_rigidbody_constraint_spring_type_items[] = { + {RBC_SPRING_TYPE1, "SPRING1", ICON_NONE, "Blender 2.7", "Spring implementation used in blender 2.7. Damping is capped at 1.0"}, + {RBC_SPRING_TYPE2, "SPRING2", ICON_NONE, "Blender 2.8", "New implementation available since 2.8"}, + {0, NULL, 0, NULL, NULL}}; + #ifndef RNA_RUNTIME /* mesh source for collision shape creation */ static const EnumPropertyItem rigidbody_mesh_source_items[] = { @@ -375,6 +381,14 @@ static void rna_RigidBodyCon_type_set(PointerRNA *ptr, int value) rbc->flag |= RBC_FLAG_NEEDS_VALIDATE; } +static void rna_RigidBodyCon_spring_type_set(PointerRNA *ptr, int value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + rbc->spring_type = value; + rbc->flag |= RBC_FLAG_NEEDS_VALIDATE; +} + static void rna_RigidBodyCon_enabled_set(PointerRNA *ptr, bool value) { RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; @@ -467,6 +481,22 @@ static void rna_RigidBodyCon_num_solver_iterations_set(PointerRNA *ptr, int valu #endif } +#ifdef WITH_BULLET +static void rna_RigidBodyCon_do_set_spring_stiffness(RigidBodyCon *rbc, float value, int flag, int axis) +{ + if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & flag)) { + switch (rbc->spring_type) { + case RBC_SPRING_TYPE1: + RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, axis, value); + break; + case RBC_SPRING_TYPE2: + RB_constraint_set_stiffness_6dof_spring2(rbc->physics_constraint, axis, value); + break; + } + } +} +#endif + static void rna_RigidBodyCon_spring_stiffness_x_set(PointerRNA *ptr, float value) { RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; @@ -474,9 +504,7 @@ static void rna_RigidBodyCon_spring_stiffness_x_set(PointerRNA *ptr, float value rbc->spring_stiffness_x = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_X)) { - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, value); - } + rna_RigidBodyCon_do_set_spring_stiffness(rbc, value, RBC_FLAG_USE_SPRING_X, RB_LIMIT_LIN_X); #endif } @@ -487,9 +515,7 @@ static void rna_RigidBodyCon_spring_stiffness_y_set(PointerRNA *ptr, float value rbc->spring_stiffness_y = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_Y)) { - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, value); - } + rna_RigidBodyCon_do_set_spring_stiffness(rbc, value, RBC_FLAG_USE_SPRING_Y, RB_LIMIT_LIN_Y); #endif } @@ -500,9 +526,7 @@ static void rna_RigidBodyCon_spring_stiffness_z_set(PointerRNA *ptr, float value rbc->spring_stiffness_z = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_Z)) { - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, value); - } + rna_RigidBodyCon_do_set_spring_stiffness(rbc, value, RBC_FLAG_USE_SPRING_Z, RB_LIMIT_LIN_Z); #endif } @@ -513,9 +537,7 @@ static void rna_RigidBodyCon_spring_stiffness_ang_x_set(PointerRNA *ptr, float v rbc->spring_stiffness_ang_x = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_X)) { - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, value); - } + rna_RigidBodyCon_do_set_spring_stiffness(rbc, value, RBC_FLAG_USE_SPRING_ANG_X, RB_LIMIT_ANG_X); #endif } @@ -526,9 +548,7 @@ static void rna_RigidBodyCon_spring_stiffness_ang_y_set(PointerRNA *ptr, float v rbc->spring_stiffness_ang_y = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_Y)) { - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, value); - } + rna_RigidBodyCon_do_set_spring_stiffness(rbc, value, RBC_FLAG_USE_SPRING_ANG_Y, RB_LIMIT_ANG_Y); #endif } @@ -539,12 +559,26 @@ static void rna_RigidBodyCon_spring_stiffness_ang_z_set(PointerRNA *ptr, float v rbc->spring_stiffness_ang_z = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_Z)) { - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, value); - } + rna_RigidBodyCon_do_set_spring_stiffness(rbc, value, RBC_FLAG_USE_SPRING_ANG_Z, RB_LIMIT_ANG_Z); #endif } +#ifdef WITH_BULLET +static void rna_RigidBodyCon_do_set_spring_damping(RigidBodyCon *rbc, float value, int flag, int axis) +{ + if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & flag)) { + switch (rbc->spring_type) { + case RBC_SPRING_TYPE1: + RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, axis, value); + break; + case RBC_SPRING_TYPE2: + RB_constraint_set_damping_6dof_spring2(rbc->physics_constraint, axis, value); + break; + } + } +} +#endif + static void rna_RigidBodyCon_spring_damping_x_set(PointerRNA *ptr, float value) { RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; @@ -552,9 +586,7 @@ static void rna_RigidBodyCon_spring_damping_x_set(PointerRNA *ptr, float value) rbc->spring_damping_x = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_X)) { - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, value); - } + rna_RigidBodyCon_do_set_spring_damping(rbc, value, RBC_FLAG_USE_SPRING_X, RB_LIMIT_LIN_X); #endif } @@ -564,9 +596,7 @@ static void rna_RigidBodyCon_spring_damping_y_set(PointerRNA *ptr, float value) rbc->spring_damping_y = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_Y)) { - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, value); - } + rna_RigidBodyCon_do_set_spring_damping(rbc, value, RBC_FLAG_USE_SPRING_Y, RB_LIMIT_LIN_Y); #endif } @@ -576,9 +606,7 @@ static void rna_RigidBodyCon_spring_damping_z_set(PointerRNA *ptr, float value) rbc->spring_damping_z = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_Z)) { - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, value); - } + rna_RigidBodyCon_do_set_spring_damping(rbc, value, RBC_FLAG_USE_SPRING_Z, RB_LIMIT_LIN_Z); #endif } @@ -589,9 +617,7 @@ static void rna_RigidBodyCon_spring_damping_ang_x_set(PointerRNA *ptr, float val rbc->spring_damping_ang_x = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_X)) { - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, value); - } + rna_RigidBodyCon_do_set_spring_damping(rbc, value, RBC_FLAG_USE_SPRING_ANG_X, RB_LIMIT_ANG_X); #endif } @@ -601,9 +627,7 @@ static void rna_RigidBodyCon_spring_damping_ang_y_set(PointerRNA *ptr, float val rbc->spring_damping_ang_y = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_Y)) { - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, value); - } + rna_RigidBodyCon_do_set_spring_damping(rbc, value, RBC_FLAG_USE_SPRING_ANG_Y, RB_LIMIT_ANG_Y); #endif } @@ -613,9 +637,7 @@ static void rna_RigidBodyCon_spring_damping_ang_z_set(PointerRNA *ptr, float val rbc->spring_damping_ang_z = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_Z)) { - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, value); - } + rna_RigidBodyCon_do_set_spring_damping(rbc, value, RBC_FLAG_USE_SPRING_ANG_Z, RB_LIMIT_ANG_Z); #endif } @@ -1031,6 +1053,14 @@ static void rna_def_rigidbody_constraint(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + prop = RNA_def_property(srna, "spring_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "spring_type"); + RNA_def_property_enum_items(prop, rna_enum_rigidbody_constraint_spring_type_items); + RNA_def_property_enum_funcs(prop, NULL, "rna_RigidBodyCon_spring_type_set", NULL); + RNA_def_property_ui_text(prop, "Spring Type", "Which implementation of spring to use"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_ENABLED); RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyCon_enabled_set"); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 339d3841b30..915018612a1 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -165,6 +165,14 @@ const EnumPropertyItem rna_enum_mesh_select_mode_items[] = { {0, NULL, 0, NULL, NULL} }; +const EnumPropertyItem rna_enum_mesh_select_mode_uv_items[] = { + {UV_SELECT_VERTEX, "VERTEX", ICON_UV_VERTEXSEL, "Vertex", "Vertex selection mode"}, + {UV_SELECT_EDGE, "EDGE", ICON_UV_EDGESEL, "Edge", "Edge selection mode"}, + {UV_SELECT_FACE, "FACE", ICON_UV_FACESEL, "Face", "Face selection mode"}, + {UV_SELECT_ISLAND, "ISLAND", ICON_UV_ISLANDSEL, "Island", "Island selection mode"}, + {0, NULL, 0, NULL, NULL} +}; + const EnumPropertyItem rna_enum_snap_element_items[] = { {SCE_SNAP_MODE_INCREMENT, "INCREMENT", ICON_SNAP_INCREMENT, "Increment", "Snap to increments of grid"}, {SCE_SNAP_MODE_VERTEX, "VERTEX", ICON_SNAP_VERTEX, "Vertex", "Snap to vertices"}, @@ -2024,11 +2032,6 @@ static void rna_Stereo3dFormat_update(Main *bmain, Scene *UNUSED(scene), Pointer } } -static bool rna_gpu_is_hq_supported_get(PointerRNA *UNUSED(ptr)) -{ - return true; -} - static ViewLayer *rna_ViewLayer_new( ID *id, Scene *UNUSED(sce), Main *bmain, const char *name) { @@ -2409,14 +2412,6 @@ static void rna_def_tool_settings(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - static const EnumPropertyItem uv_select_mode_items[] = { - {UV_SELECT_VERTEX, "VERTEX", ICON_UV_VERTEXSEL, "Vertex", "Vertex selection mode"}, - {UV_SELECT_EDGE, "EDGE", ICON_UV_EDGESEL, "Edge", "Edge selection mode"}, - {UV_SELECT_FACE, "FACE", ICON_UV_FACESEL, "Face", "Face selection mode"}, - {UV_SELECT_ISLAND, "ISLAND", ICON_UV_ISLANDSEL, "Island", "Island selection mode"}, - {0, NULL, 0, NULL, NULL} - }; - /* the construction of this enum is quite special - everything is stored as bitflags, * with 1st position only for for on/off (and exposed as boolean), while others are mutually * exclusive options but which will only have any effect when autokey is enabled @@ -2811,7 +2806,7 @@ static void rna_def_tool_settings(BlenderRNA *brna) /* UV */ prop = RNA_def_property(srna, "uv_select_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "uv_selectmode"); - RNA_def_property_enum_items(prop, uv_select_mode_items); + RNA_def_property_enum_items(prop, rna_enum_mesh_select_mode_uv_items); RNA_def_property_ui_text(prop, "UV Selection Mode", "UV selection and display mode"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL); @@ -4092,6 +4087,7 @@ static void rna_def_gpu_dof_fx(BlenderRNA *brna) prop = RNA_def_property(srna, "fstop", PROP_FLOAT, PROP_NONE); RNA_def_property_ui_text(prop, "F-stop", "F-stop for dof effect"); + RNA_def_property_float_default(prop, 128.0f); RNA_def_property_range(prop, 0.0f, FLT_MAX); RNA_def_property_ui_range(prop, 0.1f, 128.0f, 10, 1); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update"); @@ -4110,21 +4106,10 @@ static void rna_def_gpu_dof_fx(BlenderRNA *brna) prop = RNA_def_property(srna, "ratio", PROP_FLOAT, PROP_NONE); RNA_def_property_ui_text(prop, "Ratio", "Distortion to simulate anamorphic lens bokeh"); + RNA_def_property_float_default(prop, 1.0f); RNA_def_property_range(prop, 0.0000001f, FLT_MAX); RNA_def_property_ui_range(prop, 1.0f, 2.0f, 0.1, 3); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - - prop = RNA_def_property(srna, "use_high_quality", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "high_quality", 1); - RNA_def_property_ui_text(prop, "High Quality", "Use high quality depth of field"); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update"); - - /* NOTE: high quality is always supported */ - prop = RNA_def_property(srna, "is_hq_supported", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_funcs(prop, "rna_gpu_is_hq_supported_get", NULL); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "High Quality", "Use high quality depth of field"); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); } static void rna_def_gpu_ssao_fx(BlenderRNA *brna) @@ -4255,6 +4240,7 @@ static void rna_def_scene_render_view(BlenderRNA *brna) prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "viewflag", SCE_VIEW_DISABLE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Enabled", "Disable or enable the render view"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); } @@ -4793,10 +4779,10 @@ static void rna_def_scene_render_data(BlenderRNA *brna) }; static const EnumPropertyItem display_mode_items[] = { - {R_OUTPUT_SCREEN, "SCREEN", 0, "Full Screen", "Images are rendered in full Screen"}, - {R_OUTPUT_AREA, "AREA", 0, "Image Editor", "Images are rendered in Image Editor"}, - {R_OUTPUT_WINDOW, "WINDOW", 0, "New Window", "Images are rendered in new Window"}, - {R_OUTPUT_NONE, "NONE", 0, "Keep UI", "Images are rendered without forcing UI changes"}, + {R_OUTPUT_SCREEN, "SCREEN", 0, "Full Screen", "Images are rendered in a maximized Image Editor"}, + {R_OUTPUT_AREA, "AREA", 0, "Image Editor", "Images are rendered in an Image Editor"}, + {R_OUTPUT_WINDOW, "WINDOW", 0, "New Window", "Images are rendered in a new window"}, + {R_OUTPUT_NONE, "NONE", 0, "Keep User Interface", "Images are rendered without changing the user interface"}, {0, NULL, 0, NULL, NULL} }; @@ -4809,7 +4795,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) }; static const EnumPropertyItem pixel_size_items[] = { - {0, "AUTO", 0, "Automatic", "Automatic pixel size, depends on the UI scale"}, + {0, "AUTO", 0, "Automatic", "Automatic pixel size, depends on the user interface scale"}, {1, "1", 0, "1x", "Render at full resolution"}, {2, "2", 0, "2x", "Render at 50% resolution"}, {4, "4", 0, "4x", "Render at 25% resolution"}, @@ -5411,7 +5397,8 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop = RNA_def_property(srna, "use_single_layer", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_SINGLE_LAYER); - RNA_def_property_ui_text(prop, "Render Single Layer", "Only render the active layer"); + RNA_def_property_ui_text(prop, "Render Single Layer", "Only render the active layer. Only affects rendering from the interface, ignored for rendering from command line"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); /* views (stereoscopy et al) */ @@ -6015,12 +6002,6 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Volumetric Shadow Samples", "Number of samples to compute volumetric shadowing"); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "use_volumetric_colored_transmittance", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_VOLUMETRIC_COLORED); - RNA_def_property_boolean_default(prop, 1); - RNA_def_property_ui_text(prop, "Colored Transmittance", "Enable wavelength dependent volumetric transmittance"); - RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); - /* Ambient Occlusion */ prop = RNA_def_property(srna, "use_gtao", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_GTAO_ENABLED); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 6e45e52764e..1bdaa569604 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2436,6 +2436,15 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; + static const EnumPropertyItem background_type_items[] = { + {V3D_SHADING_BACKGROUND_THEME, "THEME", 0, "Theme", "Use the theme for background color"}, + {V3D_SHADING_BACKGROUND_WORLD, "WORLD", 0, "World", "Use the world for background color"}, + {V3D_SHADING_BACKGROUND_VIEWPORT, "VIEWPORT", 0, "Viewport", "Use a custom color limited to this viewport only"}, + {0, NULL, 0, NULL, NULL} + }; + static const float default_background_color[] = {0.05f, 0.05f, 0.05f}; + + /* Note these settings are used for both 3D viewport and the OpenGL render * engine in the scene, so can't assume to always be part of a screen. */ srna = RNA_def_struct(brna, "View3DShading", NULL); @@ -2523,6 +2532,18 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "background_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, background_type_items); + RNA_def_property_ui_text(prop, "Background", "Way to draw the background"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "background_color", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_float_array_default(prop, default_background_color); + RNA_def_property_ui_text(prop, "Background Color", "Color for custom background color"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "show_shadows", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_SHADOW); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -2966,11 +2987,6 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Lock Camera to View", "Enable view navigation within the camera view"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - prop = RNA_def_property(srna, "show_world", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag3", V3D_SHOW_WORLD); - RNA_def_property_ui_text(prop, "World Background", "Display world colors in the background"); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - prop = RNA_def_property(srna, "use_occlude_geometry", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_ZBUF_SELECT); RNA_def_property_ui_text(prop, "Occlude Geometry", "Limit selection to visible (clipped with depth buffer)"); diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c index f4dc07cf6c3..fe561cdef1c 100644 --- a/source/blender/makesrna/intern/rna_world.c +++ b/source/blender/makesrna/intern/rna_world.c @@ -199,6 +199,8 @@ void RNA_def_world(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; + static float default_world_color[] = {0.05f, 0.05f, 0.05f}; + srna = RNA_def_struct(brna, "World", "ID"); RNA_def_struct_ui_text(srna, "World", "World data-block describing the environment and ambient lighting of a scene"); @@ -210,6 +212,7 @@ void RNA_def_world(BlenderRNA *brna) prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR); RNA_def_property_float_sdna(prop, NULL, "horr"); RNA_def_property_array(prop, 3); + RNA_def_property_float_array_default(prop, default_world_color); RNA_def_property_ui_text(prop, "Color", "Color of the background"); /* RNA_def_property_update(prop, 0, "rna_World_update"); */ /* render-only uses this */ diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index a06a63c8067..6a40f22d9df 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -1127,23 +1127,17 @@ PyDoc_STRVAR(Vector_project_doc, static PyObject *Vector_project(VectorObject *self, PyObject *value) { const int size = self->size; - float tvec[MAX_DIMENSIONS]; - float vec[MAX_DIMENSIONS]; + float *tvec; double dot = 0.0f, dot2 = 0.0f; int x; - if (mathutils_array_parse(tvec, size, size, value, "Vector.project(other), invalid 'other' arg") == -1) + if (BaseMath_ReadCallback(self) == -1) return NULL; - if (self->size > 4) { - PyErr_SetString(PyExc_ValueError, - "Vector must be 2D, 3D or 4D"); + if (mathutils_array_parse_alloc(&tvec, size, value, "Vector.project(other), invalid 'other' arg") == -1) { return NULL; } - if (BaseMath_ReadCallback(self) == -1) - return NULL; - /* get dot products */ for (x = 0; x < size; x++) { dot += (double)(self->vec[x] * tvec[x]); @@ -1152,9 +1146,9 @@ static PyObject *Vector_project(VectorObject *self, PyObject *value) /* projection */ dot /= dot2; for (x = 0; x < size; x++) { - vec[x] = (float)dot * tvec[x]; + tvec[x] *= (float)dot; } - return Vector_CreatePyObject(vec, size, Py_TYPE(self)); + return Vector_CreatePyObject_alloc(tvec, size, Py_TYPE(self)); } PyDoc_STRVAR(Vector_lerp_doc, diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h index 3096949b49f..ab7eee128f0 100644 --- a/source/blender/render/intern/include/render_result.h +++ b/source/blender/render/intern/include/render_result.h @@ -123,7 +123,7 @@ bool render_result_has_views(struct RenderResult *rr); iter_ != NULL; \ iter_ = iter_->next, nr_++) \ { \ - if ((re_)->r.scemode & R_SINGLE_LAYER) { \ + if (!G.background && (re_)->r.scemode & R_SINGLE_LAYER) { \ if (nr_ != re->active_view_layer) { \ continue; \ } \ diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h index 547028c88f9..2e84140707d 100644 --- a/source/blender/windowmanager/WM_keymap.h +++ b/source/blender/windowmanager/WM_keymap.h @@ -70,6 +70,10 @@ wmKeyMapItem *WM_keymap_add_panel(struct wmKeyMap *keymap, const char *idname, i wmKeyMapItem *WM_keymap_add_tool(struct wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier); +void WM_keymap_add_context_enum_set_items( + wmKeyMap *keymap, const struct EnumPropertyItem *items, const char *data_path, + int type_start, int val, int modifier, int keymodifier); + bool WM_keymap_remove_item(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi); int WM_keymap_item_to_string(wmKeyMapItem *kmi, const bool compact, char *result, const int result_len); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index a5536dbd652..60dd9ad2e72 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -585,6 +585,12 @@ typedef struct wmOperatorType { * that the operator might still fail to execute even if this return true */ bool (*poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT; + /* Use to check of properties should be displayed in auto-generated UI. + * Use 'check' callback to enforce refreshing. */ + bool (*poll_property)( + const struct bContext *C, struct wmOperator *op, + const PropertyRNA *prop) ATTR_WARN_UNUSED_RESULT; + /* optional panel for redo and repeat, autogenerated if not set */ void (*ui)(struct bContext *, struct wmOperator *); diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index f92cc511449..7247529d02d 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -223,65 +223,6 @@ void WM_operator_handlers_clear(wmWindowManager *wm, wmOperatorType *ot) } } -/* ************ uiListType handling ************** */ - -static GHash *uilisttypes_hash = NULL; - -uiListType *WM_uilisttype_find(const char *idname, bool quiet) -{ - uiListType *ult; - - if (idname[0]) { - ult = BLI_ghash_lookup(uilisttypes_hash, idname); - if (ult) { - return ult; - } - } - - if (!quiet) { - printf("search for unknown uilisttype %s\n", idname); - } - - return NULL; -} - -bool WM_uilisttype_add(uiListType *ult) -{ - BLI_ghash_insert(uilisttypes_hash, ult->idname, ult); - return 1; -} - -void WM_uilisttype_freelink(uiListType *ult) -{ - bool ok; - - ok = BLI_ghash_remove(uilisttypes_hash, ult->idname, NULL, MEM_freeN); - - BLI_assert(ok); - (void)ok; -} - -/* called on initialize WM_init() */ -void WM_uilisttype_init(void) -{ - uilisttypes_hash = BLI_ghash_str_new_ex("uilisttypes_hash gh", 16); -} - -void WM_uilisttype_free(void) -{ - GHashIterator gh_iter; - - GHASH_ITER (gh_iter, uilisttypes_hash) { - uiListType *ult = BLI_ghashIterator_getValue(&gh_iter); - if (ult->ext.free) { - ult->ext.free(ult->ext.data); - } - } - - BLI_ghash_free(uilisttypes_hash, NULL, MEM_freeN); - uilisttypes_hash = NULL; -} - /* ****************************************** */ void WM_keymap_init(bContext *C) diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index c191255cd21..042bd8823c4 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -279,6 +279,10 @@ static void wm_window_match_replace_by_file_wm( wm->initialized = 0; wm->winactive = NULL; + /* Clearing drawable of before deleting any context + * to avoid clearing the wrong wm. */ + wm_window_clear_drawable(oldwm); + /* only first wm in list has ghostwins */ for (wmWindow *win = wm->windows.first; win; win = win->next) { for (wmWindow *oldwin = oldwm->windows.first; oldwin; oldwin = oldwin->next) { @@ -488,13 +492,7 @@ static void wm_file_read_post(bContext *C, const bool is_startup_file, const boo Main *bmain = CTX_data_main(C); DEG_on_visible_update(bmain, true); - - if (!is_startup_file) { - /* When starting up, the UI hasn't been fully initialised yet, and - * this call can trigger icon updates, causing a segfault due to a - * not-yet-initialised ghash for the icons. */ - wm_event_do_depsgraph(C); - } + wm_event_do_depsgraph(C); ED_editors_init(C); diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index c51d4c5534a..4b0d751a7ce 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -115,6 +115,7 @@ #include "ED_undo.h" #include "UI_interface.h" +#include "UI_resources.h" #include "BLF_api.h" #include "BLT_lang.h" @@ -237,6 +238,11 @@ void WM_init(bContext *C, int argc, const char **argv) BLF_init(); BLT_lang_init(); + /* Init icons before reading .blend files for preview icons, which can + * get triggered by the depsgraph. This is also done in background mode + * for scripts that do background processing with preview icons. */ + BKE_icons_init(BIFICONID_LAST); + /* reports cant be initialized before the wm, * but keep before file reading, since that may report errors */ wm_init_reports(C); @@ -259,13 +265,6 @@ void WM_init(bContext *C, int argc, const char **argv) UI_init(); BKE_studiolight_init(); } - else { - /* Note: Currently only inits icons, which we now want in background mode too - * (scripts could use those in background processing...). - * In case we do more later, we may need to pass a 'background' flag. - * Called from 'UI_init' above */ - BKE_icons_init(1); - } ED_spacemacros_init(); diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index a95ccf36fdb..6815ff4413a 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -526,6 +526,25 @@ wmKeyMapItem *WM_keymap_add_tool(wmKeyMap *keymap, const char *idname, int type, return kmi; } +/** Useful for mapping numbers to an enum. */ +void WM_keymap_add_context_enum_set_items( + wmKeyMap *keymap, const EnumPropertyItem *items, const char *data_path, + int type_start, int val, int modifier, int keymodifier) +{ + for (int i = 0, type_offset = 0; items[i].identifier; i++) { + if (items[i].identifier[0] == '\0') { + continue; + } + wmKeyMapItem *kmi = WM_keymap_add_item( + keymap, "WM_OT_context_set_enum", + type_start + type_offset, val, modifier, keymodifier); + RNA_string_set(kmi->ptr, "data_path", data_path); + RNA_string_set(kmi->ptr, "value", items[i].identifier); + type_offset += 1; + } +} + + bool WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi) { if (BLI_findindex(&keymap->items, kmi) != -1) { diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index e757c7bee52..df869ba6b68 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1043,15 +1043,17 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) if (op->type->flag & OPTYPE_MACRO) { for (op = op->macro.first; op; op = op->next) { - uiTemplateOperatorPropertyButs(C, layout, op, NULL, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN, - UI_TEMPLATE_OP_PROPS_SHOW_TITLE); + uiTemplateOperatorPropertyButs( + C, layout, op, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN, + UI_TEMPLATE_OP_PROPS_SHOW_TITLE); if (op->next) uiItemS(layout); } } else { - uiTemplateOperatorPropertyButs(C, layout, op, NULL, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN, - UI_TEMPLATE_OP_PROPS_SHOW_TITLE); + uiTemplateOperatorPropertyButs( + C, layout, op, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN, + UI_TEMPLATE_OP_PROPS_SHOW_TITLE); } UI_block_bounds_set_popup(block, 4, 0, 0); @@ -1120,8 +1122,9 @@ 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); - uiTemplateOperatorPropertyButs(C, layout, op, NULL, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN, - UI_TEMPLATE_OP_PROPS_SHOW_TITLE); + uiTemplateOperatorPropertyButs( + C, layout, op, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN, + UI_TEMPLATE_OP_PROPS_SHOW_TITLE); /* clear so the OK button is left alone */ UI_block_func_set(block, NULL, NULL, NULL); @@ -1160,7 +1163,7 @@ 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); /* since ui is defined the auto-layout args are not used */ - uiTemplateOperatorPropertyButs(C, layout, op, NULL, UI_BUT_LABEL_ALIGN_COLUMN, 0); + uiTemplateOperatorPropertyButs(C, layout, op, UI_BUT_LABEL_ALIGN_COLUMN, 0); UI_block_func_set(block, NULL, NULL, NULL); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index c1006db34ef..dd4013efdf2 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -123,7 +123,6 @@ static struct WMInitStruct { /* ******** win open & close ************ */ static void wm_window_set_drawable(wmWindowManager *wm, wmWindow *win, bool activate); -static void wm_window_clear_drawable(wmWindowManager *wm); /* XXX this one should correctly check for apple top header... * done for Cocoa : returns window contents (and not frame) max size*/ @@ -202,7 +201,6 @@ static void wm_ghostwindow_destroy(wmWindowManager *wm, wmWindow *win) GHOST_DisposeWindow(g_system, win->ghostwin); win->ghostwin = NULL; win->gpuctx = NULL; - } } @@ -1103,7 +1101,7 @@ static void wm_window_set_drawable(wmWindowManager *wm, wmWindow *win, bool acti immActivate(); } -static void wm_window_clear_drawable(wmWindowManager *wm) +void wm_window_clear_drawable(wmWindowManager *wm) { if (wm->windrawable) { BLF_batch_reset(); @@ -2169,7 +2167,12 @@ ViewLayer *WM_window_get_active_view_layer(const wmWindow *win) return view_layer; } - return BKE_view_layer_default_view(scene); + view_layer = BKE_view_layer_default_view(scene); + if (view_layer) { + WM_window_set_active_view_layer((wmWindow*)win, view_layer); + } + + return view_layer; } void WM_window_set_active_view_layer(wmWindow *win, ViewLayer *view_layer) diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h index 385d61217ad..4fd5d66fb43 100644 --- a/source/blender/windowmanager/wm_window.h +++ b/source/blender/windowmanager/wm_window.h @@ -57,6 +57,7 @@ void wm_window_ghostwindows_remove_invalid(bContext *C, wmWindowManager *wm); void wm_window_process_events (const bContext *C); void wm_window_process_events_nosleep(void); +void wm_window_clear_drawable(wmWindowManager *wm); void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win); void wm_window_reset_drawable(void); diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index da5dcf9ff8b..283585598bf 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -1448,6 +1448,16 @@ static int arg_handle_scene_set(int argc, const char **argv, void *data) Scene *scene = BKE_scene_set_name(CTX_data_main(C), argv[1]); if (scene) { CTX_data_scene_set(C, scene); + + /* Set the scene of the first window, see: T55991, + * otherwise scrips that run later won't get this scene back from the context. */ + wmWindow *win = CTX_wm_window(C); + if (win == NULL) { + win = CTX_wm_manager(C)->windows.first; + } + if (win != NULL) { + WM_window_set_active_scene(CTX_data_main(C), C, win, scene); + } } return 1; } |