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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Tönne <lukas.toenne@gmail.com>2018-01-28 15:34:02 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2018-01-28 16:18:10 +0300
commit49c19ca679ea89209a18374d51377084f378f289 (patch)
tree7111a90a709920ed09386d0f1e8c00aaa8905ad7 /source/blender
parente15dd419d43182f9b826210e9ae90803cb7626a4 (diff)
parentdfbe4153721b6764a41c2e8de8f41c6cdab6fe7e (diff)
Merge branch 'blender2.8' into hair_guides
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_bvhutils.h4
-rw-r--r--source/blender/blenkernel/BKE_idprop.h10
-rw-r--r--source/blender/blenkernel/BKE_layer.h1
-rw-r--r--source/blender/blenkernel/BKE_library.h6
-rw-r--r--source/blender/blenkernel/BKE_node.h2
-rw-r--r--source/blender/blenkernel/intern/collection.c12
-rw-r--r--source/blender/blenkernel/intern/idprop.c11
-rw-r--r--source/blender/blenkernel/intern/layer.c8
-rw-r--r--source/blender/blenkernel/intern/library_query.c4
-rw-r--r--source/blender/blenkernel/intern/library_remap.c6
-rw-r--r--source/blender/blenkernel/intern/lightprobe.c1
-rw-r--r--source/blender/blenkernel/intern/modifier.c7
-rw-r--r--source/blender/blenkernel/intern/node.c21
-rw-r--r--source/blender/blenkernel/intern/object_update.c8
-rw-r--r--source/blender/blenkernel/intern/screen.c3
-rw-r--r--source/blender/blenkernel/intern/sequencer.c3
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c2
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c97
-rw-r--r--source/blender/blenlib/BLI_task.h4
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c45
-rw-r--r--source/blender/blenlib/intern/math_base_inline.c2
-rw-r--r--source/blender/blenloader/intern/readfile.c11
-rw-r--r--source/blender/blenloader/intern/versioning_280.c8
-rw-r--r--source/blender/blenloader/intern/writefile.c8
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c2
-rw-r--r--source/blender/collada/ArmatureImporter.cpp7
-rw-r--r--source/blender/collada/ArmatureImporter.h3
-rw-r--r--source/blender/collada/DocumentImporter.cpp17
-rw-r--r--source/blender/collada/DocumentImporter.h1
-rw-r--r--source/blender/collada/EffectExporter.cpp2
-rw-r--r--source/blender/collada/MeshImporter.cpp8
-rw-r--r--source/blender/collada/MeshImporter.h4
-rw-r--r--source/blender/collada/SkinInfo.cpp4
-rw-r--r--source/blender/collada/SkinInfo.h2
-rw-r--r--source/blender/collada/collada_utils.cpp5
-rw-r--r--source/blender/collada/collada_utils.h2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc32
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_iter.cc51
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc80
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc163
-rw-r--r--source/blender/draw/CMakeLists.txt1
-rw-r--r--source/blender/draw/engines/clay/clay_engine.c29
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c17
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c11
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c247
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c158
-rw-r--r--source/blender/draw/engines/eevee/eevee_occlusion.c45
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h120
-rw-r--r--source/blender/draw/engines/eevee/eevee_screen_raytrace.c72
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c31
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c204
-rw-r--r--source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl11
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl13
-rw-r--r--source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl55
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl39
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl6
-rw-r--r--source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl9
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl7
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl24
-rw-r--r--source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl5
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl28
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl22
-rw-r--r--source/blender/draw/intern/DRW_render.h1
-rw-r--r--source/blender/draw/intern/draw_cache.c204
-rw-r--r--source/blender/draw/intern/draw_cache.h2
-rw-r--r--source/blender/draw/intern/draw_manager.c14
-rw-r--r--source/blender/draw/modes/object_mode.c31
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt500
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c6
-rw-r--r--source/blender/editors/include/ED_view3d.h9
-rw-r--r--source/blender/editors/include/UI_icons.h7
-rw-r--r--source/blender/editors/include/UI_interface.h4
-rw-r--r--source/blender/editors/interface/interface_handlers.c72
-rw-r--r--source/blender/editors/interface/interface_ops.c2
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c4
-rw-r--r--source/blender/editors/interface/view2d_ops.c3
-rw-r--r--source/blender/editors/io/io_collada.c3
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c12
-rw-r--r--source/blender/editors/mesh/mesh_navmesh.c5
-rw-r--r--source/blender/editors/object/object_add.c17
-rw-r--r--source/blender/editors/object/object_relations.c6
-rw-r--r--source/blender/editors/render/render_shading.c3
-rw-r--r--source/blender/editors/screen/screen_draw.c8
-rw-r--r--source/blender/editors/screen/screen_ops.c88
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c9
-rw-r--r--source/blender/editors/space_action/action_select.c6
-rw-r--r--source/blender/editors/space_graph/graph_edit.c3
-rw-r--r--source/blender/editors/space_graph/graph_select.c6
-rw-r--r--source/blender/editors/space_image/image_ops.c2
-rw-r--r--source/blender/editors/space_nla/nla_select.c3
-rw-r--r--source/blender/editors/space_node/drawnode.c12
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c94
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c8
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h9
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c163
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c20
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_view3d/drawobject.c7
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_camera_control.c7
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c15
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c1139
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h11
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_navigate.c94
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_ruler.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c1436
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c700
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c7
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c89
-rw-r--r--source/blender/gpu/intern/gpu_batch.c30
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl7
-rw-r--r--source/blender/imbuf/intern/IMB_anim.h4
-rw-r--r--source/blender/imbuf/intern/anim_movie.c23
-rw-r--r--source/blender/imbuf/intern/cineon/dpxlib.c2
-rw-r--r--source/blender/makesdna/DNA_layer_types.h4
-rw-r--r--source/blender/makesdna/DNA_lightprobe_types.h4
-rw-r--r--source/blender/makesdna/DNA_screen_types.h4
-rw-r--r--source/blender/makesrna/intern/rna_layer.c23
-rw-r--r--source/blender/makesrna/intern/rna_lightprobe.c7
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c2
-rw-r--r--source/blender/makesrna/intern/rna_scene.c6
-rw-r--r--source/blender/makesrna/intern/rna_wm_api.c7
-rw-r--r--source/blender/modifiers/intern/MOD_wireframe.c9
-rw-r--r--source/blender/nodes/CMakeLists.txt1
-rw-r--r--source/blender/nodes/NOD_shader.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h1
-rw-r--r--source/blender/nodes/intern/node_socket.c17
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c15
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bump.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_displacement.c65
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_material.c2
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h1
-rw-r--r--source/blender/render/intern/source/pipeline.c7
-rw-r--r--source/blender/render/intern/source/render_result.c19
-rw-r--r--source/blender/windowmanager/CMakeLists.txt1
-rw-r--r--source/blender/windowmanager/WM_api.h11
-rw-r--r--source/blender/windowmanager/WM_types.h17
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c37
-rw-r--r--source/blender/windowmanager/intern/wm_tooltip.c106
-rw-r--r--source/blender/windowmanager/manipulators/WM_manipulator_api.h12
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator.c25
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c4
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h5
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c86
153 files changed, 4474 insertions, 2801 deletions
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 27223afe4ff..ceb466ebdcd 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 3
+#define BLENDER_SUBVERSION 4
/* Several breakages with 270, e.g. constraint deg vs rad */
#define BLENDER_MINVERSION 270
#define BLENDER_MINSUBVERSION 6
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h
index cb72f0859d5..b3122f8adb9 100644
--- a/source/blender/blenkernel/BKE_bvhutils.h
+++ b/source/blender/blenkernel/BKE_bvhutils.h
@@ -46,7 +46,7 @@ struct MFace;
typedef struct LinkNode BVHCache;
/**
- * struct that kepts basic information about a BVHTree build from a editmesh
+ * Struct that stores basic information about a BVHTree built from a edit-mesh.
*/
typedef struct BVHTreeFromEditMesh {
struct BVHTree *tree;
@@ -66,7 +66,7 @@ typedef struct BVHTreeFromEditMesh {
} BVHTreeFromEditMesh;
/**
- * struct that kepts basic information about a BVHTree build from a mesh
+ * Struct that stores basic information about a BVHTree built from a mesh.
*/
typedef struct BVHTreeFromMesh {
struct BVHTree *tree;
diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h
index 055c530d255..02912739e86 100644
--- a/source/blender/blenkernel/BKE_idprop.h
+++ b/source/blender/blenkernel/BKE_idprop.h
@@ -32,6 +32,10 @@
#include "BLI_compiler_attrs.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct IDProperty;
struct ID;
@@ -119,6 +123,8 @@ void IDP_ClearProperty(IDProperty *prop);
void IDP_RelinkProperty(struct IDProperty *prop);
+void IDP_Reset(IDProperty *prop, const IDProperty *reference);
+
#define IDP_Int(prop) ((prop)->data.val)
#define IDP_Array(prop) ((prop)->data.pointer)
/* C11 const correctness for casts */
@@ -151,4 +157,8 @@ void IDP_RelinkProperty(struct IDProperty *prop);
void IDP_spit(IDProperty *prop);
#endif
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __BKE_IDPROP_H__ */
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
index 77f760a7843..b605b208f66 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -33,7 +33,6 @@
extern "C" {
#endif
-#define TODO_LAYER_SYNC_FILTER /* syncing of filter_objects across all trees */
#define TODO_LAYER_OVERRIDE /* CollectionOverride */
#define TODO_LAYER_OPERATORS /* collection mamanger and property panel operators */
#define TODO_LAYER /* generic todo */
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 30889b2f145..5abf9139226 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -51,9 +51,9 @@ struct PointerRNA;
struct PropertyRNA;
size_t BKE_libblock_get_alloc_info(short type, const char **name);
-void *BKE_libblock_alloc_notest(short type);
-void *BKE_libblock_alloc(struct Main *bmain, short type, const char *name, const int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void BKE_libblock_init_empty(struct ID *id);
+void *BKE_libblock_alloc_notest(short type) ATTR_WARN_UNUSED_RESULT;
+void *BKE_libblock_alloc(struct Main *bmain, short type, const char *name, const int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+void BKE_libblock_init_empty(struct ID *id) ATTR_NONNULL(1);
/**
* New ID creation/copying options.
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 3156749070e..4e30cb076d4 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -448,6 +448,7 @@ struct bNodeSocket *nodeInsertStaticSocket(struct bNodeTree *ntree, struct bNode
struct bNodeSocket *next_sock, const char *identifier, const char *name);
void nodeRemoveSocket(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock);
void nodeRemoveAllSockets(struct bNodeTree *ntree, struct bNode *node);
+void nodeModifySocketType(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, int type, int subtype);
struct bNode *nodeAddNode(const struct bContext *C, struct bNodeTree *ntree, const char *idname);
struct bNode *nodeAddStaticNode(const struct bContext *C, struct bNodeTree *ntree, int type);
@@ -799,6 +800,7 @@ struct ShadeResult;
#define SH_NODE_BSDF_PRINCIPLED 193
#define SH_NODE_EEVEE_SPECULAR 195
#define SH_NODE_BEVEL 197
+#define SH_NODE_DISPLACEMENT 198
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index edd29f793ec..ca77969ccaa 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -117,13 +117,9 @@ static void collection_free(SceneCollection *sc, const bool do_id_user)
for (LinkData *link = sc->objects.first; link; link = link->next) {
id_us_min(link->data);
}
- for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
- id_us_min(link->data);
- }
}
BLI_freelistN(&sc->objects);
- BLI_freelistN(&sc->filter_objects);
for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
collection_free(nsc, do_id_user);
@@ -265,13 +261,6 @@ void BKE_collection_copy_data(SceneCollection *sc_dst, SceneCollection *sc_src,
}
}
- BLI_duplicatelist(&sc_dst->filter_objects, &sc_src->filter_objects);
- if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
- for (LinkData *link = sc_dst->filter_objects.first; link; link = link->next) {
- id_us_plus(link->data);
- }
- }
-
BLI_duplicatelist(&sc_dst->scene_collections, &sc_src->scene_collections);
for (SceneCollection *nsc_src = sc_src->scene_collections.first, *nsc_dst = sc_dst->scene_collections.first;
nsc_src;
@@ -404,7 +393,6 @@ bool BKE_collection_object_remove(Main *bmain, ID *owner_id, SceneCollection *sc
BLI_remlink(&sc->objects, link);
MEM_freeN(link);
- TODO_LAYER_SYNC_FILTER; /* need to remove all instances of ob in scene collections -> filter_objects */
BKE_layer_sync_object_unlink(owner_id, sc, ob);
if (GS(owner_id->name) == ID_SCE) {
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index b00a62a1a87..33a665ba06e 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -1094,4 +1094,15 @@ void IDP_ClearProperty(IDProperty *prop)
prop->len = prop->totallen = 0;
}
+void IDP_Reset(IDProperty *prop, const IDProperty *reference)
+{
+ if (prop == NULL) {
+ return;
+ }
+ IDP_ClearProperty(prop);
+ if (reference != NULL) {
+ IDP_MergeGroup(prop, reference, true);
+ }
+}
+
/** \} */
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index c63cefbcd8c..c6515d0c47a 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -99,7 +99,7 @@ ViewLayer *BKE_view_layer_from_workspace_get(const struct Scene *scene, const st
/**
* This is a placeholder to know which areas of the code need to be addressed for the Workspace changes.
- * Never use this, you should either use BKE_view_layer_workspace_active or get ViewLayer explicitly.
+ * Never use this, you should either use BKE_view_layer_from_workspace_get or get ViewLayer explicitly.
*/
ViewLayer *BKE_view_layer_context_active_PLACEHOLDER(const Scene *scene)
{
@@ -1042,9 +1042,7 @@ static void layer_collection_object_add(ViewLayer *view_layer, LayerCollection *
{
Base *base = object_base_add(view_layer, ob);
- /* Only add an object once - prevent SceneCollection->objects and
- * SceneCollection->filter_objects to add the same object. */
-
+ /* Only add an object once. */
if (BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data))) {
return;
}
@@ -1085,7 +1083,6 @@ static void layer_collection_objects_populate(ViewLayer *view_layer, LayerCollec
static void layer_collection_populate(ViewLayer *view_layer, LayerCollection *lc, SceneCollection *sc)
{
layer_collection_objects_populate(view_layer, lc, &sc->objects);
- layer_collection_objects_populate(view_layer, lc, &sc->filter_objects);
for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
layer_collection_add(view_layer, lc, nsc);
@@ -1195,7 +1192,6 @@ void BKE_layer_sync_object_link(const ID *owner_id, SceneCollection *sc, Object
/**
* Remove the equivalent object base to all layers that have this collection
- * also remove all reference to ob in the filter_objects
*/
void BKE_layer_sync_object_unlink(const ID *owner_id, SceneCollection *sc, Object *ob)
{
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index fde8bd06563..da765ca45af 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -450,10 +450,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
for (LinkData *link = sc->objects.first; link; link = link->next) {
CALLBACK_INVOKE_ID(link->data, IDWALK_CB_USER);
}
-
- for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
- CALLBACK_INVOKE_ID(link->data, IDWALK_CB_USER);
- }
}
FOREACH_SCENE_COLLECTION_END
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index 8d1d657fbd9..87e45990a6c 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -207,9 +207,11 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
id->tag |= LIB_TAG_DOIT;
}
- /* Special hack in case it's Object->data and we are in edit mode (skipped_direct too). */
+ /* Special hack in case it's Object->data and we are in edit mode, and new_id is not NULL
+ * (otherwise, we follow common NEVER_NULL flags).
+ * (skipped_indirect too). */
if ((is_never_null && skip_never_null) ||
- (is_obj_editmode && (((Object *)id)->data == *id_p)) ||
+ (is_obj_editmode && (((Object *)id)->data == *id_p) && new_id != NULL) ||
(skip_indirect && is_indirect) ||
(is_reference && skip_reference))
{
diff --git a/source/blender/blenkernel/intern/lightprobe.c b/source/blender/blenkernel/intern/lightprobe.c
index d5dbbe873a2..057b6aaaf65 100644
--- a/source/blender/blenkernel/intern/lightprobe.c
+++ b/source/blender/blenkernel/intern/lightprobe.c
@@ -52,6 +52,7 @@ void BKE_lightprobe_init(LightProbe *probe)
probe->clipend = 40.0f;
probe->vis_bias = 1.0f;
probe->vis_blur = 0.2f;
+ probe->intensity = 1.0f;
probe->data_draw_size = 1.0f;
probe->flag = LIGHTPROBE_FLAG_SHOW_INFLUENCE | LIGHTPROBE_FLAG_SHOW_DATA;
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 8eb1a7733c1..8bfeacd256c 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -434,6 +434,11 @@ bool modifiers_isParticleEnabled(Object *ob)
return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
}
+/**
+ * Check whether is enabled.
+ *
+ * \param scene Current scene, may be NULL, in which case isDisabled callback of the modifier is never called.
+ */
bool modifier_isEnabled(struct Scene *scene, ModifierData *md, int required_mode)
{
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -441,7 +446,7 @@ bool modifier_isEnabled(struct Scene *scene, ModifierData *md, int required_mode
md->scene = scene;
if ((md->mode & required_mode) != required_mode) return false;
- if (mti->isDisabled && mti->isDisabled(md, required_mode == eModifierMode_Render)) return false;
+ if (scene != NULL && mti->isDisabled && mti->isDisabled(md, required_mode == eModifierMode_Render)) return false;
if (md->mode & eModifierMode_DisableTemporary) return false;
if ((required_mode & eModifierMode_Editmode) && !(mti->flags & eModifierTypeFlag_SupportsEditmode)) return false;
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index ab9e2665ff0..cac2aab26dd 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -506,6 +506,26 @@ static bNodeSocket *make_socket(bNodeTree *ntree, bNode *UNUSED(node), int in_ou
return sock;
}
+void nodeModifySocketType(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock,
+ int type, int subtype)
+{
+ const char *idname = nodeStaticSocketType(type, subtype);
+
+ if (!idname) {
+ printf("Error: static node socket type %d undefined\n", type);
+ return;
+ }
+
+ if (sock->default_value) {
+ MEM_freeN(sock->default_value);
+ sock->default_value = NULL;
+ }
+
+ sock->type = type;
+ BLI_strncpy(sock->idname, idname, sizeof(sock->idname));
+ node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(idname));
+}
+
bNodeSocket *nodeAddSocket(bNodeTree *ntree, bNode *node, int in_out, const char *idname,
const char *identifier, const char *name)
{
@@ -3569,6 +3589,7 @@ static void registerShaderNodes(void)
register_node_type_sh_attribute();
register_node_type_sh_bevel();
+ register_node_type_sh_displacement();
register_node_type_sh_geometry();
register_node_type_sh_light_path();
register_node_type_sh_light_falloff();
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index fb8aebe3004..99291b14b88 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -446,10 +446,14 @@ void BKE_object_eval_flush_base_flags(const EvaluationContext *UNUSED(eval_ctx),
Object *object, Base *base, bool is_from_set)
{
DEBUG_PRINT("%s on %s (%p)\n", __func__, object->id.name, object);
+
/* Make sure we have the base collection settings is already populated.
- * This will fail when BKE_layer_eval_layer_collection_pre hasn't run yet
- * Which usually means a missing call to DEG_id_tag_update(). */
+ * This will fail when BKE_layer_eval_layer_collection_pre hasn't run yet.
+ *
+ * Which usually means a missing call to DEG_id_tag_update(id, DEG_TAG_BASE_FLAGS_UPDATE).
+ * Either of the entire scene, or of the newly added objects.*/
BLI_assert(!BLI_listbase_is_empty(&base->collection_properties->data.group));
+
/* Copy flags and settings from base. */
object->base_flag = base->flag;
if (is_from_set) {
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 6bd88099792..754f59d2e33 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -429,6 +429,9 @@ void BKE_screen_free(bScreen *sc)
BLI_freelistN(&sc->areabase);
BKE_previewimg_free(&sc->preview);
+
+ /* Region and timer are freed by the window manager. */
+ MEM_SAFE_FREE(sc->tool_tip);
}
/* for depsgraph */
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 1b8939db185..424f4269f3c 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -4505,7 +4505,8 @@ Sequence *BKE_sequencer_foreground_frame_get(Scene *scene, int frame)
/* Only use strips that generate an image, not ones that combine
* other strips or apply some effect. */
if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_META, SEQ_TYPE_SCENE,
- SEQ_TYPE_MOVIE, SEQ_TYPE_COLOR, SEQ_TYPE_TEXT)) {
+ SEQ_TYPE_MOVIE, SEQ_TYPE_COLOR, SEQ_TYPE_TEXT))
+ {
if (seq->machine > best_machine) {
best_seq = seq;
best_machine = seq->machine;
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index 4e887d21f4f..618f495dbf1 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -175,7 +175,7 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
settings.userdata_chunk = &nearest;
settings.userdata_chunk_size = sizeof(nearest);
BLI_task_parallel_range(0, calc->numVerts,
- &data,shrinkwrap_calc_nearest_vertex_cb_ex,
+ &data, shrinkwrap_calc_nearest_vertex_cb_ex,
&settings);
free_bvhtree_from_mesh(&treeData);
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 5e2fb220327..1c3ff352126 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -67,6 +67,7 @@
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
+#include "BKE_modifier.h"
#include "BKE_multires.h"
#include "BKE_paint.h"
#include "BKE_scene.h"
@@ -1552,7 +1553,7 @@ static void ccgDM_copyFinalLoopArray(DerivedMesh *dm, MLoop *mloop)
BLI_edgehash_insert(ehash, medge[i].v1, medge[i].v2, SET_INT_IN_POINTER(i));
}
- atomic_cas_ptr((void**)&ccgdm->ehash, ccgdm->ehash, ehash);
+ atomic_cas_ptr((void **)&ccgdm->ehash, ccgdm->ehash, ehash);
}
BLI_mutex_unlock(&ccgdm->loops_cache_lock);
}
@@ -4190,7 +4191,7 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
CCGKey key;
- int numGrids, grid_pbvh;
+ int numGrids;
CCG_key_top_level(&key, ccgdm->ss);
@@ -4202,35 +4203,85 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
if (!ob->sculpt)
return NULL;
- /* In vwpaint, we always use a grid_pbvh for multires/subsurf */
- grid_pbvh = (!(ob->mode & OB_MODE_SCULPT) || ccgDM_use_grid_pbvh(ccgdm));
+ bool grid_pbvh = ccgDM_use_grid_pbvh(ccgdm);
+ if ((ob->mode & OB_MODE_SCULPT) == 0) {
+ /* In vwpaint, we may use a grid_pbvh for multires/subsurf, under certain conditions.
+ * More complex cases break 'history' trail back to original vertices, in that case we fall back to
+ * deformed cage only (i.e. original deformed mesh). */
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
+
+ grid_pbvh = true;
+ bool has_one_ccg_modifier = false;
+ for (; md; md = md->next) {
+ /* We can only accept to use this ccgdm if:
+ * - it's the only active ccgdm in the stack.
+ * - there is no topology-modifying modifier in the stack.
+ * Otherwise, there is no way to map back to original geometry from grid-generated PBVH.
+ */
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+
+ if (!modifier_isEnabled(NULL, md, eModifierMode_Realtime)) {
+ continue;
+ }
+ if (ELEM(mti->type, eModifierTypeType_OnlyDeform, eModifierTypeType_NonGeometrical)) {
+ continue;
+ }
+
+ if (ELEM(md->type, eModifierType_Subsurf, eModifierType_Multires)) {
+ if (has_one_ccg_modifier) {
+ /* We only allow a single active ccg modifier in the stack. */
+ grid_pbvh = false;
+ break;
+ }
+ has_one_ccg_modifier = true;
+ continue;
+ }
+
+ /* Any other non-deforming modifier makes it impossible to use grid pbvh. */
+ grid_pbvh = false;
+ break;
+ }
+ }
if (ob->sculpt->pbvh) {
+ /* Note that we have to clean up exisitng pbvh instead of updating it in case it does not match current
+ * grid_pbvh status. */
if (grid_pbvh) {
- /* pbvh's grids, gridadj and gridfaces points to data inside ccgdm
- * but this can be freed on ccgdm release, this updates the pointers
- * when the ccgdm gets remade, the assumption is that the topology
- * does not change. */
- ccgdm_create_grids(dm);
- BKE_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, (void **)ccgdm->gridFaces,
- ccgdm->gridFlagMats, ccgdm->gridHidden);
+ if (BKE_pbvh_get_ccgdm(ob->sculpt->pbvh) != NULL) {
+ /* pbvh's grids, gridadj and gridfaces points to data inside ccgdm
+ * but this can be freed on ccgdm release, this updates the pointers
+ * when the ccgdm gets remade, the assumption is that the topology
+ * does not change. */
+ ccgdm_create_grids(dm);
+ BKE_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, (void **)ccgdm->gridFaces,
+ ccgdm->gridFlagMats, ccgdm->gridHidden);
+ }
+ else {
+ BKE_pbvh_free(ob->sculpt->pbvh);
+ ob->sculpt->pbvh = NULL;
+ }
+ }
+ else if (BKE_pbvh_get_ccgdm(ob->sculpt->pbvh) != NULL) {
+ BKE_pbvh_free(ob->sculpt->pbvh);
+ ob->sculpt->pbvh = NULL;
}
ccgdm->pbvh = ob->sculpt->pbvh;
}
if (ccgdm->pbvh) {
- /* For vertex paint, keep track of ccgdm */
- if (!(ob->mode & OB_MODE_SCULPT)) {
+ /* For grid pbvh, keep track of ccgdm */
+ if (grid_pbvh) {
BKE_pbvh_set_ccgdm(ccgdm->pbvh, ccgdm);
}
return ccgdm->pbvh;
}
- /* no pbvh exists yet, we need to create one. only in case of multires
+ /* No pbvh exists yet, we need to create one. only in case of multires
* we build a pbvh over the modified mesh, in other cases the base mesh
* is being sculpted, so we build a pbvh from that. */
- /* Note: vwpaint always builds a pbvh over the modified mesh. */
+ /* Note: vwpaint tries to always build a pbvh over the modified mesh. */
if (grid_pbvh) {
ccgdm_create_grids(dm);
@@ -4256,6 +4307,18 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new();
BKE_pbvh_build_mesh(ccgdm->pbvh, me->mpoly, me->mloop, me->mvert, me->totvert, &me->vdata,
looptri, looptris_num);
+
+ if (ob->sculpt->modifiers_active && ob->derivedDeform != NULL) {
+ DerivedMesh *deformdm = ob->derivedDeform;
+ float (*vertCos)[3];
+ int totvert;
+
+ totvert = deformdm->getNumVerts(deformdm);
+ vertCos = MEM_malloc_arrayN(totvert, sizeof(float[3]), "ccgDM_getPBVH vertCos");
+ deformdm->getVertCos(deformdm, vertCos);
+ BKE_pbvh_apply_vertCos(ccgdm->pbvh, vertCos);
+ MEM_freeN(vertCos);
+ }
}
if (ccgdm->pbvh != NULL) {
@@ -4263,8 +4326,8 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
pbvh_show_mask_set(ccgdm->pbvh, ob->sculpt->show_mask);
}
- /* For vertex paint, keep track of ccgdm */
- if (!(ob->mode & OB_MODE_SCULPT) && ccgdm->pbvh) {
+ /* For grid pbvh, keep track of ccgdm. */
+ if (grid_pbvh && ccgdm->pbvh) {
BKE_pbvh_set_ccgdm(ccgdm->pbvh, ccgdm);
}
return ccgdm->pbvh;
diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h
index 1285e24e567..d03010af8d2 100644
--- a/source/blender/blenlib/BLI_task.h
+++ b/source/blender/blenlib/BLI_task.h
@@ -182,7 +182,7 @@ typedef struct ParallelRangeSettings {
} ParallelRangeSettings;
BLI_INLINE void BLI_parallel_range_settings_defaults(
- ParallelRangeSettings* settings);
+ ParallelRangeSettings *settings);
void BLI_task_parallel_range(
const int start, const int stop,
@@ -210,7 +210,7 @@ void BLI_task_parallel_mempool(
/* TODO(sergey): Think of a better place for this. */
BLI_INLINE void BLI_parallel_range_settings_defaults(
- ParallelRangeSettings* settings)
+ ParallelRangeSettings *settings)
{
memset(settings, 0, sizeof(*settings));
settings->use_threading = true;
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index 55667d19f76..9c055a227a9 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -875,7 +875,7 @@ static void non_recursive_bvh_div_nodes_task_cb(
* to use multithread building.
*
* To archive this is necessary to find how much leafs are accessible from a certain branch, BVHBuildHelper
- * implicit_needed_branches and implicit_leafs_index are auxiliary functions to solve that "optimal-split".
+ * #implicit_needed_branches and #implicit_leafs_index are auxiliary functions to solve that "optimal-split".
*/
static void non_recursive_bvh_div_nodes(
const BVHTree *tree, BVHNode *branches_array, BVHNode **leafs_array, int num_leafs)
@@ -888,24 +888,23 @@ static void non_recursive_bvh_div_nodes(
BVHBuildHelper data;
int depth;
-
- /* set parent from root node to NULL */
- BVHNode *tmp = &branches_array[0];
- tmp->parent = NULL;
-
- /* Most of bvhtree code relies on 1-leaf trees having at least one branch
- * We handle that special case here */
- if (num_leafs == 1) {
- BVHNode *root = &branches_array[0];
- refit_kdop_hull(tree, root, 0, num_leafs);
- root->main_axis = get_largest_axis(root->bv) / 2;
- root->totnode = 1;
- root->children[0] = leafs_array[0];
- root->children[0]->parent = root;
- return;
- }
- branches_array--; /* Implicit trees use 1-based indexs */
+ {
+ /* set parent from root node to NULL */
+ BVHNode *root = &branches_array[1];
+ root->parent = NULL;
+
+ /* Most of bvhtree code relies on 1-leaf trees having at least one branch
+ * We handle that special case here */
+ if (num_leafs == 1) {
+ refit_kdop_hull(tree, root, 0, num_leafs);
+ root->main_axis = get_largest_axis(root->bv) / 2;
+ root->totnode = 1;
+ root->children[0] = leafs_array[0];
+ root->children[0]->parent = root;
+ return;
+ }
+ }
build_implicit_tree_helper(tree, &data);
@@ -1053,9 +1052,6 @@ void BLI_bvhtree_free(BVHTree *tree)
void BLI_bvhtree_balance(BVHTree *tree)
{
- int i;
-
- BVHNode *branches_array = tree->nodearray + tree->totleaf;
BVHNode **leafs_array = tree->nodes;
/* This function should only be called once
@@ -1063,13 +1059,14 @@ void BLI_bvhtree_balance(BVHTree *tree)
BLI_assert(tree->totbranch == 0);
/* Build the implicit tree */
- non_recursive_bvh_div_nodes(tree, branches_array, leafs_array, tree->totleaf);
+ non_recursive_bvh_div_nodes(tree, tree->nodearray + (tree->totleaf - 1), leafs_array, tree->totleaf);
/* current code expects the branches to be linked to the nodes array
* we perform that linkage here */
tree->totbranch = implicit_needed_branches(tree->tree_type, tree->totleaf);
- for (i = 0; i < tree->totbranch; i++)
- tree->nodes[tree->totleaf + i] = branches_array + i;
+ for (int i = 0; i < tree->totbranch; i++) {
+ tree->nodes[tree->totleaf + i] = &tree->nodearray[tree->totleaf + i];
+ }
#ifdef USE_SKIP_LINKS
build_skip_links(tree, tree->nodes[tree->totleaf], NULL, NULL);
diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c
index a0c13e14e72..2f5b0f420b1 100644
--- a/source/blender/blenlib/intern/math_base_inline.c
+++ b/source/blender/blenlib/intern/math_base_inline.c
@@ -399,7 +399,7 @@ MINLINE int integer_digits_d(const double d)
MINLINE int integer_digits_i(const int i)
{
- return (int)log10(i) + 1;
+ return (int)log10((double)i) + 1;
}
/* Internal helpers for SSE2 implementation.
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 2e7d22cc4cd..9fd1c80a66a 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -5879,11 +5879,6 @@ static void lib_link_scene_collection(FileData *fd, Library *lib, SceneCollectio
BLI_assert(link->data);
}
- for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
- link->data = newlibadr_us(fd, lib, link->data);
- BLI_assert(link->data);
- }
-
for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
lib_link_scene_collection(fd, lib, nsc);
}
@@ -6168,7 +6163,6 @@ static void direct_link_view_settings(FileData *fd, ColorManagedViewSettings *vi
static void direct_link_scene_collection(FileData *fd, SceneCollection *sc)
{
link_list(fd, &sc->objects);
- link_list(fd, &sc->filter_objects);
link_list(fd, &sc->scene_collections);
for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
@@ -6702,6 +6696,7 @@ static void lib_link_screen(FileData *fd, Main *main)
sc->scene = newlibadr(fd, sc->id.lib, sc->scene);
sc->animtimer = NULL; /* saved in rare cases */
+ sc->tool_tip = NULL;
sc->scrubbing = false;
for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
@@ -9999,10 +9994,6 @@ static void expand_scene_collection(FileData *fd, Main *mainvar, SceneCollection
expand_doit(fd, mainvar, link->data);
}
- for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
- expand_doit(fd, mainvar, link->data);
- }
-
for (SceneCollection *nsc= sc->scene_collections.first; nsc; nsc = nsc->next) {
expand_scene_collection(fd, mainvar, nsc);
}
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index b5530d90330..2f07ca43ff0 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -915,4 +915,12 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
}
+
+ {
+ if (!DNA_struct_elem_find(fd->filesdna, "LightProbe", "float", "intensity")) {
+ for (LightProbe *probe = main->lightprobe.first; probe; probe = probe->id.next) {
+ probe->intensity = 1.0f;
+ }
+ }
+ }
}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index ea305c72f01..3bd2f67ab86 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -710,8 +710,10 @@ static void write_iddata(void *wd, const ID *id)
static void write_previews(WriteData *wd, const PreviewImage *prv_orig)
{
- /* Never write previews when doing memsave (i.e. undo/redo)! */
- if (prv_orig && !wd->current) {
+ /* Note we write previews also for undo steps. It takes up some memory,
+ * but not doing so would causes all previews to be re-rendered after
+ * undo which is too expensive. */
+ if (prv_orig) {
PreviewImage prv = *prv_orig;
/* don't write out large previews if not requested */
@@ -2620,7 +2622,6 @@ static void write_scene_collection(WriteData *wd, SceneCollection *sc)
writestruct(wd, DATA, SceneCollection, 1, sc);
writelist(wd, DATA, LinkData, &sc->objects);
- writelist(wd, DATA, LinkData, &sc->filter_objects);
for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
write_scene_collection(wd, nsc);
@@ -3919,6 +3920,7 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
memset(fg.pad, 0, sizeof(fg.pad));
memset(fg.filename, 0, sizeof(fg.filename));
memset(fg.build_hash, 0, sizeof(fg.build_hash));
+ fg.pad1 = NULL;
current_screen_compat(mainvar, is_undo, &screen, &scene, &render_layer);
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 99384be0299..18b2b4db2bf 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -2040,7 +2040,7 @@ static void adjust_offsets(BevelParams *bp)
/* Should we auto-limit the error accumulation? Typically, spirals can lead to 100x relative adjustments,
* and somewhat hacky mechanism of using bp->limit_offset to indicate "clamp the adjustments" is not
- * obvious to users, who almost certainaly want clamping in this situation.
+ * obvious to users, who almost certainly want clamping in this situation.
* The reason not to clamp always is that some models work better without it (e.g., Bent_test in regression
* suite, where relative adjust maximum is about .6). */
if (!bp->limit_offset) {
diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp
index 9c8b8fc25d6..8832e0fd577 100644
--- a/source/blender/collada/ArmatureImporter.cpp
+++ b/source/blender/collada/ArmatureImporter.cpp
@@ -55,9 +55,10 @@ static const char *bc_get_joint_name(T *node)
}
-ArmatureImporter::ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce, const ImportSettings *import_settings) :
+ArmatureImporter::ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce, ViewLayer *view_layer, const ImportSettings *import_settings) :
TransformReader(conv),
scene(sce),
+ view_layer(view_layer),
unit_converter(conv),
import_settings(import_settings),
empty(NULL),
@@ -411,7 +412,7 @@ Object *ArmatureImporter::get_empty_for_leaves()
{
if (empty) return empty;
- empty = bc_add_object(scene, OB_EMPTY, NULL);
+ empty = bc_add_object(scene, view_layer, OB_EMPTY, NULL);
empty->empty_drawtype = OB_EMPTY_SPHERE;
return empty;
@@ -586,7 +587,7 @@ Object *ArmatureImporter::create_armature_bones(SkinInfo& skin)
ob_arm = skin.set_armature(shared);
}
else {
- ob_arm = skin.create_armature(scene); //once for every armature
+ ob_arm = skin.create_armature(scene, view_layer); //once for every armature
}
// enter armature edit mode
diff --git a/source/blender/collada/ArmatureImporter.h b/source/blender/collada/ArmatureImporter.h
index 17173f157e5..f260bb2307c 100644
--- a/source/blender/collada/ArmatureImporter.h
+++ b/source/blender/collada/ArmatureImporter.h
@@ -63,6 +63,7 @@ class ArmatureImporter : private TransformReader
{
private:
Scene *scene;
+ ViewLayer *view_layer;
UnitConverter *unit_converter;
const ImportSettings *import_settings;
@@ -137,7 +138,7 @@ private:
TagsMap uid_tags_map;
public:
- ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce, const ImportSettings *import_settings);
+ ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce, ViewLayer *view_layer, const ImportSettings *import_settings);
~ArmatureImporter();
void add_root_joint(COLLADAFW::Node *node, Object *parent);
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index d3e23f740c8..dfd662aa66c 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -108,8 +108,9 @@ DocumentImporter::DocumentImporter(bContext *C, const ImportSettings *import_set
import_settings(import_settings),
mImportStage(General),
mContext(C),
- armature_importer(&unit_converter, &mesh_importer, CTX_data_scene(C), import_settings),
- mesh_importer(&unit_converter, &armature_importer, CTX_data_scene(C)),
+ view_layer(CTX_data_view_layer(mContext)),
+ armature_importer(&unit_converter, &mesh_importer, CTX_data_scene(C), view_layer, import_settings),
+ mesh_importer(&unit_converter, &armature_importer, CTX_data_scene(C), view_layer),
anim_importer(&unit_converter, &armature_importer, CTX_data_scene(C))
{
}
@@ -134,7 +135,7 @@ bool DocumentImporter::import()
loader.registerExtraDataCallbackHandler(ehandler);
// deselect all to select new objects
- BKE_view_layer_base_deselect_all(CTX_data_view_layer(mContext));
+ BKE_view_layer_base_deselect_all(view_layer);
std::string mFilename = std::string(this->import_settings->filepath);
const std::string encodedFilename = bc_url_encode(mFilename);
@@ -380,7 +381,7 @@ Object *DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera
return NULL;
}
- Object *ob = bc_add_object(sce, OB_CAMERA, NULL);
+ Object *ob = bc_add_object(sce, view_layer, OB_CAMERA, NULL);
Camera *cam = uid_camera_map[cam_uid];
Camera *old_cam = (Camera *)ob->data;
ob->data = cam;
@@ -396,7 +397,7 @@ Object *DocumentImporter::create_lamp_object(COLLADAFW::InstanceLight *lamp, Sce
return NULL;
}
- Object *ob = bc_add_object(sce, OB_LAMP, NULL);
+ Object *ob = bc_add_object(sce, view_layer, OB_LAMP, NULL);
Lamp *la = uid_lamp_map[lamp_uid];
Lamp *old_lamp = (Lamp *)ob->data;
ob->data = la;
@@ -512,7 +513,7 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
if (parent_node == NULL && !is_library_node) {
// A Joint on root level is a skeleton without root node.
// Here we add the armature "on the fly":
- par = bc_add_object(sce, OB_ARMATURE, std::string("Armature").c_str());
+ par = bc_add_object(sce, view_layer, OB_ARMATURE, std::string("Armature").c_str());
objects_done->push_back(par);
root_objects->push_back(par);
object_map.insert(std::pair<COLLADAFW::UniqueId, Object *>(node->getUniqueId(), par));
@@ -626,10 +627,10 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
if ( (geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) {
//Check if Object is armature, by checking if immediate child is a JOINT node.
if (is_armature(node)) {
- ob = bc_add_object(sce, OB_ARMATURE, name.c_str());
+ ob = bc_add_object(sce, view_layer, OB_ARMATURE, name.c_str());
}
else {
- ob = bc_add_object(sce, OB_EMPTY, NULL);
+ ob = bc_add_object(sce, view_layer, OB_EMPTY, NULL);
}
objects_done->push_back(ob);
if (parent_node == NULL) {
diff --git a/source/blender/collada/DocumentImporter.h b/source/blender/collada/DocumentImporter.h
index 62f76dbc022..fd61f3a68da 100644
--- a/source/blender/collada/DocumentImporter.h
+++ b/source/blender/collada/DocumentImporter.h
@@ -144,6 +144,7 @@ private:
ImportStage mImportStage;
bContext *mContext;
+ ViewLayer *view_layer;
UnitConverter unit_converter;
ArmatureImporter armature_importer;
diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp
index 87392352a48..5e7f92047d3 100644
--- a/source/blender/collada/EffectExporter.cpp
+++ b/source/blender/collada/EffectExporter.cpp
@@ -67,7 +67,7 @@ EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettin
bool EffectsExporter::hasEffects(Scene *sce)
{
- FOREACH_SCENE_OBJECT(scene, ob)
+ FOREACH_SCENE_OBJECT(sce, ob)
{
int a;
for (a = 0; a < ob->totcol; a++) {
diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp
index 9c95d4de695..f8cd487c355 100644
--- a/source/blender/collada/MeshImporter.cpp
+++ b/source/blender/collada/MeshImporter.cpp
@@ -207,7 +207,11 @@ void VCOLDataWrapper::get_vcol(int v_index, MLoopCol *mloopcol)
}
-MeshImporter::MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Scene *sce) : unitconverter(unitconv), scene(sce), armature_importer(arm) {
+MeshImporter::MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Scene *sce, ViewLayer *view_layer):
+ unitconverter(unitconv),
+ scene(sce),
+ view_layer(view_layer),
+ armature_importer(arm) {
}
bool MeshImporter::set_poly_indices(MPoly *mpoly, MLoop *mloop, int loop_index, unsigned int *indices, int loop_count)
@@ -1141,7 +1145,7 @@ Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::Insta
const char *name = (id.length()) ? id.c_str() : NULL;
// add object
- Object *ob = bc_add_object(scene, OB_MESH, name);
+ Object *ob = bc_add_object(scene, view_layer, OB_MESH, name);
bc_set_mark(ob); // used later for material assignement optimization
diff --git a/source/blender/collada/MeshImporter.h b/source/blender/collada/MeshImporter.h
index e8ae934a393..f57f57e07a7 100644
--- a/source/blender/collada/MeshImporter.h
+++ b/source/blender/collada/MeshImporter.h
@@ -92,6 +92,8 @@ private:
UnitConverter *unitconverter;
Scene *scene;
+ ViewLayer *view_layer;
+
ArmatureImporter *armature_importer;
std::map<std::string, std::string> mesh_geom_map; // needed for correct shape key naming
@@ -159,7 +161,7 @@ private:
public:
- MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Scene *sce);
+ MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Scene *sce, ViewLayer *view_layer);
virtual Object *get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid);
diff --git a/source/blender/collada/SkinInfo.cpp b/source/blender/collada/SkinInfo.cpp
index c29f1748efc..a2cb8237d08 100644
--- a/source/blender/collada/SkinInfo.cpp
+++ b/source/blender/collada/SkinInfo.cpp
@@ -159,9 +159,9 @@ void SkinInfo::set_controller(const COLLADAFW::SkinController *co)
}
// called from write_controller
-Object *SkinInfo::create_armature(Scene *scene)
+Object *SkinInfo::create_armature(Scene *scene, ViewLayer *view_layer)
{
- ob_arm = bc_add_object(scene, OB_ARMATURE, NULL);
+ ob_arm = bc_add_object(scene, view_layer, OB_ARMATURE, NULL);
return ob_arm;
}
diff --git a/source/blender/collada/SkinInfo.h b/source/blender/collada/SkinInfo.h
index e074f59cffc..a399bff9e3c 100644
--- a/source/blender/collada/SkinInfo.h
+++ b/source/blender/collada/SkinInfo.h
@@ -99,7 +99,7 @@ public:
void set_controller(const COLLADAFW::SkinController* co);
// called from write_controller
- Object *create_armature(Scene *scene);
+ Object *create_armature(Scene *scene, ViewLayer *view_layer);
Object* set_armature(Object *ob_arm);
diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp
index 6a52027fb47..f351ebf7952 100644
--- a/source/blender/collada/collada_utils.cpp
+++ b/source/blender/collada/collada_utils.cpp
@@ -135,7 +135,7 @@ int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
return true;
}
-Object *bc_add_object(Scene *scene, int type, const char *name)
+Object *bc_add_object(Scene *scene, ViewLayer *view_layer, int type, const char *name)
{
Object *ob = BKE_object_add_only_object(G.main, type, name);
@@ -143,9 +143,6 @@ Object *bc_add_object(Scene *scene, int type, const char *name)
ob->lay = scene->lay;
DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- /* XXX Collada should use the context scene layer, not the scene one. (dfelinto/gaia). */
- ViewLayer *view_layer = BKE_view_layer_context_active_PLACEHOLDER(scene);
-
LayerCollection *layer_collection = BKE_layer_collection_get_active_ensure(scene, view_layer);
BKE_collection_object_add(&scene->id, layer_collection->scene_collection, ob);
diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h
index 75e9fb5dcea..5d6e836b9c3 100644
--- a/source/blender/collada/collada_utils.h
+++ b/source/blender/collada/collada_utils.h
@@ -67,7 +67,7 @@ typedef std::map<COLLADAFW::TextureMapId, std::vector<MTex *> > TexIndexTextureA
extern float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index);
extern int bc_test_parent_loop(Object *par, Object *ob);
extern int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space = true);
-extern Object *bc_add_object(Scene *scene, int type, const char *name);
+extern Object *bc_add_object(Scene *scene, ViewLayer *view_layer, int type, const char *name);
extern Mesh *bc_get_mesh_copy(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate);
extern Object *bc_get_assigned_armature(Object *ob);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index c89c436cb6a..04a72f85a78 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -992,6 +992,18 @@ void DepsgraphRelationBuilder::build_animdata_curves_targets(ID *id)
graph_->add_new_relation(operation_from, operation_to,
"Animation -> Prop",
true);
+ /* It is possible that animation is writing to a nested ID datablock,
+ * need to make sure animation is evaluated after target ID is copied.
+ */
+ if (DEG_depsgraph_use_copy_on_write()) {
+ const IDDepsNode *id_node_from = operation_from->owner->owner;
+ const IDDepsNode *id_node_to = operation_to->owner->owner;
+ if (id_node_from != id_node_to) {
+ ComponentKey cow_key(id_node_to->id_orig,
+ DEG_NODE_TYPE_COPY_ON_WRITE);
+ add_relation(cow_key, adt_key, "Target CoW -> Animation", true);
+ }
+ }
}
}
@@ -1011,7 +1023,6 @@ void DepsgraphRelationBuilder::build_animdata_drivers(ID *id)
/* create the driver's relations to targets */
build_driver(id, fcu);
-
/* Special case for array drivers: we can not multithread them because
* of the way how they work internally: animation system will write the
* whole array back to RNA even when changing individual array value.
@@ -1142,6 +1153,25 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu)
else {
RNAPathKey target_key(id, rna_path);
add_relation(driver_key, target_key, "Driver -> Target");
+ /* Similar to the case with f-curves, driver might drive a nested
+ * datablock, which means driver execution should wait for that
+ * datablock to be copied.
+ */
+ if (DEG_depsgraph_use_copy_on_write()) {
+ PointerRNA id_ptr;
+ PointerRNA ptr;
+ RNA_id_pointer_create(id, &id_ptr);
+ if (RNA_path_resolve_full(&id_ptr, fcu->rna_path, &ptr, NULL, NULL)) {
+ if (id_ptr.id.data != ptr.id.data) {
+ ComponentKey cow_key((ID *)ptr.id.data,
+ DEG_NODE_TYPE_COPY_ON_WRITE);
+ add_relation(cow_key,
+ driver_key,
+ "Target CoW -> Driver",
+ true);
+ }
+ }
+ }
}
}
diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
index 42d512d473c..30c9d9f10be 100644
--- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
@@ -58,6 +58,30 @@ extern "C" {
/* ************************ DEG ITERATORS ********************* */
+static void verify_id_proeprties_freed(DEGObjectIterData *data)
+{
+ if (data->dupli_object_current == NULL) {
+ // We didn't enter duplication yet, so we can't have any dangling
+ // pointers.
+ return;
+ }
+ const Object *dupli_object = data->dupli_object_current->ob;
+ Object *temp_dupli_object = &data->temp_dupli_object;
+ if (temp_dupli_object->id.properties == NULL) {
+ // No ID proeprties in temp datablock -- no leak is possible.
+ return;
+ }
+ if (temp_dupli_object->id.properties == dupli_object->id.properties) {
+ // Temp copy of object did not modify ID properties.
+ return;
+ }
+ // Free memory which is owned by temporary storage which is about to
+ // get overwritten.
+ IDP_FreeProperty(temp_dupli_object->id.properties);
+ MEM_freeN(temp_dupli_object->id.properties);
+ temp_dupli_object->id.properties = NULL;
+}
+
static bool deg_objects_dupli_iterator_next(BLI_Iterator *iter)
{
DEGObjectIterData *data = (DEGObjectIterData *)iter->data;
@@ -78,6 +102,8 @@ static bool deg_objects_dupli_iterator_next(BLI_Iterator *iter)
continue;
}
+ verify_id_proeprties_freed(data);
+
data->dupli_object_current = dob;
/* Temporary object to evaluate. */
@@ -90,10 +116,13 @@ static bool deg_objects_dupli_iterator_next(BLI_Iterator *iter)
if (dob->collection_properties != NULL) {
temp_dupli_object->base_collection_properties = dob->collection_properties;
- IDP_MergeGroup(temp_dupli_object->base_collection_properties, dupli_parent->base_collection_properties, false);
+ IDP_MergeGroup(temp_dupli_object->base_collection_properties,
+ dupli_parent->base_collection_properties,
+ false);
}
else {
- temp_dupli_object->base_collection_properties = dupli_parent->base_collection_properties;
+ temp_dupli_object->base_collection_properties =
+ dupli_parent->base_collection_properties;
}
copy_m4_m4(data->temp_dupli_object.obmat, dob->mat);
@@ -146,15 +175,16 @@ static void DEG_iterator_objects_step(BLI_Iterator *iter, DEG::IDDepsNode *id_no
return;
}
- if ((data->flag & DEG_ITER_OBJECT_FLAG_DUPLI) && (object->transflag & OB_DUPLI)) {
+ if ((data->flag & DEG_ITER_OBJECT_FLAG_DUPLI) &&
+ (object->transflag & OB_DUPLI))
+ {
data->dupli_parent = object;
data->dupli_list = object_duplilist(&data->eval_ctx, data->scene, object);
data->dupli_object_next = (DupliObject *)data->dupli_list->first;
-
- const eObjectVisibilityCheck mode = (data->mode == DEG_ITER_OBJECT_MODE_RENDER) ?
- OB_VISIBILITY_CHECK_FOR_RENDER :
- OB_VISIBILITY_CHECK_FOR_VIEWPORT;
-
+ const eObjectVisibilityCheck mode =
+ (data->mode == DEG_ITER_OBJECT_MODE_RENDER)
+ ? OB_VISIBILITY_CHECK_FOR_RENDER
+ : OB_VISIBILITY_CHECK_FOR_VIEWPORT;
if (BKE_object_is_visible(object, mode) == false) {
return;
}
@@ -211,6 +241,7 @@ void DEG_iterator_objects_next(BLI_Iterator *iter)
return;
}
else {
+ verify_id_proeprties_freed(data);
free_object_duplilist(data->dupli_list);
data->dupli_parent = NULL;
data->dupli_list = NULL;
@@ -234,7 +265,9 @@ void DEG_iterator_objects_end(BLI_Iterator *iter)
{
#ifndef NDEBUG
DEGObjectIterData *data = (DEGObjectIterData *)iter->data;
- /* Force crash in case the iterator data is referenced and accessed down the line. (T51718) */
+ /* Force crash in case the iterator data is referenced and accessed down
+ * the line. (T51718)
+ */
memset(&data->temp_dupli_object, 0xff, sizeof(data->temp_dupli_object));
#else
(void) iter;
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index a8eea136409..e5c714cfd74 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -263,6 +263,47 @@ void depsgraph_update_editors_tag(Main *bmain, Depsgraph *graph, ID *id)
deg_editors_id_update(&update_ctx, id);
}
+void depsgraph_tag_component(Depsgraph *graph,
+ IDDepsNode *id_node,
+ eDepsNode_Type component_type,
+ eDepsOperation_Code operation_code)
+{
+ ComponentDepsNode *component_node =
+ id_node->find_component(component_type);
+ if (component_node == NULL) {
+ return;
+ }
+ if (operation_code == DEG_OPCODE_OPERATION) {
+ component_node->tag_update(graph);
+ }
+ else {
+ OperationDepsNode *operation_node =
+ component_node->find_operation(operation_code);
+ if (operation_node != NULL) {
+ operation_node->tag_update(graph);
+ }
+ }
+}
+
+/* This is a tag compatibility with legacy code.
+ *
+ * Mainly, old code was tagging object with OB_RECALC_DATA tag to inform
+ * that object's data datablock changed. Now API expects that ID is given
+ * explicitly, but not all areas are aware of this yet.
+ */
+void deg_graph_id_tag_legacy_compat(Main *bmain,
+ ID *id,
+ eDepsgraph_Tag tag)
+{
+ if (tag == DEG_TAG_GEOMETRY && GS(id->name) == ID_OB) {
+ Object *object = (Object *)id;
+ ID *data_id = (ID *)object->data;
+ if (data_id != NULL) {
+ DEG_id_tag_update_ex(bmain, data_id, 0);
+ }
+ }
+}
+
void deg_graph_id_tag_update_single_flag(Main *bmain,
Depsgraph *graph,
ID *id,
@@ -304,21 +345,13 @@ void deg_graph_id_tag_update_single_flag(Main *bmain,
id_node->tag_update(graph);
}
else {
- ComponentDepsNode *component_node =
- id_node->find_component(component_type);
- if (component_node != NULL) {
- if (operation_code == DEG_OPCODE_OPERATION) {
- component_node->tag_update(graph);
- }
- else {
- OperationDepsNode *operation_node =
- component_node->find_operation(operation_code);
- if (operation_node != NULL) {
- operation_node->tag_update(graph);
- }
- }
- }
+ depsgraph_tag_component(graph, id_node, component_type, operation_code);
}
+ /* TODO(sergey): Get rid of this once all areas are using proper data ID
+ * for tagging.
+ */
+ deg_graph_id_tag_legacy_compat(bmain, id, tag);
+
}
void deg_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id, int flag)
@@ -347,6 +380,20 @@ void deg_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id, int flag)
id_tag_update_ntree_special(bmain, graph, id, flag);
}
+/* TODO(sergey): Consider storing scene and view layer at depsgraph allocation
+ * time.
+ */
+void deg_ensure_scene_view_layer(Depsgraph *graph,
+ Scene *scene,
+ ViewLayer *view_layer)
+{
+ if (!graph->need_update) {
+ return;
+ }
+ graph->scene = scene;
+ graph->view_layer = view_layer;
+}
+
void deg_id_tag_update(Main *bmain, ID *id, int flag)
{
deg_graph_id_tag_update(bmain, NULL, id, flag);
@@ -357,6 +404,11 @@ void deg_id_tag_update(Main *bmain, ID *id, int flag)
view_layer,
false);
if (depsgraph != NULL) {
+ /* Make sure depsgraph is pointing to a correct scene and
+ * view layer. This is mainly required in cases when depsgraph
+ * was not built yet.
+ */
+ deg_ensure_scene_view_layer(depsgraph, scene, view_layer);
deg_graph_id_tag_update(bmain, depsgraph, id, flag);
}
}
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
index ff447b53b1e..a6668208574 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
@@ -46,6 +46,7 @@
#include "BLI_string.h"
#include "BKE_global.h"
+#include "BKE_idprop.h"
#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_main.h"
@@ -467,6 +468,137 @@ void update_special_pointers(const Depsgraph *depsgraph,
}
}
+void update_copy_on_write_layer_collections(
+ ListBase *layer_collections_cow,
+ const ListBase *layer_collections_orig);
+
+void update_copy_on_write_layer_collection(
+ LayerCollection *layer_collection_cow,
+ const LayerCollection *layer_collection_orig)
+{
+ // Make a local copy of original layer collection, so we can start
+ // modifying it.
+ LayerCollection local = *layer_collection_orig;
+ // Copy all pointer data from original CoW version of layer collection.
+ local.next = layer_collection_cow->next;
+ local.prev = layer_collection_cow->prev;
+ local.scene_collection = layer_collection_cow->scene_collection;
+ local.object_bases = layer_collection_cow->object_bases;
+ local.overrides = layer_collection_cow->overrides;
+ local.layer_collections = layer_collection_cow->layer_collections;
+ local.properties = layer_collection_cow->properties;
+ local.properties_evaluated = layer_collection_cow->properties_evaluated;
+ // Synchronize pointer-related data.
+ IDP_Reset(local.properties, layer_collection_orig->properties);
+ // Copy synchronized version back.
+ *layer_collection_cow = local;
+ // Recurs into nested layer collections.
+ update_copy_on_write_layer_collections(
+ &layer_collection_cow->layer_collections,
+ &layer_collection_orig->layer_collections);
+}
+
+void update_copy_on_write_layer_collections(
+ ListBase *layer_collections_cow,
+ const ListBase *layer_collections_orig)
+{
+ const LayerCollection *layer_collection_orig =
+ (const LayerCollection *)layer_collections_orig->first;
+ LayerCollection *layer_collection_cow =
+ (LayerCollection *)layer_collections_cow->first;
+ while (layer_collection_orig != NULL) {
+ update_copy_on_write_layer_collection(layer_collection_cow,
+ layer_collection_orig);
+ layer_collection_orig = layer_collection_orig->next;
+ layer_collection_cow = layer_collection_cow->next;
+ }
+}
+
+void update_copy_on_write_view_layer(const Depsgraph *depsgraph,
+ ViewLayer *view_layer_cow,
+ const ViewLayer *view_layer_orig)
+{
+ // Update pointers to active base.
+ if (view_layer_orig->basact == NULL) {
+ view_layer_cow->basact = NULL;
+ }
+ else {
+ const Object *obact_orig = view_layer_orig->basact->object;
+ Object *obact_cow = (Object *)depsgraph->get_cow_id(&obact_orig->id);
+ view_layer_cow->basact = BKE_view_layer_base_find(view_layer_cow, obact_cow);
+ }
+ // Update base flags.
+ //
+ // TODO(sergey): We should probably check visibled/selectabled.
+ // flag here?
+ const Base *base_orig = (Base *)view_layer_orig->object_bases.first;
+ Base *base_cow = (Base *)view_layer_cow->object_bases.first;;
+ while (base_orig != NULL) {
+ base_cow->flag = base_orig->flag;
+ base_orig = base_orig->next;
+ base_cow = base_cow->next;
+ }
+ // Synchronize settings.
+ view_layer_cow->active_collection = view_layer_orig->active_collection;
+ view_layer_cow->flag = view_layer_orig->flag;
+ view_layer_cow->layflag = view_layer_orig->layflag;
+ view_layer_cow->passflag = view_layer_orig->passflag;
+ view_layer_cow->pass_alpha_threshold = view_layer_orig->pass_alpha_threshold;
+ // Synchronize ID properties.
+ IDP_Reset(view_layer_cow->properties, view_layer_orig->properties);
+ IDP_Reset(view_layer_cow->id_properties, view_layer_orig->id_properties);
+ // Synchronize layer collections.
+ update_copy_on_write_layer_collections(
+ &view_layer_cow->layer_collections,
+ &view_layer_orig->layer_collections);
+}
+
+void update_copy_on_write_view_layers(const Depsgraph *depsgraph,
+ Scene *scene_cow,
+ const Scene *scene_orig)
+{
+ const ViewLayer *view_layer_orig = (const ViewLayer *)scene_orig->view_layers.first;
+ ViewLayer *view_layer_cow = (ViewLayer *)scene_cow->view_layers.first;
+ while (view_layer_orig != NULL) {
+ update_copy_on_write_view_layer(depsgraph,
+ view_layer_cow,
+ view_layer_orig);
+ view_layer_orig = view_layer_orig->next;
+ view_layer_cow = view_layer_cow->next;
+ }
+}
+
+void update_copy_on_write_scene_collections(
+ ListBase *collections_cow,
+ const ListBase *collections_orig);
+
+void update_copy_on_write_scene_collection(
+ SceneCollection *collection_cow,
+ const SceneCollection *collection_orig)
+{
+ collection_cow->active_object_index = collection_orig->active_object_index;
+ update_copy_on_write_scene_collections(
+ &collection_cow->scene_collections,
+ &collection_orig->scene_collections);
+}
+
+void update_copy_on_write_scene_collections(
+ ListBase *collections_cow,
+ const ListBase *collections_orig)
+{
+ const SceneCollection *nested_collection_orig =
+ (const SceneCollection *)collections_orig->first;
+ SceneCollection *nested_collection_cow =
+ (SceneCollection *)collections_cow->first;
+ while (nested_collection_orig != NULL) {
+ update_copy_on_write_scene_collection(
+ nested_collection_cow,
+ nested_collection_orig);
+ nested_collection_orig = nested_collection_orig->next;
+ nested_collection_cow = nested_collection_cow->next;
+ }
+}
+
/* Update copy-on-write version of scene from original scene. */
void update_copy_on_write_scene(const Depsgraph *depsgraph,
Scene *scene_cow,
@@ -476,33 +608,10 @@ void update_copy_on_write_scene(const Depsgraph *depsgraph,
// TODO(sergey): Are we missing something here?
scene_cow->r.cfra = scene_orig->r.cfra;
scene_cow->r.subframe = scene_orig->r.subframe;
- // Update bases.
- const ViewLayer *view_layer_orig = (ViewLayer *)scene_orig->view_layers.first;
- ViewLayer *view_layer_cow = (ViewLayer *)scene_cow->view_layers.first;
- while (view_layer_orig != NULL) {
- // Update pointers to active base.
- if (view_layer_orig->basact == NULL) {
- view_layer_cow->basact = NULL;
- }
- else {
- const Object *obact_orig = view_layer_orig->basact->object;
- Object *obact_cow = (Object *)depsgraph->get_cow_id(&obact_orig->id);
- view_layer_cow->basact = BKE_view_layer_base_find(view_layer_cow, obact_cow);
- }
- // Update base flags.
- //
- // TODO(sergey): We should probably check visibled/selectabled
- // flag here?
- const Base *base_orig = (Base *)view_layer_orig->object_bases.first;
- Base *base_cow = (Base *)view_layer_cow->object_bases.first;;
- while (base_orig != NULL) {
- base_cow->flag = base_orig->flag;
- base_orig = base_orig->next;
- base_cow = base_cow->next;
- }
- view_layer_orig = view_layer_orig->next;
- view_layer_cow = view_layer_cow->next;
- }
+ // Update view layers and collections.
+ update_copy_on_write_view_layers(depsgraph, scene_cow, scene_orig);
+ update_copy_on_write_scene_collection(scene_cow->collection,
+ scene_orig->collection);
// Update edit object pointer.
if (scene_orig->obedit != NULL) {
scene_cow->obedit = (Object *)depsgraph->get_cow_id(&scene_orig->obedit->id);
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 426b74e7d31..4dcc8dc081c 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -139,6 +139,7 @@ data_to_c_simple(engines/eevee/shaders/default_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/default_world_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/background_vert.glsl SRC)
data_to_c_simple(engines/eevee/shaders/concentric_samples_lib.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/common_uniforms_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/hair_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lamps_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lightprobe_lib.glsl SRC)
diff --git a/source/blender/draw/engines/clay/clay_engine.c b/source/blender/draw/engines/clay/clay_engine.c
index fcd9353bf1f..a9a919f7ac2 100644
--- a/source/blender/draw/engines/clay/clay_engine.c
+++ b/source/blender/draw/engines/clay/clay_engine.c
@@ -183,6 +183,7 @@ typedef struct CLAY_PrivateData {
DRWShadingGroup *depth_shgrp_cull;
DRWShadingGroup *depth_shgrp_cull_select;
DRWShadingGroup *depth_shgrp_cull_active;
+ bool enable_ao;
} CLAY_PrivateData; /* Transient data */
/* Functions */
@@ -607,7 +608,7 @@ static int hair_mat_in_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Material *
return id;
}
-static void ubo_mat_from_object(Object *ob, CLAY_UBO_Material *r_ubo)
+static void ubo_mat_from_object(Object *ob, CLAY_UBO_Material *r_ubo, bool *r_needs_ao)
{
IDProperty *props = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_CLAY);
@@ -622,6 +623,12 @@ static void ubo_mat_from_object(Object *ob, CLAY_UBO_Material *r_ubo)
float ssao_attenuation = BKE_collection_engine_property_value_get_float(props, "ssao_attenuation");
int matcap_icon = BKE_collection_engine_property_value_get_int(props, "matcap_icon");
+ if (((ssao_factor_cavity > 0.0) || (ssao_factor_edge > 0.0)) &&
+ (ssao_distance > 0.0))
+ {
+ *r_needs_ao = true;
+ }
+
memset(r_ubo, 0x0, sizeof(*r_ubo));
r_ubo->matcap_rot[0] = cosf(matcap_rot * 3.14159f * 2.0f);
@@ -667,7 +674,7 @@ static DRWShadingGroup *CLAY_object_shgrp_get(
DRWShadingGroup **shgrps = use_flat ? stl->storage->shgrps_flat : stl->storage->shgrps;
CLAY_UBO_Material mat_ubo_test;
- ubo_mat_from_object(ob, &mat_ubo_test);
+ ubo_mat_from_object(ob, &mat_ubo_test, &stl->g_data->enable_ao);
int id = mat_in_ubo(stl->storage, &mat_ubo_test);
@@ -712,6 +719,9 @@ static void clay_cache_init(void *vedata)
stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
}
+ /* Disable AO unless a material needs it. */
+ stl->g_data->enable_ao = false;
+
/* Depth Pass */
{
psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
@@ -851,18 +861,25 @@ static void clay_cache_finish(void *vedata)
static void clay_draw_scene(void *vedata)
{
-
+ CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl;
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
/* Pass 1 : Depth pre-pass */
- DRW_draw_pass(psl->depth_pass);
- DRW_draw_pass(psl->depth_pass_cull);
+ if (stl->g_data->enable_ao) {
+ DRW_draw_pass(psl->depth_pass);
+ DRW_draw_pass(psl->depth_pass_cull);
+ }
+ else {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
+ DRW_pass_state_set(psl->clay_pass, state);
+ DRW_pass_state_set(psl->clay_pass_flat, state);
+ }
/* Pass 2 : Duplicate depth */
/* Unless we go for deferred shading we need this to avoid manual depth test and artifacts */
- if (DRW_state_is_fbo()) {
+ if (DRW_state_is_fbo() && stl->g_data->enable_ao) {
/* attach temp textures */
DRW_framebuffer_texture_attach(fbl->dupli_depth, e_data.depth_dup, 0, 0);
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index f34601ef7b6..0a052b12e93 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -55,6 +55,7 @@ static void eevee_view_layer_data_free(void *storage)
DRW_UBO_FREE_SAFE(sldata->probe_ubo);
DRW_UBO_FREE_SAFE(sldata->grid_ubo);
DRW_UBO_FREE_SAFE(sldata->planar_ubo);
+ DRW_UBO_FREE_SAFE(sldata->common_ubo);
DRW_FRAMEBUFFER_FREE_SAFE(sldata->probe_fb);
DRW_FRAMEBUFFER_FREE_SAFE(sldata->probe_filter_fb);
DRW_TEXTURE_FREE_SAFE(sldata->probe_rt);
@@ -62,9 +63,6 @@ static void eevee_view_layer_data_free(void *storage)
DRW_TEXTURE_FREE_SAFE(sldata->probe_pool);
DRW_TEXTURE_FREE_SAFE(sldata->irradiance_pool);
DRW_TEXTURE_FREE_SAFE(sldata->irradiance_rt);
-
- /* Volumetrics */
- MEM_SAFE_FREE(sldata->volumetrics);
}
static void eevee_lightprobe_data_free(void *storage)
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index c09e180b36d..5821111c59d 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -102,6 +102,7 @@ static void eevee_create_shader_downsample(void)
void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
@@ -156,7 +157,7 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
DRW_framebuffer_init(&fbl->downsample_fb, &draw_engine_eevee_type,
- (int)viewport_size[0] / 2, (int)viewport_size[1] / 2,
+ max_ii((int)viewport_size[0] / 2, 1), max_ii((int)viewport_size[1] / 2, 1),
&texmax, 1);
@@ -169,8 +170,8 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
mip_size[0] = floorf(fmaxf(1.0f, mip_size[0] / 2.0f));
mip_size[1] = floorf(fmaxf(1.0f, mip_size[1] / 2.0f));
}
- stl->g_data->mip_ratio[i][0] = viewport_size[0] / (mip_size[0] * powf(2.0f, floorf(log2f(floorf(viewport_size[0] / mip_size[0])))));
- stl->g_data->mip_ratio[i][1] = viewport_size[1] / (mip_size[1] * powf(2.0f, floorf(log2f(floorf(viewport_size[1] / mip_size[1])))));
+ common_data->mip_ratio[i][0] = viewport_size[0] / (mip_size[0] * powf(2.0f, floorf(log2f(floorf(viewport_size[0] / mip_size[0])))));
+ common_data->mip_ratio[i][1] = viewport_size[1] / (mip_size[1] * powf(2.0f, floorf(log2f(floorf(viewport_size[1] / mip_size[1])))));
}
@@ -209,12 +210,10 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
}
-void EEVEE_effects_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
EEVEE_TextureList *txl = vedata->txl;
- EEVEE_EffectsInfo *effects = stl->effects;
int downsample_write = DRW_STATE_WRITE_DEPTH;
/* Intel gpu seems to have problem rendering to only depth format.
@@ -229,7 +228,7 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
psl->color_downsample_ps = DRW_pass_create("Downsample", DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(e_data.downsample_sh, psl->color_downsample_ps);
DRW_shgroup_uniform_buffer(grp, "source", &e_data.color_src);
- DRW_shgroup_uniform_float(grp, "fireflyFactor", &effects->ssr_firefly_fac, 1);
+ DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1);
DRW_shgroup_call_add(grp, quad, NULL);
}
@@ -401,7 +400,7 @@ void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_
DRW_stats_group_end();
}
-void EEVEE_draw_effects(EEVEE_Data *vedata)
+void EEVEE_draw_effects(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_TextureList *txl = vedata->txl;
EEVEE_FramebufferList *fbl = vedata->fbl;
@@ -478,7 +477,7 @@ void EEVEE_draw_effects(EEVEE_Data *vedata)
}
/* Record pers matrix for the next frame. */
- DRW_viewport_matrix_get(stl->g_data->prev_persmat, DRW_MAT_PERS);
+ DRW_viewport_matrix_get(sldata->common_data.prev_persmat, DRW_MAT_PERS);
/* Update double buffer status if render mode. */
if (DRW_state_is_image_render()) {
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index 2e7be2c29a5..fe2beb4b557 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -66,10 +66,14 @@ static void eevee_engine_init(void *ved)
(int)viewport_size[0], (int)viewport_size[1],
&tex, 1);
+ if (sldata->common_ubo == NULL) {
+ sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data), &sldata->common_data);
+ }
+
/* EEVEE_effects_init needs to go first for TAA */
EEVEE_effects_init(sldata, vedata);
- EEVEE_materials_init(stl, fbl);
+ EEVEE_materials_init(sldata, stl, fbl);
EEVEE_lights_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
@@ -188,6 +192,9 @@ static void eevee_draw_background(void *vedata)
EEVEE_lightprobes_refresh(sldata, vedata);
DRW_stats_group_end();
+ /* Update common buffer after probe rendering. */
+ DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
+
/* Refresh shadows */
DRW_stats_group_start("Shadows");
EEVEE_draw_shadows(sldata, psl);
@@ -263,7 +270,7 @@ static void eevee_draw_background(void *vedata)
/* Post Process */
DRW_stats_group_start("Post FX");
- EEVEE_draw_effects(vedata);
+ EEVEE_draw_effects(sldata, vedata);
DRW_stats_group_end();
if ((stl->effects->taa_current_sample > 1) && !DRW_state_is_image_render()) {
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index 9d90338131b..7403da737dd 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -83,7 +83,6 @@ static struct {
struct GPUTexture *cube_face_minmaxz;
int update_world;
- bool world_ready_to_shade;
} e_data = {NULL}; /* Engine data */
extern char datatoc_background_vert_glsl[];
@@ -107,6 +106,7 @@ extern char datatoc_irradiance_lib_glsl[];
extern char datatoc_lightprobe_lib_glsl[];
extern char datatoc_octahedron_lib_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
+extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_bsdf_sampling_lib_glsl[];
extern GlobalsUboStorage ts;
@@ -205,6 +205,7 @@ static void lightprobe_shaders_init(void)
char *shader_str = NULL;
shader_str = BLI_string_joinN(
+ datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_bsdf_sampling_lib_glsl,
datatoc_lightprobe_filter_glossy_frag_glsl);
@@ -218,6 +219,7 @@ static void lightprobe_shaders_init(void)
MEM_freeN(shader_str);
shader_str = BLI_string_joinN(
+ datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_bsdf_sampling_lib_glsl,
datatoc_lightprobe_filter_diffuse_frag_glsl);
@@ -227,6 +229,7 @@ static void lightprobe_shaders_init(void)
MEM_freeN(shader_str);
shader_str = BLI_string_joinN(
+ datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_bsdf_sampling_lib_glsl,
datatoc_lightprobe_filter_visibility_frag_glsl);
@@ -237,6 +240,7 @@ static void lightprobe_shaders_init(void)
shader_str = BLI_string_joinN(
datatoc_octahedron_lib_glsl,
+ datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_irradiance_lib_glsl,
datatoc_lightprobe_lib_glsl,
@@ -252,6 +256,7 @@ static void lightprobe_shaders_init(void)
shader_str = BLI_string_joinN(
datatoc_octahedron_lib_glsl,
+ datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_lightprobe_lib_glsl,
datatoc_lightprobe_cube_display_frag_glsl);
@@ -276,6 +281,7 @@ static void lightprobe_shaders_init(void)
void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(vedata))
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
bool update_all = false;
const DRWContextState *draw_ctx = DRW_context_state_get();
ViewLayer *view_layer = draw_ctx->view_layer;
@@ -288,15 +294,16 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(veda
if (!sldata->probes) {
sldata->probes = MEM_callocN(sizeof(EEVEE_LightProbesInfo), "EEVEE_LightProbesInfo");
- sldata->probes->specular_toggle = true;
- sldata->probes->ssr_toggle = true;
- sldata->probes->sss_toggle = true;
sldata->probes->grid_initialized = false;
sldata->probe_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_LightProbe) * MAX_PROBE, NULL);
sldata->grid_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_LightGrid) * MAX_GRID, NULL);
sldata->planar_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_PlanarReflection) * MAX_PLANAR, NULL);
}
+ common_data->spec_toggle = true;
+ common_data->ssr_toggle = true;
+ common_data->sss_toggle = true;
+
int prop_bounce_num = BKE_collection_engine_property_value_get_int(props, "gi_diffuse_bounces");
if (sldata->probes->num_bounce != prop_bounce_num) {
sldata->probes->num_bounce = prop_bounce_num;
@@ -315,8 +322,8 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(veda
}
int visibility_res = BKE_collection_engine_property_value_get_int(props, "gi_visibility_resolution");
- if (sldata->probes->irradiance_vis_size != visibility_res) {
- sldata->probes->irradiance_vis_size = visibility_res;
+ if (common_data->prb_irradiance_vis_size != visibility_res) {
+ common_data->prb_irradiance_vis_size = visibility_res;
update_all = true;
}
@@ -360,6 +367,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
EEVEE_StorageList *stl = vedata->stl;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ pinfo->do_cube_update = false;
pinfo->num_cube = 1; /* at least one for the world */
pinfo->num_grid = 1;
pinfo->num_planar = 0;
@@ -428,14 +436,15 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.probe_filter_glossy_sh, psl->probe_glossy_compute, geom);
- DRW_shgroup_uniform_float(grp, "sampleCount", &sldata->probes->samples_ct, 1);
- DRW_shgroup_uniform_float(grp, "invSampleCount", &sldata->probes->invsamples_ct, 1);
- DRW_shgroup_uniform_float(grp, "roughnessSquared", &sldata->probes->roughness, 1);
- DRW_shgroup_uniform_float(grp, "lodFactor", &sldata->probes->lodfactor, 1);
- DRW_shgroup_uniform_float(grp, "lodMax", &sldata->probes->lod_rt_max, 1);
- DRW_shgroup_uniform_float(grp, "texelSize", &sldata->probes->texel_size, 1);
- DRW_shgroup_uniform_float(grp, "paddingSize", &sldata->probes->padding_size, 1);
- DRW_shgroup_uniform_int(grp, "Layer", &sldata->probes->layer, 1);
+ DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1);
+ DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "invSampleCount", &pinfo->invsamples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "roughnessSquared", &pinfo->roughness, 1);
+ DRW_shgroup_uniform_float(grp, "lodFactor", &pinfo->lodfactor, 1);
+ DRW_shgroup_uniform_float(grp, "lodMax", &pinfo->lod_rt_max, 1);
+ DRW_shgroup_uniform_float(grp, "texelSize", &pinfo->texel_size, 1);
+ DRW_shgroup_uniform_float(grp, "paddingSize", &pinfo->padding_size, 1);
+ DRW_shgroup_uniform_int(grp, "Layer", &pinfo->layer, 1);
DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
// DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
DRW_shgroup_uniform_texture(grp, "probeHdr", sldata->probe_rt);
@@ -448,14 +457,15 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_filter_diffuse_sh, psl->probe_diffuse_compute);
#ifdef IRRADIANCE_SH_L2
- DRW_shgroup_uniform_int(grp, "probeSize", &sldata->probes->shres, 1);
+ DRW_shgroup_uniform_int(grp, "probeSize", &pinfo->shres, 1);
#else
- DRW_shgroup_uniform_float(grp, "sampleCount", &sldata->probes->samples_ct, 1);
- DRW_shgroup_uniform_float(grp, "invSampleCount", &sldata->probes->invsamples_ct, 1);
- DRW_shgroup_uniform_float(grp, "lodFactor", &sldata->probes->lodfactor, 1);
- DRW_shgroup_uniform_float(grp, "lodMax", &sldata->probes->lod_rt_max, 1);
+ DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "invSampleCount", &pinfo->invsamples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "lodFactor", &pinfo->lodfactor, 1);
+ DRW_shgroup_uniform_float(grp, "lodMax", &pinfo->lod_rt_max, 1);
DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
#endif
+ DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1);
DRW_shgroup_uniform_texture(grp, "probeHdr", sldata->probe_rt);
struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
@@ -466,14 +476,14 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
psl->probe_visibility_compute = DRW_pass_create("LightProbe Visibility Compute", DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_filter_visibility_sh, psl->probe_visibility_compute);
- DRW_shgroup_uniform_int(grp, "outputSize", &sldata->probes->shres, 1);
- DRW_shgroup_uniform_float(grp, "visibilityRange", &sldata->probes->visibility_range, 1);
- DRW_shgroup_uniform_float(grp, "visibilityBlur", &sldata->probes->visibility_blur, 1);
- DRW_shgroup_uniform_float(grp, "sampleCount", &sldata->probes->samples_ct, 1);
- DRW_shgroup_uniform_float(grp, "invSampleCount", &sldata->probes->invsamples_ct, 1);
- DRW_shgroup_uniform_float(grp, "storedTexelSize", &sldata->probes->texel_size, 1);
- DRW_shgroup_uniform_float(grp, "nearClip", &sldata->probes->near_clip, 1);
- DRW_shgroup_uniform_float(grp, "farClip", &sldata->probes->far_clip, 1);
+ DRW_shgroup_uniform_int(grp, "outputSize", &pinfo->shres, 1);
+ DRW_shgroup_uniform_float(grp, "visibilityRange", &pinfo->visibility_range, 1);
+ DRW_shgroup_uniform_float(grp, "visibilityBlur", &pinfo->visibility_blur, 1);
+ DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "invSampleCount", &pinfo->invsamples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "storedTexelSize", &pinfo->texel_size, 1);
+ DRW_shgroup_uniform_float(grp, "nearClip", &pinfo->near_clip, 1);
+ DRW_shgroup_uniform_float(grp, "farClip", &pinfo->far_clip, 1);
DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
DRW_shgroup_uniform_texture(grp, "probeDepth", sldata->probe_depth_rt);
@@ -500,8 +510,8 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
DRW_shgroup_attrib_float(grp, "probe_id", 1); /* XXX this works because we are still uploading 4bytes and using the right stride */
DRW_shgroup_attrib_float(grp, "probe_location", 3);
DRW_shgroup_attrib_float(grp, "sphere_size", 1);
- DRW_shgroup_uniform_float(grp, "lodCubeMax", &sldata->probes->lod_cube_max, 1);
DRW_shgroup_uniform_buffer(grp, "probeCubes", &sldata->probe_pool);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
geom = DRW_cache_quad_get();
grp = stl->g_data->planar_display_shgrp = DRW_shgroup_instance_create(e_data.probe_planar_display_sh, psl->probe_display, geom);
@@ -516,7 +526,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = stl->g_data->planar_downsample = DRW_shgroup_instance_create(e_data.probe_planar_downsample_sh, psl->probe_planar_downsample_ps, geom);
DRW_shgroup_uniform_buffer(grp, "source", &txl->planar_pool);
- DRW_shgroup_uniform_float(grp, "fireflyFactor", &stl->effects->ssr_firefly_fac, 1);
+ DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1);
}
}
@@ -549,7 +559,6 @@ void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
ped->need_update = true;
ped->probe_id = 0;
-
if (probe->type == LIGHTPROBE_TYPE_GRID) {
ped->updated_cells = 0;
ped->updated_lvl = 0;
@@ -565,6 +574,8 @@ void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
ped->probe_id = 0;
}
+ pinfo->do_cube_update |= ped->need_update;
+
if (probe->type == LIGHTPROBE_TYPE_CUBE) {
pinfo->probes_cube_ref[pinfo->num_cube] = ob;
pinfo->num_cube++;
@@ -832,6 +843,7 @@ static void EEVEE_lightprobes_updates(EEVEE_ViewLayerData *sldata, EEVEE_PassLis
void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
Object *ob;
@@ -849,7 +861,7 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
}
int irr_size[3];
- irradiance_pool_size_get(pinfo->irradiance_vis_size, pinfo->total_irradiance_samples, irr_size);
+ irradiance_pool_size_get(common_data->prb_irradiance_vis_size, pinfo->total_irradiance_samples, irr_size);
if ((irr_size[0] != pinfo->cache_irradiance_size[0]) ||
(irr_size[1] != pinfo->cache_irradiance_size[1]) ||
@@ -875,8 +887,7 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
/* Tag probes to refresh */
e_data.update_world |= PROBE_UPDATE_CUBE;
- e_data.world_ready_to_shade = false;
- pinfo->num_render_cube = 0;
+ common_data->prb_num_render_cube = 0;
pinfo->cache_num_cube = pinfo->num_cube;
for (int i = 1; (ob = pinfo->probes_cube_ref[i]) && (i < MAX_PROBE); i++) {
@@ -908,7 +919,7 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
sldata->irradiance_rt = DRW_texture_create_2D_array(irr_size[0], irr_size[1], irr_size[2],
irradiance_format, DRW_TEX_FILTER, NULL);
}
- pinfo->num_render_grid = 0;
+ common_data->prb_num_render_grid = 0;
pinfo->updated_bounce = 0;
pinfo->grid_initialized = false;
e_data.update_world |= PROBE_UPDATE_GRID;
@@ -920,9 +931,9 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
}
}
- if (pinfo->num_render_grid > pinfo->num_grid) {
+ if (common_data->prb_num_render_grid > pinfo->num_grid) {
/* This can happen when deleting a probe. */
- pinfo->num_render_grid = pinfo->num_grid;
+ common_data->prb_num_render_grid = pinfo->num_grid;
}
EEVEE_lightprobes_updates(sldata, vedata->psl, vedata->stl);
@@ -939,23 +950,26 @@ static void downsample_planar(void *vedata, int level)
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
const float *size = DRW_viewport_size_get();
- copy_v2_v2(stl->g_data->texel_size, size);
+ copy_v2_v2(stl->g_data->planar_texel_size, size);
for (int i = 0; i < level - 1; ++i) {
- stl->g_data->texel_size[0] /= 2.0f;
- stl->g_data->texel_size[1] /= 2.0f;
- min_ff(floorf(stl->g_data->texel_size[0]), 1.0f);
- min_ff(floorf(stl->g_data->texel_size[1]), 1.0f);
+ stl->g_data->planar_texel_size[0] /= 2.0f;
+ stl->g_data->planar_texel_size[1] /= 2.0f;
+ min_ff(floorf(stl->g_data->planar_texel_size[0]), 1.0f);
+ min_ff(floorf(stl->g_data->planar_texel_size[1]), 1.0f);
}
- invert_v2(stl->g_data->texel_size);
+ invert_v2(stl->g_data->planar_texel_size);
DRW_draw_pass(psl->probe_planar_downsample_ps);
}
/* Glossy filter probe_rt to probe_pool at index probe_idx */
-static void glossy_filter_probe(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, EEVEE_PassList *psl, int probe_idx)
+static void glossy_filter_probe(
+ EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, EEVEE_PassList *psl, int probe_idx, float intensity)
{
EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ pinfo->intensity_fac = intensity;
+
/* Max lod used from the render target probe */
pinfo->lod_rt_max = floorf(log2f(pinfo->target_size)) - 2.0f;
@@ -1018,7 +1032,7 @@ static void glossy_filter_probe(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
CLAMP_MIN(mipsize, 1);
}
/* For shading, save max level of the octahedron map */
- pinfo->lod_cube_max = (float)(maxlevel - min_lod_level) - 1.0f;
+ sldata->common_data.prb_lod_cube_max = (float)(maxlevel - min_lod_level) - 1.0f;
/* reattach to have a valid framebuffer. */
DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
@@ -1027,12 +1041,15 @@ static void glossy_filter_probe(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
/* Diffuse filter probe_rt to irradiance_pool at index probe_idx */
static void diffuse_filter_probe(
EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, EEVEE_PassList *psl, int offset,
- float clipsta, float clipend, float vis_range, float vis_blur)
+ float clipsta, float clipend, float vis_range, float vis_blur, float intensity)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ pinfo->intensity_fac = intensity;
+
int pool_size[3];
- irradiance_pool_size_get(pinfo->irradiance_vis_size, pinfo->total_irradiance_samples, pool_size);
+ irradiance_pool_size_get(common_data->prb_irradiance_vis_size, pinfo->total_irradiance_samples, pool_size);
/* find cell position on the virtual 3D texture */
/* NOTE : Keep in sync with load_irradiance_cell() */
@@ -1076,23 +1093,24 @@ static void diffuse_filter_probe(
/* Compute visibility */
pinfo->samples_ct = 512.0f; /* TODO refine */
pinfo->invsamples_ct = 1.0f / pinfo->samples_ct;
- pinfo->shres = pinfo->irradiance_vis_size;
+ pinfo->shres = common_data->prb_irradiance_vis_size;
pinfo->visibility_range = vis_range;
pinfo->visibility_blur = vis_blur;
pinfo->near_clip = -clipsta;
pinfo->far_clip = -clipend;
- pinfo->texel_size = 1.0f / (float)pinfo->irradiance_vis_size;
+ pinfo->texel_size = 1.0f / (float)common_data->prb_irradiance_vis_size;
- int cell_per_col = pool_size[1] / pinfo->irradiance_vis_size;
- cell_per_row = pool_size[0] / pinfo->irradiance_vis_size;
- x = pinfo->irradiance_vis_size * (offset % cell_per_row);
- y = pinfo->irradiance_vis_size * ((offset / cell_per_row) % cell_per_col);
+ int cell_per_col = pool_size[1] / common_data->prb_irradiance_vis_size;
+ cell_per_row = pool_size[0] / common_data->prb_irradiance_vis_size;
+ x = common_data->prb_irradiance_vis_size * (offset % cell_per_row);
+ y = common_data->prb_irradiance_vis_size * ((offset / cell_per_row) % cell_per_col);
int layer = 1 + ((offset / cell_per_row) / cell_per_col);
DRW_framebuffer_texture_detach(sldata->irradiance_rt);
DRW_framebuffer_texture_layer_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, layer, 0);
- DRW_framebuffer_viewport_size(sldata->probe_filter_fb, x, y, pinfo->irradiance_vis_size, sldata->probes->irradiance_vis_size);
+ DRW_framebuffer_viewport_size(sldata->probe_filter_fb, x, y, common_data->prb_irradiance_vis_size,
+ common_data->prb_irradiance_vis_size);
DRW_draw_pass(psl->probe_visibility_compute);
}
@@ -1111,23 +1129,13 @@ static void render_scene_to_probe(
EEVEE_StorageList *stl = vedata->stl;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
- float winmat[4][4], wininv[4][4], posmat[4][4], tmp_ao_dist, tmp_ao_settings;
+ float winmat[4][4], wininv[4][4], posmat[4][4];
unit_m4(posmat);
/* Move to capture position */
negate_v3_v3(posmat[3], pos);
- /* Disable specular lighting when rendering probes to avoid feedback loops (looks bad). */
- sldata->probes->specular_toggle = false;
- sldata->probes->ssr_toggle = false;
- sldata->probes->sss_toggle = false;
-
- /* Disable AO until we find a way to hide really bad discontinuities between cubefaces. */
- tmp_ao_dist = stl->effects->ao_dist;
- tmp_ao_settings = stl->effects->ao_settings;
- stl->effects->ao_settings = 0.0f; /* Disable AO */
-
/* 1 - Render to each cubeface individually.
* We do this instead of using geometry shader because a) it's faster,
* b) it's easier than fixing the nodetree shaders (for view dependant effects). */
@@ -1143,6 +1151,9 @@ static void render_scene_to_probe(
stl->g_data->minzbuffer = e_data.depth_placeholder;
txl->maxzbuffer = e_data.depth_placeholder;
+ /* Update common uniforms */
+ DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
+
/* Detach to rebind the right cubeface. */
DRW_framebuffer_bind(sldata->probe_fb);
DRW_framebuffer_texture_detach(sldata->probe_rt);
@@ -1204,14 +1215,9 @@ static void render_scene_to_probe(
DRW_viewport_matrix_override_unset(DRW_MAT_WININV);
/* Restore */
- pinfo->specular_toggle = true;
- pinfo->ssr_toggle = true;
- pinfo->sss_toggle = true;
txl->planar_pool = tmp_planar_pool;
stl->g_data->minzbuffer = tmp_minz;
txl->maxzbuffer = tmp_maxz;
- stl->effects->ao_dist = tmp_ao_dist;
- stl->effects->ao_settings = tmp_ao_settings;
}
static void render_scene_to_planar(
@@ -1250,11 +1256,6 @@ static void render_scene_to_planar(
DRW_framebuffer_clear(false, true, false, NULL, 1.0);
- /* Turn off ssr to avoid black specular */
- /* TODO : Enable SSR in planar reflections? (Would be very heavy) */
- sldata->probes->ssr_toggle = false;
- sldata->probes->sss_toggle = false;
-
/* Avoid using the texture attached to framebuffer when rendering. */
/* XXX */
GPUTexture *tmp_planar_pool = txl->planar_pool;
@@ -1286,8 +1287,6 @@ static void render_scene_to_planar(
DRW_state_clip_planes_reset();
/* Restore */
- sldata->probes->ssr_toggle = true;
- sldata->probes->sss_toggle = true;
txl->planar_pool = tmp_planar_pool;
txl->planar_depth = tmp_planar_depth;
DRW_viewport_matrix_override_unset(DRW_MAT_PERS);
@@ -1373,27 +1372,25 @@ static void lightprobe_cell_world_location_get(EEVEE_LightGrid *egrid, float loc
static void lightprobes_refresh_world(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_PassList *psl = vedata->psl;
- EEVEE_LightProbesInfo *pinfo = sldata->probes;
+
render_world_to_probe(sldata, psl);
if (e_data.update_world & PROBE_UPDATE_CUBE) {
- glossy_filter_probe(sldata, vedata, psl, 0);
+ glossy_filter_probe(sldata, vedata, psl, 0, 1.0);
+ common_data->prb_num_render_cube = 1;
}
if (e_data.update_world & PROBE_UPDATE_GRID) {
- diffuse_filter_probe(sldata, vedata, psl, 0, 0.0, 0.0, 0.0, 0.0);
+ diffuse_filter_probe(sldata, vedata, psl, 0, 0.0, 0.0, 0.0, 0.0, 1.0);
SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
DRW_framebuffer_texture_detach(sldata->probe_pool);
DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
DRW_draw_pass(psl->probe_grid_fill);
DRW_framebuffer_texture_detach(sldata->irradiance_rt);
DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
+ common_data->prb_num_render_grid = 1;
}
e_data.update_world = 0;
- if (!e_data.world_ready_to_shade) {
- e_data.world_ready_to_shade = true;
- pinfo->num_render_cube = 1;
- pinfo->num_render_grid = 1;
- }
DRW_viewport_request_redraw();
}
@@ -1425,36 +1422,53 @@ static void lightprobes_refresh_initialize_grid(EEVEE_ViewLayerData *sldata, EEV
static void lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_TextureList *txl = vedata->txl;
Object *ob;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
+
+ if (pinfo->num_planar == 0) {
+ return;
+ }
+
+ /* Temporary Remove all planar reflections (avoid lag effect). */
+ common_data->prb_num_planar = 0;
+ /* Turn off ssr to avoid black specular */
+ /* TODO : Enable SSR in planar reflections? (Would be very heavy) */
+ common_data->ssr_toggle = false;
+ common_data->sss_toggle = false;
+
+ DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
+
for (int i = 0; (ob = pinfo->probes_planar_ref[i]) && (i < MAX_PLANAR); i++) {
EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
if (!ped->need_update) {
continue;
}
- /* Temporary Remove all planar reflections (avoid lag effect). */
- int tmp_num_planar = pinfo->num_planar;
- pinfo->num_planar = 0;
render_scene_to_planar(sldata, vedata, i, ped->viewmat, ped->persmat, ped->planer_eq_offset);
- /* Restore */
- pinfo->num_planar = tmp_num_planar;
ped->need_update = false;
ped->probe_id = i;
}
+
+ /* Restore */
+ common_data->prb_num_planar = pinfo->num_planar;
+ common_data->ssr_toggle = true;
+ common_data->sss_toggle = true;
+
/* If there is at least one planar probe */
if (pinfo->num_planar > 0 && (vedata->stl->effects->enabled_effects & EFFECT_SSR) != 0) {
const int max_lod = 9;
DRW_stats_group_start("Planar Probe Downsample");
DRW_framebuffer_recursive_downsample(vedata->fbl->downsample_fb, txl->planar_pool, max_lod, &downsample_planar, vedata);
/* For shading, save max level of the planar map */
- pinfo->lod_planar_max = (float)(max_lod);
+ common_data->prb_lod_planar_max = (float)(max_lod);
DRW_stats_group_end();
}
}
static void lightprobes_refresh_cube(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
@@ -1466,11 +1480,11 @@ static void lightprobes_refresh_cube(EEVEE_ViewLayerData *sldata, EEVEE_Data *ve
}
LightProbe *prb = (LightProbe *)ob->data;
render_scene_to_probe(sldata, vedata, ob->obmat[3], prb->clipsta, prb->clipend);
- glossy_filter_probe(sldata, vedata, psl, i);
+ glossy_filter_probe(sldata, vedata, psl, i, prb->intensity);
ped->need_update = false;
ped->probe_id = i;
if (!ped->ready_to_shade) {
- pinfo->num_render_cube++;
+ common_data->prb_num_render_cube++;
ped->ready_to_shade = true;
}
#if 0
@@ -1487,6 +1501,7 @@ static void lightprobes_refresh_cube(EEVEE_ViewLayerData *sldata, EEVEE_Data *ve
static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
@@ -1506,7 +1521,7 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_
/* Reflection probes depend on diffuse lighting thus on irradiance grid,
* so update them first. */
while (pinfo->updated_bounce < pinfo->num_bounce) {
- pinfo->num_render_grid = pinfo->num_grid;
+ common_data->prb_num_render_grid = pinfo->num_grid;
/* TODO(sergey): This logic can be split into smaller functions. */
for (int i = 1; (ob = pinfo->probes_grid_ref[i]) && (i < MAX_GRID); i++) {
EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
@@ -1550,16 +1565,16 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_
lightprobe_cell_world_location_get(egrid, grid_loc, pos);
SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
/* Temporary Remove all probes. */
- int tmp_num_render_grid = pinfo->num_render_grid;
- int tmp_num_render_cube = pinfo->num_render_cube;
- int tmp_num_planar = pinfo->num_planar;
+ int tmp_num_render_grid = common_data->prb_num_render_grid;
+ int tmp_num_render_cube = common_data->prb_num_render_cube;
+ int tmp_num_planar = common_data->prb_num_planar;
float tmp_level_bias = egrid->level_bias;
- pinfo->num_render_cube = 0;
- pinfo->num_planar = 0;
+ common_data->prb_num_render_cube = 0;
+ common_data->prb_num_planar = 0;
/* Use light from previous bounce when capturing radiance. */
if (pinfo->updated_bounce == 0) {
/* But not on first bounce. */
- pinfo->num_render_grid = 0;
+ common_data->prb_num_render_grid = 0;
}
else {
/* Remove bias */
@@ -1568,14 +1583,15 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_
}
render_scene_to_probe(sldata, vedata, pos, prb->clipsta, prb->clipend);
diffuse_filter_probe(sldata, vedata, psl, egrid->offset + cell_id,
- prb->clipsta, prb->clipend, egrid->visibility_range, prb->vis_blur);
+ prb->clipsta, prb->clipend, egrid->visibility_range, prb->vis_blur,
+ prb->intensity);
/* To see what is going on. */
SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
/* Restore */
- pinfo->num_render_cube = tmp_num_render_cube;
+ common_data->prb_num_render_cube = tmp_num_render_cube;
pinfo->num_planar = tmp_num_planar;
if (pinfo->updated_bounce == 0) {
- pinfo->num_render_grid = tmp_num_render_grid;
+ common_data->prb_num_render_grid = tmp_num_render_grid;
}
else {
egrid->level_bias = tmp_level_bias;
@@ -1603,7 +1619,7 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_
}
pinfo->updated_bounce++;
- pinfo->num_render_grid = pinfo->num_grid;
+ common_data->prb_num_render_grid = pinfo->num_grid;
if (pinfo->updated_bounce < pinfo->num_bounce) {
/* Retag all grids to update for next bounce */
@@ -1631,18 +1647,39 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_
void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
+
+ /* Disable specular lighting when rendering probes to avoid feedback loops (looks bad). */
+ common_data->spec_toggle = false;
+ common_data->ssr_toggle = false;
+ common_data->sss_toggle = false;
+
+ /* Disable AO until we find a way to hide really bad discontinuities between cubefaces. */
+ float tmp_ao_dist = common_data->ao_dist;
+ float tmp_ao_settings = common_data->ao_settings;
+ common_data->ao_settings = 0.0f;
+ common_data->ao_dist = 0.0f;
+
/* Render world in priority */
if (e_data.update_world) {
lightprobes_refresh_world(sldata, vedata);
}
- else if (true) { /* TODO if at least one probe needs refresh */
+ else if (pinfo->do_cube_update || (pinfo->updated_bounce < pinfo->num_bounce)) {
lightprobes_refresh_all_no_world(sldata, vedata);
}
+ /* Restore */
+ common_data->spec_toggle = true;
+ common_data->ssr_toggle = true;
+ common_data->sss_toggle = true;
+ common_data->ao_dist = tmp_ao_dist;
+ common_data->ao_settings = tmp_ao_settings;
+
lightprobes_refresh_planar(sldata, vedata);
/* Disable SSR if we cannot read previous frame */
- sldata->probes->ssr_toggle = vedata->stl->g_data->valid_double_buffer;
+ common_data->ssr_toggle = vedata->stl->g_data->valid_double_buffer;
}
void EEVEE_lightprobes_free(void)
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
index 63c0b540cdf..69b58bf9670 100644
--- a/source/blender/draw/engines/eevee/eevee_lights.c
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -289,7 +289,7 @@ void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
/* Step 1 find all lamps in the scene and setup them */
if (linfo->num_light >= MAX_LIGHT) {
- printf("Too much lamps in the scene !!!\n");
+ printf("Too many lamps in the scene !!!\n");
}
else {
Lamp *la = (Lamp *)ob->data;
@@ -484,6 +484,8 @@ void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata)
EEVEE_LampsInfo *linfo = sldata->lamps;
DRWTextureFormat shadow_pool_format = DRW_TEX_R_32;
+ sldata->common_data.la_num_light = linfo->num_light;
+
/* Setup enough layers. */
/* Free textures if number mismatch. */
if (linfo->num_layer != linfo->cache_num_layer) {
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index e2d47ab4e98..cde14f0efc3 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -70,7 +70,7 @@ static struct {
unsigned int sss_count;
- float viewvecs[2][4];
+ float view_vecs[2][4];
float alpha_hash_offset;
float noise_offsets[3];
} e_data = {NULL}; /* Engine data */
@@ -88,6 +88,7 @@ extern char datatoc_btdf_lut_frag_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_bsdf_direct_lib_glsl[];
extern char datatoc_bsdf_sampling_lib_glsl[];
+extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_irradiance_lib_glsl[];
extern char datatoc_octahedron_lib_glsl[];
extern char datatoc_lit_surface_frag_glsl[];
@@ -361,65 +362,59 @@ static char *eevee_get_volume_defines(int options)
**/
static void add_standard_uniforms(
DRWShadingGroup *shgrp, EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
- int *ssr_id, float *refract_depth, bool use_ssrefraction, bool use_alpha_blend, bool use_sss)
+ int *ssr_id, float *refract_depth, bool use_ssrefraction, bool use_alpha_blend)
{
if (ssr_id == NULL) {
static int no_ssr = -1.0f;
ssr_id = &no_ssr;
}
+
DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_int(shgrp, "light_count", &sldata->lamps->num_light, 1);
- DRW_shgroup_uniform_int(shgrp, "probe_count", &sldata->probes->num_render_cube, 1);
- DRW_shgroup_uniform_int(shgrp, "grid_count", &sldata->probes->num_render_grid, 1);
- DRW_shgroup_uniform_int(shgrp, "planar_count", &sldata->probes->num_planar, 1);
- DRW_shgroup_uniform_bool(shgrp, "specToggle", &sldata->probes->specular_toggle, 1);
- DRW_shgroup_uniform_bool(shgrp, "ssrToggle", &sldata->probes->ssr_toggle, 1);
- DRW_shgroup_uniform_float(shgrp, "lodCubeMax", &sldata->probes->lod_cube_max, 1);
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
- DRW_shgroup_uniform_buffer(shgrp, "probeCubes", &sldata->probe_pool);
- DRW_shgroup_uniform_buffer(shgrp, "probePlanars", &vedata->txl->planar_pool);
- DRW_shgroup_uniform_buffer(shgrp, "irradianceGrid", &sldata->irradiance_pool);
- DRW_shgroup_uniform_int(shgrp, "irradianceVisibilitySize", &sldata->probes->irradiance_vis_size, 1);
- DRW_shgroup_uniform_buffer(shgrp, "shadowTexture", &sldata->shadow_pool);
- DRW_shgroup_uniform_int(shgrp, "outputSsrId", ssr_id, 1);
- DRW_shgroup_uniform_vec4(shgrp, "aoParameters[0]", &vedata->stl->effects->ao_dist, 2);
- DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)vedata->stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_buffer(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer);
- DRW_shgroup_uniform_vec2(shgrp, "mipRatio[0]", (float *)vedata->stl->g_data->mip_ratio, 10);
- DRW_shgroup_uniform_vec4(shgrp, "ssrParameters", &vedata->stl->effects->ssr_quality, 1);
-
- if (refract_depth != NULL) {
- DRW_shgroup_uniform_float(shgrp, "refractionDepth", refract_depth, 1);
+ DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
+
+ /* TODO if glossy or diffuse bsdf */
+ if (true) {
+ DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
+ DRW_shgroup_uniform_buffer(shgrp, "shadowTexture", &sldata->shadow_pool);
+ DRW_shgroup_uniform_buffer(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer);
+
+ if ((vedata->stl->effects->enabled_effects & EFFECT_GTAO) != 0) {
+ DRW_shgroup_uniform_buffer(shgrp, "horizonBuffer", &vedata->txl->gtao_horizons);
+ }
+ else {
+ /* Use maxzbuffer as fallback to avoid sampling problem on certain platform, see: T52593 */
+ DRW_shgroup_uniform_buffer(shgrp, "horizonBuffer", &vedata->txl->maxzbuffer);
+ }
}
- if (use_ssrefraction) {
- DRW_shgroup_uniform_buffer(shgrp, "colorBuffer", &vedata->txl->refract_color);
- DRW_shgroup_uniform_float(shgrp, "borderFadeFactor", &vedata->stl->effects->ssr_border_fac, 1);
- DRW_shgroup_uniform_float(shgrp, "maxRoughness", &vedata->stl->effects->ssr_max_roughness, 1);
+ /* TODO if diffuse bsdf */
+ if (true) {
+ DRW_shgroup_uniform_buffer(shgrp, "irradianceGrid", &sldata->irradiance_pool);
}
- if (vedata->stl->effects->use_ao) {
- DRW_shgroup_uniform_buffer(shgrp, "horizonBuffer", &vedata->txl->gtao_horizons);
+ /* TODO if glossy bsdf */
+ if (true) {
+ DRW_shgroup_uniform_buffer(shgrp, "probeCubes", &sldata->probe_pool);
+ DRW_shgroup_uniform_buffer(shgrp, "probePlanars", &vedata->txl->planar_pool);
+ DRW_shgroup_uniform_int(shgrp, "outputSsrId", ssr_id, 1);
}
- else {
- /* Use maxzbuffer as fallback to avoid sampling problem on certain platform, see: T52593 */
- DRW_shgroup_uniform_buffer(shgrp, "horizonBuffer", &vedata->txl->maxzbuffer);
+
+ if (use_ssrefraction) {
+ BLI_assert(refract_depth != NULL);
+ DRW_shgroup_uniform_float(shgrp, "refractionDepth", refract_depth, 1);
+ DRW_shgroup_uniform_buffer(shgrp, "colorBuffer", &vedata->txl->refract_color);
}
- if (vedata->stl->effects->use_volumetrics && use_alpha_blend) {
+ if ((vedata->stl->effects->enabled_effects & EFFECT_VOLUMETRIC) != 0 &&
+ use_alpha_blend)
+ {
/* Do not use history buffers as they already have been swapped */
DRW_shgroup_uniform_buffer(shgrp, "inScattering", &vedata->txl->volume_scatter);
DRW_shgroup_uniform_buffer(shgrp, "inTransmittance", &vedata->txl->volume_transmittance);
- DRW_shgroup_uniform_vec2(shgrp, "volume_uv_ratio", (float *)sldata->volumetrics->volume_coord_scale, 1);
- DRW_shgroup_uniform_vec3(shgrp, "volume_param", (float *)sldata->volumetrics->depth_param, 1);
- }
-
- if (use_sss) {
- DRW_shgroup_uniform_bool(shgrp, "sssToggle", &sldata->probes->sss_toggle, 1);
}
}
@@ -507,11 +502,12 @@ void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, double
DRW_framebuffer_texture_detach(e_data.util_tex);
}
-void EEVEE_materials_init(EEVEE_StorageList *stl, EEVEE_FramebufferList *fbl)
+void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, EEVEE_FramebufferList *fbl)
{
if (!e_data.frag_shader_lib) {
/* Shaders */
e_data.frag_shader_lib = BLI_string_joinN(
+ datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_bsdf_sampling_lib_glsl,
datatoc_ambient_occlusion_lib_glsl,
@@ -535,6 +531,7 @@ void EEVEE_materials_init(EEVEE_StorageList *stl, EEVEE_FramebufferList *fbl)
datatoc_volumetric_lib_glsl);
e_data.volume_shader_lib = BLI_string_joinN(
+ datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_ambient_occlusion_lib_glsl,
datatoc_octahedron_lib_glsl,
@@ -601,12 +598,12 @@ void EEVEE_materials_init(EEVEE_StorageList *stl, EEVEE_FramebufferList *fbl)
}
{
- /* Update viewvecs */
+ /* Update view_vecs */
const bool is_persp = DRW_viewport_is_persp_get();
float invproj[4][4], winmat[4][4];
/* view vectors for the corners of the view frustum.
* Can be used to recreate the world space position easily */
- float viewvecs[3][4] = {
+ float view_vecs[3][4] = {
{-1.0f, -1.0f, -1.0f, 1.0f},
{1.0f, -1.0f, -1.0f, 1.0f},
{-1.0f, 1.0f, -1.0f, 1.0f}
@@ -618,28 +615,28 @@ void EEVEE_materials_init(EEVEE_StorageList *stl, EEVEE_FramebufferList *fbl)
/* convert the view vectors to view space */
for (int i = 0; i < 3; i++) {
- mul_m4_v4(invproj, viewvecs[i]);
+ mul_m4_v4(invproj, view_vecs[i]);
/* normalized trick see:
* http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
- mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
+ mul_v3_fl(view_vecs[i], 1.0f / view_vecs[i][3]);
if (is_persp)
- mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
- viewvecs[i][3] = 1.0;
+ mul_v3_fl(view_vecs[i], 1.0f / view_vecs[i][2]);
+ view_vecs[i][3] = 1.0;
}
- copy_v4_v4(stl->g_data->viewvecs[0], viewvecs[0]);
- copy_v4_v4(stl->g_data->viewvecs[1], viewvecs[1]);
+ copy_v4_v4(sldata->common_data.view_vecs[0], view_vecs[0]);
+ copy_v4_v4(sldata->common_data.view_vecs[1], view_vecs[1]);
/* we need to store the differences */
- stl->g_data->viewvecs[1][0] -= viewvecs[0][0];
- stl->g_data->viewvecs[1][1] = viewvecs[2][1] - viewvecs[0][1];
+ sldata->common_data.view_vecs[1][0] -= view_vecs[0][0];
+ sldata->common_data.view_vecs[1][1] = view_vecs[2][1] - view_vecs[0][1];
/* calculate a depth offset as well */
if (!is_persp) {
float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
mul_m4_v4(invproj, vec_far);
mul_v3_fl(vec_far, 1.0f / vec_far[3]);
- stl->g_data->viewvecs[1][2] = vec_far[2] - viewvecs[0][2];
+ sldata->common_data.view_vecs[1][2] = vec_far[2] - view_vecs[0][2];
}
}
@@ -707,6 +704,7 @@ struct GPUMaterial *EEVEE_material_mesh_get(
struct Scene *scene, Material *ma, EEVEE_Data *vedata,
bool use_blend, bool use_multiply, bool use_refract, bool use_sss, bool use_translucency, int shadow_method)
{
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
const void *engine = &DRW_engine_viewport_eevee_type;
int options = VAR_MAT_MESH;
@@ -714,9 +712,9 @@ struct GPUMaterial *EEVEE_material_mesh_get(
if (use_multiply) options |= VAR_MAT_MULT;
if (use_refract) options |= VAR_MAT_REFRACT;
if (use_sss) options |= VAR_MAT_SSS;
- if (use_sss && vedata->stl->effects->sss_separate_albedo) options |= VAR_MAT_SSSALBED;
+ if (use_sss && effects->sss_separate_albedo) options |= VAR_MAT_SSSALBED;
if (use_translucency) options |= VAR_MAT_TRANSLUC;
- if (vedata->stl->effects->use_volumetrics && use_blend) options |= VAR_MAT_VOLUME;
+ if (((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) && use_blend) options |= VAR_MAT_VOLUME;
options |= eevee_material_shadow_option(shadow_method);
@@ -843,6 +841,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_create(
EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, DRWPass *pass,
bool is_hair, bool is_hair_fibers, bool is_flat_normal, bool use_blend, bool use_ssr, int shadow_method)
{
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
static int ssr_id;
ssr_id = (use_ssr) ? 1 : -1;
int options = VAR_MAT_MESH;
@@ -851,7 +850,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_create(
if (is_hair_fibers) options |= VAR_MAT_HAIR_FIBERS;
if (is_flat_normal) options |= VAR_MAT_FLAT;
if (use_blend) options |= VAR_MAT_BLEND;
- if (vedata->stl->effects->use_volumetrics && use_blend) options |= VAR_MAT_VOLUME;
+ if (((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) && use_blend) options |= VAR_MAT_VOLUME;
options |= eevee_material_shadow_option(shadow_method);
@@ -860,7 +859,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_create(
}
DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], pass);
- add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, use_blend, false);
+ add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, use_blend);
return shgrp;
}
@@ -892,7 +891,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get(
vedata->psl->default_pass[options] = DRW_pass_create("Default Lit Pass", state);
DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]);
- add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, false, false);
+ add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, false);
}
return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]);
@@ -903,19 +902,6 @@ void EEVEE_materials_cache_init(EEVEE_Data *vedata)
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
- {
- const DRWContextState *draw_ctx = DRW_context_state_get();
- ViewLayer *view_layer = draw_ctx->view_layer;
- IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
- /* Global AO Switch*/
- stl->effects->use_ao = BKE_collection_engine_property_value_get_bool(props, "gtao_enable");
- stl->effects->use_bent_normals = BKE_collection_engine_property_value_get_bool(props, "gtao_use_bent_normals");
- /* SSR switch */
- stl->effects->use_ssr = BKE_collection_engine_property_value_get_bool(props, "ssr_enable");
- /* Volumetrics */
- stl->effects->use_volumetrics = BKE_collection_engine_property_value_get_bool(props, "volumetric_enable");
- }
-
/* Create Material Ghash */
{
stl->g_data->material_hash = BLI_ghash_ptr_new("Eevee_material ghash");
@@ -1059,6 +1045,7 @@ static void material_opaque(
bool do_cull, bool use_flat_nor, struct GPUMaterial **gpumat, struct GPUMaterial **gpumat_depth,
struct DRWShadingGroup **shgrp, struct DRWShadingGroup **shgrp_depth, struct DRWShadingGroup **shgrp_depth_clip)
{
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
@@ -1072,9 +1059,9 @@ static void material_opaque(
const bool use_gpumat = (ma->use_nodes && ma->nodetree);
const bool use_refract = ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) &&
- ((stl->effects->enabled_effects & EFFECT_REFRACT) != 0);
+ ((effects->enabled_effects & EFFECT_REFRACT) != 0);
const bool use_sss = ((ma->blend_flag & MA_BL_SS_SUBSURFACE) != 0) &&
- ((stl->effects->enabled_effects & EFFECT_SSS) != 0);
+ ((effects->enabled_effects & EFFECT_SSS) != 0);
const bool use_translucency = use_sss && ((ma->blend_flag & MA_BL_TRANSLUCENCY) != 0);
EeveeMaterialShadingGroups *emsg = BLI_ghash_lookup(material_hash, (const void *)ma);
@@ -1103,8 +1090,8 @@ static void material_opaque(
if (*shgrp) {
static int no_ssr = -1;
static int first_ssr = 1;
- int *ssr_id = (stl->effects->use_ssr && !use_refract) ? &first_ssr : &no_ssr;
- add_standard_uniforms(*shgrp, sldata, vedata, ssr_id, &ma->refract_depth, use_refract, false, use_sss);
+ int *ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_refract) ? &first_ssr : &no_ssr;
+ add_standard_uniforms(*shgrp, sldata, vedata, ssr_id, &ma->refract_depth, use_refract, false);
if (use_sss) {
struct GPUTexture *sss_tex_profile = NULL;
@@ -1119,7 +1106,7 @@ static void material_opaque(
}
DRW_shgroup_stencil_mask(*shgrp, e_data.sss_count + 1);
- EEVEE_subsurface_add_pass(vedata, e_data.sss_count + 1, sss_profile);
+ EEVEE_subsurface_add_pass(sldata, vedata, e_data.sss_count + 1, sss_profile);
e_data.sss_count++;
}
}
@@ -1149,7 +1136,7 @@ static void material_opaque(
}
if (*shgrp_depth != NULL) {
- add_standard_uniforms(*shgrp_depth, sldata, vedata, NULL, NULL, false, false, false);
+ add_standard_uniforms(*shgrp_depth, sldata, vedata, NULL, NULL, false, false);
if (ma->blend_method == MA_BM_CLIP) {
DRW_shgroup_uniform_float(*shgrp_depth, "alphaThreshold", &ma->alpha_threshold, 1);
@@ -1165,7 +1152,8 @@ static void material_opaque(
/* Fallback to default shader */
if (*shgrp == NULL) {
- *shgrp = EEVEE_default_shading_group_get(sldata, vedata, false, false, use_flat_nor, stl->effects->use_ssr, linfo->shadow_method);
+ bool use_ssr = ((effects->enabled_effects & EFFECT_SSR) != 0);
+ *shgrp = EEVEE_default_shading_group_get(sldata, vedata, false, false, use_flat_nor, use_ssr, linfo->shadow_method);
DRW_shgroup_uniform_vec3(*shgrp, "basecol", color_p, 1);
DRW_shgroup_uniform_float(*shgrp, "metallic", metal_p, 1);
DRW_shgroup_uniform_float(*shgrp, "specular", spec_p, 1);
@@ -1217,7 +1205,7 @@ static void material_transparent(
if (*shgrp) {
static int ssr_id = -1; /* TODO transparent SSR */
bool use_blend = (ma->blend_method & MA_BM_BLEND) != 0;
- add_standard_uniforms(*shgrp, sldata, vedata, &ssr_id, &ma->refract_depth, use_refract, use_blend, false);
+ add_standard_uniforms(*shgrp, sldata, vedata, &ssr_id, &ma->refract_depth, use_refract, use_blend);
}
else {
/* Shader failed : pink color */
@@ -1332,7 +1320,7 @@ static void material_particle_hair(
shgrp = DRW_shgroup_material_create(gpumat, psl->material_pass);
if (shgrp) {
- add_standard_uniforms(shgrp, sldata, vedata, NULL, NULL, false, false, false);
+ add_standard_uniforms(shgrp, sldata, vedata, NULL, NULL, false, false);
BLI_ghash_insert(material_hash, ma, shgrp);
}
@@ -1348,7 +1336,9 @@ static void material_particle_hair(
/* Fallback to default shader */
if (shgrp == NULL) {
- shgrp = EEVEE_default_shading_group_get(sldata, vedata, true, false, false, stl->effects->use_ssr, sldata->lamps->shadow_method);
+ bool use_ssr = ((stl->effects->enabled_effects & EFFECT_SSR) != 0);
+ shgrp = EEVEE_default_shading_group_get(sldata, vedata, true, false, false, use_ssr,
+ sldata->lamps->shadow_method);
DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1);
DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1);
DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1);
@@ -1415,7 +1405,7 @@ static void material_hair(
shgrp = DRW_shgroup_material_create(gpumat, psl->material_pass);
if (shgrp) {
- add_standard_uniforms(shgrp, sldata, vedata, NULL, NULL, false, false, false);
+ add_standard_uniforms(shgrp, sldata, vedata, NULL, NULL, false, false);
BLI_ghash_insert(material_hash, ma, shgrp);
}
else {
@@ -1430,7 +1420,9 @@ static void material_hair(
/* Fallback to default shader */
if (shgrp == NULL) {
- shgrp = EEVEE_default_shading_group_get(sldata, vedata, true, true, false, stl->effects->use_ssr, sldata->lamps->shadow_method);
+ bool use_ssr = ((stl->effects->enabled_effects & EFFECT_SSR) != 0);
+ shgrp = EEVEE_default_shading_group_get(sldata, vedata, true, true, false, use_ssr,
+ sldata->lamps->shadow_method);
DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1);
DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1);
DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1);
@@ -1589,7 +1581,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld
}
/* Volumetrics */
- if (vedata->stl->effects->use_volumetrics && use_volume_material) {
+ if (((stl->effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) && use_volume_material) {
EEVEE_volumes_cache_object_add(sldata, vedata, scene, ob);
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c
index f6f3bcd060e..9da438e825f 100644
--- a/source/blender/draw/engines/eevee/eevee_occlusion.c
+++ b/source/blender/draw/engines/eevee/eevee_occlusion.c
@@ -44,12 +44,14 @@ static struct {
} e_data = {NULL}; /* Engine data */
extern char datatoc_ambient_occlusion_lib_glsl[];
+extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_effect_gtao_frag_glsl[];
static void eevee_create_shader_occlusion(void)
{
char *frag_str = BLI_string_joinN(
+ datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_ambient_occlusion_lib_glsl,
datatoc_effect_gtao_frag_glsl);
@@ -61,12 +63,12 @@ static void eevee_create_shader_occlusion(void)
MEM_freeN(frag_str);
}
-int EEVEE_occlusion_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
- EEVEE_EffectsInfo *effects = stl->effects;
const DRWContextState *draw_ctx = DRW_context_state_get();
ViewLayer *view_layer = draw_ctx->view_layer;
@@ -82,22 +84,19 @@ int EEVEE_occlusion_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata
eevee_create_shader_occlusion();
}
- effects->ao_dist = BKE_collection_engine_property_value_get_float(props, "gtao_distance");
- effects->ao_factor = BKE_collection_engine_property_value_get_float(props, "gtao_factor");
- effects->ao_quality = 1.0f - BKE_collection_engine_property_value_get_float(props, "gtao_quality");
+ common_data->ao_dist = BKE_collection_engine_property_value_get_float(props, "gtao_distance");
+ common_data->ao_factor = BKE_collection_engine_property_value_get_float(props, "gtao_factor");
+ common_data->ao_quality = 1.0f - BKE_collection_engine_property_value_get_float(props, "gtao_quality");
- effects->ao_settings = 1.0; /* USE_AO */
+ common_data->ao_settings = 1.0; /* USE_AO */
if (BKE_collection_engine_property_value_get_bool(props, "gtao_use_bent_normals")) {
- effects->ao_settings += 2.0; /* USE_BENT_NORMAL */
+ common_data->ao_settings += 2.0; /* USE_BENT_NORMAL */
}
if (BKE_collection_engine_property_value_get_bool(props, "gtao_denoise")) {
- effects->ao_settings += 4.0; /* USE_DENOISE */
+ common_data->ao_settings += 4.0; /* USE_DENOISE */
}
- effects->ao_bounce_fac = (float)BKE_collection_engine_property_value_get_bool(props, "gtao_bounce");
-
- effects->ao_texsize[0] = ((int)viewport_size[0]);
- effects->ao_texsize[1] = ((int)viewport_size[1]);
+ common_data->ao_bounce_fac = (float)BKE_collection_engine_property_value_get_bool(props, "gtao_bounce");
DRWFboTexture tex = {&txl->gtao_horizons, DRW_TEX_RGBA_8, 0};
@@ -119,12 +118,12 @@ int EEVEE_occlusion_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata
/* Cleanup */
DRW_TEXTURE_FREE_SAFE(txl->gtao_horizons);
DRW_FRAMEBUFFER_FREE_SAFE(fbl->gtao_fb);
- effects->ao_settings = 0.0f;
+ common_data->ao_settings = 0.0f;
return 0;
}
-void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
@@ -148,36 +147,30 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
**/
psl->ao_horizon_search = DRW_pass_create("GTAO Horizon Search", DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(e_data.gtao_sh, psl->ao_horizon_search);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer);
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &effects->ao_src_depth);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_vec2(grp, "mipRatio[0]", (float *)stl->g_data->mip_ratio, 10);
- DRW_shgroup_uniform_vec4(grp, "aoParameters[0]", &stl->effects->ao_dist, 2);
- DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_call_add(grp, quad, NULL);
psl->ao_horizon_search_layer = DRW_pass_create("GTAO Horizon Search Layer", DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_create(e_data.gtao_layer_sh, psl->ao_horizon_search_layer);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer);
DRW_shgroup_uniform_buffer(grp, "depthBufferLayered", &effects->ao_src_depth);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_uniform_int(grp, "layer", &stl->effects->ao_depth_layer, 1);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_vec2(grp, "mipRatio[0]", (float *)stl->g_data->mip_ratio, 10);
- DRW_shgroup_uniform_vec4(grp, "aoParameters[0]", &stl->effects->ao_dist, 2);
- DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_call_add(grp, quad, NULL);
if (G.debug_value == 6) {
psl->ao_horizon_debug = DRW_pass_create("GTAO Horizon Debug", DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_create(e_data.gtao_debug_sh, psl->ao_horizon_debug);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer);
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input);
DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &txl->gtao_horizons);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_vec2(grp, "mipRatio[0]", (float *)stl->g_data->mip_ratio, 10);
- DRW_shgroup_uniform_vec4(grp, "aoParameters[0]", &stl->effects->ao_dist, 2);
- DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_call_add(grp, quad, NULL);
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 16544f185df..22440fb62c6 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -344,18 +344,6 @@ typedef struct EEVEE_ShadowCasterBuffer {
unsigned int count;
} EEVEE_ShadowCasterBuffer;
-/* ************ VOLUME DATA ************ */
-typedef struct EEVEE_VolumetricsInfo {
- float integration_step_count, shadow_step_count, sample_distribution, light_clamp;
- float integration_start, integration_end;
- float depth_param[3], history_alpha;
- bool use_lights, use_volume_shadows;
- int froxel_tex_size[3];
- float inv_tex_size[3];
- float volume_coord_scale[2];
- float jitter[3];
-} EEVEE_VolumetricsInfo;
-
/* ************ LIGHT DATA ************* */
typedef struct EEVEE_LampsInfo {
int num_light, cache_num_light;
@@ -441,12 +429,9 @@ typedef struct EEVEE_LightProbesInfo {
int num_bounce;
int cubemap_res;
int target_size;
- int irradiance_vis_size;
int grid_initialized;
struct World *prev_world;
- /* Actual number of probes that have datas. */
- int num_render_cube;
- int num_render_grid;
+ bool do_cube_update;
/* For rendering probes */
float probemat[6][4][4];
int layer;
@@ -461,11 +446,8 @@ typedef struct EEVEE_LightProbesInfo {
float lod_rt_max, lod_cube_max, lod_planar_max;
float visibility_range;
float visibility_blur;
+ float intensity_fac;
int shres;
- int shnbr;
- int specular_toggle;
- int ssr_toggle;
- int sss_toggle;
/* List of probes in the scene. */
/* XXX This is fragile, can get out of sync quickly. */
struct Object *probes_cube_ref[MAX_PROBE];
@@ -488,30 +470,15 @@ enum {
typedef struct EEVEE_EffectsInfo {
int enabled_effects;
bool swap_double_buffer;
-
/* SSSS */
int sss_sample_count;
- float sss_jitter_threshold;
bool sss_separate_albedo;
-
/* Volumetrics */
- bool use_volumetrics;
int volume_current_sample;
-
/* SSR */
- bool use_ssr;
bool reflection_trace_full;
- bool ssr_use_normalization;
int ssr_neighbor_ofs;
int ssr_halfres_ofs[2];
- float ssr_brdf_bias;
- float ssr_firefly_fac;
- float ssr_border_fac;
- float ssr_max_roughness;
- float ssr_quality;
- float ssr_thickness;
- float ssr_pixelsize[2];
-
/* Temporal Anti Aliasing */
int taa_current_sample;
int taa_render_sample;
@@ -523,29 +490,19 @@ typedef struct EEVEE_EffectsInfo {
float overide_persinv[4][4];
float overide_winmat[4][4];
float overide_wininv[4][4];
-
/* Ambient Occlusion */
- bool use_ao, use_bent_normals;
- float ao_dist, pad1, ao_factor, pad2;
- float ao_offset, ao_bounce_fac, ao_quality, ao_settings;
- float ao_sample_nbr;
- int ao_texsize[2], hori_tex_layers;
int ao_depth_layer;
struct GPUTexture *ao_src_depth; /* pointer copy */
-
/* Motion Blur */
float current_ndc_to_world[4][4];
float past_world_to_ndc[4][4];
- float tmp_mat[4][4];
int motion_blur_samples;
-
/* Depth Of Field */
float dof_near_far[2];
float dof_params[3];
float dof_bokeh[4];
float dof_layer_select[2];
int dof_target_size[2];
-
/* Bloom */
int bloom_iteration_ct;
float source_texel_size[2];
@@ -558,7 +515,6 @@ typedef struct EEVEE_EffectsInfo {
float unf_source_texel_size[2];
struct GPUTexture *unf_source_buffer; /* pointer copy */
struct GPUTexture *unf_base_buffer; /* pointer copy */
-
/* Not alloced, just a copy of a *GPUtexture in EEVEE_TextureList. */
struct GPUTexture *source_buffer; /* latest updated texture */
struct GPUFrameBuffer *target_buffer; /* next target to render to */
@@ -579,6 +535,58 @@ enum {
EFFECT_SSS = (1 << 11),
};
+/* ***************** COMMON DATA **************** */
+
+/* Common uniform buffer containing all "constant" data over the whole drawing pipeline. */
+/* !! CAUTION !!
+ * - [i]vec3 need to be paded to [i]vec4 (even in ubo declaration).
+ * - Make sure that [i]vec4 start at a multiple of 16 bytes.
+ * - Arrays of vec2/vec3 are padded as arrays of vec4.
+ * - sizeof(bool) == sizeof(int) in GLSL so use int in C */
+typedef struct EEVEE_CommonUniformBuffer {
+ float prev_persmat[4][4]; /* mat4 */
+ float view_vecs[2][4]; /* vec4[2] */
+ float mip_ratio[10][4]; /* vec2[10] */
+ /* Ambient Occlusion */
+ /* -- 16 byte aligned -- */
+ float ao_dist, pad1, ao_factor, pad2; /* vec4 */
+ float ao_offset, ao_bounce_fac, ao_quality, ao_settings; /* vec4 */
+ /* Volumetric */
+ /* -- 16 byte aligned -- */
+ int vol_tex_size[3], pad3; /* ivec3 */
+ float vol_depth_param[3], pad4; /* vec3 */
+ float vol_inv_tex_size[3], pad5; /* vec3 */
+ float vol_jitter[3], pad6; /* vec3 */
+ float vol_coord_scale[2], pad7[2]; /* vec2 */
+ /* -- 16 byte aligned -- */
+ float vol_history_alpha; /* float */
+ float vol_light_clamp; /* float */
+ float vol_shadow_steps; /* float */
+ int vol_use_lights; /* bool */
+ /* Screen Space Reflections */
+ /* -- 16 byte aligned -- */
+ float ssr_quality, ssr_thickness, ssr_pixelsize[2]; /* vec4 */
+ float ssr_border_fac; /* float */
+ float ssr_max_roughness; /* float */
+ float ssr_firefly_fac; /* float */
+ float ssr_brdf_bias; /* float */
+ int ssr_toggle; /* bool */
+ /* SubSurface Scattering */
+ float sss_jitter_threshold; /* float */
+ int sss_toggle; /* bool */
+ /* Specular */
+ int spec_toggle; /* bool */
+ /* Lamps */
+ int la_num_light; /* int */
+ /* Probes */
+ int prb_num_planar; /* int */
+ int prb_num_render_cube; /* int */
+ int prb_num_render_grid; /* int */
+ int prb_irradiance_vis_size; /* int */
+ float prb_lod_cube_max; /* float */
+ float prb_lod_planar_max; /* float */
+} EEVEE_CommonUniformBuffer;
+
/* ************** SCENE LAYER DATA ************** */
typedef struct EEVEE_ViewLayerData {
/* Lamps */
@@ -616,10 +624,9 @@ typedef struct EEVEE_ViewLayerData {
struct GPUTexture *irradiance_pool;
struct GPUTexture *irradiance_rt;
- struct ListBase probe_queue; /* List of probes to update */
-
- /* Volumetrics */
- struct EEVEE_VolumetricsInfo *volumetrics;
+ /* Common Uniform Buffer */
+ struct EEVEE_CommonUniformBuffer common_data;
+ struct GPUUniformBuffer *common_ubo;
} EEVEE_ViewLayerData;
/* ************ OBJECT DATA ************ */
@@ -717,15 +724,11 @@ typedef struct EEVEE_PrivateData {
struct GPUTexture *ssr_pdf_output;
struct GPUTexture *gtao_horizons_debug;
float background_alpha; /* TODO find a better place for this. */
- float viewvecs[2][4];
/* For planar probes */
- float texel_size[2];
- /* To correct mip level texel mis-alignement */
- float mip_ratio[10][2]; /* TODO put in a UBO */
+ float planar_texel_size[2];
/* For double buffering */
bool view_updated;
bool valid_double_buffer;
- float prev_persmat[4][4];
} EEVEE_PrivateData; /* Transient data */
/* eevee_data.c */
@@ -740,7 +743,7 @@ EEVEE_LampEngineData *EEVEE_lamp_data_ensure(Object *ob);
/* eevee_materials.c */
struct GPUTexture *EEVEE_materials_get_util_tex(void); /* XXX */
-void EEVEE_materials_init(EEVEE_StorageList *stl, EEVEE_FramebufferList *fbl);
+void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, EEVEE_FramebufferList *fbl);
void EEVEE_materials_cache_init(EEVEE_Data *vedata);
void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob);
void EEVEE_materials_cache_finish(EEVEE_Data *vedata);
@@ -810,7 +813,8 @@ void EEVEE_screen_raytrace_free(void);
/* eevee_subsurface.c */
int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
-void EEVEE_subsurface_add_pass(EEVEE_Data *vedata, unsigned int sss_id, struct GPUUniformBuffer *sss_profile);
+void EEVEE_subsurface_add_pass(
+ EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, unsigned int sss_id, struct GPUUniformBuffer *sss_profile);
void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_free(void);
@@ -843,7 +847,7 @@ void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, struct GPUTexture *depth_src
void EEVEE_downsample_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, struct GPUTexture *texture_src, int level);
void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, struct GPUTexture *texture_src, int level);
void EEVEE_effects_do_gtao(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
-void EEVEE_draw_effects(EEVEE_Data *vedata);
+void EEVEE_draw_effects(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_effects_free(void);
/* Shadow Matrix */
diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
index 86896a1e01a..2917bfd1236 100644
--- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
+++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
@@ -37,7 +37,8 @@
enum {
SSR_RESOLVE = (1 << 0),
SSR_FULL_TRACE = (1 << 1),
- SSR_MAX_SHADER = (1 << 2),
+ SSR_AO = (1 << 3),
+ SSR_MAX_SHADER = (1 << 4),
};
static struct {
@@ -50,6 +51,7 @@ static struct {
} e_data = {NULL}; /* Engine data */
extern char datatoc_ambient_occlusion_lib_glsl[];
+extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_bsdf_sampling_lib_glsl[];
extern char datatoc_octahedron_lib_glsl[];
@@ -61,6 +63,7 @@ static struct GPUShader *eevee_effects_screen_raytrace_shader_get(int options)
{
if (e_data.ssr_sh[options] == NULL) {
char *ssr_shader_str = BLI_string_joinN(
+ datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_bsdf_sampling_lib_glsl,
datatoc_octahedron_lib_glsl,
@@ -81,6 +84,9 @@ static struct GPUShader *eevee_effects_screen_raytrace_shader_get(int options)
if (options & SSR_FULL_TRACE) {
BLI_dynstr_appendf(ds_defines, "#define FULLRES\n");
}
+ if (options & SSR_AO) {
+ BLI_dynstr_appendf(ds_defines, "#define SSR_AO\n");
+ }
char *ssr_define_str = BLI_dynstr_get_cstring(ds_defines);
BLI_dynstr_free(ds_defines);
@@ -93,8 +99,9 @@ static struct GPUShader *eevee_effects_screen_raytrace_shader_get(int options)
return e_data.ssr_sh[options];
}
-int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
@@ -108,8 +115,8 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *
RE_engine_id_BLENDER_EEVEE);
/* Compute pixel size, (shared with contact shadows) */
- copy_v2_v2(effects->ssr_pixelsize, viewport_size);
- invert_v2(effects->ssr_pixelsize);
+ copy_v2_v2(common_data->ssr_pixelsize, viewport_size);
+ invert_v2(common_data->ssr_pixelsize);
if (BKE_collection_engine_property_value_get_bool(props, "ssr_enable")) {
const bool use_refraction = BKE_collection_engine_property_value_get_bool(props, "ssr_refraction");
@@ -124,16 +131,15 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *
bool prev_trace_full = effects->reflection_trace_full;
effects->reflection_trace_full = !BKE_collection_engine_property_value_get_bool(props, "ssr_halfres");
- effects->ssr_use_normalization = BKE_collection_engine_property_value_get_bool(props, "ssr_normalize_weight");
- effects->ssr_quality = 1.0f - 0.95f * BKE_collection_engine_property_value_get_float(props, "ssr_quality");
- effects->ssr_thickness = BKE_collection_engine_property_value_get_float(props, "ssr_thickness");
- effects->ssr_border_fac = BKE_collection_engine_property_value_get_float(props, "ssr_border_fade");
- effects->ssr_firefly_fac = BKE_collection_engine_property_value_get_float(props, "ssr_firefly_fac");
- effects->ssr_max_roughness = BKE_collection_engine_property_value_get_float(props, "ssr_max_roughness");
- effects->ssr_brdf_bias = 0.1f + effects->ssr_quality * 0.6f; /* Range [0.1, 0.7]. */
-
- if (effects->ssr_firefly_fac < 1e-8f) {
- effects->ssr_firefly_fac = FLT_MAX;
+ common_data->ssr_thickness = BKE_collection_engine_property_value_get_float(props, "ssr_thickness");
+ common_data->ssr_border_fac = BKE_collection_engine_property_value_get_float(props, "ssr_border_fade");
+ common_data->ssr_firefly_fac = BKE_collection_engine_property_value_get_float(props, "ssr_firefly_fac");
+ common_data->ssr_max_roughness = BKE_collection_engine_property_value_get_float(props, "ssr_max_roughness");
+ common_data->ssr_quality = 1.0f - 0.95f * BKE_collection_engine_property_value_get_float(props, "ssr_quality");
+ common_data->ssr_brdf_bias = 0.1f + common_data->ssr_quality * 0.6f; /* Range [0.1, 0.7]. */
+
+ if (common_data->ssr_firefly_fac < 1e-8f) {
+ common_data->ssr_firefly_fac = FLT_MAX;
}
if (prev_trace_full != effects->reflection_trace_full) {
@@ -192,6 +198,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
if ((effects->enabled_effects & EFFECT_SSR) != 0) {
int options = (effects->reflection_trace_full) ? SSR_FULL_TRACE : 0;
+ options |= ((effects->enabled_effects & EFFECT_GTAO) != 0) ? SSR_AO : 0;
struct GPUShader *trace_shader = eevee_effects_screen_raytrace_shader_get(options);
struct GPUShader *resolve_shader = eevee_effects_screen_raytrace_shader_get(SSR_RESOLVE | options);
@@ -214,16 +221,11 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input);
DRW_shgroup_uniform_buffer(grp, "specroughBuffer", &txl->ssr_specrough_input);
- DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_vec2(grp, "mipRatio[0]", (float *)stl->g_data->mip_ratio, 10);
- DRW_shgroup_uniform_vec4(grp, "ssrParameters", &effects->ssr_quality, 1);
- DRW_shgroup_uniform_int(grp, "planar_count", &sldata->probes->num_planar, 1);
- DRW_shgroup_uniform_float(grp, "maxRoughness", &effects->ssr_max_roughness, 1);
- DRW_shgroup_uniform_float(grp, "brdfBias", &effects->ssr_brdf_bias, 1);
DRW_shgroup_uniform_buffer(grp, "planarDepth", &vedata->txl->planar_depth);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
if (!effects->reflection_trace_full) {
DRW_shgroup_uniform_ivec2(grp, "halfresOffset", effects->ssr_halfres_ofs, 1);
}
@@ -234,36 +236,20 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input);
DRW_shgroup_uniform_buffer(grp, "specroughBuffer", &txl->ssr_specrough_input);
- DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
- DRW_shgroup_uniform_buffer(grp, "prevColorBuffer", &txl->color_double_buffer);
- DRW_shgroup_uniform_mat4(grp, "PastViewProjectionMatrix", (float *)stl->g_data->prev_persmat);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_int(grp, "planar_count", &sldata->probes->num_planar, 1);
- DRW_shgroup_uniform_int(grp, "probe_count", &sldata->probes->num_render_cube, 1);
- DRW_shgroup_uniform_vec2(grp, "mipRatio[0]", (float *)stl->g_data->mip_ratio, 10);
- DRW_shgroup_uniform_float(grp, "borderFadeFactor", &effects->ssr_border_fac, 1);
- DRW_shgroup_uniform_float(grp, "maxRoughness", &effects->ssr_max_roughness, 1);
- DRW_shgroup_uniform_float(grp, "lodCubeMax", &sldata->probes->lod_cube_max, 1);
- DRW_shgroup_uniform_float(grp, "lodPlanarMax", &sldata->probes->lod_planar_max, 1);
- DRW_shgroup_uniform_float(grp, "fireflyFactor", &effects->ssr_firefly_fac, 1);
- DRW_shgroup_uniform_float(grp, "brdfBias", &effects->ssr_brdf_bias, 1);
- DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_buffer(grp, "probeCubes", &sldata->probe_pool);
DRW_shgroup_uniform_buffer(grp, "probePlanars", &vedata->txl->planar_pool);
DRW_shgroup_uniform_buffer(grp, "planarDepth", &vedata->txl->planar_depth);
DRW_shgroup_uniform_buffer(grp, "hitBuffer", &vedata->txl->ssr_hit_output);
DRW_shgroup_uniform_buffer(grp, "pdfBuffer", &stl->g_data->ssr_pdf_output);
+ DRW_shgroup_uniform_buffer(grp, "prevColorBuffer", &txl->color_double_buffer);
+ DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_uniform_int(grp, "neighborOffset", &effects->ssr_neighbor_ofs, 1);
-
- DRW_shgroup_uniform_vec4(grp, "aoParameters[0]", &effects->ao_dist, 2);
- if (effects->use_ao) {
+ if ((effects->enabled_effects & EFFECT_GTAO) != 0) {
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &vedata->txl->gtao_horizons);
}
- else {
- /* Use ssr_specrough_input as fallback to avoid sampling problem on certain platform, see: T52593 */
- DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &txl->ssr_specrough_input);
- }
DRW_shgroup_call_add(grp, quad, NULL);
}
diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c
index 4efdfb0fb84..17da4a18b78 100644
--- a/source/blender/draw/engines/eevee/eevee_subsurface.c
+++ b/source/blender/draw/engines/eevee/eevee_subsurface.c
@@ -27,7 +27,7 @@
#include "DRW_render.h"
-#include "BLI_dynstr.h"
+#include "BLI_string_utils.h"
#include "eevee_private.h"
#include "GPU_texture.h"
@@ -36,18 +36,26 @@ static struct {
struct GPUShader *sss_sh[3];
} e_data = {NULL}; /* Engine data */
+extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_effect_subsurface_frag_glsl[];
static void eevee_create_shader_subsurface(void)
{
- e_data.sss_sh[0] = DRW_shader_create_fullscreen(datatoc_effect_subsurface_frag_glsl, "#define FIRST_PASS\n");
- e_data.sss_sh[1] = DRW_shader_create_fullscreen(datatoc_effect_subsurface_frag_glsl, "#define SECOND_PASS\n");
- e_data.sss_sh[2] = DRW_shader_create_fullscreen(datatoc_effect_subsurface_frag_glsl, "#define SECOND_PASS\n"
- "#define USE_SEP_ALBEDO\n");
+ char *frag_str = BLI_string_joinN(
+ datatoc_common_uniforms_lib_glsl,
+ datatoc_effect_subsurface_frag_glsl);
+
+ e_data.sss_sh[0] = DRW_shader_create_fullscreen(frag_str, "#define FIRST_PASS\n");
+ e_data.sss_sh[1] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n");
+ e_data.sss_sh[2] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n"
+ "#define USE_SEP_ALBEDO\n");
+
+ MEM_freeN(frag_str);
}
-int EEVEE_subsurface_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
EEVEE_FramebufferList *fbl = vedata->fbl;
@@ -60,8 +68,8 @@ int EEVEE_subsurface_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedat
if (BKE_collection_engine_property_value_get_bool(props, "sss_enable")) {
effects->sss_sample_count = 1 + BKE_collection_engine_property_value_get_int(props, "sss_samples") * 2;
- effects->sss_jitter_threshold = BKE_collection_engine_property_value_get_float(props, "sss_jitter_threshold");
effects->sss_separate_albedo = BKE_collection_engine_property_value_get_bool(props, "sss_separate_albedo");
+ common_data->sss_jitter_threshold = BKE_collection_engine_property_value_get_float(props, "sss_jitter_threshold");
/* Shaders */
if (!e_data.sss_sh[0]) {
@@ -117,7 +125,8 @@ void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
}
}
-void EEVEE_subsurface_add_pass(EEVEE_Data *vedata, unsigned int sss_id, struct GPUUniformBuffer *sss_profile)
+void EEVEE_subsurface_add_pass(
+ EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, unsigned int sss_id, struct GPUUniformBuffer *sss_profile)
{
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
EEVEE_TextureList *txl = vedata->txl;
@@ -127,23 +136,21 @@ void EEVEE_subsurface_add_pass(EEVEE_Data *vedata, unsigned int sss_id, struct G
struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)vedata->stl->g_data->viewvecs, 2);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_buffer(grp, "sssData", &txl->sss_data);
DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
- DRW_shgroup_uniform_float(grp, "jitterThreshold", &effects->sss_jitter_threshold, 1);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_stencil_mask(grp, sss_id);
DRW_shgroup_call_add(grp, quad, NULL);
struct GPUShader *sh = (effects->sss_separate_albedo) ? e_data.sss_sh[2] : e_data.sss_sh[1];
grp = DRW_shgroup_create(sh, psl->sss_resolve_ps);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)vedata->stl->g_data->viewvecs, 2);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_buffer(grp, "sssData", &txl->sss_blur);
DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
- DRW_shgroup_uniform_float(grp, "jitterThreshold", &effects->sss_jitter_threshold, 1);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_stencil_mask(grp, sss_id);
DRW_shgroup_call_add(grp, quad, NULL);
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index d1a45657a29..a960682e8c9 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -51,6 +51,7 @@ static struct {
struct GPUShader *volumetric_clear_sh;
struct GPUShader *volumetric_scatter_sh;
+ struct GPUShader *volumetric_scatter_with_lamps_sh;
struct GPUShader *volumetric_integration_sh;
struct GPUShader *volumetric_resolve_sh;
@@ -63,6 +64,7 @@ static struct {
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_bsdf_direct_lib_glsl[];
+extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_octahedron_lib_glsl[];
extern char datatoc_irradiance_lib_glsl[];
extern char datatoc_lamps_lib_glsl[];
@@ -78,10 +80,12 @@ extern char datatoc_gpu_shader_fullscreen_vert_glsl[];
static void eevee_create_shader_volumes(void)
{
e_data.volumetric_common_lib = BLI_string_joinN(
+ datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_volumetric_lib_glsl);
e_data.volumetric_common_lamps_lib = BLI_string_joinN(
+ datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_bsdf_direct_lib_glsl,
datatoc_octahedron_lib_glsl,
@@ -104,6 +108,15 @@ static void eevee_create_shader_volumes(void)
SHADER_DEFINES
"#define VOLUMETRICS\n"
"#define VOLUME_SHADOW\n");
+ e_data.volumetric_scatter_with_lamps_sh = DRW_shader_create_with_lib(
+ datatoc_volumetric_vert_glsl,
+ datatoc_volumetric_geom_glsl,
+ datatoc_volumetric_scatter_frag_glsl,
+ e_data.volumetric_common_lamps_lib,
+ SHADER_DEFINES
+ "#define VOLUMETRICS\n"
+ "#define VOLUME_LIGHTING\n"
+ "#define VOLUME_SHADOW\n");
e_data.volumetric_integration_sh = DRW_shader_create_with_lib(
datatoc_volumetric_vert_glsl,
datatoc_volumetric_geom_glsl,
@@ -121,6 +134,7 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects = stl->effects;
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
const DRWContextState *draw_ctx = DRW_context_state_get();
ViewLayer *view_layer = draw_ctx->view_layer;
@@ -137,29 +151,23 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
eevee_create_shader_volumes();
}
- if (sldata->volumetrics == NULL) {
- sldata->volumetrics = MEM_callocN(sizeof(EEVEE_VolumetricsInfo), "EEVEE_VolumetricsInfo");
- }
-
- EEVEE_VolumetricsInfo *volumetrics = sldata->volumetrics;
-
int tile_size = BKE_collection_engine_property_value_get_int(props, "volumetric_tile_size");
/* Find Froxel Texture resolution. */
- int froxel_tex_size[3];
+ int tex_size[3];
- froxel_tex_size[0] = (int)ceilf(fmaxf(1.0f, viewport_size[0] / (float)tile_size));
- froxel_tex_size[1] = (int)ceilf(fmaxf(1.0f, viewport_size[1] / (float)tile_size));
- froxel_tex_size[2] = max_ii(BKE_collection_engine_property_value_get_int(props, "volumetric_samples"), 1);
+ tex_size[0] = (int)ceilf(fmaxf(1.0f, viewport_size[0] / (float)tile_size));
+ tex_size[1] = (int)ceilf(fmaxf(1.0f, viewport_size[1] / (float)tile_size));
+ tex_size[2] = max_ii(BKE_collection_engine_property_value_get_int(props, "volumetric_samples"), 1);
- volumetrics->volume_coord_scale[0] = viewport_size[0] / (float)(tile_size * froxel_tex_size[0]);
- volumetrics->volume_coord_scale[1] = viewport_size[1] / (float)(tile_size * froxel_tex_size[1]);
+ common_data->vol_coord_scale[0] = viewport_size[0] / (float)(tile_size * tex_size[0]);
+ common_data->vol_coord_scale[1] = viewport_size[1] / (float)(tile_size * tex_size[1]);
/* TODO compute snap to maxZBuffer for clustered rendering */
- if ((volumetrics->froxel_tex_size[0] != froxel_tex_size[0]) ||
- (volumetrics->froxel_tex_size[1] != froxel_tex_size[1]) ||
- (volumetrics->froxel_tex_size[2] != froxel_tex_size[2]))
+ if ((common_data->vol_tex_size[0] != tex_size[0]) ||
+ (common_data->vol_tex_size[1] != tex_size[1]) ||
+ (common_data->vol_tex_size[2] != tex_size[2]))
{
DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering);
DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction);
@@ -172,38 +180,46 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
- volumetrics->froxel_tex_size[0] = froxel_tex_size[0];
- volumetrics->froxel_tex_size[1] = froxel_tex_size[1];
- volumetrics->froxel_tex_size[2] = froxel_tex_size[2];
+ common_data->vol_tex_size[0] = tex_size[0];
+ common_data->vol_tex_size[1] = tex_size[1];
+ common_data->vol_tex_size[2] = tex_size[2];
- volumetrics->inv_tex_size[0] = 1.0f / (float)(volumetrics->froxel_tex_size[0]);
- volumetrics->inv_tex_size[1] = 1.0f / (float)(volumetrics->froxel_tex_size[1]);
- volumetrics->inv_tex_size[2] = 1.0f / (float)(volumetrics->froxel_tex_size[2]);
+ common_data->vol_inv_tex_size[0] = 1.0f / (float)(tex_size[0]);
+ common_data->vol_inv_tex_size[1] = 1.0f / (float)(tex_size[1]);
+ common_data->vol_inv_tex_size[2] = 1.0f / (float)(tex_size[2]);
}
/* Like frostbite's paper, 5% blend of the new frame. */
- volumetrics->history_alpha = (txl->volume_prop_scattering == NULL) ? 0.0f : 0.95f;
+ common_data->vol_history_alpha = (txl->volume_prop_scattering == NULL) ? 0.0f : 0.95f;
if (txl->volume_prop_scattering == NULL) {
/* Volume properties: We evaluate all volumetric objects
* and store their final properties into each froxel */
- txl->volume_prop_scattering = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
- txl->volume_prop_extinction = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
- txl->volume_prop_emission = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
- txl->volume_prop_phase = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RG_16, DRW_TEX_FILTER, NULL);
+ txl->volume_prop_scattering = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
+ DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+ txl->volume_prop_extinction = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
+ DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+ txl->volume_prop_emission = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
+ DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+ txl->volume_prop_phase = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
+ DRW_TEX_RG_16, DRW_TEX_FILTER, NULL);
/* Volume scattering: We compute for each froxel the
* Scattered light towards the view. We also resolve temporal
* super sampling during this stage. */
- txl->volume_scatter = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
- txl->volume_transmittance = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+ txl->volume_scatter = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
+ DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+ txl->volume_transmittance = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
+ DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
/* Final integration: We compute for each froxel the
* amount of scattered light and extinction coef at this
* given depth. We use theses textures as double buffer
* for the volumetric history. */
- txl->volume_scatter_history = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
- txl->volume_transmittance_history = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+ txl->volume_scatter_history = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
+ DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+ txl->volume_transmittance_history = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
+ DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
}
/* Temporal Super sampling jitter */
@@ -221,7 +237,7 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
if (do_taa) {
- volumetrics->history_alpha = 0.0f;
+ common_data->vol_history_alpha = 0.0f;
current_sample = effects->taa_current_sample - 1;
effects->volume_current_sample = -1;
}
@@ -234,9 +250,9 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
BLI_halton_3D(ht_primes, ht_offset, current_sample, ht_point);
- volumetrics->jitter[0] = (float)ht_point[0];
- volumetrics->jitter[1] = (float)ht_point[1];
- volumetrics->jitter[2] = (float)ht_point[2];
+ common_data->vol_jitter[0] = (float)ht_point[0];
+ common_data->vol_jitter[1] = (float)ht_point[1];
+ common_data->vol_jitter[2] = (float)ht_point[2];
/* Framebuffer setup */
DRWFboTexture tex_vol[4] = {{&txl->volume_prop_scattering, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
@@ -245,63 +261,64 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{&txl->volume_prop_phase, DRW_TEX_RG_16, DRW_TEX_FILTER}};
DRW_framebuffer_init(&fbl->volumetric_fb, &draw_engine_eevee_type,
- (int)froxel_tex_size[0], (int)froxel_tex_size[1],
+ (int)tex_size[0], (int)tex_size[1],
tex_vol, 4);
DRWFboTexture tex_vol_scat[2] = {{&txl->volume_scatter, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
{&txl->volume_transmittance, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER}};
DRW_framebuffer_init(&fbl->volumetric_scat_fb, &draw_engine_eevee_type,
- (int)froxel_tex_size[0], (int)froxel_tex_size[1],
+ (int)tex_size[0], (int)tex_size[1],
tex_vol_scat, 2);
DRWFboTexture tex_vol_integ[2] = {{&txl->volume_scatter_history, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
{&txl->volume_transmittance_history, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER}};
DRW_framebuffer_init(&fbl->volumetric_integ_fb, &draw_engine_eevee_type,
- (int)froxel_tex_size[0], (int)froxel_tex_size[1],
+ (int)tex_size[0], (int)tex_size[1],
tex_vol_integ, 2);
- volumetrics->integration_start = BKE_collection_engine_property_value_get_float(props, "volumetric_start");
- volumetrics->integration_end = BKE_collection_engine_property_value_get_float(props, "volumetric_end");
- volumetrics->sample_distribution = 4.0f * (1.00001f - BKE_collection_engine_property_value_get_float(props, "volumetric_sample_distribution"));
- volumetrics->use_volume_shadows = BKE_collection_engine_property_value_get_bool(props, "volumetric_shadows");
- volumetrics->light_clamp = BKE_collection_engine_property_value_get_float(props, "volumetric_light_clamp");
+ float integration_start = BKE_collection_engine_property_value_get_float(props, "volumetric_start");
+ float integration_end = BKE_collection_engine_property_value_get_float(props, "volumetric_end");
+ common_data->vol_light_clamp = BKE_collection_engine_property_value_get_float(props, "volumetric_light_clamp");
- if (volumetrics->use_volume_shadows) {
- volumetrics->shadow_step_count = (float)BKE_collection_engine_property_value_get_int(props, "volumetric_shadow_samples");
+ common_data->vol_shadow_steps = (float)BKE_collection_engine_property_value_get_int(props, "volumetric_shadow_samples");
+ if (BKE_collection_engine_property_value_get_bool(props, "volumetric_shadows")) {
}
else {
- volumetrics->shadow_step_count = 0;
+ common_data->vol_shadow_steps = 0;
}
if (DRW_viewport_is_persp_get()) {
- const float clip_start = stl->g_data->viewvecs[0][2];
+ float sample_distribution = BKE_collection_engine_property_value_get_float(props, "volumetric_sample_distribution");
+ sample_distribution = 4.0f * (1.00001f - sample_distribution);
+
+ const float clip_start = common_data->view_vecs[0][2];
/* Negate */
- float near = volumetrics->integration_start = min_ff(-volumetrics->integration_start, clip_start - 1e-4f);
- float far = volumetrics->integration_end = min_ff(-volumetrics->integration_end, near - 1e-4f);
+ float near = integration_start = min_ff(-integration_start, clip_start - 1e-4f);
+ float far = integration_end = min_ff(-integration_end, near - 1e-4f);
- volumetrics->depth_param[0] = (far - near * exp2(1.0f / volumetrics->sample_distribution)) / (far - near);
- volumetrics->depth_param[1] = (1.0f - volumetrics->depth_param[0]) / near;
- volumetrics->depth_param[2] = volumetrics->sample_distribution;
+ common_data->vol_depth_param[0] = (far - near * exp2(1.0f / sample_distribution)) / (far - near);
+ common_data->vol_depth_param[1] = (1.0f - common_data->vol_depth_param[0]) / near;
+ common_data->vol_depth_param[2] = sample_distribution;
}
else {
- const float clip_start = stl->g_data->viewvecs[0][2];
- const float clip_end = stl->g_data->viewvecs[1][2];
- volumetrics->integration_start = min_ff(volumetrics->integration_end, clip_start);
- volumetrics->integration_end = max_ff(-volumetrics->integration_end, clip_end);
-
- volumetrics->depth_param[0] = volumetrics->integration_start;
- volumetrics->depth_param[1] = volumetrics->integration_end;
- volumetrics->depth_param[2] = 1.0f / (volumetrics->integration_end - volumetrics->integration_start);
+ const float clip_start = common_data->view_vecs[0][2];
+ const float clip_end = common_data->view_vecs[1][2];
+ integration_start = min_ff(integration_end, clip_start);
+ integration_end = max_ff(-integration_end, clip_end);
+
+ common_data->vol_depth_param[0] = integration_start;
+ common_data->vol_depth_param[1] = integration_end;
+ common_data->vol_depth_param[2] = 1.0f / (integration_end - integration_start);
}
/* Disable clamp if equal to 0. */
- if (volumetrics->light_clamp == 0.0) {
- volumetrics->light_clamp = FLT_MAX;
+ if (common_data->vol_light_clamp == 0.0) {
+ common_data->vol_light_clamp = FLT_MAX;
}
- volumetrics->use_lights = BKE_collection_engine_property_value_get_bool(props, "volumetric_lights");
+ common_data->vol_use_lights = BKE_collection_engine_property_value_get_bool(props, "volumetric_lights");
return EFFECT_VOLUMETRIC | EFFECT_POST_BUFFER;
}
@@ -328,12 +345,11 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
EEVEE_StorageList *stl = vedata->stl;
EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects = stl->effects;
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- EEVEE_VolumetricsInfo *volumetrics = sldata->volumetrics;
- static int zero = 0;
DRWShadingGroup *grp;
/* Quick breakdown of the Volumetric rendering:
@@ -370,65 +386,59 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
if (wo != NULL && wo->use_nodes && wo->nodetree) {
struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo);
- grp = DRW_shgroup_material_empty_tri_batch_create(mat, psl->volumetric_world_ps, volumetrics->froxel_tex_size[2]);
+ grp = DRW_shgroup_material_empty_tri_batch_create(mat,
+ psl->volumetric_world_ps,
+ common_data->vol_tex_size[2]);
if (grp) {
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_ivec3(grp, "volumeTextureSize", (int *)volumetrics->froxel_tex_size, 1);
- DRW_shgroup_uniform_vec2(grp, "volume_uv_ratio", (float *)volumetrics->volume_coord_scale, 1);
- DRW_shgroup_uniform_vec3(grp, "volume_param", (float *)volumetrics->depth_param, 1);
- DRW_shgroup_uniform_vec3(grp, "volume_jitter", (float *)volumetrics->jitter, 1);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
}
}
else {
/* If no world or volume material is present just clear the buffer with this drawcall */
- grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_clear_sh, psl->volumetric_world_ps, volumetrics->froxel_tex_size[2]);
+ grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_clear_sh,
+ psl->volumetric_world_ps,
+ common_data->vol_tex_size[2]);
- DRW_shgroup_uniform_ivec3(grp, "volumeTextureSize", (int *)volumetrics->froxel_tex_size, 1);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
}
/* Volumetric Objects */
- psl->volumetric_objects_ps = DRW_pass_create("Volumetric Properties", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
+ psl->volumetric_objects_ps = DRW_pass_create("Volumetric Properties", DRW_STATE_WRITE_COLOR |
+ DRW_STATE_ADDITIVE);
+ struct GPUShader *scatter_sh = (common_data->vol_use_lights) ? e_data.volumetric_scatter_with_lamps_sh
+ : e_data.volumetric_scatter_sh;
psl->volumetric_scatter_ps = DRW_pass_create("Volumetric Scattering", DRW_STATE_WRITE_COLOR);
- grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_scatter_sh, psl->volumetric_scatter_ps, volumetrics->froxel_tex_size[2]);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_vec2(grp, "volume_uv_ratio", (float *)volumetrics->volume_coord_scale, 1);
- DRW_shgroup_uniform_vec3(grp, "volume_param", (float *)volumetrics->depth_param, 1);
- DRW_shgroup_uniform_vec3(grp, "volume_jitter", (float *)volumetrics->jitter, 1);
- DRW_shgroup_uniform_mat4(grp, "PastViewProjectionMatrix", (float *)stl->g_data->prev_persmat);
- DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_int(grp, "light_count", (volumetrics->use_lights) ? &sldata->lamps->num_light : &zero, 1);
+ grp = DRW_shgroup_empty_tri_batch_create(scatter_sh, psl->volumetric_scatter_ps,
+ common_data->vol_tex_size[2]);
DRW_shgroup_uniform_buffer(grp, "irradianceGrid", &sldata->irradiance_pool);
DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_pool);
- DRW_shgroup_uniform_float(grp, "volume_light_clamp", &volumetrics->light_clamp, 1);
- DRW_shgroup_uniform_float(grp, "volume_shadows_steps", &volumetrics->shadow_step_count, 1);
- DRW_shgroup_uniform_float(grp, "volume_history_alpha", &volumetrics->history_alpha, 1);
DRW_shgroup_uniform_buffer(grp, "volumeScattering", &txl->volume_prop_scattering);
DRW_shgroup_uniform_buffer(grp, "volumeExtinction", &txl->volume_prop_extinction);
DRW_shgroup_uniform_buffer(grp, "volumeEmission", &txl->volume_prop_emission);
DRW_shgroup_uniform_buffer(grp, "volumePhase", &txl->volume_prop_phase);
DRW_shgroup_uniform_buffer(grp, "historyScattering", &txl->volume_scatter_history);
DRW_shgroup_uniform_buffer(grp, "historyTransmittance", &txl->volume_transmittance_history);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
psl->volumetric_integration_ps = DRW_pass_create("Volumetric Integration", DRW_STATE_WRITE_COLOR);
- grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_integration_sh, psl->volumetric_integration_ps, volumetrics->froxel_tex_size[2]);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_vec2(grp, "volume_uv_ratio", (float *)volumetrics->volume_coord_scale, 1);
- DRW_shgroup_uniform_vec3(grp, "volume_param", (float *)volumetrics->depth_param, 1);
+ grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_integration_sh,
+ psl->volumetric_integration_ps,
+ common_data->vol_tex_size[2]);
DRW_shgroup_uniform_buffer(grp, "volumeScattering", &txl->volume_scatter);
DRW_shgroup_uniform_buffer(grp, "volumeExtinction", &txl->volume_transmittance);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
psl->volumetric_resolve_ps = DRW_pass_create("Volumetric Resolve", DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_create(e_data.volumetric_resolve_sh, psl->volumetric_resolve_ps);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_vec2(grp, "volume_uv_ratio", (float *)volumetrics->volume_coord_scale, 1);
- DRW_shgroup_uniform_vec3(grp, "volume_param", (float *)volumetrics->depth_param, 1);
DRW_shgroup_uniform_buffer(grp, "inScattering", &txl->volume_scatter);
DRW_shgroup_uniform_buffer(grp, "inTransmittance", &txl->volume_transmittance);
DRW_shgroup_uniform_buffer(grp, "inSceneColor", &e_data.color_src);
DRW_shgroup_uniform_buffer(grp, "inSceneDepth", &e_data.depth_src);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
}
@@ -438,7 +448,6 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
float *texcoloc = NULL;
float *texcosize = NULL;
struct ModifierData *md = NULL;
- EEVEE_VolumetricsInfo *volumetrics = sldata->volumetrics;
Material *ma = give_current_material(ob, 1);
if (ma == NULL) {
@@ -447,7 +456,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
struct GPUMaterial *mat = EEVEE_material_mesh_volume_get(scene, ma);
- DRWShadingGroup *grp = DRW_shgroup_material_empty_tri_batch_create(mat, vedata->psl->volumetric_objects_ps, volumetrics->froxel_tex_size[2]);
+ DRWShadingGroup *grp = DRW_shgroup_material_empty_tri_batch_create(mat, vedata->psl->volumetric_objects_ps, sldata->common_data.vol_tex_size[2]);
/* Making sure it's updated. */
invert_m4_m4(ob->imat, ob->obmat);
@@ -455,14 +464,10 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
BKE_mesh_texspace_get_reference((struct Mesh *)ob->data, NULL, &texcoloc, NULL, &texcosize);
if (grp) {
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_uniform_mat4(grp, "volumeObjectMatrix", (float *)ob->imat);
DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texcoloc, 1);
DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texcosize, 1);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)vedata->stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_ivec3(grp, "volumeTextureSize", (int *)volumetrics->froxel_tex_size, 1);
- DRW_shgroup_uniform_vec2(grp, "volume_uv_ratio", (float *)volumetrics->volume_coord_scale, 1);
- DRW_shgroup_uniform_vec3(grp, "volume_param", (float *)volumetrics->depth_param, 1);
- DRW_shgroup_uniform_vec3(grp, "volume_jitter", (float *)volumetrics->jitter, 1);
}
/* Smoke Simulation */
@@ -572,6 +577,7 @@ void EEVEE_volumes_free(void)
DRW_SHADER_FREE_SAFE(e_data.volumetric_clear_sh);
DRW_SHADER_FREE_SAFE(e_data.volumetric_scatter_sh);
+ DRW_SHADER_FREE_SAFE(e_data.volumetric_scatter_with_lamps_sh);
DRW_SHADER_FREE_SAFE(e_data.volumetric_integration_sh);
DRW_SHADER_FREE_SAFE(e_data.volumetric_resolve_sh);
}
diff --git a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
index 302b7596cc3..55f66f5500a 100644
--- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
@@ -33,19 +33,8 @@ uniform sampler2DArray utilTex;
#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
#endif /* UTIL_TEX */
-uniform vec4 aoParameters[2];
uniform sampler2D horizonBuffer;
-#define aoDistance aoParameters[0].x
-#define aoSamples aoParameters[0].y /* UNUSED */
-#define aoFactor aoParameters[0].z
-#define aoInvSamples aoParameters[0].w /* UNUSED */
-
-#define aoOffset aoParameters[1].x /* UNUSED */
-#define aoBounceFac aoParameters[1].y
-#define aoQuality aoParameters[1].z
-#define aoSettings aoParameters[1].w
-
/* aoSettings flags */
#define USE_AO 1
#define USE_BENT_NORMAL 2
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
index bdc59ec345a..68299fe7546 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -11,7 +11,6 @@
uniform mat4 ProjectionMatrix;
uniform mat4 ViewProjectionMatrix;
uniform mat4 ViewMatrixInverse;
-uniform vec4 viewvecs[2];
#ifndef SHADOW_SHADER
uniform mat4 ViewMatrix;
#else
@@ -31,8 +30,6 @@ flat in int shFace; /* Shadow layer we are rendering to. */
#define ViewMatrix FaceViewMatrix[shFace]
#endif
-uniform vec2 mipRatio[10];
-
/* Buffers */
uniform sampler2D colorBuffer;
uniform sampler2D depthBuffer;
@@ -304,7 +301,7 @@ float get_view_z_from_depth(float depth)
return -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]);
}
else {
- return viewvecs[0].z + depth * viewvecs[1].z;
+ return viewVecs[0].z + depth * viewVecs[1].z;
}
}
@@ -315,7 +312,7 @@ float get_depth_from_view_z(float z)
return d * 0.5 + 0.5;
}
else {
- return (z - viewvecs[0].z) / viewvecs[1].z;
+ return (z - viewVecs[0].z) / viewVecs[1].z;
}
}
@@ -328,10 +325,10 @@ vec2 get_uvs_from_view(vec3 view)
vec3 get_view_space_from_depth(vec2 uvcoords, float depth)
{
if (ProjectionMatrix[3][3] == 0.0) {
- return (viewvecs[0].xyz + vec3(uvcoords, 0.0) * viewvecs[1].xyz) * get_view_z_from_depth(depth);
+ return (viewVecs[0].xyz + vec3(uvcoords, 0.0) * viewVecs[1].xyz) * get_view_z_from_depth(depth);
}
else {
- return viewvecs[0].xyz + vec3(uvcoords, depth) * viewvecs[1].xyz;
+ return viewVecs[0].xyz + vec3(uvcoords, depth) * viewVecs[1].xyz;
}
}
@@ -746,8 +743,6 @@ Closure closure_add(Closure cl1, Closure cl2)
return cl;
}
-uniform bool sssToggle;
-
#if defined(MESH_SHADER) && !defined(USE_ALPHA_HASH) && !defined(USE_ALPHA_CLIP) && !defined(SHADOW_SHADER) && !defined(USE_MULTIPLY)
layout(location = 0) out vec4 fragColor;
#ifdef USE_SSS
diff --git a/source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl b/source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl
new file mode 100644
index 00000000000..37106fc32bd
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl
@@ -0,0 +1,55 @@
+
+layout(std140) uniform common_block {
+ mat4 pastViewProjectionMatrix;
+ vec4 viewVecs[2];
+ vec2 mipRatio[10]; /* To correct mip level texel mis-alignement */
+ /* Ambient Occlusion */
+ vec4 aoParameters[2];
+ /* Volumetric */
+ ivec4 volTexSize;
+ vec4 volDepthParameters; /* Parameters to the volume Z equation */
+ vec4 volInvTexSize;
+ vec4 volJitter;
+ vec4 volCoordScale; /* To convert volume uvs to screen uvs */
+ float volHistoryAlpha;
+ float volLightClamp;
+ float volShadowSteps;
+ bool volUseLights;
+ /* Screen Space Reflections */
+ vec4 ssrParameters;
+ float ssrBorderFac;
+ float ssrMaxRoughness;
+ float ssrFireflyFac;
+ float ssrBrdfBias;
+ bool ssrToggle;
+ /* SubSurface Scattering */
+ float sssJitterThreshold;
+ bool sssToggle;
+ /* Specular */
+ bool specToggle;
+ /* Lamps */
+ int laNumLight;
+ /* Probes */
+ int prbNumPlanar;
+ int prbNumRenderCube;
+ int prbNumRenderGrid;
+ int prbIrradianceVisSize;
+ float prbLodCubeMax;
+ float prbLodPlanarMax;
+};
+
+/* aoParameters */
+#define aoDistance aoParameters[0].x
+#define aoSamples aoParameters[0].y /* UNUSED */
+#define aoFactor aoParameters[0].z
+#define aoInvSamples aoParameters[0].w /* UNUSED */
+
+#define aoOffset aoParameters[1].x /* UNUSED */
+#define aoBounceFac aoParameters[1].y
+#define aoQuality aoParameters[1].z
+#define aoSettings aoParameters[1].w
+
+/* ssrParameters */
+#define ssrQuality ssrParameters.x
+#define ssrThickness ssrParameters.y
+#define ssrPixelSize ssrParameters.zw \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl
index 9043a4ca768..aa88e365d93 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl
@@ -10,9 +10,6 @@ uniform sampler2DArray utilTex;
#define MAX_MIP 9.0
-uniform float brdfBias;
-uniform float fireflyFactor;
-uniform float maxRoughness;
uniform ivec2 halfresOffset;
ivec2 encode_hit_data(vec2 hit_pos, bool has_hit, bool is_planar)
@@ -35,9 +32,6 @@ vec2 decode_hit_data(vec2 hit_data, out bool has_hit, out bool is_planar)
uniform sampler2D normalBuffer;
uniform sampler2D specroughBuffer;
-uniform int planar_count;
-uniform float noiseOffset;
-
layout(location = 0) out ivec2 hitData;
layout(location = 1) out float pdfData;
@@ -125,7 +119,7 @@ void main()
float a2 = roughnessSquared * roughnessSquared;
/* Early out */
- if (roughness > maxRoughness + 0.2)
+ if (roughness > ssrMaxRoughness + 0.2)
return;
vec4 rand = texelFetch(utilTex, ivec3(halfres_texel % LUT_SIZE, 2), 0);
@@ -135,7 +129,7 @@ void main()
rand.xzw *= 0.0;
}
/* Importance sampling bias */
- rand.x = mix(rand.x, 0.0, brdfBias);
+ rand.x = mix(rand.x, 0.0, ssrBrdfBias);
vec3 worldPosition = transform_point(ViewMatrixInverse, viewPosition);
vec3 wN = transform_direction(ViewMatrixInverse, N);
@@ -144,7 +138,7 @@ void main()
make_orthonormal_basis(N, T, B); /* Generate tangent space */
/* Planar Reflections */
- for (int i = 0; i < MAX_PLANAR && i < planar_count; ++i) {
+ for (int i = 0; i < MAX_PLANAR && i < prbNumPlanar; ++i) {
PlanarData pd = planars_data[i];
float fade = probe_attenuation_planar(pd, worldPosition, wN, 0.0);
@@ -173,9 +167,6 @@ uniform sampler2D specroughBuffer;
uniform isampler2D hitBuffer;
uniform sampler2D pdfBuffer;
-uniform int probe_count;
-uniform int planar_count;
-
uniform int neighborOffset;
const ivec2 neighbors[32] = ivec2[32](
@@ -190,8 +181,6 @@ const ivec2 neighbors[32] = ivec2[32](
ivec2( 0, 0), ivec2( 2, 2), ivec2( 2, -2), ivec2(-1, 0)
);
-uniform mat4 PastViewProjectionMatrix;
-
out vec4 fragColor;
void fallback_cubemap(
@@ -202,11 +191,15 @@ void fallback_cubemap(
vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy);
vec3 bent_normal;
+#ifdef SSR_AO
float final_ao = occlusion_compute(N, viewPosition, 1.0, rand, bent_normal);
final_ao = specular_occlusion(dot(N, V), final_ao, roughness);
+#else
+ const float final_ao = 1.0;
+#endif
/* Starts at 1 because 0 is world probe */
- for (int i = 1; i < MAX_PROBE && i < probe_count && spec_accum.a < 0.999; ++i) {
+ for (int i = 1; i < MAX_PROBE && i < prbNumRenderCube && spec_accum.a < 0.999; ++i) {
CubeData cd = probes_data[i];
float fade = probe_attenuation_cube(cd, W);
@@ -257,7 +250,7 @@ float brightness(vec3 c)
vec2 get_reprojected_reflection(vec3 hit, vec3 pos, vec3 N)
{
/* TODO real reprojection with motion vectors, etc... */
- return project_point(PastViewProjectionMatrix, hit).xy * 0.5 + 0.5;
+ return project_point(pastViewProjectionMatrix, hit).xy * 0.5 + 0.5;
}
float get_sample_depth(vec2 hit_co, bool is_planar, float planar_index)
@@ -296,7 +289,7 @@ vec3 get_hit_vector(
vec3 get_scene_color(vec2 ref_uvs, float mip, float planar_index, bool is_planar)
{
if (is_planar) {
- return textureLod(probePlanars, vec3(ref_uvs, planar_index), min(mip, lodPlanarMax)).rgb;
+ return textureLod(probePlanars, vec3(ref_uvs, planar_index), min(mip, prbLodPlanarMax)).rgb;
}
else {
return textureLod(prevColorBuffer, ref_uvs, mip).rgb;
@@ -361,7 +354,7 @@ vec4 get_ssr_samples(
/* Compute cone footprint in screen space. */
vec4 cone_footprint = hit_dist * cone_tan;
- cone_footprint = brdfBias * 0.5 * cone_footprint * max(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) / homcoord;
+ cone_footprint = ssrBrdfBias * 0.5 * cone_footprint * max(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) / homcoord;
/* Estimate a cone footprint to sample a corresponding mipmap level. */
vec4 mip = log2(cone_footprint * max_v2(vec2(textureSize(depthBuffer, 0))));
@@ -395,7 +388,7 @@ vec4 get_ssr_samples(
luma.z = brightness(sample[2]);
luma.w = brightness(sample[3]);
luma = max(vec4(1e-8), luma);
- luma = 1.0 - max(vec4(0.0), luma - fireflyFactor) / luma;
+ luma = 1.0 - max(vec4(0.0), luma - ssrFireflyFac) / luma;
sample[0] *= luma.x;
sample[1] *= luma.y;
@@ -474,7 +467,7 @@ void main()
/* Find Planar Reflections affecting this pixel */
PlanarData pd;
float planar_index;
- for (int i = 0; i < MAX_PLANAR && i < planar_count; ++i) {
+ for (int i = 0; i < MAX_PLANAR && i < prbNumPlanar; ++i) {
pd = planars_data[i];
float fade = probe_attenuation_planar(pd, worldPosition, N, 0.0);
@@ -495,12 +488,12 @@ void main()
float cone_tan = sqrt(1 - cone_cos * cone_cos) / cone_cos;
cone_tan *= mix(saturate(dot(N, -V) * 2.0), 1.0, roughness); /* Elongation fit */
- vec2 source_uvs = project_point(PastViewProjectionMatrix, worldPosition).xy * 0.5 + 0.5;
+ vec2 source_uvs = project_point(pastViewProjectionMatrix, worldPosition).xy * 0.5 + 0.5;
vec4 ssr_accum = vec4(0.0);
float weight_acc = 0.0;
- if (roughness < maxRoughness + 0.2) {
+ if (roughness < ssrMaxRoughness + 0.2) {
ssr_accum += get_ssr_samples(hit_pdf, hit_data, pd, planar_index, worldPosition, N, V,
roughnessSquared, cone_tan, source_uvs, weight_acc);
}
@@ -509,7 +502,7 @@ void main()
if (weight_acc > 0.0) {
ssr_accum /= weight_acc;
/* fade between 0.5 and 1.0 roughness */
- ssr_accum.a *= smoothstep(maxRoughness + 0.2, maxRoughness, roughness);
+ ssr_accum.a *= smoothstep(ssrMaxRoughness + 0.2, ssrMaxRoughness, roughness);
accumulate_light(ssr_accum.rgb, ssr_accum.a, spec_accum);
}
diff --git a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
index a0c39c79048..184eac54c26 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
@@ -8,7 +8,6 @@ layout(std140) uniform sssProfile {
int sss_samples;
};
-uniform float jitterThreshold;
uniform sampler2D depthBuffer;
uniform sampler2D sssData;
uniform sampler2D sssAlbedo;
@@ -22,7 +21,6 @@ uniform sampler2DArray utilTex;
out vec4 FragColor;
uniform mat4 ProjectionMatrix;
-uniform vec4 viewvecs[2];
float get_view_z_from_depth(float depth)
{
@@ -31,7 +29,7 @@ float get_view_z_from_depth(float depth)
return -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]);
}
else {
- return viewvecs[0].z + depth * viewvecs[1].z;
+ return viewVecs[0].z + depth * viewVecs[1].z;
}
}
@@ -66,7 +64,7 @@ void main(void)
vec3 accum = sss_data.rgb * kernel[0].rgb;
for (int i = 1; i < sss_samples && i < MAX_SSS_SAMPLES; i++) {
- vec2 sample_uv = uvs + kernel[i].a * finalStep * ((abs(kernel[i].a) > jitterThreshold) ? dir : dir_rand);
+ vec2 sample_uv = uvs + kernel[i].a * finalStep * ((abs(kernel[i].a) > sssJitterThreshold) ? dir : dir_rand);
vec3 color = texture(sssData, sample_uv).rgb;
float sample_depth = texture(depthBuffer, sample_uv).r;
sample_depth = get_view_z_from_depth(sample_depth);
diff --git a/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl b/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl
index 76d20486d3d..132cc16fcbd 100644
--- a/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl
@@ -1,6 +1,5 @@
uniform sampler2DArray irradianceGrid;
-uniform int irradianceVisibilitySize;
#define IRRADIANCE_LIB
@@ -81,8 +80,8 @@ IrradianceData load_irradiance_cell(int cell, vec3 N)
float load_visibility_cell(int cell, vec3 L, float dist, float bias, float bleed_bias, float range)
{
/* Keep in sync with diffuse_filter_probe() */
- ivec2 cell_co = ivec2(irradianceVisibilitySize);
- ivec2 cell_per_row_col = textureSize(irradianceGrid, 0).xy / irradianceVisibilitySize;
+ ivec2 cell_co = ivec2(prbIrradianceVisSize);
+ ivec2 cell_per_row_col = textureSize(irradianceGrid, 0).xy / prbIrradianceVisSize;
cell_co.x *= (cell % cell_per_row_col.x);
cell_co.y *= (cell / cell_per_row_col.x) % cell_per_row_col.y;
float layer = 1.0 + float((cell / cell_per_row_col.x) / cell_per_row_col.y);
@@ -90,8 +89,8 @@ float load_visibility_cell(int cell, vec3 L, float dist, float bias, float bleed
vec2 texel_size = 1.0 / vec2(textureSize(irradianceGrid, 0).xy);
vec2 co = vec2(cell_co) * texel_size;
- vec2 uv = mapping_octahedron(-L, vec2(1.0 / float(irradianceVisibilitySize)));
- uv *= vec2(irradianceVisibilitySize) * texel_size;
+ vec2 uv = mapping_octahedron(-L, vec2(1.0 / float(prbIrradianceVisSize)));
+ uv *= vec2(prbIrradianceVisSize) * texel_size;
vec4 data = texture(irradianceGrid, vec3(co + uv, layer));
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl
index fc0b5b9548b..d10f4bc0d42 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl
@@ -11,5 +11,5 @@ void main()
? normalize(cameraPos - worldPosition)
: cameraForward;
vec3 N = normalize(worldNormal);
- FragColor = vec4(textureLod_octahedron(probeCubes, vec4(reflect(-V, N), pid), 0.0, lodCubeMax).rgb, 1.0);
+ FragColor = vec4(textureLod_octahedron(probeCubes, vec4(reflect(-V, N), pid), 0.0, prbLodCubeMax).rgb, 1.0);
}
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl
index eb4315c93a3..b19ee7a9ea3 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl
@@ -3,6 +3,7 @@ uniform samplerCube probeHdr;
uniform int probeSize;
uniform float lodFactor;
uniform float lodMax;
+uniform float intensityFac;
in vec3 worldPosition;
@@ -192,6 +193,6 @@ void main()
}
}
- FragColor = irradiance_encode(out_radiance / weight);
+ FragColor = irradiance_encode(intensityFac * out_radiance / weight);
#endif
} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl
index 33714c5293c..3aec3ce4642 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl
@@ -5,6 +5,7 @@ uniform float texelSize;
uniform float lodFactor;
uniform float lodMax;
uniform float paddingSize;
+uniform float intensityFac;
in vec3 worldPosition;
@@ -82,5 +83,5 @@ void main() {
}
}
- FragColor = vec4(out_radiance / weight, 1.0);
+ FragColor = vec4(intensityFac * out_radiance / weight, 1.0);
} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl
index e914228aded..429f6ea92e4 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl
@@ -1,10 +1,7 @@
/* ----------- Uniforms --------- */
uniform sampler2DArray probePlanars;
-uniform float lodPlanarMax;
-
uniform sampler2DArray probeCubes;
-uniform float lodCubeMax;
/* ----------- Structures --------- */
@@ -162,12 +159,12 @@ vec3 probe_evaluate_cube(float id, CubeData cd, vec3 W, vec3 R, float roughness)
float fac = saturate(original_roughness * 2.0 - 1.0);
R = mix(intersection, R, fac * fac);
- return textureLod_octahedron(probeCubes, vec4(R, id), roughness * lodCubeMax, lodCubeMax).rgb;
+ return textureLod_octahedron(probeCubes, vec4(R, id), roughness * prbLodCubeMax, prbLodCubeMax).rgb;
}
vec3 probe_evaluate_world_spec(vec3 R, float roughness)
{
- return textureLod_octahedron(probeCubes, vec4(R, 0.0), roughness * lodCubeMax, lodCubeMax).rgb;
+ return textureLod_octahedron(probeCubes, vec4(R, 0.0), roughness * prbLodCubeMax, prbLodCubeMax).rgb;
}
vec3 probe_evaluate_planar(
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
index a2917842d43..cc66b477da0 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -2,14 +2,6 @@
#ifndef LIT_SURFACE_UNIFORM
#define LIT_SURFACE_UNIFORM
-uniform int light_count;
-uniform int probe_count;
-uniform int grid_count;
-uniform int planar_count;
-
-uniform bool specToggle;
-uniform bool ssrToggle;
-
uniform float refractionDepth;
#ifndef UTIL_TEX
@@ -29,8 +21,6 @@ in vec3 worldNormal;
in vec3 viewNormal;
#endif
-uniform float maxRoughness;
-
#endif /* LIT_SURFACE_UNIFORM */
/** AUTO CONFIG
@@ -187,7 +177,7 @@ void CLOSURE_NAME(
norm_view = normalize(cross(norm_view, N)); /* Normal facing view */
#endif
- for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
+ for (int i = 0; i < MAX_LIGHT && i < laNumLight; ++i) {
LightData ld = lights_data[i];
vec4 l_vector; /* Non-Normalized Light Vector with length in last component. */
@@ -266,7 +256,7 @@ void CLOSURE_NAME(
/* Planar Reflections */
/* ---------------------------- */
- for (int i = 0; i < MAX_PLANAR && i < planar_count && spec_accum.a < 0.999; ++i) {
+ for (int i = 0; i < MAX_PLANAR && i < prbNumPlanar && spec_accum.a < 0.999; ++i) {
PlanarData pd = planars_data[i];
/* Fade on geometric normal. */
@@ -312,11 +302,11 @@ void CLOSURE_NAME(
/* Screen Space Refraction */
/* ---------------------------- */
#ifdef USE_REFRACTION
- if (ssrToggle && roughness < maxRoughness + 0.2) {
+ if (ssrToggle && roughness < ssrMaxRoughness + 0.2) {
/* Find approximated position of the 2nd refraction event. */
vec3 refr_vpos = (refractionDepth > 0.0) ? transform_point(ViewMatrix, refr_pos) : viewPosition;
vec4 trans = screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand);
- trans.a *= smoothstep(maxRoughness + 0.2, maxRoughness, roughness);
+ trans.a *= smoothstep(ssrMaxRoughness + 0.2, ssrMaxRoughness, roughness);
accumulate_light(trans.rgb, trans.a, refr_accum);
}
#endif
@@ -336,7 +326,7 @@ void CLOSURE_NAME(
#endif
/* Starts at 1 because 0 is world probe */
- for (int i = 1; ACCUM.a < 0.999 && i < probe_count && i < MAX_PROBE; ++i) {
+ for (int i = 1; ACCUM.a < 0.999 && i < prbNumRenderCube && i < MAX_PROBE; ++i) {
CubeData cd = probes_data[i];
float fade = probe_attenuation_cube(cd, worldPosition);
@@ -448,7 +438,7 @@ void CLOSURE_NAME(
/* Irradiance Grids */
/* ---------------------------- */
/* Start at 1 because 0 is world irradiance */
- for (int i = 1; i < MAX_GRID && i < grid_count && diff_accum.a < 0.999; ++i) {
+ for (int i = 1; i < MAX_GRID && i < prbNumRenderGrid && diff_accum.a < 0.999; ++i) {
GridData gd = grids_data[i];
vec3 localpos;
@@ -463,7 +453,7 @@ void CLOSURE_NAME(
/* ---------------------------- */
/* World Diffuse */
/* ---------------------------- */
- if (diff_accum.a < 0.999 && grid_count > 0) {
+ if (diff_accum.a < 0.999 && prbNumRenderGrid > 0) {
vec3 diff = probe_evaluate_world_diff(bent_normal);
accumulate_light(diff, 1.0, diff_accum);
}
diff --git a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl
index c593081ce91..cb75731b7da 100644
--- a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl
@@ -1,13 +1,5 @@
#define MAX_STEP 256
-uniform vec4 ssrParameters;
-
-#define ssrQuality ssrParameters.x
-#define ssrThickness ssrParameters.y
-#define ssrPixelSize ssrParameters.zw
-
-uniform float borderFadeFactor;
-
float sample_depth(vec2 uv, int index, float lod)
{
#ifdef PLANAR_PROBE_RAYTRACE
@@ -233,7 +225,7 @@ vec3 raycast(
float screen_border_mask(vec2 hit_co)
{
const float margin = 0.003;
- float atten = borderFadeFactor + margin; /* Screen percentage */
+ float atten = ssrBorderFac + margin; /* Screen percentage */
hit_co = smoothstep(margin, atten, hit_co) * (1 - smoothstep(1.0 - atten, 1.0 - margin, hit_co));
float screenfade = hit_co.x * hit_co.y;
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
index 00e01e753f9..3a293647f84 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
@@ -4,9 +4,6 @@
#define NODETREE_EXEC
-uniform ivec3 volumeTextureSize;
-uniform vec3 volume_jitter;
-
#ifdef MESH_SHADER
uniform mat4 volumeObjectMatrix;
uniform vec3 volumeOrcoLoc;
@@ -33,7 +30,7 @@ layout(location = 3) out vec4 volumePhase;
void main()
{
ivec3 volume_cell = ivec3(gl_FragCoord.xy, slice);
- vec3 ndc_cell = volume_to_ndc((vec3(volume_cell) + volume_jitter) / volumeTextureSize);
+ vec3 ndc_cell = volume_to_ndc((vec3(volume_cell) + volJitter.xyz) * volInvTexSize.xyz);
viewPosition = get_view_space_from_depth(ndc_cell.xy, ndc_cell.z);
worldPosition = transform_point(ViewMatrixInverse, viewPosition);
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
index e12554bfabc..1a8167c2830 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
@@ -2,22 +2,16 @@
/* Based on Frosbite Unified Volumetric.
* https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */
-uniform float volume_light_clamp;
-
-uniform vec3 volume_param; /* Parameters to the volume Z equation */
-
-uniform vec2 volume_uv_ratio; /* To convert volume uvs to screen uvs */
-
/* Volume slice to view space depth. */
float volume_z_to_view_z(float z)
{
if (ProjectionMatrix[3][3] == 0.0) {
/* Exponential distribution */
- return (exp2(z / volume_param.z) - volume_param.x) / volume_param.y;
+ return (exp2(z / volDepthParameters.z) - volDepthParameters.x) / volDepthParameters.y;
}
else {
/* Linear distribution */
- return mix(volume_param.x, volume_param.y, z);
+ return mix(volDepthParameters.x, volDepthParameters.y, z);
}
}
@@ -25,11 +19,11 @@ float view_z_to_volume_z(float depth)
{
if (ProjectionMatrix[3][3] == 0.0) {
/* Exponential distribution */
- return volume_param.z * log2(depth * volume_param.y + volume_param.x);
+ return volDepthParameters.z * log2(depth * volDepthParameters.y + volDepthParameters.x);
}
else {
/* Linear distribution */
- return (depth - volume_param.x) * volume_param.z;
+ return (depth - volDepthParameters.x) * volDepthParameters.z;
}
}
@@ -38,7 +32,7 @@ vec3 volume_to_ndc(vec3 cos)
{
cos.z = volume_z_to_view_z(cos.z);
cos.z = get_depth_from_view_z(cos.z);
- cos.xy /= volume_uv_ratio;
+ cos.xy /= volCoordScale.xy;
return cos;
}
@@ -46,7 +40,7 @@ vec3 ndc_to_volume(vec3 cos)
{
cos.z = get_view_z_from_depth(cos.z);
cos.z = view_z_to_volume_z(cos.z);
- cos.xy *= volume_uv_ratio;
+ cos.xy *= volCoordScale.xy;
return cos;
}
@@ -90,15 +84,13 @@ vec3 light_volume(LightData ld, vec4 l_vector)
power /= (l_vector.w * l_vector.w);
- lum = min(lum * power, volume_light_clamp);
+ lum = min(lum * power, volLightClamp);
return tint * lum;
}
#define VOLUMETRIC_SHADOW_MAX_STEP 32.0
-uniform float volume_shadows_steps;
-
vec3 participating_media_extinction(vec3 wpos, sampler3D volume_extinction)
{
/* Waiting for proper volume shadowmaps and out of frustum shadow map. */
@@ -113,11 +105,11 @@ vec3 light_volume_shadow(LightData ld, vec3 ray_wpos, vec4 l_vector, sampler3D v
{
#if defined(VOLUME_SHADOW)
/* Heterogeneous volume shadows */
- float dd = l_vector.w / volume_shadows_steps;
+ float dd = l_vector.w / volShadowSteps;
vec3 L = l_vector.xyz * l_vector.w;
vec3 shadow = vec3(1.0);
- for (float s = 0.5; s < VOLUMETRIC_SHADOW_MAX_STEP && s < (volume_shadows_steps - 0.1); s += 1.0) {
- vec3 pos = ray_wpos + L * (s / volume_shadows_steps);
+ for (float s = 0.5; s < VOLUMETRIC_SHADOW_MAX_STEP && s < (volShadowSteps - 0.1); s += 1.0) {
+ vec3 pos = ray_wpos + L * (s / volShadowSteps);
vec3 s_extinction = participating_media_extinction(pos, volume_extinction);
shadow *= exp(-s_extinction * dd);
}
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl
index ea402ff3d99..fcbb6661b14 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl
@@ -13,28 +13,20 @@ uniform sampler3D volumePhase;
uniform sampler3D historyScattering;
uniform sampler3D historyTransmittance;
-uniform vec3 volume_jitter;
-uniform float volume_history_alpha;
-uniform int light_count;
-uniform mat4 PastViewProjectionMatrix;
-
flat in int slice;
layout(location = 0) out vec4 outScattering;
layout(location = 1) out vec4 outTransmittance;
-#define VOLUME_LIGHTING
-
void main()
{
- vec3 volume_tex_size = vec3(textureSize(volumeScattering, 0));
ivec3 volume_cell = ivec3(gl_FragCoord.xy, slice);
/* Emission */
outScattering = texelFetch(volumeEmission, volume_cell, 0);
outTransmittance = texelFetch(volumeExtinction, volume_cell, 0);
vec3 s_scattering = texelFetch(volumeScattering, volume_cell, 0).rgb;
- vec3 volume_ndc = volume_to_ndc((vec3(volume_cell) + volume_jitter) / volume_tex_size);
+ vec3 volume_ndc = volume_to_ndc((vec3(volume_cell) + volJitter.xyz) * volInvTexSize.xyz);
vec3 worldPosition = get_world_space_from_depth(volume_ndc.xy, volume_ndc.z);
vec3 wdir = cameraVec;
@@ -45,7 +37,7 @@ void main()
outScattering.rgb += irradiance_volumetric(worldPosition) * s_scattering * phase_function_isotropic();
#ifdef VOLUME_LIGHTING /* Lights */
- for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
+ for (int i = 0; i < MAX_LIGHT && i < laNumLight; ++i) {
LightData ld = lights_data[i];
@@ -63,16 +55,16 @@ void main()
/* Temporal supersampling */
/* Note : this uses the cell non-jittered position (texel center). */
- vec3 curr_ndc = volume_to_ndc(vec3(gl_FragCoord.xy, float(slice) + 0.5) / volume_tex_size);
+ vec3 curr_ndc = volume_to_ndc(vec3(gl_FragCoord.xy, float(slice) + 0.5) * volInvTexSize.xyz);
vec3 wpos = get_world_space_from_depth(curr_ndc.xy, curr_ndc.z);
- vec3 prev_ndc = project_point(PastViewProjectionMatrix, wpos);
+ vec3 prev_ndc = project_point(pastViewProjectionMatrix, wpos);
vec3 prev_volume = ndc_to_volume(prev_ndc * 0.5 + 0.5);
- if ((volume_history_alpha > 0.0) && all(greaterThan(prev_volume, vec3(0.0))) && all(lessThan(prev_volume, vec3(1.0)))) {
+ if ((volHistoryAlpha > 0.0) && all(greaterThan(prev_volume, vec3(0.0))) && all(lessThan(prev_volume, vec3(1.0)))) {
vec4 h_Scattering = texture(historyScattering, prev_volume);
vec4 h_Transmittance = texture(historyTransmittance, prev_volume);
- outScattering = mix(outScattering, h_Scattering, volume_history_alpha);
- outTransmittance = mix(outTransmittance, h_Transmittance, volume_history_alpha);
+ outScattering = mix(outScattering, h_Scattering, volHistoryAlpha);
+ outTransmittance = mix(outTransmittance, h_Transmittance, volHistoryAlpha);
}
/* Catch NaNs */
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 8b95661681d..1f16f63ba14 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -358,6 +358,7 @@ void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const
/* Passes */
DRWPass *DRW_pass_create(const char *name, DRWState state);
+void DRW_pass_state_set(DRWPass *pass, DRWState state);
void DRW_pass_foreach_shgroup(DRWPass *pass, void (*callback)(void *userData, DRWShadingGroup *shgrp), void *userData);
void DRW_pass_sort_shgroup_z(DRWPass *pass);
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 442f30bfcbb..5faf397cc37 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -65,6 +65,7 @@ static struct DRWShapeCache {
Gwn_Batch *drw_field_tube_limit;
Gwn_Batch *drw_field_cone_limit;
Gwn_Batch *drw_lamp;
+ Gwn_Batch *drw_lamp_shadows;
Gwn_Batch *drw_lamp_sunrays;
Gwn_Batch *drw_lamp_area;
Gwn_Batch *drw_lamp_hemi;
@@ -87,6 +88,7 @@ static struct DRWShapeCache {
Gwn_Batch *drw_bone_point_wire;
Gwn_Batch *drw_bone_arrows;
Gwn_Batch *drw_camera;
+ Gwn_Batch *drw_camera_frame;
Gwn_Batch *drw_camera_tria;
Gwn_Batch *drw_camera_focus;
Gwn_Batch *drw_particle_cross;
@@ -1013,14 +1015,14 @@ Gwn_Batch *DRW_cache_lamp_get(void)
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
GWN_vertbuf_data_alloc(vbo, NSEGMENTS * 2);
- for (int a = 0; a < NSEGMENTS; a++) {
- v[0] = sinf((2.0f * M_PI * a) / ((float)NSEGMENTS));
- v[1] = cosf((2.0f * M_PI * a) / ((float)NSEGMENTS));
- GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 2, v);
+ for (int a = 0; a < NSEGMENTS * 2; a += 2) {
+ v[0] = sinf((2.0f * M_PI * a) / ((float)NSEGMENTS * 2));
+ v[1] = cosf((2.0f * M_PI * a) / ((float)NSEGMENTS * 2));
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a, v);
- v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS));
- v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS));
- GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 2 + 1, v);
+ v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS * 2));
+ v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS * 2));
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a + 1, v);
}
SHC.drw_lamp = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
@@ -1029,6 +1031,38 @@ Gwn_Batch *DRW_cache_lamp_get(void)
#undef NSEGMENTS
}
+Gwn_Batch *DRW_cache_lamp_shadows_get(void)
+{
+#define NSEGMENTS 10
+ if (!SHC.drw_lamp_shadows) {
+ float v[2];
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, NSEGMENTS * 2);
+
+ for (int a = 0; a < NSEGMENTS * 2; a += 2) {
+ v[0] = sinf((2.0f * M_PI * a) / ((float)NSEGMENTS * 2));
+ v[1] = cosf((2.0f * M_PI * a) / ((float)NSEGMENTS * 2));
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a, v);
+
+ v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS * 2));
+ v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS * 2));
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a + 1, v);
+ }
+
+ SHC.drw_lamp_shadows = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_lamp_shadows;
+#undef NSEGMENTS
+}
+
Gwn_Batch *DRW_cache_lamp_sunrays_get(void)
{
if (!SHC.drw_lamp_sunrays) {
@@ -1852,7 +1886,7 @@ Gwn_Batch *DRW_cache_bone_envelope_distance_outline_get(void)
const float x = cosf(alpha);
const float y = -sinf(alpha);
- /* { X, Y, head/tail, inner/outer border } */
+ /* { X, Y, head/tail, inner/outer border } */
GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){x, y, head_tail, 0.0f});
GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){x, y, head_tail, 1.0f});
if (is_headtail_transition) {
@@ -1886,7 +1920,7 @@ Gwn_Batch *DRW_cache_bone_envelope_wire_outline_get(void)
/* Two lines between head and tail circles. */
/* Encoded lines, vertex shader gives them final correct value. */
- /* { X, Y, head/tail, inner/outer border } */
+ /* { X, Y, head/tail, inner/outer border } */
GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){ 1.0f, 0.0f, 0.0f, 0.0f});
GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){ 1.0f, 0.0f, 1.0f, 0.0f});
GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){-1.0f, 0.0f, 0.0f, 0.0f});
@@ -1922,7 +1956,7 @@ Gwn_Batch *DRW_cache_bone_envelope_head_wire_outline_get(void)
const float x = cosf(alpha);
const float y = -sinf(alpha);
- /* { X, Y, head/tail, inner/outer border } */
+ /* { X, Y, head/tail, inner/outer border } */
GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){ x, y, 0.0f, 0.0f});
}
@@ -2002,97 +2036,139 @@ Gwn_Batch *DRW_cache_bone_arrows_get(void)
/** \name Camera
* \{ */
+/**
+ * We could make these more generic functions.
+ * although filling 1d lines is not common.
+ *
+ * \note Use x coordinate to identify the vertex the vertex shader take care to place it appropriately.
+ */
+
+static const float camera_coords_frame_bounds[5] = {
+ 0.0f, /* center point */
+ 1.0f, /* + X + Y */
+ 2.0f, /* + X - Y */
+ 3.0f, /* - X - Y */
+ 4.0f, /* - X + Y */
+};
+
+static const float camera_coords_frame_tri[3] = {
+ 5.0f, /* tria + X */
+ 6.0f, /* tria - X */
+ 7.0f, /* tria + Y */
+};
+
+/** Draw a loop of lines. */
+static void camera_fill_lines_loop_fl_v1(
+ Gwn_VertBufRaw *pos_step,
+ const float *coords, const uint coords_len)
+{
+ for (uint i = 0, i_prev = coords_len - 1; i < coords_len; i_prev = i++) {
+ *((float *)GWN_vertbuf_raw_step(pos_step)) = coords[i_prev];
+ *((float *)GWN_vertbuf_raw_step(pos_step)) = coords[i];
+ }
+}
+
+/** Fan lines out from the first vertex. */
+static void camera_fill_lines_fan_fl_v1(
+ Gwn_VertBufRaw *pos_step,
+ const float *coords, const uint coords_len)
+{
+ for (uint i = 1; i < coords_len; i++) {
+ *((float *)GWN_vertbuf_raw_step(pos_step)) = coords[0];
+ *((float *)GWN_vertbuf_raw_step(pos_step)) = coords[i];
+ }
+}
+
+/** Simply fill the array. */
+static void camera_fill_array_fl_v1(
+ Gwn_VertBufRaw *pos_step,
+ const float *coords, const uint coords_len)
+{
+ for (uint i = 0; i < coords_len; i++) {
+ *((float *)GWN_vertbuf_raw_step(pos_step)) = coords[i];
+ }
+}
+
+
Gwn_Batch *DRW_cache_camera_get(void)
{
if (!SHC.drw_camera) {
- float v0 = 0.0f; /* Center point */
- float v1 = 1.0f; /* + X + Y */
- float v2 = 2.0f; /* + X - Y */
- float v3 = 3.0f; /* - X - Y */
- float v4 = 4.0f; /* - X + Y */
- float v5 = 5.0f; /* tria + X */
- float v6 = 6.0f; /* tria - X */
- float v7 = 7.0f; /* tria + Y */
- int v_idx = 0;
-
static Gwn_VertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attrib_ct == 0) {
- /* use x coordinate to identify the vertex
- * the vertex shader take care to place it
- * appropriatelly */
attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
}
/* Vertices */
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 22);
-
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v0);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v1);
+ const int vbo_len_capacity = 22;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ Gwn_VertBufRaw pos_step;
+ GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v0);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v2);
+ /* camera cone (from center to frame) */
+ camera_fill_lines_fan_fl_v1(&pos_step, camera_coords_frame_bounds, ARRAY_SIZE(camera_coords_frame_bounds));
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v0);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v3);
+ /* camera frame (skip center) */
+ camera_fill_lines_loop_fl_v1(&pos_step, &camera_coords_frame_bounds[1], ARRAY_SIZE(camera_coords_frame_bounds) - 1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v0);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v4);
+ /* camera triangle (above the frame) */
+ camera_fill_lines_loop_fl_v1(&pos_step, camera_coords_frame_tri, ARRAY_SIZE(camera_coords_frame_tri));
- /* camera frame */
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v2);
+ BLI_assert(vbo_len_capacity == GWN_vertbuf_raw_used(&pos_step));
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v2);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v3);
+ SHC.drw_camera = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_camera;
+}
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v3);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v4);
+Gwn_Batch *DRW_cache_camera_frame_get(void)
+{
+ if (!SHC.drw_camera_frame) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v4);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v1);
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+ }
- /* tria */
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v5);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v6);
+ /* Vertices */
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ const int vbo_len_capacity = 8;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ Gwn_VertBufRaw pos_step;
+ GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v6);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v7);
+ /* camera frame (skip center) */
+ camera_fill_lines_loop_fl_v1(&pos_step, &camera_coords_frame_bounds[1], ARRAY_SIZE(camera_coords_frame_bounds) - 1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v7);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v5);
+ BLI_assert(vbo_len_capacity == GWN_vertbuf_raw_used(&pos_step));
- SHC.drw_camera = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_camera_frame = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
}
- return SHC.drw_camera;
+ return SHC.drw_camera_frame;
}
Gwn_Batch *DRW_cache_camera_tria_get(void)
{
if (!SHC.drw_camera_tria) {
- float v5 = 5.0f; /* tria + X */
- float v6 = 6.0f; /* tria - X */
- float v7 = 7.0f; /* tria + Y */
- int v_idx = 0;
-
static Gwn_VertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attrib_ct == 0) {
- /* use x coordinate to identify the vertex
- * the vertex shader take care to place it
- * appropriatelly */
attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
}
/* Vertices */
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 6);
+ const int vbo_len_capacity = 3;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ Gwn_VertBufRaw pos_step;
+ GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
+
+ /* camera triangle (above the frame) */
+ camera_fill_array_fl_v1(&pos_step, camera_coords_frame_tri, ARRAY_SIZE(camera_coords_frame_tri));
- /* tria */
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v5);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v6);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v7);
+ BLI_assert(vbo_len_capacity == GWN_vertbuf_raw_used(&pos_step));
SHC.drw_camera_tria = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
}
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index 3bef2940175..10539af5a94 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -74,6 +74,7 @@ struct Gwn_Batch *DRW_cache_field_cone_limit_get(void);
/* Lamps */
struct Gwn_Batch *DRW_cache_lamp_get(void);
+struct Gwn_Batch *DRW_cache_lamp_shadows_get(void);
struct Gwn_Batch *DRW_cache_lamp_sunrays_get(void);
struct Gwn_Batch *DRW_cache_lamp_area_get(void);
struct Gwn_Batch *DRW_cache_lamp_hemi_get(void);
@@ -82,6 +83,7 @@ struct Gwn_Batch *DRW_cache_lamp_spot_square_get(void);
/* Camera */
struct Gwn_Batch *DRW_cache_camera_get(void);
+struct Gwn_Batch *DRW_cache_camera_frame_get(void);
struct Gwn_Batch *DRW_cache_camera_tria_get(void);
/* Speaker */
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 41fb5c1ab8b..e5b959cdd3b 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -817,16 +817,10 @@ DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPa
else {
switch (input->type) {
case GPU_FLOAT:
- DRW_shgroup_uniform_float(grp, input->shadername, (float *)input->dynamicvec, 1);
- break;
case GPU_VEC2:
- DRW_shgroup_uniform_vec2(grp, input->shadername, (float *)input->dynamicvec, 1);
- break;
case GPU_VEC3:
- DRW_shgroup_uniform_vec3(grp, input->shadername, (float *)input->dynamicvec, 1);
- break;
case GPU_VEC4:
- DRW_shgroup_uniform_vec4(grp, input->shadername, (float *)input->dynamicvec, 1);
+ /* Should already be in the material ubo. */
break;
case GPU_MAT3:
DRW_shgroup_uniform_mat3(grp, input->shadername, (float *)input->dynamicvec);
@@ -1296,6 +1290,11 @@ DRWPass *DRW_pass_create(const char *name, DRWState state)
return pass;
}
+void DRW_pass_state_set(DRWPass *pass, DRWState state)
+{
+ pass->state = state;
+}
+
void DRW_pass_free(DRWPass *pass)
{
for (DRWShadingGroup *shgroup = pass->shgroups; shgroup; shgroup = shgroup->next) {
@@ -2309,6 +2308,7 @@ void DRW_framebuffer_init(
DRWFboTexture textures[MAX_FBO_TEX], int textures_len)
{
BLI_assert(textures_len <= MAX_FBO_TEX);
+ BLI_assert(width > 0 && height > 0);
bool create_fb = false;
int color_attachment = -1;
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c
index 7f4d595fd43..091edf10435 100644
--- a/source/blender/draw/modes/object_mode.c
+++ b/source/blender/draw/modes/object_mode.c
@@ -191,6 +191,7 @@ typedef struct OBJECT_PrivateData {
/* Camera */
DRWShadingGroup *camera;
+ DRWShadingGroup *camera_frame;
DRWShadingGroup *camera_tria;
DRWShadingGroup *camera_focus;
DRWShadingGroup *camera_clip;
@@ -938,6 +939,9 @@ static void OBJECT_cache_init(void *vedata)
geom = DRW_cache_camera_get();
stl->g_data->camera = shgroup_camera_instance(psl->non_meshes, geom);
+ geom = DRW_cache_camera_frame_get();
+ stl->g_data->camera_frame = shgroup_camera_instance(psl->non_meshes, geom);
+
geom = DRW_cache_camera_tria_get();
stl->g_data->camera_tria = shgroup_camera_instance(psl->non_meshes, geom);
@@ -995,6 +999,7 @@ static void OBJECT_cache_init(void *vedata)
geom = DRW_cache_lamp_get();
stl->g_data->lamp_circle = shgroup_instance_screenspace(psl->non_meshes, geom, &ts.sizeLampCircle);
+ geom = DRW_cache_lamp_shadows_get();
stl->g_data->lamp_circle_shadow = shgroup_instance_screenspace(psl->non_meshes, geom, &ts.sizeLampCircleShadow);
geom = DRW_cache_lamp_sunrays_get();
@@ -1249,9 +1254,11 @@ static void DRW_shgroup_camera(OBJECT_StorageList *stl, Object *ob, ViewLayer *v
const DRWContextState *draw_ctx = DRW_context_state_get();
View3D *v3d = draw_ctx->v3d;
Scene *scene = draw_ctx->scene;
+ RegionView3D *rv3d = draw_ctx->rv3d;
Camera *cam = ob->data;
const bool is_active = (ob == v3d->camera);
+ const bool look_through = (is_active && (rv3d->persp == RV3D_CAMOB));
float *color;
DRW_object_wire_theme_get(ob, view_layer, &color);
@@ -1264,7 +1271,7 @@ static void DRW_shgroup_camera(OBJECT_StorageList *stl, Object *ob, ViewLayer *v
BKE_camera_view_frame_ex(scene, cam, cam->drawsize, false, scale,
asp, shift, &drawsize, vec);
- // /* Frame coords */
+ /* Frame coords */
copy_v2_v2(cam->drwcorners[0], vec[0]);
copy_v2_v2(cam->drwcorners[1], vec[1]);
copy_v2_v2(cam->drwcorners[2], vec[2]);
@@ -1279,13 +1286,23 @@ static void DRW_shgroup_camera(OBJECT_StorageList *stl, Object *ob, ViewLayer *v
cam->drwtria[1][0] = shift[0];
cam->drwtria[1][1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
- DRW_shgroup_call_dynamic_add(stl->g_data->camera, color, cam->drwcorners, &cam->drwdepth, cam->drwtria, ob->obmat);
-
- /* Active cam */
- if (is_active) {
+ if (look_through) {
+ /* Only draw the frame. */
+ DRW_shgroup_call_dynamic_add(
+ stl->g_data->camera_frame, color, cam->drwcorners,
+ &cam->drwdepth, cam->drwtria, ob->obmat);
+ }
+ else {
DRW_shgroup_call_dynamic_add(
- stl->g_data->camera_tria, color,
- cam->drwcorners, &cam->drwdepth, cam->drwtria, ob->obmat);
+ stl->g_data->camera, color, cam->drwcorners,
+ &cam->drwdepth, cam->drwtria, ob->obmat);
+
+ /* Active cam */
+ if (is_active) {
+ DRW_shgroup_call_dynamic_add(
+ stl->g_data->camera_tria, color,
+ cam->drwcorners, &cam->drwdepth, cam->drwtria, ob->obmat);
+ }
}
/* draw the rest in normalize object space */
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index 2a84ca7f297..65c55b6cd22 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -31,6 +31,500 @@ set(SRC
)
+# Order matches "UI_icons.h", final name will be formatted: "icons{size}_{name}.dat"
+set(ICON_NAMES
+ question
+ error
+ cancel
+ tria_right
+ tria_down
+ tria_left
+ tria_up
+ arrow_leftright
+ plus
+ disclosure_tri_down
+ disclosure_tri_right
+ radiobut_off
+ radiobut_on
+ menu_panel
+ blender
+ grip
+ dot
+ collapsemenu
+ x
+ go_left
+ plug
+ ui
+ node
+ node_sel
+ fullscreen
+ splitscreen
+ rightarrow_thin
+ bordermove
+ viewzoom
+ zoomin
+ zoomout
+ panel_close
+ copy_id
+ eyedropper
+ link_area
+ auto
+ checkbox_dehlt
+ checkbox_hlt
+ unlocked
+ locked
+ unpinned
+ pinned
+ screen_back
+ rightarrow
+ downarrow_hlt
+ dotsup
+ dotsdown
+ link
+ inlink
+ plugin
+ help
+ ghost_enabled
+ color
+ linked
+ unlinked
+ hand
+ zoom_all
+ zoom_selected
+ zoom_previous
+ zoom_in
+ zoom_out
+ render_region
+ border_rect
+ border_lasso
+ freeze
+ stylus_pressure
+ ghost_disabled
+ new
+ file_tick
+ quit
+ url
+ recover_last
+ fullscreen_enter
+ fullscreen_exit
+ lamp
+ material
+ texture
+ anim
+ world
+ scene
+ edit
+ game
+ radio
+ script
+ particles
+ physics
+ speaker
+ texture_shaded
+ view3d
+ ipo
+ oops
+ buts
+ filesel
+ image_col
+ info
+ sequence
+ text
+ imasel
+ sound
+ action
+ nla
+ scriptwin
+ time
+ nodetree
+ logic
+ console
+ preferences
+ clip
+ asset_manager
+ object_datamode
+ editmode_hlt
+ facesel_hlt
+ vpaint_hlt
+ tpaint_hlt
+ wpaint_hlt
+ sculptmode_hlt
+ pose_hlt
+ particlemode
+ lightpaint
+ greasepencil_stroke_paint
+ scene_data
+ renderlayers
+ world_data
+ object_data
+ mesh_data
+ curve_data
+ meta_data
+ lattice_data
+ lamp_data
+ material_data
+ texture_data
+ anim_data
+ camera_data
+ particle_data
+ library_data_direct
+ group
+ armature_data
+ pose_data
+ bone_data
+ constraint
+ shapekey_data
+ constraint_bone
+ camera_stereo
+ package
+ uglypackage
+ brush_data
+ image_data
+ file
+ fcurve
+ font_data
+ render_result
+ surface_data
+ empty_data
+ settings
+ render_animation
+ render_still
+ library_data_broken
+ boids
+ strands
+ library_data_indirect
+ greasepencil
+ line_data
+ library_data_override
+ group_bone
+ group_vertex
+ group_vcol
+ group_uvs
+ rna
+ rna_add
+ outliner_ob_empty
+ outliner_ob_mesh
+ outliner_ob_curve
+ outliner_ob_lattice
+ outliner_ob_meta
+ outliner_ob_lamp
+ outliner_ob_camera
+ outliner_ob_armature
+ outliner_ob_font
+ outliner_ob_surface
+ outliner_ob_speaker
+ outliner_ob_force_field
+ outliner_ob_group_instance
+ outliner_ob_greasepencil
+ restrict_color_off
+ restrict_color_on
+ restrict_view_off
+ restrict_view_on
+ restrict_select_off
+ restrict_select_on
+ restrict_render_off
+ restrict_render_on
+ outliner_data_empty
+ outliner_data_mesh
+ outliner_data_curve
+ outliner_data_lattice
+ outliner_data_meta
+ outliner_data_lamp
+ outliner_data_camera
+ outliner_data_armature
+ outliner_data_font
+ outliner_data_surface
+ outliner_data_speaker
+ outliner_data_pose
+ outliner_data_greasepencil
+ mesh_plane
+ mesh_cube
+ mesh_circle
+ mesh_uvsphere
+ mesh_icosphere
+ mesh_grid
+ mesh_monkey
+ mesh_cylinder
+ mesh_torus
+ mesh_cone
+ mesh_capsule
+ lamp_point
+ lamp_sun
+ lamp_spot
+ lamp_hemi
+ lamp_area
+ meta_empty
+ meta_plane
+ meta_cube
+ meta_ball
+ meta_ellipsoid
+ meta_capsule
+ surface_ncurve
+ surface_ncircle
+ surface_nsurface
+ surface_ncylinder
+ surface_nsphere
+ surface_ntorus
+ curve_bezcurve
+ curve_bezcircle
+ curve_ncurve
+ curve_ncircle
+ curve_path
+ color_red
+ color_green
+ color_blue
+ tria_right_bar
+ tria_down_bar
+ tria_left_bar
+ tria_up_bar
+ force_force
+ force_wind
+ force_vortex
+ force_magnetic
+ force_harmonic
+ force_charge
+ force_lennardjones
+ force_texture
+ force_curve
+ force_boid
+ force_turbulence
+ force_drag
+ force_smokeflow
+ node_insert_on
+ node_insert_off
+ modifier
+ mod_wave
+ mod_build
+ mod_decim
+ mod_mirror
+ mod_soft
+ mod_subsurf
+ hook
+ mod_physics
+ mod_particles
+ mod_boolean
+ mod_edgesplit
+ mod_array
+ mod_uvproject
+ mod_displace
+ mod_curve
+ mod_lattice
+ constraint_data
+ mod_armature
+ mod_shrinkwrap
+ mod_cast
+ mod_meshdeform
+ mod_bevel
+ mod_smooth
+ mod_simpledeform
+ mod_mask
+ mod_cloth
+ mod_explode
+ mod_fluidsim
+ mod_multires
+ mod_smoke
+ mod_solidify
+ mod_screw
+ mod_vertex_weight
+ mod_dynamicpaint
+ mod_remesh
+ mod_ocean
+ mod_warp
+ mod_skin
+ mod_triangulate
+ mod_wireframe
+ mod_data_transfer
+ mod_normaledit
+ rec
+ play
+ ff
+ rew
+ pause
+ prev_keyframe
+ next_keyframe
+ play_audio
+ play_reverse
+ preview_range
+ action_tweak
+ pmarker_act
+ pmarker_sel
+ pmarker
+ marker_hlt
+ marker
+ space2
+ space3
+ keyingset
+ key_dehlt
+ key_hlt
+ mute_ipo_off
+ mute_ipo_on
+ visible_ipo_off
+ visible_ipo_on
+ driver
+ solo_off
+ solo_on
+ frame_prev
+ frame_next
+ nla_pushdown
+ ipo_constant
+ ipo_linear
+ ipo_bezier
+ ipo_sine
+ ipo_quad
+ ipo_cubic
+ ipo_quart
+ ipo_quint
+ ipo_expo
+ ipo_circ
+ ipo_bounce
+ ipo_elastic
+ ipo_back
+ ipo_ease_in
+ ipo_ease_out
+ ipo_ease_in_out
+ normalize_fcurves
+ vertexsel
+ edgesel
+ facesel
+ loopsel
+ rotate
+ cursor
+ rotatecollection
+ rotatecenter
+ rotactive
+ align
+ smoothcurve
+ spherecurve
+ rootcurve
+ sharpcurve
+ lincurve
+ nocurve
+ rndcurve
+ prop_off
+ prop_on
+ prop_con
+ particle_point
+ particle_tip
+ particle_path
+ man_trans
+ man_rot
+ man_scale
+ manipul
+ snap_off
+ snap_on
+ snap_normal
+ snap_grid
+ snap_vertex
+ snap_edge
+ snap_face
+ snap_volume
+ snap_increment
+ sticky_uvs_loc
+ sticky_uvs_disable
+ sticky_uvs_vert
+ clipuv_dehlt
+ clipuv_hlt
+ snap_peel_object
+ grid
+ object_origin
+ pastedown
+ copydown
+ pasteflipup
+ pasteflipdown
+ snap_surface
+ automerge_on
+ automerge_off
+ retopo
+ uv_vertexsel
+ uv_edgesel
+ uv_facesel
+ uv_islandsel
+ uv_sync_select
+ bbox
+ wire
+ solid
+ smooth
+ potato
+ ortho
+ lockview_off
+ lockview_on
+ axis_side
+ axis_front
+ axis_top
+ ndof_dom
+ ndof_turn
+ ndof_fly
+ ndof_trans
+ layer_used
+ layer_active
+ sortalpha
+ sortbyext
+ sorttime
+ sortsize
+ longdisplay
+ shortdisplay
+ ghost
+ imgdisplay
+ save_as
+ save_copy
+ bookmarks
+ fontpreview
+ filter
+ newfolder
+ open_recent
+ file_parent
+ file_refresh
+ file_folder
+ file_blend
+ file_image
+ file_movie
+ file_script
+ file_sound
+ file_font
+ file_text
+ recover_auto
+ save_prefs
+ link_blend
+ append_blend
+ import
+ export
+ external_data
+ load_factory
+ loop_back
+ loop_forwards
+ back
+ forward
+ file_hidden
+ file_backup
+ disk_drive
+ matplane
+ matsphere
+ matcube
+ monkey
+ hair
+ aliased
+ antialiased
+ mat_sphere_sky
+ wordwrap_off
+ wordwrap_on
+ syntax_off
+ syntax_on
+ linenumbers_off
+ linenumbers_on
+ scriptplugins
+ seq_sequencer
+ seq_preview
+ seq_luma_waveform
+ seq_chroma_scope
+ seq_histogram
+ seq_splitview
+ image_rgb
+ image_rgb_alpha
+ image_alpha
+ image_zdepth
+ imagefile
+)
+
data_to_c_simple(../../../../release/datafiles/bfont.pfb SRC)
data_to_c_simple(../../../../release/datafiles/bfont.ttf SRC)
data_to_c_simple(../../../../release/datafiles/bmonofont.ttf SRC)
@@ -53,12 +547,12 @@ if(WITH_BLENDER)
#../../../../release/datafiles/blender_icons16.png
#90 SRC)
- data_to_c_simple_icons(../../../../release/datafiles/blender_icons16 SRC)
+ data_to_c_simple_icons(../../../../release/datafiles/blender_icons16 "icon16_" "${ICON_NAMES}" SRC)
#data_to_c_simple(../../../../release/datafiles/blender_icons16.png SRC)
#svg_to_png(../../../../release/datafiles/blender_icons.svg
#../../../../release/datafiles/blender_icons32.png
#180 SRC)
- data_to_c_simple_icons(../../../../release/datafiles/blender_icons32 SRC)
+ data_to_c_simple_icons(../../../../release/datafiles/blender_icons32 "icon32_" "${ICON_NAMES}" SRC)
#data_to_c_simple(../../../../release/datafiles/blender_icons32.png SRC)
#svg_to_png(../../../../release/datafiles/prvicons.svg
#../../../../release/datafiles/prvicons.png
@@ -130,4 +624,6 @@ if(WITH_BLENDER)
data_to_c_simple(../../../../release/datafiles/startup.blend SRC)
endif()
+unset(ICON_NAMES)
+
blender_add_lib(bf_editor_datafiles "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index a82148788c8..22a3224e563 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -105,7 +105,8 @@ static int gpencil_editmode_toggle_exec(bContext *C, wmOperator *UNUSED(op))
ED_gpencil_reset_layers_parent(gpd);
}
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, NULL);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_GPENCIL_EDITMODE, NULL);
WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
return OPERATOR_FINISHED;
@@ -153,7 +154,8 @@ static int gpencil_hideselect_toggle_exec(bContext *C, wmOperator *UNUSED(op))
ts->gp_sculpt.alpha = 1.0f;
}
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, NULL);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_GPENCIL_EDITMODE, NULL);
WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index e66e5e7462d..8201401296a 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -236,6 +236,8 @@ eV3DProjStatus ED_view3d_project_float_ex(const struct ARegion *ar, float perspm
eV3DProjStatus ED_view3d_project_float_global(const struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag);
eV3DProjStatus ED_view3d_project_float_object(const struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag);
+float ED_view3d_pixel_size(const struct RegionView3D *rv3d, const float co[3]);
+
float ED_view3d_calc_zfac(const struct RegionView3D *rv3d, const float co[3], bool *r_flip);
bool ED_view3d_clip_segment(const struct RegionView3D *rv3d, float ray_start[3], float ray_end[3]);
bool ED_view3d_win_to_ray(
@@ -308,8 +310,6 @@ void ED_view3d_clipping_set(struct RegionView3D *rv3d);
void ED_view3d_clipping_enable(void);
void ED_view3d_clipping_disable(void);
-float ED_view3d_pixel_size(const struct RegionView3D *rv3d, const float co[3]);
-
float ED_view3d_radius_to_dist_persp(const float angle, const float radius);
float ED_view3d_radius_to_dist_ortho(const float lens, const float radius);
float ED_view3d_radius_to_dist(
@@ -446,6 +446,9 @@ uint64_t ED_view3d_datamask(const struct Scene *scene, const struct View3D *v3d)
uint64_t ED_view3d_screen_datamask(const struct Scene *scene, const struct bScreen *screen);
bool ED_view3d_offset_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d);
+void ED_view3d_persp_switch_from_camera(struct View3D *v3d, struct RegionView3D *rv3d, const char persp);
+bool ED_view3d_persp_ensure(struct View3D *v3d, struct ARegion *ar);
+
/* camera lock functions */
bool ED_view3d_camera_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d);
@@ -462,7 +465,7 @@ bool ED_view3d_camera_lock_autokey(
struct View3D *v3d, struct RegionView3D *rv3d,
struct bContext *C, const bool do_rotate, const bool do_translate);
-void ED_view3D_lock_clear(struct View3D *v3d);
+void ED_view3d_lock_clear(struct View3D *v3d);
#define VIEW3D_MARGIN 1.4f
#define VIEW3D_DIST_FALLBACK 1.0f
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 0b846ad642f..b6714e80e80 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -190,8 +190,8 @@ DEF_ICON(SCULPTMODE_HLT)
DEF_ICON(POSE_HLT)
DEF_ICON(PARTICLEMODE)
DEF_ICON(LIGHTPAINT)
+DEF_ICON(GREASEPENCIL_STROKE_PAINT)
#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK063)
DEF_ICON(BLANK064)
DEF_ICON(BLANK065)
DEF_ICON(BLANK066)
@@ -313,6 +313,7 @@ DEF_ICON(OUTLINER_OB_SURFACE)
DEF_ICON(OUTLINER_OB_SPEAKER)
DEF_ICON(OUTLINER_OB_FORCE_FIELD)
DEF_ICON(OUTLINER_OB_GROUP_INSTANCE)
+DEF_ICON(OUTLINER_OB_GREASEPENCIL)
DEF_ICON(OUTLINER_OB_GROOM)
#ifndef DEF_ICON_BLANK_SKIP
DEF_ICON(BLANK123)
@@ -344,8 +345,8 @@ DEF_ICON(OUTLINER_DATA_FONT)
DEF_ICON(OUTLINER_DATA_SURFACE)
DEF_ICON(OUTLINER_DATA_SPEAKER)
DEF_ICON(OUTLINER_DATA_POSE)
+DEF_ICON(OUTLINER_DATA_GREASEPENCIL)
#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK130)
DEF_ICON(BLANK131)
DEF_ICON(BLANK132)
DEF_ICON(BLANK133)
@@ -713,8 +714,8 @@ DEF_ICON(CLIPUV_DEHLT)
DEF_ICON(CLIPUV_HLT)
DEF_ICON(SNAP_PEEL_OBJECT)
DEF_ICON(GRID)
+DEF_ICON(OBJECT_ORIGIN)
#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK221)
DEF_ICON(BLANK222)
DEF_ICON(BLANK224)
DEF_ICON(BLANK225)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 5d7a45a7e48..6e09318314d 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1105,6 +1105,8 @@ void UI_context_active_but_prop_get_templateID(
struct bContext *C,
struct PointerRNA *r_ptr, struct PropertyRNA **r_prop);
+uiBut *UI_region_active_but_get(struct ARegion *ar);
+
/* Styled text draw */
void UI_fontstyle_set(const struct uiFontStyle *fs);
void UI_fontstyle_draw_ex(const struct uiFontStyle *fs, const struct rcti *rect, const char *str,
@@ -1151,7 +1153,7 @@ void UI_butstore_unregister(uiButStore *bs_handle, uiBut **but_p);
/* ui_interface_region_tooltip.c */
struct ARegion *UI_tooltip_create_from_button(struct bContext *C, struct ARegion *butregion, uiBut *but);
struct ARegion *UI_tooltip_create_from_manipulator(struct bContext *C, struct wmManipulator *mpr);
-void UI_tooltip_free(struct bContext *C, struct ARegion *ar);
+void UI_tooltip_free(struct bContext *C, struct bScreen *sc, struct ARegion *ar);
/* How long before a tool-tip shows. */
#define UI_TOOLTIP_DELAY 0.5
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 9c1cee915e4..3af64c8c5a6 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -296,8 +296,6 @@ typedef struct uiHandleButtonData {
ColorBand *coba;
/* tooltip */
- ARegion *tooltip;
- wmTimer *tooltiptimer;
unsigned int tooltip_force : 1;
/* auto open */
@@ -7701,12 +7699,12 @@ static bool button_modal_state(uiHandleButtonState state)
*/
void UI_but_tooltip_refresh(bContext *C, uiBut *but)
{
- uiHandleButtonData *data;
-
- data = but->active;
- if (data && data->tooltip) {
- UI_tooltip_free(C, data->tooltip);
- data->tooltip = UI_tooltip_create_from_button(C, data->region, but);
+ uiHandleButtonData *data = but->active;
+ if (data) {
+ bScreen *sc = WM_window_get_active_screen(data->window);
+ if (sc->tool_tip && sc->tool_tip->region) {
+ WM_tooltip_refresh(C, data->window);
+ }
}
}
@@ -7717,39 +7715,38 @@ void UI_but_tooltip_timer_remove(bContext *C, uiBut *but)
data = but->active;
if (data) {
-
- if (data->tooltiptimer) {
- WM_event_remove_timer(data->wm, data->window, data->tooltiptimer);
- data->tooltiptimer = NULL;
- }
- if (data->tooltip) {
- UI_tooltip_free(C, data->tooltip);
- data->tooltip = NULL;
- }
-
if (data->autoopentimer) {
WM_event_remove_timer(data->wm, data->window, data->autoopentimer);
data->autoopentimer = NULL;
}
+
+ if (data->window) {
+ WM_tooltip_clear(C, data->window);
+ }
+ }
+}
+
+static ARegion *ui_but_tooltip_init(bContext *C, ARegion *ar, bool *r_exit_on_event)
+{
+ uiBut *but = UI_region_active_but_get(ar);
+ *r_exit_on_event = false;
+ if (but) {
+ return UI_tooltip_create_from_button(C, ar, but);
}
+ return NULL;
}
static void button_tooltip_timer_reset(bContext *C, uiBut *but)
{
wmWindowManager *wm = CTX_wm_manager(C);
- uiHandleButtonData *data;
-
- data = but->active;
+ uiHandleButtonData *data = but->active;
- if (data->tooltiptimer) {
- WM_event_remove_timer(data->wm, data->window, data->tooltiptimer);
- data->tooltiptimer = NULL;
- }
+ WM_tooltip_timer_clear(C, data->window);
if ((U.flag & USER_TOOLTIPS) || (data->tooltip_force)) {
if (!but->block->tooltipdisabled) {
if (!wm->drags.first) {
- data->tooltiptimer = WM_event_add_timer(data->wm, data->window, TIMER, UI_TOOLTIP_DELAY);
+ WM_tooltip_timer_init(C, data->window, data->region, ui_but_tooltip_init);
}
}
}
@@ -8109,12 +8106,10 @@ void ui_but_active_free(const bContext *C, uiBut *but)
}
/* returns the active button with an optional checking function */
-static uiBut *ui_context_button_active(const bContext *C, bool (*but_check_cb)(uiBut *))
+static uiBut *ui_context_button_active(ARegion *ar, bool (*but_check_cb)(uiBut *))
{
uiBut *but_found = NULL;
- ARegion *ar = CTX_wm_region(C);
-
while (ar) {
uiBlock *block;
uiBut *but, *activebut = NULL;
@@ -8157,12 +8152,17 @@ static bool ui_context_rna_button_active_test(uiBut *but)
}
static uiBut *ui_context_rna_button_active(const bContext *C)
{
- return ui_context_button_active(C, ui_context_rna_button_active_test);
+ return ui_context_button_active(CTX_wm_region(C), ui_context_rna_button_active_test);
}
uiBut *UI_context_active_but_get(const struct bContext *C)
{
- return ui_context_button_active(C, NULL);
+ return ui_context_button_active(CTX_wm_region(C), NULL);
+}
+
+uiBut *UI_region_active_but_get(ARegion *ar)
+{
+ return ui_context_button_active(ar, NULL);
}
/**
@@ -8445,16 +8445,8 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
}
case TIMER:
{
- /* handle tooltip timer */
- if (event->customdata == data->tooltiptimer) {
- WM_event_remove_timer(data->wm, data->window, data->tooltiptimer);
- data->tooltiptimer = NULL;
-
- if (!data->tooltip)
- data->tooltip = UI_tooltip_create_from_button(C, data->region, but);
- }
/* handle menu auto open timer */
- else if (event->customdata == data->autoopentimer) {
+ if (event->customdata == data->autoopentimer) {
WM_event_remove_timer(data->wm, data->window, data->autoopentimer);
data->autoopentimer = NULL;
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index eeda0a25195..16525dfbc9e 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -1485,7 +1485,7 @@ void ED_keymap_ui(wmKeyConfig *keyconf)
* through until a suitable eyedropper for the active button is found */
WM_keymap_add_item(keymap, "UI_OT_eyedropper_color", EKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "UI_OT_eyedropper_colorband", EKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "UI_OT_eyedropper_colorband_point", EKEY, KM_PRESS , KM_ALT, 0);
+ WM_keymap_add_item(keymap, "UI_OT_eyedropper_colorband_point", EKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "UI_OT_eyedropper_id", EKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "UI_OT_eyedropper_depth", EKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index 9a818efebee..07fbefa42e1 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -953,9 +953,9 @@ ARegion *UI_tooltip_create_from_manipulator(bContext *C, wmManipulator *mpr)
return ui_tooltip_create_with_data(C, data, init_position, aspect);
}
-void UI_tooltip_free(bContext *C, ARegion *ar)
+void UI_tooltip_free(bContext *C, bScreen *sc, ARegion *ar)
{
- ui_region_temp_remove(C, CTX_wm_screen(C), ar);
+ ui_region_temp_remove(C, sc, ar);
}
/** \} */
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index b271b0b5bc6..dc68c8b58de 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -1509,6 +1509,9 @@ static int view2d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const w
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), v2d->smooth_timer);
v2d->smooth_timer = NULL;
+
+ /* Event handling won't know if a UI item has been moved under the pointer. */
+ WM_event_add_mousemove(C);
}
else {
/* ease in/out */
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index fc227a2aa75..1b7fd319da0 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -40,6 +40,8 @@
#include "BKE_main.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "ED_screen.h"
#include "ED_object.h"
@@ -447,6 +449,7 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op)
min_chain_length,
keep_bind_info) )
{
+ DEG_id_tag_update(&CTX_data_scene(C)->id, DEG_TAG_BASE_FLAGS_UPDATE);
return OPERATOR_FINISHED;
}
else {
diff --git a/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c
index ce6992e7ad9..7e57b48c77c 100644
--- a/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c
+++ b/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c
@@ -133,7 +133,6 @@ static void button2d_draw_intern(
if (select == false) {
if (button->shape_batch[0] != NULL) {
- glEnable(GL_POLYGON_SMOOTH);
glEnable(GL_LINE_SMOOTH);
glLineWidth(1.0f);
for (uint i = 0; i < ARRAY_SIZE(button->shape_batch) && button->shape_batch[i]; i++) {
@@ -146,7 +145,6 @@ static void button2d_draw_intern(
GWN_batch_uniform_4f(button->shape_batch[i], "color", UNPACK4(color));
GWN_batch_draw(button->shape_batch[i]);
}
- glDisable(GL_POLYGON_SMOOTH);
glDisable(GL_LINE_SMOOTH);
gpuPopMatrix();
}
@@ -206,9 +204,12 @@ static int manipulator_button2d_test_select(
return -1;
}
-static int manipulator_button2d_cursor_get(wmManipulator *UNUSED(mpr))
+static int manipulator_button2d_cursor_get(wmManipulator *mpr)
{
- return BC_HANDCURSOR;
+ if (RNA_boolean_get(mpr->ptr, "show_drag")) {
+ return BC_NSEW_SCROLLCURSOR;
+ }
+ return CURSOR_STD;
}
static void manipulator_button2d_free(wmManipulator *mpr)
@@ -248,6 +249,9 @@ static void MANIPULATOR_WT_button_2d(wmManipulatorType *wt)
/* Passed to 'GPU_batch_from_poly_2d_encoded' */
RNA_def_property(wt->srna, "shape", PROP_STRING, PROP_BYTESTRING);
+
+ /* Currently only used for cursor display. */
+ RNA_def_boolean(wt->srna, "show_drag", true, "Show Drag", "");
}
void ED_manipulatortypes_button_2d(void)
diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c
index d7e59a05772..bd2ad21d51c 100644
--- a/source/blender/editors/mesh/mesh_navmesh.c
+++ b/source/blender/editors/mesh/mesh_navmesh.c
@@ -75,7 +75,7 @@ static void createVertsTrisData(bContext *C, LinkNode *obs,
DerivedMesh *dm;
Scene *scene = CTX_data_scene(C);
EvaluationContext eval_ctx;
- LinkNode *dms = NULL;
+ LinkNodePair dms_pair = {NULL, NULL};
int nverts, ntris, *tris;
float *verts;
@@ -90,7 +90,7 @@ static void createVertsTrisData(bContext *C, LinkNode *obs,
ob = (Object *) oblink->link;
dm = mesh_create_derived_no_virtual(&eval_ctx, scene, ob, NULL, CD_MASK_MESH);
DM_ensure_tessface(dm);
- BLI_linklist_prepend(&dms, dm);
+ BLI_linklist_append(&dms_pair, dm);
nverts += dm->getNumVerts(dm);
nfaces = dm->getNumTessFaces(dm);
@@ -106,6 +106,7 @@ static void createVertsTrisData(bContext *C, LinkNode *obs,
*r_lay |= ob->lay;
}
+ LinkNode *dms = dms_pair.list;
/* create data */
verts = MEM_mallocN(sizeof(float) * 3 * nverts, "createVertsTrisData verts");
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index af131e270ef..89b131fa340 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -2123,7 +2123,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer
#define ID_NEW_REMAP_US(a) if ( (a)->id.newid) { (a) = (void *)(a)->id.newid; (a)->id.us++; }
#define ID_NEW_REMAP_US2(a) if (((ID *)a)->newid) { (a) = ((ID *)a)->newid; ((ID *)a)->us++; }
- Base *basen = NULL;
+ Base *base, *basen = NULL;
Material ***matarar;
Object *obn;
ID *id;
@@ -2136,7 +2136,14 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer
obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
DEG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- BKE_collection_object_add_from(scene, ob, obn);
+ base = BKE_view_layer_base_find(view_layer, ob);
+ if ((base != NULL) && (base->flag & BASE_VISIBLED)) {
+ BKE_collection_object_add_from(scene, ob, obn);
+ }
+ else {
+ LayerCollection *layer_collection = BKE_layer_collection_get_active_ensure(scene, view_layer);
+ BKE_collection_object_add(&scene->id, layer_collection->scene_collection, obn);
+ }
basen = BKE_view_layer_base_find(view_layer, obn);
/* 1) duplis should end up in same group as the original
@@ -2486,13 +2493,13 @@ static int add_named_exec(bContext *C, wmOperator *op)
clear_sca_new_poins(); /* BGE logic */
basen = object_add_duplicate_internal(bmain, scene, view_layer, ob, dupflag);
- BKE_scene_object_base_flag_sync_from_object(basen);
if (basen == NULL) {
BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated");
return OPERATOR_CANCELLED;
}
+ BKE_scene_object_base_flag_sync_from_object(basen);
basen->object->restrictflag &= ~OB_RESTRICT_VIEW;
if (event) {
@@ -2510,9 +2517,11 @@ static int add_named_exec(bContext *C, wmOperator *op)
BKE_main_id_clear_newpoins(bmain);
+ /* TODO(sergey): Only update relations for the current scene. */
DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT | ND_OB_ACTIVE, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index b351bc7f114..13cc53c04a7 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -1679,9 +1679,6 @@ static void single_object_users_scene_collection(Main *bmain, Scene *scene, Scen
}
}
- /* we reset filter objects because they should be regenerated after this */
- BLI_freelistN(&sc->filter_objects);
-
for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
single_object_users_scene_collection(bmain, scene, nsc, flag, copy_groups);
}
@@ -1741,9 +1738,6 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
libblock_relink_scene_collection(msc);
set_sca_new_poins();
-
- /* TODO redo filter */
- TODO_LAYER_SYNC_FILTER
}
/* not an especially efficient function, only added so the single user
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 6fdbe5e88a2..270ba2a7947 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -427,7 +427,8 @@ static int material_slot_move_exec(bContext *C, wmOperator *op)
MEM_freeN(slot_remap);
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW | ND_DATA, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c
index 694770d088d..2e4e9127ed6 100644
--- a/source/blender/editors/screen/screen_draw.c
+++ b/source/blender/editors/screen/screen_draw.c
@@ -288,7 +288,7 @@ static void drawscredge_area(ScrArea *sa, int sizex, int sizey, unsigned int pos
}
/**
- * Only for edge lines between areas, and the blended join arrows.
+ * Only for edge lines between areas.
*/
void ED_screen_draw_edges(wmWindow *win)
{
@@ -326,6 +326,12 @@ void ED_screen_draw_edges(wmWindow *win)
screen->do_draw = false;
}
+/**
+ * The blended join arrows.
+ *
+ * \param sa1: Area from which the resultant originates.
+ * \param sa2: Target area that will be replaced.
+ */
void ED_screen_draw_join_shape(ScrArea *sa1, ScrArea *sa2)
{
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index b73174917f3..030c24b0061 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -1479,8 +1479,6 @@ static void SCREEN_OT_area_move(wmOperatorType *ot)
*/
typedef struct sAreaSplitData {
- int x, y; /* last used mouse position */
-
int origval; /* for move areas */
int bigger, smaller; /* constraints for moving new edge */
int delta; /* delta move edge */
@@ -1727,9 +1725,6 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
sd = (sAreaSplitData *)op->customdata;
- sd->x = event->x;
- sd->y = event->y;
-
if (event->type == EVT_ACTIONZONE_AREA) {
/* do the split */
@@ -1797,28 +1792,9 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* execute the events */
switch (event->type) {
case MOUSEMOVE:
- {
- const int dir = RNA_property_enum_get(op->ptr, prop_dir);
-
- sd->delta = (dir == 'v') ? event->x - sd->origval : event->y - sd->origval;
- if (sd->previewmode == 0)
- area_move_apply_do(C, sd->delta, sd->origval, dir, sd->bigger, sd->smaller, sd->do_snap);
- else {
- if (sd->sarea) {
- ED_area_tag_redraw(sd->sarea);
- }
- /* area context not set */
- sd->sarea = BKE_screen_find_area_xy(CTX_wm_screen(C), SPACE_TYPE_ANY, event->x, event->y);
-
- if (sd->sarea) {
- ED_area_tag_redraw(sd->sarea);
- update_factor = true;
- }
-
- CTX_wm_screen(C)->do_draw = true;
- }
+ update_factor = true;
break;
- }
+
case LEFTMOUSE:
if (sd->previewmode) {
area_split_apply(C, op);
@@ -1845,8 +1821,6 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
RNA_property_enum_set(op->ptr, prop_dir, (dir == 'v') ? 'h' : 'v');
area_split_preview_update_cursor(C, op);
update_factor = true;
-
- ED_area_tag_redraw(sd->sarea);
}
}
}
@@ -1866,31 +1840,53 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (update_factor) {
const int dir = RNA_property_enum_get(op->ptr, prop_dir);
- float fac;
- if (dir == 'v') {
- sd->origsize = sd->sarea->winx;
- sd->origmin = sd->sarea->totrct.xmin;
+ sd->delta = (dir == 'v') ? event->x - sd->origval : event->y - sd->origval;
+
+ if (sd->previewmode == 0) {
+ if (sd->do_snap) {
+ const int snap_loc = area_snap_calc_location(
+ CTX_wm_screen(C), sd->delta, sd->origval, dir, sd->bigger, sd->smaller);
+ sd->delta = snap_loc - sd->origval;
+ }
+ area_move_apply_do(C, sd->delta, sd->origval, dir, sd->bigger, sd->smaller, false);
}
else {
- sd->origsize = sd->sarea->winy;
- sd->origmin = sd->sarea->totrct.ymin;
- }
+ if (sd->sarea) {
+ ED_area_tag_redraw(sd->sarea);
+ }
+ /* area context not set */
+ sd->sarea = BKE_screen_find_area_xy(CTX_wm_screen(C), SPACE_TYPE_ANY, event->x, event->y);
+
+ if (sd->sarea) {
+ ScrArea *sa = sd->sarea;
+ if (dir == 'v') {
+ sd->origsize = sa->winx;
+ sd->origmin = sa->totrct.xmin;
+ }
+ else {
+ sd->origsize = sa->winy;
+ sd->origmin = sa->totrct.ymin;
+ }
- if (sd->do_snap) {
- ScrArea *sa = sd->sarea;
- sa->v1->editflag = sa->v2->editflag = sa->v3->editflag = sa->v4->editflag = 1;
+ if (sd->do_snap) {
+ sa->v1->editflag = sa->v2->editflag = sa->v3->editflag = sa->v4->editflag = 1;
- int snap_loc = area_snap_calc_location(
- CTX_wm_screen(C), sd->delta, sd->origval, dir, sd->origmin + sd->origsize, -sd->origmin);
+ const int snap_loc = area_snap_calc_location(
+ CTX_wm_screen(C), sd->delta, sd->origval, dir, sd->origmin + sd->origsize, -sd->origmin);
- sa->v1->editflag = sa->v2->editflag = sa->v3->editflag = sa->v4->editflag = 0;
- fac = snap_loc - sd->origmin;
- }
- else {
- fac = (dir == 'v') ? event->x - sd->origmin : event->y - sd->origmin;
+ sa->v1->editflag = sa->v2->editflag = sa->v3->editflag = sa->v4->editflag = 0;
+ sd->delta = snap_loc - sd->origval;
+ }
+
+ ED_area_tag_redraw(sd->sarea);
+ }
+
+ CTX_wm_screen(C)->do_draw = true;
}
- RNA_float_set(op->ptr, "factor", fac / (float)sd->origsize);
+
+ float fac = (float)(sd->delta + sd->origval - sd->origmin) / sd->origsize;
+ RNA_float_set(op->ptr, "factor", fac);
}
return OPERATOR_RUNNING_MODAL;
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 9dd51b289f4..3982c9a3c30 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -109,6 +109,8 @@ typedef struct PaintStroke {
* e.g. in sculpt mode, stroke doesn't start until cursor
* passes over the mesh */
bool stroke_started;
+ /* Set when enough motion was found for rake rotation */
+ bool rake_started;
/* event that started stroke, for modal() return */
int event_type;
/* check if stroke variables have been initialized */
@@ -376,7 +378,12 @@ static bool paint_brush_update(bContext *C,
else if (!(brush->flag & BRUSH_CURVE)) {
if (!paint_calculate_rake_rotation(ups, brush, mouse_init)) {
/* Not enough motion to define an angle. */
- is_dry_run = true;
+ if (!stroke->rake_started) {
+ is_dry_run = true;
+ }
+ }
+ else {
+ stroke->rake_started = true;
}
}
}
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index 1c55a0d76cf..110c4d1789d 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -1127,7 +1127,8 @@ static int actkeys_select_leftright_exec(bContext *C, wmOperator *op)
actkeys_select_leftright(&ac, leftright, selectmode);
/* set notifier that keyframe selection (and channels too) have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | ND_ANIMCHAN | NA_SELECTED, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
}
@@ -1577,7 +1578,8 @@ static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent
mouse_action_keys(&ac, event->mval, selectmode, column, channel);
/* set notifier that keyframe selection (and channels too) have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | ND_ANIMCHAN | NA_SELECTED, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
/* for tweak grab to work */
return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 0e5c5ddc0c7..ce6ce802a5b 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -2792,7 +2792,8 @@ static int graph_driver_delete_invalid_exec(bContext *C, wmOperator *op)
DEG_relations_tag_update(CTX_data_main(C));
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL);
WM_reportf(RPT_INFO, "Deleted %u drivers", deleted);
- } else {
+ }
+ else {
WM_report(RPT_INFO, "No drivers deleted");
}
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index 1683fbdbdb9..392db4ef4b5 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -1003,7 +1003,8 @@ static int graphkeys_select_leftright_exec(bContext *C, wmOperator *op)
graphkeys_select_leftright(&ac, leftright, selectmode);
/* set notifier that keyframe selection (and channels too) have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | ND_ANIMCHAN | NA_SELECTED, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
}
@@ -1517,7 +1518,8 @@ static int graphkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEve
}
/* set notifier that keyframe selection (and also channel selection in some cases) has changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | ND_ANIMCHAN | NA_SELECTED, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
/* for tweak grab to work */
return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 2cc5c7f8d68..6c0ab33dd2c 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1858,7 +1858,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
scene = CTX_data_scene(C);
rr = BKE_image_acquire_renderresult(scene, ima);
bool is_mono = rr ? BLI_listbase_count_ex(&rr->views, 2) < 2 : BLI_listbase_count_ex(&ima->views, 2) < 2;
- bool is_exr_rr = rr && ELEM(imf->imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER);
+ bool is_exr_rr = rr && ELEM(imf->imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER) && RE_HasFloatPixels(rr);
/* error handling */
if (!rr) {
diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c
index 1179401f346..e09e4417d5d 100644
--- a/source/blender/editors/space_nla/nla_select.c
+++ b/source/blender/editors/space_nla/nla_select.c
@@ -444,7 +444,8 @@ static int nlaedit_select_leftright_exec(bContext *C, wmOperator *op)
nlaedit_select_leftright(C, &ac, leftright, selectmode);
/* set notifier that keyframe selection (and channels too) have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | ND_ANIMCHAN | NA_SELECTED, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 0fdd52d3205..1bee2716e65 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -633,7 +633,8 @@ static void node_common_set_butfunc(bNodeType *ntype)
/* ****************** BUTTON CALLBACKS FOR SHADER NODES ***************** */
static void node_buts_image_user(uiLayout *layout, bContext *C, PointerRNA *ptr,
- PointerRNA *imaptr, PointerRNA *iuserptr)
+ PointerRNA *imaptr, PointerRNA *iuserptr,
+ bool compositor)
{
uiLayout *col;
int source;
@@ -668,7 +669,8 @@ static void node_buts_image_user(uiLayout *layout, bContext *C, PointerRNA *ptr,
uiItemR(col, ptr, "use_auto_refresh", 0, NULL, ICON_NONE);
}
- if (RNA_enum_get(imaptr, "type") == IMA_TYPE_MULTILAYER &&
+ if (compositor &&
+ RNA_enum_get(imaptr, "type") == IMA_TYPE_MULTILAYER &&
RNA_boolean_get(ptr, "has_layers"))
{
col = uiLayoutColumn(layout, false);
@@ -792,7 +794,7 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA
/* note: image user properties used directly here, unlike compositor image node,
* which redefines them in the node struct RNA to get proper updates.
*/
- node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr);
+ node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false);
}
static void node_shader_buts_tex_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -811,7 +813,7 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin
layout, C, ptr, "image",
NULL, "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL);
- node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr);
+ node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false);
uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE);
@@ -1261,7 +1263,7 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *
imaptr = RNA_pointer_get(ptr, "image");
- node_buts_image_user(layout, C, ptr, &imaptr, &iuserptr);
+ node_buts_image_user(layout, C, ptr, &imaptr, &iuserptr, true);
node_buts_image_views(layout, C, ptr, &imaptr);
}
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 1ffe62fbc00..8999555521a 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -58,9 +58,6 @@ static int collection_delete_exec(struct bContext *C, struct wmOperator *op);
static LayerCollection *outliner_collection_active(bContext *C)
{
- TODO_LAYER_OPERATORS;
- /* consider that we may have overrides or objects active
- * leading to no active collections */
return CTX_data_layer_collection(C);
}
@@ -79,15 +76,6 @@ SceneCollection *outliner_scene_collection_from_tree_element(TreeElement *te)
return NULL;
}
-#if 0
-static CollectionOverride *outliner_override_active(bContext *UNUSED(C))
-{
- TODO_LAYER_OPERATORS;
- TODO_LAYER_OVERRIDE;
- return NULL;
-}
-#endif
-
/* -------------------------------------------------------------------- */
/* Poll functions. */
@@ -250,7 +238,6 @@ void OUTLINER_OT_collection_link(wmOperatorType *ot)
/* api callbacks */
ot->exec = collection_link_exec;
ot->invoke = collection_link_invoke;
- ot->poll = view_layer_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -327,14 +314,12 @@ void OUTLINER_OT_collection_unlink(wmOperatorType *ot)
static int collection_new_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceOops *soops = CTX_wm_space_outliner(C);
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
SceneCollection *scene_collection = BKE_collection_add(&scene->id, NULL, COLLECTION_TYPE_NONE, NULL);
BKE_collection_link(view_layer, scene_collection);
- outliner_cleanup_tree(soops);
DEG_relations_tag_update(bmain);
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
return OPERATOR_FINISHED;
@@ -572,46 +557,6 @@ void OUTLINER_OT_collection_objects_remove(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/**********************************************************************************/
-
-/**
- * Returns true is selected element is a collection
- */
-static int collection_override_new_poll(bContext *(C))
-{
-#ifdef TODO_LAYER_OVERRIDE
- /* disable for now, since it's not implemented */
- (void) C;
- return 0;
-#else
- return outliner_collection_active(C) ? 1 : 0;
-#endif
-}
-
-static int collection_override_new_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event))
-{
- TODO_LAYER_OPERATORS;
- TODO_LAYER_OVERRIDE;
- BKE_report(op->reports, RPT_ERROR, "OUTLINER_OT_collections_override_new not implemented yet");
- return OPERATOR_CANCELLED;
-}
-
-/* in the middle of renames remove s */
-void OUTLINER_OT_collection_override_new(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "New Override";
- ot->idname = "OUTLINER_OT_collection_override_new";
- ot->description = "Add a new override to the active collection";
-
- /* api callbacks */
- ot->invoke = collection_override_new_invoke;
- ot->poll = collection_override_new_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
struct CollectionDeleteData {
Scene *scene;
SpaceOops *soops;
@@ -666,8 +611,6 @@ static int collection_delete_exec(bContext *C, wmOperator *UNUSED(op))
data.collections_to_delete = BLI_gset_ptr_new(__func__);
- TODO_LAYER_OVERRIDE; /* handle overrides */
-
/* We first walk over and find the SceneCollections we actually want to delete (ignoring duplicates). */
outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_delete, &data);
@@ -814,40 +757,3 @@ void OUTLINER_OT_collection_toggle(wmOperatorType *ot)
#undef ACTION_TOGGLE
#undef ACTION_ENABLE
#undef ACTION_DISABLE
-
-/* -------------------------------------------------------------------- */
-
-static int stubs_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event))
-{
- TODO_LAYER_OPERATORS;
- BKE_report(op->reports, RPT_ERROR, "Operator not implemented yet");
- return OPERATOR_CANCELLED;
-}
-
-void OUTLINER_OT_collection_objects_select(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Objects";
- ot->idname = "OUTLINER_OT_collection_objects_select";
- ot->description = "Select collection objects";
-
- /* api callbacks */
- ot->invoke = stubs_invoke;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-void OUTLINER_OT_collection_objects_deselect(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Deselect Objects";
- ot->idname = "OUTLINER_OT_collection_objects_deselect";
- ot->description = "Deselect collection objects";
-
- /* api callbacks */
- ot->invoke = stubs_invoke;
-
- /* 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 feeade036d1..45459bdb030 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -1427,11 +1427,7 @@ static void outliner_draw_tree_element(
}
else if (te->subtree.first || (tselem->type == 0 && te->idcode == ID_SCE) || (te->flag & TE_LAZY_CLOSED)) {
/* open/close icon, only when sublevels, except for scene */
- int icon_x;
- if (tselem->type == 0 && ELEM(te->idcode, ID_OB, ID_SCE))
- icon_x = startx;
- else
- icon_x = startx + 5 * ufac;
+ int icon_x = startx;
// icons a bit higher
if (TSELEM_OPEN(tselem, soops))
@@ -1819,7 +1815,7 @@ static void outliner_draw_tree(
// gray hierarchy lines
starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y / 2 - OL_Y_OFFSET;
- startx = 6;
+ startx = UI_UNIT_X / 2 - 1.0f;
outliner_draw_hierarchy_lines(soops, &soops->tree, startx, &starty);
// items themselves
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index fb4c8cd7506..30ede0a5e55 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -48,6 +48,7 @@ struct ID;
struct Object;
struct bPoseChannel;
struct EditBone;
+struct wmEvent;
struct wmKeyConfig;
@@ -72,7 +73,9 @@ typedef enum TreeTraversalAction {
typedef void (*TreeElementReinsertFunc)(struct Main *bmain,
struct SpaceOops *soops,
struct TreeElement *insert_element,
- struct TreeElement *insert_handle, TreeElementInsertType action);
+ struct TreeElement *insert_handle,
+ TreeElementInsertType action,
+ const struct wmEvent *event);
/**
* Executed on (almost) each mouse move while dragging. It's supposed to give info
* if reinserting insert_element before/after/into insert_handle would be allowed.
@@ -104,6 +107,7 @@ typedef struct TreeElement {
TreeElementInsertType insert_type;
/* the element before/after/into which we may insert the dragged one (NULL to insert at top) */
struct TreeElement *insert_handle;
+ void *tooltip_draw_handle;
} *drag_data;
} TreeElement;
@@ -340,10 +344,7 @@ void OUTLINER_OT_collection_toggle(struct wmOperatorType *ot);
void OUTLINER_OT_collection_link(struct wmOperatorType *ot);
void OUTLINER_OT_collection_unlink(struct wmOperatorType *ot);
void OUTLINER_OT_collection_new(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_override_new(struct wmOperatorType *ot);
void OUTLINER_OT_collection_objects_remove(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_objects_select(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_objects_deselect(struct wmOperatorType *ot);
void OUTLINER_OT_collection_objects_add(struct wmOperatorType *ot);
void OUTLINER_OT_collection_nested_new(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index 9022552c429..52f27b9708e 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -33,9 +33,13 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "BLT_translation.h"
+
#include "BKE_context.h"
#include "BKE_main.h"
+#include "GPU_immediate.h"
+
#include "RNA_access.h"
#include "UI_interface.h"
@@ -48,6 +52,11 @@
#include "outliner_intern.h"
+typedef struct OutlinerDragDropTooltip {
+ TreeElement *te;
+ void *handle;
+} OutlinerDragDropTooltip;
+
enum {
OUTLINER_ITEM_DRAG_CANCEL,
OUTLINER_ITEM_DRAG_CONFIRM,
@@ -69,9 +78,15 @@ static TreeElement *outliner_item_drag_element_find(SpaceOops *soops, ARegion *a
return outliner_find_item_at_y(soops, &soops->tree, my);
}
-static void outliner_item_drag_end(TreeElement *dragged_te)
+static void outliner_item_drag_end(wmWindow *win, OutlinerDragDropTooltip *data)
{
- MEM_SAFE_FREE(dragged_te->drag_data);
+ MEM_SAFE_FREE(data->te->drag_data);
+
+ if (data->handle) {
+ WM_draw_cb_exit(win, data->handle);
+ }
+
+ MEM_SAFE_FREE(data);
}
static void outliner_item_drag_get_insert_data(
@@ -164,8 +179,35 @@ static void outliner_item_drag_handle(
te_dragged->drag_data->insert_handle = te_insert_handle;
}
-static bool outliner_item_drag_drop_apply(Main *bmain, SpaceOops *soops, TreeElement *dragged_te)
+/**
+ * Returns true if it is a collection and empty.
+ */
+static bool is_empty_collection(TreeElement *te)
{
+ if (!ELEM(TREESTORE(te)->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION)) {
+ return false;
+ }
+
+ SceneCollection *scene_collection;
+ if (TREESTORE(te)->type == TSE_SCENE_COLLECTION) {
+ scene_collection = (SceneCollection *)te->directdata;
+ }
+ else {
+ BLI_assert(TREESTORE(te)->type == TSE_LAYER_COLLECTION);
+ scene_collection = ((LayerCollection *)te->directdata)->scene_collection;
+ }
+
+ return BLI_listbase_is_empty(&scene_collection->objects) &&
+ BLI_listbase_is_empty(&scene_collection->scene_collections);
+}
+
+static bool outliner_item_drag_drop_apply(
+ Main *bmain,
+ SpaceOops *soops,
+ OutlinerDragDropTooltip *data,
+ const wmEvent *event)
+{
+ TreeElement *dragged_te = data->te;
TreeElement *insert_handle = dragged_te->drag_data->insert_handle;
TreeElementInsertType insert_type = dragged_te->drag_data->insert_type;
@@ -178,7 +220,16 @@ static bool outliner_item_drag_drop_apply(Main *bmain, SpaceOops *soops, TreeEle
/* call of assert above should not have changed insert_handle and insert_type at this point */
BLI_assert(dragged_te->drag_data->insert_handle == insert_handle &&
dragged_te->drag_data->insert_type == insert_type);
- dragged_te->reinsert(bmain, soops, dragged_te, insert_handle, insert_type);
+
+ /* If the collection was just created and you moved objects/collections inside it,
+ * it is strange to have it closed and we not see the newly dragged elements. */
+ const bool should_open_collection = (insert_type == TE_INSERT_INTO) && is_empty_collection(insert_handle);
+
+ dragged_te->reinsert(bmain, soops, dragged_te, insert_handle, insert_type, event);
+
+ if (should_open_collection && !is_empty_collection(insert_handle)) {
+ TREESTORE(insert_handle)->flag &= ~TSE_CLOSED;
+ }
return true;
}
@@ -190,7 +241,8 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv
Main *bmain = CTX_data_main(C);
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
- TreeElement *te_dragged = op->customdata;
+ OutlinerDragDropTooltip *data = op->customdata;
+ TreeElement *te_dragged = data->te;
int retval = OPERATOR_RUNNING_MODAL;
bool redraw = false;
bool skip_rebuild = true;
@@ -198,7 +250,7 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv
switch (event->type) {
case EVT_MODAL_MAP:
if (event->val == OUTLINER_ITEM_DRAG_CONFIRM) {
- if (outliner_item_drag_drop_apply(bmain, soops, te_dragged)) {
+ if (outliner_item_drag_drop_apply(bmain, soops, data, event)) {
skip_rebuild = false;
}
retval = OPERATOR_FINISHED;
@@ -210,7 +262,7 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv
BLI_assert(0);
}
WM_event_add_mousemove(C); /* update highlight */
- outliner_item_drag_end(te_dragged);
+ outliner_item_drag_end(CTX_wm_window(C), data);
redraw = true;
break;
case MOUSEMOVE:
@@ -229,6 +281,93 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv
return retval;
}
+/**
+ * Check if the given TreeElement is a collection
+ *
+ * This test is mainly used to see if next/prev TreeElement is a collection.
+ * It will fail when there is no next/prev TreeElement, or when the
+ * element is an Override or something else in the future.
+ */
+static bool tree_element_is_collection_get(const TreeElement *te) {
+ if (te == NULL) {
+ return false;
+ }
+
+ TreeStoreElem *tselem = TREESTORE(te);
+ return ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION);
+}
+
+static const char *outliner_drag_drop_tooltip_get(
+ const TreeElement *te_float)
+{
+ const char *name = NULL;
+
+ const TreeElement *te_insert = te_float->drag_data->insert_handle;
+ if (tree_element_is_collection_get(te_float)) {
+ if (te_insert == NULL) {
+ name = TIP_("Move collection");
+ }
+ else {
+ switch (te_float->drag_data->insert_type) {
+ case TE_INSERT_BEFORE:
+ if (tree_element_is_collection_get(te_insert->prev)) {
+ name = TIP_("Move between collections");
+ }
+ else {
+ name = TIP_("Move before collection");
+ }
+ break;
+ case TE_INSERT_AFTER:
+ if (tree_element_is_collection_get(te_insert->next)) {
+ name = TIP_("Move between collections");
+ }
+ else {
+ name = TIP_("Move after collection");
+ }
+ break;
+ case TE_INSERT_INTO:
+ name = TIP_("Move inside collection");
+ break;
+ }
+ }
+ }
+ else if ((TREESTORE(te_float)->type == 0) && (te_float->idcode == ID_OB)) {
+ name = TIP_("Move to collection (Ctrl to add)");
+ }
+
+ return name;
+}
+
+static void outliner_drag_drop_tooltip_cb(const wmWindow *win, void *vdata)
+{
+ OutlinerDragDropTooltip *data = vdata;
+ const char *tooltip;
+
+ int cursorx, cursory;
+ int x, y;
+
+ tooltip = outliner_drag_drop_tooltip_get(data->te);
+ if (tooltip == NULL) {
+ return;
+ }
+
+ cursorx = win->eventstate->x;
+ cursory = win->eventstate->y;
+
+ x = cursorx + U.widget_unit;
+ y = cursory - U.widget_unit;
+
+ /* Drawing. */
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+
+ const float col_fg[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ const float col_bg[4] = {0.0f, 0.0f, 0.0f, 0.2f};
+
+ glEnable(GL_BLEND);
+ UI_fontstyle_draw_simple_backdrop(fstyle, x, y, tooltip, col_fg, col_bg);
+ glDisable(GL_BLEND);
+}
+
static int outliner_item_drag_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
@@ -239,7 +378,10 @@ static int outliner_item_drag_drop_invoke(bContext *C, wmOperator *op, const wmE
return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
}
- op->customdata = te_dragged;
+ OutlinerDragDropTooltip *data = MEM_mallocN(sizeof(OutlinerDragDropTooltip), __func__);
+ data->te = te_dragged;
+
+ op->customdata = data;
te_dragged->drag_data = MEM_callocN(sizeof(*te_dragged->drag_data), __func__);
/* by default we don't change the item position */
te_dragged->drag_data->insert_handle = te_dragged;
@@ -251,6 +393,8 @@ static int outliner_item_drag_drop_invoke(bContext *C, wmOperator *op, const wmE
WM_event_add_modal_handler(C, op);
+ data->handle = WM_draw_cb_activate(CTX_wm_window(C), outliner_drag_drop_tooltip_cb, data);
+
return OPERATOR_RUNNING_MODAL;
}
@@ -330,9 +474,6 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_collection_link);
WM_operatortype_append(OUTLINER_OT_collection_unlink);
WM_operatortype_append(OUTLINER_OT_collection_new);
- WM_operatortype_append(OUTLINER_OT_collection_override_new);
- WM_operatortype_append(OUTLINER_OT_collection_objects_select);
- WM_operatortype_append(OUTLINER_OT_collection_objects_deselect);
WM_operatortype_append(OUTLINER_OT_collection_nested_new);
WM_operatortype_append(OUTLINER_OT_collection_delete_selected);
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index bf0dea06724..205f70e58dc 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -446,7 +446,8 @@ static TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void
static void outliner_object_reorder(
Main *bmain, SpaceOops *soops,
TreeElement *insert_element,
- TreeElement *insert_handle, TreeElementInsertType action)
+ TreeElement *insert_handle, TreeElementInsertType action,
+ const wmEvent *event)
{
SceneCollection *sc = outliner_scene_collection_from_tree_element(insert_handle);
SceneCollection *sc_ob_parent = NULL;
@@ -459,12 +460,21 @@ static void outliner_object_reorder(
.objects_selected_array = {NULL, NULL},
};
+ const bool is_append = event->ctrl;
+
/* Make sure we include the originally inserted element as well. */
TREESTORE(insert_element)->flag |= TSE_SELECTED;
outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &data);
BLI_LISTBASE_FOREACH (LinkData *, link, &data.objects_selected_array) {
TreeElement *ten_selected = (TreeElement *)link->data;
+ Object *ob = (Object *)TREESTORE(ten_selected)->id;
+
+ if (is_append) {
+ BKE_collection_object_add(id, sc, ob);
+ continue;
+ }
+
/* Find parent scene-collection of object. */
if (ten_selected->parent) {
for (TreeElement *te_ob_parent = ten_selected->parent; te_ob_parent; te_ob_parent = te_ob_parent->parent) {
@@ -477,7 +487,7 @@ static void outliner_object_reorder(
else {
sc_ob_parent = BKE_collection_master(id);
}
- Object *ob = (Object *)TREESTORE(ten_selected)->id;
+
BKE_collection_object_move(id, sc, sc_ob_parent, ob);
}
@@ -1443,7 +1453,8 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
static void outliner_layer_collections_reorder(
Main *bmain,
SpaceOops *UNUSED(soops),
- TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action)
+ TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action,
+ const wmEvent *UNUSED(event))
{
LayerCollection *lc_insert = insert_element->directdata;
LayerCollection *lc_handle = insert_handle->directdata;
@@ -1510,7 +1521,8 @@ static void outliner_add_view_layer(SpaceOops *soops, ListBase *tree, TreeElemen
static void outliner_scene_collections_reorder(
Main *bmain,
SpaceOops *UNUSED(soops),
- TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action)
+ TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action,
+ const wmEvent *UNUSED(event))
{
SceneCollection *sc_insert = insert_element->directdata;
SceneCollection *sc_handle = insert_handle->directdata;
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index 11ef781b229..d148ef3c6fe 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -73,6 +73,7 @@ set(SRC
view3d_select.c
view3d_snap.c
view3d_toolbar.c
+ view3d_utils.c
view3d_view.c
view3d_intern.h
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 3bc2481a608..51dc56bafaf 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -1034,7 +1034,7 @@ static void drawcube_size(float size, unsigned pos)
{ size, size, size}
};
- const GLubyte indices[24] = {0,1,1,3,3,2,2,0,0,4,4,5,5,7,7,6,6,4,1,5,3,7,2,6};
+ const GLubyte indices[24] = {0, 1, 1, 3, 3, 2, 2, 0, 0, 4, 4, 5, 5, 7, 7, 6, 6, 4, 1, 5, 3, 7, 2, 6};
#if 0
glEnableClientState(GL_VERTEX_ARRAY);
@@ -8065,7 +8065,7 @@ static void imm_draw_box(const float vec[8][3], bool solid, unsigned pos)
if (solid) {
/* Adpated from "Optimizing Triangle Strips for Fast Rendering" by F. Evans, S. Skiena and A. Varshney
* (http://www.cs.umd.edu/gvil/papers/av_ts.pdf). */
- static const GLubyte tris_strip_indices[14] = {0,1,3,2,6,1,5,0,4,3,7,6,4,5};
+ static const GLubyte tris_strip_indices[14] = {0, 1, 3, 2, 6, 1, 5, 0, 4, 3, 7, 6, 4, 5};
immBegin(GWN_PRIM_TRI_STRIP, 14);
for (int i = 0; i < 14; ++i) {
immVertex3fv(pos, vec[tris_strip_indices[i]]);
@@ -8073,7 +8073,8 @@ static void imm_draw_box(const float vec[8][3], bool solid, unsigned pos)
immEnd();
}
else {
- static const GLubyte line_indices[24] = {0,1,1,2,2,3,3,0,0,4,4,5,5,6,6,7,7,4,1,5,2,6,3,7};
+ static const GLubyte line_indices[24] =
+ {0, 1, 1, 2, 2, 3, 3, 0, 0, 4, 4, 5, 5, 6, 6, 7, 7, 4, 1, 5, 2, 6, 3, 7};
immBegin(GWN_PRIM_LINES, 24);
for (int i = 0; i < 24; ++i) {
immVertex3fv(pos, vec[line_indices[i]]);
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 64b607aa9f7..fb5b9386dde 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -1128,10 +1128,12 @@ static void view3d_main_region_message_subscribe(
extern StructRNA RNA_ViewLayerEngineSettingsEevee;
WM_msg_subscribe_rna_anon_type(mbus, ViewLayerEngineSettingsEevee, &msg_sub_value_region_tag_redraw);
}
+#ifdef WITH_CLAY_ENGINE
else if (STREQ(view_render->engine_id, RE_engine_id_BLENDER_CLAY)) {
extern StructRNA RNA_ViewLayerEngineSettingsClay;
WM_msg_subscribe_rna_anon_type(mbus, ViewLayerEngineSettingsClay, &msg_sub_value_region_tag_redraw);
}
+#endif
}
/* concept is to retrieve cursor type context-less */
diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c
index 9b07593e576..c39057431c2 100644
--- a/source/blender/editors/space_view3d/view3d_camera_control.c
+++ b/source/blender/editors/space_view3d/view3d_camera_control.c
@@ -138,13 +138,10 @@ Object *ED_view3d_cameracontrol_object_get(View3DCameraControl *vctrl)
* the view for first-person style navigation.
*/
struct View3DCameraControl *ED_view3d_cameracontrol_acquire(
- const bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d,
+ const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, RegionView3D *rv3d,
const bool use_parent_root)
{
View3DCameraControl *vctrl;
- EvaluationContext eval_ctx;
-
- CTX_data_eval_ctx(C, &eval_ctx);
vctrl = MEM_callocN(sizeof(View3DCameraControl), __func__);
@@ -181,7 +178,7 @@ struct View3DCameraControl *ED_view3d_cameracontrol_acquire(
/* store the original camera loc and rot */
vctrl->obtfm = BKE_object_tfm_backup(ob_back);
- BKE_object_where_is_calc(&eval_ctx, scene, v3d->camera);
+ BKE_object_where_is_calc(eval_ctx, scene, v3d->camera);
negate_v3_v3(rv3d->ofs, v3d->camera->obmat[3]);
rv3d->dist = 0.0;
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index cf43d65b44a..f734bb085d0 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -133,11 +133,18 @@ void ED_view3d_update_viewmat(
view3d_winmatrix_set(depsgraph, ar, v3d, rect);
/* setup view matrix */
- if (viewmat)
+ if (viewmat) {
copy_m4_m4(rv3d->viewmat, viewmat);
- else
- view3d_viewmatrix_set(eval_ctx, scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */
-
+ }
+ else {
+ float rect_scale[2];
+ if (rect) {
+ rect_scale[0] = (float)BLI_rcti_size_x(rect) / (float)ar->winx;
+ rect_scale[1] = (float)BLI_rcti_size_y(rect) / (float)ar->winy;
+ }
+ /* note: calls BKE_object_where_is_calc for camera... */
+ view3d_viewmatrix_set(eval_ctx, scene, v3d, rv3d, rect ? rect_scale : NULL);
+ }
/* update utility matrices */
mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
invert_m4_m4(rv3d->persinv, rv3d->persmat);
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index d286e608de4..1e368e2d171 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -26,6 +26,8 @@
/** \file blender/editors/space_view3d/view3d_edit.c
* \ingroup spview3d
+ *
+ * 3D view manipulation/operators.
*/
#include <string.h>
@@ -42,9 +44,7 @@
#include "MEM_guardedalloc.h"
-#include "BLI_bitmap_draw_2d.h"
#include "BLI_blenlib.h"
-#include "BLI_kdopbvh.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -57,13 +57,11 @@
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_report.h"
-#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_action.h"
#include "DEG_depsgraph.h"
-#include "BIF_gl.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -73,14 +71,12 @@
#include "ED_armature.h"
#include "ED_particle.h"
-#include "ED_keyframing.h"
#include "ED_screen.h"
#include "ED_transform.h"
#include "ED_mesh.h"
#include "ED_gpencil.h"
#include "ED_view3d.h"
-#include "DEG_depsgraph_query.h"
#include "UI_resources.h"
@@ -88,440 +84,9 @@
#include "view3d_intern.h" /* own include */
-static bool view3d_ensure_persp(struct View3D *v3d, ARegion *ar);
-
-bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d)
-{
- return (rv3d->persp != RV3D_CAMOB) && (v3d->ob_centre_cursor || v3d->ob_centre);
-}
-
-/* ********************** view3d_edit: view manipulations ********************* */
-
-/**
- * \return true when the view-port is locked to its camera.
- */
-bool ED_view3d_camera_lock_check(const View3D *v3d, const RegionView3D *rv3d)
-{
- return ((v3d->camera) &&
- (!ID_IS_LINKED(v3d->camera)) &&
- (v3d->flag2 & V3D_LOCK_CAMERA) &&
- (rv3d->persp == RV3D_CAMOB));
-}
-
-/**
- * Apply the camera object transformation to the view-port.
- * (needed so we can use regular view-port manipulation operators, that sync back to the camera).
- */
-void ED_view3d_camera_lock_init_ex(View3D *v3d, RegionView3D *rv3d, const bool calc_dist)
-{
- if (ED_view3d_camera_lock_check(v3d, rv3d)) {
- if (calc_dist) {
- /* using a fallback dist is OK here since ED_view3d_from_object() compensates for it */
- rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
- }
- ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
- }
-}
-
-void ED_view3d_camera_lock_init(View3D *v3d, RegionView3D *rv3d)
-{
- ED_view3d_camera_lock_init_ex(v3d, rv3d, true);
-}
-
-/**
- * Apply the view-port transformation back to the camera object.
- *
- * \return true if the camera is moved.
- */
-bool ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d)
-{
- if (ED_view3d_camera_lock_check(v3d, rv3d)) {
- ObjectTfmProtectedChannels obtfm;
- Object *root_parent;
-
- if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (root_parent = v3d->camera->parent)) {
- Object *ob_update;
- float tmat[4][4];
- float imat[4][4];
- float view_mat[4][4];
- float diff_mat[4][4];
- float parent_mat[4][4];
-
- while (root_parent->parent) {
- root_parent = root_parent->parent;
- }
-
- ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
-
- normalize_m4_m4(tmat, v3d->camera->obmat);
-
- invert_m4_m4(imat, tmat);
- mul_m4_m4m4(diff_mat, view_mat, imat);
-
- mul_m4_m4m4(parent_mat, diff_mat, root_parent->obmat);
-
- BKE_object_tfm_protected_backup(root_parent, &obtfm);
- BKE_object_apply_mat4(root_parent, parent_mat, true, false);
- BKE_object_tfm_protected_restore(root_parent, &obtfm, root_parent->protectflag);
-
- ob_update = v3d->camera;
- while (ob_update) {
- DEG_id_tag_update(&ob_update->id, OB_RECALC_OB);
- WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, ob_update);
- ob_update = ob_update->parent;
- }
- }
- else {
- /* always maintain the same scale */
- const short protect_scale_all = (OB_LOCK_SCALEX | OB_LOCK_SCALEY | OB_LOCK_SCALEZ);
- BKE_object_tfm_protected_backup(v3d->camera, &obtfm);
- ED_view3d_to_object(v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist);
- BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag | protect_scale_all);
-
- DEG_id_tag_update(&v3d->camera->id, OB_RECALC_OB);
- WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, v3d->camera);
- }
-
- return true;
- }
- else {
- return false;
- }
-}
-
-bool ED_view3d_camera_autokey(
- Scene *scene, ID *id_key,
- struct bContext *C, const bool do_rotate, const bool do_translate)
-{
- if (autokeyframe_cfra_can_key(scene, id_key)) {
- const float cfra = (float)CFRA;
- ListBase dsources = {NULL, NULL};
-
- /* add data-source override for the camera object */
- ANIM_relative_keyingset_add_source(&dsources, id_key, NULL, NULL);
-
- /* insert keyframes
- * 1) on the first frame
- * 2) on each subsequent frame
- * TODO: need to check in future that frame changed before doing this
- */
- if (do_rotate) {
- struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_ROTATION_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
- }
- if (do_translate) {
- struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
- }
-
- /* free temp data */
- BLI_freelistN(&dsources);
-
- return true;
- }
- else {
- return false;
- }
-}
-
-/**
- * Call after modifying a locked view.
- *
- * \note Not every view edit currently auto-keys (numpad for eg),
- * this is complicated because of smoothview.
- */
-bool ED_view3d_camera_lock_autokey(
- View3D *v3d, RegionView3D *rv3d,
- struct bContext *C, const bool do_rotate, const bool do_translate)
-{
- /* similar to ED_view3d_cameracontrol_update */
- if (ED_view3d_camera_lock_check(v3d, rv3d)) {
- Scene *scene = CTX_data_scene(C);
- ID *id_key;
- Object *root_parent;
- if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (root_parent = v3d->camera->parent)) {
- while (root_parent->parent) {
- root_parent = root_parent->parent;
- }
- id_key = &root_parent->id;
- }
- else {
- id_key = &v3d->camera->id;
- }
-
- return ED_view3d_camera_autokey(scene, id_key, C, do_rotate, do_translate);
- }
- else {
- return false;
- }
-}
-
-/**
- * For viewport operators that exit camera persp.
- *
- * \note This differs from simply setting ``rv3d->persp = persp`` because it
- * sets the ``ofs`` and ``dist`` values of the viewport so it matches the camera,
- * otherwise switching out of camera view may jump to a different part of the scene.
- */
-static void view3d_persp_switch_from_camera(View3D *v3d, RegionView3D *rv3d, const char persp)
-{
- BLI_assert(rv3d->persp == RV3D_CAMOB);
- BLI_assert(persp != RV3D_CAMOB);
-
- if (v3d->camera) {
- rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
- ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
- }
-
- if (!ED_view3d_camera_lock_check(v3d, rv3d)) {
- rv3d->persp = persp;
- }
-}
-
-/* ********************* box view support ***************** */
-
-static void view3d_boxview_clip(ScrArea *sa)
-{
- ARegion *ar;
- BoundBox *bb = MEM_callocN(sizeof(BoundBox), "clipbb");
- float clip[6][4];
- float x1 = 0.0f, y1 = 0.0f, z1 = 0.0f, ofs[3] = {0.0f, 0.0f, 0.0f};
- int val;
-
- /* create bounding box */
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = ar->regiondata;
-
- if (rv3d->viewlock & RV3D_BOXCLIP) {
- if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) {
- if (ar->winx > ar->winy) x1 = rv3d->dist;
- else x1 = ar->winx * rv3d->dist / ar->winy;
-
- if (ar->winx > ar->winy) y1 = ar->winy * rv3d->dist / ar->winx;
- else y1 = rv3d->dist;
- copy_v2_v2(ofs, rv3d->ofs);
- }
- else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) {
- ofs[2] = rv3d->ofs[2];
-
- if (ar->winx > ar->winy) z1 = ar->winy * rv3d->dist / ar->winx;
- else z1 = rv3d->dist;
- }
- }
- }
- }
-
- for (val = 0; val < 8; val++) {
- if (ELEM(val, 0, 3, 4, 7))
- bb->vec[val][0] = -x1 - ofs[0];
- else
- bb->vec[val][0] = x1 - ofs[0];
-
- if (ELEM(val, 0, 1, 4, 5))
- bb->vec[val][1] = -y1 - ofs[1];
- else
- bb->vec[val][1] = y1 - ofs[1];
-
- if (val > 3)
- bb->vec[val][2] = -z1 - ofs[2];
- else
- bb->vec[val][2] = z1 - ofs[2];
- }
-
- /* normals for plane equations */
- normal_tri_v3(clip[0], bb->vec[0], bb->vec[1], bb->vec[4]);
- normal_tri_v3(clip[1], bb->vec[1], bb->vec[2], bb->vec[5]);
- normal_tri_v3(clip[2], bb->vec[2], bb->vec[3], bb->vec[6]);
- normal_tri_v3(clip[3], bb->vec[3], bb->vec[0], bb->vec[7]);
- normal_tri_v3(clip[4], bb->vec[4], bb->vec[5], bb->vec[6]);
- normal_tri_v3(clip[5], bb->vec[0], bb->vec[2], bb->vec[1]);
-
- /* then plane equations */
- for (val = 0; val < 6; val++) {
- clip[val][3] = -dot_v3v3(clip[val], bb->vec[val % 5]);
- }
-
- /* create bounding box */
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = ar->regiondata;
-
- if (rv3d->viewlock & RV3D_BOXCLIP) {
- rv3d->rflag |= RV3D_CLIPPING;
- memcpy(rv3d->clip, clip, sizeof(clip));
- if (rv3d->clipbb) MEM_freeN(rv3d->clipbb);
- rv3d->clipbb = MEM_dupallocN(bb);
- }
- }
- }
- MEM_freeN(bb);
-}
-
-/**
- * Find which axis values are shared between both views and copy to \a rv3d_dst
- * taking axis flipping into account.
- */
-static void view3d_boxview_sync_axis(RegionView3D *rv3d_dst, RegionView3D *rv3d_src)
-{
- /* absolute axis values above this are considered to be set (will be ~1.0f) */
- const float axis_eps = 0.5f;
- float viewinv[4];
-
- /* use the view rotation to identify which axis to sync on */
- float view_axis_all[4][3] = {
- {1.0f, 0.0f, 0.0f},
- {0.0f, 1.0f, 0.0f},
- {1.0f, 0.0f, 0.0f},
- {0.0f, 1.0f, 0.0f}};
-
- float *view_src_x = &view_axis_all[0][0];
- float *view_src_y = &view_axis_all[1][0];
-
- float *view_dst_x = &view_axis_all[2][0];
- float *view_dst_y = &view_axis_all[3][0];
- int i;
-
-
- /* we could use rv3d->viewinv, but better not depend on view matrix being updated */
- if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_src->view, viewinv) == false)) {
- return;
- }
- invert_qt_normalized(viewinv);
- mul_qt_v3(viewinv, view_src_x);
- mul_qt_v3(viewinv, view_src_y);
-
- if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_dst->view, viewinv) == false)) {
- return;
- }
- invert_qt_normalized(viewinv);
- mul_qt_v3(viewinv, view_dst_x);
- mul_qt_v3(viewinv, view_dst_y);
-
- /* check source and dest have a matching axis */
- for (i = 0; i < 3; i++) {
- if (((fabsf(view_src_x[i]) > axis_eps) || (fabsf(view_src_y[i]) > axis_eps)) &&
- ((fabsf(view_dst_x[i]) > axis_eps) || (fabsf(view_dst_y[i]) > axis_eps)))
- {
- rv3d_dst->ofs[i] = rv3d_src->ofs[i];
- }
- }
-}
-
-/* sync center/zoom view of region to others, for view transforms */
-static void view3d_boxview_sync(ScrArea *sa, ARegion *ar)
-{
- ARegion *artest;
- RegionView3D *rv3d = ar->regiondata;
- short clip = 0;
-
- for (artest = sa->regionbase.first; artest; artest = artest->next) {
- if (artest != ar && artest->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3dtest = artest->regiondata;
-
- if (rv3dtest->viewlock & RV3D_LOCKED) {
- rv3dtest->dist = rv3d->dist;
- view3d_boxview_sync_axis(rv3dtest, rv3d);
- clip |= rv3dtest->viewlock & RV3D_BOXCLIP;
-
- ED_region_tag_redraw(artest);
- }
- }
- }
-
- if (clip) {
- view3d_boxview_clip(sa);
- }
-}
-
-/* for home, center etc */
-void view3d_boxview_copy(ScrArea *sa, ARegion *ar)
-{
- ARegion *artest;
- RegionView3D *rv3d = ar->regiondata;
- bool clip = false;
-
- for (artest = sa->regionbase.first; artest; artest = artest->next) {
- if (artest != ar && artest->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3dtest = artest->regiondata;
-
- if (rv3dtest->viewlock) {
- rv3dtest->dist = rv3d->dist;
- copy_v3_v3(rv3dtest->ofs, rv3d->ofs);
- ED_region_tag_redraw(artest);
-
- clip |= ((rv3dtest->viewlock & RV3D_BOXCLIP) != 0);
- }
- }
- }
-
- if (clip) {
- view3d_boxview_clip(sa);
- }
-}
-
-/* 'clip' is used to know if our clip setting has changed */
-void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip)
-{
- ARegion *ar_sync = NULL;
- RegionView3D *rv3d = ar->regiondata;
- short viewlock;
- /* this function copies flags from the first of the 3 other quadview
- * regions to the 2 other, so it assumes this is the region whose
- * properties are always being edited, weak */
- viewlock = rv3d->viewlock;
-
- if ((viewlock & RV3D_LOCKED) == 0) {
- do_clip = (viewlock & RV3D_BOXCLIP) != 0;
- viewlock = 0;
- }
- else if ((viewlock & RV3D_BOXVIEW) == 0 && (viewlock & RV3D_BOXCLIP) != 0) {
- do_clip = true;
- viewlock &= ~RV3D_BOXCLIP;
- }
-
- for (; ar; ar = ar->prev) {
- if (ar->alignment == RGN_ALIGN_QSPLIT) {
- rv3d = ar->regiondata;
- rv3d->viewlock = viewlock;
-
- if (do_clip && (viewlock & RV3D_BOXCLIP) == 0) {
- rv3d->rflag &= ~RV3D_BOXCLIP;
- }
-
- /* use ar_sync so we sync with one of the aligned views below
- * else the view jumps on changing view settings like 'clip'
- * since it copies from the perspective view */
- ar_sync = ar;
- }
- }
-
- if (rv3d->viewlock & RV3D_BOXVIEW) {
- view3d_boxview_sync(sa, ar_sync ? ar_sync : sa->regionbase.last);
- }
-
- /* ensure locked regions have an axis, locked user views don't make much sense */
- if (viewlock & RV3D_LOCKED) {
- int index_qsplit = 0;
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->alignment == RGN_ALIGN_QSPLIT) {
- rv3d = ar->regiondata;
- if (rv3d->viewlock) {
- if (!RV3D_VIEW_IS_AXIS(rv3d->view)) {
- rv3d->view = ED_view3d_lock_view_from_index(index_qsplit);
- rv3d->persp = RV3D_ORTHO;
- ED_view3d_lock(rv3d);
- }
- }
- index_qsplit++;
- }
- }
- }
-
- ED_area_tag_redraw(sa);
-}
-
-/* ************************** init for view ops **********************************/
+/* -------------------------------------------------------------------- */
+/** \name Generic View Operator Custom-Data
+ * \{ */
typedef struct ViewOpsData {
/* context pointers (assigned by viewops_data_alloc) */
@@ -581,13 +146,6 @@ static void calctrackballvec(const rcti *rect, int mx, int my, float vec[3])
vec[2] = -z; /* yah yah! */
}
-
-/* -------------------------------------------------------------------- */
-/* ViewOpsData */
-
-/** \name Generic View Operator Custom-Data.
- * \{ */
-
/**
* Allocate and fill in context pointers for #ViewOpsData
*/
@@ -732,7 +290,7 @@ static enum eViewOpsOrbit viewops_orbit_mode(void)
/**
* Calculate the values for #ViewOpsData
*
- * \param use_ensure_persp: When enabled run #view3d_ensure_persp this may switch out of
+ * \param use_ensure_persp: When enabled run #ED_view3d_persp_ensure this may switch out of
* camera view when orbiting or switch from ortho to perspective when auto-persp is enabled.
* Some operations don't require this (view zoom/pan or ndof where subtle rotation is common
* so we don't want it to trigger auto-perspective).
@@ -765,7 +323,7 @@ static void viewops_data_create_ex(
}
if (use_ensure_persp) {
- if (view3d_ensure_persp(vod->v3d, vod->ar)) {
+ if (ED_view3d_persp_ensure(vod->v3d, vod->ar)) {
/* If we're switching from camera view to the perspective one,
* need to tag viewport update, so camera vuew and borders
* are properly updated.
@@ -898,10 +456,12 @@ static void viewops_data_free(bContext *C, wmOperator *op)
#endif
ED_region_tag_redraw(ar);
}
-/** \} */
+/** \} */
-/* ************************** viewrotate **********************************/
+/* -------------------------------------------------------------------- */
+/** \name View Rotate Operator
+ * \{ */
enum {
VIEW_PASS = 0,
@@ -910,12 +470,14 @@ enum {
};
/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
-#define VIEW_MODAL_CONFIRM 1 /* used for all view operations */
-#define VIEWROT_MODAL_AXIS_SNAP_ENABLE 2
-#define VIEWROT_MODAL_AXIS_SNAP_DISABLE 3
-#define VIEWROT_MODAL_SWITCH_ZOOM 4
-#define VIEWROT_MODAL_SWITCH_MOVE 5
-#define VIEWROT_MODAL_SWITCH_ROTATE 6
+enum {
+ VIEW_MODAL_CONFIRM = 1, /* used for all view operations */
+ VIEWROT_MODAL_AXIS_SNAP_ENABLE = 2,
+ VIEWROT_MODAL_AXIS_SNAP_DISABLE = 3,
+ VIEWROT_MODAL_SWITCH_ZOOM = 4,
+ VIEWROT_MODAL_SWITCH_MOVE = 5,
+ VIEWROT_MODAL_SWITCH_ROTATE = 6,
+};
/* called in transform_ops.c, on each regeneration of keymaps */
void viewrotate_modal_keymap(wmKeyConfig *keyconf)
@@ -1231,37 +793,6 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
return ret;
}
-/**
- * Action to take when rotating the view,
- * handle auto-persp and logic for switching out of views.
- *
- * shared with NDOF.
- */
-static bool view3d_ensure_persp(struct View3D *v3d, ARegion *ar)
-{
- RegionView3D *rv3d = ar->regiondata;
- const bool autopersp = (U.uiflag & USER_AUTOPERSP) != 0;
-
- BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0);
-
- if (ED_view3d_camera_lock_check(v3d, rv3d))
- return false;
-
- if (rv3d->persp != RV3D_PERSP) {
- if (rv3d->persp == RV3D_CAMOB) {
- /* If autopersp and previous view was an axis one, switch back to PERSP mode, else reuse previous mode. */
- char persp = (autopersp && RV3D_VIEW_IS_AXIS(rv3d->lview)) ? RV3D_PERSP : rv3d->lpersp;
- view3d_persp_switch_from_camera(v3d, rv3d, persp);
- }
- else if (autopersp && RV3D_VIEW_IS_AXIS(rv3d->view)) {
- rv3d->persp = RV3D_PERSP;
- }
- return true;
- }
-
- return false;
-}
-
static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod;
@@ -1365,11 +896,13 @@ void VIEW3D_OT_rotate(wmOperatorType *ot)
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
}
-#ifdef WITH_INPUT_NDOF
+/** \} */
+/* -------------------------------------------------------------------- */
/** \name NDOF Utility Functions
* \{ */
+#ifdef WITH_INPUT_NDOF
#define NDOF_HAS_TRANSLATE ((!ED_view3d_offset_lock_check(v3d, rv3d)) && !is_zero_v3(ndof->tvec))
#define NDOF_HAS_ROTATE (((rv3d->viewlock & RV3D_LOCKED) == 0) && !is_zero_v3(ndof->rvec))
@@ -1419,8 +952,9 @@ static float view3d_ndof_pan_speed_calc(RegionView3D *rv3d)
*
* \param has_zoom zoom, otherwise dolly, often `!rv3d->is_persp` since it doesnt make sense to dolly in ortho.
*/
-static void view3d_ndof_pan_zoom(const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar,
- const bool has_translate, const bool has_zoom)
+static void view3d_ndof_pan_zoom(
+ const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar,
+ const bool has_translate, const bool has_zoom)
{
RegionView3D *rv3d = ar->regiondata;
float view_inv[4];
@@ -1481,9 +1015,10 @@ static void view3d_ndof_pan_zoom(const struct wmNDOFMotionData *ndof, ScrArea *s
}
-static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar,
- /* optional, can be NULL*/
- ViewOpsData *vod)
+static void view3d_ndof_orbit(
+ const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar,
+ /* optional, can be NULL*/
+ ViewOpsData *vod)
{
View3D *v3d = sa->spacedata.first;
RegionView3D *rv3d = ar->regiondata;
@@ -1492,7 +1027,7 @@ static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof, ScrArea *sa,
BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0);
- view3d_ensure_persp(v3d, ar);
+ ED_view3d_persp_ensure(v3d, ar);
rv3d->view = RV3D_VIEW_USER;
@@ -1668,11 +1203,14 @@ void view3d_ndof_fly(
/** \} */
+/* -------------------------------------------------------------------- */
+/** \name NDOF Operators
+ *
+ * - "orbit" navigation (trackball/turntable)
+ * - zooming
+ * - panning in rotationally-locked views
+ * \{ */
-/* -- "orbit" navigation (trackball/turntable)
- * -- zooming
- * -- panning in rotationally-locked views
- */
static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
@@ -1936,8 +1474,11 @@ void VIEW3D_OT_ndof_all(struct wmOperatorType *ot)
#endif /* WITH_INPUT_NDOF */
-/* ************************ viewmove ******************************** */
+/** \} */
+/* -------------------------------------------------------------------- */
+/** \name View Move (Pan) Operator
+ * \{ */
/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
@@ -1999,8 +1540,9 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y)
add_v3_v3(vod->rv3d->ofs, dvec);
- if (vod->rv3d->viewlock & RV3D_BOXVIEW)
+ if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
view3d_boxview_sync(vod->sa, vod->ar);
+ }
}
vod->oldx = x;
@@ -2117,7 +1659,11 @@ void VIEW3D_OT_move(wmOperatorType *ot)
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
}
-/* ************************ viewzoom ******************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Zoom Operator
+ * \{ */
/* viewdolly_modal_keymap has an exact copy of this, apply fixes to both */
/* called in transform_ops.c, on each regeneration of keymaps */
@@ -2359,8 +1905,9 @@ static void viewzoom_apply_3d(
/* these limits were in old code too */
CLAMP(vod->rv3d->dist, dist_range[0], dist_range[1]);
- if (vod->rv3d->viewlock & RV3D_BOXVIEW)
+ if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
view3d_boxview_sync(vod->sa, vod->ar);
+ }
ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
@@ -2497,8 +2044,9 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
}
}
- if (rv3d->viewlock & RV3D_BOXVIEW)
+ if (rv3d->viewlock & RV3D_BOXVIEW) {
view3d_boxview_sync(sa, ar);
+ }
ED_view3d_depth_tag_update(rv3d);
@@ -2512,41 +2060,6 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-/* this is an exact copy of viewzoom_modal_keymap */
-/* called in transform_ops.c, on each regeneration of keymaps */
-void viewdolly_modal_keymap(wmKeyConfig *keyconf)
-{
- static const EnumPropertyItem modal_items[] = {
- {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
-
- {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
- {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
-
- {0, NULL, 0, NULL, NULL}
- };
-
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Dolly Modal");
-
- /* this function is called for each spacetype, only needs to add map once */
- if (keymap && keymap->modal_items) return;
-
- keymap = WM_modalkeymap_add(keyconf, "View3D Dolly Modal", modal_items);
-
- /* items for modal map */
- WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM);
- WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM);
-
- /* disabled mode switching for now, can re-implement better, later on */
-#if 0
- WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
- WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
- WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
-#endif
-
- /* assign map to operators */
- WM_modalkeymap_assign(keymap, "VIEW3D_OT_dolly");
-}
-
/* viewdolly_invoke() copied this function, changes here may apply there */
static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
@@ -2634,8 +2147,50 @@ void VIEW3D_OT_zoom(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Dolly Operator
+ *
+ * Like zoom but translates the view offset along the view direction
+ * which avoids #RegionView3D.dist approaching zero.
+ * \{ */
+
+/* this is an exact copy of viewzoom_modal_keymap */
+/* called in transform_ops.c, on each regeneration of keymaps */
+void viewdolly_modal_keymap(wmKeyConfig *keyconf)
+{
+ static const EnumPropertyItem modal_items[] = {
+ {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+
+ {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
+ {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
+
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Dolly Modal");
+
+ /* this function is called for each spacetype, only needs to add map once */
+ if (keymap && keymap->modal_items) return;
+
+ keymap = WM_modalkeymap_add(keyconf, "View3D Dolly Modal", modal_items);
+
+ /* items for modal map */
+ WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM);
+
+ /* disabled mode switching for now, can re-implement better, later on */
+#if 0
+ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
+ WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
+ WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
+#endif
+
+ /* assign map to operators */
+ WM_modalkeymap_assign(keymap, "VIEW3D_OT_dolly");
+}
-/* ************************ viewdolly ******************************** */
static bool viewdolly_offset_lock_check(bContext *C, wmOperator *op)
{
View3D *v3d = CTX_wm_view3d(C);
@@ -2679,8 +2234,9 @@ static void viewdolly_apply(ViewOpsData *vod, int x, int y, const short zoom_inv
if (zfac != 1.0f)
view_dolly_mouseloc(vod->ar, vod->ofs, vod->mousevec, zfac);
- if (vod->rv3d->viewlock & RV3D_BOXVIEW)
+ if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
view3d_boxview_sync(vod->sa, vod->ar);
+ }
ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
@@ -2780,8 +2336,9 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
view_dolly_mouseloc(ar, rv3d->ofs, mousevec, 1.8f);
}
- if (rv3d->viewlock & RV3D_BOXVIEW)
+ if (rv3d->viewlock & RV3D_BOXVIEW) {
view3d_boxview_sync(sa, ar);
+ }
ED_view3d_depth_tag_update(rv3d);
@@ -2819,7 +2376,7 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (vod->rv3d->persp != RV3D_PERSP) {
if (vod->rv3d->persp == RV3D_CAMOB) {
/* ignore rv3d->lpersp because dolly only makes sense in perspective mode */
- view3d_persp_switch_from_camera(vod->v3d, vod->rv3d, RV3D_PERSP);
+ ED_view3d_persp_switch_from_camera(vod->v3d, vod->rv3d, RV3D_PERSP);
}
else {
vod->rv3d->persp = RV3D_PERSP;
@@ -2901,6 +2458,13 @@ void VIEW3D_OT_dolly(wmOperatorType *ot)
RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Zoom Position Y", "", 0, INT_MAX);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View All Operator
+ *
+ * Move & Zoom the view to fit all of it's contents.
+ * \{ */
static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar,
const float min[3], const float max[3],
bool ok_dist, const int smooth_viewtx)
@@ -2970,9 +2534,10 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar,
}
/* same as view3d_from_minmax but for all regions (except cameras) */
-static void view3d_from_minmax_multi(bContext *C, View3D *v3d,
- const float min[3], const float max[3],
- const bool ok_dist, const int smooth_viewtx)
+static void view3d_from_minmax_multi(
+ bContext *C, View3D *v3d,
+ const float min[3], const float max[3],
+ const bool ok_dist, const int smooth_viewtx)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar;
@@ -3072,6 +2637,14 @@ void VIEW3D_OT_view_all(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "center", 0, "Center", "");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Selected Operator
+ *
+ * Move & Zoom the view to fit selected contents.
+ * \{ */
+
/* like a localview without local!, was centerview() in 2.4x */
static int viewselected_exec(bContext *C, wmOperator *op)
{
@@ -3202,12 +2775,18 @@ void VIEW3D_OT_view_selected(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Lock Clear Operator
+ * \{ */
+
static int view_lock_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
View3D *v3d = CTX_wm_view3d(C);
if (v3d) {
- ED_view3D_lock_clear(v3d);
+ ED_view3d_lock_clear(v3d);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
@@ -3234,6 +2813,12 @@ void VIEW3D_OT_view_lock_clear(wmOperatorType *ot)
ot->flag = 0;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Lock to Active Operator
+ * \{ */
+
static int view_lock_to_active_exec(bContext *C, wmOperator *UNUSED(op))
{
View3D *v3d = CTX_wm_view3d(C);
@@ -3241,7 +2826,7 @@ static int view_lock_to_active_exec(bContext *C, wmOperator *UNUSED(op))
if (v3d) {
- ED_view3D_lock_clear(v3d);
+ ED_view3d_lock_clear(v3d);
v3d->ob_centre = obact; /* can be NULL */
@@ -3285,6 +2870,12 @@ void VIEW3D_OT_view_lock_to_active(wmOperatorType *ot)
ot->flag = 0;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Center Cursor Operator
+ * \{ */
+
static int viewcenter_cursor_exec(bContext *C, wmOperator *op)
{
View3D *v3d = CTX_wm_view3d(C);
@@ -3325,6 +2916,12 @@ void VIEW3D_OT_view_center_cursor(wmOperatorType *ot)
ot->flag = 0;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Center Pick Operator
+ * \{ */
+
static int viewcenter_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
View3D *v3d = CTX_wm_view3d(C);
@@ -3375,6 +2972,12 @@ void VIEW3D_OT_view_center_pick(wmOperatorType *ot)
ot->flag = 0;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Camera Center Operator
+ * \{ */
+
static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op)) /* was view3d_home() in 2.4x */
{
const Depsgraph *depsgraph = CTX_data_depsgraph(C);
@@ -3421,6 +3024,12 @@ void VIEW3D_OT_view_center_camera(wmOperatorType *ot)
ot->flag = 0;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Lock Center Operator
+ * \{ */
+
static int view3d_center_lock_exec(bContext *C, wmOperator *UNUSED(op)) /* was view3d_home() in 2.4x */
{
RegionView3D *rv3d = CTX_wm_region_view3d(C);
@@ -3447,7 +3056,11 @@ void VIEW3D_OT_view_center_lock(wmOperatorType *ot)
ot->flag = 0;
}
-/* ********************* Set render border operator ****************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set Render Border Operator
+ * \{ */
static int render_border_exec(bContext *C, wmOperator *op)
{
@@ -3549,7 +3162,11 @@ void VIEW3D_OT_render_border(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN);
}
-/* ********************* Clear render border operator ****************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Clear Render Border Operator
+ * \{ */
static int clear_render_border_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -3596,7 +3213,11 @@ void VIEW3D_OT_clear_render_border(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ********************* Border Zoom operator ****************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Border Zoom Operator
+ * \{ */
static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
{
@@ -3724,8 +3345,9 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
C, v3d, ar, smooth_viewtx,
&(const V3D_SmoothParams) {.ofs = new_ofs, .dist = &new_dist});
- if (rv3d->viewlock & RV3D_BOXVIEW)
+ if (rv3d->viewlock & RV3D_BOXVIEW) {
view3d_boxview_sync(CTX_wm_area(C), ar);
+ }
return OPERATOR_FINISHED;
}
@@ -3764,7 +3386,14 @@ void VIEW3D_OT_zoom_border(wmOperatorType *ot)
WM_operator_properties_gesture_border_zoom(ot);
}
-/* sets the view to 1:1 camera/render-pixel */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set Camera Zoom 1:1 Operator
+ *
+ * Sets the view to 1:1 camera/render-pixel.
+ * \{ */
+
static void view3d_set_1_to_1_viewborder(Scene *scene, const Depsgraph *depsgraph, ARegion *ar, View3D *v3d)
{
RegionView3D *rv3d = ar->regiondata;
@@ -3810,7 +3439,11 @@ void VIEW3D_OT_zoom_camera_1_to_1(wmOperatorType *ot)
ot->flag = 0;
}
-/* ********************* Changing view operator ****************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Axis/Type Operator
+ * \{ */
static const EnumPropertyItem prop_view_items[] = {
{RV3D_VIEW_LEFT, "LEFT", ICON_TRIA_LEFT, "Left", "View From the Left"},
@@ -3826,10 +3459,11 @@ static const EnumPropertyItem prop_view_items[] = {
/* would like to make this a generic function - outside of transform */
-static void axis_set_view(bContext *C, View3D *v3d, ARegion *ar,
- const float quat_[4],
- short view, int perspo, bool align_active,
- const int smooth_viewtx)
+static void axis_set_view(
+ bContext *C, View3D *v3d, ARegion *ar,
+ const float quat_[4],
+ short view, int perspo, bool align_active,
+ const int smooth_viewtx)
{
RegionView3D *rv3d = ar->regiondata; /* no NULL check is needed, poll checks */
float quat[4];
@@ -4049,6 +3683,12 @@ void VIEW3D_OT_viewnumpad(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Orbit Operator
+ * \{ */
+
static const EnumPropertyItem prop_view_orbit_items[] = {
{V3D_VIEW_STEPLEFT, "ORBITLEFT", 0, "Orbit Left", "Orbit the view around to the Left"},
{V3D_VIEW_STEPRIGHT, "ORBITRIGHT", 0, "Orbit Right", "Orbit the view around to the Right"},
@@ -4092,7 +3732,7 @@ static int vieworbit_exec(bContext *C, wmOperator *op)
float quat_new[4];
if (view_opposite == RV3D_VIEW_USER) {
- view3d_ensure_persp(v3d, ar);
+ ED_view3d_persp_ensure(v3d, ar);
}
if (ELEM(orbitdir, V3D_VIEW_STEPLEFT, V3D_VIEW_STEPRIGHT)) {
@@ -4169,11 +3809,13 @@ void VIEW3D_OT_view_orbit(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
ot->prop = RNA_def_enum(ot->srna, "type", prop_view_orbit_items, 0, "Orbit", "Direction of View Orbit");
-
}
+/** \} */
-/* ************************ viewroll ******************************** */
+/* -------------------------------------------------------------------- */
+/** \name View Roll Operator
+ * \{ */
static void view_roll_angle(ARegion *ar, float quat[4], const float orig_quat[4], const float dvec[3], float angle)
{
@@ -4211,8 +3853,9 @@ static void viewroll_apply(ViewOpsData *vod, int x, int UNUSED(y))
view3d_orbit_apply_dyn_ofs(vod->rv3d->ofs, vod->ofs, vod->oldquat, vod->rv3d->viewquat, vod->dyn_ofs);
}
- if (vod->rv3d->viewlock & RV3D_BOXVIEW)
+ if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
view3d_boxview_sync(vod->sa, vod->ar);
+ }
ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
@@ -4415,6 +4058,14 @@ static const EnumPropertyItem prop_view_pan_items[] = {
{0, NULL, 0, NULL, NULL}
};
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Pan Operator
+ *
+ * Move (pan) in incremental steps.
+ * \{ */
+
static int viewpan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int x = 0, y = 0;
@@ -4455,6 +4106,12 @@ void VIEW3D_OT_view_pan(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_view_pan_items, 0, "Pan", "Direction of View Pan");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Toggle Perspective/Orthographic Operator
+ * \{ */
+
static int viewpersportho_exec(bContext *C, wmOperator *UNUSED(op))
{
View3D *v3d_dummy;
@@ -4491,6 +4148,14 @@ void VIEW3D_OT_view_persportho(wmOperatorType *ot)
ot->flag = 0;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Navigate Operator
+ *
+ * Wraps walk/fly modes.
+ * \{ */
+
static int view3d_navigate_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
eViewNavigation_Method mode = U.navigation_mode;
@@ -4520,8 +4185,11 @@ void VIEW3D_OT_navigate(wmOperatorType *ot)
ot->poll = ED_operator_view3d_active;
}
+/** \} */
-/* ******************** add background image operator **************** */
+/* -------------------------------------------------------------------- */
+/** \name Background Image Add Operator
+ * \{ */
static CameraBGImage *background_image_add(bContext *C)
{
@@ -4580,8 +4248,12 @@ void VIEW3D_OT_background_image_add(wmOperatorType *ot)
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Background Image Remove Operator
+ * \{ */
-/* ***** remove image operator ******* */
static int background_image_remove_exec(bContext *C, wmOperator *op)
{
Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
@@ -4626,7 +4298,13 @@ void VIEW3D_OT_background_image_remove(wmOperatorType *ot)
RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Background image index to remove", 0, INT_MAX);
}
-/* ********************* set clipping operator ****************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Clipping Planes Operator
+ *
+ * Draw border or toggle off.
+ * \{ */
static void calc_local_clipping(float clip_local[6][4], BoundBox *clipbb, float mat[4][4])
{
@@ -4707,7 +4385,11 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot)
WM_operator_properties_border(ot);
}
-/* ***************** 3d cursor cursor op ******************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set Cursor Operator
+ * \{ */
/* cursor position in vec, result in vec, mval in region coords */
/* note: cannot use event->mval here (called by object_add() */
@@ -4819,7 +4501,11 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot)
}
-/* ***************** manipulator op ******************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Enable Transform Manipulator Operator
+ * \{ */
static int enable_manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
@@ -4861,7 +4547,11 @@ void VIEW3D_OT_enable_manipulator(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/* ************************* Toggle rendered shading *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Toggle Render Shading Operator
+ * \{ */
static int toggle_render_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -4890,315 +4580,4 @@ void VIEW3D_OT_toggle_render(wmOperatorType *ot)
ot->poll = ED_operator_view3d_active;
}
-/* ************************* below the line! *********************** */
-
-
-static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int margin)
-{
- ViewDepths depth_temp = {0};
- rcti rect;
- float depth_close;
-
- if (margin == 0) {
- /* Get Z Depths, needed for perspective, nice for ortho */
- rect.xmin = mval[0];
- rect.ymin = mval[1];
- rect.xmax = mval[0] + 1;
- rect.ymax = mval[1] + 1;
- }
- else {
- BLI_rcti_init_pt_radius(&rect, mval, margin);
- }
-
- view3d_update_depths_rect(ar, &depth_temp, &rect);
- depth_close = view3d_depth_near(&depth_temp);
- MEM_SAFE_FREE(depth_temp.depths);
- return depth_close;
-}
-
-/**
- * Get the world-space 3d location from a screen-space 2d point.
- *
- * \param mval: Input screen-space pixel location.
- * \param mouse_worldloc: Output world-space location.
- * \param fallback_depth_pt: Use this points depth when no depth can be found.
- */
-bool ED_view3d_autodist(
- const EvaluationContext *eval_ctx, struct Depsgraph *graph, ARegion *ar, View3D *v3d,
- const int mval[2], float mouse_worldloc[3],
- const bool alphaoverride, const float fallback_depth_pt[3])
-{
- float depth_close;
- int margin_arr[] = {0, 2, 4};
- int i;
- bool depth_ok = false;
-
- /* Get Z Depths, needed for perspective, nice for ortho */
- ED_view3d_draw_depth(eval_ctx, graph, ar, v3d, alphaoverride);
-
- /* Attempt with low margin's first */
- i = 0;
- do {
- depth_close = view_autodist_depth_margin(ar, mval, margin_arr[i++] * U.pixelsize);
- depth_ok = (depth_close != FLT_MAX);
- } while ((depth_ok == false) && (i < ARRAY_SIZE(margin_arr)));
-
- if (depth_ok) {
- float centx = (float)mval[0] + 0.5f;
- float centy = (float)mval[1] + 0.5f;
-
- if (ED_view3d_unproject(ar, centx, centy, depth_close, mouse_worldloc)) {
- return true;
- }
- }
-
- if (fallback_depth_pt) {
- ED_view3d_win_to_3d_int(v3d, ar, fallback_depth_pt, mval, mouse_worldloc);
- return true;
- }
- else {
- return false;
- }
-}
-
-void ED_view3d_autodist_init(
- const EvaluationContext *eval_ctx, struct Depsgraph *graph,
- ARegion *ar, View3D *v3d, int mode)
-{
- /* Get Z Depths, needed for perspective, nice for ortho */
- switch (mode) {
- case 0:
- ED_view3d_draw_depth(eval_ctx, graph, ar, v3d, true);
- break;
- case 1:
- {
- Scene *scene = DEG_get_evaluated_scene(graph);
- ED_view3d_draw_depth_gpencil(eval_ctx, scene, ar, v3d);
- break;
- }
- }
-}
-
-/* no 4x4 sampling, run #ED_view3d_autodist_init first */
-bool ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_worldloc[3],
- int margin, float *force_depth)
-{
- float depth;
-
- /* Get Z Depths, needed for perspective, nice for ortho */
- if (force_depth)
- depth = *force_depth;
- else
- depth = view_autodist_depth_margin(ar, mval, margin);
-
- if (depth == FLT_MAX)
- return false;
-
- float centx = (float)mval[0] + 0.5f;
- float centy = (float)mval[1] + 0.5f;
- return ED_view3d_unproject(ar, centx, centy, depth, mouse_worldloc);
-}
-
-bool ED_view3d_autodist_depth(ARegion *ar, const int mval[2], int margin, float *depth)
-{
- *depth = view_autodist_depth_margin(ar, mval, margin);
-
- return (*depth != FLT_MAX);
-}
-
-static bool depth_segment_cb(int x, int y, void *userData)
-{
- struct { ARegion *ar; int margin; float depth; } *data = userData;
- int mval[2];
- float depth;
-
- mval[0] = x;
- mval[1] = y;
-
- depth = view_autodist_depth_margin(data->ar, mval, data->margin);
-
- if (depth != FLT_MAX) {
- data->depth = depth;
- return 0;
- }
- else {
- return 1;
- }
-}
-
-bool ED_view3d_autodist_depth_seg(ARegion *ar, const int mval_sta[2], const int mval_end[2],
- int margin, float *depth)
-{
- struct { ARegion *ar; int margin; float depth; } data = {NULL};
- int p1[2];
- int p2[2];
-
- data.ar = ar;
- data.margin = margin;
- data.depth = FLT_MAX;
-
- copy_v2_v2_int(p1, mval_sta);
- copy_v2_v2_int(p2, mval_end);
-
- BLI_bitmap_draw_2d_line_v2v2i(p1, p2, depth_segment_cb, &data);
-
- *depth = data.depth;
-
- return (*depth != FLT_MAX);
-}
-
-/* problem - ofs[3] can be on same location as camera itself.
- * Blender needs proper dist value for zoom.
- * use fallback_dist to override small values
- */
-float ED_view3d_offset_distance(float mat[4][4], const float ofs[3], const float fallback_dist)
-{
- float pos[4] = {0.0f, 0.0f, 0.0f, 1.0f};
- float dir[4] = {0.0f, 0.0f, 1.0f, 0.0f};
- float dist;
-
- mul_m4_v4(mat, pos);
- add_v3_v3(pos, ofs);
- mul_m4_v4(mat, dir);
- normalize_v3(dir);
-
- dist = dot_v3v3(pos, dir);
-
- if ((dist < FLT_EPSILON) && (fallback_dist != 0.0f)) {
- dist = fallback_dist;
- }
-
- return dist;
-}
-
-/**
- * Set the dist without moving the view (compensate with #RegionView3D.ofs)
- *
- * \note take care that viewinv is up to date, #ED_view3d_update_viewmat first.
- */
-void ED_view3d_distance_set(RegionView3D *rv3d, const float dist)
-{
- float viewinv[4];
- float tvec[3];
-
- BLI_assert(dist >= 0.0f);
-
- copy_v3_fl3(tvec, 0.0f, 0.0f, rv3d->dist - dist);
- /* rv3d->viewinv isn't always valid */
-#if 0
- mul_mat3_m4_v3(rv3d->viewinv, tvec);
-#else
- invert_qt_qt_normalized(viewinv, rv3d->viewquat);
- mul_qt_v3(viewinv, tvec);
-#endif
- sub_v3_v3(rv3d->ofs, tvec);
-
- rv3d->dist = dist;
-}
-
-/**
- * Set the view transformation from a 4x4 matrix.
- *
- * \param mat The view 4x4 transformation matrix to assign.
- * \param ofs The view offset, normally from RegionView3D.ofs.
- * \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
- * \param dist The view distance from ofs, normally from RegionView3D.dist.
- */
-void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist)
-{
- float nmat[3][3];
-
- /* dist depends on offset */
- BLI_assert(dist == NULL || ofs != NULL);
-
- copy_m3_m4(nmat, mat);
- normalize_m3(nmat);
-
- /* Offset */
- if (ofs)
- negate_v3_v3(ofs, mat[3]);
-
- /* Quat */
- if (quat) {
- mat3_normalized_to_quat(quat, nmat);
- invert_qt_normalized(quat);
- }
-
- if (ofs && dist) {
- madd_v3_v3fl(ofs, nmat[2], *dist);
- }
-}
-
-/**
- * Calculate the view transformation matrix from RegionView3D input.
- * The resulting matrix is equivalent to RegionView3D.viewinv
- * \param mat The view 4x4 transformation matrix to calculate.
- * \param ofs The view offset, normally from RegionView3D.ofs.
- * \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
- * \param dist The view distance from ofs, normally from RegionView3D.dist.
- */
-void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], const float dist)
-{
- float iviewquat[4] = {-quat[0], quat[1], quat[2], quat[3]};
- float dvec[3] = {0.0f, 0.0f, dist};
-
- quat_to_mat4(mat, iviewquat);
- mul_mat3_m4_v3(mat, dvec);
- sub_v3_v3v3(mat[3], dvec, ofs);
-}
-
-/**
- * Set the RegionView3D members from an objects transformation and optionally lens.
- * \param ob The object to set the view to.
- * \param ofs The view offset to be set, normally from RegionView3D.ofs.
- * \param quat The view rotation to be set, quaternion normally from RegionView3D.viewquat.
- * \param dist The view distance from ofs to be set, normally from RegionView3D.dist.
- * \param lens The view lens angle set for cameras and lamps, normally from View3D.lens.
- */
-void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist, float *lens)
-{
- ED_view3d_from_m4(ob->obmat, ofs, quat, dist);
-
- if (lens) {
- CameraParams params;
-
- BKE_camera_params_init(&params);
- BKE_camera_params_from_object(&params, ob);
- *lens = params.lens;
- }
-}
-
-/**
- * Set the object transformation from RegionView3D members.
- * \param ob The object which has the transformation assigned.
- * \param ofs The view offset, normally from RegionView3D.ofs.
- * \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
- * \param dist The view distance from ofs, normally from RegionView3D.dist.
- */
-void ED_view3d_to_object(Object *ob, const float ofs[3], const float quat[4], const float dist)
-{
- float mat[4][4];
-
- ED_view3d_to_m4(mat, ofs, quat, dist);
- BKE_object_apply_mat4(ob, mat, true, true);
-}
-
-/**
- * Use to store the last view, before entering camera view.
- */
-void ED_view3d_lastview_store(RegionView3D *rv3d)
-{
- copy_qt_qt(rv3d->lviewquat, rv3d->viewquat);
- rv3d->lview = rv3d->view;
- if (rv3d->persp != RV3D_CAMOB) {
- rv3d->lpersp = rv3d->persp;
- }
-}
-
-void ED_view3D_lock_clear(View3D *v3d)
-{
- v3d->ob_centre = NULL;
- v3d->ob_centre_bone[0] = '\0';
- v3d->ob_centre_cursor = false;
- v3d->flag2 &= ~V3D_LOCK_CAMERA;
-}
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index 8a48b1dc3aa..d2aa19509d7 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -58,6 +58,8 @@
#include "GPU_immediate.h"
+#include "DEG_depsgraph.h"
+
#include "view3d_intern.h" /* own include */
/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
@@ -344,6 +346,10 @@ enum {
static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
+
rctf viewborder;
float upvec[3]; /* tmp */
@@ -419,7 +425,7 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent
}
fly->v3d_camera_control = ED_view3d_cameracontrol_acquire(
- C, fly->scene, fly->v3d, fly->rv3d,
+ &eval_ctx, fly->scene, fly->v3d, fly->rv3d,
(U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0);
/* calculate center */
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index df2e5315c39..5e34bc188f0 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -111,6 +111,7 @@ void VIEW3D_OT_zoom_border(struct wmOperatorType *ot);
void VIEW3D_OT_toggle_render(struct wmOperatorType *ot);
void view3d_boxview_copy(ScrArea *sa, ARegion *ar);
+void view3d_boxview_sync(ScrArea *sa, ARegion *ar);
void view3d_orbit_apply_dyn_ofs(
float r_ofs[3], const float ofs_old[3], const float viewquat_old[4],
@@ -276,8 +277,12 @@ void ED_view3d_smooth_view_force_finish(
struct bContext *C,
struct View3D *v3d, struct ARegion *ar);
-void view3d_winmatrix_set(const struct Depsgraph *depsgraph, ARegion *ar, const View3D *v3d, const rcti *rect);
-void view3d_viewmatrix_set(const struct EvaluationContext *eval_ctx, Scene *scene, const View3D *v3d, RegionView3D *rv3d);
+void view3d_winmatrix_set(
+ const struct Depsgraph *depsgraph,
+ ARegion *ar, const View3D *v3d, const rcti *rect);
+void view3d_viewmatrix_set(
+ const struct EvaluationContext *eval_ctx, Scene *scene,
+ const View3D *v3d, RegionView3D *rv3d, const float rect_scale[2]);
void fly_modal_keymap(struct wmKeyConfig *keyconf);
void walk_modal_keymap(struct wmKeyConfig *keyconf);
@@ -292,7 +297,7 @@ void view3d_buttons_register(struct ARegionType *art);
/* view3d_camera_control.c */
struct View3DCameraControl *ED_view3d_cameracontrol_acquire(
- const struct bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d,
+ const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, RegionView3D *rv3d,
const bool use_parent_root);
void ED_view3d_cameracontrol_update(
struct View3DCameraControl *vctrl,
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
index 0f7df8fe6aa..9f655fff8a1 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
@@ -163,6 +163,16 @@ struct NavigateManipulatorInfo g_navigate_params[MPR_TOTAL] = {
struct NavigateWidgetGroup {
wmManipulator *mpr_array[MPR_TOTAL];
+ /* Store the view state to check for changes. */
+ struct {
+ struct {
+ short winx, winy;
+ } ar;
+ struct {
+ char is_persp;
+ char viewlock;
+ } rv3d;
+ } state;
int region_size[2];
bool is_persp;
};
@@ -200,8 +210,6 @@ static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmManipulatorG
RNA_property_string_set_bytes(
mpr->ptr, prop,
(const char *)info->shape, info->shape_size);
- /* don't fade icons so much */
- mpr->color[3] = 0.5f;
}
wmOperatorType *ot = WM_operatortype_find(info->opname, true);
@@ -214,6 +222,15 @@ static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmManipulatorG
RNA_enum_set(ptr, "type", RV3D_VIEW_CAMERA);
}
+ /* Click only buttons (not modal). */
+ {
+ int mpr_ids[] = {MPR_PERSP, MPR_ORTHO, MPR_CAMERA};
+ for (int i = 0; i < ARRAY_SIZE(mpr_ids); i++) {
+ wmManipulator *mpr = navgroup->mpr_array[mpr_ids[i]];
+ RNA_boolean_set(mpr->ptr, "show_drag", false);
+ }
+ }
+
{
wmManipulator *mpr = navgroup->mpr_array[MPR_ROTATE];
mpr->scale_basis = MANIPULATOR_SIZE / 2;
@@ -248,16 +265,19 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmManipulatorGr
copy_v3_v3(navgroup->mpr_array[MPR_ROTATE]->matrix_offset[i], rv3d->viewmat[i]);
}
- if ((navgroup->region_size[0] == ar->winx) &&
- (navgroup->region_size[1] == ar->winy) &&
- (navgroup->is_persp == rv3d->is_persp))
+ if ((navgroup->state.ar.winx == ar->winx) &&
+ (navgroup->state.ar.winy == ar->winy) &&
+ (navgroup->state.rv3d.is_persp == rv3d->is_persp) &&
+ (navgroup->state.rv3d.viewlock == rv3d->viewlock))
{
return;
}
- navgroup->region_size[0] = ar->winx;
- navgroup->region_size[1] = ar->winy;
- navgroup->is_persp = rv3d->is_persp;
+
+ navgroup->state.ar.winx = ar->winx;
+ navgroup->state.ar.winy = ar->winy;
+ navgroup->state.rv3d.is_persp = rv3d->is_persp;
+ navgroup->state.rv3d.viewlock = rv3d->viewlock;
const float icon_size = MANIPULATOR_SIZE;
@@ -266,36 +286,50 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmManipulatorGr
const float co[2] = {ar->winx - icon_offset, ar->winy - icon_offset};
wmManipulator *mpr;
- mpr = navgroup->mpr_array[MPR_ROTATE];
- mpr->matrix_basis[3][0] = co[0];
- mpr->matrix_basis[3][1] = co[1];
- mpr = navgroup->mpr_array[MPR_MOVE];
- mpr->matrix_basis[3][0] = co[0] + icon_offset_mini;
- mpr->matrix_basis[3][1] = co[1] - icon_offset_mini;
+ for (uint i = 0; i < ARRAY_SIZE(navgroup->mpr_array); i++) {
+ mpr = navgroup->mpr_array[i];
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true);
+ }
- mpr = navgroup->mpr_array[MPR_ZOOM];
- mpr->matrix_basis[3][0] = co[0] - icon_offset_mini;
- mpr->matrix_basis[3][1] = co[1] - icon_offset_mini;
+ if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
+ mpr = navgroup->mpr_array[MPR_ROTATE];
+ mpr->matrix_basis[3][0] = co[0];
+ mpr->matrix_basis[3][1] = co[1];
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
- if (rv3d->is_persp) {
- mpr = navgroup->mpr_array[MPR_PERSP];
- WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true);
- mpr = navgroup->mpr_array[MPR_ORTHO];
+ mpr = navgroup->mpr_array[MPR_MOVE];
+ mpr->matrix_basis[3][0] = co[0] + icon_offset_mini;
+ mpr->matrix_basis[3][1] = co[1] - icon_offset_mini;
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+
+ mpr = navgroup->mpr_array[MPR_ZOOM];
+ mpr->matrix_basis[3][0] = co[0] - icon_offset_mini;
+ mpr->matrix_basis[3][1] = co[1] - icon_offset_mini;
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+
+ mpr = navgroup->mpr_array[rv3d->is_persp ? MPR_ORTHO : MPR_PERSP];
+ mpr->matrix_basis[3][0] = co[0] + icon_offset_mini;
+ mpr->matrix_basis[3][1] = co[1] + icon_offset_mini;
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+
+ mpr = navgroup->mpr_array[MPR_CAMERA];
+ mpr->matrix_basis[3][0] = co[0] - icon_offset_mini;
+ mpr->matrix_basis[3][1] = co[1] + icon_offset_mini;
WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
}
else {
- mpr = navgroup->mpr_array[MPR_ORTHO];
- WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true);
- mpr = navgroup->mpr_array[MPR_PERSP];
+ /* RV3D_LOCKED: only show supported buttons. */
+ mpr = navgroup->mpr_array[MPR_MOVE];
+ mpr->matrix_basis[3][0] = co[0] + icon_offset_mini;
+ mpr->matrix_basis[3][1] = co[1] + icon_offset_mini;
WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
- }
- mpr->matrix_basis[3][0] = co[0] + icon_offset_mini;
- mpr->matrix_basis[3][1] = co[1] + icon_offset_mini;
- mpr = navgroup->mpr_array[MPR_CAMERA];
- mpr->matrix_basis[3][0] = co[0] - icon_offset_mini;
- mpr->matrix_basis[3][1] = co[1] + icon_offset_mini;
+ mpr = navgroup->mpr_array[MPR_ZOOM];
+ mpr->matrix_basis[3][0] = co[0];
+ mpr->matrix_basis[3][1] = co[1] + icon_offset_mini;
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+ }
}
void VIEW3D_WGT_navigate(wmManipulatorGroupType *wgt)
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
index bda692a0e5c..e8d540bcc9d 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
@@ -1011,7 +1011,7 @@ void VIEW3D_WGT_ruler(wmManipulatorGroupType *wgt)
wgt->name = "Ruler Widgets";
wgt->idname = view3d_wgt_ruler_id;
- wgt->flag |= WM_MANIPULATORGROUPTYPE_SCALE;
+ wgt->flag |= WM_MANIPULATORGROUPTYPE_SCALE | WM_MANIPULATORGROUPTYPE_DRAW_MODAL_ALL;
wgt->mmap_params.spaceid = SPACE_VIEW3D;
wgt->mmap_params.regionid = RGN_TYPE_WINDOW;
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index af44629a18e..ba3e78b25b9 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -277,6 +277,11 @@ eV3DProjStatus ED_view3d_project_float_object(const ARegion *ar, const float co[
/* More Generic Window/Ray/Vector projection functions
* *************************************************** */
+float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3])
+{
+ return mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co) * rv3d->pixsize * U.pixelsize;
+}
+
/**
* Calculate a depth value from \a co, use with #ED_view3d_win_to_delta
*/
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
new file mode 100644
index 00000000000..7bb3f443ac6
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -0,0 +1,1436 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_view3d/view3d_utils.c
+ * \ingroup spview3d
+ *
+ * 3D View checks and manipulation (no operators).
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <float.h>
+
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_bitmap_draw_2d.h"
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_camera.h"
+#include "BKE_context.h"
+#include "BKE_object.h"
+#include "BKE_screen.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "GPU_matrix.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_keyframing.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "view3d_intern.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+/** \name View Data Access Utilities
+ *
+ * \{ */
+
+float *ED_view3d_cursor3d_get(Scene *scene, View3D *v3d)
+{
+ if (v3d && v3d->localvd) return v3d->cursor;
+ else return scene->cursor;
+}
+
+Camera *ED_view3d_camera_data_get(View3D *v3d, RegionView3D *rv3d)
+{
+ /* establish the camera object, so we can default to view mapping if anything is wrong with it */
+ if ((rv3d->persp == RV3D_CAMOB) && v3d->camera && (v3d->camera->type == OB_CAMERA)) {
+ return v3d->camera->data;
+ }
+ else {
+ return NULL;
+ }
+}
+
+void ED_view3d_dist_range_get(
+ const View3D *v3d,
+ float r_dist_range[2])
+{
+ r_dist_range[0] = v3d->grid * 0.001f;
+ r_dist_range[1] = v3d->far * 10.0f;
+}
+
+/**
+ * \note copies logic of #ED_view3d_viewplane_get(), keep in sync.
+ */
+bool ED_view3d_clip_range_get(
+ const Depsgraph *depsgraph,
+ const View3D *v3d, const RegionView3D *rv3d,
+ float *r_clipsta, float *r_clipend,
+ const bool use_ortho_factor)
+{
+ CameraParams params;
+
+ BKE_camera_params_init(&params);
+ BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
+
+ if (use_ortho_factor && params.is_ortho) {
+ const float fac = 2.0f / (params.clipend - params.clipsta);
+ params.clipsta *= fac;
+ params.clipend *= fac;
+ }
+
+ if (r_clipsta) *r_clipsta = params.clipsta;
+ if (r_clipend) *r_clipend = params.clipend;
+
+ return params.is_ortho;
+}
+
+bool ED_view3d_viewplane_get(
+ const Depsgraph *depsgraph,
+ const View3D *v3d, const RegionView3D *rv3d, int winx, int winy,
+ rctf *r_viewplane, float *r_clipsta, float *r_clipend, float *r_pixsize)
+{
+ CameraParams params;
+
+ BKE_camera_params_init(&params);
+ BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
+ BKE_camera_params_compute_viewplane(&params, winx, winy, 1.0f, 1.0f);
+
+ if (r_viewplane) *r_viewplane = params.viewplane;
+ if (r_clipsta) *r_clipsta = params.clipsta;
+ if (r_clipend) *r_clipend = params.clipend;
+ if (r_pixsize) *r_pixsize = params.viewdx;
+
+ return params.is_ortho;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/** \name View State/Context Utilities
+ *
+ * \{ */
+
+/**
+ * Use this call when executing an operator,
+ * event system doesn't set for each event the OpenGL drawing context.
+ */
+void view3d_operator_needs_opengl(const bContext *C)
+{
+ wmWindow *win = CTX_wm_window(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ view3d_region_operator_needs_opengl(win, ar);
+}
+
+void view3d_region_operator_needs_opengl(wmWindow *win, ARegion *ar)
+{
+ /* for debugging purpose, context should always be OK */
+ if ((ar == NULL) || (ar->regiontype != RGN_TYPE_WINDOW)) {
+ printf("view3d_region_operator_needs_opengl error, wrong region\n");
+ }
+ else {
+ RegionView3D *rv3d = ar->regiondata;
+
+ wmSubWindowSet(win, ar->swinid);
+ gpuLoadProjectionMatrix(rv3d->winmat);
+ gpuLoadMatrix(rv3d->viewmat);
+ }
+}
+
+/**
+ * Use instead of: ``bglPolygonOffset(rv3d->dist, ...)`` see bug [#37727]
+ */
+void ED_view3d_polygon_offset(const RegionView3D *rv3d, const float dist)
+{
+ float viewdist;
+
+ if (rv3d->rflag & RV3D_ZOFFSET_DISABLED) {
+ return;
+ }
+
+ viewdist = rv3d->dist;
+
+ /* special exception for ortho camera (viewdist isnt used for perspective cameras) */
+ if (dist != 0.0f) {
+ if (rv3d->persp == RV3D_CAMOB) {
+ if (rv3d->is_persp == false) {
+ viewdist = 1.0f / max_ff(fabsf(rv3d->winmat[0][0]), fabsf(rv3d->winmat[1][1]));
+ }
+ }
+ }
+
+ bglPolygonOffset(viewdist, dist);
+}
+
+bool ED_view3d_context_activate(bContext *C)
+{
+ bScreen *sc = CTX_wm_screen(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar;
+
+ /* sa can be NULL when called from python */
+ if (sa == NULL || sa->spacetype != SPACE_VIEW3D) {
+ sa = BKE_screen_find_big_area(sc, SPACE_VIEW3D, 0);
+ }
+
+ if (sa == NULL) {
+ return false;
+ }
+
+ ar = BKE_area_find_region_active_win(sa);
+ if (ar == NULL) {
+ return false;
+ }
+
+ /* bad context switch .. */
+ CTX_wm_area_set(C, sa);
+ CTX_wm_region_set(C, ar);
+
+ return true;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Clipping Utilities
+ *
+ * \{ */
+
+void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const BoundBox *bb, const bool is_flip)
+{
+ int val;
+
+ for (val = 0; val < 4; val++) {
+ normal_tri_v3(clip[val], bb->vec[val], bb->vec[val == 3 ? 0 : val + 1], bb->vec[val + 4]);
+ if (UNLIKELY(is_flip)) {
+ negate_v3(clip[val]);
+ }
+
+ clip[val][3] = -dot_v3v3(clip[val], bb->vec[val]);
+ }
+}
+
+void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], const ARegion *ar, const Object *ob, const rcti *rect)
+{
+ /* init in case unproject fails */
+ memset(bb->vec, 0, sizeof(bb->vec));
+
+ /* four clipping planes and bounding volume */
+ /* first do the bounding volume */
+ for (int val = 0; val < 4; val++) {
+ float xs = (val == 0 || val == 3) ? rect->xmin : rect->xmax;
+ float ys = (val == 0 || val == 1) ? rect->ymin : rect->ymax;
+
+ ED_view3d_unproject(ar, xs, ys, 0.0, bb->vec[val]);
+ ED_view3d_unproject(ar, xs, ys, 1.0, bb->vec[4 + val]);
+ }
+
+ /* optionally transform to object space */
+ if (ob) {
+ float imat[4][4];
+ invert_m4_m4(imat, ob->obmat);
+
+ for (int val = 0; val < 8; val++) {
+ mul_m4_v3(imat, bb->vec[val]);
+ }
+ }
+
+ /* verify if we have negative scale. doing the transform before cross
+ * product flips the sign of the vector compared to doing cross product
+ * before transform then, so we correct for that. */
+ int flip_sign = (ob) ? is_negative_m4(ob->obmat) : false;
+
+ ED_view3d_clipping_calc_from_boundbox(planes, bb, flip_sign);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Bound-Box Utilities
+ *
+ * \{ */
+
+static bool view3d_boundbox_clip_m4(const BoundBox *bb, float persmatob[4][4])
+{
+ int a, flag = -1, fl;
+
+ for (a = 0; a < 8; a++) {
+ float vec[4], min, max;
+ copy_v3_v3(vec, bb->vec[a]);
+ vec[3] = 1.0;
+ mul_m4_v4(persmatob, vec);
+ max = vec[3];
+ min = -vec[3];
+
+ fl = 0;
+ if (vec[0] < min) fl += 1;
+ if (vec[0] > max) fl += 2;
+ if (vec[1] < min) fl += 4;
+ if (vec[1] > max) fl += 8;
+ if (vec[2] < min) fl += 16;
+ if (vec[2] > max) fl += 32;
+
+ flag &= fl;
+ if (flag == 0) return true;
+ }
+
+ return false;
+}
+
+bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, const BoundBox *bb, float obmat[4][4])
+{
+ /* return 1: draw */
+
+ float persmatob[4][4];
+
+ if (bb == NULL) return true;
+ if (bb->flag & BOUNDBOX_DISABLED) return true;
+
+ mul_m4_m4m4(persmatob, (float(*)[4])rv3d->persmat, obmat);
+
+ return view3d_boundbox_clip_m4(bb, persmatob);
+}
+
+bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const BoundBox *bb)
+{
+ if (bb == NULL) return true;
+ if (bb->flag & BOUNDBOX_DISABLED) return true;
+
+ return view3d_boundbox_clip_m4(bb, rv3d->persmatob);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Perspective & Mode Switching
+ *
+ * Misc view utility functions.
+ * \{ */
+
+bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d)
+{
+ return (rv3d->persp != RV3D_CAMOB) && (v3d->ob_centre_cursor || v3d->ob_centre);
+}
+
+/**
+ * Use to store the last view, before entering camera view.
+ */
+void ED_view3d_lastview_store(RegionView3D *rv3d)
+{
+ copy_qt_qt(rv3d->lviewquat, rv3d->viewquat);
+ rv3d->lview = rv3d->view;
+ if (rv3d->persp != RV3D_CAMOB) {
+ rv3d->lpersp = rv3d->persp;
+ }
+}
+
+void ED_view3d_lock_clear(View3D *v3d)
+{
+ v3d->ob_centre = NULL;
+ v3d->ob_centre_bone[0] = '\0';
+ v3d->ob_centre_cursor = false;
+ v3d->flag2 &= ~V3D_LOCK_CAMERA;
+}
+
+/**
+ * For viewport operators that exit camera perspective.
+ *
+ * \note This differs from simply setting ``rv3d->persp = persp`` because it
+ * sets the ``ofs`` and ``dist`` values of the viewport so it matches the camera,
+ * otherwise switching out of camera view may jump to a different part of the scene.
+ */
+void ED_view3d_persp_switch_from_camera(View3D *v3d, RegionView3D *rv3d, const char persp)
+{
+ BLI_assert(rv3d->persp == RV3D_CAMOB);
+ BLI_assert(persp != RV3D_CAMOB);
+
+ if (v3d->camera) {
+ rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
+ ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
+ }
+
+ if (!ED_view3d_camera_lock_check(v3d, rv3d)) {
+ rv3d->persp = persp;
+ }
+}
+/**
+ * Action to take when rotating the view,
+ * handle auto-persp and logic for switching out of views.
+ *
+ * shared with NDOF.
+ */
+bool ED_view3d_persp_ensure(struct View3D *v3d, ARegion *ar)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ const bool autopersp = (U.uiflag & USER_AUTOPERSP) != 0;
+
+ BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0);
+
+ if (ED_view3d_camera_lock_check(v3d, rv3d))
+ return false;
+
+ if (rv3d->persp != RV3D_PERSP) {
+ if (rv3d->persp == RV3D_CAMOB) {
+ /* If autopersp and previous view was an axis one, switch back to PERSP mode, else reuse previous mode. */
+ char persp = (autopersp && RV3D_VIEW_IS_AXIS(rv3d->lview)) ? RV3D_PERSP : rv3d->lpersp;
+ ED_view3d_persp_switch_from_camera(v3d, rv3d, persp);
+ }
+ else if (autopersp && RV3D_VIEW_IS_AXIS(rv3d->view)) {
+ rv3d->persp = RV3D_PERSP;
+ }
+ return true;
+ }
+
+ return false;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Camera Lock API
+ *
+ * Lock the camera to the view-port, allowing view manipulation to transform the camera.
+ * \{ */
+
+/**
+ * \return true when the view-port is locked to its camera.
+ */
+bool ED_view3d_camera_lock_check(const View3D *v3d, const RegionView3D *rv3d)
+{
+ return ((v3d->camera) &&
+ (!ID_IS_LINKED(v3d->camera)) &&
+ (v3d->flag2 & V3D_LOCK_CAMERA) &&
+ (rv3d->persp == RV3D_CAMOB));
+}
+
+/**
+ * Apply the camera object transformation to the view-port.
+ * (needed so we can use regular view-port manipulation operators, that sync back to the camera).
+ */
+void ED_view3d_camera_lock_init_ex(View3D *v3d, RegionView3D *rv3d, const bool calc_dist)
+{
+ if (ED_view3d_camera_lock_check(v3d, rv3d)) {
+ if (calc_dist) {
+ /* using a fallback dist is OK here since ED_view3d_from_object() compensates for it */
+ rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
+ }
+ ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
+ }
+}
+
+void ED_view3d_camera_lock_init(View3D *v3d, RegionView3D *rv3d)
+{
+ ED_view3d_camera_lock_init_ex(v3d, rv3d, true);
+}
+
+/**
+ * Apply the view-port transformation back to the camera object.
+ *
+ * \return true if the camera is moved.
+ */
+bool ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d)
+{
+ if (ED_view3d_camera_lock_check(v3d, rv3d)) {
+ ObjectTfmProtectedChannels obtfm;
+ Object *root_parent;
+
+ if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (root_parent = v3d->camera->parent)) {
+ Object *ob_update;
+ float tmat[4][4];
+ float imat[4][4];
+ float view_mat[4][4];
+ float diff_mat[4][4];
+ float parent_mat[4][4];
+
+ while (root_parent->parent) {
+ root_parent = root_parent->parent;
+ }
+
+ ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
+
+ normalize_m4_m4(tmat, v3d->camera->obmat);
+
+ invert_m4_m4(imat, tmat);
+ mul_m4_m4m4(diff_mat, view_mat, imat);
+
+ mul_m4_m4m4(parent_mat, diff_mat, root_parent->obmat);
+
+ BKE_object_tfm_protected_backup(root_parent, &obtfm);
+ BKE_object_apply_mat4(root_parent, parent_mat, true, false);
+ BKE_object_tfm_protected_restore(root_parent, &obtfm, root_parent->protectflag);
+
+ ob_update = v3d->camera;
+ while (ob_update) {
+ DEG_id_tag_update(&ob_update->id, OB_RECALC_OB);
+ WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, ob_update);
+ ob_update = ob_update->parent;
+ }
+ }
+ else {
+ /* always maintain the same scale */
+ const short protect_scale_all = (OB_LOCK_SCALEX | OB_LOCK_SCALEY | OB_LOCK_SCALEZ);
+ BKE_object_tfm_protected_backup(v3d->camera, &obtfm);
+ ED_view3d_to_object(v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist);
+ BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag | protect_scale_all);
+
+ DEG_id_tag_update(&v3d->camera->id, OB_RECALC_OB);
+ WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, v3d->camera);
+ }
+
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+bool ED_view3d_camera_autokey(
+ Scene *scene, ID *id_key,
+ struct bContext *C, const bool do_rotate, const bool do_translate)
+{
+ if (autokeyframe_cfra_can_key(scene, id_key)) {
+ const float cfra = (float)CFRA;
+ ListBase dsources = {NULL, NULL};
+
+ /* add data-source override for the camera object */
+ ANIM_relative_keyingset_add_source(&dsources, id_key, NULL, NULL);
+
+ /* insert keyframes
+ * 1) on the first frame
+ * 2) on each subsequent frame
+ * TODO: need to check in future that frame changed before doing this
+ */
+ if (do_rotate) {
+ struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_ROTATION_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+ if (do_translate) {
+ struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+
+ /* free temp data */
+ BLI_freelistN(&dsources);
+
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+/**
+ * Call after modifying a locked view.
+ *
+ * \note Not every view edit currently auto-keys (numpad for eg),
+ * this is complicated because of smoothview.
+ */
+bool ED_view3d_camera_lock_autokey(
+ View3D *v3d, RegionView3D *rv3d,
+ struct bContext *C, const bool do_rotate, const bool do_translate)
+{
+ /* similar to ED_view3d_cameracontrol_update */
+ if (ED_view3d_camera_lock_check(v3d, rv3d)) {
+ Scene *scene = CTX_data_scene(C);
+ ID *id_key;
+ Object *root_parent;
+ if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (root_parent = v3d->camera->parent)) {
+ while (root_parent->parent) {
+ root_parent = root_parent->parent;
+ }
+ id_key = &root_parent->id;
+ }
+ else {
+ id_key = &v3d->camera->id;
+ }
+
+ return ED_view3d_camera_autokey(scene, id_key, C, do_rotate, do_translate);
+ }
+ else {
+ return false;
+ }
+}
+
+/** \} */
+
+
+
+/* -------------------------------------------------------------------- */
+/** \name Box View Support
+ *
+ * Use with quad-split so each view is clipped by the bounds of each view axis.
+ * \{ */
+
+static void view3d_boxview_clip(ScrArea *sa)
+{
+ ARegion *ar;
+ BoundBox *bb = MEM_callocN(sizeof(BoundBox), "clipbb");
+ float clip[6][4];
+ float x1 = 0.0f, y1 = 0.0f, z1 = 0.0f, ofs[3] = {0.0f, 0.0f, 0.0f};
+ int val;
+
+ /* create bounding box */
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = ar->regiondata;
+
+ if (rv3d->viewlock & RV3D_BOXCLIP) {
+ if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) {
+ if (ar->winx > ar->winy) x1 = rv3d->dist;
+ else x1 = ar->winx * rv3d->dist / ar->winy;
+
+ if (ar->winx > ar->winy) y1 = ar->winy * rv3d->dist / ar->winx;
+ else y1 = rv3d->dist;
+ copy_v2_v2(ofs, rv3d->ofs);
+ }
+ else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) {
+ ofs[2] = rv3d->ofs[2];
+
+ if (ar->winx > ar->winy) z1 = ar->winy * rv3d->dist / ar->winx;
+ else z1 = rv3d->dist;
+ }
+ }
+ }
+ }
+
+ for (val = 0; val < 8; val++) {
+ if (ELEM(val, 0, 3, 4, 7))
+ bb->vec[val][0] = -x1 - ofs[0];
+ else
+ bb->vec[val][0] = x1 - ofs[0];
+
+ if (ELEM(val, 0, 1, 4, 5))
+ bb->vec[val][1] = -y1 - ofs[1];
+ else
+ bb->vec[val][1] = y1 - ofs[1];
+
+ if (val > 3)
+ bb->vec[val][2] = -z1 - ofs[2];
+ else
+ bb->vec[val][2] = z1 - ofs[2];
+ }
+
+ /* normals for plane equations */
+ normal_tri_v3(clip[0], bb->vec[0], bb->vec[1], bb->vec[4]);
+ normal_tri_v3(clip[1], bb->vec[1], bb->vec[2], bb->vec[5]);
+ normal_tri_v3(clip[2], bb->vec[2], bb->vec[3], bb->vec[6]);
+ normal_tri_v3(clip[3], bb->vec[3], bb->vec[0], bb->vec[7]);
+ normal_tri_v3(clip[4], bb->vec[4], bb->vec[5], bb->vec[6]);
+ normal_tri_v3(clip[5], bb->vec[0], bb->vec[2], bb->vec[1]);
+
+ /* then plane equations */
+ for (val = 0; val < 6; val++) {
+ clip[val][3] = -dot_v3v3(clip[val], bb->vec[val % 5]);
+ }
+
+ /* create bounding box */
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = ar->regiondata;
+
+ if (rv3d->viewlock & RV3D_BOXCLIP) {
+ rv3d->rflag |= RV3D_CLIPPING;
+ memcpy(rv3d->clip, clip, sizeof(clip));
+ if (rv3d->clipbb) MEM_freeN(rv3d->clipbb);
+ rv3d->clipbb = MEM_dupallocN(bb);
+ }
+ }
+ }
+ MEM_freeN(bb);
+}
+
+/**
+ * Find which axis values are shared between both views and copy to \a rv3d_dst
+ * taking axis flipping into account.
+ */
+static void view3d_boxview_sync_axis(RegionView3D *rv3d_dst, RegionView3D *rv3d_src)
+{
+ /* absolute axis values above this are considered to be set (will be ~1.0f) */
+ const float axis_eps = 0.5f;
+ float viewinv[4];
+
+ /* use the view rotation to identify which axis to sync on */
+ float view_axis_all[4][3] = {
+ {1.0f, 0.0f, 0.0f},
+ {0.0f, 1.0f, 0.0f},
+ {1.0f, 0.0f, 0.0f},
+ {0.0f, 1.0f, 0.0f}};
+
+ float *view_src_x = &view_axis_all[0][0];
+ float *view_src_y = &view_axis_all[1][0];
+
+ float *view_dst_x = &view_axis_all[2][0];
+ float *view_dst_y = &view_axis_all[3][0];
+ int i;
+
+
+ /* we could use rv3d->viewinv, but better not depend on view matrix being updated */
+ if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_src->view, viewinv) == false)) {
+ return;
+ }
+ invert_qt_normalized(viewinv);
+ mul_qt_v3(viewinv, view_src_x);
+ mul_qt_v3(viewinv, view_src_y);
+
+ if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_dst->view, viewinv) == false)) {
+ return;
+ }
+ invert_qt_normalized(viewinv);
+ mul_qt_v3(viewinv, view_dst_x);
+ mul_qt_v3(viewinv, view_dst_y);
+
+ /* check source and dest have a matching axis */
+ for (i = 0; i < 3; i++) {
+ if (((fabsf(view_src_x[i]) > axis_eps) || (fabsf(view_src_y[i]) > axis_eps)) &&
+ ((fabsf(view_dst_x[i]) > axis_eps) || (fabsf(view_dst_y[i]) > axis_eps)))
+ {
+ rv3d_dst->ofs[i] = rv3d_src->ofs[i];
+ }
+ }
+}
+
+/* sync center/zoom view of region to others, for view transforms */
+void view3d_boxview_sync(ScrArea *sa, ARegion *ar)
+{
+ ARegion *artest;
+ RegionView3D *rv3d = ar->regiondata;
+ short clip = 0;
+
+ for (artest = sa->regionbase.first; artest; artest = artest->next) {
+ if (artest != ar && artest->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3dtest = artest->regiondata;
+
+ if (rv3dtest->viewlock & RV3D_LOCKED) {
+ rv3dtest->dist = rv3d->dist;
+ view3d_boxview_sync_axis(rv3dtest, rv3d);
+ clip |= rv3dtest->viewlock & RV3D_BOXCLIP;
+
+ ED_region_tag_redraw(artest);
+ }
+ }
+ }
+
+ if (clip) {
+ view3d_boxview_clip(sa);
+ }
+}
+
+/* for home, center etc */
+void view3d_boxview_copy(ScrArea *sa, ARegion *ar)
+{
+ ARegion *artest;
+ RegionView3D *rv3d = ar->regiondata;
+ bool clip = false;
+
+ for (artest = sa->regionbase.first; artest; artest = artest->next) {
+ if (artest != ar && artest->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3dtest = artest->regiondata;
+
+ if (rv3dtest->viewlock) {
+ rv3dtest->dist = rv3d->dist;
+ copy_v3_v3(rv3dtest->ofs, rv3d->ofs);
+ ED_region_tag_redraw(artest);
+
+ clip |= ((rv3dtest->viewlock & RV3D_BOXCLIP) != 0);
+ }
+ }
+ }
+
+ if (clip) {
+ view3d_boxview_clip(sa);
+ }
+}
+
+/* 'clip' is used to know if our clip setting has changed */
+void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip)
+{
+ ARegion *ar_sync = NULL;
+ RegionView3D *rv3d = ar->regiondata;
+ short viewlock;
+ /* this function copies flags from the first of the 3 other quadview
+ * regions to the 2 other, so it assumes this is the region whose
+ * properties are always being edited, weak */
+ viewlock = rv3d->viewlock;
+
+ if ((viewlock & RV3D_LOCKED) == 0) {
+ do_clip = (viewlock & RV3D_BOXCLIP) != 0;
+ viewlock = 0;
+ }
+ else if ((viewlock & RV3D_BOXVIEW) == 0 && (viewlock & RV3D_BOXCLIP) != 0) {
+ do_clip = true;
+ viewlock &= ~RV3D_BOXCLIP;
+ }
+
+ for (; ar; ar = ar->prev) {
+ if (ar->alignment == RGN_ALIGN_QSPLIT) {
+ rv3d = ar->regiondata;
+ rv3d->viewlock = viewlock;
+
+ if (do_clip && (viewlock & RV3D_BOXCLIP) == 0) {
+ rv3d->rflag &= ~RV3D_BOXCLIP;
+ }
+
+ /* use ar_sync so we sync with one of the aligned views below
+ * else the view jumps on changing view settings like 'clip'
+ * since it copies from the perspective view */
+ ar_sync = ar;
+ }
+ }
+
+ if (rv3d->viewlock & RV3D_BOXVIEW) {
+ view3d_boxview_sync(sa, ar_sync ? ar_sync : sa->regionbase.last);
+ }
+
+ /* ensure locked regions have an axis, locked user views don't make much sense */
+ if (viewlock & RV3D_LOCKED) {
+ int index_qsplit = 0;
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->alignment == RGN_ALIGN_QSPLIT) {
+ rv3d = ar->regiondata;
+ if (rv3d->viewlock) {
+ if (!RV3D_VIEW_IS_AXIS(rv3d->view)) {
+ rv3d->view = ED_view3d_lock_view_from_index(index_qsplit);
+ rv3d->persp = RV3D_ORTHO;
+ ED_view3d_lock(rv3d);
+ }
+ }
+ index_qsplit++;
+ }
+ }
+ }
+
+ ED_area_tag_redraw(sa);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Auto-Depth Utilities
+ * \{ */
+
+static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int margin)
+{
+ ViewDepths depth_temp = {0};
+ rcti rect;
+ float depth_close;
+
+ if (margin == 0) {
+ /* Get Z Depths, needed for perspective, nice for ortho */
+ rect.xmin = mval[0];
+ rect.ymin = mval[1];
+ rect.xmax = mval[0] + 1;
+ rect.ymax = mval[1] + 1;
+ }
+ else {
+ BLI_rcti_init_pt_radius(&rect, mval, margin);
+ }
+
+ view3d_update_depths_rect(ar, &depth_temp, &rect);
+ depth_close = view3d_depth_near(&depth_temp);
+ MEM_SAFE_FREE(depth_temp.depths);
+ return depth_close;
+}
+
+/**
+ * Get the world-space 3d location from a screen-space 2d point.
+ *
+ * \param mval: Input screen-space pixel location.
+ * \param mouse_worldloc: Output world-space location.
+ * \param fallback_depth_pt: Use this points depth when no depth can be found.
+ */
+bool ED_view3d_autodist(
+ const EvaluationContext *eval_ctx, struct Depsgraph *graph, ARegion *ar, View3D *v3d,
+ const int mval[2], float mouse_worldloc[3],
+ const bool alphaoverride, const float fallback_depth_pt[3])
+{
+ float depth_close;
+ int margin_arr[] = {0, 2, 4};
+ int i;
+ bool depth_ok = false;
+
+ /* Get Z Depths, needed for perspective, nice for ortho */
+ ED_view3d_draw_depth(eval_ctx, graph, ar, v3d, alphaoverride);
+
+ /* Attempt with low margin's first */
+ i = 0;
+ do {
+ depth_close = view_autodist_depth_margin(ar, mval, margin_arr[i++] * U.pixelsize);
+ depth_ok = (depth_close != FLT_MAX);
+ } while ((depth_ok == false) && (i < ARRAY_SIZE(margin_arr)));
+
+ if (depth_ok) {
+ float centx = (float)mval[0] + 0.5f;
+ float centy = (float)mval[1] + 0.5f;
+
+ if (ED_view3d_unproject(ar, centx, centy, depth_close, mouse_worldloc)) {
+ return true;
+ }
+ }
+
+ if (fallback_depth_pt) {
+ ED_view3d_win_to_3d_int(v3d, ar, fallback_depth_pt, mval, mouse_worldloc);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+void ED_view3d_autodist_init(
+ const EvaluationContext *eval_ctx, struct Depsgraph *graph,
+ ARegion *ar, View3D *v3d, int mode)
+{
+ /* Get Z Depths, needed for perspective, nice for ortho */
+ switch (mode) {
+ case 0:
+ ED_view3d_draw_depth(eval_ctx, graph, ar, v3d, true);
+ break;
+ case 1:
+ {
+ Scene *scene = DEG_get_evaluated_scene(graph);
+ ED_view3d_draw_depth_gpencil(eval_ctx, scene, ar, v3d);
+ break;
+ }
+ }
+}
+
+/* no 4x4 sampling, run #ED_view3d_autodist_init first */
+bool ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_worldloc[3],
+ int margin, float *force_depth)
+{
+ float depth;
+
+ /* Get Z Depths, needed for perspective, nice for ortho */
+ if (force_depth)
+ depth = *force_depth;
+ else
+ depth = view_autodist_depth_margin(ar, mval, margin);
+
+ if (depth == FLT_MAX)
+ return false;
+
+ float centx = (float)mval[0] + 0.5f;
+ float centy = (float)mval[1] + 0.5f;
+ return ED_view3d_unproject(ar, centx, centy, depth, mouse_worldloc);
+}
+
+bool ED_view3d_autodist_depth(ARegion *ar, const int mval[2], int margin, float *depth)
+{
+ *depth = view_autodist_depth_margin(ar, mval, margin);
+
+ return (*depth != FLT_MAX);
+}
+
+static bool depth_segment_cb(int x, int y, void *userData)
+{
+ struct { ARegion *ar; int margin; float depth; } *data = userData;
+ int mval[2];
+ float depth;
+
+ mval[0] = x;
+ mval[1] = y;
+
+ depth = view_autodist_depth_margin(data->ar, mval, data->margin);
+
+ if (depth != FLT_MAX) {
+ data->depth = depth;
+ return 0;
+ }
+ else {
+ return 1;
+ }
+}
+
+bool ED_view3d_autodist_depth_seg(
+ ARegion *ar, const int mval_sta[2], const int mval_end[2],
+ int margin, float *depth)
+{
+ struct { ARegion *ar; int margin; float depth; } data = {NULL};
+ int p1[2];
+ int p2[2];
+
+ data.ar = ar;
+ data.margin = margin;
+ data.depth = FLT_MAX;
+
+ copy_v2_v2_int(p1, mval_sta);
+ copy_v2_v2_int(p2, mval_end);
+
+ BLI_bitmap_draw_2d_line_v2v2i(p1, p2, depth_segment_cb, &data);
+
+ *depth = data.depth;
+
+ return (*depth != FLT_MAX);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Radius/Distance Utilities
+ *
+ * Use to calculate a distance to a point based on it's radius.
+ * \{ */
+
+float ED_view3d_radius_to_dist_persp(const float angle, const float radius)
+{
+ return radius * (1.0f / tanf(angle / 2.0f));
+}
+
+float ED_view3d_radius_to_dist_ortho(const float lens, const float radius)
+{
+ return radius / (DEFAULT_SENSOR_WIDTH / lens);
+}
+
+/**
+ * Return a new RegionView3D.dist value to fit the \a radius.
+ *
+ * \note Depth isn't taken into account, this will fit a flat plane exactly,
+ * but points towards the view (with a perspective projection),
+ * may be within the radius but outside the view. eg:
+ *
+ * <pre>
+ * +
+ * pt --> + /^ radius
+ * / |
+ * / |
+ * view + +
+ * \ |
+ * \ |
+ * \|
+ * +
+ * </pre>
+ *
+ * \param ar Can be NULL if \a use_aspect is false.
+ * \param persp Allow the caller to tell what kind of perspective to use (ortho/view/camera)
+ * \param use_aspect Increase the distance to account for non 1:1 view aspect.
+ * \param radius The radius will be fitted exactly, typically pre-scaled by a margin (#VIEW3D_MARGIN).
+ */
+float ED_view3d_radius_to_dist(
+ const View3D *v3d, const ARegion *ar,
+ const char persp, const bool use_aspect,
+ const float radius)
+{
+ float dist;
+
+ BLI_assert(ELEM(persp, RV3D_ORTHO, RV3D_PERSP, RV3D_CAMOB));
+ BLI_assert((persp != RV3D_CAMOB) || v3d->camera);
+
+ if (persp == RV3D_ORTHO) {
+ dist = ED_view3d_radius_to_dist_ortho(v3d->lens, radius);
+ }
+ else {
+ float lens, sensor_size, zoom;
+ float angle;
+
+ if (persp == RV3D_CAMOB) {
+ CameraParams params;
+ BKE_camera_params_init(&params);
+ params.clipsta = v3d->near;
+ params.clipend = v3d->far;
+ BKE_camera_params_from_object(&params, v3d->camera);
+
+ lens = params.lens;
+ sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y);
+
+ /* ignore 'rv3d->camzoom' because we want to fit to the cameras frame */
+ zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB;
+ }
+ else {
+ lens = v3d->lens;
+ sensor_size = DEFAULT_SENSOR_WIDTH;
+ zoom = CAMERA_PARAM_ZOOM_INIT_PERSP;
+ }
+
+ angle = focallength_to_fov(lens, sensor_size);
+
+ /* zoom influences lens, correct this by scaling the angle as a distance (by the zoom-level) */
+ angle = atanf(tanf(angle / 2.0f) * zoom) * 2.0f;
+
+ dist = ED_view3d_radius_to_dist_persp(angle, radius);
+ }
+
+ if (use_aspect) {
+ const RegionView3D *rv3d = ar->regiondata;
+
+ float winx, winy;
+
+ if (persp == RV3D_CAMOB) {
+ /* camera frame x/y in pixels */
+ winx = ar->winx / rv3d->viewcamtexcofac[0];
+ winy = ar->winy / rv3d->viewcamtexcofac[1];
+ }
+ else {
+ winx = ar->winx;
+ winy = ar->winy;
+ }
+
+ if (winx && winy) {
+ float aspect = winx / winy;
+ if (aspect < 1.0f) {
+ aspect = 1.0f / aspect;
+ }
+ dist *= aspect;
+ }
+ }
+
+ return dist;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Distance Utilities
+ * \{ */
+
+/* problem - ofs[3] can be on same location as camera itself.
+ * Blender needs proper dist value for zoom.
+ * use fallback_dist to override small values
+ */
+float ED_view3d_offset_distance(float mat[4][4], const float ofs[3], const float fallback_dist)
+{
+ float pos[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ float dir[4] = {0.0f, 0.0f, 1.0f, 0.0f};
+ float dist;
+
+ mul_m4_v4(mat, pos);
+ add_v3_v3(pos, ofs);
+ mul_m4_v4(mat, dir);
+ normalize_v3(dir);
+
+ dist = dot_v3v3(pos, dir);
+
+ if ((dist < FLT_EPSILON) && (fallback_dist != 0.0f)) {
+ dist = fallback_dist;
+ }
+
+ return dist;
+}
+
+/**
+ * Set the dist without moving the view (compensate with #RegionView3D.ofs)
+ *
+ * \note take care that viewinv is up to date, #ED_view3d_update_viewmat first.
+ */
+void ED_view3d_distance_set(RegionView3D *rv3d, const float dist)
+{
+ float viewinv[4];
+ float tvec[3];
+
+ BLI_assert(dist >= 0.0f);
+
+ copy_v3_fl3(tvec, 0.0f, 0.0f, rv3d->dist - dist);
+ /* rv3d->viewinv isn't always valid */
+#if 0
+ mul_mat3_m4_v3(rv3d->viewinv, tvec);
+#else
+ invert_qt_qt_normalized(viewinv, rv3d->viewquat);
+ mul_qt_v3(viewinv, tvec);
+#endif
+ sub_v3_v3(rv3d->ofs, tvec);
+
+ rv3d->dist = dist;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Axis Utilities
+ * \{ */
+static float view3d_quat_axis[6][4] = {
+ {M_SQRT1_2, -M_SQRT1_2, 0.0f, 0.0f}, /* RV3D_VIEW_FRONT */
+ {0.0f, 0.0f, -M_SQRT1_2, -M_SQRT1_2}, /* RV3D_VIEW_BACK */
+ {0.5f, -0.5f, 0.5f, 0.5f}, /* RV3D_VIEW_LEFT */
+ {0.5f, -0.5f, -0.5f, -0.5f}, /* RV3D_VIEW_RIGHT */
+ {1.0f, 0.0f, 0.0f, 0.0f}, /* RV3D_VIEW_TOP */
+ {0.0f, -1.0f, 0.0f, 0.0f}, /* RV3D_VIEW_BOTTOM */
+};
+
+
+bool ED_view3d_quat_from_axis_view(const char view, float quat[4])
+{
+ if (RV3D_VIEW_IS_AXIS(view)) {
+ copy_qt_qt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT]);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon)
+{
+ /* quat values are all unit length */
+
+ char view;
+
+ for (view = RV3D_VIEW_FRONT; view <= RV3D_VIEW_BOTTOM; view++) {
+ if (fabsf(angle_signed_qtqt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT])) < epsilon) {
+ return view;
+ }
+ }
+
+ return RV3D_VIEW_USER;
+}
+
+char ED_view3d_lock_view_from_index(int index)
+{
+ switch (index) {
+ case 0: return RV3D_VIEW_FRONT;
+ case 1: return RV3D_VIEW_TOP;
+ case 2: return RV3D_VIEW_RIGHT;
+ default: return RV3D_VIEW_USER;
+ }
+
+}
+
+char ED_view3d_axis_view_opposite(char view)
+{
+ switch (view) {
+ case RV3D_VIEW_FRONT: return RV3D_VIEW_BACK;
+ case RV3D_VIEW_BACK: return RV3D_VIEW_FRONT;
+ case RV3D_VIEW_LEFT: return RV3D_VIEW_RIGHT;
+ case RV3D_VIEW_RIGHT: return RV3D_VIEW_LEFT;
+ case RV3D_VIEW_TOP: return RV3D_VIEW_BOTTOM;
+ case RV3D_VIEW_BOTTOM: return RV3D_VIEW_TOP;
+ }
+
+ return RV3D_VIEW_USER;
+}
+
+
+bool ED_view3d_lock(RegionView3D *rv3d)
+{
+ return ED_view3d_quat_from_axis_view(rv3d->view, rv3d->viewquat);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Transform Utilities
+ * \{ */
+
+/**
+ * Set the view transformation from a 4x4 matrix.
+ *
+ * \param mat The view 4x4 transformation matrix to assign.
+ * \param ofs The view offset, normally from RegionView3D.ofs.
+ * \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
+ * \param dist The view distance from ofs, normally from RegionView3D.dist.
+ */
+void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist)
+{
+ float nmat[3][3];
+
+ /* dist depends on offset */
+ BLI_assert(dist == NULL || ofs != NULL);
+
+ copy_m3_m4(nmat, mat);
+ normalize_m3(nmat);
+
+ /* Offset */
+ if (ofs)
+ negate_v3_v3(ofs, mat[3]);
+
+ /* Quat */
+ if (quat) {
+ mat3_normalized_to_quat(quat, nmat);
+ invert_qt_normalized(quat);
+ }
+
+ if (ofs && dist) {
+ madd_v3_v3fl(ofs, nmat[2], *dist);
+ }
+}
+
+/**
+ * Calculate the view transformation matrix from RegionView3D input.
+ * The resulting matrix is equivalent to RegionView3D.viewinv
+ * \param mat The view 4x4 transformation matrix to calculate.
+ * \param ofs The view offset, normally from RegionView3D.ofs.
+ * \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
+ * \param dist The view distance from ofs, normally from RegionView3D.dist.
+ */
+void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], const float dist)
+{
+ float iviewquat[4] = {-quat[0], quat[1], quat[2], quat[3]};
+ float dvec[3] = {0.0f, 0.0f, dist};
+
+ quat_to_mat4(mat, iviewquat);
+ mul_mat3_m4_v3(mat, dvec);
+ sub_v3_v3v3(mat[3], dvec, ofs);
+}
+
+/**
+ * Set the RegionView3D members from an objects transformation and optionally lens.
+ * \param ob The object to set the view to.
+ * \param ofs The view offset to be set, normally from RegionView3D.ofs.
+ * \param quat The view rotation to be set, quaternion normally from RegionView3D.viewquat.
+ * \param dist The view distance from ofs to be set, normally from RegionView3D.dist.
+ * \param lens The view lens angle set for cameras and lamps, normally from View3D.lens.
+ */
+void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist, float *lens)
+{
+ ED_view3d_from_m4(ob->obmat, ofs, quat, dist);
+
+ if (lens) {
+ CameraParams params;
+
+ BKE_camera_params_init(&params);
+ BKE_camera_params_from_object(&params, ob);
+ *lens = params.lens;
+ }
+}
+
+/**
+ * Set the object transformation from RegionView3D members.
+ * \param ob The object which has the transformation assigned.
+ * \param ofs The view offset, normally from RegionView3D.ofs.
+ * \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
+ * \param dist The view distance from ofs, normally from RegionView3D.dist.
+ */
+void ED_view3d_to_object(Object *ob, const float ofs[3], const float quat[4], const float dist)
+{
+ float mat[4][4];
+ ED_view3d_to_m4(mat, ofs, quat, dist);
+ BKE_object_apply_mat4(ob, mat, true, true);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Depth Buffer Utilities
+ * \{ */
+
+float ED_view3d_depth_read_cached(const ViewContext *vc, const int mval[2])
+{
+ ViewDepths *vd = vc->rv3d->depths;
+
+ int x = mval[0];
+ int y = mval[1];
+
+ if (vd && vd->depths && x > 0 && y > 0 && x < vd->w && y < vd->h) {
+ return vd->depths[y * vd->w + x];
+ }
+ else {
+ BLI_assert(1.0 <= vd->depth_range[1]);
+ return 1.0f;
+ }
+}
+
+bool ED_view3d_depth_read_cached_normal(
+ const ViewContext *vc, const int mval[2],
+ float r_normal[3])
+{
+ /* Note: we could support passing in a radius.
+ * For now just read 9 pixels. */
+
+ /* pixels surrounding */
+ bool depths_valid[9] = {false};
+ float coords[9][3] = {{0}};
+
+ ARegion *ar = vc->ar;
+ const ViewDepths *depths = vc->rv3d->depths;
+
+ for (int x = 0, i = 0; x < 2; x++) {
+ for (int y = 0; y < 2; y++) {
+ const int mval_ofs[2] = {mval[0] + (x - 1), mval[1] + (y - 1)};
+
+ const double depth = (double)ED_view3d_depth_read_cached(vc, mval_ofs);
+ if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
+ if (ED_view3d_depth_unproject(ar, mval_ofs, depth, coords[i])) {
+ depths_valid[i] = true;
+ }
+ }
+ i++;
+ }
+ }
+
+ const int edges[2][6][2] = {
+ /* x edges */
+ {{0, 1}, {1, 2},
+ {3, 4}, {4, 5},
+ {6, 7}, {7, 8}},
+ /* y edges */
+ {{0, 3}, {3, 6},
+ {1, 4}, {4, 7},
+ {2, 5}, {5, 8}},
+ };
+
+ float cross[2][3] = {{0.0f}};
+
+ for (int i = 0; i < 6; i++) {
+ for (int axis = 0; axis < 2; axis++) {
+ if (depths_valid[edges[axis][i][0]] && depths_valid[edges[axis][i][1]]) {
+ float delta[3];
+ sub_v3_v3v3(delta, coords[edges[axis][i][0]], coords[edges[axis][i][1]]);
+ add_v3_v3(cross[axis], delta);
+ }
+ }
+ }
+
+ cross_v3_v3v3(r_normal, cross[0], cross[1]);
+
+ if (normalize_v3(r_normal) != 0.0f) {
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+bool ED_view3d_depth_unproject(
+ const ARegion *ar,
+ const int mval[2], const double depth,
+ float r_location_world[3])
+{
+ float centx = (float)mval[0] + 0.5f;
+ float centy = (float)mval[1] + 0.5f;
+ return ED_view3d_unproject(ar, centx, centy, depth, r_location_world);
+}
+
+void ED_view3d_depth_tag_update(RegionView3D *rv3d)
+{
+ if (rv3d->depths)
+ rv3d->depths->damaged = true;
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 72443a5a227..0597f2806b3 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -28,7 +28,6 @@
* \ingroup spview3d
*/
-
#include "DNA_camera_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
@@ -39,7 +38,6 @@
#include "BLI_rect.h"
#include "BLI_utildefines.h"
-#include "BKE_anim.h"
#include "BKE_action.h"
#include "BKE_camera.h"
#include "BKE_context.h"
@@ -48,12 +46,9 @@
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_scene.h"
-#include "BKE_screen.h"
#include "DEG_depsgraph.h"
-#include "BIF_glutil.h"
-
#include "UI_resources.h"
#include "GPU_glew.h"
@@ -64,7 +59,6 @@
#include "WM_types.h"
#include "ED_screen.h"
-#include "ED_armature.h"
#include "DRW_engine.h"
@@ -79,53 +73,14 @@
# include "BL_System.h"
#endif
-
#include "view3d_intern.h" /* own include */
-/* use this call when executing an operator,
- * event system doesn't set for each event the
- * opengl drawing context */
-void view3d_operator_needs_opengl(const bContext *C)
-{
- wmWindow *win = CTX_wm_window(C);
- ARegion *ar = CTX_wm_region(C);
-
- view3d_region_operator_needs_opengl(win, ar);
-}
-
-void view3d_region_operator_needs_opengl(wmWindow *win, ARegion *ar)
-{
- /* for debugging purpose, context should always be OK */
- if ((ar == NULL) || (ar->regiontype != RGN_TYPE_WINDOW)) {
- printf("view3d_region_operator_needs_opengl error, wrong region\n");
- }
- else {
- RegionView3D *rv3d = ar->regiondata;
-
- wmSubWindowSet(win, ar->swinid);
- gpuLoadProjectionMatrix(rv3d->winmat);
- gpuLoadMatrix(rv3d->viewmat);
- }
-}
-
-float *ED_view3d_cursor3d_get(Scene *scene, View3D *v3d)
-{
- if (v3d && v3d->localvd) return v3d->cursor;
- else return scene->cursor;
-}
-
-Camera *ED_view3d_camera_data_get(View3D *v3d, RegionView3D *rv3d)
-{
- /* establish the camera object, so we can default to view mapping if anything is wrong with it */
- if ((rv3d->persp == RV3D_CAMOB) && v3d->camera && (v3d->camera->type == OB_CAMERA)) {
- return v3d->camera->data;
- }
- else {
- return NULL;
- }
-}
+/* -------------------------------------------------------------------- */
+/** \name Smooth View Operator & Utilities
+ *
+ * Use for view transitions to have smooth (animated) transitions.
+ * \{ */
-/* ****************** smooth view operator ****************** */
/* This operator is one of the 'timer refresh' ones like animation playback */
struct SmoothView3DState {
@@ -402,6 +357,8 @@ static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *ar, bool
ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
}
+ /* Event handling won't know if a UI item has been moved under the pointer. */
+ WM_event_add_mousemove(C);
}
if (sync_boxview && (rv3d->viewlock & RV3D_BOXVIEW)) {
@@ -463,22 +420,25 @@ void ED_view3d_smooth_view_force_finish(
void VIEW3D_OT_smoothview(wmOperatorType *ot)
{
-
/* identifiers */
ot->name = "Smooth View";
ot->description = "";
ot->idname = "VIEW3D_OT_smoothview";
-
+
/* api callbacks */
ot->invoke = view3d_smoothview_invoke;
-
+
/* flags */
ot->flag = OPTYPE_INTERNAL;
ot->poll = ED_operator_view3d_active;
}
-/* ****************** change view operators ****************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Camera to View Operator
+ * \{ */
static int view3d_camera_to_view_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -542,6 +502,12 @@ void VIEW3D_OT_camera_to_view(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Camera Fit Frame to Selected Operator
+ * \{ */
+
/* unlike VIEW3D_OT_view_selected this is for framing a render and not
* meant to take into account vertex/bone selection for eg. */
static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op)
@@ -601,6 +567,12 @@ void VIEW3D_OT_camera_to_view_selected(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object as Camera Operator
+ * \{ */
+
static void sync_viewport_camera_smoothview(bContext *C, View3D *v3d, Object *ob, const int smooth_viewtx)
{
Main *bmain = CTX_data_main(C);
@@ -651,7 +623,7 @@ static void sync_viewport_camera_smoothview(bContext *C, View3D *v3d, Object *ob
}
static int view3d_setobjectascamera_exec(bContext *C, wmOperator *op)
-{
+{
View3D *v3d;
ARegion *ar;
RegionView3D *rv3d;
@@ -704,7 +676,6 @@ int ED_operator_rv3d_user_region_poll(bContext *C)
void VIEW3D_OT_object_as_camera(wmOperatorType *ot)
{
-
/* identifiers */
ot->name = "Set Active Object as Camera";
ot->description = "Set the active object as the active camera for this view or scene";
@@ -718,280 +689,12 @@ void VIEW3D_OT_object_as_camera(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ********************************** */
-
-void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const BoundBox *bb, const bool is_flip)
-{
- int val;
-
- for (val = 0; val < 4; val++) {
- normal_tri_v3(clip[val], bb->vec[val], bb->vec[val == 3 ? 0 : val + 1], bb->vec[val + 4]);
- if (UNLIKELY(is_flip)) {
- negate_v3(clip[val]);
- }
-
- clip[val][3] = -dot_v3v3(clip[val], bb->vec[val]);
- }
-}
-
-void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], const ARegion *ar, const Object *ob, const rcti *rect)
-{
- /* init in case unproject fails */
- memset(bb->vec, 0, sizeof(bb->vec));
-
- /* four clipping planes and bounding volume */
- /* first do the bounding volume */
- for (int val = 0; val < 4; val++) {
- float xs = (val == 0 || val == 3) ? rect->xmin : rect->xmax;
- float ys = (val == 0 || val == 1) ? rect->ymin : rect->ymax;
-
- ED_view3d_unproject(ar, xs, ys, 0.0, bb->vec[val]);
- ED_view3d_unproject(ar, xs, ys, 1.0, bb->vec[4 + val]);
- }
-
- /* optionally transform to object space */
- if (ob) {
- float imat[4][4];
- invert_m4_m4(imat, ob->obmat);
-
- for (int val = 0; val < 8; val++) {
- mul_m4_v3(imat, bb->vec[val]);
- }
- }
-
- /* verify if we have negative scale. doing the transform before cross
- * product flips the sign of the vector compared to doing cross product
- * before transform then, so we correct for that. */
- int flip_sign = (ob) ? is_negative_m4(ob->obmat) : false;
-
- ED_view3d_clipping_calc_from_boundbox(planes, bb, flip_sign);
-}
-
-static bool view3d_boundbox_clip_m4(const BoundBox *bb, float persmatob[4][4])
-{
- int a, flag = -1, fl;
-
- for (a = 0; a < 8; a++) {
- float vec[4], min, max;
- copy_v3_v3(vec, bb->vec[a]);
- vec[3] = 1.0;
- mul_m4_v4(persmatob, vec);
- max = vec[3];
- min = -vec[3];
-
- fl = 0;
- if (vec[0] < min) fl += 1;
- if (vec[0] > max) fl += 2;
- if (vec[1] < min) fl += 4;
- if (vec[1] > max) fl += 8;
- if (vec[2] < min) fl += 16;
- if (vec[2] > max) fl += 32;
-
- flag &= fl;
- if (flag == 0) return true;
- }
-
- return false;
-}
-
-bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, const BoundBox *bb, float obmat[4][4])
-{
- /* return 1: draw */
-
- float persmatob[4][4];
-
- if (bb == NULL) return true;
- if (bb->flag & BOUNDBOX_DISABLED) return true;
-
- mul_m4_m4m4(persmatob, (float(*)[4])rv3d->persmat, obmat);
-
- return view3d_boundbox_clip_m4(bb, persmatob);
-}
-
-bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const BoundBox *bb)
-{
- if (bb == NULL) return true;
- if (bb->flag & BOUNDBOX_DISABLED) return true;
-
- return view3d_boundbox_clip_m4(bb, rv3d->persmatob);
-}
+/** \} */
/* -------------------------------------------------------------------- */
-
-/** \name Depth Utilities
+/** \name Window and View Matrix Calculation
* \{ */
-float ED_view3d_depth_read_cached(const ViewContext *vc, const int mval[2])
-{
- ViewDepths *vd = vc->rv3d->depths;
-
- int x = mval[0];
- int y = mval[1];
-
- if (vd && vd->depths && x > 0 && y > 0 && x < vd->w && y < vd->h) {
- return vd->depths[y * vd->w + x];
- }
- else {
- BLI_assert(1.0 <= vd->depth_range[1]);
- return 1.0f;
- }
-}
-
-bool ED_view3d_depth_read_cached_normal(
- const ViewContext *vc, const int mval[2],
- float r_normal[3])
-{
- /* Note: we could support passing in a radius.
- * For now just read 9 pixels. */
-
- /* pixels surrounding */
- bool depths_valid[9] = {false};
- float coords[9][3] = {{0}};
-
- ARegion *ar = vc->ar;
- const ViewDepths *depths = vc->rv3d->depths;
-
- for (int x = 0, i = 0; x < 2; x++) {
- for (int y = 0; y < 2; y++) {
- const int mval_ofs[2] = {mval[0] + (x - 1), mval[1] + (y - 1)};
-
- const double depth = (double)ED_view3d_depth_read_cached(vc, mval_ofs);
- if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
- if (ED_view3d_depth_unproject(ar, mval_ofs, depth, coords[i])) {
- depths_valid[i] = true;
- }
- }
- i++;
- }
- }
-
- const int edges[2][6][2] = {
- /* x edges */
- {{0, 1}, {1, 2},
- {3, 4}, {4, 5},
- {6, 7}, {7, 8}},
- /* y edges */
- {{0, 3}, {3, 6},
- {1, 4}, {4, 7},
- {2, 5}, {5, 8}},
- };
-
- float cross[2][3] = {{0.0f}};
-
- for (int i = 0; i < 6; i++) {
- for (int axis = 0; axis < 2; axis++) {
- if (depths_valid[edges[axis][i][0]] && depths_valid[edges[axis][i][1]]) {
- float delta[3];
- sub_v3_v3v3(delta, coords[edges[axis][i][0]], coords[edges[axis][i][1]]);
- add_v3_v3(cross[axis], delta);
- }
- }
- }
-
- cross_v3_v3v3(r_normal, cross[0], cross[1]);
-
- if (normalize_v3(r_normal) != 0.0f) {
- return true;
- }
- else {
- return false;
- }
-}
-
-bool ED_view3d_depth_unproject(
- const ARegion *ar,
- const int mval[2], const double depth,
- float r_location_world[3])
-{
- float centx = (float)mval[0] + 0.5f;
- float centy = (float)mval[1] + 0.5f;
- return ED_view3d_unproject(ar, centx, centy, depth, r_location_world);
-}
-
-/** \} */
-
-void ED_view3d_depth_tag_update(RegionView3D *rv3d)
-{
- if (rv3d->depths)
- rv3d->depths->damaged = true;
-}
-
-void ED_view3d_dist_range_get(
- const View3D *v3d,
- float r_dist_range[2])
-{
- r_dist_range[0] = v3d->grid * 0.001f;
- r_dist_range[1] = v3d->far * 10.0f;
-}
-
-/* copies logic of get_view3d_viewplane(), keep in sync */
-bool ED_view3d_clip_range_get(
- const Depsgraph *depsgraph,
- const View3D *v3d, const RegionView3D *rv3d,
- float *r_clipsta, float *r_clipend,
- const bool use_ortho_factor)
-{
- CameraParams params;
-
- BKE_camera_params_init(&params);
- BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
-
- if (use_ortho_factor && params.is_ortho) {
- const float fac = 2.0f / (params.clipend - params.clipsta);
- params.clipsta *= fac;
- params.clipend *= fac;
- }
-
- if (r_clipsta) *r_clipsta = params.clipsta;
- if (r_clipend) *r_clipend = params.clipend;
-
- return params.is_ortho;
-}
-
-bool ED_view3d_viewplane_get(
- const Depsgraph *depsgraph,
- const View3D *v3d, const RegionView3D *rv3d, int winx, int winy,
- rctf *r_viewplane, float *r_clipsta, float *r_clipend, float *r_pixsize)
-{
- CameraParams params;
-
- BKE_camera_params_init(&params);
- BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
- BKE_camera_params_compute_viewplane(&params, winx, winy, 1.0f, 1.0f);
-
- if (r_viewplane) *r_viewplane = params.viewplane;
- if (r_clipsta) *r_clipsta = params.clipsta;
- if (r_clipend) *r_clipend = params.clipend;
- if (r_pixsize) *r_pixsize = params.viewdx;
-
- return params.is_ortho;
-}
-
-/**
- * Use instead of: ``bglPolygonOffset(rv3d->dist, ...)`` see bug [#37727]
- */
-void ED_view3d_polygon_offset(const RegionView3D *rv3d, const float dist)
-{
- float viewdist;
-
- if (rv3d->rflag & RV3D_ZOFFSET_DISABLED) {
- return;
- }
-
- viewdist = rv3d->dist;
-
- /* special exception for ortho camera (viewdist isnt used for perspective cameras) */
- if (dist != 0.0f) {
- if (rv3d->persp == RV3D_CAMOB) {
- if (rv3d->is_persp == false) {
- viewdist = 1.0f / max_ff(fabsf(rv3d->winmat[0][0]), fabsf(rv3d->winmat[1][1]));
- }
- }
- }
-
- bglPolygonOffset(viewdist, dist);
-}
-
/**
* \param rect optional for picking (can be NULL).
*/
@@ -1044,75 +747,21 @@ static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob)
mat4_normalized_to_quat(rv3d->viewquat, rv3d->viewmat);
}
-static float view3d_quat_axis[6][4] = {
- {M_SQRT1_2, -M_SQRT1_2, 0.0f, 0.0f}, /* RV3D_VIEW_FRONT */
- {0.0f, 0.0f, -M_SQRT1_2, -M_SQRT1_2}, /* RV3D_VIEW_BACK */
- {0.5f, -0.5f, 0.5f, 0.5f}, /* RV3D_VIEW_LEFT */
- {0.5f, -0.5f, -0.5f, -0.5f}, /* RV3D_VIEW_RIGHT */
- {1.0f, 0.0f, 0.0f, 0.0f}, /* RV3D_VIEW_TOP */
- {0.0f, -1.0f, 0.0f, 0.0f}, /* RV3D_VIEW_BOTTOM */
-};
-
-
-bool ED_view3d_quat_from_axis_view(const char view, float quat[4])
-{
- if (RV3D_VIEW_IS_AXIS(view)) {
- copy_qt_qt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT]);
- return true;
- }
- else {
- return false;
- }
-}
-
-char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon)
-{
- /* quat values are all unit length */
-
- char view;
-
- for (view = RV3D_VIEW_FRONT; view <= RV3D_VIEW_BOTTOM; view++) {
- if (fabsf(angle_signed_qtqt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT])) < epsilon) {
- return view;
- }
- }
-
- return RV3D_VIEW_USER;
-}
-
-char ED_view3d_lock_view_from_index(int index)
-{
- switch (index) {
- case 0: return RV3D_VIEW_FRONT;
- case 1: return RV3D_VIEW_TOP;
- case 2: return RV3D_VIEW_RIGHT;
- default: return RV3D_VIEW_USER;
- }
-
-}
-
-char ED_view3d_axis_view_opposite(char view)
-{
- switch (view) {
- case RV3D_VIEW_FRONT: return RV3D_VIEW_BACK;
- case RV3D_VIEW_BACK: return RV3D_VIEW_FRONT;
- case RV3D_VIEW_LEFT: return RV3D_VIEW_RIGHT;
- case RV3D_VIEW_RIGHT: return RV3D_VIEW_LEFT;
- case RV3D_VIEW_TOP: return RV3D_VIEW_BOTTOM;
- case RV3D_VIEW_BOTTOM: return RV3D_VIEW_TOP;
- }
-
- return RV3D_VIEW_USER;
-}
-
-
-bool ED_view3d_lock(RegionView3D *rv3d)
-{
- return ED_view3d_quat_from_axis_view(rv3d->view, rv3d->viewquat);
-}
-
-/* don't set windows active in here, is used by renderwin too */
-void view3d_viewmatrix_set(const EvaluationContext *eval_ctx, Scene *scene, const View3D *v3d, RegionView3D *rv3d)
+/**
+ * Sets #RegionView3D.viewmat
+ *
+ * \param eval_ctx: Context.
+ * \param scene: Scene for camera and cursor location.
+ * \param v3d: View 3D space data.
+ * \param rv3d: 3D region which stores the final matrices.
+ * \param rect_scale: Optional 2D scale argument,
+ * Use when displaying a sub-region, eg: when #view3d_winmatrix_set takes a 'rect' argument.
+ *
+ * \note don't set windows active in here, is used by renderwin too.
+ */
+void view3d_viewmatrix_set(
+ const EvaluationContext *eval_ctx, Scene *scene,
+ const View3D *v3d, RegionView3D *rv3d, const float rect_scale[2])
{
if (rv3d->persp == RV3D_CAMOB) { /* obs/camera */
if (v3d->camera) {
@@ -1173,6 +822,17 @@ void view3d_viewmatrix_set(const EvaluationContext *eval_ctx, Scene *scene, cons
mul_v2_v2fl(vec, rv3d->ofs_lock, rv3d->is_persp ? rv3d->dist : 1.0f);
vec[2] = 0.0f;
+
+ if (rect_scale) {
+ /* Since 'RegionView3D.winmat' has been calculated and this function doesn't take the 'ARegion'
+ * we don't know about the region size.
+ * Use 'rect_scale' when drawing a sub-region to apply 2D offset,
+ * scaled by the difference between the sub-region and the region size.
+ */
+ vec[0] /= rect_scale[0];
+ vec[1] /= rect_scale[1];
+ }
+
mul_mat3_m4_v3(persinv, vec);
translate_m4(rv3d->viewmat, vec[0], vec[1], vec[2]);
}
@@ -1180,6 +840,12 @@ void view3d_viewmatrix_set(const EvaluationContext *eval_ctx, Scene *scene, cons
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name OpenGL Select Utilities
+ * \{ */
+
/**
* Optionally cache data for multiple calls to #view3d_opengl_select
*
@@ -1331,6 +997,12 @@ finally:
return hits;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Layer Utilities
+ * \{ */
+
int ED_view3d_view_layer_set(int lay, const int *values, int *active)
{
int i, tot = 0;
@@ -1369,43 +1041,43 @@ int ED_view3d_view_layer_set(int lay, const int *values, int *active)
return lay;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Game Engine Operator
+ *
+ * Start the game engine (handles context switching).
+ * \{ */
+
#ifdef WITH_GAMEENGINE
static ListBase queue_back;
-static void SaveState(bContext *C, wmWindow *win)
+static void game_engine_save_state(bContext *C, wmWindow *win)
{
Object *obact = CTX_data_active_object(C);
-
+
glPushAttrib(GL_ALL_ATTRIB_BITS);
if (obact && obact->mode & OB_MODE_TEXTURE_PAINT)
GPU_paint_set_mipmap(1);
-
+
queue_back = win->queue;
-
+
BLI_listbase_clear(&win->queue);
-
- //XXX waitcursor(1);
}
-static void RestoreState(bContext *C, wmWindow *win)
+static void game_engine_restore_state(bContext *C, wmWindow *win)
{
Object *obact = CTX_data_active_object(C);
-
+
if (obact && obact->mode & OB_MODE_TEXTURE_PAINT)
GPU_paint_set_mipmap(0);
- //XXX curarea->win_swap = 0;
- //XXX curarea->head_swap = 0;
- //XXX allqueue(REDRAWVIEW3D, 1);
- //XXX allqueue(REDRAWBUTSALL, 0);
- //XXX reset_slowparents();
- //XXX waitcursor(0);
- //XXX G.qual = 0;
-
- if (win) /* check because closing win can set to NULL */
+ /* check because closing win can set to NULL */
+ if (win) {
win->queue = queue_back;
-
+ }
+
GPU_state_init();
glPopAttrib();
@@ -1476,33 +1148,6 @@ static int game_engine_poll(bContext *C)
return 1;
}
-bool ED_view3d_context_activate(bContext *C)
-{
- bScreen *sc = CTX_wm_screen(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar;
-
- /* sa can be NULL when called from python */
- if (sa == NULL || sa->spacetype != SPACE_VIEW3D) {
- sa = BKE_screen_find_big_area(sc, SPACE_VIEW3D, 0);
- }
-
- if (sa == NULL) {
- return false;
- }
-
- ar = BKE_area_find_region_active_win(sa);
- if (ar == NULL) {
- return false;
- }
-
- /* bad context switch .. */
- CTX_wm_area_set(C, sa);
- CTX_wm_region_set(C, ar);
-
- return true;
-}
-
static int game_engine_exec(bContext *C, wmOperator *op)
{
#ifdef WITH_GAMEENGINE
@@ -1514,12 +1159,12 @@ static int game_engine_exec(bContext *C, wmOperator *op)
RegionView3D *rv3d;
rcti cam_frame;
- (void)op; /* unused */
-
+ UNUSED_VARS(op);
+
/* bad context switch .. */
if (!ED_view3d_context_activate(C))
return OPERATOR_CANCELLED;
-
+
/* redraw to hide any menus/popups, we don't go back to
* the window manager until after this operator exits */
WM_redraw_windows(C);
@@ -1531,7 +1176,7 @@ static int game_engine_exec(bContext *C, wmOperator *op)
ar = CTX_wm_region(C);
view3d_operator_needs_opengl(C);
-
+
game_set_commmandline_options(&startscene->gm);
if ((rv3d->persp == RV3D_CAMOB) &&
@@ -1556,7 +1201,7 @@ static int game_engine_exec(bContext *C, wmOperator *op)
}
- SaveState(C, prevwin);
+ game_engine_save_state(C, prevwin);
StartKetsjiShell(C, ar, &cam_frame, 1);
@@ -1565,7 +1210,7 @@ static int game_engine_exec(bContext *C, wmOperator *op)
prevwin = NULL;
CTX_wm_window_set(C, NULL);
}
-
+
ED_area_tag_redraw(CTX_wm_area(C));
if (prevwin) {
@@ -1576,7 +1221,7 @@ static int game_engine_exec(bContext *C, wmOperator *op)
CTX_wm_area_set(C, prevsa);
}
- RestoreState(C, prevwin);
+ game_engine_restore_state(C, prevwin);
//XXX restore_all_scene_cfra(scene_cfra_store);
BKE_scene_set_background(CTX_data_main(C), startscene);
@@ -1586,7 +1231,7 @@ static int game_engine_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
#else
- (void)C; /* unused */
+ UNUSED_VARS(C);
BKE_report(op->reports, RPT_ERROR, "Game engine is disabled in this build");
return OPERATOR_CANCELLED;
#endif
@@ -1594,168 +1239,15 @@ static int game_engine_exec(bContext *C, wmOperator *op)
void VIEW3D_OT_game_start(wmOperatorType *ot)
{
-
/* identifiers */
ot->name = "Start Game Engine";
ot->description = "Start game engine";
ot->idname = "VIEW3D_OT_game_start";
-
+
/* api callbacks */
ot->exec = game_engine_exec;
-
- ot->poll = game_engine_poll;
-}
-
-/* ************************************** */
-
-float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3])
-{
- return mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co) * rv3d->pixsize * U.pixelsize;
-}
-
-float ED_view3d_radius_to_dist_persp(const float angle, const float radius)
-{
- return radius * (1.0f / tanf(angle / 2.0f));
-}
-
-float ED_view3d_radius_to_dist_ortho(const float lens, const float radius)
-{
- return radius / (DEFAULT_SENSOR_WIDTH / lens);
-}
-
-/**
- * Return a new RegionView3D.dist value to fit the \a radius.
- *
- * \note Depth isn't taken into account, this will fit a flat plane exactly,
- * but points towards the view (with a perspective projection),
- * may be within the radius but outside the view. eg:
- *
- * <pre>
- * +
- * pt --> + /^ radius
- * / |
- * / |
- * view + +
- * \ |
- * \ |
- * \|
- * +
- * </pre>
- *
- * \param ar Can be NULL if \a use_aspect is false.
- * \param persp Allow the caller to tell what kind of perspective to use (ortho/view/camera)
- * \param use_aspect Increase the distance to account for non 1:1 view aspect.
- * \param radius The radius will be fitted exactly, typically pre-scaled by a margin (#VIEW3D_MARGIN).
- */
-float ED_view3d_radius_to_dist(
- const View3D *v3d, const ARegion *ar,
- const char persp, const bool use_aspect,
- const float radius)
-{
- float dist;
-
- BLI_assert(ELEM(persp, RV3D_ORTHO, RV3D_PERSP, RV3D_CAMOB));
- BLI_assert((persp != RV3D_CAMOB) || v3d->camera);
-
- if (persp == RV3D_ORTHO) {
- dist = ED_view3d_radius_to_dist_ortho(v3d->lens, radius);
- }
- else {
- float lens, sensor_size, zoom;
- float angle;
-
- if (persp == RV3D_CAMOB) {
- CameraParams params;
- BKE_camera_params_init(&params);
- params.clipsta = v3d->near;
- params.clipend = v3d->far;
- BKE_camera_params_from_object(&params, v3d->camera);
-
- lens = params.lens;
- sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y);
- /* ignore 'rv3d->camzoom' because we want to fit to the cameras frame */
- zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB;
- }
- else {
- lens = v3d->lens;
- sensor_size = DEFAULT_SENSOR_WIDTH;
- zoom = CAMERA_PARAM_ZOOM_INIT_PERSP;
- }
-
- angle = focallength_to_fov(lens, sensor_size);
-
- /* zoom influences lens, correct this by scaling the angle as a distance (by the zoom-level) */
- angle = atanf(tanf(angle / 2.0f) * zoom) * 2.0f;
-
- dist = ED_view3d_radius_to_dist_persp(angle, radius);
- }
-
- if (use_aspect) {
- const RegionView3D *rv3d = ar->regiondata;
-
- float winx, winy;
-
- if (persp == RV3D_CAMOB) {
- /* camera frame x/y in pixels */
- winx = ar->winx / rv3d->viewcamtexcofac[0];
- winy = ar->winy / rv3d->viewcamtexcofac[1];
- }
- else {
- winx = ar->winx;
- winy = ar->winy;
- }
-
- if (winx && winy) {
- float aspect = winx / winy;
- if (aspect < 1.0f) {
- aspect = 1.0f / aspect;
- }
- dist *= aspect;
- }
- }
-
- return dist;
-}
-
-/* view matrix properties utilities */
-
-/* unused */
-#if 0
-void ED_view3d_operator_properties_viewmat(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- prop = RNA_def_int(ot->srna, "region_width", 0, 0, INT_MAX, "Region Width", "", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
-
- prop = RNA_def_int(ot->srna, "region_height", 0, 0, INT_MAX, "Region height", "", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
-
- prop = RNA_def_float_matrix(ot->srna, "perspective_matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Perspective Matrix", 0.0f, 0.0f);
- RNA_def_property_flag(prop, PROP_HIDDEN);
-}
-
-void ED_view3d_operator_properties_viewmat_set(bContext *C, wmOperator *op)
-{
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ED_view3d_context_rv3d(C);
-
- if (!RNA_struct_property_is_set(op->ptr, "region_width"))
- RNA_int_set(op->ptr, "region_width", ar->winx);
-
- if (!RNA_struct_property_is_set(op->ptr, "region_height"))
- RNA_int_set(op->ptr, "region_height", ar->winy);
-
- if (!RNA_struct_property_is_set(op->ptr, "perspective_matrix"))
- RNA_float_set_array(op->ptr, "perspective_matrix", (float *)rv3d->persmat);
+ ot->poll = game_engine_poll;
}
-void ED_view3d_operator_properties_viewmat_get(wmOperator *op, int *winx, int *winy, float persmat[4][4])
-{
- *winx = RNA_int_get(op->ptr, "region_width");
- *winy = RNA_int_get(op->ptr, "region_height");
-
- RNA_float_get_array(op->ptr, "perspective_matrix", (float *)persmat);
-}
-#endif
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index 724f60734f1..e65f9abae27 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -60,6 +60,8 @@
#include "RE_engine.h"
+#include "DEG_depsgraph.h"
+
#include "view3d_intern.h" /* own include */
#ifdef WITH_INPUT_NDOF
@@ -510,6 +512,9 @@ static float userdef_speed = -1.f;
static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
{
wmWindow *win = CTX_wm_window(C);
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
walk->rv3d = CTX_wm_region_view3d(C);
walk->v3d = CTX_wm_view3d(C);
@@ -610,7 +615,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->ar, walk->v3d);
walk->v3d_camera_control = ED_view3d_cameracontrol_acquire(
- C, walk->scene, walk->v3d, walk->rv3d,
+ &eval_ctx, walk->scene, walk->v3d, walk->rv3d,
(U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0);
/* center the mouse */
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index db6f2c27623..f882f3ecd65 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -622,7 +622,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
- unsigned int pos;
+ unsigned int pos, color;
efa_act = EDBM_uv_active_face_get(em, false, false); /* will be set to NULL if hidden */
ts = scene->toolsettings;
@@ -671,58 +671,61 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
if (sima->flag & SI_DRAW_STRETCH) {
draw_uvs_stretch(sima, scene, em, efa_act);
}
- else if (!(sima->flag & SI_NO_DRAWFACES)) {
- /* draw transparent faces */
- UI_GetThemeColor4ubv(TH_FACE, col1);
- UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
-
- pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- for (unsigned int i = 0; i < em->tottri; i++) {
- efa = em->looptris[i][0]->f;
+ else {
+ unsigned int tri_count = 0;
+ BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
if (uvedit_face_visible_test(scene, ima, efa)) {
- const bool is_select = uvedit_face_select_test(scene, efa, cd_loop_uv_offset);
BM_elem_flag_enable(efa, BM_ELEM_TAG);
-
- if (efa == efa_act) {
- /* only once */
- immUniformThemeColor(TH_EDITMESH_ACTIVE);
- }
- else {
- immUniformColor4ubv(is_select ? col2 : col1);
- }
-
- immBegin(GWN_PRIM_TRIS, (em->looptris[i][0]->f->len - 2) * 3);
- draw_uvs_looptri(em, &i, cd_loop_uv_offset, pos);
- immEnd();
+ tri_count += efa->len - 2;
}
else {
BM_elem_flag_disable(efa, BM_ELEM_TAG);
}
}
- immUnbindProgram();
+ if (!(sima->flag & SI_NO_DRAWFACES)) {
+ /* draw transparent faces */
+ UI_GetThemeColor4ubv(TH_FACE, col1);
+ UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
- glDisable(GL_BLEND);
- }
- else {
- /* would be nice to do this within a draw loop but most below are optional, so it would involve too many checks */
-
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- if (uvedit_face_visible_test(scene, ima, efa)) {
- BM_elem_flag_enable(efa, BM_ELEM_TAG);
+ Gwn_VertFormat *format = immVertexFormat();
+ pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
+ immBegin(GWN_PRIM_TRIS, tri_count * 3);
+ for (unsigned int i = 0; i < em->tottri; i++) {
+ efa = em->looptris[i][0]->f;
+ if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
+ const bool is_select = uvedit_face_select_test(scene, efa, cd_loop_uv_offset);
+
+ if (efa == efa_act) {
+ /* only once */
+ unsigned char tmp_col[4];
+ UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, tmp_col);
+ immAttrib4ubv(color, tmp_col);
+ }
+ else {
+ immAttrib4ubv(color, is_select ? col2 : col1);
+ }
+
+ draw_uvs_looptri(em, &i, cd_loop_uv_offset, pos);
+ }
}
- else {
- if (efa == efa_act)
- efa_act = NULL;
- BM_elem_flag_disable(efa, BM_ELEM_TAG);
+ immEnd();
+
+ immUnbindProgram();
+
+ glDisable(GL_BLEND);
+ }
+ else {
+ if (efa_act && !uvedit_face_visible_test(scene, ima, efa_act)) {
+ efa_act = NULL;
}
}
-
}
/* 3. draw active face stippled */
@@ -813,7 +816,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
Gwn_VertFormat *format = immVertexFormat();
pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
if (interpedges) {
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
@@ -900,7 +903,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
Gwn_VertFormat *format = immVertexFormat();
pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c
index 1e99db2c32f..0400fc1025b 100644
--- a/source/blender/gpu/intern/gpu_batch.c
+++ b/source/blender/gpu/intern/gpu_batch.c
@@ -166,6 +166,7 @@ Gwn_Batch *GPU_batch_wire_from_poly_2d_encoded(
BLI_assert(polys_flat_len == polys_len * 2);
/* Over alloc */
+ /* Lines are pairs of (x, y) byte locations packed into an int32_t. */
int32_t *lines = MEM_mallocN(sizeof(*lines) * polys_len, __func__);
int32_t *lines_step = lines;
@@ -178,8 +179,6 @@ Gwn_Batch *GPU_batch_wire_from_poly_2d_encoded(
(rect ? rect->ymin : -1.0f),
};
- const bool hide_lines = true;
-
uint i_poly_prev = 0;
uint i_poly = 0;
while (i_poly != polys_len) {
@@ -210,15 +209,22 @@ Gwn_Batch *GPU_batch_wire_from_poly_2d_encoded(
}
}
- uint lines_len = (lines_step - lines);
- uint lines_hide_len = 0;
- if (hide_lines) {
+ uint lines_len = lines_step - lines;
+
+ /* Hide Lines (we could make optional) */
+ {
qsort(lines, lines_len, sizeof(int32_t), BLI_sortutil_cmp_int);
+ lines_step = lines;
+
+ if (lines[0] != lines[1]) {
+ *lines_step++ = lines[0];
+ }
for (uint i_prev = 0, i = 1; i < lines_len; i_prev = i++) {
- if ((lines[i] == lines[i_prev])) {
- lines_hide_len++;
+ if (lines[i] != lines[i_prev]) {
+ *lines_step++ = lines[i];
}
}
+ lines_len = lines_step - lines;
}
/* We have vertices and tris, make a batch from this. */
@@ -229,18 +235,13 @@ Gwn_Batch *GPU_batch_wire_from_poly_2d_encoded(
}
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, (lines_len - lines_hide_len) * 2);
+ const uint vbo_len_capacity = lines_len * 2;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
Gwn_VertBufRaw pos_step;
GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
for (uint i = 0; i < lines_len; i++) {
- if (hide_lines) {
- if ((i + 1 != lines_len) && (lines[i + 1] == lines[i])) {
- i++;
- continue;
- }
- }
union {
uint8_t as_u8_pair[2][2];
uint32_t as_u32;
@@ -253,6 +254,7 @@ Gwn_Batch *GPU_batch_wire_from_poly_2d_encoded(
}
}
}
+ BLI_assert(vbo_len_capacity == GWN_vertbuf_raw_used(&pos_step));
MEM_freeN(lines);
return GWN_batch_create_ex(
GWN_PRIM_LINES, vbo,
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 07c3b1e782b..780f4f59fb9 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -4135,9 +4135,14 @@ void node_bevel(float radius, vec3 N, out vec3 result)
result = N;
}
+void node_displacement(float height, float dist, vec3 N, out vec3 result)
+{
+ result = height * dist * N;
+}
+
/* output */
-void node_output_material(Closure surface, Closure volume, float displacement, out Closure result)
+void node_output_material(Closure surface, Closure volume, vec3 displacement, out Closure result)
{
#ifdef VOLUMETRICS
result = volume;
diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h
index b10ae4f6fe9..c4c4f4405a5 100644
--- a/source/blender/imbuf/intern/IMB_anim.h
+++ b/source/blender/imbuf/intern/IMB_anim.h
@@ -99,8 +99,8 @@ struct anim {
int curtype;
int curposition; /* index 0 = 1e, 1 = 2e, enz. */
int duration;
- short frs_sec;
- float frs_sec_base;
+ int frs_sec;
+ double frs_sec_base;
int x, y;
/* for number */
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index 25b0c0d7b1a..5472cae3ef2 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -55,6 +55,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
+#include <limits.h>
#ifndef _WIN32
#include <dirent.h>
#else
@@ -1365,16 +1366,32 @@ int IMB_anim_get_duration(struct anim *anim, IMB_Timecode_Type tc)
bool IMB_anim_get_fps(struct anim *anim,
short *frs_sec, float *frs_sec_base, bool no_av_base)
{
+ double frs_sec_base_double;
if (anim->frs_sec) {
- *frs_sec = anim->frs_sec;
- *frs_sec_base = anim->frs_sec_base;
+ if (anim->frs_sec > SHRT_MAX) {
+ /* We cannot store original rational in our short/float format,
+ * we need to approximate it as best as we can... */
+ *frs_sec = SHRT_MAX;
+ frs_sec_base_double = anim->frs_sec_base * (double)SHRT_MAX / (double)anim->frs_sec;
+ }
+ else {
+ *frs_sec = anim->frs_sec;
+ frs_sec_base_double = anim->frs_sec_base;
+ }
#ifdef WITH_FFMPEG
if (no_av_base) {
- *frs_sec_base /= AV_TIME_BASE;
+ *frs_sec_base = (float)(frs_sec_base_double / AV_TIME_BASE);
+ }
+ else {
+ *frs_sec_base = (float)frs_sec_base_double;
}
#else
UNUSED_VARS(no_av_base);
+ *frs_sec_base = (float)frs_sec_base_double;
#endif
+ BLI_assert(*frs_sec > 0);
+ BLI_assert(*frs_sec_base > 0.0f);
+
return true;
}
return false;
diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c
index b6e8b43b009..d29518fc5bc 100644
--- a/source/blender/imbuf/intern/cineon/dpxlib.c
+++ b/source/blender/imbuf/intern/cineon/dpxlib.c
@@ -193,7 +193,7 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf
dpx->srcFormat = format_DPX;
dpx->numElements = swap_ushort(header.imageHeader.elements_per_image, dpx->isMSB);
- size_t max_elements = sizeof(header.imageHeader.element)/sizeof(header.imageHeader.element[0]);
+ size_t max_elements = sizeof(header.imageHeader.element) / sizeof(header.imageHeader.element[0]);
if (dpx->numElements == 0 || dpx->numElements >= max_elements) {
if (verbose) printf("DPX: Wrong number of elements: %d\n", dpx->numElements);
logImageClose(dpx);
diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h
index ff81e04c5a1..806c1ca76fc 100644
--- a/source/blender/makesdna/DNA_layer_types.h
+++ b/source/blender/makesdna/DNA_layer_types.h
@@ -65,7 +65,7 @@ typedef struct LayerCollection {
/* TODO(sergey): Get rid of this once we've got CoW in DEG, */
short flag_evaluated;
short pad[2];
- ListBase object_bases; /* (ObjectBase *)LinkData->data - synced with collection->objects and collection->filter_objects */
+ ListBase object_bases; /* (ObjectBase *)LinkData->data - synced with collection->objects */
ListBase overrides;
ListBase layer_collections; /* synced with collection->collections */
struct IDProperty *properties; /* overrides */
@@ -102,12 +102,10 @@ typedef struct ViewLayer {
typedef struct SceneCollection {
struct SceneCollection *next, *prev;
char name[64]; /* MAX_NAME */
- char filter[64]; /* MAX_NAME */
int active_object_index; /* for UI */
char type;
char pad[3];
ListBase objects; /* (Object *)LinkData->data */
- ListBase filter_objects; /* (Object *)LinkData->data */
ListBase scene_collections; /* nested collections */
} SceneCollection;
diff --git a/source/blender/makesdna/DNA_lightprobe_types.h b/source/blender/makesdna/DNA_lightprobe_types.h
index 75705f7dd37..649df714457 100644
--- a/source/blender/makesdna/DNA_lightprobe_types.h
+++ b/source/blender/makesdna/DNA_lightprobe_types.h
@@ -55,7 +55,9 @@ typedef struct LightProbe {
float clipsta, clipend;
float vis_bias, vis_bleedbias; /* VSM visibility biases */
- float vis_blur, pad2;
+ float vis_blur;
+
+ float intensity; /* Intensity multiplier */
int grid_resolution_x; /* Irradiance grid resolution */
int grid_resolution_y;
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index dd716014f66..375641d1115 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -45,6 +45,8 @@ struct PanelType;
struct Scene;
struct uiLayout;
struct wmTimer;
+struct wmTooltipState;
+
typedef struct bScreen {
ID id;
@@ -77,6 +79,8 @@ typedef struct bScreen {
struct wmTimer *animtimer; /* if set, screen has timer handler added in window */
void *context; /* context callback */
+ struct wmTooltipState *tool_tip; /* runtime */
+
PreviewImage *preview;
} bScreen;
diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c
index ef3d7c0ae88..47f5d037d09 100644
--- a/source/blender/makesrna/intern/rna_layer.c
+++ b/source/blender/makesrna/intern/rna_layer.c
@@ -97,16 +97,6 @@ static void rna_SceneCollection_name_set(PointerRNA *ptr, const char *value)
BKE_collection_rename(scene, sc, value);
}
-static void rna_SceneCollection_filter_set(PointerRNA *ptr, const char *value)
-{
- Scene *scene = (Scene *)ptr->id.data;
- SceneCollection *sc = (SceneCollection *)ptr->data;
- BLI_strncpy_utf8(sc->filter, value, sizeof(sc->filter));
-
- TODO_LAYER_SYNC_FILTER;
- (void)scene;
-}
-
static PointerRNA rna_SceneCollection_objects_get(CollectionPropertyIterator *iter)
{
ListBaseIterator *internal = &iter->internal.listbase;
@@ -1055,11 +1045,6 @@ static void rna_def_scene_collection(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Type", "Type of collection");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- prop = RNA_def_property(srna, "filter", PROP_STRING, PROP_NONE);
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SceneCollection_filter_set");
- RNA_def_property_ui_text(prop, "Filter", "Filter to dynamically include objects based on their names (e.g., CHAR_*)");
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL);
-
prop = RNA_def_property(srna, "collections", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "scene_collections", NULL);
RNA_def_property_struct_type(prop, "SceneCollection");
@@ -1073,12 +1058,6 @@ static void rna_def_scene_collection(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Objects", "All the objects directly added to this collection (not including sub-collection objects)");
rna_def_collection_objects(brna, prop);
- prop = RNA_def_property(srna, "filters_objects", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "filter_objects", NULL);
- RNA_def_property_struct_type(prop, "Object");
- RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_SceneCollection_objects_get", NULL, NULL, NULL, NULL);
- RNA_def_property_ui_text(prop, "Filter Objects", "All the objects dynamically added to this collection via the filter");
-
/* Functions */
func = RNA_def_function(srna, "move_above", "rna_SceneCollection_move_above");
RNA_def_function_ui_description(func, "Move collection after another");
@@ -2034,8 +2013,6 @@ static void rna_def_layer_collection(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Enabled", "Enable or disable collection");
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollection_flag_update");
-
- /* TODO_LAYER_OVERRIDE */
}
static void rna_def_layer_collections(BlenderRNA *brna, PropertyRNA *cprop)
diff --git a/source/blender/makesrna/intern/rna_lightprobe.c b/source/blender/makesrna/intern/rna_lightprobe.c
index 61dc835022b..6586b456960 100644
--- a/source/blender/makesrna/intern/rna_lightprobe.c
+++ b/source/blender/makesrna/intern/rna_lightprobe.c
@@ -179,6 +179,13 @@ static void rna_def_lightprobe(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Visibility Blur", "Filter size of the visibilty blur");
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
+ prop = RNA_def_property(srna, "intensity", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "intensity");
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0f, 3.0f, 1.0, 3);
+ RNA_def_property_ui_text(prop, "Intensity", "Modify the intensity of the lighting captured by this probe");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
+
/* Data preview */
prop = RNA_def_property(srna, "show_data", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", LIGHTPROBE_FLAG_SHOW_DATA);
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index 62360ea34a3..79a9d072ad2 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -1667,7 +1667,7 @@ static int rna_MeshPolygonStringPropertyLayer_data_length(PointerRNA *ptr)
return me->totpoly;
}
-/* XXX, we dont have propper byte string support yet, so for now use the (bytes + 1)
+/* XXX, we dont have proper byte string support yet, so for now use the (bytes + 1)
* bmesh API exposes correct python/bytestring access */
void rna_MeshStringProperty_s_get(PointerRNA *ptr, char *value)
{
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 4f7dc35c2c1..e23fce47aad 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -5680,14 +5680,16 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "fps", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "frs_sec");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_range(prop, 1, 120);
+ RNA_def_property_range(prop, 1, SHRT_MAX);
+ RNA_def_property_ui_range(prop, 1, 120, 1, -1);
RNA_def_property_ui_text(prop, "FPS", "Framerate, expressed in frames per second");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_fps_update");
prop = RNA_def_property(srna, "fps_base", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "frs_sec_base");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_range(prop, 0.1f, 120.0f);
+ RNA_def_property_range(prop, 1e-5f, 1e6f);
+ RNA_def_property_ui_range(prop, 0.1f, 120.0f, 2, -1);
RNA_def_property_ui_text(prop, "FPS Base", "Framerate base");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_fps_update");
diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c
index 188b63d7d24..82077051c18 100644
--- a/source/blender/makesrna/intern/rna_wm_api.c
+++ b/source/blender/makesrna/intern/rna_wm_api.c
@@ -504,8 +504,11 @@ void RNA_api_wm(StructRNA *srna)
/* invoke enum */
func = RNA_def_function(srna, "invoke_search_popup", "rna_Operator_enum_search_invoke");
- RNA_def_function_ui_description(func, "Operator search popup invoke (search in values of "
- "operator's type 'prop' EnumProperty, and execute it on confirmation)");
+ RNA_def_function_ui_description(
+ func,
+ "Operator search popup invoke which "
+ "searches values of the operator's :class:`bpy.types.Operator.bl_property` "
+ "(which must be an EnumProperty), executing it on confirmation");
rna_generic_op_invoke(func, 0);
/* invoke functions, for use with python */
diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c
index 6fc1907ba0a..3cb35286114 100644
--- a/source/blender/modifiers/intern/MOD_wireframe.c
+++ b/source/blender/modifiers/intern/MOD_wireframe.c
@@ -52,11 +52,6 @@ static void copyData(ModifierData *md, ModifierData *target)
modifier_copyData_generic(md, target);
}
-static bool isDisabled(ModifierData *UNUSED(md), int UNUSED(useRenderParams))
-{
- return false;
-}
-
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
{
WireframeModifierData *wmd = (WireframeModifierData *)md;
@@ -132,8 +127,8 @@ ModifierTypeInfo modifierType_Wireframe = {
/* initData */ initData,
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
- /* isDisabled */ isDisabled,
- /* updateDepsgraph */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
/* foreachObjectLink */ NULL,
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index a6e04510b03..c83daa185a8 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -194,6 +194,7 @@ set(SRC
shader/nodes/node_shader_subsurface_scattering.c
shader/nodes/node_shader_tangent.c
shader/nodes/node_shader_bevel.c
+ shader/nodes/node_shader_displacement.c
shader/nodes/node_shader_tex_brick.c
shader/nodes/node_shader_tex_checker.c
shader/nodes/node_shader_tex_coord.c
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index 62a92e8d084..cbdfd8d3dbf 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -79,6 +79,7 @@ void register_node_type_sh_tex_pointdensity(void);
void register_node_type_sh_attribute(void);
void register_node_type_sh_bevel(void);
+void register_node_type_sh_displacement(void);
void register_node_type_sh_geometry(void);
void register_node_type_sh_light_path(void);
void register_node_type_sh_light_falloff(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index a18ee154af8..e2c1fae1bde 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -128,6 +128,7 @@ DefNode( ShaderNode, SH_NODE_UVALONGSTROKE, def_sh_uvalongstroke, "UV
DefNode( ShaderNode, SH_NODE_SEPXYZ, 0, "SEPXYZ", SeparateXYZ, "Separate XYZ", "" )
DefNode( ShaderNode, SH_NODE_COMBXYZ, 0, "COMBXYZ", CombineXYZ, "Combine XYZ", "" )
DefNode( ShaderNode, SH_NODE_BEVEL, def_sh_bevel, "BEVEL", Bevel, "Bevel", "" )
+DefNode( ShaderNode, SH_NODE_DISPLACEMENT, 0, "DISPLACEMENT", Displacement, "Displacement", "" )
DefNode( CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" )
DefNode( CompositorNode, CMP_NODE_RGB, 0, "RGB", RGB, "RGB", "" )
diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c
index 382492707ce..e1d17003ba4 100644
--- a/source/blender/nodes/intern/node_socket.c
+++ b/source/blender/nodes/intern/node_socket.c
@@ -112,22 +112,21 @@ static bNodeSocket *verify_socket_template(bNodeTree *ntree, bNode *node, int in
break;
}
if (sock) {
- sock->type = stemp->type;
+ if (sock->type != stemp->type) {
+ nodeModifySocketType(ntree, node, sock, stemp->type, stemp->subtype);
+ }
+
sock->limit = (stemp->limit == 0 ? 0xFFF : stemp->limit);
sock->flag |= stemp->flag;
-
- BLI_remlink(socklist, sock);
-
- return sock;
}
else {
/* no socket for this template found, make a new one */
sock = node_add_socket_from_template(ntree, node, stemp, in_out);
- /* remove the new socket from the node socket list first,
- * will be added back after verification.
- */
- BLI_remlink(socklist, sock);
}
+
+ /* remove the new socket from the node socket list first,
+ * will be added back after verification. */
+ BLI_remlink(socklist, sock);
return sock;
}
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index bd22a2be647..2f65188841e 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -460,6 +460,21 @@ static void ntree_shader_relink_displacement(bNodeTree *ntree,
* cycles in the Cycles material :)
*/
nodeRemLink(ntree, displacement_link);
+
+ /* Convert displacement vector to bump height. */
+ bNode *dot_node = nodeAddStaticNode(NULL, ntree, SH_NODE_VECT_MATH);
+ bNode *geo_node = nodeAddStaticNode(NULL, ntree, SH_NODE_NEW_GEOMETRY);
+ dot_node->custom1 = 3; /* dot product */
+
+ nodeAddLink(ntree,
+ displacement_node, displacement_socket,
+ dot_node, dot_node->inputs.first);
+ nodeAddLink(ntree,
+ geo_node, ntree_shader_node_find_output(geo_node, "Normal"),
+ dot_node, dot_node->inputs.last);
+ displacement_node = dot_node;
+ displacement_socket = ntree_shader_node_find_output(dot_node, "Value");
+
/* We can't connect displacement to normal directly, use bump node for that
* and hope that it gives good enough approximation.
*/
diff --git a/source/blender/nodes/shader/nodes/node_shader_bump.c b/source/blender/nodes/shader/nodes/node_shader_bump.c
index 15a8c47db7a..84481a50993 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bump.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bump.c
@@ -34,7 +34,7 @@
/* **************** BUMP ******************** */
static bNodeSocketTemplate sh_node_bump_in[] = {
{ SOCK_FLOAT, 1, N_("Strength"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
- { SOCK_FLOAT, 1, N_("Distance"), 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
+ { SOCK_FLOAT, 1, N_("Distance"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
{ SOCK_FLOAT, 1, N_("Height"), 1.0f, 1.0f, 1.0f, 1.0f, -1000.0f, 1000.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ -1, 0, "" }
diff --git a/source/blender/nodes/shader/nodes/node_shader_displacement.c b/source/blender/nodes/shader/nodes/node_shader_displacement.c
new file mode 100644
index 00000000000..d5c191b3966
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_displacement.c
@@ -0,0 +1,65 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../node_shader_util.h"
+
+/* **************** OUTPUT ******************** */
+
+static bNodeSocketTemplate sh_node_displacement_in[] = {
+ { SOCK_FLOAT, 0, N_("Height"), 0.00f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
+ { SOCK_FLOAT, 0, N_("Scale"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
+ { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ { -1, 0, "" }
+};
+
+static bNodeSocketTemplate sh_node_displacement_out[] = {
+ { SOCK_VECTOR, 0, N_("Displacement"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static int gpu_shader_displacement(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ if (!in[2].link) {
+ GPU_link(mat, "direction_transform_m4v3", GPU_builtin(GPU_VIEW_NORMAL), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &in[2].link);
+ }
+
+ return GPU_stack_link(mat, node, "node_displacement", in, out);
+}
+
+/* node type definition */
+void register_node_type_sh_displacement(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_DISPLACEMENT, "Displacement", NODE_CLASS_OP_VECTOR, 0);
+ node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_socket_templates(&ntype, sh_node_displacement_in, sh_node_displacement_out);
+ node_type_storage(&ntype, "", NULL, NULL);
+ node_type_gpu(&ntype, gpu_shader_displacement);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/shader/nodes/node_shader_output_material.c b/source/blender/nodes/shader/nodes/node_shader_output_material.c
index 0418b039337..e901e7c4590 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output_material.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output_material.c
@@ -34,7 +34,7 @@
static bNodeSocketTemplate sh_node_output_material_in[] = {
{ SOCK_SHADER, 1, N_("Surface")},
{ SOCK_SHADER, 1, N_("Volume")},
- { SOCK_FLOAT, 1, N_("Displacement"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ { SOCK_VECTOR, 1, N_("Displacement"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ -1, 0, "" }
};
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index a0f3a053618..0557efccc2f 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -392,6 +392,7 @@ void RE_updateRenderInstances(Render *re, int flag);
/******* defined in render_result.c *********/
bool RE_HasCombinedLayer(RenderResult *res);
+bool RE_HasFloatPixels(RenderResult *res);
bool RE_RenderResult_is_stereo(RenderResult *res);
struct RenderView *RE_RenderViewGetById(struct RenderResult *res, const int view_id);
struct RenderView *RE_RenderViewGetByName(struct RenderResult *res, const char *viewname);
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 999e0f7f70e..5a5c99724fe 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -449,8 +449,6 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id)
rr->rectz = rv->rectz;
rr->rect32 = rv->rect32;
- rr->have_combined = (rv->rectf != NULL);
-
/* active layer */
rl = render_get_active_layer(re, re->result);
@@ -861,7 +859,7 @@ void RE_InitState(Render *re, Render *source, RenderData *rd,
re->result = MEM_callocN(sizeof(RenderResult), "new render result");
re->result->rectx = re->rectx;
re->result->recty = re->recty;
- render_result_view_new(re->result, "new temporary view");
+ render_result_view_new(re->result, "");
}
if (re->r.scemode & R_VIEWPORT_PREVIEW)
@@ -3395,7 +3393,8 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen
return false;
bool is_mono = BLI_listbase_count_ex(&rr->views, 2) < 2;
- bool is_exr_rr = ELEM(rd->im_format.imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER);
+ bool is_exr_rr = ELEM(rd->im_format.imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER) &&
+ RE_HasFloatPixels(rr);
if (rd->im_format.views_format == R_IMF_VIEWS_MULTIVIEW && is_exr_rr)
{
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index c250a91f4cb..6749fedb16e 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -80,6 +80,8 @@ static void render_result_views_free(RenderResult *res)
MEM_freeN(rv);
}
+
+ res->have_combined = false;
}
void render_result_free(RenderResult *res)
@@ -1352,6 +1354,8 @@ void RE_render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), I
RenderView *rv = RE_RenderViewGetById(rr, view_id);
if (ibuf->rect_float) {
+ rr->have_combined = true;
+
if (!rv->rectf)
rv->rectf = MEM_mallocN(4 * sizeof(float) * rr->rectx * rr->recty, "render_seq rectf");
@@ -1362,6 +1366,8 @@ void RE_render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), I
MEM_SAFE_FREE(rv->rect32);
}
else if (ibuf->rect) {
+ rr->have_combined = true;
+
if (!rv->rect32)
rv->rect32 = MEM_mallocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect");
@@ -1417,6 +1423,19 @@ bool RE_HasCombinedLayer(RenderResult *res)
return (rv->rect32 || rv->rectf);
}
+bool RE_HasFloatPixels(RenderResult *res)
+{
+ RenderView *rview;
+
+ for (rview = res->views.first; rview; rview = rview->next) {
+ if (rview->rect32 && !rview->rectf) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool RE_RenderResult_is_stereo(RenderResult *res)
{
if (! BLI_findstring(&res->views, STEREO_LEFT_NAME, offsetof(RenderView, name)))
diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt
index b5784fe543c..059055daea9 100644
--- a/source/blender/windowmanager/CMakeLists.txt
+++ b/source/blender/windowmanager/CMakeLists.txt
@@ -73,6 +73,7 @@ set(SRC
intern/wm_window.c
intern/wm_stereo.c
intern/wm_toolsystem.c
+ intern/wm_tooltip.c
manipulators/intern/wm_manipulator.c
manipulators/intern/wm_manipulator_group.c
manipulators/intern/wm_manipulator_group_type.c
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 85f94721d40..7a66cc04014 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -576,6 +576,17 @@ void WM_toolsystem_link(struct bContext *C, struct WorkSpace *workspace);
void WM_toolsystem_set(struct bContext *C, const struct bToolDef *tool);
void WM_toolsystem_init(struct bContext *C);
+/* wm_tooltip.c */
+typedef struct ARegion *(*wmTooltipInitFn)(struct bContext *, struct ARegion *, bool *);
+
+void WM_tooltip_timer_init(
+ struct bContext *C, struct wmWindow *win, struct ARegion *ar,
+ wmTooltipInitFn init);
+void WM_tooltip_timer_clear(struct bContext *C, struct wmWindow *win);
+void WM_tooltip_clear(struct bContext *C, struct wmWindow *win);
+void WM_tooltip_init(struct bContext *C, struct wmWindow *win);
+void WM_tooltip_refresh(struct bContext *C, struct wmWindow *win);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index e30a109057d..74703daeb9c 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -704,6 +704,23 @@ typedef struct wmDropBox {
} wmDropBox;
+/**
+ * Struct to store tool-tip timer and possible creation if the time is reached.
+ * Allows UI code to call #WM_tooltip_timer_init without each user having to handle the timer.
+ */
+typedef struct wmTooltipState {
+ /** Create tooltip on this event. */
+ struct wmTimer *timer;
+ /** The region the tooltip is created in. */
+ struct ARegion *region_from;
+ /** The tooltip region. */
+ struct ARegion *region;
+ /** Create the tooltip region (assign to 'region'). */
+ struct ARegion *(*init)(struct bContext *, struct ARegion *, bool *r_exit_on_event);
+ /** Exit on any event, not needed for buttons since their highlight state is used. */
+ bool exit_on_event;
+} wmTooltipState;
+
/* *************** migrated stuff, clean later? ************** */
typedef struct RecentFile {
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 6e559ef7157..133ac6564f8 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -2275,30 +2275,13 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
wm_manipulatormap_handler_context(C, handler);
wm_region_mouse_co(C, event);
- if (event->type == MOUSEMOVE) {
- WM_manipulatormap_tooltip_clear(C, mmap);
- }
-
/* handle manipulator highlighting */
if (event->type == MOUSEMOVE && !wm_manipulatormap_modal_get(mmap)) {
int part;
mpr = wm_manipulatormap_highlight_find(mmap, C, event, &part);
wm_manipulatormap_highlight_set(mmap, C, mpr, part);
if (mpr != NULL) {
- WM_manipulatormap_tooltip_timer_init(C, mmap);
- }
- }
- /* handle user configurable manipulator-map keymap */
- else if ((event->type == TIMER) &&
- (event->customdata == WM_manipulatormap_tooltip_timer_get(mmap)))
- {
- if (mpr) {
- if (mpr->state & WM_MANIPULATOR_STATE_MODAL) {
- WM_manipulatormap_tooltip_clear(C, mmap);
- }
- else {
- WM_manipulatormap_tooltip_create(C, mmap);
- }
+ WM_tooltip_timer_init(C, CTX_wm_window(C), region, WM_manipulatormap_tooltip_init);
}
}
else {
@@ -2735,6 +2718,13 @@ void wm_event_do_handlers(bContext *C)
CTX_wm_window_set(C, win);
+ /* Clear tool-tip on mouse move. */
+ if (screen->tool_tip && screen->tool_tip->exit_on_event) {
+ if (ISMOUSE(event->type)) {
+ WM_tooltip_clear(C, win);
+ }
+ }
+
/* we let modal handlers get active area/region, also wm_paintcursor_test needs it */
CTX_wm_area_set(C, area_event_inside(C, &event->x));
CTX_wm_region_set(C, region_event_inside(C, &event->x));
@@ -2751,7 +2741,16 @@ void wm_event_do_handlers(bContext *C)
/* fileread case */
if (CTX_wm_window(C) == NULL)
return;
-
+
+ /* check for a tooltip */
+ if (screen == WM_window_get_active_screen(win)) {
+ if (screen->tool_tip && screen->tool_tip->timer) {
+ if ((event->type == TIMER) && (event->customdata == screen->tool_tip->timer)) {
+ WM_tooltip_init(C, win);
+ }
+ }
+ }
+
/* check dragging, creates new event or frees, adds draw tag */
wm_event_drag_test(wm, win, event);
diff --git a/source/blender/windowmanager/intern/wm_tooltip.c b/source/blender/windowmanager/intern/wm_tooltip.c
new file mode 100644
index 00000000000..83d620d1522
--- /dev/null
+++ b/source/blender/windowmanager/intern/wm_tooltip.c
@@ -0,0 +1,106 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/intern/wm_tooltip.c
+ * \ingroup wm
+ *
+ * Manages a per-window tool-tip.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+void WM_tooltip_timer_init(
+ bContext *C, wmWindow *win, ARegion *ar,
+ wmTooltipInitFn init)
+{
+ bScreen *screen = WM_window_get_active_screen(win);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ if (screen->tool_tip == NULL) {
+ screen->tool_tip = MEM_callocN(sizeof(*screen->tool_tip), __func__);
+ }
+ screen->tool_tip->region_from = ar;
+ screen->tool_tip->timer = WM_event_add_timer(wm, win, TIMER, UI_TOOLTIP_DELAY);
+ screen->tool_tip->init = init;
+}
+
+void WM_tooltip_timer_clear(bContext *C, wmWindow *win)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ bScreen *screen = WM_window_get_active_screen(win);
+ if (screen->tool_tip != NULL) {
+ if (screen->tool_tip->timer != NULL) {
+ WM_event_remove_timer(wm, win, screen->tool_tip->timer);
+ screen->tool_tip->timer = NULL;
+ }
+ }
+}
+
+void WM_tooltip_clear(bContext *C, wmWindow *win)
+{
+ WM_tooltip_timer_clear(C, win);
+ bScreen *screen = WM_window_get_active_screen(win);
+ if (screen->tool_tip != NULL) {
+ if (screen->tool_tip->region) {
+ UI_tooltip_free(C, screen, screen->tool_tip->region);
+ screen->tool_tip->region = NULL;
+ }
+ MEM_freeN(screen->tool_tip);
+ screen->tool_tip = NULL;
+ }
+}
+
+void WM_tooltip_init(bContext *C, wmWindow *win)
+{
+ WM_tooltip_timer_clear(C, win);
+ bScreen *screen = WM_window_get_active_screen(win);
+ if (screen->tool_tip->region) {
+ UI_tooltip_free(C, screen, screen->tool_tip->region);
+ screen->tool_tip->region = NULL;
+ }
+ screen->tool_tip->region = screen->tool_tip->init(
+ C, screen->tool_tip->region_from, &screen->tool_tip->exit_on_event);
+ if (screen->tool_tip->region == NULL) {
+ WM_tooltip_clear(C, win);
+ }
+}
+
+void WM_tooltip_refresh(bContext *C, wmWindow *win)
+{
+ WM_tooltip_timer_clear(C, win);
+ bScreen *screen = WM_window_get_active_screen(win);
+ if (screen->tool_tip != NULL) {
+ if (screen->tool_tip->region) {
+ UI_tooltip_free(C, screen, screen->tool_tip->region);
+ screen->tool_tip->region = NULL;
+ }
+ WM_tooltip_init(C, win);
+ }
+}
diff --git a/source/blender/windowmanager/manipulators/WM_manipulator_api.h b/source/blender/windowmanager/manipulators/WM_manipulator_api.h
index 7a31f4e6f1f..53bee9c6775 100644
--- a/source/blender/windowmanager/manipulators/WM_manipulator_api.h
+++ b/source/blender/windowmanager/manipulators/WM_manipulator_api.h
@@ -259,14 +259,8 @@ bool WM_manipulatormap_minmax(
const struct wmManipulatorMap *mmap, bool use_hidden, bool use_select,
float r_min[3], float r_max[3]);
-void WM_manipulatormap_tooltip_create(
- struct bContext *C, struct wmManipulatorMap *mmap);
-void WM_manipulatormap_tooltip_clear(
- struct bContext *C, struct wmManipulatorMap *mmap);
-void WM_manipulatormap_tooltip_timer_init(
- struct bContext *C, struct wmManipulatorMap *mmap);
-const void *WM_manipulatormap_tooltip_timer_get(
- struct wmManipulatorMap *mmap);
+struct ARegion *WM_manipulatormap_tooltip_init(
+ struct bContext *C, struct ARegion *ar, bool *r_exit_on_event);
/* -------------------------------------------------------------------- */
/* wmManipulatorMapType */
@@ -335,6 +329,6 @@ void WM_manipulator_group_type_unlink_delayed_ptr(
void WM_manipulator_group_type_unlink_delayed(const char *idname);
/* Utilities */
-void WM_manipulator_group_type_is_any_selected(const char *idname);
+bool WM_manipulator_context_check_drawstep(const struct bContext *C, eWM_ManipulatorMapDrawStep step);
#endif /* __WM_MANIPULATOR_API_H__ */
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
index dff8d8b4e6c..3a78dd32f94 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
@@ -735,3 +735,28 @@ void WM_manipulator_properties_free(PointerRNA *ptr)
}
/** \} */
+
+/** \name General Utilities
+ *
+ * \{ */
+
+bool WM_manipulator_context_check_drawstep(const struct bContext *C, eWM_ManipulatorMapDrawStep step)
+{
+ switch (step) {
+ case WM_MANIPULATORMAP_DRAWSTEP_2D:
+ {
+ break;
+ }
+ case WM_MANIPULATORMAP_DRAWSTEP_3D:
+ {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ if (ED_screen_animation_playing(wm)) {
+ return false;
+ }
+ break;
+ }
+ }
+ return true;
+}
+
+/** \} */
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c
index 2bd218298e6..0e63f3d6ffe 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c
@@ -145,7 +145,7 @@ void wm_manipulatorgroup_manipulator_register(wmManipulatorGroup *mgroup, wmMani
mpr->parent_mgroup = mgroup;
}
-wmManipulator *wm_manipulatorgroup_find_intersected_mainpulator(
+wmManipulator *wm_manipulatorgroup_find_intersected_manipulator(
const wmManipulatorGroup *mgroup, bContext *C, const wmEvent *event,
int *r_part)
{
@@ -500,7 +500,7 @@ static int manipulator_tweak_invoke(bContext *C, wmOperator *op, const wmEvent *
wmManipulator *mpr = mmap->mmap_context.highlight;
/* Needed for single click actions which don't enter modal state. */
- WM_manipulatormap_tooltip_clear(C, mmap);
+ WM_tooltip_clear(C, CTX_wm_window(C));
if (!mpr) {
/* wm_handlers_do_intern shouldn't let this happen */
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h b/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
index fc814adaef1..b7982cf00df 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
@@ -69,7 +69,7 @@ struct wmManipulatorGroup *wm_manipulatorgroup_new_from_type(
struct wmManipulatorMap *mmap, struct wmManipulatorGroupType *wgt);
void wm_manipulatorgroup_free(bContext *C, struct wmManipulatorGroup *mgroup);
void wm_manipulatorgroup_manipulator_register(struct wmManipulatorGroup *mgroup, struct wmManipulator *mpr);
-struct wmManipulator *wm_manipulatorgroup_find_intersected_mainpulator(
+struct wmManipulator *wm_manipulatorgroup_find_intersected_manipulator(
const struct wmManipulatorGroup *mgroup, struct bContext *C, const struct wmEvent *event,
int *r_part);
void wm_manipulatorgroup_intersectable_manipulators_to_list(
@@ -115,9 +115,6 @@ struct wmManipulatorMap {
/* cursor location at point of entering modal (see: WM_MANIPULATOR_GRAB_CURSOR) */
int event_xy[2];
short event_grabcursor;
-
- struct ARegion *tooltip;
- struct wmTimer *tooltip_timer;
} mmap_context;
};
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c
index d051c93d892..a9875020fbb 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c
@@ -445,6 +445,10 @@ void WM_manipulatormap_draw(
wmManipulatorMap *mmap, const bContext *C,
const eWM_ManipulatorMapDrawStep drawstep)
{
+ if (!WM_manipulator_context_check_drawstep(C, drawstep)) {
+ return;
+ }
+
ListBase draw_manipulators = {NULL};
manipulatormap_prepare_drawing(mmap, C, &draw_manipulators, drawstep);
@@ -550,6 +554,7 @@ static wmManipulator *manipulator_find_intersected_3d(
};
*r_part = 0;
+
/* set up view matrices */
view3d_operator_needs_opengl(C);
@@ -588,6 +593,11 @@ wmManipulator *wm_manipulatormap_highlight_find(
{
wmManipulator *mpr = NULL;
ListBase visible_3d_manipulators = {NULL};
+ bool do_step[WM_MANIPULATORMAP_DRAWSTEP_MAX];
+
+ for (int i = 0; i < ARRAY_SIZE(do_step); i++) {
+ do_step[i] = WM_manipulator_context_check_drawstep(C, i);
+ }
for (wmManipulatorGroup *mgroup = mmap->groups.first; mgroup; mgroup = mgroup->next) {
@@ -599,25 +609,28 @@ wmManipulator *wm_manipulatormap_highlight_find(
}
if (wm_manipulatorgroup_is_visible(mgroup, C)) {
+ eWM_ManipulatorMapDrawStep step;
if (mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) {
- if ((mmap->update_flag[WM_MANIPULATORMAP_DRAWSTEP_3D] & MANIPULATORMAP_IS_REFRESH_CALLBACK) &&
- mgroup->type->refresh)
- {
- mgroup->type->refresh(C, mgroup);
- /* cleared below */
- }
- wm_manipulatorgroup_intersectable_manipulators_to_list(mgroup, &visible_3d_manipulators);
+ step = WM_MANIPULATORMAP_DRAWSTEP_3D;
}
else {
- if ((mmap->update_flag[WM_MANIPULATORMAP_DRAWSTEP_2D] & MANIPULATORMAP_IS_REFRESH_CALLBACK) &&
- mgroup->type->refresh)
+ step = WM_MANIPULATORMAP_DRAWSTEP_2D;
+ }
+
+ if (do_step[step]) {
+ if ((mmap->update_flag[step] & MANIPULATORMAP_IS_REFRESH_CALLBACK) &&
+ (mgroup->type->refresh != NULL))
{
mgroup->type->refresh(C, mgroup);
/* cleared below */
}
-
- if ((mpr = wm_manipulatorgroup_find_intersected_mainpulator(mgroup, C, event, r_part))) {
- break;
+ if (step == WM_MANIPULATORMAP_DRAWSTEP_3D) {
+ wm_manipulatorgroup_intersectable_manipulators_to_list(mgroup, &visible_3d_manipulators);
+ }
+ else if (step == WM_MANIPULATORMAP_DRAWSTEP_2D) {
+ if ((mpr = wm_manipulatorgroup_find_intersected_manipulator(mgroup, C, event, r_part))) {
+ break;
+ }
}
}
}
@@ -891,7 +904,7 @@ void wm_manipulatormap_modal_set(
BLI_assert(mmap->mmap_context.modal == NULL);
wmWindow *win = CTX_wm_window(C);
- WM_manipulatormap_tooltip_clear(C, mmap);
+ WM_tooltip_clear(C, win);
if (mpr->type->invoke &&
(mpr->type->modal || mpr->custom_modal))
@@ -1005,45 +1018,18 @@ void WM_manipulatormap_message_subscribe(
*
* \{ */
-
-void WM_manipulatormap_tooltip_create(
- bContext *C, wmManipulatorMap *mmap)
+struct ARegion *WM_manipulatormap_tooltip_init(
+ struct bContext *C, struct ARegion *ar, bool *r_exit_on_event)
{
- WM_manipulatormap_tooltip_clear(C, mmap);
- if (mmap->mmap_context.highlight) {
- mmap->mmap_context.tooltip = UI_tooltip_create_from_manipulator(C, mmap->mmap_context.highlight);
- }
-}
-
-void WM_manipulatormap_tooltip_clear(
- bContext *C, wmManipulatorMap *mmap)
-{
- if (mmap->mmap_context.tooltip_timer != NULL) {
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win = CTX_wm_window(C);
- WM_event_remove_timer(wm, win, mmap->mmap_context.tooltip_timer);
- mmap->mmap_context.tooltip_timer = NULL;
- }
- if (mmap->mmap_context.tooltip != NULL) {
- UI_tooltip_free(C, mmap->mmap_context.tooltip);
- mmap->mmap_context.tooltip = NULL;
- }
-}
-
-void WM_manipulatormap_tooltip_timer_init(
- bContext *C, wmManipulatorMap *mmap)
-{
- if (mmap->mmap_context.tooltip_timer == NULL) {
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win = CTX_wm_window(C);
- /* TODO: BUTTON_TOOLTIP_DELAY */
- mmap->mmap_context.tooltip_timer = WM_event_add_timer(wm, win, TIMER, UI_TOOLTIP_DELAY);
+ wmManipulatorMap *mmap = ar->manipulator_map;
+ *r_exit_on_event = true;
+ if (mmap) {
+ wmManipulator *mpr = mmap->mmap_context.highlight;
+ if (mpr) {
+ return UI_tooltip_create_from_manipulator(C, mpr);
+ }
}
-}
-
-const void *WM_manipulatormap_tooltip_timer_get(wmManipulatorMap *mmap)
-{
- return mmap->mmap_context.tooltip_timer;
+ return NULL;
}
/** \} */ /* wmManipulatorMapType */