From 18d900caca8317d33216bbc778c07b9f6ce3da84 Mon Sep 17 00:00:00 2001 From: Ankit Meel Date: Wed, 4 Aug 2021 01:22:27 +0530 Subject: macOS: Fix OpenMP dynamic loader error. --- build_files/cmake/platform/platform_apple.cmake | 9 ++++++--- source/creator/CMakeLists.txt | 3 +-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake index 529c01db009..a130d265dff 100644 --- a/build_files/cmake/platform/platform_apple.cmake +++ b/build_files/cmake/platform/platform_apple.cmake @@ -500,14 +500,17 @@ endif() # makesdna, tests, etc.), we add an rpath to the OpenMP library dir through # CMAKE_BUILD_RPATH. This avoids having to make many copies of the dylib next to each binary. # -# For the installed Blender executable, CMAKE_INSTALL_RPATH will be used, but -# needs no changes since it already looks for dylibs next to the executable by -# default (@executable_path). +# For the installed Blender executable, CMAKE_INSTALL_RPATH will be used +# to locate the dylibs at @executable_path, next to the Blender executable. # # For the installed Python module, CMAKE_INSTALL_RPATH is modified to find the # dylib in an adjacent folder. set(CMAKE_SKIP_BUILD_RPATH FALSE) list(APPEND CMAKE_BUILD_RPATH "${OpenMP_LIBRARY_DIR}") + +set(CMAKE_SKIP_INSTALL_RPATH FALSE) +list(APPEND CMAKE_INSTALL_RPATH "@executable_path") + if(WITH_PYTHON_MODULE) list(APPEND CMAKE_INSTALL_RPATH "@loader_path/../Resources/${BLENDER_VERSION}/lib") endif() diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index f7179dfb7e9..e928be571a2 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -349,8 +349,7 @@ elseif(APPLE) set(MAC_BLENDER_TARGET_DYLIBS_DIR "${TARGETDIR_VER}/lib") else() set(TARGETDIR_VER Blender.app/Contents/Resources/${BLENDER_VERSION}) - # Dylibs folder for Blender executable. @executable_path is a default - # rpath, so dropping libraries next to Blender is enough. + # Dylibs folder for Blender executable. @executable_path is an rpath. set(MAC_BLENDER_TARGET_DYLIBS_DIR "$") endif() # Skip relinking on cpack / install -- cgit v1.2.3 From fb87d236edb7e98c5fc526b9829e6bc6b8916828 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Tue, 3 Aug 2021 17:34:14 -0300 Subject: Fix calculation of 'projmat_dimensions' `r_left`, `r_right`, `r_bottom` and `r_top` were ignoring `clip_near` value when in perspective view. Also rename `projmat` to `winmat` in these cases. --- source/blender/blenlib/BLI_math_geom.h | 4 +- source/blender/blenlib/intern/math_geom.c | 64 +++++++++++++++---------------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 9ac14a6edfe..bcda25ca533 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -682,14 +682,14 @@ void planes_from_projmat(const float mat[4][4], float near[4], float far[4]); -void projmat_dimensions(const float projmat[4][4], +void projmat_dimensions(const float winmat[4][4], float *r_left, float *r_right, float *r_bottom, float *r_top, float *r_near, float *r_far); -void projmat_dimensions_db(const float projmat[4][4], +void projmat_dimensions_db(const float winmat[4][4], double *r_left, double *r_right, double *r_bottom, diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 803291e4a3b..823e72a91e5 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -4962,7 +4962,7 @@ void planes_from_projmat(const float mat[4][4], } } -void projmat_dimensions(const float projmat[4][4], +void projmat_dimensions(const float winmat[4][4], float *r_left, float *r_right, float *r_bottom, @@ -4970,27 +4970,27 @@ void projmat_dimensions(const float projmat[4][4], float *r_near, float *r_far) { - bool is_persp = projmat[3][3] == 0.0f; - + const bool is_persp = winmat[3][3] == 0.0f; if (is_persp) { - *r_left = (projmat[2][0] - 1.0f) / projmat[0][0]; - *r_right = (projmat[2][0] + 1.0f) / projmat[0][0]; - *r_bottom = (projmat[2][1] - 1.0f) / projmat[1][1]; - *r_top = (projmat[2][1] + 1.0f) / projmat[1][1]; - *r_near = projmat[3][2] / (projmat[2][2] - 1.0f); - *r_far = projmat[3][2] / (projmat[2][2] + 1.0f); + const float near = winmat[3][2] / (winmat[2][2] - 1.0f); + *r_left = near * ((winmat[2][0] - 1.0f) / winmat[0][0]); + *r_right = near * ((winmat[2][0] + 1.0f) / winmat[0][0]); + *r_bottom = near * ((winmat[2][1] - 1.0f) / winmat[1][1]); + *r_top = near * ((winmat[2][1] + 1.0f) / winmat[1][1]); + *r_near = near; + *r_far = winmat[3][2] / (winmat[2][2] + 1.0f); } else { - *r_left = (-projmat[3][0] - 1.0f) / projmat[0][0]; - *r_right = (-projmat[3][0] + 1.0f) / projmat[0][0]; - *r_bottom = (-projmat[3][1] - 1.0f) / projmat[1][1]; - *r_top = (-projmat[3][1] + 1.0f) / projmat[1][1]; - *r_near = (projmat[3][2] + 1.0f) / projmat[2][2]; - *r_far = (projmat[3][2] - 1.0f) / projmat[2][2]; + *r_left = (-winmat[3][0] - 1.0f) / winmat[0][0]; + *r_right = (-winmat[3][0] + 1.0f) / winmat[0][0]; + *r_bottom = (-winmat[3][1] - 1.0f) / winmat[1][1]; + *r_top = (-winmat[3][1] + 1.0f) / winmat[1][1]; + *r_near = (winmat[3][2] + 1.0f) / winmat[2][2]; + *r_far = (winmat[3][2] - 1.0f) / winmat[2][2]; } } -void projmat_dimensions_db(const float projmat_fl[4][4], +void projmat_dimensions_db(const float winmat_fl[4][4], double *r_left, double *r_right, double *r_bottom, @@ -4998,26 +4998,26 @@ void projmat_dimensions_db(const float projmat_fl[4][4], double *r_near, double *r_far) { - double projmat[4][4]; - copy_m4d_m4(projmat, projmat_fl); - - bool is_persp = projmat[3][3] == 0.0f; + double winmat[4][4]; + copy_m4d_m4(winmat, winmat_fl); + const bool is_persp = winmat[3][3] == 0.0f; if (is_persp) { - *r_left = (projmat[2][0] - 1.0) / projmat[0][0]; - *r_right = (projmat[2][0] + 1.0) / projmat[0][0]; - *r_bottom = (projmat[2][1] - 1.0) / projmat[1][1]; - *r_top = (projmat[2][1] + 1.0) / projmat[1][1]; - *r_near = projmat[3][2] / (projmat[2][2] - 1.0); - *r_far = projmat[3][2] / (projmat[2][2] + 1.0); + const double near = winmat[3][2] / (winmat[2][2] - 1.0); + *r_left = near * ((winmat[2][0] - 1.0) / winmat[0][0]); + *r_right = near * ((winmat[2][0] + 1.0) / winmat[0][0]); + *r_bottom = near * ((winmat[2][1] - 1.0) / winmat[1][1]); + *r_top = near * ((winmat[2][1] + 1.0) / winmat[1][1]); + *r_near = near; + *r_far = winmat[3][2] / (winmat[2][2] + 1.0); } else { - *r_left = (-projmat[3][0] - 1.0) / projmat[0][0]; - *r_right = (-projmat[3][0] + 1.0) / projmat[0][0]; - *r_bottom = (-projmat[3][1] - 1.0) / projmat[1][1]; - *r_top = (-projmat[3][1] + 1.0) / projmat[1][1]; - *r_near = (projmat[3][2] + 1.0) / projmat[2][2]; - *r_far = (projmat[3][2] - 1.0) / projmat[2][2]; + *r_left = (-winmat[3][0] - 1.0) / winmat[0][0]; + *r_right = (-winmat[3][0] + 1.0) / winmat[0][0]; + *r_bottom = (-winmat[3][1] - 1.0) / winmat[1][1]; + *r_top = (-winmat[3][1] + 1.0) / winmat[1][1]; + *r_near = (winmat[3][2] + 1.0) / winmat[2][2]; + *r_far = (winmat[3][2] - 1.0) / winmat[2][2]; } } -- cgit v1.2.3 From 0d2589d08c615d1bc07e5156b41b9ffda6c3ba27 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 4 Aug 2021 10:03:07 +1000 Subject: Cleanup: spelling --- source/blender/blenlib/BLI_array.h | 2 +- .../blender/blenlib/intern/polyfill_2d_beautify.c | 2 +- .../blender/bmesh/tools/bmesh_decimate_collapse.c | 4 ++-- .../compositor/operations/COM_GlareBaseOperation.h | 4 ++-- source/blender/editors/animation/time_scrub_ui.c | 4 ++-- source/blender/editors/mask/mask_select.c | 4 ++-- source/blender/editors/uvedit/uvedit_smart_stitch.c | 2 +- source/blender/io/usd/intern/usd_capi_import.cc | 5 ++--- source/blender/io/usd/intern/usd_reader_material.h | 21 +++++++++++---------- source/blender/io/usd/intern/usd_reader_mesh.cc | 18 +++++++++--------- 10 files changed, 33 insertions(+), 33 deletions(-) diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h index 6bf29a6168f..084f573e8c7 100644 --- a/source/blender/blenlib/BLI_array.h +++ b/source/blender/blenlib/BLI_array.h @@ -156,7 +156,7 @@ void _bli_array_grow_func(void **arr_p, * \{ */ /** - * not part of the 'API' but handy funcs, + * Not part of the 'API' but handy functions, * same purpose as #BLI_array_staticdeclare() * but use when the max size is known ahead of time */ #define BLI_array_fixedstack_declare(arr, maxstatic, realsize, allocstr) \ diff --git a/source/blender/blenlib/intern/polyfill_2d_beautify.c b/source/blender/blenlib/intern/polyfill_2d_beautify.c index 7781e3a0f6f..ed07b002e32 100644 --- a/source/blender/blenlib/intern/polyfill_2d_beautify.c +++ b/source/blender/blenlib/intern/polyfill_2d_beautify.c @@ -25,7 +25,7 @@ * on a simple polygon representation where we _know_: * * - The polygon is primitive with no holes with a continuous boundary. - * - Tris have consistent winding. + * - Triangles have consistent winding. * - 2d (saves some hassles projecting face pairs on an axis for every edge-rotation) * also saves us having to store all previous edge-states (see #EdRotState in bmesh_beautify.c) * diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index 20b6903b239..97fccbe01fd 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -935,9 +935,9 @@ static bool bm_edge_collapse_is_degenerate_topology(BMEdge *e_first) } /** - * special, highly limited edge collapse function + * Special, highly limited edge collapse function * intended for speed over flexibility. - * can only collapse edges connected to (1, 2) tris. + * can only collapse edges connected to (1, 2) triangles. * * Important - don't add vert/edge/face data on collapsing! * diff --git a/source/blender/compositor/operations/COM_GlareBaseOperation.h b/source/blender/compositor/operations/COM_GlareBaseOperation.h index 50db4e02940..6dac6f5ecc7 100644 --- a/source/blender/compositor/operations/COM_GlareBaseOperation.h +++ b/source/blender/compositor/operations/COM_GlareBaseOperation.h @@ -23,8 +23,8 @@ namespace blender::compositor { -/* utility functions used by glare, tonemap and lens distortion */ -/* soms macros for color handling */ +/* Utility functions used by glare, tone-map and lens distortion. */ +/* Some macros for color handling. */ typedef float fRGB[4]; /* TODO: replace with BLI_math_vector. */ diff --git a/source/blender/editors/animation/time_scrub_ui.c b/source/blender/editors/animation/time_scrub_ui.c index 182e61e53b6..8aeb6a57124 100644 --- a/source/blender/editors/animation/time_scrub_ui.c +++ b/source/blender/editors/animation/time_scrub_ui.c @@ -244,8 +244,8 @@ void ED_time_scrub_channel_search_draw(const bContext *C, ARegion *region, bDope UI_block_align_end(block); UI_block_layout_resolve(block, NULL, NULL); - /* Make sure the events are consumed from the search and dont reach other UI blocks since this is - * drawn on top of animchannels. */ + /* Make sure the events are consumed from the search and don't reach other UI blocks since this + * is drawn on top of animation-channels. */ UI_block_flag_enable(block, UI_BLOCK_CLIP_EVENTS); UI_block_bounds_set_normal(block, 0); UI_block_end(C, block); diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index 3bb05a27c54..8ddc3758e4e 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -164,8 +164,8 @@ void ED_mask_select_flush_all(Mask *mask) LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) { spline->flag &= ~SELECT; - /* intentionally _dont_ do this in the mask layer loop - * so we clear flags on all splines */ + /* Intentionally *don't* do this in the mask layer loop + * so we clear flags on all splines. */ if (mask_layer->restrictflag & MASK_RESTRICT_VIEW) { continue; } diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index 535a0e00347..1bcd1fad9d6 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -1769,7 +1769,7 @@ static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void GPU_blend(GPU_BLEND_ALPHA); - /* Static Tris */ + /* Static Triangles. */ if (stitch_preview->static_tris) { UI_GetThemeColor4fv(TH_STITCH_PREVIEW_ACTIVE, col); vbo = GPU_vertbuf_create_with_format(&format); diff --git a/source/blender/io/usd/intern/usd_capi_import.cc b/source/blender/io/usd/intern/usd_capi_import.cc index 8255fca284c..789ff20ba82 100644 --- a/source/blender/io/usd/intern/usd_capi_import.cc +++ b/source/blender/io/usd/intern/usd_capi_import.cc @@ -365,8 +365,7 @@ bool USD_import(struct bContext *C, { blender::io::usd::ensure_usd_plugin_path_registered(); - /* Using new here since MEM_* funcs do not call ctor to properly initialize - * data. */ + /* Using new here since `MEM_*` functions do not call constructor to properly initialize data. */ ImportJobData *job = new ImportJobData(); job->bmain = CTX_data_main(C); job->scene = CTX_data_scene(C); @@ -496,7 +495,7 @@ CacheReader *CacheReader_open_usd_object(CacheArchiveHandle *handle, USDPrimReader *usd_reader = archive->create_reader(prim); if (usd_reader == nullptr) { - /* This object is not supported */ + /* This object is not supported. */ return nullptr; } usd_reader->object(object); diff --git a/source/blender/io/usd/intern/usd_reader_material.h b/source/blender/io/usd/intern/usd_reader_material.h index 3e8fc675931..a17504bd590 100644 --- a/source/blender/io/usd/intern/usd_reader_material.h +++ b/source/blender/io/usd/intern/usd_reader_material.h @@ -55,28 +55,29 @@ struct NodePlacementContext { /* Converts USD materials to Blender representation. */ -/* By default, the USDMaterialReader creates a Blender material with +/** + By default, the #USDMaterialReader creates a Blender material with * the same name as the USD material. If the USD material has a - * UsdPreviewSurface source, the Blender material's viewport display + * #UsdPreviewSurface source, the Blender material's viewport display * color, roughness and metallic properties are set to the corresponding - * UsdPreoviewSurface inputs. + * #UsdPreoviewSurface inputs. * * If the Import USD Preview option is enabled, the current implementation - * converts UsdPreviewSurface to Blender nodes as follows: + * converts #UsdPreviewSurface to Blender nodes as follows: * - * UsdPreviewSurface -> Pricipled BSDF - * UsdUVTexture -> Texture Image + Normal Map - * UsdPrimvarReader_float2 -> UV Map + * - #UsdPreviewSurface -> Principled BSDF + * - #UsdUVTexture -> Texture Image + Normal Map + * - UsdPrimvarReader_float2 -> UV Map * * Limitations: arbitrary primvar readers or UsdTransform2d not yet - * supported. For UsdUVTexture, only the file, st and sourceColorSpace + * supported. For #UsdUVTexture, only the file, st and #sourceColorSpace * inputs are handled. * * TODO(makowalski): Investigate adding support for converting additional * shaders and inputs. Supporting certain types of inputs, such as texture * scale and bias, will probably require creating Blender Group nodes with - * the corresponding inputs. */ - + * the corresponding inputs. + */ class USDMaterialReader { protected: USDImportParams params_; diff --git a/source/blender/io/usd/intern/usd_reader_mesh.cc b/source/blender/io/usd/intern/usd_reader_mesh.cc index f13da4680e2..9c75bc8afae 100644 --- a/source/blender/io/usd/intern/usd_reader_mesh.cc +++ b/source/blender/io/usd/intern/usd_reader_mesh.cc @@ -61,7 +61,7 @@ static const pxr::TfToken normalsPrimvar("normals", pxr::TfToken::Immortal); } // namespace usdtokens namespace utils { -/* Very similar to abc mesh utils. */ +/* Very similar to #blender::io::alembic::utils. */ static void build_mat_map(const Main *bmain, std::map *r_mat_map) { if (r_mat_map == nullptr) { @@ -71,7 +71,7 @@ static void build_mat_map(const Main *bmain, std::map * Material *material = static_cast(bmain->materials.first); for (; material; material = static_cast(material->id.next)) { - /* We have to do this because the stored material name is coming directly from usd. */ + /* We have to do this because the stored material name is coming directly from USD. */ (*r_mat_map)[pxr::TfMakeValidIdentifier(material->id.name + 2)] = material; } } @@ -212,7 +212,7 @@ void USDMeshReader::read_object_data(Main *bmain, const double motionSampleTime) is_initial_load_ = false; if (read_mesh != mesh) { - /* XXX fixme after 2.80; mesh->flag isn't copied by BKE_mesh_nomain_to_mesh() */ + /* FIXME: after 2.80; `mesh->flag` isn't copied by #BKE_mesh_nomain_to_mesh() */ /* read_mesh can be freed by BKE_mesh_nomain_to_mesh(), so get the flag before that happens. */ short autosmooth = (read_mesh->flag & ME_AUTOSMOOTH); BKE_mesh_nomain_to_mesh(read_mesh, mesh, object_, &CD_MASK_MESH, true); @@ -334,7 +334,7 @@ void USDMeshReader::read_uvs(Mesh *mesh, const double motionSampleTime, const bo pxr::TfToken uv_token; - /* If first time seeing uv token, store in map of uid, TfToken> */ + /* If first time seeing uv token, store in map of `uid, TfToken>`. */ if (uv_token_map_.find(layer_name) == uv_token_map_.end()) { uv_token = pxr::TfToken(layer_name); uv_token_map_.insert(std::make_pair(layer_name, uv_token)); @@ -347,7 +347,7 @@ void USDMeshReader::read_uvs(Mesh *mesh, const double motionSampleTime, const bo if (uv_token.IsEmpty()) { continue; } - /* Early out if not first load and uvs arent animated. */ + /* Early out if not first load and UVs aren't animated. */ if (!load_uvs && primvar_varying_map_.find(uv_token) != primvar_varying_map_.end() && !primvar_varying_map_.at(uv_token)) { continue; @@ -630,7 +630,7 @@ void USDMeshReader::read_mesh_sample(ImportSettings *settings, const bool new_mesh) { /* Note that for new meshes we always want to read verts and polys, - * regradless of the value of the read_flag, to avoid a crash downstream + * regardless of the value of the read_flag, to avoid a crash downstream * in code that expect this data to be there. */ if (new_mesh || (settings->read_flag & MOD_MESHSEQ_READ_VERT) != 0) { @@ -684,7 +684,7 @@ void USDMeshReader::assign_facesets_to_mpoly(double motionSampleTime, } /* Find the geom subsets that have bound materials. - * We don't call pxr::UsdShadeMaterialBindingAPI::GetMaterialBindSubsets() + * We don't call #pxr::UsdShadeMaterialBindingAPI::GetMaterialBindSubsets() * because this function returns only those subsets that are in the 'materialBind' * family, but, in practice, applications (like Houdini) might export subsets * in different families that are bound to materials. @@ -780,7 +780,7 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh, bool is_uv = false; - /* Assume all uvs are stored in one of these primvar types */ + /* Assume all UVs are stored in one of these primvar types */ if (type == pxr::SdfValueTypeNames->TexCoord2hArray || type == pxr::SdfValueTypeNames->TexCoord2fArray || type == pxr::SdfValueTypeNames->TexCoord2dArray) { @@ -817,7 +817,7 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh, Mesh *active_mesh = existing_mesh; bool new_mesh = false; - /* TODO(makowalski): inmplement the optimization of only updating the mesh points when + /* TODO(makowalski): implement the optimization of only updating the mesh points when * the topology is consistent, as in the Alembic importer. */ ImportSettings settings; -- cgit v1.2.3 From 8a1c1279b3d9c5478d7e94c4875c141db750fbcb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 4 Aug 2021 11:03:23 +1000 Subject: Icons: update alert icon script Missed from c549d736cff0d5013f05fb5240ef07671c5aa5ce. --- release/datafiles/alert_icons_update.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/release/datafiles/alert_icons_update.py b/release/datafiles/alert_icons_update.py index dba96c2126a..95e4ee7afbb 100644 --- a/release/datafiles/alert_icons_update.py +++ b/release/datafiles/alert_icons_update.py @@ -10,7 +10,7 @@ BASEDIR = os.path.abspath(os.path.dirname(__file__)) inkscape_path = 'inkscape' if sys.platform == 'darwin': - inkscape_app_path = '/Applications/Inkscape.app/Contents/Resources/script' + inkscape_app_path = '/Applications/Inkscape.app/Contents/MacOS/inkscape' if os.path.exists(inkscape_app_path): inkscape_path = inkscape_app_path @@ -19,7 +19,7 @@ cmd = ( os.path.join(BASEDIR, "alert_icons.svg"), "--export-width=1280", "--export-height=256", - "--without-gui", - "--export-png=" + os.path.join(BASEDIR, "alert_icons.png"), + "--export-type=png", + "--export-filename=" + os.path.join(BASEDIR, "alert_icons.png"), ) subprocess.check_call(cmd) -- cgit v1.2.3 From 7389fd9a35a3c8911f2d502ea2c745d574a2de21 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 4 Aug 2021 11:31:28 +1000 Subject: Icons: resolve various issues for generating icons - INKSCAPE_BIN environment variable was ignored by alert_icons_update & prvicons_update. - `make icons` wasn't regenerating alert icons. - Updating SVG icons failed using blender built with ASAN. --- GNUmakefile | 4 +++- release/datafiles/alert_icons_update.py | 6 +++--- release/datafiles/blender_icons_geom_update.py | 12 ++++++++---- release/datafiles/blender_icons_update.py | 16 ++++++++++------ release/datafiles/prvicons_update.py | 6 +++--- 5 files changed, 27 insertions(+), 17 deletions(-) mode change 100644 => 100755 release/datafiles/alert_icons_update.py diff --git a/GNUmakefile b/GNUmakefile index 7df561ed34f..635cc321d03 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -528,8 +528,10 @@ INKSCAPE_BIN?="inkscape" icons: .FORCE BLENDER_BIN=$(BLENDER_BIN) INKSCAPE_BIN=$(INKSCAPE_BIN) \ "$(BLENDER_DIR)/release/datafiles/blender_icons_update.py" - BLENDER_BIN=$(BLENDER_BIN) INKSCAPE_BIN=$(INKSCAPE_BIN) \ + INKSCAPE_BIN=$(INKSCAPE_BIN) \ "$(BLENDER_DIR)/release/datafiles/prvicons_update.py" + INKSCAPE_BIN=$(INKSCAPE_BIN) \ + "$(BLENDER_DIR)/release/datafiles/alert_icons_update.py" icons_geom: .FORCE BLENDER_BIN=$(BLENDER_BIN) \ diff --git a/release/datafiles/alert_icons_update.py b/release/datafiles/alert_icons_update.py old mode 100644 new mode 100755 index 95e4ee7afbb..a3951c114ae --- a/release/datafiles/alert_icons_update.py +++ b/release/datafiles/alert_icons_update.py @@ -7,15 +7,15 @@ import sys BASEDIR = os.path.abspath(os.path.dirname(__file__)) -inkscape_path = 'inkscape' +inkscape_bin = os.environ.get("INKSCAPE_BIN", "inkscape") if sys.platform == 'darwin': inkscape_app_path = '/Applications/Inkscape.app/Contents/MacOS/inkscape' if os.path.exists(inkscape_app_path): - inkscape_path = inkscape_app_path + inkscape_bin = inkscape_app_path cmd = ( - inkscape_path, + inkscape_bin, os.path.join(BASEDIR, "alert_icons.svg"), "--export-width=1280", "--export-height=256", diff --git a/release/datafiles/blender_icons_geom_update.py b/release/datafiles/blender_icons_geom_update.py index 5b95961ae6b..d5373d6b2e9 100755 --- a/release/datafiles/blender_icons_geom_update.py +++ b/release/datafiles/blender_icons_geom_update.py @@ -6,10 +6,9 @@ import subprocess import sys -def run(cmd): +def run(cmd, *, env=None): print(" ", " ".join(cmd)) - # Don't use check_call because asan causes nonzero exitcode :S - subprocess.call(cmd) + subprocess.check_call(cmd, env=env) def edit_text_file(filename, marker_begin, marker_end, content): @@ -73,7 +72,12 @@ for blend in icons_blend: "--group", "Export", "--output-dir", output_dir, ) - run(cmd) + + env = {} + # Developers may have ASAN enabled, avoid non-zero exit codes. + env["ASAN_OPTIONS"] = "exitcode=0:" + os.environ.get("ASAN_OPTIONS", "") + + run(cmd, env=env) files_new = set(names_and_time_from_path(output_dir)) icon_files.extend([ diff --git a/release/datafiles/blender_icons_update.py b/release/datafiles/blender_icons_update.py index 8167b8b25e6..ead74aac759 100755 --- a/release/datafiles/blender_icons_update.py +++ b/release/datafiles/blender_icons_update.py @@ -6,13 +6,17 @@ import subprocess import sys -def run(cmd): +def run(cmd, *, env=None): print(" ", " ".join(cmd)) - subprocess.check_call(cmd) + subprocess.check_call(cmd, env=env) BASEDIR = os.path.abspath(os.path.dirname(__file__)) +env = {} +# Developers may have ASAN enabled, avoid non-zero exit codes. +env["ASAN_OPTIONS"] = "exitcode=0:" + os.environ.get("ASAN_OPTIONS", "") + inkscape_bin = os.environ.get("INKSCAPE_BIN", "inkscape") blender_bin = os.environ.get("BLENDER_BIN", "blender") @@ -32,7 +36,7 @@ cmd = ( "--export-type=png", "--export-filename=" + os.path.join(BASEDIR, "blender_icons16.png"), ) -run(cmd) +run(cmd, env=env) cmd = ( inkscape_bin, @@ -42,7 +46,7 @@ cmd = ( "--export-type=png", "--export-filename=" + os.path.join(BASEDIR, "blender_icons32.png"), ) -run(cmd) +run(cmd, env=env) # For testing it can be good to clear all old @@ -64,7 +68,7 @@ cmd = ( "--minx_icon", "2", "--maxx_icon", "2", "--miny_icon", "2", "--maxy_icon", "2", "--spacex_icon", "1", "--spacey_icon", "1", ) -run(cmd) +run(cmd, env=env) cmd = ( blender_bin, "--background", "--factory-startup", "-noaudio", @@ -78,7 +82,7 @@ cmd = ( "--minx_icon", "4", "--maxx_icon", "4", "--miny_icon", "4", "--maxy_icon", "4", "--spacex_icon", "2", "--spacey_icon", "2", ) -run(cmd) +run(cmd, env=env) os.remove(os.path.join(BASEDIR, "blender_icons16.png")) os.remove(os.path.join(BASEDIR, "blender_icons32.png")) diff --git a/release/datafiles/prvicons_update.py b/release/datafiles/prvicons_update.py index fa526f88e96..c9bd8b44301 100755 --- a/release/datafiles/prvicons_update.py +++ b/release/datafiles/prvicons_update.py @@ -7,15 +7,15 @@ import sys BASEDIR = os.path.abspath(os.path.dirname(__file__)) -inkscape_path = 'inkscape' +inkscape_bin = os.environ.get("INKSCAPE_BIN", "inkscape") if sys.platform == 'darwin': inkscape_app_path = '/Applications/Inkscape.app/Contents/MacOS/inkscape' if os.path.exists(inkscape_app_path): - inkscape_path = inkscape_app_path + inkscape_bin = inkscape_app_path cmd = ( - inkscape_path, + inkscape_bin, os.path.join(BASEDIR, "prvicons.svg"), "--export-width=1792", "--export-height=256", -- cgit v1.2.3 From 71dc134f8908cda02a3e5e5800bb9da966c10ad2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 4 Aug 2021 11:43:56 +1000 Subject: Icons: add license headers to utilities --- release/datafiles/alert_icons_update.py | 20 ++++++++++++++++++ release/datafiles/blender_icons_geom_update.py | 20 ++++++++++++++++++ release/datafiles/blender_icons_update.py | 20 ++++++++++++++++++ release/datafiles/ctodata.py | 28 ++++++++++++-------------- release/datafiles/prvicons_update.py | 20 ++++++++++++++++++ 5 files changed, 93 insertions(+), 15 deletions(-) diff --git a/release/datafiles/alert_icons_update.py b/release/datafiles/alert_icons_update.py index a3951c114ae..34a2798a18c 100755 --- a/release/datafiles/alert_icons_update.py +++ b/release/datafiles/alert_icons_update.py @@ -1,5 +1,25 @@ #!/usr/bin/env python3 +# ##### 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 ##### + +# + # This script updates icons from the SVG file import os import subprocess diff --git a/release/datafiles/blender_icons_geom_update.py b/release/datafiles/blender_icons_geom_update.py index d5373d6b2e9..df4683809db 100755 --- a/release/datafiles/blender_icons_geom_update.py +++ b/release/datafiles/blender_icons_geom_update.py @@ -1,5 +1,25 @@ #!/usr/bin/env python3 +# ##### 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 ##### + +# + # This script updates icons from the BLEND file import os import subprocess diff --git a/release/datafiles/blender_icons_update.py b/release/datafiles/blender_icons_update.py index ead74aac759..dab3cd76a87 100755 --- a/release/datafiles/blender_icons_update.py +++ b/release/datafiles/blender_icons_update.py @@ -1,5 +1,25 @@ #!/usr/bin/env python3 +# ##### 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 ##### + +# + # This script updates icons from the SVG file import os import subprocess diff --git a/release/datafiles/ctodata.py b/release/datafiles/ctodata.py index 0471faad565..20f119c4264 100755 --- a/release/datafiles/ctodata.py +++ b/release/datafiles/ctodata.py @@ -1,27 +1,25 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# ***** BEGIN GPL LICENSE BLOCK ***** +# ##### 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 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. +# 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. +# 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) 2009 Blender Foundation. # All rights reserved. # -# ***** END GPL LICENCE BLOCK ***** - +# ##### END GPL LICENSE BLOCK ##### # diff --git a/release/datafiles/prvicons_update.py b/release/datafiles/prvicons_update.py index c9bd8b44301..ad42ede9772 100755 --- a/release/datafiles/prvicons_update.py +++ b/release/datafiles/prvicons_update.py @@ -1,5 +1,25 @@ #!/usr/bin/env python3 +# ##### 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 ##### + +# + # This script updates icons from the SVG file import os import subprocess -- cgit v1.2.3 From 5950b3ab739f0d57cdac44c57d4448c0a5dbebb2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 4 Aug 2021 12:43:07 +1000 Subject: Cleanup: de-duplicate ID renaming utility for versioning --- source/blender/blenloader/intern/versioning_280.c | 53 +++++--------------- .../blender/blenloader/intern/versioning_common.cc | 37 ++++++++++++++ .../blender/blenloader/intern/versioning_common.h | 6 +++ .../blenloader/intern/versioning_defaults.c | 57 ++++++---------------- 4 files changed, 71 insertions(+), 82 deletions(-) diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index af05c4b902f..93959237f29 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -111,40 +111,13 @@ #include "BLO_readfile.h" #include "readfile.h" +#include "versioning_common.h" + #include "MEM_guardedalloc.h" /* Make preferences read-only, use versioning_userdef.c. */ #define U (*((const UserDef *)&U)) -/** - * Rename if the ID doesn't exist. - */ -static ID *rename_id_for_versioning(Main *bmain, - const short id_type, - const char *name_src, - const char *name_dst) -{ - /* We can ignore libraries */ - ListBase *lb = which_libbase(bmain, id_type); - ID *id = NULL; - LISTBASE_FOREACH (ID *, idtest, lb) { - if (idtest->lib == NULL) { - if (STREQ(idtest->name + 2, name_src)) { - id = idtest; - } - if (STREQ(idtest->name + 2, name_dst)) { - return NULL; - } - } - } - if (id != NULL) { - BLI_strncpy(id->name + 2, name_dst, sizeof(id->name) - 2); - /* We know it's unique, this just sorts. */ - BLI_libblock_ensure_unique_name(bmain, id->name); - } - return id; -} - static bScreen *screen_parent_find(const bScreen *screen) { /* Can avoid lookup if screen state isn't maximized/full @@ -1679,32 +1652,32 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) Brush *brush; Material *ma; /* Pen Soft brush. */ - brush = (Brush *)rename_id_for_versioning(bmain, ID_BR, "Draw Soft", "Pencil Soft"); + brush = (Brush *)do_versions_rename_id(bmain, ID_BR, "Draw Soft", "Pencil Soft"); if (brush) { brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PEN; } - rename_id_for_versioning(bmain, ID_BR, "Draw Pencil", "Pencil"); - rename_id_for_versioning(bmain, ID_BR, "Draw Pen", "Pen"); - rename_id_for_versioning(bmain, ID_BR, "Draw Ink", "Ink Pen"); - rename_id_for_versioning(bmain, ID_BR, "Draw Noise", "Ink Pen Rough"); - rename_id_for_versioning(bmain, ID_BR, "Draw Marker", "Marker Bold"); - rename_id_for_versioning(bmain, ID_BR, "Draw Block", "Marker Chisel"); + do_versions_rename_id(bmain, ID_BR, "Draw Pencil", "Pencil"); + do_versions_rename_id(bmain, ID_BR, "Draw Pen", "Pen"); + do_versions_rename_id(bmain, ID_BR, "Draw Ink", "Ink Pen"); + do_versions_rename_id(bmain, ID_BR, "Draw Noise", "Ink Pen Rough"); + do_versions_rename_id(bmain, ID_BR, "Draw Marker", "Marker Bold"); + do_versions_rename_id(bmain, ID_BR, "Draw Block", "Marker Chisel"); ma = BLI_findstring(&bmain->materials, "Black", offsetof(ID, name) + 2); if (ma && ma->gp_style) { - rename_id_for_versioning(bmain, ID_MA, "Black", "Solid Stroke"); + do_versions_rename_id(bmain, ID_MA, "Black", "Solid Stroke"); } ma = BLI_findstring(&bmain->materials, "Red", offsetof(ID, name) + 2); if (ma && ma->gp_style) { - rename_id_for_versioning(bmain, ID_MA, "Red", "Squares Stroke"); + do_versions_rename_id(bmain, ID_MA, "Red", "Squares Stroke"); } ma = BLI_findstring(&bmain->materials, "Grey", offsetof(ID, name) + 2); if (ma && ma->gp_style) { - rename_id_for_versioning(bmain, ID_MA, "Grey", "Solid Fill"); + do_versions_rename_id(bmain, ID_MA, "Grey", "Solid Fill"); } ma = BLI_findstring(&bmain->materials, "Black Dots", offsetof(ID, name) + 2); if (ma && ma->gp_style) { - rename_id_for_versioning(bmain, ID_MA, "Black Dots", "Dots Stroke"); + do_versions_rename_id(bmain, ID_MA, "Black Dots", "Dots Stroke"); } brush = BLI_findstring(&bmain->brushes, "Pencil", offsetof(ID, name) + 2); diff --git a/source/blender/blenloader/intern/versioning_common.cc b/source/blender/blenloader/intern/versioning_common.cc index f5083b8e259..208c02b60d1 100644 --- a/source/blender/blenloader/intern/versioning_common.cc +++ b/source/blender/blenloader/intern/versioning_common.cc @@ -20,9 +20,15 @@ /* allow readfile to use deprecated functionality */ #define DNA_DEPRECATED_ALLOW +#include + #include "DNA_screen_types.h" #include "BLI_listbase.h" +#include "BLI_string.h" + +#include "BKE_lib_id.h" +#include "BKE_main.h" #include "MEM_guardedalloc.h" @@ -48,3 +54,34 @@ ARegion *do_versions_add_region_if_not_found(ListBase *regionbase, BLI_insertlinkafter(regionbase, link_after_region, new_region); return new_region; } + +/** + * Rename if the ID doesn't exist. + * + * \return the ID (if found). + */ +ID *do_versions_rename_id(Main *bmain, + const short id_type, + const char *name_src, + const char *name_dst) +{ + /* We can ignore libraries */ + ListBase *lb = which_libbase(bmain, id_type); + ID *id = nullptr; + LISTBASE_FOREACH (ID *, idtest, lb) { + if (idtest->lib == nullptr) { + if (STREQ(idtest->name + 2, name_src)) { + id = idtest; + } + if (STREQ(idtest->name + 2, name_dst)) { + return nullptr; + } + } + } + if (id != nullptr) { + BLI_strncpy(id->name + 2, name_dst, sizeof(id->name) - 2); + /* We know it's unique, this just sorts. */ + BLI_libblock_ensure_unique_name(bmain, id->name); + } + return id; +} diff --git a/source/blender/blenloader/intern/versioning_common.h b/source/blender/blenloader/intern/versioning_common.h index a1769d4639e..47e0b74a3e4 100644 --- a/source/blender/blenloader/intern/versioning_common.h +++ b/source/blender/blenloader/intern/versioning_common.h @@ -22,6 +22,7 @@ struct ARegion; struct ListBase; +struct Main; #ifdef __cplusplus extern "C" { @@ -32,6 +33,11 @@ struct ARegion *do_versions_add_region_if_not_found(struct ListBase *regionbase, const char *name, int link_after_region_type); +ID *do_versions_rename_id(Main *bmain, + const short id_type, + const char *name_src, + const char *name_dst); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index 8362e001ea6..7ff624b44da 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -65,38 +65,11 @@ #include "BLO_readfile.h" +#include "versioning_common.h" + /* Make preferences read-only, use versioning_userdef.c. */ #define U (*((const UserDef *)&U)) -/** - * Rename if the ID doesn't exist. - */ -static ID *rename_id_for_versioning(Main *bmain, - const short id_type, - const char *name_src, - const char *name_dst) -{ - /* We can ignore libraries */ - ListBase *lb = which_libbase(bmain, id_type); - ID *id = NULL; - LISTBASE_FOREACH (ID *, idtest, lb) { - if (idtest->lib == NULL) { - if (STREQ(idtest->name + 2, name_src)) { - id = idtest; - } - if (STREQ(idtest->name + 2, name_dst)) { - return NULL; - } - } - } - if (id != NULL) { - BLI_strncpy(id->name + 2, name_dst, sizeof(id->name) - 2); - /* We know it's unique, this just sorts. */ - BLI_libblock_ensure_unique_name(bmain, id->name); - } - return id; -} - static bool blo_is_builtin_template(const char *app_template) { /* For all builtin templates shipped with Blender. */ @@ -406,28 +379,28 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) Brush *brush; /* Pencil brush. */ - rename_id_for_versioning(bmain, ID_BR, "Draw Pencil", "Pencil"); + do_versions_rename_id(bmain, ID_BR, "Draw Pencil", "Pencil"); /* Pen brush. */ - rename_id_for_versioning(bmain, ID_BR, "Draw Pen", "Pen"); + do_versions_rename_id(bmain, ID_BR, "Draw Pen", "Pen"); /* Pen Soft brush. */ - brush = (Brush *)rename_id_for_versioning(bmain, ID_BR, "Draw Soft", "Pencil Soft"); + brush = (Brush *)do_versions_rename_id(bmain, ID_BR, "Draw Soft", "Pencil Soft"); if (brush) { brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PEN; } /* Ink Pen brush. */ - rename_id_for_versioning(bmain, ID_BR, "Draw Ink", "Ink Pen"); + do_versions_rename_id(bmain, ID_BR, "Draw Ink", "Ink Pen"); /* Ink Pen Rough brush. */ - rename_id_for_versioning(bmain, ID_BR, "Draw Noise", "Ink Pen Rough"); + do_versions_rename_id(bmain, ID_BR, "Draw Noise", "Ink Pen Rough"); /* Marker Bold brush. */ - rename_id_for_versioning(bmain, ID_BR, "Draw Marker", "Marker Bold"); + do_versions_rename_id(bmain, ID_BR, "Draw Marker", "Marker Bold"); /* Marker Chisel brush. */ - rename_id_for_versioning(bmain, ID_BR, "Draw Block", "Marker Chisel"); + do_versions_rename_id(bmain, ID_BR, "Draw Block", "Marker Chisel"); /* Remove useless Fill Area.001 brush. */ brush = BLI_findstring(&bmain->brushes, "Fill Area.001", offsetof(ID, name) + 2); @@ -438,10 +411,10 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) /* Rename and fix materials and enable default object lights on. */ if (app_template && STREQ(app_template, "2D_Animation")) { Material *ma = NULL; - rename_id_for_versioning(bmain, ID_MA, "Black", "Solid Stroke"); - rename_id_for_versioning(bmain, ID_MA, "Red", "Squares Stroke"); - rename_id_for_versioning(bmain, ID_MA, "Grey", "Solid Fill"); - rename_id_for_versioning(bmain, ID_MA, "Black Dots", "Dots Stroke"); + do_versions_rename_id(bmain, ID_MA, "Black", "Solid Stroke"); + do_versions_rename_id(bmain, ID_MA, "Red", "Squares Stroke"); + do_versions_rename_id(bmain, ID_MA, "Grey", "Solid Fill"); + do_versions_rename_id(bmain, ID_MA, "Black Dots", "Dots Stroke"); /* Dots Stroke. */ ma = BLI_findstring(&bmain->materials, "Dots Stroke", offsetof(ID, name) + 2); @@ -553,8 +526,8 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) } /* Objects */ - rename_id_for_versioning(bmain, ID_OB, "Lamp", "Light"); - rename_id_for_versioning(bmain, ID_LA, "Lamp", "Light"); + do_versions_rename_id(bmain, ID_OB, "Lamp", "Light"); + do_versions_rename_id(bmain, ID_LA, "Lamp", "Light"); if (app_template && STREQ(app_template, "2D_Animation")) { for (Object *object = bmain->objects.first; object; object = object->id.next) { -- cgit v1.2.3 From 26f1a5e2c8d705443ab51a608b5721b8f0178de3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 4 Aug 2021 12:57:20 +1000 Subject: Fix T90417: font loading creates duplicate ID names Also repair any errors in existing files. Error from e0dd3fe5872ba37ff188e292b80b46fcf8df413c. --- source/blender/blenkernel/BKE_blender_version.h | 2 +- source/blender/blenkernel/intern/font.c | 8 ++------ source/blender/blenloader/intern/versioning_300.c | 5 +++++ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index e76e3ed8fe0..0d5835a5eed 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -39,7 +39,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 15 +#define BLENDER_FILE_SUBVERSION 16 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index d0b9aeefa55..37fc14911fe 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -337,13 +337,9 @@ VFont *BKE_vfont_load(Main *bmain, const char *filepath) vfd = BLI_vfontdata_from_freetypefont(pf); if (vfd) { - vfont = BKE_libblock_alloc(bmain, ID_VF, filename, 0); + /* If there's a font name, use it for the ID name. */ + vfont = BKE_libblock_alloc(bmain, ID_VF, vfd->name[0] ? vfd->name : filename, 0); vfont->data = vfd; - - /* if there's a font name, use it for the ID name */ - if (vfd->name[0] != '\0') { - BLI_strncpy(vfont->id.name + 2, vfd->name, sizeof(vfont->id.name) - 2); - } BLI_strncpy(vfont->filepath, filepath, sizeof(vfont->filepath)); /* if autopack is on store the packedfile in de font structure */ diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c index 9aec18ea279..7b5f95408ea 100644 --- a/source/blender/blenloader/intern/versioning_300.c +++ b/source/blender/blenloader/intern/versioning_300.c @@ -691,6 +691,11 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) } } + if (!MAIN_VERSION_ATLEAST(bmain, 300, 16)) { + ListBase *lb = which_libbase(bmain, ID_VF); + BKE_main_id_repair_duplicate_names_listbase(lb); + } + /** * Versioning code until next subversion bump goes here. * -- cgit v1.2.3 From 0f455765907528ea9d6c15e9d224d81d507e51ad Mon Sep 17 00:00:00 2001 From: Johnny Matthews Date: Tue, 3 Aug 2021 23:14:03 -0400 Subject: Geometry Nodes: Curve Set Spline Type This node sets the selected (or all) splines in curve to a chosen target spline type. Poly, Bezier, and NURB splines can be converted to any of the other types. This is meant to be a building block node, useful in many procedural situations. In the future the node could be optimized with multi-threading, or by avoiding copying in many cases, either by retrieving the curve for write access or by passing the raw vectors to the new splines where possible. With edits from Hans Goudey (@HooglyBoogly) Differential Revision: https://developer.blender.org/D12013 --- release/scripts/startup/nodeitems_builtins.py | 1 + source/blender/blenkernel/BKE_node.h | 1 + source/blender/blenkernel/intern/node.cc | 1 + source/blender/makesdna/DNA_node_types.h | 11 + source/blender/makesrna/intern/rna_nodetree.c | 17 ++ source/blender/nodes/CMakeLists.txt | 1 + source/blender/nodes/NOD_geometry.h | 1 + source/blender/nodes/NOD_static_types.h | 1 + .../geometry/nodes/node_geo_curve_spline_type.cc | 307 +++++++++++++++++++++ 9 files changed, 341 insertions(+) create mode 100644 source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index 09820291222..03859b04c50 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -510,6 +510,7 @@ geometry_node_categories = [ NodeItem("GeometryNodeCurveTrim"), NodeItem("GeometryNodeCurveLength"), NodeItem("GeometryNodeCurveReverse"), + NodeItem("GeometryNodeCurveSplineType"), NodeItem("GeometryNodeCurveSetHandles"), ]), GeometryNodeCategory("GEO_PRIMITIVES_CURVE", "Curve Primitives", items=[ diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index a1bc6fa505b..084ec20c172 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1475,6 +1475,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define GEO_NODE_CURVE_PRIMITIVE_QUADRILATERAL 1070 #define GEO_NODE_CURVE_TRIM 1071 #define GEO_NODE_CURVE_SET_HANDLES 1072 +#define GEO_NODE_CURVE_SPLINE_TYPE 1073 /** \} */ diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 9888e23a7bd..54bcdf4c92a 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -5149,6 +5149,7 @@ static void registerGeometryNodes() register_node_type_geo_curve_resample(); register_node_type_geo_curve_reverse(); register_node_type_geo_curve_set_handles(); + register_node_type_geo_curve_spline_type(); register_node_type_geo_curve_subdivide(); register_node_type_geo_curve_to_mesh(); register_node_type_geo_curve_to_points(); diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 5152098f57a..4b08aeb2008 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1355,6 +1355,11 @@ typedef struct NodeSwitch { uint8_t input_type; } NodeSwitch; +typedef struct NodeGeometryCurveSplineType { + /* GeometryNodeSplineType. */ + uint8_t spline_type; +} NodeGeometryCurveSplineType; + typedef struct NodeGeometryCurveSetHandles { /* GeometryNodeCurveHandleType. */ uint8_t handle_type; @@ -1828,6 +1833,12 @@ typedef enum GeometryNodeBooleanOperation { GEO_NODE_BOOLEAN_DIFFERENCE = 2, } GeometryNodeBooleanOperation; +typedef enum GeometryNodeSplineType { + GEO_NODE_SPLINE_TYPE_BEZIER = 0, + GEO_NODE_SPLINE_TYPE_NURBS = 1, + GEO_NODE_SPLINE_TYPE_POLY = 2, +} GeometryNodeSplineType; + typedef enum GeometryNodeCurvePrimitiveCircleMode { GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_POINTS = 0, GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_RADIUS = 1 diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 3d4256db335..cd7cbbf76d3 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -9441,6 +9441,23 @@ static void def_geo_attribute_vector_rotate(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } +static void def_geo_curve_spline_type(StructRNA *srna) +{ + static const EnumPropertyItem type_items[] = { + {GEO_NODE_SPLINE_TYPE_BEZIER, "BEZIER", ICON_NONE, "Bezier", "Set the splines to Bezier"}, + {GEO_NODE_SPLINE_TYPE_NURBS, "NURBS", ICON_NONE, "NURBS", "Set the splines to NURBS"}, + {GEO_NODE_SPLINE_TYPE_POLY, "POLY", ICON_NONE, "Poly", "Set the splines to Poly"}, + {0, NULL, 0, NULL, NULL}}; + + PropertyRNA *prop; + RNA_def_struct_sdna_from(srna, "NodeGeometryCurveSplineType", "storage"); + + prop = RNA_def_property(srna, "spline_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "spline_type"); + RNA_def_property_enum_items(prop, type_items); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); +} + static void def_geo_curve_set_handles(StructRNA *srna) { static const EnumPropertyItem type_items[] = { diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 36e5be6a292..7defb36bb83 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -176,6 +176,7 @@ set(SRC geometry/nodes/node_geo_curve_resample.cc geometry/nodes/node_geo_curve_reverse.cc geometry/nodes/node_geo_curve_set_handles.cc + geometry/nodes/node_geo_curve_spline_type.cc geometry/nodes/node_geo_curve_subdivide.cc geometry/nodes/node_geo_curve_to_mesh.cc geometry/nodes/node_geo_curve_to_points.cc diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index 868fcbb33af..c2297796b97 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -63,6 +63,7 @@ void register_node_type_geo_curve_primitive_star(void); void register_node_type_geo_curve_resample(void); void register_node_type_geo_curve_reverse(void); void register_node_type_geo_curve_set_handles(void); +void register_node_type_geo_curve_spline_type(void); void register_node_type_geo_curve_subdivide(void); void register_node_type_geo_curve_to_mesh(void); void register_node_type_geo_curve_to_points(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index a091f28f3a0..b368ac74894 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -303,6 +303,7 @@ DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_STAR, 0, "CURVE_PRIMITIVE_STAR", DefNode(GeometryNode, GEO_NODE_CURVE_RESAMPLE, def_geo_curve_resample, "CURVE_RESAMPLE", CurveResample, "Resample Curve", "") DefNode(GeometryNode, GEO_NODE_CURVE_REVERSE, 0, "CURVE_REVERSE", CurveReverse, "Curve Reverse", "") DefNode(GeometryNode, GEO_NODE_CURVE_SET_HANDLES, def_geo_curve_set_handles, "CURVE_SET_HANDLES", CurveSetHandles, "Set Handle Type", "") +DefNode(GeometryNode, GEO_NODE_CURVE_SPLINE_TYPE, def_geo_curve_spline_type, "CURVE_SPLINE_TYPE", CurveSplineType, "Set Spline Type", "") DefNode(GeometryNode, GEO_NODE_CURVE_SUBDIVIDE, def_geo_curve_subdivide, "CURVE_SUBDIVIDE", CurveSubdivide, "Curve Subdivide", "") DefNode(GeometryNode, GEO_NODE_CURVE_TO_MESH, 0, "CURVE_TO_MESH", CurveToMesh, "Curve to Mesh", "") DefNode(GeometryNode, GEO_NODE_CURVE_TO_POINTS, def_geo_curve_to_points, "CURVE_TO_POINTS", CurveToPoints, "Curve to Points", "") diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc new file mode 100644 index 00000000000..fe3f42625ae --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc @@ -0,0 +1,307 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "BKE_spline.hh" + +#include "BLI_task.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "node_geometry_util.hh" + +static bNodeSocketTemplate geo_node_curve_spline_type_in[] = { + {SOCK_GEOMETRY, N_("Curve")}, + {SOCK_STRING, N_("Selection")}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_curve_spline_type_out[] = { + {SOCK_GEOMETRY, N_("Curve")}, + {-1, ""}, +}; + +static void geo_node_curve_spline_type_layout(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "spline_type", 0, "", ICON_NONE); +} + +namespace blender::nodes { + +static void geo_node_curve_spline_type_init(bNodeTree *UNUSED(tree), bNode *node) +{ + NodeGeometryCurveSplineType *data = (NodeGeometryCurveSplineType *)MEM_callocN( + sizeof(NodeGeometryCurveSplineType), __func__); + + data->spline_type = GEO_NODE_SPLINE_TYPE_POLY; + node->storage = data; +} + +template +static void scale_input_assign(const Span input, + const int scale, + const int offset, + const MutableSpan r_output) +{ + for (const int i : IndexRange(r_output.size())) { + r_output[i] = input[i * scale + offset]; + } +} + +template +static void scale_output_assign(const Span input, + const int scale, + const int offset, + const MutableSpan &r_output) +{ + for (const int i : IndexRange(input.size())) { + r_output[i * scale + offset] = input[i]; + } +} + +template +static void copy_attributes(const Spline &input_spline, Spline &output_spline, CopyFn copy_fn) +{ + input_spline.attributes.foreach_attribute( + [&](StringRefNull name, const AttributeMetaData &meta_data) { + std::optional src = input_spline.attributes.get_for_read(name); + BLI_assert(src); + if (!output_spline.attributes.create(name, meta_data.data_type)) { + BLI_assert_unreachable(); + return false; + } + std::optional dst = output_spline.attributes.get_for_write(name); + if (!dst) { + BLI_assert_unreachable(); + return false; + } + + copy_fn(*src, *dst); + + return true; + }, + ATTR_DOMAIN_POINT); +} + +static SplinePtr convert_to_poly_spline(const Spline &input) +{ + std::unique_ptr output = std::make_unique(); + output->resize(input.positions().size()); + output->positions().copy_from(input.positions()); + output->radii().copy_from(input.radii()); + output->tilts().copy_from(input.tilts()); + Spline::copy_base_settings(input, *output); + output->attributes = input.attributes; + return output; +} + +static SplinePtr poly_to_nurbs(const Spline &input) +{ + std::unique_ptr output = std::make_unique(); + output->resize(input.positions().size()); + output->positions().copy_from(input.positions()); + output->radii().copy_from(input.radii()); + output->tilts().copy_from(input.tilts()); + output->weights().fill(1.0f); + output->set_resolution(12); + output->set_order(4); + Spline::copy_base_settings(input, *output); + output->knots_mode = NURBSpline::KnotsMode::Bezier; + output->attributes = input.attributes; + return output; +} + +static SplinePtr bezier_to_nurbs(const Spline &input) +{ + const BezierSpline &bezier_spline = static_cast(input); + std::unique_ptr output = std::make_unique(); + output->resize(input.size() * 3); + + scale_output_assign(bezier_spline.handle_positions_left(), 3, 0, output->positions()); + scale_output_assign(input.radii(), 3, 0, output->radii()); + scale_output_assign(input.tilts(), 3, 0, output->tilts()); + + scale_output_assign(bezier_spline.positions(), 3, 1, output->positions()); + scale_output_assign(input.radii(), 3, 1, output->radii()); + scale_output_assign(input.tilts(), 3, 1, output->tilts()); + + scale_output_assign(bezier_spline.handle_positions_right(), 3, 2, output->positions()); + scale_output_assign(input.radii(), 3, 2, output->radii()); + scale_output_assign(input.tilts(), 3, 2, output->tilts()); + + Spline::copy_base_settings(input, *output); + output->weights().fill(1.0f); + output->set_resolution(12); + output->set_order(4); + output->set_cyclic(input.is_cyclic()); + output->knots_mode = NURBSpline::KnotsMode::Bezier; + output->attributes.reallocate(output->size()); + copy_attributes(input, *output, [](GSpan src, GMutableSpan dst) { + attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { + using T = decltype(dummy); + scale_output_assign(src.typed(), 3, 0, dst.typed()); + scale_output_assign(src.typed(), 3, 1, dst.typed()); + scale_output_assign(src.typed(), 3, 2, dst.typed()); + }); + }); + return output; +} + +static SplinePtr poly_to_bezier(const Spline &input) +{ + std::unique_ptr output = std::make_unique(); + output->resize(input.size()); + output->positions().copy_from(input.positions()); + output->radii().copy_from(input.radii()); + output->tilts().copy_from(input.tilts()); + output->handle_types_left().fill(BezierSpline::HandleType::Vector); + output->handle_types_right().fill(BezierSpline::HandleType::Vector); + output->set_resolution(12); + Spline::copy_base_settings(input, *output); + output->attributes = input.attributes; + return output; +} + +static SplinePtr nurbs_to_bezier(const Spline &input) +{ + const NURBSpline &nurbs_spline = static_cast(input); + std::unique_ptr output = std::make_unique(); + output->resize(input.size() / 3); + scale_input_assign(input.positions(), 3, 1, output->positions()); + scale_input_assign(input.positions(), 3, 0, output->handle_positions_left()); + scale_input_assign(input.positions(), 3, 2, output->handle_positions_right()); + scale_input_assign(input.radii(), 3, 2, output->radii()); + scale_input_assign(input.tilts(), 3, 2, output->tilts()); + output->handle_types_left().fill(BezierSpline::HandleType::Align); + output->handle_types_right().fill(BezierSpline::HandleType::Align); + output->set_resolution(nurbs_spline.resolution()); + Spline::copy_base_settings(input, *output); + output->attributes.reallocate(output->size()); + copy_attributes(input, *output, [](GSpan src, GMutableSpan dst) { + attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { + using T = decltype(dummy); + scale_input_assign(src.typed(), 3, 1, dst.typed()); + }); + }); + return output; +} + +static SplinePtr convert_to_bezier(const Spline &input, GeoNodeExecParams params) +{ + switch (input.type()) { + case Spline::Type::Bezier: + return input.copy(); + case Spline::Type::Poly: + return poly_to_bezier(input); + case Spline::Type::NURBS: + if (input.size() < 6) { + params.error_message_add( + NodeWarningType::Info, + TIP_("NURBS must have minimum of 6 points for Bezier Conversion")); + return input.copy(); + } + else { + if (input.size() % 3 != 0) { + params.error_message_add(NodeWarningType::Info, + TIP_("NURBS must have multiples of 3 points for full Bezier " + "conversion, curve truncated")); + } + return nurbs_to_bezier(input); + } + } + BLI_assert_unreachable(); + return {}; +} + +static SplinePtr convert_to_nurbs(const Spline &input) +{ + switch (input.type()) { + case Spline::Type::NURBS: + return input.copy(); + case Spline::Type::Bezier: + return bezier_to_nurbs(input); + case Spline::Type::Poly: + return poly_to_nurbs(input); + } + BLI_assert_unreachable(); + return {}; +} + +static void geo_node_curve_spline_type_exec(GeoNodeExecParams params) +{ + const NodeGeometryCurveSplineType *storage = + (const NodeGeometryCurveSplineType *)params.node().storage; + const GeometryNodeSplineType output_type = (const GeometryNodeSplineType)storage->spline_type; + + GeometrySet geometry_set = params.extract_input("Curve"); + geometry_set = bke::geometry_set_realize_instances(geometry_set); + if (!geometry_set.has_curve()) { + params.set_output("Curve", geometry_set); + return; + } + + const CurveComponent *curve_component = geometry_set.get_component_for_read(); + const CurveEval &curve = *curve_component->get_for_read(); + + const std::string selection_name = params.extract_input("Selection"); + GVArray_Typed selection = curve_component->attribute_get_for_read( + selection_name, ATTR_DOMAIN_CURVE, true); + + std::unique_ptr new_curve = std::make_unique(); + for (const int i : curve.splines().index_range()) { + if (selection[i]) { + switch (output_type) { + case GEO_NODE_SPLINE_TYPE_POLY: + new_curve->add_spline(convert_to_poly_spline(*curve.splines()[i])); + break; + case GEO_NODE_SPLINE_TYPE_BEZIER: + new_curve->add_spline(convert_to_bezier(*curve.splines()[i], params)); + break; + case GEO_NODE_SPLINE_TYPE_NURBS: + new_curve->add_spline(convert_to_nurbs(*curve.splines()[i])); + break; + } + } + else { + new_curve->add_spline(curve.splines()[i]->copy()); + } + } + + new_curve->attributes = curve.attributes; + params.set_output("Curve", GeometrySet::create_with_curve(new_curve.release())); +} + +} // namespace blender::nodes + +void register_node_type_geo_curve_spline_type() +{ + static bNodeType ntype; + geo_node_type_base( + &ntype, GEO_NODE_CURVE_SPLINE_TYPE, "Set Spline Type", NODE_CLASS_GEOMETRY, 0); + node_type_socket_templates( + &ntype, geo_node_curve_spline_type_in, geo_node_curve_spline_type_out); + ntype.geometry_node_execute = blender::nodes::geo_node_curve_spline_type_exec; + node_type_init(&ntype, blender::nodes::geo_node_curve_spline_type_init); + node_type_storage(&ntype, + "NodeGeometryCurveSplineType", + node_free_standard_storage, + node_copy_standard_storage); + ntype.draw_buttons = geo_node_curve_spline_type_layout; + + nodeRegisterType(&ntype); +} -- cgit v1.2.3 From 10464843dd3b175c0841f8d9a3f26751c12c8579 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 4 Aug 2021 13:13:02 +1000 Subject: Cleanup: add comment to fix for T90417 --- source/blender/blenloader/intern/versioning_300.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c index 7b5f95408ea..f1f7f2edd35 100644 --- a/source/blender/blenloader/intern/versioning_300.c +++ b/source/blender/blenloader/intern/versioning_300.c @@ -691,6 +691,7 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) } } + /* Font names were copied directly into ID names, see: T90417. */ if (!MAIN_VERSION_ATLEAST(bmain, 300, 16)) { ListBase *lb = which_libbase(bmain, ID_VF); BKE_main_id_repair_duplicate_names_listbase(lb); -- cgit v1.2.3 From cd92b2350fc20f6c91128881b5fd20dd173d2308 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 4 Aug 2021 13:26:47 +1000 Subject: Cleanup: use C comments for descriptive text --- intern/ghost/intern/GHOST_ContextGLX.cpp | 4 +- intern/ghost/intern/GHOST_SystemX11.cpp | 3 +- intern/ghost/intern/GHOST_WindowX11.cpp | 18 ++++----- source/blender/blenkernel/intern/armature_test.cc | 6 +-- source/blender/blenkernel/intern/softbody.c | 4 +- source/blender/blenkernel/intern/text.c | 2 +- source/blender/blenlib/BLI_winstuff.h | 4 +- source/blender/blenlib/intern/path_util.c | 9 ++--- source/blender/blenloader/intern/versioning_290.c | 2 +- source/blender/compositor/nodes/COM_MaskNode.cc | 2 +- .../blender/compositor/nodes/COM_MovieClipNode.cc | 2 +- .../operations/COM_DilateErodeOperation.cc | 46 +++++++++++----------- .../operations/COM_OutputFileOperation.cc | 2 +- .../compositor/operations/COM_WrapOperation.cc | 12 +++--- source/blender/depsgraph/DEG_depsgraph.h | 2 +- .../gpu_shader_3D_point_uniform_size_aa_vert.glsl | 6 +-- source/blender/imbuf/intern/dds/ColorBlock.h | 2 +- .../blender/imbuf/intern/openexr/openexr_api.cpp | 2 +- source/blender/windowmanager/intern/wm_window.c | 2 +- 19 files changed, 63 insertions(+), 67 deletions(-) diff --git a/intern/ghost/intern/GHOST_ContextGLX.cpp b/intern/ghost/intern/GHOST_ContextGLX.cpp index eb49dc4f98b..78c7201ff5f 100644 --- a/intern/ghost/intern/GHOST_ContextGLX.cpp +++ b/intern/ghost/intern/GHOST_ContextGLX.cpp @@ -295,8 +295,8 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext() glXMakeCurrent(m_display, m_window, m_context); - // Seems that this has to be called after MakeCurrent, - // which means we cannot use glX extensions until after we create a context + /* Seems that this has to be called after #glXMakeCurrent, + * which means we cannot use `glX` extensions until after we create a context. */ initContextGLXEW(); if (m_window) { diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 9fcad8aabf7..9422d15692d 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -802,8 +802,7 @@ static bool checkTabletProximity(Display *display, XDevice *device) if (state) { XInputClass *cls = state->data; - // printf("%d class%s :\n", state->num_classes, - // (state->num_classes > 1) ? "es" : ""); + // printf("%d class%s :\n", state->num_classes, (state->num_classes > 1) ? "es" : ""); for (int loop = 0; loop < state->num_classes; loop++) { switch (cls->c_class) { case ValuatorClass: diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 185d12717e7..de389951613 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -1275,15 +1275,15 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type { if (type == GHOST_kDrawingContextTypeOpenGL) { - // During development: - // try 4.x compatibility profile - // try 3.3 compatibility profile - // fall back to 3.0 if needed - // - // Final Blender 2.8: - // try 4.x core profile - // try 3.3 core profile - // no fallbacks + /* During development: + * - Try 4.x compatibility profile. + * - Try 3.3 compatibility profile. + * - Fall back to 3.0 if needed. + * + * Final Blender 2.8: + * - Try 4.x core profile + * - Try 3.3 core profile + * - No fall-backs. */ #if defined(WITH_GL_PROFILE_CORE) { diff --git a/source/blender/blenkernel/intern/armature_test.cc b/source/blender/blenkernel/intern/armature_test.cc index 47853deec3e..99eb064d061 100644 --- a/source/blender/blenkernel/intern/armature_test.cc +++ b/source/blender/blenkernel/intern/armature_test.cc @@ -180,7 +180,7 @@ class BKE_armature_find_selected_bones_test : public testing::Test { BLI_addtail(&arm.bonebase, &bone2); // bone2 is root bone BLI_addtail(&bone2.childbase, &bone3); // bone3 has bone2 as parent - // Make sure the armature & its bones are visible, to make them selectable. + /* Make sure the armature & its bones are visible, to make them selectable. */ arm.layer = bone1.layer = bone2.layer = bone3.layer = 1; } }; @@ -200,8 +200,8 @@ TEST_F(BKE_armature_find_selected_bones_test, some_bones_selected) EXPECT_EQ(seen_bones[0], &bone1); EXPECT_EQ(seen_bones[1], &bone3); - EXPECT_FALSE(result.all_bones_selected); // Bone 2 was not selected. - EXPECT_FALSE(result.no_bones_selected); // Bones 1 and 3 were selected. + EXPECT_FALSE(result.all_bones_selected); /* Bone 2 was not selected. */ + EXPECT_FALSE(result.no_bones_selected); /* Bones 1 and 3 were selected. */ } TEST_F(BKE_armature_find_selected_bones_test, no_bones_selected) diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 1a408aceeb2..f41251f6ea5 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -3447,10 +3447,10 @@ static void softbody_step( float newtime = forcetime * 1.1f; /* hope for 1.1 times better conditions in next step */ if (sb->scratch->flag & SBF_DOFUZZY) { - ///* stay with this stepsize unless err really small */ + // /* stay with this stepsize unless err really small */ // if (err > SoftHeunTol/(2.0f*sb->fuzzyness)) { newtime = forcetime; - //} + // } } else { if (err > SoftHeunTol / 2.0f) { /* stay with this stepsize unless err really small */ diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 80ff8ce9162..6048e823abb 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -2331,7 +2331,7 @@ int txt_setcurr_tab_spaces(Text *text, int space) } while (text->curl->line[i] == indent) { - // we only count those tabs/spaces that are before any text or before the curs; + /* We only count those tabs/spaces that are before any text or before the curs; */ if (i == text->curc) { return i; } diff --git a/source/blender/blenlib/BLI_winstuff.h b/source/blender/blenlib/BLI_winstuff.h index 0953e3f1946..bf09b56c779 100644 --- a/source/blender/blenlib/BLI_winstuff.h +++ b/source/blender/blenlib/BLI_winstuff.h @@ -45,7 +45,7 @@ #undef small -// These definitions are also in BLI_math for simplicity +/* These definitions are also in BLI_math for simplicity. */ #ifdef __cplusplus extern "C" { @@ -72,7 +72,7 @@ extern "C" { #if defined(_MSC_VER) # define R_OK 4 # define W_OK 2 -// not accepted by access() on windows +/* Not accepted by `access()` on windows. */ //# define X_OK 1 # define F_OK 0 #endif diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 99fae1f1616..4d0678035ba 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1102,12 +1102,9 @@ bool BLI_path_abs(char *path, const char *basepath) } #ifdef WIN32 - /* skip first two chars, which in case of - * absolute path will be drive:/blabla and - * in case of relpath //blabla/. So relpath - * // will be retained, rest will be nice and - * shiny win32 backward slashes :) -jesterKing - */ + /* NOTE(@jesterking): Skip first two chars, which in case of absolute path will + * be `drive:/blabla` and in case of `relpath` `//blabla/`. + * So `relpath` `//` will be retained, rest will be nice and shiny WIN32 backward slashes. */ BLI_str_replace_char(path + 2, '/', '\\'); #endif diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 09d43676b8f..7f7a2d97cbb 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -170,7 +170,7 @@ static void seq_convert_transform_crop(const Scene *scene, int image_size_x = scene->r.xsch; int image_size_y = scene->r.ysch; - /* Hardcoded legacy bit-flags which has been removed. */ + /* Hard-coded legacy bit-flags which has been removed. */ const uint32_t use_transform_flag = (1 << 16); const uint32_t use_crop_flag = (1 << 17); diff --git a/source/blender/compositor/nodes/COM_MaskNode.cc b/source/blender/compositor/nodes/COM_MaskNode.cc index ef171c01653..b5b23798160 100644 --- a/source/blender/compositor/nodes/COM_MaskNode.cc +++ b/source/blender/compositor/nodes/COM_MaskNode.cc @@ -41,7 +41,7 @@ void MaskNode::convertToOperations(NodeConverter &converter, NodeMask *data = (NodeMask *)editorNode->storage; Mask *mask = (Mask *)editorNode->id; - // always connect the output image + /* Always connect the output image. */ MaskOperation *operation = new MaskOperation(); if (editorNode->custom1 & CMP_NODEFLAG_MASK_FIXED) { diff --git a/source/blender/compositor/nodes/COM_MovieClipNode.cc b/source/blender/compositor/nodes/COM_MovieClipNode.cc index 50bd9b4d71b..b80071d27c7 100644 --- a/source/blender/compositor/nodes/COM_MovieClipNode.cc +++ b/source/blender/compositor/nodes/COM_MovieClipNode.cc @@ -62,7 +62,7 @@ void MovieClipNode::convertToOperations(NodeConverter &converter, } } - // always connect the output image + /* Always connect the output image. */ MovieClipOperation *operation = new MovieClipOperation(); operation->setMovieClip(movieClip); operation->setMovieClipUser(movieClipUser); diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cc b/source/blender/compositor/operations/COM_DilateErodeOperation.cc index 2454f507664..e9305e0e192 100644 --- a/source/blender/compositor/operations/COM_DilateErodeOperation.cc +++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cc @@ -24,7 +24,7 @@ namespace blender::compositor { -// DilateErode Distance Threshold +/* DilateErode Distance Threshold */ DilateErodeThresholdOperation::DilateErodeThresholdOperation() { this->addInputSocket(DataType::Value); @@ -258,7 +258,7 @@ void DilateDistanceOperation::executeOpenCL(OpenCLDevice *device, device->COM_clEnqueueRange(dilateKernel, outputMemoryBuffer, 7, this); } -// Erode Distance +/* Erode Distance */ ErodeDistanceOperation::ErodeDistanceOperation() : DilateDistanceOperation() { /* pass */ @@ -318,7 +318,7 @@ void ErodeDistanceOperation::executeOpenCL(OpenCLDevice *device, device->COM_clEnqueueRange(erodeKernel, outputMemoryBuffer, 7, this); } -// Dilate step +/* Dilate step */ DilateStepOperation::DilateStepOperation() { this->addInputSocket(DataType::Value); @@ -331,7 +331,7 @@ void DilateStepOperation::initExecution() this->m_inputProgram = this->getInputSocketReader(0); } -// small helper to pass data from initializeTileData to executePixel +/* Small helper to pass data from initializeTileData to executePixel. */ struct tile_info { rcti rect; int width; @@ -370,21 +370,21 @@ void *DilateStepOperation::initializeTileData(rcti *rect) int bwidth = rect->xmax - rect->xmin; int bheight = rect->ymax - rect->ymin; - // NOTE: Cache buffer has original tilesize width, but new height. - // We have to calculate the additional rows in the first pass, - // to have valid data available for the second pass. + /* NOTE: Cache buffer has original tilesize width, but new height. + * We have to calculate the additional rows in the first pass, + * to have valid data available for the second pass. */ tile_info *result = create_cache(rect->xmin, rect->xmax, ymin, ymax); float *rectf = result->buffer; - // temp holds maxima for every step in the algorithm, buf holds a - // single row or column of input values, padded with FLT_MAX's to - // simplify the logic. + /* temp holds maxima for every step in the algorithm, buf holds a + * single row or column of input values, padded with FLT_MAX's to + * simplify the logic. */ float *temp = (float *)MEM_mallocN(sizeof(float) * (2 * window - 1), "dilate erode temp"); float *buf = (float *)MEM_mallocN(sizeof(float) * (MAX2(bwidth, bheight) + 5 * half_window), "dilate erode buf"); - // The following is based on the van Herk/Gil-Werman algorithm for morphology operations. - // first pass, horizontal dilate/erode + /* The following is based on the van Herk/Gil-Werman algorithm for morphology operations. + * first pass, horizontal dilate/erode. */ for (y = ymin; y < ymax; y++) { for (x = 0; x < bwidth + 5 * half_window; x++) { buf[x] = -FLT_MAX; @@ -409,7 +409,7 @@ void *DilateStepOperation::initializeTileData(rcti *rect) } } - // second pass, vertical dilate/erode + /* Second pass, vertical dilate/erode. */ for (x = 0; x < bwidth; x++) { for (y = 0; y < bheight + 5 * half_window; y++) { buf[y] = -FLT_MAX; @@ -475,7 +475,7 @@ bool DilateStepOperation::determineDependingAreaOfInterest(rcti *input, return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } -// Erode step +/* Erode step */ ErodeStepOperation::ErodeStepOperation() : DilateStepOperation() { /* pass */ @@ -500,21 +500,21 @@ void *ErodeStepOperation::initializeTileData(rcti *rect) int bwidth = rect->xmax - rect->xmin; int bheight = rect->ymax - rect->ymin; - // NOTE: Cache buffer has original tilesize width, but new height. - // We have to calculate the additional rows in the first pass, - // to have valid data available for the second pass. + /* NOTE: Cache buffer has original tilesize width, but new height. + * We have to calculate the additional rows in the first pass, + * to have valid data available for the second pass. */ tile_info *result = create_cache(rect->xmin, rect->xmax, ymin, ymax); float *rectf = result->buffer; - // temp holds maxima for every step in the algorithm, buf holds a - // single row or column of input values, padded with FLT_MAX's to - // simplify the logic. + /* temp holds maxima for every step in the algorithm, buf holds a + * single row or column of input values, padded with FLT_MAX's to + * simplify the logic. */ float *temp = (float *)MEM_mallocN(sizeof(float) * (2 * window - 1), "dilate erode temp"); float *buf = (float *)MEM_mallocN(sizeof(float) * (MAX2(bwidth, bheight) + 5 * half_window), "dilate erode buf"); - // The following is based on the van Herk/Gil-Werman algorithm for morphology operations. - // first pass, horizontal dilate/erode + /* The following is based on the van Herk/Gil-Werman algorithm for morphology operations. + * first pass, horizontal dilate/erode */ for (y = ymin; y < ymax; y++) { for (x = 0; x < bwidth + 5 * half_window; x++) { buf[x] = FLT_MAX; @@ -539,7 +539,7 @@ void *ErodeStepOperation::initializeTileData(rcti *rect) } } - // second pass, vertical dilate/erode + /* Second pass, vertical dilate/erode. */ for (x = 0; x < bwidth; x++) { for (y = 0; y < bheight + 5 * half_window; y++) { buf[y] = FLT_MAX; diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cc b/source/blender/compositor/operations/COM_OutputFileOperation.cc index 7e896046f01..6c5984e3414 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.cc +++ b/source/blender/compositor/operations/COM_OutputFileOperation.cc @@ -160,7 +160,7 @@ int get_datatype_size(DataType datatype) static float *init_buffer(unsigned int width, unsigned int height, DataType datatype) { - // When initializing the tree during initial load the width and height can be zero. + /* When initializing the tree during initial load the width and height can be zero. */ if (width != 0 && height != 0) { int size = get_datatype_size(datatype); return (float *)MEM_callocN(width * height * size * sizeof(float), "OutputFile buffer"); diff --git a/source/blender/compositor/operations/COM_WrapOperation.cc b/source/blender/compositor/operations/COM_WrapOperation.cc index d0d2fcac3ac..888602114cc 100644 --- a/source/blender/compositor/operations/COM_WrapOperation.cc +++ b/source/blender/compositor/operations/COM_WrapOperation.cc @@ -57,20 +57,20 @@ void WrapOperation::executePixelSampled(float output[4], float x, float y, Pixel MemoryBufferExtend extend_x = MemoryBufferExtend::Clip, extend_y = MemoryBufferExtend::Clip; switch (m_wrappingType) { case CMP_NODE_WRAP_NONE: - // Intentionally empty, originalXPos and originalYPos have been set before + /* Intentionally empty, originalXPos and originalYPos have been set before. */ break; case CMP_NODE_WRAP_X: - // wrap only on the x-axis + /* Wrap only on the x-axis. */ nx = this->getWrappedOriginalXPos(x); extend_x = MemoryBufferExtend::Repeat; break; case CMP_NODE_WRAP_Y: - // wrap only on the y-axis + /* Wrap only on the y-axis. */ ny = this->getWrappedOriginalYPos(y); extend_y = MemoryBufferExtend::Repeat; break; case CMP_NODE_WRAP_XY: - // wrap on both + /* Wrap on both. */ nx = this->getWrappedOriginalXPos(x); ny = this->getWrappedOriginalYPos(y); extend_x = MemoryBufferExtend::Repeat; @@ -92,7 +92,7 @@ bool WrapOperation::determineDependingAreaOfInterest(rcti *input, newInput.ymax = input->ymax; if (ELEM(m_wrappingType, CMP_NODE_WRAP_X, CMP_NODE_WRAP_XY)) { - // wrap only on the x-axis if tile is wrapping + /* Wrap only on the x-axis if tile is wrapping. */ newInput.xmin = getWrappedOriginalXPos(input->xmin); newInput.xmax = roundf(getWrappedOriginalXPos(input->xmax)); if (newInput.xmin >= newInput.xmax) { @@ -101,7 +101,7 @@ bool WrapOperation::determineDependingAreaOfInterest(rcti *input, } } if (ELEM(m_wrappingType, CMP_NODE_WRAP_Y, CMP_NODE_WRAP_XY)) { - // wrap only on the y-axis if tile is wrapping + /* Wrap only on the y-axis if tile is wrapping. */ newInput.ymin = getWrappedOriginalYPos(input->ymin); newInput.ymax = roundf(getWrappedOriginalYPos(input->ymax)); if (newInput.ymin >= newInput.ymax) { diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h index 749b1bba871..47dad17b482 100644 --- a/source/blender/depsgraph/DEG_depsgraph.h +++ b/source/blender/depsgraph/DEG_depsgraph.h @@ -85,7 +85,7 @@ extern "C" { // Get main depsgraph instance from context! /* Create new Depsgraph instance */ -// TODO: what args are needed here? What's the building-graph entry point? +/* TODO: what args are needed here? What's the building-graph entry point? */ Depsgraph *DEG_graph_new(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl index f5b6d2ea3ed..5d67658c639 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl @@ -14,14 +14,14 @@ void main() gl_Position = ModelViewProjectionMatrix * pos_4d; gl_PointSize = size; - // calculate concentric radii in pixels + /* Calculate concentric radii in pixels. */ float radius = 0.5 * size; - // start at the outside and progress toward the center + /* Start at the outside and progress toward the center. */ radii[0] = radius; radii[1] = radius - 1.0; - // convert to PointCoord units + /* Convert to PointCoord units. */ radii /= size; #ifdef USE_WORLD_CLIP_PLANES diff --git a/source/blender/imbuf/intern/dds/ColorBlock.h b/source/blender/imbuf/intern/dds/ColorBlock.h index 158695cfbf3..934837bb129 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.h +++ b/source/blender/imbuf/intern/dds/ColorBlock.h @@ -25,7 +25,7 @@ * Original license from NVIDIA follows. */ -// This code is in the public domain -- +/* This code is in the public domain -- */ #pragma once diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index d1fa26e1a3e..a465c6b92bc 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -69,7 +69,7 @@ extern "C" { -// The following prevents a linking error in debug mode for MSVC using the libs in CVS +/* The following prevents a linking error in debug mode for MSVC using the libs in SVN. */ #if defined(WITH_OPENEXR) && defined(_WIN32) && defined(DEBUG) && _MSC_VER < 1900 _CRTIMP void __cdecl _invalid_parameter_noinfo(void) { diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 8f37e7f34a9..93417213a65 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -1058,7 +1058,7 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win) BLI_assert(GPU_framebuffer_active_get() == GPU_framebuffer_back_get()); if (win != wm->windrawable && win->ghostwin) { - // win->lmbut = 0; /* keeps hanging when mousepressed while other window opened */ + // win->lmbut = 0; /* Keeps hanging when mouse-pressed while other window opened. */ wm_window_clear_drawable(wm); if (G.debug & G_DEBUG_EVENTS) { -- cgit v1.2.3 From effc0487106bc74590acf35a61541597b1149daa Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 4 Aug 2021 08:58:19 +0200 Subject: T90371: Asset: Drop Material Tooltip. This patch changes the drop named material tooltip to give feedback to the user what is going to happen when they invoke the change. There are 3 states: * "": Operator will be canceled as not all data is present (dropping on background.) * "Drop on (slot , replacing ). * "Drop on (slot mval); + + char name[MAX_ID_NAME - 2]; + RNA_string_get(properties, "name", name); + + if (base == NULL) { + return BLI_strdup(""); + } + + Object *ob = base->object; + int active_mat_slot = max_ii(ob->actcol, 1); + Material *prev_mat = BKE_object_material_get(ob, active_mat_slot); + + char *result; + if (prev_mat) { + const char *tooltip = TIP_("Drop %s on %s (slot %d, replacing %s)."); + result = BLI_sprintfN(tooltip, name, ob->id.name + 2, active_mat_slot, prev_mat->id.name + 2); + } + else { + const char *tooltip = TIP_("Drop %s on %s (slot %d)."); + result = BLI_sprintfN(tooltip, name, ob->id.name + 2, active_mat_slot); + } + return result; +} + static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Main *bmain = CTX_data_main(C); diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c index 36b2966dc43..11ad3abcd54 100644 --- a/source/blender/editors/space_outliner/outliner_dragdrop.c +++ b/source/blender/editors/space_outliner/outliner_dragdrop.c @@ -868,7 +868,8 @@ static bool datastack_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) static char *datastack_drop_tooltip(bContext *UNUSED(C), wmDrag *drag, - const wmEvent *UNUSED(event)) + const wmEvent *UNUSED(event), + struct wmDropBox *UNUSED(drop)) { StackDropData *drop_data = drag->poin; switch (drop_data->drop_action) { @@ -1191,7 +1192,10 @@ static bool collection_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event return false; } -static char *collection_drop_tooltip(bContext *C, wmDrag *drag, const wmEvent *event) +static char *collection_drop_tooltip(bContext *C, + wmDrag *drag, + const wmEvent *event, + wmDropBox *UNUSED(drop)) { CollectionDrop data; if (!event->shift && collection_drop_init(C, drag, event, &data)) { diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index a2564469c16..0803b4c4776 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -53,6 +53,7 @@ #include "BKE_screen.h" #include "BKE_workspace.h" +#include "ED_object.h" #include "ED_render.h" #include "ED_screen.h" #include "ED_space_api.h" @@ -528,6 +529,16 @@ static bool view3d_mat_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event return view3d_drop_id_in_main_region_poll(C, drag, event, ID_MA); } +static char *view3d_mat_drop_tooltip(bContext *C, + wmDrag *drag, + const wmEvent *event, + struct wmDropBox *drop) +{ + wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, ID_MA); + RNA_string_set(drop->ptr, "name", asset_drag->name); + return ED_object_ot_drop_named_material_tooltip(C, drop->ptr, event); +} + static bool view3d_object_data_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) { ID_Type id_type = view3d_drop_id_in_main_region_poll_get_id_type(C, drag, event); @@ -539,7 +550,8 @@ static bool view3d_object_data_drop_poll(bContext *C, wmDrag *drag, const wmEven static char *view3d_object_data_drop_tooltip(bContext *UNUSED(C), wmDrag *UNUSED(drag), - const wmEvent *UNUSED(event)) + const wmEvent *UNUSED(event), + wmDropBox *UNUSED(drop)) { return BLI_strdup(TIP_("Create object instance from object-data")); } @@ -689,7 +701,7 @@ static void view3d_dropboxes(void) view3d_mat_drop_poll, view3d_id_drop_copy, WM_drag_free_imported_drag_ID, - NULL); + view3d_mat_drop_tooltip); WM_dropbox_add(lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 4d6cb941347..485d8e5a162 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -115,6 +115,7 @@ struct wmEvent; struct wmOperator; struct wmWindowManager; struct wmDrag; +struct wmDropBox; #include "BLI_compiler_attrs.h" #include "DNA_listBase.h" @@ -937,7 +938,8 @@ typedef struct wmDragAsset { typedef char *(*WMDropboxTooltipFunc)(struct bContext *, struct wmDrag *, - const struct wmEvent *event); + const struct wmEvent *event, + struct wmDropBox *drop); typedef struct wmDrag { struct wmDrag *next, *prev; diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c index c58d3c53e03..dcbb502117e 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.c +++ b/source/blender/windowmanager/intern/wm_dragdrop.c @@ -220,14 +220,11 @@ void WM_drag_free_list(struct ListBase *lb) } } -static char *dropbox_tooltip(bContext *C, - wmDrag *drag, - const wmEvent *event, - const wmDropBox *drop) +static char *dropbox_tooltip(bContext *C, wmDrag *drag, const wmEvent *event, wmDropBox *drop) { char *tooltip = NULL; if (drop->tooltip) { - tooltip = drop->tooltip(C, drag, event); + tooltip = drop->tooltip(C, drag, event, drop); } if (!tooltip) { tooltip = BLI_strdup(WM_operatortype_name(drop->ot, drop->ptr)); -- cgit v1.2.3 From 3b0fab6dfaa00a6fd476d28c160fcd9219f9a973 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 4 Aug 2021 09:18:21 +0200 Subject: Override: API update_operations. The update_operations function will update the override structure of the local object. When working with overrides the override structure is only updated when the work-file is stored. When using scripts you might want to enforce the update of override properties and operations. This function removes a hack on the test cases. Reviewed By: mont29 Maniphest Tasks: T86656 Differential Revision: https://developer.blender.org/D10848 --- source/blender/makesrna/intern/rna_ID.c | 21 +++++++++++++++++++++ tests/python/bl_blendfile_library_overrides.py | 10 ++-------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 6df03d19538..e177f211c7f 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -741,6 +741,19 @@ static void rna_ID_override_template_create(ID *id, ReportList *reports) BKE_lib_override_library_template_create(id); } +static void rna_ID_override_library_update_operations(ID *id, + IDOverrideLibrary *UNUSED(override_library), + Main *bmain, + ReportList *reports) +{ + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + BKE_report(reports, RPT_ERROR, "ID isn't an override"); + return; + } + + BKE_lib_override_library_operations_create(bmain, id); +} + static IDOverrideLibraryProperty *rna_ID_override_library_properties_add( IDOverrideLibrary *override_library, ReportList *reports, const char rna_path[]) { @@ -1695,6 +1708,7 @@ static void rna_def_ID_override_library(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; + FunctionRNA *func; srna = RNA_def_struct(brna, "IDOverrideLibrary", NULL); RNA_def_struct_ui_text( @@ -1710,6 +1724,13 @@ static void rna_def_ID_override_library(BlenderRNA *brna) "List of overridden properties"); rna_def_ID_override_library_properties(brna, prop); + /* Update function. */ + func = RNA_def_function(srna, "update_operations", "rna_ID_override_library_update_operations"); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_SELF_ID | FUNC_USE_REPORTS); + RNA_def_function_ui_description(func, + "Update the library override operations based on the " + "differences between this override ID and its reference"); + rna_def_ID_override_library_property(brna); } diff --git a/tests/python/bl_blendfile_library_overrides.py b/tests/python/bl_blendfile_library_overrides.py index c9c89c01cee..138c5fd13b5 100644 --- a/tests/python/bl_blendfile_library_overrides.py +++ b/tests/python/bl_blendfile_library_overrides.py @@ -45,10 +45,6 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase): bpy.ops.wm.save_as_mainfile(filepath=str(self.output_path), check_existing=False, compress=False) - def __ensure_override_library_updated(self): - # During save the override_library is updated. - bpy.ops.wm.save_as_mainfile(filepath=str(self.test_output_path), check_existing=False, compress=False) - def test_link_and_override_property(self): bpy.ops.wm.read_homefile(use_empty=True, use_factory_startup=True) bpy.data.orphans_purge() @@ -64,8 +60,7 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase): assert(len(local_id.override_library.properties) == 0) local_id.location.y = 1.0 - - self.__ensure_override_library_updated() + local_id.override_library.update_operations() assert(len(local_id.override_library.properties) == 1) override_prop = local_id.override_library.properties[0] @@ -101,7 +96,6 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase): override_operation = override_prop.operations[0] assert(override_operation.operation == 'NOOP') assert(override_operation.subitem_local_index == -1) - local_id.location.y = 1.0 local_id.scale.x = 0.5 # `scale.x` will apply, but will be reverted when the library overrides @@ -110,7 +104,7 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase): assert(local_id.scale.x == 0.5) assert(local_id.location.y == 1.0) - self.__ensure_override_library_updated() + local_id.override_library.update_operations() assert(local_id.scale.x == 1.0) assert(local_id.location.y == 1.0) -- cgit v1.2.3 From 218df9941097bf973485ac343c070bdc6641a539 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 4 Aug 2021 09:18:21 +0200 Subject: Modifier: warn if the ocean simulation fails to allocate memory While most modifies don't handle out of memory cases, ocean simulation could attempt huge allocations: 2048 gb at the maximum resolution. Resolves T83952. --- source/blender/blenkernel/BKE_ocean.h | 6 +- source/blender/blenkernel/intern/ocean.c | 104 ++++++++++++++++++---------- source/blender/modifiers/intern/MOD_ocean.c | 14 ++-- 3 files changed, 82 insertions(+), 42 deletions(-) diff --git a/source/blender/blenkernel/BKE_ocean.h b/source/blender/blenkernel/BKE_ocean.h index 2c0c6989acf..380f9045520 100644 --- a/source/blender/blenkernel/BKE_ocean.h +++ b/source/blender/blenkernel/BKE_ocean.h @@ -74,11 +74,13 @@ struct Ocean *BKE_ocean_add(void); void BKE_ocean_free_data(struct Ocean *oc); void BKE_ocean_free(struct Ocean *oc); bool BKE_ocean_ensure(struct OceanModifierData *omd, const int resolution); -void BKE_ocean_init_from_modifier(struct Ocean *ocean, +bool BKE_ocean_init_from_modifier(struct Ocean *ocean, struct OceanModifierData const *omd, const int resolution); -void BKE_ocean_init(struct Ocean *o, +bool BKE_ocean_is_valid(const struct Ocean *o); + +bool BKE_ocean_init(struct Ocean *o, int M, int N, float Lx, diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 3aee5cd639d..30e9213cdae 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -650,6 +650,14 @@ static void ocean_compute_normal_z(TaskPool *__restrict pool, void *UNUSED(taskd fftw_execute(o->_N_z_plan); } +/** + * Return true if the ocean is valid and can be used. + */ +bool BKE_ocean_is_valid(const struct Ocean *o) +{ + return o->_k != NULL; +} + void BKE_ocean_simulate(struct Ocean *o, float t, float scale, float chop_amount) { TaskPool *pool; @@ -769,7 +777,10 @@ bool BKE_ocean_ensure(struct OceanModifierData *omd, const int resolution) return true; } -void BKE_ocean_init_from_modifier(struct Ocean *ocean, +/** + * Return true if the ocean data is valid and can be used. + */ +bool BKE_ocean_init_from_modifier(struct Ocean *ocean, struct OceanModifierData const *omd, const int resolution) { @@ -783,31 +794,34 @@ void BKE_ocean_init_from_modifier(struct Ocean *ocean, BKE_ocean_free_data(ocean); - BKE_ocean_init(ocean, - resolution * resolution, - resolution * resolution, - omd->spatial_size, - omd->spatial_size, - omd->wind_velocity, - omd->smallest_wave, - 1.0, - omd->wave_direction, - omd->damp, - omd->wave_alignment, - omd->depth, - omd->time, - omd->spectrum, - omd->fetch_jonswap, - omd->sharpen_peak_jonswap, - do_heightfield, - do_chop, - do_spray, - do_normals, - do_jacobian, - omd->seed); -} - -void BKE_ocean_init(struct Ocean *o, + return BKE_ocean_init(ocean, + resolution * resolution, + resolution * resolution, + omd->spatial_size, + omd->spatial_size, + omd->wind_velocity, + omd->smallest_wave, + 1.0, + omd->wave_direction, + omd->damp, + omd->wave_alignment, + omd->depth, + omd->time, + omd->spectrum, + omd->fetch_jonswap, + omd->sharpen_peak_jonswap, + do_heightfield, + do_chop, + do_spray, + do_normals, + do_jacobian, + omd->seed); +} + +/** + * Return true if the ocean data is valid and can be used. + */ +bool BKE_ocean_init(struct Ocean *o, int M, int N, float Lx, @@ -830,7 +844,6 @@ void BKE_ocean_init(struct Ocean *o, short do_jacobian, int seed) { - RNG *rng; int i, j, ii; BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE); @@ -858,18 +871,34 @@ void BKE_ocean_init(struct Ocean *o, o->_fetch_jonswap = fetch_jonswap; o->_sharpen_peak_jonswap = sharpen_peak_jonswap * 10.0f; + /* NOTE: most modifiers don't account for failure to allocate. + * In this case however a large resolution can easily perform large allocations that fail, + * support early exiting in this case. */ + if ((o->_k = (float *)MEM_mallocN(sizeof(float) * (size_t)M * (1 + N / 2), "ocean_k")) && + (o->_h0 = (fftw_complex *)MEM_mallocN(sizeof(fftw_complex) * (size_t)M * N, "ocean_h0")) && + (o->_h0_minus = (fftw_complex *)MEM_mallocN(sizeof(fftw_complex) * (size_t)M * N, + "ocean_h0_minus")) && + (o->_kx = (float *)MEM_mallocN(sizeof(float) * o->_M, "ocean_kx")) && + (o->_kz = (float *)MEM_mallocN(sizeof(float) * o->_N, "ocean_kz"))) { + /* Success. */ + } + else { + MEM_SAFE_FREE(o->_k); + MEM_SAFE_FREE(o->_h0); + MEM_SAFE_FREE(o->_h0_minus); + MEM_SAFE_FREE(o->_kx); + MEM_SAFE_FREE(o->_kz); + + BLI_rw_mutex_unlock(&o->oceanmutex); + return false; + } + o->_do_disp_y = do_height_field; o->_do_normals = do_normals; o->_do_spray = do_spray; o->_do_chop = do_chop; o->_do_jacobian = do_jacobian; - o->_k = (float *)MEM_mallocN(M * (1 + N / 2) * sizeof(float), "ocean_k"); - o->_h0 = (fftw_complex *)MEM_mallocN(M * N * sizeof(fftw_complex), "ocean_h0"); - o->_h0_minus = (fftw_complex *)MEM_mallocN(M * N * sizeof(fftw_complex), "ocean_h0_minus"); - o->_kx = (float *)MEM_mallocN(o->_M * sizeof(float), "ocean_kx"); - o->_kz = (float *)MEM_mallocN(o->_N * sizeof(float), "ocean_kz"); - /* make this robust in the face of erroneous usage */ if (o->_Lx == 0.0f) { o->_Lx = 0.001f; @@ -902,11 +931,11 @@ void BKE_ocean_init(struct Ocean *o, /* pre-calculate the k matrix */ for (i = 0; i < o->_M; i++) { for (j = 0; j <= o->_N / 2; j++) { - o->_k[i * (1 + o->_N / 2) + j] = sqrt(o->_kx[i] * o->_kx[i] + o->_kz[j] * o->_kz[j]); + o->_k[(size_t)i * (1 + o->_N / 2) + j] = sqrt(o->_kx[i] * o->_kx[i] + o->_kz[j] * o->_kz[j]); } } - rng = BLI_rng_new(seed); + RNG *rng = BLI_rng_new(seed); for (i = 0; i < o->_M; i++) { for (j = 0; j < o->_N; j++) { @@ -1029,6 +1058,8 @@ void BKE_ocean_init(struct Ocean *o, set_height_normalize_factor(o); BLI_rng_free(rng); + + return true; } void BKE_ocean_free_data(struct Ocean *oc) @@ -1700,10 +1731,11 @@ void BKE_ocean_bake(struct Ocean *UNUSED(o), (void)update_cb; } -void BKE_ocean_init_from_modifier(struct Ocean *UNUSED(ocean), +bool BKE_ocean_init_from_modifier(struct Ocean *UNUSED(ocean), struct OceanModifierData const *UNUSED(omd), int UNUSED(resolution)) { + return true; } #endif /* WITH_OCEANSIM */ diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index 8f3206da5be..1c502b94bdb 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -95,8 +95,9 @@ static void initData(ModifierData *md) BKE_modifier_path_init(omd->cachepath, sizeof(omd->cachepath), "cache_ocean"); omd->ocean = BKE_ocean_add(); - BKE_ocean_init_from_modifier(omd->ocean, omd, omd->viewport_resolution); - simulate_ocean_modifier(omd); + if (BKE_ocean_init_from_modifier(omd->ocean, omd, omd->viewport_resolution)) { + simulate_ocean_modifier(omd); + } #else /* WITH_OCEANSIM */ UNUSED_VARS(md); #endif /* WITH_OCEANSIM */ @@ -132,8 +133,9 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla tomd->oceancache = NULL; tomd->ocean = BKE_ocean_add(); - BKE_ocean_init_from_modifier(tomd->ocean, tomd, tomd->viewport_resolution); - simulate_ocean_modifier(tomd); + if (BKE_ocean_init_from_modifier(tomd->ocean, tomd, tomd->viewport_resolution)) { + simulate_ocean_modifier(tomd); + } #else /* WITH_OCEANSIM */ /* unused */ (void)md; @@ -323,6 +325,10 @@ static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig, co static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { OceanModifierData *omd = (OceanModifierData *)md; + if (omd->ocean && !BKE_ocean_is_valid(omd->ocean)) { + BKE_modifier_set_error(ctx->object, md, "Failed to allocate memory"); + return mesh; + } int cfra_scene = (int)DEG_get_ctime(ctx->depsgraph); Object *ob = ctx->object; bool allocated_ocean = false; -- cgit v1.2.3 From cb67bfdba2e22d0ee967e50afe0912ac80d73e9b Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 4 Aug 2021 10:52:51 +0200 Subject: Viewport normal drawing with constant length Patch for: T37878 {F10169694} Reviewed By: fclem Differential Revision: https://developer.blender.org/D11487 --- release/datafiles/alert_icons.png | Bin 24026 -> 25576 bytes release/datafiles/blender_icons.svg | 5 +++++ .../datafiles/blender_icons16/icon16_fixed_size.dat | Bin 0 -> 1048 bytes .../datafiles/blender_icons16/icon16_force_boid.dat | Bin 1048 -> 1048 bytes .../datafiles/blender_icons32/icon32_fixed_size.dat | Bin 0 -> 4120 bytes .../datafiles/blender_icons32/icon32_force_boid.dat | Bin 4120 -> 4120 bytes release/scripts/startup/bl_ui/space_view3d.py | 8 +++++++- source/blender/blenloader/intern/versioning_300.c | 14 ++++++++++++++ .../blender/blenloader/intern/versioning_defaults.c | 1 + .../draw/engines/overlay/overlay_edit_mesh.c | 5 +++++ .../overlay/shaders/edit_mesh_normal_vert.glsl | 20 ++++++++++++++++++-- source/blender/editors/datafiles/CMakeLists.txt | 1 + source/blender/editors/include/UI_icons.h | 2 +- source/blender/makesdna/DNA_view3d_defaults.h | 1 + source/blender/makesdna/DNA_view3d_types.h | 4 ++++ source/blender/makesdna/DNA_view3d_types.h.rej | 9 +++++++++ source/blender/makesrna/intern/rna_space.c | 15 +++++++++++++++ 17 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 release/datafiles/blender_icons16/icon16_fixed_size.dat create mode 100644 release/datafiles/blender_icons32/icon32_fixed_size.dat create mode 100644 source/blender/makesdna/DNA_view3d_types.h.rej diff --git a/release/datafiles/alert_icons.png b/release/datafiles/alert_icons.png index e1cb671713f..0add7a3ccf8 100644 Binary files a/release/datafiles/alert_icons.png and b/release/datafiles/alert_icons.png differ diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg index f894ca3f298..54357550847 100644 --- a/release/datafiles/blender_icons.svg +++ b/release/datafiles/blender_icons.svg @@ -17301,6 +17301,11 @@ d="m 1800,348 h 3 v 14 h -3 z m -4,7 h 16 v 3 h -16 z" inkscape:connector-curvature="0" /> + filesdna, "View3DOverlay", "float", "normals_constant_screen_size")) { + LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) { + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + if (sl->spacetype == SPACE_VIEW3D) { + View3D *v3d = (View3D *)sl; + v3d->overlay.normals_constant_screen_size = 7.0f; + } + } + } + } + } } } diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index 7ff624b44da..82c577d11a0 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -190,6 +190,7 @@ static void blo_update_defaults_screen(bScreen *screen, } /* Disable Curve Normals. */ v3d->overlay.edit_flag &= ~V3D_OVERLAY_EDIT_CU_NORMALS; + v3d->overlay.normals_constant_screen_size = 7.0f; } else if (area->spacetype == SPACE_CLIP) { SpaceClip *sclip = area->spacedata.first; diff --git a/source/blender/draw/engines/overlay/overlay_edit_mesh.c b/source/blender/draw/engines/overlay/overlay_edit_mesh.c index a7ed6c777e8..3a2871249a2 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_mesh.c +++ b/source/blender/draw/engines/overlay/overlay_edit_mesh.c @@ -132,6 +132,11 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata) DRW_shgroup_uniform_float_copy(grp, "normalSize", v3d->overlay.normals_length); DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity); DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex); + DRW_shgroup_uniform_bool_copy(grp, + "isConstantScreenSizeNormals", + (flag & V3D_OVERLAY_EDIT_CONSTANT_SCREEN_SIZE_NORMALS) != 0); + DRW_shgroup_uniform_float_copy( + grp, "normalScreenSize", v3d->overlay.normals_constant_screen_size); } { /* Mesh Analysis Pass */ diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl index 007495f84e0..f649a5cb3ed 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl @@ -1,5 +1,7 @@ uniform float normalSize; +uniform float normalScreenSize; +uniform bool isConstantScreenSizeNormals; uniform sampler2D depthTex; uniform float alpha = 1.0; @@ -49,11 +51,25 @@ void main() } vec3 n = normalize(normal_object_to_world(nor)); - vec3 world_pos = point_object_to_world(pos); if (gl_VertexID == 0) { - world_pos += n * normalSize; + if (isConstantScreenSizeNormals) { + bool is_persp = (ProjectionMatrix[3][3] == 0.0); + if (is_persp) + { + float dist_fac = length(cameraPos - world_pos); + float cos_fac = dot(cameraForward, cameraVec(world_pos)); + world_pos += n * normalScreenSize * dist_fac * cos_fac * pixelFac * sizePixel; + } + else { + float frustrum_fac = mul_project_m4_v3_zfac(n) * sizePixel; + world_pos += n * normalScreenSize * frustrum_fac; + } + } + else { + world_pos += n * normalSize; + } } gl_Position = point_world_to_ndc(world_pos); diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index beb22d43930..4af6e1bdcb8 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -583,6 +583,7 @@ set(ICON_NAMES uv_facesel uv_islandsel uv_sync_select + fixed_size transform_origins gizmo orientation_cursor diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index 7ccdc49d291..eb893fbe029 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -715,7 +715,7 @@ DEF_ICON(UV_ISLANDSEL) DEF_ICON(UV_SYNC_SELECT) DEF_ICON_BLANK(240) DEF_ICON_BLANK(241) -DEF_ICON_BLANK(242) +DEF_ICON(FIXED_SIZE) DEF_ICON(TRANSFORM_ORIGINS) DEF_ICON(GIZMO) DEF_ICON(ORIENTATION_CURSOR) diff --git a/source/blender/makesdna/DNA_view3d_defaults.h b/source/blender/makesdna/DNA_view3d_defaults.h index 9dfc37e57b1..c4d0c83b346 100644 --- a/source/blender/makesdna/DNA_view3d_defaults.h +++ b/source/blender/makesdna/DNA_view3d_defaults.h @@ -71,6 +71,7 @@ .gpencil_paper_opacity = 0.5f, \ .gpencil_grid_opacity = 0.9f, \ .gpencil_vertex_paint_opacity = 1.0f, \ + .normals_constant_screen_size = 7.0f, \ } #define _DNA_DEFAULT_View3DCursor \ diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 08b29c82707..4d88f6f0c15 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -204,6 +204,7 @@ typedef struct View3DOverlay { /** Edit mode settings. */ int edit_flag; float normals_length; + float normals_constant_screen_size; float backwire_opacity; /** Paint mode settings. */ @@ -238,6 +239,8 @@ typedef struct View3DOverlay { float gpencil_vertex_paint_opacity; /** Handles display type for curves. */ int handle_display; + + char _pad[4]; } View3DOverlay; /* View3DOverlay->handle_display */ @@ -551,6 +554,7 @@ enum { // V3D_OVERLAY_EDIT_CU_HANDLES = (1 << 20), V3D_OVERLAY_EDIT_CU_NORMALS = (1 << 21), + V3D_OVERLAY_EDIT_CONSTANT_SCREEN_SIZE_NORMALS = (1 << 22), }; /** #View3DOverlay.paint_flag */ diff --git a/source/blender/makesdna/DNA_view3d_types.h.rej b/source/blender/makesdna/DNA_view3d_types.h.rej new file mode 100644 index 00000000000..a62f1c4b7d3 --- /dev/null +++ b/source/blender/makesdna/DNA_view3d_types.h.rej @@ -0,0 +1,9 @@ +diff a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h (rejected hunks) +@@ -550,6 +553,7 @@ + /* V3D_OVERLAY_EDIT_CU_HANDLES = (1 << 20), */ + + V3D_OVERLAY_EDIT_CU_NORMALS = (1 << 21), ++ V3D_OVERLAY_EDIT_CONSTANT_SCREEN_SIZE_NORMALS = (1 << 22), + }; + + /** #View3DOverlay.paint_flag */ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 796e62c8b2a..c7a5c43255a 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -4363,6 +4363,21 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna) RNA_def_property_float_default(prop, 0.02); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "normals_constant_screen_size", PROP_FLOAT, PROP_PIXEL); + RNA_def_property_float_sdna(prop, NULL, "overlay.normals_constant_screen_size"); + RNA_def_property_ui_text(prop, "Normal Screen Size", "Screen size for normals in the 3D view"); + RNA_def_property_range(prop, 0.0, 100000.0); + RNA_def_property_ui_range(prop, 1.0, 100.0, 50, 0); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "use_normals_constant_screen_size", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna( + prop, NULL, "overlay.edit_flag", V3D_OVERLAY_EDIT_CONSTANT_SCREEN_SIZE_NORMALS); + RNA_def_property_ui_text(prop, + "Constant Screen Size Normals", + "Keep size of normals constant in relation to 3D view"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "backwire_opacity", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "overlay.backwire_opacity"); RNA_def_property_ui_text(prop, "Backwire Opacity", "Opacity when rendering transparent wires"); -- cgit v1.2.3 From b867df903fc89df06b835e2c9172612887efc761 Mon Sep 17 00:00:00 2001 From: Anthony Edlin Date: Wed, 4 Aug 2021 11:04:04 +0200 Subject: Make loopcut drawing consistent between gizmo and operator. Loopcut drawing from gizmo had thicker lines because it was using line smoothing without alpha blend, compared to thin jagged lines from operator. Make the drawing anti aliased and consistent by using 3D_POLYLINE/3D_POINT shaders, and making sure alpha blending is on. Reviewed By: #eevee_viewport, fclem Differential Revision: https://developer.blender.org/D11333 --- .../editors/mesh/editmesh_preselect_edgering.c | 28 +++++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_preselect_edgering.c b/source/blender/editors/mesh/editmesh_preselect_edgering.c index 43e36957dc9..c58f29917b1 100644 --- a/source/blender/editors/mesh/editmesh_preselect_edgering.c +++ b/source/blender/editors/mesh/editmesh_preselect_edgering.c @@ -20,6 +20,8 @@ #include "MEM_guardedalloc.h" +#include "DNA_userdef_types.h" + #include "BLI_math.h" #include "BLI_stack.h" @@ -160,16 +162,21 @@ void EDBM_preselect_edgering_draw(struct EditMesh_PreSelEdgeRing *psel, const fl } GPU_depth_test(GPU_DEPTH_NONE); + GPU_blend(GPU_BLEND_ALPHA); GPU_matrix_push(); GPU_matrix_mul(matrix); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - immUniformThemeColor3(TH_GIZMO_PRIMARY); - if (psel->edges_len > 0) { + float viewport[4]; + GPU_viewport_size_get_f(viewport); + + immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR); + immUniform2fv("viewportSize", &viewport[2]); + immUniformThemeColor3(TH_GIZMO_PRIMARY); + immUniform1f("lineWidth", U.pixelsize); immBegin(GPU_PRIM_LINES, psel->edges_len * 2); for (int i = 0; i < psel->edges_len; i++) { @@ -178,10 +185,18 @@ void EDBM_preselect_edgering_draw(struct EditMesh_PreSelEdgeRing *psel, const fl } immEnd(); + immUnbindProgram(); } if (psel->verts_len > 0) { - GPU_point_size(3.0f); + GPU_program_point_size(true); + immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); + immUniformThemeColor3(TH_GIZMO_PRIMARY); + + /* Same size as an edit mode vertex */ + immUniform1f("size", + 2.0 * U.pixelsize * + (max_ff(1.0f, UI_GetThemeValuef(TH_VERTEX_SIZE) * (float)M_SQRT2 / 2.0f))); immBegin(GPU_PRIM_POINTS, psel->verts_len); @@ -190,14 +205,15 @@ void EDBM_preselect_edgering_draw(struct EditMesh_PreSelEdgeRing *psel, const fl } immEnd(); + immUnbindProgram(); + GPU_program_point_size(false); } - immUnbindProgram(); - GPU_matrix_pop(); /* Reset default */ GPU_depth_test(GPU_DEPTH_LESS_EQUAL); + GPU_blend(GPU_BLEND_NONE); } static void view3d_preselect_mesh_edgering_update_verts_from_edge( -- cgit v1.2.3 From c8004ab4078c98c54a70113c12bbb186403e90cf Mon Sep 17 00:00:00 2001 From: Gottfried Hofmann Date: Wed, 4 Aug 2021 11:20:10 +0200 Subject: Expose Color Management as argument for gpu.types.GPUOffScreen.draw_view3d() Fix for https://developer.blender.org/T84227 The problem was that https://developer.blender.org/rBe0ffb911a22bb03755687f45fc1a996870e059a8 turned color management for offscreen rendering off by default, which makes it non-color-managed in some cases. So the idea here is that script authors get the choice wether they want color managed non-color-managed output. Thus this patch introduces a new argument do_color_management as a bool to gpu.types.GPUOffScreen.draw_view3d(). Reviewed By: jbakker Differential Revision: https://developer.blender.org/D11645 --- source/blender/python/gpu/gpu_py_offscreen.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/source/blender/python/gpu/gpu_py_offscreen.c b/source/blender/python/gpu/gpu_py_offscreen.c index 457f00b1267..02f72f20ac4 100644 --- a/source/blender/python/gpu/gpu_py_offscreen.c +++ b/source/blender/python/gpu/gpu_py_offscreen.c @@ -279,7 +279,7 @@ static PyObject *pygpu_offscreen_texture_color_get(BPyGPUOffScreen *self, void * PyDoc_STRVAR( pygpu_offscreen_draw_view3d_doc, - ".. method:: draw_view3d(scene, view_layer, view3d, region, view_matrix, projection_matrix)\n" + ".. method:: draw_view3d(scene, view_layer, view3d, region, view_matrix, projection_matrix, do_color_management=False)\n" "\n" " Draw the 3d viewport in the offscreen object.\n" "\n" @@ -294,7 +294,9 @@ PyDoc_STRVAR( " :arg view_matrix: View Matrix (e.g. ``camera.matrix_world.inverted()``).\n" " :type view_matrix: :class:`mathutils.Matrix`\n" " :arg projection_matrix: Projection Matrix (e.g. ``camera.calc_matrix_camera(...)``).\n" - " :type projection_matrix: :class:`mathutils.Matrix`\n"); + " :type projection_matrix: :class:`mathutils.Matrix`\n" + " :arg do_color_management: Color manage the output.\n" + " :type do_color_management: bool\n"); static PyObject *pygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *args, PyObject *kwds) { MatrixObject *py_mat_view, *py_mat_projection; @@ -306,12 +308,14 @@ static PyObject *pygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *ar View3D *v3d; ARegion *region; + bool do_color_management = false; + BPY_GPU_OFFSCREEN_CHECK_OBJ(self); static const char *_keywords[] = { - "scene", "view_layer", "view3d", "region", "view_matrix", "projection_matrix", NULL}; + "scene", "view_layer", "view3d", "region", "view_matrix", "projection_matrix", "do_color_management", NULL}; - static _PyArg_Parser _parser = {"OOOOO&O&:draw_view3d", _keywords, 0}; + static _PyArg_Parser _parser = {"OOOOO&O&|$O&:draw_view3d", _keywords, 0}; if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, @@ -322,7 +326,9 @@ static PyObject *pygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *ar Matrix_Parse4x4, &py_mat_view, Matrix_Parse4x4, - &py_mat_projection) || + &py_mat_projection, + PyC_ParseBool, + &do_color_management) || (!(scene = PyC_RNA_AsPointer(py_scene, "Scene")) || !(view_layer = PyC_RNA_AsPointer(py_view_layer, "ViewLayer")) || !(v3d = PyC_RNA_AsPointer(py_view3d, "SpaceView3D")) || @@ -354,7 +360,7 @@ static PyObject *pygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *ar true, true, "", - false, + do_color_management, true, self->ofs, NULL); -- cgit v1.2.3 From 8c21076addf4de01c2f5640c5aaa563d99655783 Mon Sep 17 00:00:00 2001 From: Pratik Borhade Date: Wed, 4 Aug 2021 11:20:43 +0200 Subject: Fix T87635: Rename shader node "Specular" to "Specular BSDF" Node name edited in Specular node definition Reviewed By: fclem Maniphest Tasks: T87635 Differential Revision: https://developer.blender.org/D11022 --- source/blender/nodes/NOD_static_types.h | 2 +- source/blender/nodes/shader/nodes/node_shader_eevee_specular.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index b368ac74894..6c3f91df434 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -61,7 +61,7 @@ DefNode(ShaderNode, SH_NODE_COMBRGB, 0, "COMBRG DefNode(ShaderNode, SH_NODE_HUE_SAT, 0, "HUE_SAT", HueSaturation, "Hue/Saturation", "" ) DefNode(ShaderNode, SH_NODE_OUTPUT_MATERIAL, def_sh_output, "OUTPUT_MATERIAL", OutputMaterial, "Material Output", "" ) -DefNode(ShaderNode, SH_NODE_EEVEE_SPECULAR, 0, "EEVEE_SPECULAR", EeveeSpecular, "Specular", "" ) +DefNode(ShaderNode, SH_NODE_EEVEE_SPECULAR, 0, "EEVEE_SPECULAR", EeveeSpecular, "Specular BSDF", "" ) DefNode(ShaderNode, SH_NODE_OUTPUT_LIGHT, def_sh_output, "OUTPUT_LIGHT", OutputLight, "Light Output", "" ) DefNode(ShaderNode, SH_NODE_OUTPUT_WORLD, def_sh_output, "OUTPUT_WORLD", OutputWorld, "World Output", "" ) DefNode(ShaderNode, SH_NODE_OUTPUT_LINESTYLE, def_sh_output_linestyle,"OUTPUT_LINESTYLE", OutputLineStyle, "Line Style Output", "" ) diff --git a/source/blender/nodes/shader/nodes/node_shader_eevee_specular.c b/source/blender/nodes/shader/nodes/node_shader_eevee_specular.c index 56169b9be5e..015af19abb2 100644 --- a/source/blender/nodes/shader/nodes/node_shader_eevee_specular.c +++ b/source/blender/nodes/shader/nodes/node_shader_eevee_specular.c @@ -91,7 +91,7 @@ void register_node_type_sh_eevee_specular(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_EEVEE_SPECULAR, "Specular", NODE_CLASS_SHADER, 0); + sh_node_type_base(&ntype, SH_NODE_EEVEE_SPECULAR, "Specular BSDF", NODE_CLASS_SHADER, 0); node_type_socket_templates(&ntype, sh_node_eevee_specular_in, sh_node_eevee_specular_out); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); -- cgit v1.2.3 From d9a530c55e869376aa2d0e9175a659d965d38d2a Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 4 Aug 2021 11:29:43 +0200 Subject: Fix compile error without `WITH_OCEANSIM` enabled Was changed in 218df9941097. --- source/blender/blenkernel/intern/ocean.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 30e9213cdae..4d003ddc900 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -1639,7 +1639,7 @@ struct Ocean *BKE_ocean_add(void) return oc; } -void BKE_ocean_init(struct Ocean *UNUSED(o), +bool BKE_ocean_init(struct Ocean *UNUSED(o), int UNUSED(M), int UNUSED(N), float UNUSED(Lx), @@ -1662,6 +1662,7 @@ void BKE_ocean_init(struct Ocean *UNUSED(o), short UNUSED(do_jacobian), int UNUSED(seed)) { + return false; } void BKE_ocean_free_data(struct Ocean *UNUSED(oc)) -- cgit v1.2.3 From 051141acdecfd11f82cbe37bac368c2882dd4f92 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 4 Aug 2021 11:40:20 +0200 Subject: Outliner/LibOverrides: Fix logic of checks for drag'n'drop of Collections. Previous check was too blunt, preventing e.g. re-organization of collection overrides inside a local parent collection, which is perfectly valid operation. Reported by @hjalti from the studio, thanks! --- source/blender/editors/space_outliner/outliner_dragdrop.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c index 11ad3abcd54..a82f516b125 100644 --- a/source/blender/editors/space_outliner/outliner_dragdrop.c +++ b/source/blender/editors/space_outliner/outliner_dragdrop.c @@ -1104,10 +1104,6 @@ static bool collection_drop_init(bContext *C, if (ID_IS_LINKED(to_collection)) { return false; } - /* Currently this should not be allowed (might be supported in the future though...). */ - if (ID_IS_OVERRIDE_LIBRARY(to_collection)) { - return false; - } /* Get drag datablocks. */ if (drag->type != WM_DRAG_ID) { @@ -1131,6 +1127,11 @@ static bool collection_drop_init(bContext *C, from_collection = NULL; } + /* Currently this should not be allowed, cannot edit items in an override of a Collection. */ + if (from_collection != NULL && ID_IS_OVERRIDE_LIBRARY(from_collection)) { + return false; + } + /* Get collections. */ if (GS(id->name) == ID_GR) { if (id == &to_collection->id) { @@ -1141,6 +1142,12 @@ static bool collection_drop_init(bContext *C, insert_type = TE_INSERT_INTO; } + /* Currently this should not be allowed, cannot edit items in an override of a Collection. */ + if (ID_IS_OVERRIDE_LIBRARY(to_collection) && + !ELEM(insert_type, TE_INSERT_AFTER, TE_INSERT_BEFORE)) { + return false; + } + data->from = from_collection; data->to = to_collection; data->te = te; -- cgit v1.2.3 From 557e7f135ec22b19cf809109ea5f6bd0be607dbd Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Wed, 4 Aug 2021 12:31:48 +0200 Subject: Cleanup: initialize variable to quiet warning --- source/blender/imbuf/intern/metadata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/imbuf/intern/metadata.c b/source/blender/imbuf/intern/metadata.c index c59997b34f5..5a01c42cf00 100644 --- a/source/blender/imbuf/intern/metadata.c +++ b/source/blender/imbuf/intern/metadata.c @@ -44,7 +44,7 @@ void IMB_metadata_ensure(struct IDProperty **metadata) return; } - IDPropertyTemplate val; + IDPropertyTemplate val = {0}; *metadata = IDP_New(IDP_GROUP, &val, "metadata"); } -- cgit v1.2.3 From ac6b263906c92d6adaafd014db28e0863cfd13e9 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Wed, 4 Aug 2021 12:32:25 +0200 Subject: Cleanup: inconsistent parameter name --- source/blender/python/generic/py_capi_utils.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h index 1591413530c..bfe0e66e393 100644 --- a/source/blender/python/generic/py_capi_utils.h +++ b/source/blender/python/generic/py_capi_utils.h @@ -42,13 +42,13 @@ void PyC_Err_PrintWithFunc(PyObject *py_func); void PyC_FileAndNum(const char **r_filename, int *r_lineno); void PyC_FileAndNum_Safe(const char **r_filename, int *r_lineno); /* checks python is running */ int PyC_AsArray_FAST(void *array, - const size_t array_elem_size, + const size_t array_item_size, PyObject *value_fast, const Py_ssize_t length, const PyTypeObject *type, const char *error_prefix); int PyC_AsArray(void *array, - const size_t array_elem_size, + const size_t array_item_size, PyObject *value, const Py_ssize_t length, const PyTypeObject *type, -- cgit v1.2.3 From add719e31aa7d5668fd33cb1a1e02417a334be97 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 4 Aug 2021 12:36:06 +0200 Subject: Tweak to recent liboverride API addition: naming. Rename new API function introduced in recent rB3b0fab6dfaa0 to match our convention to put the action (verb) at the end of names: `operations_update`. Sorry for not catching that during review. --- source/blender/makesrna/intern/rna_ID.c | 4 ++-- tests/python/bl_blendfile_library_overrides.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index e177f211c7f..15704fc2523 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -741,7 +741,7 @@ static void rna_ID_override_template_create(ID *id, ReportList *reports) BKE_lib_override_library_template_create(id); } -static void rna_ID_override_library_update_operations(ID *id, +static void rna_ID_override_library_operations_update(ID *id, IDOverrideLibrary *UNUSED(override_library), Main *bmain, ReportList *reports) @@ -1725,7 +1725,7 @@ static void rna_def_ID_override_library(BlenderRNA *brna) rna_def_ID_override_library_properties(brna, prop); /* Update function. */ - func = RNA_def_function(srna, "update_operations", "rna_ID_override_library_update_operations"); + func = RNA_def_function(srna, "operations_update", "rna_ID_override_library_operations_update"); RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_SELF_ID | FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Update the library override operations based on the " diff --git a/tests/python/bl_blendfile_library_overrides.py b/tests/python/bl_blendfile_library_overrides.py index 138c5fd13b5..19f06dc698e 100644 --- a/tests/python/bl_blendfile_library_overrides.py +++ b/tests/python/bl_blendfile_library_overrides.py @@ -60,7 +60,7 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase): assert(len(local_id.override_library.properties) == 0) local_id.location.y = 1.0 - local_id.override_library.update_operations() + local_id.override_library.operations_update() assert(len(local_id.override_library.properties) == 1) override_prop = local_id.override_library.properties[0] @@ -104,7 +104,7 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase): assert(local_id.scale.x == 0.5) assert(local_id.location.y == 1.0) - local_id.override_library.update_operations() + local_id.override_library.operations_update() assert(local_id.scale.x == 1.0) assert(local_id.location.y == 1.0) -- cgit v1.2.3 From d2130c53276a985ab82b310c4a0c87b824116729 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 4 Aug 2021 21:09:21 +1000 Subject: Cleanup: remove *.rej from cb67bfdba2e22d0ee967e50afe0912ac80d73e9b --- source/blender/makesdna/DNA_view3d_types.h.rej | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 source/blender/makesdna/DNA_view3d_types.h.rej diff --git a/source/blender/makesdna/DNA_view3d_types.h.rej b/source/blender/makesdna/DNA_view3d_types.h.rej deleted file mode 100644 index a62f1c4b7d3..00000000000 --- a/source/blender/makesdna/DNA_view3d_types.h.rej +++ /dev/null @@ -1,9 +0,0 @@ -diff a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h (rejected hunks) -@@ -550,6 +553,7 @@ - /* V3D_OVERLAY_EDIT_CU_HANDLES = (1 << 20), */ - - V3D_OVERLAY_EDIT_CU_NORMALS = (1 << 21), -+ V3D_OVERLAY_EDIT_CONSTANT_SCREEN_SIZE_NORMALS = (1 << 22), - }; - - /** #View3DOverlay.paint_flag */ -- cgit v1.2.3 From 76dcf70dacedb1af4f5e04ed5016e0b8ea4eb305 Mon Sep 17 00:00:00 2001 From: Gavin Li Date: Wed, 4 Aug 2021 13:18:23 +0200 Subject: Fix transparent faces on certain AMD cards This patch fixes an issue with missing faces when assigning a material slot other than the first to faces on AMD TAHITI cards. Refer to T78390 and T74024 for a description of this issue. This patch also incorporates fix from T78390 for KAVERI. {F9029258} Reviewed By: fclem Differential Revision: https://developer.blender.org/D9305 --- source/blender/gpu/opengl/gl_backend.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index 42b85da1f93..772fc19d919 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -283,7 +283,8 @@ static void detect_workarounds() } /* We have issues with this specific renderer. (see T74024) */ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE) && - strstr(renderer, "AMD VERDE")) { + (strstr(renderer, "AMD VERDE") || strstr(renderer, "AMD KAVERI") || + strstr(renderer, "AMD TAHITI"))) { GLContext::unused_fb_slot_workaround = true; GCaps.shader_image_load_store_support = false; GCaps.broken_amd_driver = true; -- cgit v1.2.3 From 26c2c617b468ee2900f584b0ec0c82dfd632849a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 4 Aug 2021 22:34:55 +1000 Subject: Fix T90421: edit-mode auto-smooth crash when angle set to 180degrees Error in 39b2a7bb7e815e051348bf5c5ec777d091324164 which failed to set edge flags with single threaded calculation, used for low poly models. --- source/blender/bmesh/intern/bmesh_mesh_normals.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_mesh_normals.c b/source/blender/bmesh/intern/bmesh_mesh_normals.c index 746f094aed6..6504a2de116 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_normals.c +++ b/source/blender/bmesh/intern/bmesh_mesh_normals.c @@ -1156,10 +1156,6 @@ static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm, edge_vectors = BLI_stack_new(sizeof(float[3]), __func__); } - if (split_angle_cos != -1.0f) { - bm_mesh_edges_sharp_tag(bm, fnos, has_clnors ? (float)M_PI : split_angle, false); - } - /* Clear all loops' tags (means none are to be skipped for now). */ int index_face, index_loop = 0; BM_ITER_MESH_INDEX (f_curr, &fiter, bm, BM_FACES_OF_MESH, index_face) { @@ -1171,10 +1167,16 @@ static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm, do { BM_elem_index_set(l_curr, index_loop++); /* set_inline */ BM_elem_flag_disable(l_curr, BM_ELEM_TAG); + /* Needed for when #bm_mesh_edges_sharp_tag doesn't run. */ + BM_elem_flag_disable(l_curr->e, BM_ELEM_TAG); } while ((l_curr = l_curr->next) != l_first); } bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); + if (split_angle_cos != -1.0f) { + bm_mesh_edges_sharp_tag(bm, fnos, has_clnors ? (float)M_PI : split_angle, false); + } + /* We now know edges that can be smoothed (they are tagged), * and edges that will be hard (they aren't). * Now, time to generate the normals. -- cgit v1.2.3 From e5d4a0c5596daaae14251872755df1e71e54e108 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Wed, 4 Aug 2021 10:38:03 -0300 Subject: BLI: add double version of 'scaleform' No functional changes. New utility. --- source/blender/blenlib/BLI_math_base.h | 3 +++ source/blender/blenlib/intern/math_base_inline.c | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index 88dc20a64f2..e877503e835 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -120,6 +120,9 @@ MINLINE double interpd(double a, double b, double t); MINLINE float ratiof(float min, float max, float pos); MINLINE double ratiod(double min, double max, double pos); +MINLINE float scalenorm(float a, float b, float x); +MINLINE double scalenormd(double a, double b, double x); + /* NOTE: Compilers will upcast all types smaller than int to int when performing arithmetic * operation. */ MINLINE int square_s(short a); diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index 6e3846e59c6..a80c495ecf3 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -199,6 +199,13 @@ MINLINE float scalenorm(float a, float b, float x) return (x * (b - a)) + a; } +/* Map a normalized value, i.e. from interval [0, 1] to interval [a, b]. */ +MINLINE double scalenormd(double a, double b, double x) +{ + BLI_assert(x <= 1 && x >= 0); + return (x * (b - a)) + a; +} + /* Used for zoom values. */ MINLINE float power_of_2(float val) { -- cgit v1.2.3 From 145270d8d7c6812de9fd1ba50cc51ffc53953881 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Wed, 4 Aug 2021 10:46:42 -0300 Subject: Fix T90427: Center View to Mouse broken rBfb87d236edb7 made the values returned by `projmat_dimensions` more standardized following the documentations. But the functions in Blender that called `projmat_dimensions` followed a proposal that these values corresponded to a distance of 1m of clip. Adjust these functions to follow the new algorithm. --- source/blender/draw/intern/draw_manager_data.c | 7 ------- source/blender/gpu/intern/gpu_matrix.cc | 12 ++++++------ 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index 2126385a352..af331c86a8b 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -1533,13 +1533,6 @@ static void draw_frustum_boundbox_calc(const float (*viewinv)[4], projmat_dimensions(projmat, &left, &right, &bottom, &top, &near, &far); - if (is_persp) { - left *= near; - right *= near; - bottom *= near; - top *= near; - } - r_bbox->vec[0][2] = r_bbox->vec[3][2] = r_bbox->vec[7][2] = r_bbox->vec[4][2] = -near; r_bbox->vec[0][0] = r_bbox->vec[3][0] = left; r_bbox->vec[4][0] = r_bbox->vec[7][0] = right; diff --git a/source/blender/gpu/intern/gpu_matrix.cc b/source/blender/gpu/intern/gpu_matrix.cc index 6eb9cb823d5..efa04568401 100644 --- a/source/blender/gpu/intern/gpu_matrix.cc +++ b/source/blender/gpu/intern/gpu_matrix.cc @@ -532,17 +532,17 @@ static void gpu_mul_invert_projmat_m4_unmapped_v3_with_precalc( const struct GPUMatrixUnproject_Precalc *precalc, float co[3]) { /* 'precalc->dims' is the result of 'projmat_dimensions(proj, ...)'. */ - co[0] = precalc->dims.xmin + co[0] * (precalc->dims.xmax - precalc->dims.xmin); - co[1] = precalc->dims.ymin + co[1] * (precalc->dims.ymax - precalc->dims.ymin); + co[0] = (float)scalenormd(precalc->dims.xmin, precalc->dims.xmax, co[0]); + co[1] = (float)scalenormd(precalc->dims.ymin, precalc->dims.ymax, co[1]); if (precalc->is_persp) { - co[2] = precalc->dims.zmax * precalc->dims.zmin / + co[2] = (precalc->dims.zmax * precalc->dims.zmin) / (precalc->dims.zmax + co[2] * (precalc->dims.zmin - precalc->dims.zmax)); - co[0] *= co[2]; - co[1] *= co[2]; + co[0] *= co[2] / precalc->dims.zmin; + co[1] *= co[2] / precalc->dims.zmin; } else { - co[2] = precalc->dims.zmin + co[2] * (precalc->dims.zmax - precalc->dims.zmin); + co[2] = (float)scalenormd(precalc->dims.zmin, precalc->dims.zmax, co[2]); } co[2] *= -1; } -- cgit v1.2.3 From c1730ed16568784552678908becfad2389ac391f Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Wed, 4 Aug 2021 15:54:54 +0200 Subject: GPencil: New Brush option to define Caps type This is used to set the default caps type for the stroke. Before always was rounded and only could be changed later in Edit mode Two new buttons has been added to topbar. NOTE: New icons are been designed (T90414) The buttons are expanded to list in Properties panel. Reviewed By: mendio, HooglyBoogly Differential Revision: https://developer.blender.org/D11999 --- release/scripts/startup/bl_ui/properties_paint_common.py | 6 ++++++ source/blender/draw/intern/draw_cache_impl_gpencil.c | 3 +++ source/blender/editors/gpencil/gpencil_paint.c | 3 +++ source/blender/editors/gpencil/gpencil_primitive.c | 3 +++ source/blender/makesdna/DNA_brush_types.h | 4 +++- source/blender/makesrna/intern/rna_brush.c | 12 ++++++++++++ 6 files changed, 30 insertions(+), 1 deletion(-) diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py index 4bfd2fd32b0..97a0c5abf24 100644 --- a/release/scripts/startup/bl_ui/properties_paint_common.py +++ b/release/scripts/startup/bl_ui/properties_paint_common.py @@ -1252,6 +1252,12 @@ def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=False) if brush.gpencil_tool == 'TINT': row = layout.row(align=True) row.prop(gp_settings, "vertex_mode", text="Mode") + else: + row = layout.row(align=True) + if context.region.type == 'TOOL_HEADER': + row.prop(gp_settings, "caps_type", text="", expand=True) + else: + row.prop(gp_settings, "caps_type", text="Caps Type") # FIXME: tools must use their own UI drawing! if tool.idname in { diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c index 336ccd40d5c..2a476ab41bb 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.c +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c @@ -552,6 +552,9 @@ bGPDstroke *DRW_cache_gpencil_sbuffer_stroke_data_get(Object *ob) gps->caps[0] = gps->caps[1] = GP_STROKE_CAP_ROUND; gps->runtime.stroke_start = 1; /* Add one for the adjacency index. */ copy_v4_v4(gps->vert_color_fill, gpd->runtime.vert_color_fill); + /* Caps. */ + gps->caps[0] = gps->caps[1] = brush->gpencil_settings->caps_type; + gpd->runtime.sbuffer_gps = gps; } return gpd->runtime.sbuffer_gps; diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index d6f6dbb2b10..aaea1c0ddaf 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -996,6 +996,9 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p) gps->inittime = p->inittime; gps->uv_scale = 1.0f; + /* Set stroke caps. */ + gps->caps[0] = gps->caps[1] = brush->gpencil_settings->caps_type; + /* allocate enough memory for a continuous array for storage points */ const int subdivide = brush->gpencil_settings->draw_subdivide; diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index cf49aefe2ea..27374f21b66 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -335,6 +335,9 @@ static void gpencil_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi) gps->uv_scale = 1.0f; gps->inittime = 0.0f; + /* Set stroke caps. */ + gps->caps[0] = gps->caps[1] = brush->gpencil_settings->caps_type; + /* Apply the vertex color to fill. */ ED_gpencil_fill_vertex_color_set(ts, brush, gps); diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 986c009ac26..634ebdff253 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -76,7 +76,9 @@ typedef struct BrushGpencilSettings { float fill_threshold; /** Number of pixel to consider the leak is too small (x 2). */ short fill_leak; - char _pad2[2]; + /* Type of caps: eGPDstroke_Caps. */ + int8_t caps_type; + char _pad; int flag2; diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 2b09ea51a84..eb968f9ecde 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -1281,6 +1281,12 @@ static void rna_def_gpencil_options(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; + static EnumPropertyItem rna_enum_gpencil_brush_caps_types_items[] = { + {GP_STROKE_CAP_ROUND, "ROUND", ICON_HANDLETYPE_AUTO_CLAMP_VEC, "Round", ""}, + {GP_STROKE_CAP_FLAT, "FLAT", ICON_HANDLETYPE_VECTOR_VEC, "Flat", ""}, + {0, NULL, 0, NULL, NULL}, + }; + srna = RNA_def_struct(brna, "BrushGpencilSettings", NULL); RNA_def_struct_sdna(srna, "BrushGpencilSettings"); RNA_def_struct_path_func(srna, "rna_BrushGpencilSettings_path"); @@ -1750,6 +1756,12 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_update( prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_eraser_mode_update"); + prop = RNA_def_property(srna, "caps_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "caps_type"); + RNA_def_property_enum_items(prop, rna_enum_gpencil_brush_caps_types_items); + RNA_def_property_ui_text(prop, "Caps Type", "The shape of the start and end of the stroke"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + prop = RNA_def_property(srna, "fill_draw_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "fill_draw_mode"); RNA_def_property_enum_items(prop, rna_enum_gpencil_fill_draw_modes_items); -- cgit v1.2.3 From 2af789d1f3b8a36d0578997bea5f907e31a613ed Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 4 Aug 2021 16:05:49 +0200 Subject: Added some TODO remarks. --- source/blender/editors/animation/anim_draw.c | 1 + source/blender/editors/animation/anim_motion_paths.c | 1 + 2 files changed, 2 insertions(+) diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 6469c47ab11..735f3b86924 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -522,6 +522,7 @@ static bool find_prev_next_keyframes(struct bContext *C, int *r_nextfra, int *r_ mask_to_keylist(&ads, masklay, keylist); } + /* TODO(jbakker): Keylists are ordered, no need to do any searching at all. */ /* find matching keyframe in the right direction */ do { aknext = ED_keylist_find_next(keylist, cfranext); diff --git a/source/blender/editors/animation/anim_motion_paths.c b/source/blender/editors/animation/anim_motion_paths.c index 2a3ae35aab0..d976f5f72ad 100644 --- a/source/blender/editors/animation/anim_motion_paths.c +++ b/source/blender/editors/animation/anim_motion_paths.c @@ -234,6 +234,7 @@ static void motionpath_get_global_framerange(ListBase *targets, int *r_sfra, int } } +/* TODO(jbakker): Remove complexity, keylists are ordered. */ static int motionpath_get_prev_keyframe(MPathTarget *mpt, struct AnimKeylist *keylist, int current_frame) -- cgit v1.2.3 From a8185d2d74d42389d881890897958c1223eb5cf1 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 4 Aug 2021 15:13:20 +0200 Subject: LibOverride: Add RNA API to reset/delete overrides. Ref. T86656. --- source/blender/makesrna/intern/rna_ID.c | 63 +++++++++++++++++++++++++- tests/python/bl_blendfile_library_overrides.py | 10 ++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 15704fc2523..e4c9b70a1ec 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -747,13 +747,52 @@ static void rna_ID_override_library_operations_update(ID *id, ReportList *reports) { if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { - BKE_report(reports, RPT_ERROR, "ID isn't an override"); + BKE_reportf(reports, RPT_ERROR, "ID '%s' isn't an override", id->name); return; } BKE_lib_override_library_operations_create(bmain, id); } +static void rna_ID_override_library_reset(ID *id, + IDOverrideLibrary *UNUSED(override_library), + Main *bmain, + ReportList *reports, + bool do_hierarchy) +{ + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + BKE_reportf(reports, RPT_ERROR, "ID '%s' isn't an override", id->name); + return; + } + + if (do_hierarchy) { + BKE_lib_override_library_id_hierarchy_reset(bmain, id); + } + else { + BKE_lib_override_library_id_reset(bmain, id); + } +} + +static void rna_ID_override_library_destroy(ID *id, + IDOverrideLibrary *UNUSED(override_library), + Main *bmain, + ReportList *reports, + bool do_hierarchy) +{ + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + BKE_reportf(reports, RPT_ERROR, "ID '%s' isn't an override", id->name); + return; + } + + if (do_hierarchy) { + BKE_lib_override_library_delete(bmain, id); + } + else { + BKE_libblock_remap(bmain, id, id->override_library->reference, ID_REMAP_SKIP_INDIRECT_USAGE); + BKE_id_delete(bmain, id); + } +} + static IDOverrideLibraryProperty *rna_ID_override_library_properties_add( IDOverrideLibrary *override_library, ReportList *reports, const char rna_path[]) { @@ -1731,6 +1770,28 @@ static void rna_def_ID_override_library(BlenderRNA *brna) "Update the library override operations based on the " "differences between this override ID and its reference"); + func = RNA_def_function(srna, "reset", "rna_ID_override_library_reset"); + RNA_def_function_ui_description(func, + "Reset this override to match again its linked reference ID"); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_SELF_ID | FUNC_USE_REPORTS); + RNA_def_boolean( + func, + "do_hierarchy", + true, + "", + "Also reset all the dependencies of this override to match their reference linked IDs"); + + func = RNA_def_function(srna, "destroy", "rna_ID_override_library_destroy"); + RNA_def_function_ui_description( + func, "Delete this override ID and remap its usages to its linked reference ID instead"); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_SELF_ID | FUNC_USE_REPORTS); + RNA_def_boolean(func, + "do_hierarchy", + true, + "", + "Also delete all the dependencies of this override and remap their usages to " + "their reference linked IDs"); + rna_def_ID_override_library_property(brna); } diff --git a/tests/python/bl_blendfile_library_overrides.py b/tests/python/bl_blendfile_library_overrides.py index 19f06dc698e..358f77d49ea 100644 --- a/tests/python/bl_blendfile_library_overrides.py +++ b/tests/python/bl_blendfile_library_overrides.py @@ -71,6 +71,16 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase): # Setting location.y overridded all elements in the location array. -1 is a wildcard. assert(override_operation.subitem_local_index == -1) + local_id.override_library.reset() + + assert(len(local_id.override_library.properties) == 0) + assert(local_id.location == local_id.override_library.reference.location) + + local_id_name = local_id.name + assert(bpy.data.objects.get((local_id_name, None), None) == local_id) + local_id.override_library.destroy() + assert(bpy.data.objects.get((local_id_name, None), None) == None) + def test_link_permissive(self): """ Linked assets with a permissive template. -- cgit v1.2.3 From 58ba75f9e3bfc4ff08dbd1f2ce269c65388dfcfd Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 4 Aug 2021 16:56:06 +0200 Subject: LibOverride RNA API: add removal of properties and operations. This should complete the basics of RNA API for library overrides. Ref. T86656. --- source/blender/makesrna/intern/rna_ID.c | 45 ++++++++++++++++++++++++++ tests/python/bl_blendfile_library_overrides.py | 24 ++++++++++++-- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index e4c9b70a1ec..8f8ad077935 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -807,6 +807,18 @@ static IDOverrideLibraryProperty *rna_ID_override_library_properties_add( return result; } +static void rna_ID_override_library_properties_remove(IDOverrideLibrary *override_library, + ReportList *reports, + IDOverrideLibraryProperty *override_property) +{ + if (BLI_findindex(&override_library->properties, override_property) == -1) { + BKE_report(reports, RPT_ERROR, "Override property cannot be removed"); + return; + } + + BKE_lib_override_library_property_delete(override_library, override_property); +} + static IDOverrideLibraryPropertyOperation *rna_ID_override_library_property_operations_add( IDOverrideLibraryProperty *override_property, ReportList *reports, @@ -834,6 +846,19 @@ static IDOverrideLibraryPropertyOperation *rna_ID_override_library_property_oper return result; } +static void rna_ID_override_library_property_operations_remove( + IDOverrideLibraryProperty *override_property, + ReportList *reports, + IDOverrideLibraryPropertyOperation *override_operation) +{ + if (BLI_findindex(&override_property->operations, override_operation) == -1) { + BKE_report(reports, RPT_ERROR, "Override operation cannot be removed"); + return; + } + + BKE_lib_override_library_property_operation_delete(override_property, override_operation); +} + static void rna_ID_update_tag(ID *id, Main *bmain, ReportList *reports, int flag) { /* XXX, new function for this! */ @@ -1685,6 +1710,16 @@ static void rna_def_ID_override_library_property_operations(BlenderRNA *brna, Pr "New Operation", "Created operation"); RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_ID_override_library_property_operations_remove"); + RNA_def_function_ui_description(func, "Remove and delete an operation"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, + "operation", + "IDOverrideLibraryPropertyOperation", + "Operation", + "Override operation to be deleted"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); } static void rna_def_ID_override_library_property(BlenderRNA *brna) @@ -1741,6 +1776,16 @@ static void rna_def_ID_override_library_properties(BlenderRNA *brna, PropertyRNA parm = RNA_def_string( func, "rna_path", NULL, 256, "RNA Path", "RNA-Path of the property to add"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + + func = RNA_def_function(srna, "remove", "rna_ID_override_library_properties_remove"); + RNA_def_function_ui_description(func, "Remove and delete a property"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, + "property", + "IDOverrideLibraryProperty", + "Property", + "Override property to be deleted"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); } static void rna_def_ID_override_library(BlenderRNA *brna) diff --git a/tests/python/bl_blendfile_library_overrides.py b/tests/python/bl_blendfile_library_overrides.py index 358f77d49ea..b44e4d48564 100644 --- a/tests/python/bl_blendfile_library_overrides.py +++ b/tests/python/bl_blendfile_library_overrides.py @@ -59,9 +59,9 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase): self.assertIsNone(local_id.data.override_library) assert(len(local_id.override_library.properties) == 0) + ##### Generate an override property & operation automaticaly by editing the local override data. local_id.location.y = 1.0 local_id.override_library.operations_update() - assert(len(local_id.override_library.properties) == 1) override_prop = local_id.override_library.properties[0] assert(override_prop.rna_path == "location") @@ -71,11 +71,31 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase): # Setting location.y overridded all elements in the location array. -1 is a wildcard. assert(override_operation.subitem_local_index == -1) + ##### Reset the override to its linked reference data. local_id.override_library.reset() - assert(len(local_id.override_library.properties) == 0) assert(local_id.location == local_id.override_library.reference.location) + ##### Generate an override property & operation manually using the API. + override_property = local_id.override_library.properties.add(rna_path="location") + override_property.operations.add(operation='REPLACE') + + assert(len(local_id.override_library.properties) == 1) + override_prop = local_id.override_library.properties[0] + assert(override_prop.rna_path == "location") + assert(len(override_prop.operations) == 1) + override_operation = override_prop.operations[0] + assert(override_operation.operation == 'REPLACE') + # Setting location.y overridded all elements in the location array. -1 is a wildcard. + assert(override_operation.subitem_local_index == -1) + + override_property = local_id.override_library.properties[0] + override_property.operations.remove(override_property.operations[0]) + local_id.override_library.properties.remove(override_property) + + assert(len(local_id.override_library.properties) == 0) + + ##### Delete the override. local_id_name = local_id.name assert(bpy.data.objects.get((local_id_name, None), None) == local_id) local_id.override_library.destroy() -- cgit v1.2.3 From c18d91918fbb18d8c0d2e95de210ba818937cd87 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 3 Aug 2021 12:20:28 +0200 Subject: Cycles: More flexible GI Approximation AO distance control The goal: allow to easily use AO approximation in scenes which combines both small and large scale objects. The idea: use per-object AO distance which will allow to override world settings. Instancer object will "propagate" its AO distance to all its instances unless the instance defines own distance (this allows to modify AO distance in the shot files, without requiring to modify props used in the shots. Available from the new Fats GI Approximation panel in object properties. Differential Revision: https://developer.blender.org/D12112 --- intern/cycles/blender/addon/properties.py | 8 ++++++++ intern/cycles/blender/addon/ui.py | 21 +++++++++++++++++++++ intern/cycles/blender/blender_object.cpp | 7 +++++++ intern/cycles/kernel/bvh/bvh_util.h | 10 ++++++++++ intern/cycles/kernel/kernel_bake.h | 6 ++++-- intern/cycles/kernel/kernel_path.h | 16 ++++++++++++---- intern/cycles/kernel/kernel_path_branched.h | 11 +++++++---- intern/cycles/kernel/kernel_types.h | 5 ++++- intern/cycles/kernel/split/kernel_scene_intersect.h | 5 ++++- intern/cycles/render/object.cpp | 3 +++ intern/cycles/render/object.h | 2 ++ 11 files changed, 82 insertions(+), 12 deletions(-) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 4cd75edee5f..70efb1054a2 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -1268,6 +1268,14 @@ class CyclesObjectSettings(bpy.types.PropertyGroup): default=0.1, ) + ao_distance: FloatProperty( + name="AO Distance", + description="AO distance used for approximate global illumination (0 means use world setting)", + min=0.0, + default=0.0, + subtype='DISTANCE', + ) + is_shadow_catcher: BoolProperty( name="Shadow Catcher", description="Only render shadows on this object, for compositing renders into real footage", diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index e9a4ce77080..8846c621529 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1228,6 +1228,26 @@ class CYCLES_OBJECT_PT_shading_shadow_terminator(CyclesButtonsPanel, Panel): flow.prop(cob, "shadow_terminator_offset", text="Shading Offset") +class CYCLES_OBJECT_PT_gi_approximation(CyclesButtonsPanel, Panel): + bl_label = "Fast GI Approximation" + bl_context = "object" + bl_options = {'DEFAULT_CLOSED'} + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + scene = context.scene + ob = context.object + + cob = ob.cycles + cscene = scene.cycles + + col = layout.column() + col.active = cscene.use_fast_gi + col.prop(cob, "ao_distance") + + class CYCLES_OBJECT_PT_visibility(CyclesButtonsPanel, Panel): bl_label = "Visibility" bl_context = "object" @@ -2305,6 +2325,7 @@ classes = ( CYCLES_OBJECT_PT_motion_blur, CYCLES_OBJECT_PT_shading, CYCLES_OBJECT_PT_shading_shadow_terminator, + CYCLES_OBJECT_PT_gi_approximation, CYCLES_OBJECT_PT_visibility, CYCLES_OBJECT_PT_visibility_ray_visibility, CYCLES_OBJECT_PT_visibility_culling, diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index f5e8db2aee1..65b5ac2c58f 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -297,6 +297,13 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, "shadow_terminator_geometry_offset"); object->set_shadow_terminator_geometry_offset(shadow_terminator_geometry_offset); + float ao_distance = get_float(cobject, "ao_distance"); + if (ao_distance == 0.0f && b_parent.ptr.data != b_ob.ptr.data) { + PointerRNA cparent = RNA_pointer_get(&b_parent.ptr, "cycles"); + ao_distance = get_float(cparent, "ao_distance"); + } + object->set_ao_distance(ao_distance); + /* sync the asset name for Cryptomatte */ BL::Object parent = b_ob.parent(); ustring parent_name; diff --git a/intern/cycles/kernel/bvh/bvh_util.h b/intern/cycles/kernel/bvh/bvh_util.h index 867ea3af8d1..b1faebce957 100644 --- a/intern/cycles/kernel/bvh/bvh_util.h +++ b/intern/cycles/kernel/bvh/bvh_util.h @@ -239,4 +239,14 @@ ccl_device_forceinline int intersection_get_shader(KernelGlobals *ccl_restrict k return shader & SHADER_MASK; } +ccl_device_forceinline int intersection_get_object(KernelGlobals *ccl_restrict kg, + const Intersection *ccl_restrict isect) +{ + if (isect->object != OBJECT_NONE) { + return isect->object; + } + + return kernel_tex_fetch(__prim_object, isect->prim); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h index d1f33a4d0f0..7da890b908d 100644 --- a/intern/cycles/kernel/kernel_bake.h +++ b/intern/cycles/kernel/kernel_bake.h @@ -81,7 +81,8 @@ ccl_device_noinline void compute_light_pass( kg, sd, emission_sd, L, &state, &ray, &throughput, &ss_indirect)) { while (ss_indirect.num_rays) { kernel_path_subsurface_setup_indirect(kg, &ss_indirect, &state, &ray, L, &throughput); - kernel_path_indirect(kg, &indirect_sd, emission_sd, &ray, throughput, &state, L); + kernel_path_indirect( + kg, &indirect_sd, emission_sd, &ray, throughput, &state, L, sd->object); } is_sss_sample = true; } @@ -97,7 +98,8 @@ ccl_device_noinline void compute_light_pass( state.ray_t = 0.0f; # endif /* compute indirect light */ - kernel_path_indirect(kg, &indirect_sd, emission_sd, &ray, throughput, &state, L); + kernel_path_indirect( + kg, &indirect_sd, emission_sd, &ray, throughput, &state, L, sd->object); /* sum and reset indirect light pass variables for the next samples */ path_radiance_sum_indirect(L); diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 3430543bc8e..ec577fa20b0 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -58,7 +58,8 @@ ccl_device_forceinline bool kernel_path_scene_intersect(KernelGlobals *kg, ccl_addr_space PathState *state, Ray *ray, Intersection *isect, - PathRadiance *L) + PathRadiance *L, + const int last_object) { PROFILING_INIT(kg, PROFILING_SCENE_INTERSECT); @@ -66,6 +67,12 @@ ccl_device_forceinline bool kernel_path_scene_intersect(KernelGlobals *kg, if (path_state_ao_bounce(kg, state)) { ray->t = kernel_data.background.ao_distance; + if (last_object != OBJECT_NONE) { + const float object_ao_distance = kernel_tex_fetch(__objects, last_object).ao_distance; + if (object_ao_distance != 0.0f) { + ray->t = object_ao_distance; + } + } } bool hit = scene_intersect(kg, ray, visibility, isect); @@ -369,7 +376,8 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, Ray *ray, float3 throughput, PathState *state, - PathRadiance *L) + PathRadiance *L, + const int last_object) { # ifdef __SUBSURFACE__ SubsurfaceIndirectRays ss_indirect; @@ -382,7 +390,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, for (;;) { /* Find intersection with objects in scene. */ Intersection isect; - bool hit = kernel_path_scene_intersect(kg, state, ray, &isect, L); + bool hit = kernel_path_scene_intersect(kg, state, ray, &isect, L, last_object); /* Find intersection with lamps and compute emission for MIS. */ kernel_path_lamp_emission(kg, state, ray, throughput, &isect, sd, L); @@ -526,7 +534,7 @@ ccl_device_forceinline void kernel_path_integrate(KernelGlobals *kg, for (;;) { /* Find intersection with objects in scene. */ Intersection isect; - bool hit = kernel_path_scene_intersect(kg, state, ray, &isect, L); + bool hit = kernel_path_scene_intersect(kg, state, ray, &isect, L, sd.object); /* Find intersection with lamps and compute emission for MIS. */ kernel_path_lamp_emission(kg, state, ray, throughput, &isect, &sd, L); diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h index 5ea7687ec3b..a1ee1bc107e 100644 --- a/intern/cycles/kernel/kernel_path_branched.h +++ b/intern/cycles/kernel/kernel_path_branched.h @@ -92,6 +92,7 @@ ccl_device_forceinline void kernel_branched_path_volume(KernelGlobals *kg, volume_ray.t = (hit) ? isect->t : FLT_MAX; float step_size = volume_stack_step_size(kg, state->volume_stack); + const int object = sd->object; # ifdef __VOLUME_DECOUPLED__ /* decoupled ray marching only supported on CPU */ @@ -134,7 +135,8 @@ ccl_device_forceinline void kernel_branched_path_volume(KernelGlobals *kg, if (result == VOLUME_PATH_SCATTERED && kernel_path_volume_bounce(kg, sd, &tp, &ps, &L->state, &pray)) { - kernel_path_indirect(kg, indirect_sd, emission_sd, &pray, tp * num_samples_inv, &ps, L); + kernel_path_indirect( + kg, indirect_sd, emission_sd, &pray, tp * num_samples_inv, &ps, L, object); /* for render passes, sum and reset indirect light pass variables * for the next samples */ @@ -180,7 +182,7 @@ ccl_device_forceinline void kernel_branched_path_volume(KernelGlobals *kg, kernel_path_volume_connect_light(kg, sd, emission_sd, tp, state, L); if (kernel_path_volume_bounce(kg, sd, &tp, &ps, &L->state, &pray)) { - kernel_path_indirect(kg, indirect_sd, emission_sd, &pray, tp, &ps, L); + kernel_path_indirect(kg, indirect_sd, emission_sd, &pray, tp, &ps, L, object); /* for render passes, sum and reset indirect light pass variables * for the next samples */ @@ -266,7 +268,8 @@ ccl_device_noinline_cpu void kernel_branched_path_surface_indirect_light(KernelG ps.rng_hash = state->rng_hash; - kernel_path_indirect(kg, indirect_sd, emission_sd, &bsdf_ray, tp * num_samples_inv, &ps, L); + kernel_path_indirect( + kg, indirect_sd, emission_sd, &bsdf_ray, tp * num_samples_inv, &ps, L, sd->object); /* for render passes, sum and reset indirect light pass variables * for the next samples */ @@ -395,7 +398,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg, for (;;) { /* Find intersection with objects in scene. */ Intersection isect; - bool hit = kernel_path_scene_intersect(kg, &state, &ray, &isect, L); + bool hit = kernel_path_scene_intersect(kg, &state, &ray, &isect, L, sd.object); # ifdef __VOLUME__ /* Volume integration. */ diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index f9ea3a2d0a8..7cbe18acf28 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -1447,7 +1447,10 @@ typedef struct KernelObject { float shadow_terminator_shading_offset; float shadow_terminator_geometry_offset; - float pad1, pad2, pad3; + + float ao_distance; + + float pad1, pad2; } KernelObject; static_assert_align(KernelObject, 16); diff --git a/intern/cycles/kernel/split/kernel_scene_intersect.h b/intern/cycles/kernel/split/kernel_scene_intersect.h index 5fef3e045f8..9ac95aafd2f 100644 --- a/intern/cycles/kernel/split/kernel_scene_intersect.h +++ b/intern/cycles/kernel/split/kernel_scene_intersect.h @@ -65,7 +65,10 @@ ccl_device void kernel_scene_intersect(KernelGlobals *kg) PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; Intersection isect; - bool hit = kernel_path_scene_intersect(kg, state, &ray, &isect, L); + const int last_object = state->bounce > 0 ? + intersection_get_object(kg, &kernel_split_state.isect[ray_index]) : + OBJECT_NONE; + bool hit = kernel_path_scene_intersect(kg, state, &ray, &isect, L, last_object); kernel_split_state.isect[ray_index] = isect; if (!hit) { diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 5fe4e9ed57f..c88d94fe4c2 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -102,6 +102,8 @@ NODE_DEFINE(Object) SOCKET_NODE(particle_system, "Particle System", ParticleSystem::get_node_type()); SOCKET_INT(particle_index, "Particle Index", 0); + SOCKET_FLOAT(ao_distance, "AO Distance", 0.0f); + return type; } @@ -428,6 +430,7 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s kobject.random_number = random_number; kobject.particle_index = particle_index; kobject.motion_offset = 0; + kobject.ao_distance = ob->ao_distance; if (geom->get_use_motion_blur()) { state->have_motion = true; diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index ebb7733c2aa..c52ddce48da 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -73,6 +73,8 @@ class Object : public Node { NODE_SOCKET_API(ParticleSystem *, particle_system); NODE_SOCKET_API(int, particle_index); + NODE_SOCKET_API(float, ao_distance) + Object(); ~Object(); -- cgit v1.2.3 From b5bfb5f34c1228df0ba673faf9d2a38a866115ac Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Wed, 4 Aug 2021 08:33:19 -0700 Subject: UI: VFont Display Names When displaying the names of fonts for 3D Text objects, use the same format as shown in File Browser: Family name + Style name. They are currently shown with Postscript Name, which doesn't match well. see D12069 for more details. Differential Revision: https://developer.blender.org/D12069 Reviewed by Campbell Barton --- source/blender/blenlib/intern/freetypefont.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c index 98da85e3a8c..15c4910310f 100644 --- a/source/blender/blenlib/intern/freetypefont.c +++ b/source/blender/blenlib/intern/freetypefont.c @@ -40,6 +40,7 @@ #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_string.h" +#include "BLI_string_utf8.h" #include "BLI_utildefines.h" #include "BLI_vfontdata.h" @@ -286,7 +287,6 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile *pf) const FT_ULong charcode_reserve = 256; FT_ULong charcode = 0, lcode; FT_UInt glyph_index; - const char *fontname; VFontData *vfd; /* load the freetype font */ @@ -299,9 +299,11 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile *pf) /* allocate blender font */ vfd = MEM_callocN(sizeof(*vfd), "FTVFontData"); - /* get the name */ - fontname = FT_Get_Postscript_Name(face); - BLI_strncpy(vfd->name, (fontname == NULL) ? "" : fontname, sizeof(vfd->name)); + /* Get the name. */ + if (face->family_name) { + BLI_snprintf(vfd->name, sizeof(vfd->name), "%s %s", face->family_name, face->style_name); + BLI_utf8_invalid_strip(vfd->name, strlen(vfd->name)); + } /* Extract the first 256 character from TTF */ lcode = charcode = FT_Get_First_Char(face, &glyph_index); -- cgit v1.2.3 From ae920d789ed3986e7c50049c074739fed7d33f32 Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Wed, 4 Aug 2021 09:31:01 -0700 Subject: VSE: Allow Wingdings and Symbol Fonts This patch makes us less restrictive on the allowed types of FreeType font character maps we allow, rather than primarily unicode-only. This allows us to use some legacy, symbol, specialty, and proprietary fonts like Wingdings. Note we were a little less restrictive with vfonts, used for 3D Text Objects, so this patch primarily helps VSE. See D12124 for details and examples. Differential Revision: https://developer.blender.org/D12124 Reviewed by Brecht Van Lommel --- source/blender/blenfont/intern/blf_font.c | 10 ++++++-- source/blender/blenlib/intern/freetypefont.c | 37 +++++++++++----------------- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index 53c4135254a..6e2be4a8353 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -1359,9 +1359,15 @@ FontBLF *blf_font_new(const char *name, const char *filename) return NULL; } - err = FT_Select_Charmap(font->face, ft_encoding_unicode); + err = FT_Select_Charmap(font->face, FT_ENCODING_UNICODE); if (err) { - printf("Can't set the unicode character map!\n"); + err = FT_Select_Charmap(font->face, FT_ENCODING_APPLE_ROMAN); + } + if (err && font->face->num_charmaps > 0) { + err = FT_Select_Charmap(font->face, font->face->charmaps[0]->encoding); + } + if (err) { + printf("Can't set a character map!\n"); FT_Done_Face(font->face); MEM_freeN(font); return NULL; diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c index 15c4910310f..a8b50b66f5f 100644 --- a/source/blender/blenlib/intern/freetypefont.c +++ b/source/blender/blenlib/intern/freetypefont.c @@ -305,32 +305,23 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile *pf) BLI_utf8_invalid_strip(vfd->name, strlen(vfd->name)); } + /* Select a character map. */ + err = FT_Select_Charmap(face, FT_ENCODING_UNICODE); + if (err) { + err = FT_Select_Charmap(face, FT_ENCODING_APPLE_ROMAN); + } + if (err && face->num_charmaps > 0) { + err = FT_Select_Charmap(face, face->charmaps[0]->encoding); + } + if (err) { + FT_Done_Face(face); + MEM_freeN(vfd); + return NULL; + } + /* Extract the first 256 character from TTF */ lcode = charcode = FT_Get_First_Char(face, &glyph_index); - /* No `charmap` found from the TTF so we need to figure it out. */ - if (glyph_index == 0) { - FT_CharMap found = NULL; - FT_CharMap charmap; - int n; - - for (n = 0; n < face->num_charmaps; n++) { - charmap = face->charmaps[n]; - if (charmap->encoding == FT_ENCODING_APPLE_ROMAN) { - found = charmap; - break; - } - } - - err = FT_Set_Charmap(face, found); - - if (err) { - return NULL; - } - - lcode = charcode = FT_Get_First_Char(face, &glyph_index); - } - /* Blender default BFont is not "complete". */ const bool complete_font = (face->ascender != 0) && (face->descender != 0) && (face->ascender != face->descender); -- cgit v1.2.3 From 10b9621079823048e73d4677413bc5e59f833dcf Mon Sep 17 00:00:00 2001 From: Romain Toumi Date: Mon, 2 Aug 2021 19:54:04 +0200 Subject: Fix Cycles material slots list being too short Bring it in line with Eevee. Differential Revision: https://developer.blender.org/D11982 --- intern/cycles/blender/addon/ui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 8846c621529..336fb02ba36 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1102,7 +1102,7 @@ class CYCLES_PT_context_material(CyclesButtonsPanel, Panel): if ob: is_sortable = len(ob.material_slots) > 1 - rows = 1 + rows = 3 if (is_sortable): rows = 4 -- cgit v1.2.3 From 8abf6efcf60fa7f609f38fda0e085d84a72b6dba Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 4 Aug 2021 17:46:55 +0200 Subject: Cleanup: rename restrict to hide/visibility in Object, Collection, MaskLayer This makes the internal naming consistent with the public API. And also gives us a visibility_flag rather than restrictflag that can be extended with more flags. --- source/blender/blenkernel/BKE_collection.h | 7 ++- source/blender/blenkernel/intern/collection.c | 6 +- source/blender/blenkernel/intern/layer.c | 28 ++++----- source/blender/blenkernel/intern/lib_override.c | 7 +-- source/blender/blenkernel/intern/mask.c | 4 +- source/blender/blenkernel/intern/mask_rasterize.c | 2 +- source/blender/blenkernel/intern/object_dupli.cc | 6 +- source/blender/blenkernel/intern/scene.c | 2 +- source/blender/blenloader/intern/versioning_280.c | 14 ++--- source/blender/bmesh/intern/bmesh_walkers_impl.c | 8 +-- .../depsgraph/intern/builder/deg_builder_nodes.cc | 6 +- .../intern/builder/deg_builder_nodes_view_layer.cc | 6 +- .../builder/deg_builder_relations_view_layer.cc | 6 +- source/blender/editors/animation/anim_filter.c | 4 +- source/blender/editors/animation/anim_markers.c | 2 +- source/blender/editors/mask/mask_add.c | 2 +- source/blender/editors/mask/mask_draw.c | 8 +-- source/blender/editors/mask/mask_ops.c | 24 ++++---- source/blender/editors/mask/mask_query.c | 8 +-- source/blender/editors/mask/mask_relationships.c | 4 +- source/blender/editors/mask/mask_select.c | 20 +++---- source/blender/editors/mask/mask_shapekey.c | 4 +- source/blender/editors/object/object_add.c | 2 +- source/blender/editors/object/object_bake_api.c | 10 ++-- source/blender/editors/object/object_edit.c | 6 +- source/blender/editors/render/render_preview.c | 8 +-- source/blender/editors/screen/screen_ops.c | 2 +- source/blender/editors/space_clip/clip_utils.c | 2 +- .../editors/space_outliner/outliner_collections.c | 10 ++-- .../editors/transform/transform_convert_mask.c | 4 +- .../gpencil_modifiers/intern/lineart/lineart_cpu.c | 4 +- source/blender/makesdna/DNA_collection_types.h | 6 +- source/blender/makesdna/DNA_layer_types.h | 2 +- source/blender/makesdna/DNA_mask_types.h | 10 ++-- source/blender/makesdna/DNA_object_types.h | 10 ++-- source/blender/makesdna/intern/dna_rename_defs.h | 2 + source/blender/makesrna/intern/rna_collection.c | 12 ++-- source/blender/makesrna/intern/rna_layer.c | 2 +- source/blender/makesrna/intern/rna_mask.c | 6 +- source/blender/makesrna/intern/rna_object.c | 70 ++++++++++++---------- 40 files changed, 177 insertions(+), 169 deletions(-) diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h index 0326386e5c1..8b8d0f7b107 100644 --- a/source/blender/blenkernel/BKE_collection.h +++ b/source/blender/blenkernel/BKE_collection.h @@ -197,13 +197,14 @@ typedef void (*BKE_scene_collections_Cb)(struct Collection *ob, void *data); #define FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN(_collection, _object, _mode) \ { \ int _base_flag = (_mode == DAG_EVAL_VIEWPORT) ? BASE_ENABLED_VIEWPORT : BASE_ENABLED_RENDER; \ - int _object_restrict_flag = (_mode == DAG_EVAL_VIEWPORT) ? OB_RESTRICT_VIEWPORT : \ - OB_RESTRICT_RENDER; \ + int _object_visibility_flag = (_mode == DAG_EVAL_VIEWPORT) ? OB_HIDE_VIEWPORT : \ + OB_HIDE_RENDER; \ int _base_id = 0; \ for (Base *_base = (Base *)BKE_collection_object_cache_get(_collection).first; _base; \ _base = _base->next, _base_id++) { \ Object *_object = _base->object; \ - if ((_base->flag & _base_flag) && (_object->restrictflag & _object_restrict_flag) == 0) { + if ((_base->flag & _base_flag) && \ + (_object->visibility_flag & _object_visibility_flag) == 0) { #define FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END \ } \ diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index b90214f1814..dbcd80fe065 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -806,10 +806,10 @@ static void collection_object_cache_fill(ListBase *lb, /* Only collection flags are checked here currently, object restrict flag is checked * in FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN since it can be animated * without updating the cache. */ - if (((child_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0)) { + if (((child_restrict & COLLECTION_HIDE_VIEWPORT) == 0)) { base->flag |= BASE_ENABLED_VIEWPORT; } - if (((child_restrict & COLLECTION_RESTRICT_RENDER) == 0)) { + if (((child_restrict & COLLECTION_HIDE_RENDER) == 0)) { base->flag |= BASE_ENABLED_RENDER; } } @@ -1755,7 +1755,7 @@ static bool collection_objects_select(ViewLayer *view_layer, Collection *collect { bool changed = false; - if (collection->flag & COLLECTION_RESTRICT_SELECT) { + if (collection->flag & COLLECTION_HIDE_SELECT) { return false; } diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index ae1863f0a47..5940569ba76 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -602,7 +602,7 @@ static bool layer_collection_hidden(ViewLayer *view_layer, LayerCollection *lc) } /* Check visiblilty restriction flags */ - if (lc->flag & LAYER_COLLECTION_HIDE || lc->collection->flag & COLLECTION_RESTRICT_VIEWPORT) { + if (lc->flag & LAYER_COLLECTION_HIDE || lc->collection->flag & COLLECTION_HIDE_VIEWPORT) { return true; } @@ -1005,17 +1005,17 @@ static void layer_collection_objects_sync(ViewLayer *view_layer, BLI_addtail(r_lb_new_object_bases, base); } - if ((collection_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0) { + if ((collection_restrict & COLLECTION_HIDE_VIEWPORT) == 0) { base->flag_from_collection |= (BASE_ENABLED_VIEWPORT | BASE_VISIBLE_DEPSGRAPH); if ((layer_restrict & LAYER_COLLECTION_HIDE) == 0) { base->flag_from_collection |= BASE_VISIBLE_VIEWLAYER; } - if (((collection_restrict & COLLECTION_RESTRICT_SELECT) == 0)) { + if (((collection_restrict & COLLECTION_HIDE_SELECT) == 0)) { base->flag_from_collection |= BASE_SELECTABLE; } } - if ((collection_restrict & COLLECTION_RESTRICT_RENDER) == 0) { + if ((collection_restrict & COLLECTION_HIDE_RENDER) == 0) { base->flag_from_collection |= BASE_ENABLED_RENDER; } @@ -1150,11 +1150,11 @@ static void layer_collection_sync(ViewLayer *view_layer, /* We separate restrict viewport and visible view layer because a layer collection can be * hidden in the view layer yet (locally) visible in a viewport (if it is not restricted). */ - if (child_collection_restrict & COLLECTION_RESTRICT_VIEWPORT) { - child_layer->runtime_flag |= LAYER_COLLECTION_RESTRICT_VIEWPORT; + if (child_collection_restrict & COLLECTION_HIDE_VIEWPORT) { + child_layer->runtime_flag |= LAYER_COLLECTION_HIDE_VIEWPORT; } - if (((child_layer->runtime_flag & LAYER_COLLECTION_RESTRICT_VIEWPORT) == 0) && + if (((child_layer->runtime_flag & LAYER_COLLECTION_HIDE_VIEWPORT) == 0) && ((child_layer_restrict & LAYER_COLLECTION_HIDE) == 0)) { child_layer->runtime_flag |= LAYER_COLLECTION_VISIBLE_VIEW_LAYER; } @@ -1333,7 +1333,7 @@ void BKE_main_collection_sync_remap(const Main *bmain) */ bool BKE_layer_collection_objects_select(ViewLayer *view_layer, LayerCollection *lc, bool deselect) { - if (lc->collection->flag & COLLECTION_RESTRICT_SELECT) { + if (lc->collection->flag & COLLECTION_HIDE_SELECT) { return false; } @@ -1369,7 +1369,7 @@ bool BKE_layer_collection_objects_select(ViewLayer *view_layer, LayerCollection bool BKE_layer_collection_has_selected_objects(ViewLayer *view_layer, LayerCollection *lc) { - if (lc->collection->flag & COLLECTION_RESTRICT_SELECT) { + if (lc->collection->flag & COLLECTION_HIDE_SELECT) { return false; } @@ -1457,7 +1457,7 @@ bool BKE_object_is_visible_in_viewport(const View3D *v3d, const struct Object *o { BLI_assert(v3d != NULL); - if (ob->restrictflag & OB_RESTRICT_VIEWPORT) { + if (ob->visibility_flag & OB_HIDE_VIEWPORT) { return false; } @@ -2146,14 +2146,14 @@ void BKE_base_eval_flags(Base *base) base->flag |= (base->flag_from_collection & g_base_collection_flags); /* Apply object restrictions. */ - const int object_restrict = base->object->restrictflag; - if (object_restrict & OB_RESTRICT_VIEWPORT) { + const int object_restrict = base->object->visibility_flag; + if (object_restrict & OB_HIDE_VIEWPORT) { base->flag &= ~BASE_ENABLED_VIEWPORT; } - if (object_restrict & OB_RESTRICT_RENDER) { + if (object_restrict & OB_HIDE_RENDER) { base->flag &= ~BASE_ENABLED_RENDER; } - if (object_restrict & OB_RESTRICT_SELECT) { + if (object_restrict & OB_HIDE_SELECT) { base->flag &= ~BASE_SELECTABLE; } diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 8e67547b719..38687fa47b2 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -855,8 +855,8 @@ static void lib_override_library_create_post_process(Main *bmain, default_instantiating_collection = BKE_collection_add( bmain, (Collection *)id_root, "OVERRIDE_HIDDEN"); /* Hide the collection from viewport and render. */ - default_instantiating_collection->flag |= COLLECTION_RESTRICT_VIEWPORT | - COLLECTION_RESTRICT_RENDER; + default_instantiating_collection->flag |= COLLECTION_HIDE_VIEWPORT | + COLLECTION_HIDE_RENDER; break; } case ID_OB: { @@ -1731,8 +1731,7 @@ void BKE_lib_override_library_main_resync(Main *bmain, override_resync_residual_storage = BKE_collection_add( bmain, scene->master_collection, OVERRIDE_RESYNC_RESIDUAL_STORAGE_NAME); /* Hide the collection from viewport and render. */ - override_resync_residual_storage->flag |= COLLECTION_RESTRICT_VIEWPORT | - COLLECTION_RESTRICT_RENDER; + override_resync_residual_storage->flag |= COLLECTION_HIDE_VIEWPORT | COLLECTION_HIDE_RENDER; } /* Necessary to improve performances, and prevent layers matching override sub-collections to be diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 34dd38164c2..f40d1db60ff 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -429,7 +429,7 @@ MaskLayer *BKE_mask_layer_copy(const MaskLayer *masklay) masklay_new->blend_flag = masklay->blend_flag; masklay_new->flag = masklay->flag; masklay_new->falloff = masklay->falloff; - masklay_new->restrictflag = masklay->restrictflag; + masklay_new->visibility_flag = masklay->visibility_flag; for (spline = masklay->splines.first; spline; spline = spline->next) { MaskSpline *spline_new = BKE_mask_spline_copy(spline); @@ -2092,7 +2092,7 @@ void BKE_mask_clipboard_copy_from_layer(MaskLayer *mask_layer) MaskSpline *spline; /* Nothing to do if selection if disabled for the given layer. */ - if (mask_layer->restrictflag & MASK_RESTRICT_SELECT) { + if (mask_layer->visibility_flag & MASK_HIDE_SELECT) { return; } diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index 00ed7d86975..8acc929a089 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -619,7 +619,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, unsigned int tot_boundary_found = 0; #endif - if (masklay->restrictflag & MASK_RESTRICT_RENDER) { + if (masklay->visibility_flag & MASK_HIDE_RENDER) { /* skip the layer */ mr_handle->layers_tot--; masklay_index--; diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc index 77969328365..141a9a25eca 100644 --- a/source/blender/blenkernel/intern/object_dupli.cc +++ b/source/blender/blenkernel/intern/object_dupli.cc @@ -1554,15 +1554,15 @@ static const DupliGenerator gen_dupli_particles = { static const DupliGenerator *get_dupli_generator(const DupliContext *ctx) { int transflag = ctx->object->transflag; - int restrictflag = ctx->object->restrictflag; + int visibility_flag = ctx->object->visibility_flag; if ((transflag & OB_DUPLI) == 0 && ctx->object->runtime.geometry_set_eval == nullptr) { return nullptr; } /* Should the dupli's be generated for this object? - Respect restrict flags. */ - if (DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER ? (restrictflag & OB_RESTRICT_RENDER) : - (restrictflag & OB_RESTRICT_VIEWPORT)) { + if (DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER ? (visibility_flag & OB_HIDE_RENDER) : + (visibility_flag & OB_HIDE_VIEWPORT)) { return nullptr; } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 3f75d0963c6..6d60f5e91b4 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -2305,7 +2305,7 @@ Object *BKE_scene_camera_switch_find(Scene *scene) Object *first_camera = NULL; LISTBASE_FOREACH (TimeMarker *, m, &scene->markers) { - if (m->camera && (m->camera->restrictflag & OB_RESTRICT_RENDER) == 0) { + if (m->camera && (m->camera->visibility_flag & OB_HIDE_RENDER) == 0) { if ((m->frame <= ctime) && (m->frame > frame)) { camera = m->camera; frame = m->frame; diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 93959237f29..9d65488e8d4 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -321,7 +321,7 @@ static void do_version_layer_collection_post(ViewLayer *view_layer, lc->flag |= LAYER_COLLECTION_EXCLUDE; } if (enabled && !selectable) { - lc->collection->flag |= COLLECTION_RESTRICT_SELECT; + lc->collection->flag |= COLLECTION_HIDE_SELECT; } } @@ -450,7 +450,7 @@ static void do_version_layers_to_collections(Main *bmain, Scene *scene) collections[layer] = collection; if (!(scene->lay & (1 << layer))) { - collection->flag |= COLLECTION_RESTRICT_VIEWPORT | COLLECTION_RESTRICT_RENDER; + collection->flag |= COLLECTION_HIDE_VIEWPORT | COLLECTION_HIDE_RENDER; } } @@ -1198,7 +1198,7 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) /* Add fake user for all existing groups. */ id_fake_user_set(&collection->id); - if (collection->flag & (COLLECTION_RESTRICT_VIEWPORT | COLLECTION_RESTRICT_RENDER)) { + if (collection->flag & (COLLECTION_HIDE_VIEWPORT | COLLECTION_HIDE_RENDER)) { continue; } @@ -1229,8 +1229,7 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) char name[MAX_ID_NAME]; BLI_snprintf(name, sizeof(name), DATA_("Hidden %d"), coll_idx + 1); *collection_hidden = BKE_collection_add(bmain, collection, name); - (*collection_hidden)->flag |= COLLECTION_RESTRICT_VIEWPORT | - COLLECTION_RESTRICT_RENDER; + (*collection_hidden)->flag |= COLLECTION_HIDE_VIEWPORT | COLLECTION_HIDE_RENDER; } BKE_collection_object_add(bmain, *collection_hidden, ob); @@ -4083,9 +4082,8 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) if (!MAIN_VERSION_ATLEAST(bmain, 280, 75)) { for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { if (scene->master_collection != NULL) { - scene->master_collection->flag &= ~(COLLECTION_RESTRICT_VIEWPORT | - COLLECTION_RESTRICT_SELECT | - COLLECTION_RESTRICT_RENDER); + scene->master_collection->flag &= ~(COLLECTION_HIDE_VIEWPORT | COLLECTION_HIDE_SELECT | + COLLECTION_HIDE_RENDER); } UnitSettings *unit = &scene->unit; diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c index e66afcd88d9..7931e953295 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_impl.c +++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c @@ -203,9 +203,9 @@ static void *bmw_VertShellWalker_step(BMWalker *walker) curedge = shellWalk.curedge; do { if (!BLI_gset_haskey(walker->visit_set, curedge)) { - if (!walker->restrictflag || - (walker->restrictflag && - BMO_edge_flag_test(walker->bm, curedge, walker->restrictflag))) { + if (!walker->visibility_flag || + (walker->visibility_flag && + BMO_edge_flag_test(walker->bm, curedge, walker->visibility_flag))) { BMwShellWalker *newstate; v_old = BM_edge_other_vert(curedge, shellWalk.base); @@ -714,7 +714,7 @@ static void *bmw_IslandboundWalker_step(BMWalker *walker) iwalk->base = owalk.base; #if 0 - if (!BMO_face_flag_test(walker->bm, l->f, walker->restrictflag)) { + if (!BMO_face_flag_test(walker->bm, l->f, walker->visibility_flag)) { iwalk->curloop = l->radial_next; } else { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 8d1074d912f..22bce10937d 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -648,9 +648,9 @@ void DepsgraphNodeBuilder::build_idproperties(IDProperty *id_property) void DepsgraphNodeBuilder::build_collection(LayerCollection *from_layer_collection, Collection *collection) { - const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEWPORT : - COLLECTION_RESTRICT_RENDER; - const bool is_collection_restricted = (collection->flag & restrict_flag); + const int visibility_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_HIDE_VIEWPORT : + COLLECTION_HIDE_RENDER; + const bool is_collection_restricted = (collection->flag & visibility_flag); const bool is_collection_visible = !is_collection_restricted && is_parent_collection_visible_; IDNode *id_node; if (built_map_.checkIsBuiltAndTag(collection)) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc index 29aa05b83db..b6e3f4fa935 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc @@ -60,11 +60,11 @@ namespace blender::deg { void DepsgraphNodeBuilder::build_layer_collections(ListBase *lb) { - const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEWPORT : - COLLECTION_RESTRICT_RENDER; + const int visibility_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_HIDE_VIEWPORT : + COLLECTION_HIDE_RENDER; for (LayerCollection *lc = (LayerCollection *)lb->first; lc; lc = lc->next) { - if (lc->collection->flag & restrict_flag) { + if (lc->collection->flag & visibility_flag) { continue; } if ((lc->flag & LAYER_COLLECTION_EXCLUDE) == 0) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc index 24876049942..6527f165552 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc @@ -61,11 +61,11 @@ namespace blender::deg { void DepsgraphRelationBuilder::build_layer_collections(ListBase *lb) { - const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEWPORT : - COLLECTION_RESTRICT_RENDER; + const int visibility_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_HIDE_VIEWPORT : + COLLECTION_HIDE_RENDER; for (LayerCollection *lc = (LayerCollection *)lb->first; lc; lc = lc->next) { - if ((lc->collection->flag & restrict_flag)) { + if ((lc->collection->flag & visibility_flag)) { continue; } if ((lc->flag & LAYER_COLLECTION_EXCLUDE) == 0) { diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index b2d387ea898..020518b5813 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -1892,7 +1892,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, } /* outliner restrict-flag */ - if (ob->restrictflag & OB_RESTRICT_VIEWPORT) { + if (ob->visibility_flag & OB_HIDE_VIEWPORT) { continue; } } @@ -3098,7 +3098,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, int filter_m } /* outliner restrict-flag */ - if (ob->restrictflag & OB_RESTRICT_VIEWPORT) { + if (ob->visibility_flag & OB_HIDE_VIEWPORT) { return false; } } diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index cfcea950955..0de3f429bc7 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -445,7 +445,7 @@ static void draw_marker_name(const uchar *text_color, if (marker->camera) { Object *camera = marker->camera; name = camera->id.name + 2; - if (camera->restrictflag & OB_RESTRICT_RENDER) { + if (camera->visibility_flag & OB_HIDE_RENDER) { final_text_color[3] = 100; } } diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index ad71f4d9da7..110f4541e8f 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -521,7 +521,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op) MaskLayer *mask_layer = BKE_mask_layer_active(mask); - if (mask_layer && mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer && mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { mask_layer = NULL; } diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index de8ea8e21eb..22232e9c87e 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -191,7 +191,7 @@ static void draw_spline_points(const bContext *C, const char draw_type) { const bool is_spline_sel = (spline->flag & SELECT) && - (mask_layer->restrictflag & MASK_RESTRICT_SELECT) == 0; + (mask_layer->visibility_flag & MASK_HIDE_SELECT) == 0; const bool is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH) != 0; uchar rgb_spline[4]; @@ -529,7 +529,7 @@ static void draw_spline_curve(const bContext *C, uchar rgb_tmp[4]; const bool is_spline_sel = (spline->flag & SELECT) && - (mask_layer->restrictflag & MASK_RESTRICT_SELECT) == 0; + (mask_layer->visibility_flag & MASK_HIDE_SELECT) == 0; const bool is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH) != 0; const bool is_fill = (spline->flag & MASK_SPLINE_NOFILL) == 0; @@ -604,7 +604,7 @@ static void draw_mask_layers(const bContext *C, mask_layer = mask_layer->next, i++) { const bool is_active = (i == mask->masklay_act); - if (mask_layer->restrictflag & MASK_RESTRICT_VIEW) { + if (mask_layer->visibility_flag & MASK_HIDE_VIEW) { continue; } @@ -613,7 +613,7 @@ static void draw_mask_layers(const bContext *C, /* draw curve itself first... */ draw_spline_curve(C, mask_layer, spline, draw_flag, draw_type, is_active, width, height); - if (!(mask_layer->restrictflag & MASK_RESTRICT_SELECT)) { + if (!(mask_layer->visibility_flag & MASK_HIDE_SELECT)) { /* ...and then handles over the curve so they're nicely visible */ draw_spline_points(C, mask_layer, spline, draw_flag, draw_type); } diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 6fa7457ce14..fd5925bbd0c 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -287,7 +287,7 @@ static bool spline_under_mouse_get(const bContext *C, } for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer != NULL; mask_layer = mask_layer->next) { - if (mask_layer->restrictflag & MASK_RESTRICT_SELECT) { + if (mask_layer->visibility_flag & MASK_HIDE_SELECT) { continue; } @@ -1322,7 +1322,7 @@ static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op)) Mask *mask = CTX_data_edit_mask(C); LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -1403,7 +1403,7 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) MaskSpline *spline; int mask_layer_shape_ofs = 0; - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -1523,7 +1523,7 @@ static int mask_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { bool changed_layer = false; - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -1581,7 +1581,7 @@ static int mask_normals_make_consistent_exec(bContext *C, wmOperator *UNUSED(op) LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { bool changed_layer = false; - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -1642,7 +1642,7 @@ static int set_handle_type_exec(bContext *C, wmOperator *op) bool changed = false; LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -1724,9 +1724,9 @@ static int mask_hide_view_clear_exec(bContext *C, wmOperator *op) LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & OB_RESTRICT_VIEWPORT) { + if (mask_layer->visibility_flag & OB_HIDE_VIEWPORT) { ED_mask_layer_select_set(mask_layer, select); - mask_layer->restrictflag &= ~OB_RESTRICT_VIEWPORT; + mask_layer->visibility_flag &= ~OB_HIDE_VIEWPORT; changed = true; } } @@ -1766,7 +1766,7 @@ static int mask_hide_view_set_exec(bContext *C, wmOperator *op) LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & MASK_RESTRICT_SELECT) { + if (mask_layer->visibility_flag & MASK_HIDE_SELECT) { continue; } @@ -1774,7 +1774,7 @@ static int mask_hide_view_set_exec(bContext *C, wmOperator *op) if (ED_mask_layer_select_check(mask_layer)) { ED_mask_layer_select_set(mask_layer, false); - mask_layer->restrictflag |= OB_RESTRICT_VIEWPORT; + mask_layer->visibility_flag |= OB_HIDE_VIEWPORT; changed = true; if (mask_layer == BKE_mask_layer_active(mask)) { BKE_mask_layer_active_set(mask, NULL); @@ -1783,7 +1783,7 @@ static int mask_hide_view_set_exec(bContext *C, wmOperator *op) } else { if (!ED_mask_layer_select_check(mask_layer)) { - mask_layer->restrictflag |= OB_RESTRICT_VIEWPORT; + mask_layer->visibility_flag |= OB_HIDE_VIEWPORT; changed = true; if (mask_layer == BKE_mask_layer_active(mask)) { BKE_mask_layer_active_set(mask, NULL); @@ -1825,7 +1825,7 @@ static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op)) bool changed = false; LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_SELECT | MASK_RESTRICT_VIEW)) { + if (mask_layer->visibility_flag & (MASK_HIDE_SELECT | MASK_HIDE_VIEW)) { continue; } diff --git a/source/blender/editors/mask/mask_query.c b/source/blender/editors/mask/mask_query.c index cd51026d20c..e66c4e45e27 100644 --- a/source/blender/editors/mask/mask_query.c +++ b/source/blender/editors/mask/mask_query.c @@ -85,7 +85,7 @@ bool ED_mask_find_nearest_diff_point(const bContext *C, *mask_layer_eval = mask_eval->masklayers.first; mask_layer_orig != NULL; mask_layer_orig = mask_layer_orig->next, mask_layer_eval = mask_layer_eval->next) { - if (mask_layer_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer_orig->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -245,7 +245,7 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, mask_layer_orig != NULL; mask_layer_orig = mask_layer_orig->next, mask_layer_eval = mask_layer_eval->next) { - if (mask_layer_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer_orig->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -409,7 +409,7 @@ bool ED_mask_feather_find_nearest(const bContext *C, int i, tot_feather_point; float(*feather_points)[2], (*fp)[2]; - if (mask_layer_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer_orig->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -638,7 +638,7 @@ bool ED_mask_selected_minmax(const bContext *C, INIT_MINMAX2(min, max); for (MaskLayer *mask_layer = mask_eval->masklayers.first; mask_layer != NULL; mask_layer = mask_layer->next) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } for (MaskSpline *spline = mask_layer->splines.first; spline != NULL; spline = spline->next) { diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c index 971e1c948c9..9c4740b3087 100644 --- a/source/blender/editors/mask/mask_relationships.c +++ b/source/blender/editors/mask/mask_relationships.c @@ -46,7 +46,7 @@ static int mask_parent_clear_exec(bContext *C, wmOperator *UNUSED(op)) Mask *mask = CTX_data_edit_mask(C); LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -138,7 +138,7 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) } LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index 8ddc3758e4e..6a1be8dcef3 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -68,7 +68,7 @@ bool ED_mask_spline_select_check(const MaskSpline *spline) bool ED_mask_layer_select_check(const MaskLayer *mask_layer) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { return false; } @@ -110,7 +110,7 @@ void ED_mask_spline_select_set(MaskSpline *spline, const bool do_select) void ED_mask_layer_select_set(MaskLayer *mask_layer, const bool do_select) { - if (mask_layer->restrictflag & MASK_RESTRICT_SELECT) { + if (mask_layer->visibility_flag & MASK_HIDE_SELECT) { if (do_select == true) { return; } @@ -134,7 +134,7 @@ void ED_mask_select_toggle_all(Mask *mask, int action) LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & MASK_RESTRICT_VIEW) { + if (mask_layer->visibility_flag & MASK_HIDE_VIEW) { continue; } @@ -142,7 +142,7 @@ void ED_mask_select_toggle_all(Mask *mask, int action) /* we don't have generic functions for this, its restricted to this operator * if one day we need to re-use such functionality, they can be split out */ - if (mask_layer->restrictflag & MASK_RESTRICT_SELECT) { + if (mask_layer->visibility_flag & MASK_HIDE_SELECT) { continue; } LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) { @@ -166,7 +166,7 @@ void ED_mask_select_flush_all(Mask *mask) /* Intentionally *don't* do this in the mask layer loop * so we clear flags on all splines. */ - if (mask_layer->restrictflag & MASK_RESTRICT_VIEW) { + if (mask_layer->visibility_flag & MASK_HIDE_VIEW) { continue; } @@ -465,7 +465,7 @@ static int box_select_exec(bContext *C, wmOperator *op) /* do actual selection */ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -550,7 +550,7 @@ static bool do_lasso_select_mask(bContext *C, /* do actual selection */ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -691,7 +691,7 @@ static int circle_select_exec(bContext *C, wmOperator *op) /* do actual selection */ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -820,7 +820,7 @@ static int mask_select_linked_exec(bContext *C, wmOperator *UNUSED(op)) /* do actual selection */ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -870,7 +870,7 @@ static int mask_select_more_less(bContext *C, bool more) Mask *mask = CTX_data_edit_mask(C); LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c index a5a3489c143..6620096c39a 100644 --- a/source/blender/editors/mask/mask_shapekey.c +++ b/source/blender/editors/mask/mask_shapekey.c @@ -144,7 +144,7 @@ static int mask_shape_key_feather_reset_exec(bContext *C, wmOperator *UNUSED(op) LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -238,7 +238,7 @@ static int mask_shape_key_rekey_exec(bContext *C, wmOperator *op) const bool do_location = RNA_boolean_get(op->ptr, "location"); LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 8ae74fbfafa..f98f3242163 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -3530,7 +3530,7 @@ static int object_add_named_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - basen->object->restrictflag &= ~OB_RESTRICT_VIEWPORT; + basen->object->visibility_flag &= ~OB_HIDE_VIEWPORT; int mval[2]; if (object_add_drop_xy_get(C, op, &mval)) { diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index 43358f51396..0a2df655395 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -1311,7 +1311,7 @@ static int bake(const BakeAPIRender *bkr, } else { ob_cage_eval = DEG_get_evaluated_object(depsgraph, ob_cage); - ob_cage_eval->restrictflag |= OB_RESTRICT_RENDER; + ob_cage_eval->visibility_flag |= OB_HIDE_RENDER; ob_cage_eval->base_flag &= ~(BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER); } } @@ -1411,7 +1411,7 @@ static int bake(const BakeAPIRender *bkr, /* initialize highpoly_data */ highpoly[i].ob = ob_iter; highpoly[i].ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter); - highpoly[i].ob_eval->restrictflag &= ~OB_RESTRICT_RENDER; + highpoly[i].ob_eval->visibility_flag &= ~OB_HIDE_RENDER; highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER); highpoly[i].me = BKE_mesh_new_from_object(NULL, highpoly[i].ob_eval, false, false); @@ -1427,10 +1427,10 @@ static int bake(const BakeAPIRender *bkr, BLI_assert(i == tot_highpoly); if (ob_cage != NULL) { - ob_cage_eval->restrictflag |= OB_RESTRICT_RENDER; + ob_cage_eval->visibility_flag |= OB_HIDE_RENDER; ob_cage_eval->base_flag &= ~(BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER); } - ob_low_eval->restrictflag |= OB_RESTRICT_RENDER; + ob_low_eval->visibility_flag |= OB_HIDE_RENDER; ob_low_eval->base_flag &= ~(BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER); /* populate the pixel arrays with the corresponding face data for each high poly object */ @@ -1473,7 +1473,7 @@ static int bake(const BakeAPIRender *bkr, } else { /* If low poly is not renderable it should have failed long ago. */ - BLI_assert((ob_low_eval->restrictflag & OB_RESTRICT_RENDER) == 0); + BLI_assert((ob_low_eval->visibility_flag & OB_HIDE_RENDER) == 0); if (RE_bake_has_engine(re)) { ok = RE_bake_engine(re, diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 6108691b2f1..5697c2c973d 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -384,7 +384,7 @@ static int object_hide_collection_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); if (v3d->flag & V3D_LOCAL_COLLECTIONS) { - if (lc->runtime_flag & LAYER_COLLECTION_RESTRICT_VIEWPORT) { + if (lc->runtime_flag & LAYER_COLLECTION_HIDE_VIEWPORT) { return OPERATOR_CANCELLED; } if (toggle) { @@ -421,7 +421,7 @@ void ED_collection_hide_menu_draw(const bContext *C, uiLayout *layout) continue; } - if (lc->collection->flag & COLLECTION_RESTRICT_VIEWPORT) { + if (lc->collection->flag & COLLECTION_HIDE_VIEWPORT) { continue; } @@ -926,7 +926,7 @@ static bool editmode_toggle_poll(bContext *C) } /* if hidden but in edit mode, we still display */ - if ((ob->restrictflag & OB_RESTRICT_VIEWPORT) && !(ob->mode & OB_MODE_EDIT)) { + if ((ob->visibility_flag & OB_HIDE_VIEWPORT) && !(ob->mode & OB_MODE_EDIT)) { return false; } diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index fe1e850dcba..bd4c83c107e 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -273,10 +273,10 @@ static void switch_preview_collection_visibilty(ViewLayer *view_layer, const ePr for (lc = lc->layer_collections.first; lc; lc = lc->next) { if (STREQ(lc->collection->id.name + 2, collection_name)) { - lc->collection->flag &= ~COLLECTION_RESTRICT_RENDER; + lc->collection->flag &= ~COLLECTION_HIDE_RENDER; } else { - lc->collection->flag |= COLLECTION_RESTRICT_RENDER; + lc->collection->flag |= COLLECTION_HIDE_RENDER; } } } @@ -288,10 +288,10 @@ static void switch_preview_floor_visibility(ViewLayer *view_layer, LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { if (STREQ(base->object->id.name + 2, "Floor")) { if (pr_method == PR_ICON_RENDER) { - base->object->restrictflag |= OB_RESTRICT_RENDER; + base->object->visibility_flag |= OB_HIDE_RENDER; } else { - base->object->restrictflag &= ~OB_RESTRICT_RENDER; + base->object->visibility_flag &= ~OB_HIDE_RENDER; } } } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 107466a8a0b..0bc2a224a4b 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -381,7 +381,7 @@ bool ED_operator_console_active(bContext *C) static bool ed_object_hidden(const Object *ob) { /* if hidden but in edit mode, we still display, can happen with animation */ - return ((ob->restrictflag & OB_RESTRICT_VIEWPORT) && !(ob->mode & OB_MODE_EDIT)); + return ((ob->visibility_flag & OB_HIDE_VIEWPORT) && !(ob->mode & OB_MODE_EDIT)); } bool ED_operator_object_active(bContext *C) diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index 7194e78e940..23dd290e13f 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -492,7 +492,7 @@ static bool mask_has_selection(const bContext *C) } LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) { diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c index 6538f5709b7..1ec1afe86fc 100644 --- a/source/blender/editors/space_outliner/outliner_collections.c +++ b/source/blender/editors/space_outliner/outliner_collections.c @@ -1263,22 +1263,22 @@ static bool collection_flag_poll(bContext *C, bool clear, int flag) static bool collection_enable_poll(bContext *C) { - return collection_flag_poll(C, true, COLLECTION_RESTRICT_VIEWPORT); + return collection_flag_poll(C, true, COLLECTION_HIDE_VIEWPORT); } static bool collection_disable_poll(bContext *C) { - return collection_flag_poll(C, false, COLLECTION_RESTRICT_VIEWPORT); + return collection_flag_poll(C, false, COLLECTION_HIDE_VIEWPORT); } static bool collection_enable_render_poll(bContext *C) { - return collection_flag_poll(C, true, COLLECTION_RESTRICT_RENDER); + return collection_flag_poll(C, true, COLLECTION_HIDE_RENDER); } static bool collection_disable_render_poll(bContext *C) { - return collection_flag_poll(C, false, COLLECTION_RESTRICT_RENDER); + return collection_flag_poll(C, false, COLLECTION_HIDE_RENDER); } static int collection_flag_exec(bContext *C, wmOperator *op) @@ -1288,7 +1288,7 @@ static int collection_flag_exec(bContext *C, wmOperator *op) SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); const bool is_render = strstr(op->idname, "render"); const bool clear = strstr(op->idname, "show") || strstr(op->idname, "enable"); - int flag = is_render ? COLLECTION_RESTRICT_RENDER : COLLECTION_RESTRICT_VIEWPORT; + int flag = is_render ? COLLECTION_HIDE_RENDER : COLLECTION_HIDE_VIEWPORT; struct CollectionEditData data = { .scene = scene, .space_outliner = space_outliner, diff --git a/source/blender/editors/transform/transform_convert_mask.c b/source/blender/editors/transform/transform_convert_mask.c index 54df8270702..1a25cfd1efb 100644 --- a/source/blender/editors/transform/transform_convert_mask.c +++ b/source/blender/editors/transform/transform_convert_mask.c @@ -293,7 +293,7 @@ void createTransMaskingData(bContext *C, TransInfo *t) for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -351,7 +351,7 @@ void createTransMaskingData(bContext *C, TransInfo *t) for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c index 8762ca1f384..f02b73e8430 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c @@ -1968,8 +1968,8 @@ static int lineart_usage_check(Collection *c, Object *ob, bool is_render) if (c->gobject.first) { if (BKE_collection_has_object(c, (Object *)(ob->id.orig_id))) { - if ((is_render && (c->flag & COLLECTION_RESTRICT_RENDER)) || - ((!is_render) && (c->flag & COLLECTION_RESTRICT_VIEWPORT))) { + if ((is_render && (c->flag & COLLECTION_HIDE_RENDER)) || + ((!is_render) && (c->flag & COLLECTION_HIDE_VIEWPORT))) { return OBJECT_LRT_EXCLUDE; } if (ob->lineart.usage == OBJECT_LRT_INHERIT) { diff --git a/source/blender/makesdna/DNA_collection_types.h b/source/blender/makesdna/DNA_collection_types.h index 1defa8b782b..3eba02de2a3 100644 --- a/source/blender/makesdna/DNA_collection_types.h +++ b/source/blender/makesdna/DNA_collection_types.h @@ -102,10 +102,10 @@ typedef struct Collection { /* Collection->flag */ enum { - COLLECTION_RESTRICT_VIEWPORT = (1 << 0), /* Disable in viewports. */ - COLLECTION_RESTRICT_SELECT = (1 << 1), /* Not selectable in viewport. */ + COLLECTION_HIDE_VIEWPORT = (1 << 0), /* Disable in viewports. */ + COLLECTION_HIDE_SELECT = (1 << 1), /* Not selectable in viewport. */ /* COLLECTION_DISABLED_DEPRECATED = (1 << 2), */ /* Not used anymore */ - COLLECTION_RESTRICT_RENDER = (1 << 3), /* Disable in renders. */ + COLLECTION_HIDE_RENDER = (1 << 3), /* Disable in renders. */ COLLECTION_HAS_OBJECT_CACHE = (1 << 4), /* Runtime: object_cache is populated. */ COLLECTION_IS_MASTER = (1 << 5), /* Is master collection embedded in the scene. */ COLLECTION_HAS_OBJECT_CACHE_INSTANCED = (1 << 6), /* for object_cache_instanced. */ diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h index 828c6ff2a51..63e4597150c 100644 --- a/source/blender/makesdna/DNA_layer_types.h +++ b/source/blender/makesdna/DNA_layer_types.h @@ -222,7 +222,7 @@ enum { enum { LAYER_COLLECTION_HAS_OBJECTS = (1 << 0), /* LAYER_COLLECTION_VISIBLE_DEPSGRAPH = (1 << 1), */ /* UNUSED */ - LAYER_COLLECTION_RESTRICT_VIEWPORT = (1 << 2), + LAYER_COLLECTION_HIDE_VIEWPORT = (1 << 2), LAYER_COLLECTION_VISIBLE_VIEW_LAYER = (1 << 4), }; diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index e6a7c004078..419118a38f4 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -174,7 +174,7 @@ typedef struct MaskLayer { /** For animation. */ char flag; /** Matching 'Object' flag of the same name - eventually use in the outliner. */ - char restrictflag; + char visibility_flag; } MaskLayer; /* MaskParent->flag */ @@ -206,10 +206,10 @@ enum { MASK_SPLINE_OFFSET_SMOOTH = 1, }; -/* ob->restrictflag */ -#define MASK_RESTRICT_VIEW (1 << 0) -#define MASK_RESTRICT_SELECT (1 << 1) -#define MASK_RESTRICT_RENDER (1 << 2) +/* MaskLayer->visibility_flag */ +#define MASK_HIDE_VIEW (1 << 0) +#define MASK_HIDE_SELECT (1 << 1) +#define MASK_HIDE_RENDER (1 << 2) /* SpaceClip->mask_draw_flag */ #define MASK_DRAWFLAG_SMOOTH (1 << 0) diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 60a34fef899..a37536f7022 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -385,7 +385,7 @@ typedef struct Object { short softflag; /** For restricting view, select, render etc. accessible in outliner. */ - char restrictflag; + char visibility_flag; /** Flag for pinning. */ char shapeflag; @@ -670,11 +670,11 @@ enum { # define OB_FLAG_UNUSED_12 (1 << 12) /* cleared */ #endif -/* ob->restrictflag */ +/* ob->visibility_flag */ enum { - OB_RESTRICT_VIEWPORT = 1 << 0, - OB_RESTRICT_SELECT = 1 << 1, - OB_RESTRICT_RENDER = 1 << 2, + OB_HIDE_VIEWPORT = 1 << 0, + OB_HIDE_SELECT = 1 << 1, + OB_HIDE_RENDER = 1 << 2, }; /* ob->shapeflag */ diff --git a/source/blender/makesdna/intern/dna_rename_defs.h b/source/blender/makesdna/intern/dna_rename_defs.h index d363e40e4f0..2feebbfd4f4 100644 --- a/source/blender/makesdna/intern/dna_rename_defs.h +++ b/source/blender/makesdna/intern/dna_rename_defs.h @@ -82,11 +82,13 @@ DNA_STRUCT_RENAME_ELEM(FluidDomainSettings, guiding_vel_factor, guide_vel_factor DNA_STRUCT_RENAME_ELEM(FluidEffectorSettings, guiding_mode, guide_mode) DNA_STRUCT_RENAME_ELEM(Image, name, filepath) DNA_STRUCT_RENAME_ELEM(Library, name, filepath) +DNA_STRUCT_RENAME_ELEM(MaskLayer, restrictflag, visibility_flag) DNA_STRUCT_RENAME_ELEM(MovieClip, name, filepath) DNA_STRUCT_RENAME_ELEM(Object, col, color) DNA_STRUCT_RENAME_ELEM(Object, dup_group, instance_collection) DNA_STRUCT_RENAME_ELEM(Object, dupfacesca, instance_faces_scale) DNA_STRUCT_RENAME_ELEM(Object, size, scale) +DNA_STRUCT_RENAME_ELEM(Object, restrictflag, visibility_flag) DNA_STRUCT_RENAME_ELEM(ParticleSettings, dup_group, instance_collection) DNA_STRUCT_RENAME_ELEM(ParticleSettings, dup_ob, instance_object) DNA_STRUCT_RENAME_ELEM(ParticleSettings, dupliweights, instance_weights) diff --git a/source/blender/makesrna/intern/rna_collection.c b/source/blender/makesrna/intern/rna_collection.c index 608a8e51b09..77276f47689 100644 --- a/source/blender/makesrna/intern/rna_collection.c +++ b/source/blender/makesrna/intern/rna_collection.c @@ -322,17 +322,17 @@ static void rna_Collection_flag_set(PointerRNA *ptr, const bool value, const int static void rna_Collection_hide_select_set(PointerRNA *ptr, bool value) { - rna_Collection_flag_set(ptr, value, COLLECTION_RESTRICT_SELECT); + rna_Collection_flag_set(ptr, value, COLLECTION_HIDE_SELECT); } static void rna_Collection_hide_viewport_set(PointerRNA *ptr, bool value) { - rna_Collection_flag_set(ptr, value, COLLECTION_RESTRICT_VIEWPORT); + rna_Collection_flag_set(ptr, value, COLLECTION_HIDE_VIEWPORT); } static void rna_Collection_hide_render_set(PointerRNA *ptr, bool value) { - rna_Collection_flag_set(ptr, value, COLLECTION_RESTRICT_RENDER); + rna_Collection_flag_set(ptr, value, COLLECTION_HIDE_RENDER); } static void rna_Collection_flag_update(Main *bmain, Scene *scene, PointerRNA *ptr) @@ -496,7 +496,7 @@ void RNA_def_collections(BlenderRNA *brna) /* Flags */ prop = RNA_def_property(srna, "hide_select", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_RESTRICT_SELECT); + RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_HIDE_SELECT); RNA_def_property_boolean_funcs(prop, NULL, "rna_Collection_hide_select_set"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, -1); @@ -504,7 +504,7 @@ void RNA_def_collections(BlenderRNA *brna) RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_Collection_flag_update"); prop = RNA_def_property(srna, "hide_viewport", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_RESTRICT_VIEWPORT); + RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_HIDE_VIEWPORT); RNA_def_property_boolean_funcs(prop, NULL, "rna_Collection_hide_viewport_set"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, -1); @@ -512,7 +512,7 @@ void RNA_def_collections(BlenderRNA *brna) RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_Collection_flag_update"); prop = RNA_def_property(srna, "hide_render", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_RESTRICT_RENDER); + RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_HIDE_RENDER); RNA_def_property_boolean_funcs(prop, NULL, "rna_Collection_hide_render_set"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, -1); diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c index 0414afe1514..ab4cbc429ce 100644 --- a/source/blender/makesrna/intern/rna_layer.c +++ b/source/blender/makesrna/intern/rna_layer.c @@ -134,7 +134,7 @@ static bool rna_LayerCollection_visible_get(LayerCollection *layer_collection, b } if (v3d->local_collections_uuid & layer_collection->local_collections_bits) { - return (layer_collection->runtime_flag & LAYER_COLLECTION_RESTRICT_VIEWPORT) == 0; + return (layer_collection->runtime_flag & LAYER_COLLECTION_HIDE_VIEWPORT) == 0; } return false; diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index 8c7d9698a67..9c90c209389 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -991,19 +991,19 @@ static void rna_def_mask_layer(BlenderRNA *brna) /* restrict */ prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", MASK_RESTRICT_VIEW); + RNA_def_property_boolean_sdna(prop, NULL, "visibility_flag", MASK_HIDE_VIEW); RNA_def_property_ui_text(prop, "Restrict View", "Restrict visibility in the viewport"); RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, -1); RNA_def_property_update(prop, NC_MASK | ND_DRAW, NULL); prop = RNA_def_property(srna, "hide_select", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", MASK_RESTRICT_SELECT); + RNA_def_property_boolean_sdna(prop, NULL, "visibility_flag", MASK_HIDE_SELECT); RNA_def_property_ui_text(prop, "Restrict Select", "Restrict selection in the viewport"); RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, -1); RNA_def_property_update(prop, NC_MASK | ND_DRAW, NULL); prop = RNA_def_property(srna, "hide_render", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", MASK_RESTRICT_RENDER); + RNA_def_property_boolean_sdna(prop, NULL, "visibility_flag", MASK_HIDE_RENDER); RNA_def_property_ui_text(prop, "Restrict Render", "Restrict renderability"); RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, -1); RNA_def_property_update(prop, NC_MASK | NA_EDITED, NULL); diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index ed681291e29..f0b83f3eb46 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -2927,6 +2927,44 @@ static void rna_def_object_lineart(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_object_lineart_update"); } +static void rna_def_object_visibility(StructRNA *srna) +{ + PropertyRNA *prop; + + /* Hide options. */ + prop = RNA_def_property(srna, "hide_viewport", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "visibility_flag", OB_HIDE_VIEWPORT); + RNA_def_property_ui_text(prop, "Disable in Viewports", "Globally disable in viewports"); + RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, -1); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update"); + + prop = RNA_def_property(srna, "hide_select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "visibility_flag", OB_HIDE_SELECT); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Disable Selection", "Disable selection in viewport"); + RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, -1); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update"); + + prop = RNA_def_property(srna, "hide_render", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "visibility_flag", OB_HIDE_RENDER); + RNA_def_property_ui_text(prop, "Disable in Renders", "Globally disable in renders"); + RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, -1); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update"); + + /* Instancer options. */ + prop = RNA_def_property(srna, "show_instancer_for_render", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "duplicator_visibility_flag", OB_DUPLI_FLAG_RENDER); + RNA_def_property_ui_text(prop, "Render Instancer", "Make instancer visible when rendering"); + RNA_def_property_update( + prop, NC_OBJECT | ND_DRAW, "rna_Object_duplicator_visibility_flag_update"); + + prop = RNA_def_property(srna, "show_instancer_for_viewport", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "duplicator_visibility_flag", OB_DUPLI_FLAG_VIEWPORT); + RNA_def_property_ui_text(prop, "Display Instancer", "Make instancer visible in the viewport"); + RNA_def_property_update( + prop, NC_OBJECT | ND_DRAW, "rna_Object_duplicator_visibility_flag_update"); +} + static void rna_def_object(BlenderRNA *brna) { StructRNA *srna; @@ -3506,37 +3544,7 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_struct_type(prop, "RigidBodyConstraint"); RNA_def_property_ui_text(prop, "Rigid Body Constraint", "Constraint constraining rigid bodies"); - /* restrict */ - prop = RNA_def_property(srna, "hide_viewport", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", OB_RESTRICT_VIEWPORT); - RNA_def_property_ui_text(prop, "Disable in Viewports", "Globally disable in viewports"); - RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, -1); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update"); - - prop = RNA_def_property(srna, "hide_select", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", OB_RESTRICT_SELECT); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Disable Selection", "Disable selection in viewport"); - RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, -1); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update"); - - prop = RNA_def_property(srna, "hide_render", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", OB_RESTRICT_RENDER); - RNA_def_property_ui_text(prop, "Disable in Renders", "Globally disable in renders"); - RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, -1); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update"); - - prop = RNA_def_property(srna, "show_instancer_for_render", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "duplicator_visibility_flag", OB_DUPLI_FLAG_RENDER); - RNA_def_property_ui_text(prop, "Render Instancer", "Make instancer visible when rendering"); - RNA_def_property_update( - prop, NC_OBJECT | ND_DRAW, "rna_Object_duplicator_visibility_flag_update"); - - prop = RNA_def_property(srna, "show_instancer_for_viewport", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "duplicator_visibility_flag", OB_DUPLI_FLAG_VIEWPORT); - RNA_def_property_ui_text(prop, "Display Instancer", "Make instancer visible in the viewport"); - RNA_def_property_update( - prop, NC_OBJECT | ND_DRAW, "rna_Object_duplicator_visibility_flag_update"); + rna_def_object_visibility(srna); /* instancing */ prop = RNA_def_property(srna, "instance_type", PROP_ENUM, PROP_NONE); -- cgit v1.2.3 From 49acc52e02ec9e0577d3fa1f298720139d9f751b Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 4 Aug 2021 20:49:50 +0200 Subject: Cycles: make object Fast GI Approximation panel a subpanel of Shading --- intern/cycles/blender/addon/ui.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 336fb02ba36..e804f697571 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1228,10 +1228,10 @@ class CYCLES_OBJECT_PT_shading_shadow_terminator(CyclesButtonsPanel, Panel): flow.prop(cob, "shadow_terminator_offset", text="Shading Offset") -class CYCLES_OBJECT_PT_gi_approximation(CyclesButtonsPanel, Panel): +class CYCLES_OBJECT_PT_shading_gi_approximation(CyclesButtonsPanel, Panel): bl_label = "Fast GI Approximation" + bl_parent_id = "CYCLES_OBJECT_PT_shading" bl_context = "object" - bl_options = {'DEFAULT_CLOSED'} def draw(self, context): layout = self.layout @@ -2325,7 +2325,7 @@ classes = ( CYCLES_OBJECT_PT_motion_blur, CYCLES_OBJECT_PT_shading, CYCLES_OBJECT_PT_shading_shadow_terminator, - CYCLES_OBJECT_PT_gi_approximation, + CYCLES_OBJECT_PT_shading_gi_approximation, CYCLES_OBJECT_PT_visibility, CYCLES_OBJECT_PT_visibility_ray_visibility, CYCLES_OBJECT_PT_visibility_culling, -- cgit v1.2.3 From 1d1020b79ff3ac9cc23921aa2e7ba1ef16c930ce Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Wed, 4 Aug 2021 13:19:16 -0700 Subject: Win32 IME: Remove ime_status_ This removes one member of GHOST_ImeWin32 that is not used and cannot be used in the future. It is holding the result of ImmIsIME, which is whether an input language supports IME. It does not indicate that one is in use, turned on, composing, in English mode, etc. see D12131 for more information. Differential Revision: https://developer.blender.org/D12131 Reviewed by Ray Molenkamp --- intern/ghost/intern/GHOST_ImeWin32.cpp | 10 ++-------- intern/ghost/intern/GHOST_ImeWin32.h | 16 +--------------- 2 files changed, 3 insertions(+), 23 deletions(-) diff --git a/intern/ghost/intern/GHOST_ImeWin32.cpp b/intern/ghost/intern/GHOST_ImeWin32.cpp index 8daa07b5003..f6baa601db9 100644 --- a/intern/ghost/intern/GHOST_ImeWin32.cpp +++ b/intern/ghost/intern/GHOST_ImeWin32.cpp @@ -32,7 +32,6 @@ GHOST_ImeWin32::GHOST_ImeWin32() : is_composing_(false), - ime_status_(false), input_language_id_(LANG_USER_DEFAULT), conversion_modes_(IME_CMODE_ALPHANUMERIC), sentence_mode_(IME_SMODE_NONE), @@ -47,18 +46,13 @@ GHOST_ImeWin32::~GHOST_ImeWin32() { } -bool GHOST_ImeWin32::SetInputLanguage() +void GHOST_ImeWin32::SetInputLanguage() { /** - * Retrieve the current keyboard layout from Windows and determine whether - * or not the current input context has IMEs. - * Also save its input language for language-specific operations required - * while composing a text. + * Retrieve the current input language. */ HKL keyboard_layout = ::GetKeyboardLayout(0); input_language_id_ = LOWORD(keyboard_layout); - ime_status_ = ::ImmIsIME(keyboard_layout); - return ime_status_; } WORD GHOST_ImeWin32::GetInputLanguage() diff --git a/intern/ghost/intern/GHOST_ImeWin32.h b/intern/ghost/intern/GHOST_ImeWin32.h index bcc4b6eef7c..7ccb0cdfd06 100644 --- a/intern/ghost/intern/GHOST_ImeWin32.h +++ b/intern/ghost/intern/GHOST_ImeWin32.h @@ -148,13 +148,8 @@ class GHOST_ImeWin32 { /** * Retrieves the input language from Windows and update it. - * Return values - * * true - * The given input language has IMEs. - * * false - * The given input language does not have IMEs. */ - bool SetInputLanguage(); + void SetInputLanguage(); /* Returns the current input language id. */ WORD GetInputLanguage(); @@ -350,15 +345,6 @@ class GHOST_ImeWin32 { */ bool is_composing_; - /** - * This value represents whether or not the current input context has IMEs. - * The following table shows the list of IME status: - * Value Description - * false The current input language does not have IMEs. - * true The current input language has IMEs. - */ - bool ime_status_; - /** * The current input Language ID retrieved from Windows, which consists of: * * Primary Language ID (bit 0 to bit 9), which shows a natural language -- cgit v1.2.3 From 07b702f82846322df4b0b6065db90d7e3ebf3eb1 Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Wed, 4 Aug 2021 14:30:16 -0700 Subject: Win32 IME: Rename SetInputLanguage() GHOST_ImeWin32::SetInputLanguage() has a confusing name because it does not set the input language. It actually retrieves the current input locale from the OS and caches the value of the current input language ID. Therefore this patch renames it to "UpdateInputLanguage" Differential Revision: https://developer.blender.org/D12134 Reviewed by Ray Molenkamp --- intern/ghost/intern/GHOST_ImeWin32.cpp | 8 ++++---- intern/ghost/intern/GHOST_ImeWin32.h | 4 ++-- intern/ghost/intern/GHOST_SystemWin32.cpp | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/intern/ghost/intern/GHOST_ImeWin32.cpp b/intern/ghost/intern/GHOST_ImeWin32.cpp index f6baa601db9..343f4d68078 100644 --- a/intern/ghost/intern/GHOST_ImeWin32.cpp +++ b/intern/ghost/intern/GHOST_ImeWin32.cpp @@ -46,13 +46,13 @@ GHOST_ImeWin32::~GHOST_ImeWin32() { } -void GHOST_ImeWin32::SetInputLanguage() +void GHOST_ImeWin32::UpdateInputLanguage() { /** - * Retrieve the current input language. + * Store the current input language. */ - HKL keyboard_layout = ::GetKeyboardLayout(0); - input_language_id_ = LOWORD(keyboard_layout); + HKL input_locale = ::GetKeyboardLayout(0); + input_language_id_ = LOWORD(input_locale); } WORD GHOST_ImeWin32::GetInputLanguage() diff --git a/intern/ghost/intern/GHOST_ImeWin32.h b/intern/ghost/intern/GHOST_ImeWin32.h index 7ccb0cdfd06..d430a7d745d 100644 --- a/intern/ghost/intern/GHOST_ImeWin32.h +++ b/intern/ghost/intern/GHOST_ImeWin32.h @@ -88,7 +88,7 @@ class GHOST_EventIME : public GHOST_Event { * An application CAN call ::DefWindowProc(). * 2.5. WM_INPUTLANGCHANGE (0x0051) * Call the functions listed below: - * - GHOST_ImeWin32::SetInputLanguage(). + * - GHOST_ImeWin32::UpdateInputLanguage(). * An application CAN call ::DefWindowProc(). */ @@ -149,7 +149,7 @@ class GHOST_ImeWin32 { /** * Retrieves the input language from Windows and update it. */ - void SetInputLanguage(); + void UpdateInputLanguage(); /* Returns the current input language id. */ WORD GetInputLanguage(); diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 60fd175dbf7..347067eae50 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -1424,7 +1424,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, case WM_INPUTLANGCHANGE: { system->handleKeyboardChange(); #ifdef WITH_INPUT_IME - window->getImeInput()->SetInputLanguage(); + window->getImeInput()->UpdateInputLanguage(); window->getImeInput()->UpdateConversionStatus(hwnd); #endif break; @@ -1471,7 +1471,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, } case WM_IME_SETCONTEXT: { GHOST_ImeWin32 *ime = window->getImeInput(); - ime->SetInputLanguage(); + ime->UpdateInputLanguage(); ime->CreateImeWindow(hwnd); ime->CleanupComposition(hwnd); ime->CheckFirst(hwnd); -- cgit v1.2.3 From d6ca7ab20ed6f4f1df29cfc55b88beaecdec4525 Mon Sep 17 00:00:00 2001 From: Aaron Carlisle Date: Wed, 4 Aug 2021 19:24:19 -0400 Subject: Cleanup: make format --- .../engines/overlay/shaders/edit_mesh_normal_vert.glsl | 3 +-- source/blender/editors/include/ED_keyframes_keylist.h | 4 +++- source/blender/python/gpu/gpu_py_offscreen.c | 15 +++++++++++---- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl index f649a5cb3ed..d370943db03 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl @@ -56,8 +56,7 @@ void main() if (gl_VertexID == 0) { if (isConstantScreenSizeNormals) { bool is_persp = (ProjectionMatrix[3][3] == 0.0); - if (is_persp) - { + if (is_persp) { float dist_fac = length(cameraPos - world_pos); float cos_fac = dot(cameraForward, cameraVec(world_pos)); world_pos += n * normalScreenSize * dist_fac * cos_fac * pixelFac * sizePixel; diff --git a/source/blender/editors/include/ED_keyframes_keylist.h b/source/blender/editors/include/ED_keyframes_keylist.h index e7d1b5d4363..d3690fa3aa0 100644 --- a/source/blender/editors/include/ED_keyframes_keylist.h +++ b/source/blender/editors/include/ED_keyframes_keylist.h @@ -190,7 +190,9 @@ void gpencil_to_keylist(struct bDopeSheet *ads, /* Grease Pencil Layer */ void gpl_to_keylist(struct bDopeSheet *ads, struct bGPDlayer *gpl, struct AnimKeylist *keylist); /* Mask */ -void mask_to_keylist(struct bDopeSheet *ads, struct MaskLayer *masklay, struct AnimKeylist *keylist); +void mask_to_keylist(struct bDopeSheet *ads, + struct MaskLayer *masklay, + struct AnimKeylist *keylist); /* ActKeyColumn API ---------------- */ /* Comparator callback used for ActKeyColumns and cframe float-value pointer */ diff --git a/source/blender/python/gpu/gpu_py_offscreen.c b/source/blender/python/gpu/gpu_py_offscreen.c index 02f72f20ac4..32053df5e97 100644 --- a/source/blender/python/gpu/gpu_py_offscreen.c +++ b/source/blender/python/gpu/gpu_py_offscreen.c @@ -279,7 +279,8 @@ static PyObject *pygpu_offscreen_texture_color_get(BPyGPUOffScreen *self, void * PyDoc_STRVAR( pygpu_offscreen_draw_view3d_doc, - ".. method:: draw_view3d(scene, view_layer, view3d, region, view_matrix, projection_matrix, do_color_management=False)\n" + ".. method:: draw_view3d(scene, view_layer, view3d, region, view_matrix, projection_matrix, " + "do_color_management=False)\n" "\n" " Draw the 3d viewport in the offscreen object.\n" "\n" @@ -312,8 +313,14 @@ static PyObject *pygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *ar BPY_GPU_OFFSCREEN_CHECK_OBJ(self); - static const char *_keywords[] = { - "scene", "view_layer", "view3d", "region", "view_matrix", "projection_matrix", "do_color_management", NULL}; + static const char *_keywords[] = {"scene", + "view_layer", + "view3d", + "region", + "view_matrix", + "projection_matrix", + "do_color_management", + NULL}; static _PyArg_Parser _parser = {"OOOOO&O&|$O&:draw_view3d", _keywords, 0}; if (!_PyArg_ParseTupleAndKeywordsFast(args, @@ -327,7 +334,7 @@ static PyObject *pygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *ar &py_mat_view, Matrix_Parse4x4, &py_mat_projection, - PyC_ParseBool, + PyC_ParseBool, &do_color_management) || (!(scene = PyC_RNA_AsPointer(py_scene, "Scene")) || !(view_layer = PyC_RNA_AsPointer(py_view_layer, "ViewLayer")) || -- cgit v1.2.3 From 171433e841379e7efad069bbda9880fb271e2fc4 Mon Sep 17 00:00:00 2001 From: Aaron Carlisle Date: Wed, 4 Aug 2021 19:26:01 -0400 Subject: PyDoc: Improve description of texture.evaluate Inspired by the old 2.49 docs: https://docs.blender.org/api/249PythonDoc/Texture.Texture-class.html#evaluate --- source/blender/makesrna/intern/rna_texture_api.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/source/blender/makesrna/intern/rna_texture_api.c b/source/blender/makesrna/intern/rna_texture_api.c index 42b3e4420c1..c46b9acf986 100644 --- a/source/blender/makesrna/intern/rna_texture_api.c +++ b/source/blender/makesrna/intern/rna_texture_api.c @@ -61,12 +61,30 @@ void RNA_api_texture(StructRNA *srna) func = RNA_def_function(srna, "evaluate", "texture_evaluate"); RNA_def_function_ui_description(func, "Evaluate the texture at the coordinates given"); - parm = RNA_def_float_vector(func, "value", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4); + parm = RNA_def_float_vector(func, + "value", + 3, + NULL, + -FLT_MAX, + FLT_MAX, + "The object coordinates (x,y,z) used to generate/map the texture", + "", + -1e4, + 1e4); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); - /* return location and normal */ parm = RNA_def_float_vector( - func, "result", 4, NULL, -FLT_MAX, FLT_MAX, "Result", NULL, -1e4, 1e4); + func, + "result", + 4, + NULL, + -FLT_MAX, + FLT_MAX, + "The result of the texture where (x,y,z,w) are (red, green, blue, intensity). For greyscale " + "textures, often intensity only will be used", + NULL, + -1e4, + 1e4); RNA_def_parameter_flags(parm, PROP_THICK_WRAP, 0); RNA_def_function_output(func, parm); } -- cgit v1.2.3 From 438d645a365045b4d89d59af59e17584f0593dc4 Mon Sep 17 00:00:00 2001 From: Aaron Carlisle Date: Wed, 4 Aug 2021 20:25:50 -0400 Subject: PyDoc: Update GPU Example of `draw_view3d` This function was changed in rBc8004ab4078c98c54a70113c12bbb186403e90cf but didnt update the example. Part of T84227 --- doc/python_api/examples/gpu.9.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/python_api/examples/gpu.9.py b/doc/python_api/examples/gpu.9.py index e358cb517bd..b0400ce7809 100644 --- a/doc/python_api/examples/gpu.9.py +++ b/doc/python_api/examples/gpu.9.py @@ -31,7 +31,8 @@ def draw(): context.space_data, context.region, view_matrix, - projection_matrix) + projection_matrix, + True) gpu.state.depth_mask_set(False) draw_texture_2d(offscreen.texture_color, (10, 10), WIDTH, HEIGHT) -- cgit v1.2.3 From 1def985d78db113ea4426311692941e44f0467eb Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Wed, 4 Aug 2021 19:32:24 -0600 Subject: Windows: Add icons and icons_geom to make.bat This adds support for building the icons from make.bat unlike bash there is no passing environment variables on the command line. The scripts go out of their way to locate both blender and inkscape however if they are not found, the user is given a helpful error message telling them how to set the variables. Although some extra help can be given there, if your normal build is a 2019 full build running `make 2019 full icons` will help it find the blender executable as well. finally if you know the name of your build folder running `make builddir build_windows_Lite_x64_vc16_Release icons` will also work, if all fails you can point directly to the blender executable by running `set BLENDER_BIN=c:\where\blender\lives\blender.exe` before running `make icons` or `make icons_geom` The python scripts needed some small modifications since without the PATHEXT, SystemRoot and SystemDrive environment variables python will not initialize properly on windows. (Not blender related, even mainline python won't start without those) --- build_files/windows/find_blender.cmd | 28 +++++++++++++++++ build_files/windows/find_inkscape.cmd | 21 +++++++++++++ build_files/windows/icons.cmd | 42 ++++++++++++++++++++++++++ build_files/windows/icons_geom.cmd | 29 ++++++++++++++++++ build_files/windows/parse_arguments.cmd | 6 ++++ build_files/windows/reset_variables.cmd | 2 ++ make.bat | 10 ++++++ release/datafiles/blender_icons_geom_update.py | 5 +++ release/datafiles/blender_icons_update.py | 6 ++++ 9 files changed, 149 insertions(+) create mode 100644 build_files/windows/find_blender.cmd create mode 100644 build_files/windows/find_inkscape.cmd create mode 100644 build_files/windows/icons.cmd create mode 100644 build_files/windows/icons_geom.cmd diff --git a/build_files/windows/find_blender.cmd b/build_files/windows/find_blender.cmd new file mode 100644 index 00000000000..9adbfd35ae9 --- /dev/null +++ b/build_files/windows/find_blender.cmd @@ -0,0 +1,28 @@ +REM First see if there is an environment variable set +if EXIST "%BLENDER_BIN%" ( + goto detect_blender_done +) + +REM Check the build folder next, if ninja was used there will be no +REM debug/release folder +set BLENDER_BIN=%BUILD_DIR%\bin\blender.exe +if EXIST "%BLENDER_BIN%" ( + goto detect_blender_done +) + +REM Check the release folder next +set BLENDER_BIN=%BUILD_DIR%\bin\release\blender.exe +if EXIST "%BLENDER_BIN%" ( + goto detect_blender_done +) + +REM Check the debug folder next +set BLENDER_BIN=%BUILD_DIR%\bin\debug\blender.exe +if EXIST "%BLENDER_BIN%" ( + goto detect_blender_done +) + +REM at this point, we don't know where blender is, clear the variable +set BLENDER_BIN= + +:detect_blender_done diff --git a/build_files/windows/find_inkscape.cmd b/build_files/windows/find_inkscape.cmd new file mode 100644 index 00000000000..2fa27f70d47 --- /dev/null +++ b/build_files/windows/find_inkscape.cmd @@ -0,0 +1,21 @@ +REM First see if there is an environment variable set +if EXIST "%INKSCAPE_BIN%" ( + goto detect_inkscape_done +) + +REM Then see if inkscape is available in the path +for %%X in (inkscape.exe) do (set INKSCAPE_BIN=%%~$PATH:X) +if EXIST "%INKSCAPE_BIN%" ( + goto detect_inkscape_done +) + +REM Finally see if it is perhaps installed at the default location +set INKSCAPE_BIN=%ProgramFiles%\Inkscape\bin\inkscape.exe +if EXIST "%INKSCAPE_BIN%" ( + goto detect_inkscape_done +) + +REM If still not found clear the variable +set INKSCAPE_BIN= + +:detect_inkscape_done diff --git a/build_files/windows/icons.cmd b/build_files/windows/icons.cmd new file mode 100644 index 00000000000..473a40885a8 --- /dev/null +++ b/build_files/windows/icons.cmd @@ -0,0 +1,42 @@ +if EXIST %PYTHON% ( + goto detect_python_done +) + +set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\39\bin\python.exe +if EXIST %PYTHON% ( + goto detect_python_done +) + +echo python not found at %PYTHON% +exit /b 1 + +:detect_python_done +echo found python (%PYTHON%) + +call "%~dp0\find_inkscape.cmd" + +if EXIST "%INKSCAPE_BIN%" ( + goto detect_inkscape_done +) + +echo unable to locate inkscape, run "set inkscape_BIN=full_path_to_inkscape.exe" +exit /b 1 + +:detect_inkscape_done + +call "%~dp0\find_blender.cmd" + +if EXIST "%BLENDER_BIN%" ( + goto detect_blender_done +) + +echo unable to locate blender, run "set BLENDER_BIN=full_path_to_blender.exe" +exit /b 1 + +:detect_blender_done + +%PYTHON% -B %BLENDER_DIR%\release\datafiles\blender_icons_update.py +%PYTHON% -B %BLENDER_DIR%\release\datafiles\prvicons_update.py +%PYTHON% -B %BLENDER_DIR%\release\datafiles\alert_icons_update.py + +:EOF diff --git a/build_files/windows/icons_geom.cmd b/build_files/windows/icons_geom.cmd new file mode 100644 index 00000000000..18312daf35b --- /dev/null +++ b/build_files/windows/icons_geom.cmd @@ -0,0 +1,29 @@ +if EXIST %PYTHON% ( + goto detect_python_done +) + +set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\39\bin\python.exe +if EXIST %PYTHON% ( + goto detect_python_done +) + +echo python not found at %PYTHON% +exit /b 1 + +:detect_python_done +echo found python (%PYTHON%) + +call "%~dp0\find_blender.cmd" + +if EXIST "%BLENDER_BIN%" ( + goto detect_blender_done +) + +echo unable to locate blender, run "set BLENDER_BIN=full_path_to_blender.exe" +exit /b 1 + +:detect_blender_done + +%PYTHON% -B %BLENDER_DIR%\release\datafiles\blender_icons_geom_update.py + +:EOF diff --git a/build_files/windows/parse_arguments.cmd b/build_files/windows/parse_arguments.cmd index 000b98c992e..c71093f2394 100644 --- a/build_files/windows/parse_arguments.cmd +++ b/build_files/windows/parse_arguments.cmd @@ -107,6 +107,12 @@ if NOT "%1" == "" ( set FORMAT=1 set FORMAT_ARGS=%2 %3 %4 %5 %6 %7 %8 %9 goto EOF + ) else if "%1" == "icons" ( + set ICONS=1 + goto EOF + ) else if "%1" == "icons_geom" ( + set ICONS_GEOM=1 + goto EOF ) else ( echo Command "%1" unknown, aborting! goto ERR diff --git a/build_files/windows/reset_variables.cmd b/build_files/windows/reset_variables.cmd index 262874713eb..590d4ca246a 100644 --- a/build_files/windows/reset_variables.cmd +++ b/build_files/windows/reset_variables.cmd @@ -31,3 +31,5 @@ set PYDEBUG_CMAKE_ARGS= set FORMAT= set TEST= set BUILD_WITH_SCCACHE= +set ICONS= +set ICONS_GEOM= \ No newline at end of file diff --git a/make.bat b/make.bat index ea80bd591f7..75d424202ae 100644 --- a/make.bat +++ b/make.bat @@ -58,6 +58,16 @@ if "%BUILD_UPDATE%" == "1" ( call "%BLENDER_DIR%\build_files\windows\set_build_dir.cmd" +if "%ICONS%" == "1" ( + call "%BLENDER_DIR%\build_files\windows\icons.cmd" + goto EOF +) + +if "%ICONS_GEOM%" == "1" ( + call "%BLENDER_DIR%\build_files\windows\icons_geom.cmd" + goto EOF +) + echo Building blender with VS%BUILD_VS_YEAR% for %BUILD_ARCH% in %BUILD_DIR% call "%BLENDER_DIR%\build_files\windows\check_libraries.cmd" diff --git a/release/datafiles/blender_icons_geom_update.py b/release/datafiles/blender_icons_geom_update.py index df4683809db..257b7a49285 100755 --- a/release/datafiles/blender_icons_geom_update.py +++ b/release/datafiles/blender_icons_geom_update.py @@ -96,6 +96,11 @@ for blend in icons_blend: env = {} # Developers may have ASAN enabled, avoid non-zero exit codes. env["ASAN_OPTIONS"] = "exitcode=0:" + os.environ.get("ASAN_OPTIONS", "") + # These NEED to be set on windows for python to initialize properly. + if sys.platform[:3] == "win": + env["PATHEXT"] = os.environ.get("PATHEXT", "") + env["SystemDrive"] = os.environ.get("SystemDrive", "") + env["SystemRoot"] = os.environ.get("SystemRoot", "") run(cmd, env=env) files_new = set(names_and_time_from_path(output_dir)) diff --git a/release/datafiles/blender_icons_update.py b/release/datafiles/blender_icons_update.py index dab3cd76a87..524cc512f29 100755 --- a/release/datafiles/blender_icons_update.py +++ b/release/datafiles/blender_icons_update.py @@ -37,6 +37,12 @@ env = {} # Developers may have ASAN enabled, avoid non-zero exit codes. env["ASAN_OPTIONS"] = "exitcode=0:" + os.environ.get("ASAN_OPTIONS", "") +# These NEED to be set on windows for python to initialize properly. +if sys.platform[:3] == "win": + env["PATHEXT"] = os.environ.get("PATHEXT", "") + env["SystemDrive"] = os.environ.get("SystemDrive", "") + env["SystemRoot"] = os.environ.get("SystemRoot", "") + inkscape_bin = os.environ.get("INKSCAPE_BIN", "inkscape") blender_bin = os.environ.get("BLENDER_BIN", "blender") -- cgit v1.2.3 From 604ae5f7b628e5ce78bd0313ec119634eafa1048 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 5 Aug 2021 12:02:49 +1000 Subject: Cleanup: tab indentation for CMake / GNUmakefile --- GNUmakefile | 32 ++++++++++++++----------- build_files/cmake/platform/platform_win32.cmake | 4 ++-- extern/CMakeLists.txt | 2 +- source/blender/compositor/CMakeLists.txt | 13 +++++----- 4 files changed, 27 insertions(+), 24 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 635cc321d03..d620e5c4363 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -63,7 +63,7 @@ Package Targets * package_debian: Build a debian package. * package_pacman: Build an arch linux pacman package. - * package_archive: Build an archive package. + * package_archive: Build an archive package. Testing Targets Not associated with building Blender. @@ -167,7 +167,7 @@ endef # This makefile is not meant for Windows ifeq ($(OS),Windows_NT) - $(error On Windows, use "cmd //c make.bat" instead of "make") + $(error On Windows, use "cmd //c make.bat" instead of "make") endif # System Vars @@ -379,7 +379,7 @@ deps: .FORCE @cmake -H"$(DEPS_SOURCE_DIR)" \ -B"$(DEPS_BUILD_DIR)" \ - -DHARVEST_TARGET=$(DEPS_INSTALL_DIR) + -DHARVEST_TARGET=$(DEPS_INSTALL_DIR) @echo @echo Building dependencies ... @@ -456,7 +456,8 @@ project_eclipse: .FORCE check_cppcheck: .FORCE $(CMAKE_CONFIG) cd "$(BUILD_DIR)" ; \ - $(PYTHON) "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_cppcheck.py" 2> \ + $(PYTHON) \ + "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_cppcheck.py" 2> \ "$(BLENDER_DIR)/check_cppcheck.txt" @echo "written: check_cppcheck.txt" @@ -518,8 +519,9 @@ source_archive: .FORCE python3 ./build_files/utils/make_source_archive.py source_archive_complete: .FORCE - cmake -S "$(BLENDER_DIR)/build_files/build_environment" -B"$(BUILD_DIR)/source_archive" \ - -DCMAKE_BUILD_TYPE_INIT:STRING=$(BUILD_TYPE) -DPACKAGE_USE_UPSTREAM_SOURCES=OFF + cmake \ + -S "$(BLENDER_DIR)/build_files/build_environment" -B"$(BUILD_DIR)/source_archive" \ + -DCMAKE_BUILD_TYPE_INIT:STRING=$(BUILD_TYPE) -DPACKAGE_USE_UPSTREAM_SOURCES=OFF # This assumes CMake is still using a default `PACKAGE_DIR` variable: python3 ./build_files/utils/make_source_archive.py --include-packages "$(BUILD_DIR)/source_archive/packages" @@ -527,11 +529,11 @@ source_archive_complete: .FORCE INKSCAPE_BIN?="inkscape" icons: .FORCE BLENDER_BIN=$(BLENDER_BIN) INKSCAPE_BIN=$(INKSCAPE_BIN) \ - "$(BLENDER_DIR)/release/datafiles/blender_icons_update.py" + "$(BLENDER_DIR)/release/datafiles/blender_icons_update.py" INKSCAPE_BIN=$(INKSCAPE_BIN) \ - "$(BLENDER_DIR)/release/datafiles/prvicons_update.py" + "$(BLENDER_DIR)/release/datafiles/prvicons_update.py" INKSCAPE_BIN=$(INKSCAPE_BIN) \ - "$(BLENDER_DIR)/release/datafiles/alert_icons_update.py" + "$(BLENDER_DIR)/release/datafiles/alert_icons_update.py" icons_geom: .FORCE BLENDER_BIN=$(BLENDER_BIN) \ @@ -545,7 +547,7 @@ update_code: .FORCE format: .FORCE PATH="../lib/${OS_NCASE}_${CPU}/llvm/bin/:../lib/${OS_NCASE}_centos7_${CPU}/llvm/bin/:../lib/${OS_NCASE}/llvm/bin/:$(PATH)" \ - $(PYTHON) source/tools/utils_maintenance/clang_format_paths.py $(PATHS) + $(PYTHON) source/tools/utils_maintenance/clang_format_paths.py $(PATHS) # ----------------------------------------------------------------------------- @@ -555,8 +557,9 @@ format: .FORCE # Simple version of ./doc/python_api/sphinx_doc_gen.sh with no PDF generation. doc_py: .FORCE ASAN_OPTIONS=halt_on_error=0:${ASAN_OPTIONS} \ - $(BLENDER_BIN) --background -noaudio --factory-startup \ - --python doc/python_api/sphinx_doc_gen.py + $(BLENDER_BIN) \ + --background -noaudio --factory-startup \ + --python doc/python_api/sphinx_doc_gen.py sphinx-build -b html -j $(NPROCS) doc/python_api/sphinx-in doc/python_api/sphinx-out @echo "docs written into: '$(BLENDER_DIR)/doc/python_api/sphinx-out/index.html'" @@ -565,8 +568,9 @@ doc_doxy: .FORCE @echo "docs written into: '$(BLENDER_DIR)/doc/doxygen/html/index.html'" doc_dna: .FORCE - $(BLENDER_BIN) --background -noaudio --factory-startup \ - --python doc/blender_file_format/BlendFileDnaExporter_25.py + $(BLENDER_BIN) \ + --background -noaudio --factory-startup \ + --python doc/blender_file_format/BlendFileDnaExporter_25.py @echo "docs written into: '$(BLENDER_DIR)/doc/blender_file_format/dna.html'" doc_man: .FORCE diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index a0e91199c72..113c41c545b 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -217,8 +217,8 @@ else() endif() if(WITH_WINDOWS_PDB) - set(PDB_INFO_OVERRIDE_FLAGS "${SYMBOL_FORMAT_RELEASE}") - set(PDB_INFO_OVERRIDE_LINKER_FLAGS "/DEBUG /OPT:REF /OPT:ICF /INCREMENTAL:NO") + set(PDB_INFO_OVERRIDE_FLAGS "${SYMBOL_FORMAT_RELEASE}") + set(PDB_INFO_OVERRIDE_LINKER_FLAGS "/DEBUG /OPT:REF /OPT:ICF /INCREMENTAL:NO") endif() string(APPEND CMAKE_CXX_FLAGS_DEBUG " /MDd ${SYMBOL_FORMAT}") diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt index 824b2fb0e9c..7f7d91f0765 100644 --- a/extern/CMakeLists.txt +++ b/extern/CMakeLists.txt @@ -111,5 +111,5 @@ if(WITH_MOD_FLUID) endif() if (WITH_COMPOSITOR) - add_subdirectory(smaa_areatex) + add_subdirectory(smaa_areatex) endif() diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index 000ba298c2d..ee287c65fe9 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -597,16 +597,16 @@ add_definitions(-DCL_USE_DEPRECATED_OPENCL_1_1_APIS) set(GENSRC_DIR ${CMAKE_CURRENT_BINARY_DIR}/operations) set(GENSRC ${GENSRC_DIR}/COM_SMAAAreaTexture.h) add_custom_command( - OUTPUT ${GENSRC} - COMMAND ${CMAKE_COMMAND} -E make_directory ${GENSRC_DIR} - COMMAND "$" ${GENSRC} - DEPENDS smaa_areatex + OUTPUT ${GENSRC} + COMMAND ${CMAKE_COMMAND} -E make_directory ${GENSRC_DIR} + COMMAND "$" ${GENSRC} + DEPENDS smaa_areatex ) add_custom_target(smaa_areatex_header - SOURCES ${GENSRC} + SOURCES ${GENSRC} ) list(APPEND SRC - ${GENSRC} + ${GENSRC} ) unset(GENSRC) unset(GENSRC_DIR) @@ -650,4 +650,3 @@ if(WITH_GTESTS) include(GTestTesting) blender_add_test_lib(bf_compositor_tests "${TEST_SRC}" "${INC};${TEST_INC}" "${INC_SYS}" "${LIB};${TEST_LIB}") endif() - -- cgit v1.2.3 From d1c5e2e050a57216f9555098313d65511455e042 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 5 Aug 2021 12:02:50 +1000 Subject: Cleanup: license headers These were removed globally in 65ec7ec524e667ec95ce947a95f6273088dffee6. Some files re-introduced these conventions since. --- source/blender/blenlib/BLI_enumerable_thread_specific.hh | 2 +- source/blender/gpencil_modifiers/intern/MOD_gpencillength.c | 7 +------ source/blender/io/usd/intern/usd_reader_stage.cc | 2 +- source/blender/io/usd/intern/usd_reader_stage.h | 2 +- source/blender/makesdna/DNA_lineart_types.h | 8 -------- source/blender/modifiers/intern/MOD_nodes_evaluator.cc | 2 +- source/blender/modifiers/intern/MOD_nodes_evaluator.hh | 2 +- .../blender/nodes/composite/nodes/node_composite_antialiasing.c | 6 ------ 8 files changed, 6 insertions(+), 25 deletions(-) diff --git a/source/blender/blenlib/BLI_enumerable_thread_specific.hh b/source/blender/blenlib/BLI_enumerable_thread_specific.hh index 3051d980d45..b5981028893 100644 --- a/source/blender/blenlib/BLI_enumerable_thread_specific.hh +++ b/source/blender/blenlib/BLI_enumerable_thread_specific.hh @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillength.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillength.c index fd94ac92bc3..857c683d95a 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencillength.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillength.c @@ -1,6 +1,4 @@ /* - * ***** 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 @@ -12,14 +10,11 @@ * 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, + * 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) 2017, Blender Foundation * This is a new part of Blender - * - * ***** END GPL LICENSE BLOCK ***** - * */ /** \file diff --git a/source/blender/io/usd/intern/usd_reader_stage.cc b/source/blender/io/usd/intern/usd_reader_stage.cc index d3693f783ec..233b3d9da4d 100644 --- a/source/blender/io/usd/intern/usd_reader_stage.cc +++ b/source/blender/io/usd/intern/usd_reader_stage.cc @@ -10,7 +10,7 @@ * 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, + * 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) 2021 Tangent Animation and diff --git a/source/blender/io/usd/intern/usd_reader_stage.h b/source/blender/io/usd/intern/usd_reader_stage.h index 7cc557f7802..ba223962c0c 100644 --- a/source/blender/io/usd/intern/usd_reader_stage.h +++ b/source/blender/io/usd/intern/usd_reader_stage.h @@ -10,7 +10,7 @@ * 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, + * 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) 2021 Tangent Animation and diff --git a/source/blender/makesdna/DNA_lineart_types.h b/source/blender/makesdna/DNA_lineart_types.h index e93cf050e18..cdb09c3af50 100644 --- a/source/blender/makesdna/DNA_lineart_types.h +++ b/source/blender/makesdna/DNA_lineart_types.h @@ -1,6 +1,4 @@ /* - * ***** 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 @@ -17,12 +15,6 @@ * * The Original Code is Copyright (C) 2010 Blender Foundation. * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** */ #pragma once diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc index 1391587fa7d..47dfd9bc8f6 100644 --- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc +++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.hh b/source/blender/modifiers/intern/MOD_nodes_evaluator.hh index f4ee6242dcb..d8c60d31986 100644 --- a/source/blender/modifiers/intern/MOD_nodes_evaluator.hh +++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.hh @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/source/blender/nodes/composite/nodes/node_composite_antialiasing.c b/source/blender/nodes/composite/nodes/node_composite_antialiasing.c index 81e2408fcf9..a5906c31093 100644 --- a/source/blender/nodes/composite/nodes/node_composite_antialiasing.c +++ b/source/blender/nodes/composite/nodes/node_composite_antialiasing.c @@ -1,6 +1,4 @@ /* - * ***** 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 @@ -19,10 +17,6 @@ * All rights reserved. * * The Original Code is: all of this file. - * - * Contributor(s): IRIE Shinsuke - * - * ***** END GPL LICENSE BLOCK ***** */ /** \file -- cgit v1.2.3 From d3d4be1db3a09084eb2ff329bb7a530a87481480 Mon Sep 17 00:00:00 2001 From: Peter Kim Date: Thu, 5 Aug 2021 13:14:26 +0900 Subject: XR: Action Binding Improvements Provides several important improvements to the runtime action bindings operation and internal API. Moves input-specific action data (input thresholds, input regions, pose offsets/spaces) from actions to more granular action bindings. This allows a single action to be mapped to a variety of inputs, without having to share a single input threshold, region, or space. Also removes the need for action space creation API, as spaces for pose actions will be automatically created with the bindings. The correct action data for the current inputs is set by calling xrGetCurrentInteractionProfile() to get the current profile and then retrieving the corresponding mapped data. Does not bring about any changes for users since only internal runtime functionality is currently affected. Reviewed By: Julian Eisel Differential Revision: http://developer.blender.org/D12077 --- intern/ghost/GHOST_C-api.h | 19 +- intern/ghost/GHOST_Types.h | 24 +- intern/ghost/intern/GHOST_C-api.cpp | 29 +- intern/ghost/intern/GHOST_XrAction.cpp | 188 ++++---- intern/ghost/intern/GHOST_XrAction.h | 47 +- intern/ghost/intern/GHOST_XrSession.cpp | 87 +--- intern/ghost/intern/GHOST_XrSession.h | 9 +- source/blender/makesdna/DNA_xr_types.h | 9 + source/blender/windowmanager/CMakeLists.txt | 2 +- source/blender/windowmanager/WM_api.h | 26 +- .../blender/windowmanager/xr/intern/wm_xr_action.c | 454 +++++++++++++++++++ .../windowmanager/xr/intern/wm_xr_actions.c | 480 --------------------- .../blender/windowmanager/xr/intern/wm_xr_intern.h | 5 +- 13 files changed, 654 insertions(+), 725 deletions(-) create mode 100644 source/blender/windowmanager/xr/intern/wm_xr_action.c delete mode 100644 source/blender/windowmanager/xr/intern/wm_xr_actions.c diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index 46e3888a367..fea5a545807 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -1066,22 +1066,6 @@ void GHOST_XrDestroyActions(GHOST_XrContextHandle xr_context, uint32_t count, const char *const *action_names); -/** - * Create spaces for pose-based OpenXR actions. - */ -int GHOST_XrCreateActionSpaces(GHOST_XrContextHandle xr_context, - const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos); - -/** - * Destroy previously created spaces for OpenXR actions. - */ -void GHOST_XrDestroyActionSpaces(GHOST_XrContextHandle xr_context, - const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos); - /** * Create input/output path bindings for OpenXR actions. */ @@ -1096,7 +1080,8 @@ int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_context, void GHOST_XrDestroyActionBindings(GHOST_XrContextHandle xr_context, const char *action_set_name, uint32_t count, - const GHOST_XrActionProfileInfo *infos); + const char *const *action_names, + const char *const *profile_paths); /** * Attach all created action sets to the current OpenXR session. diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 94a3fd86b73..fb19b9535ad 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -719,29 +719,27 @@ typedef struct GHOST_XrActionInfo { const char **subaction_paths; /** States for each subaction path. */ void *states; + /** Input thresholds/regions for each subaction path. */ + float *float_thresholds; + int16_t *axis_flags; GHOST_XrCustomdataFreeFn customdata_free_fn; void *customdata; /* wmXrAction */ } GHOST_XrActionInfo; -typedef struct GHOST_XrActionSpaceInfo { - const char *action_name; - uint32_t count_subaction_paths; - const char **subaction_paths; - /** Poses for each subaction path. */ - const GHOST_XrPose *poses; -} GHOST_XrActionSpaceInfo; - typedef struct GHOST_XrActionBindingInfo { - const char *action_name; - uint32_t count_interaction_paths; - /** Interaction path: User (sub-action) path + component path. */ - const char **interaction_paths; + const char *component_path; + float float_threshold; + int16_t axis_flag; + GHOST_XrPose pose; } GHOST_XrActionBindingInfo; typedef struct GHOST_XrActionProfileInfo { + const char *action_name; const char *profile_path; - uint32_t count_bindings; + uint32_t count_subaction_paths; + const char **subaction_paths; + /* Bindings for each subaction path. */ const GHOST_XrActionBindingInfo *bindings; } GHOST_XrActionProfileInfo; diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index cb409595e50..0bc9be26eb1 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -961,28 +961,6 @@ void GHOST_XrDestroyActions(GHOST_XrContextHandle xr_contexthandle, GHOST_XR_CAPI_CALL(xr_session->destroyActions(action_set_name, count, action_names), xr_context); } -int GHOST_XrCreateActionSpaces(GHOST_XrContextHandle xr_contexthandle, - const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos) -{ - GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; - GHOST_XrSession *xr_session = xr_context->getSession(); - GHOST_XR_CAPI_CALL_RET(xr_session->createActionSpaces(action_set_name, count, infos), - xr_context); - return 0; -} - -void GHOST_XrDestroyActionSpaces(GHOST_XrContextHandle xr_contexthandle, - const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos) -{ - GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; - GHOST_XrSession *xr_session = xr_context->getSession(); - GHOST_XR_CAPI_CALL(xr_session->destroyActionSpaces(action_set_name, count, infos), xr_context); -} - int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_contexthandle, const char *action_set_name, uint32_t count, @@ -998,11 +976,14 @@ int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_contexthandle, void GHOST_XrDestroyActionBindings(GHOST_XrContextHandle xr_contexthandle, const char *action_set_name, uint32_t count, - const GHOST_XrActionProfileInfo *infos) + const char *const *action_names, + const char *const *profile_paths) { GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; GHOST_XrSession *xr_session = xr_context->getSession(); - GHOST_XR_CAPI_CALL(xr_session->destroyActionBindings(action_set_name, count, infos), xr_context); + GHOST_XR_CAPI_CALL( + xr_session->destroyActionBindings(action_set_name, count, action_names, profile_paths), + xr_context); } int GHOST_XrAttachActionSets(GHOST_XrContextHandle xr_contexthandle) diff --git a/intern/ghost/intern/GHOST_XrAction.cpp b/intern/ghost/intern/GHOST_XrAction.cpp index 9c4f7fbc7d8..676a3367ee1 100644 --- a/intern/ghost/intern/GHOST_XrAction.cpp +++ b/intern/ghost/intern/GHOST_XrAction.cpp @@ -33,24 +33,22 @@ * * \{ */ -GHOST_XrActionSpace::GHOST_XrActionSpace(XrInstance instance, - XrSession session, +GHOST_XrActionSpace::GHOST_XrActionSpace(XrSession session, XrAction action, - const GHOST_XrActionSpaceInfo &info, - uint32_t subaction_idx) + const char *action_name, + const char *profile_path, + XrPath subaction_path, + const char *subaction_path_str, + const GHOST_XrPose &pose) { - const char *subaction_path = info.subaction_paths[subaction_idx]; - CHECK_XR(xrStringToPath(instance, subaction_path, &m_subaction_path), - (std::string("Failed to get user path \"") + subaction_path + "\".").data()); - XrActionSpaceCreateInfo action_space_info{XR_TYPE_ACTION_SPACE_CREATE_INFO}; action_space_info.action = action; - action_space_info.subactionPath = m_subaction_path; - copy_ghost_pose_to_openxr_pose(info.poses[subaction_idx], action_space_info.poseInActionSpace); + action_space_info.subactionPath = subaction_path; + copy_ghost_pose_to_openxr_pose(pose, action_space_info.poseInActionSpace); CHECK_XR(xrCreateActionSpace(session, &action_space_info, &m_space), - (std::string("Failed to create space \"") + subaction_path + "\" for action \"" + - info.action_name + "\".") + (std::string("Failed to create space \"") + subaction_path_str + "\" for action \"" + + action_name + "\" and profile \"" + profile_path + "\".") .data()); } @@ -66,11 +64,6 @@ XrSpace GHOST_XrActionSpace::getSpace() const return m_space; } -const XrPath &GHOST_XrActionSpace::getSubactionPath() const -{ - return m_subaction_path; -} - /** \} */ /* -------------------------------------------------------------------- */ @@ -79,13 +72,19 @@ const XrPath &GHOST_XrActionSpace::getSubactionPath() const * \{ */ GHOST_XrActionProfile::GHOST_XrActionProfile(XrInstance instance, + XrSession session, XrAction action, - const char *profile_path, - const GHOST_XrActionBindingInfo &info) + GHOST_XrActionType type, + const GHOST_XrActionProfileInfo &info) { - CHECK_XR( - xrStringToPath(instance, profile_path, &m_profile), - (std::string("Failed to get interaction profile path \"") + profile_path + "\".").data()); + CHECK_XR(xrStringToPath(instance, info.profile_path, &m_profile), + (std::string("Failed to get interaction profile path \"") + info.profile_path + "\".") + .data()); + + const bool is_float_action = (type == GHOST_kXrActionTypeFloatInput || + type == GHOST_kXrActionTypeVector2fInput); + const bool is_button_action = (is_float_action || type == GHOST_kXrActionTypeBooleanInput); + const bool is_pose_action = (type == GHOST_kXrActionTypePoseInput); /* Create bindings. */ XrInteractionProfileSuggestedBinding bindings_info{ @@ -93,31 +92,80 @@ GHOST_XrActionProfile::GHOST_XrActionProfile(XrInstance instance, bindings_info.interactionProfile = m_profile; bindings_info.countSuggestedBindings = 1; - for (uint32_t interaction_idx = 0; interaction_idx < info.count_interaction_paths; - ++interaction_idx) { - const char *interaction_path = info.interaction_paths[interaction_idx]; + for (uint32_t subaction_idx = 0; subaction_idx < info.count_subaction_paths; ++subaction_idx) { + const char *subaction_path_str = info.subaction_paths[subaction_idx]; + const GHOST_XrActionBindingInfo &binding_info = info.bindings[subaction_idx]; + + const std::string interaction_path = std::string(subaction_path_str) + + binding_info.component_path; if (m_bindings.find(interaction_path) != m_bindings.end()) { continue; } XrActionSuggestedBinding sbinding; sbinding.action = action; - CHECK_XR(xrStringToPath(instance, interaction_path, &sbinding.binding), + CHECK_XR(xrStringToPath(instance, interaction_path.data(), &sbinding.binding), (std::string("Failed to get interaction path \"") + interaction_path + "\".").data()); bindings_info.suggestedBindings = &sbinding; /* Although the bindings will be re-suggested in GHOST_XrSession::attachActionSets(), it * greatly improves error checking to suggest them here first. */ CHECK_XR(xrSuggestInteractionProfileBindings(instance, &bindings_info), - (std::string("Failed to create binding for profile \"") + profile_path + - "\" and action \"" + info.action_name + - "\". Are the profile and action paths correct?") + (std::string("Failed to create binding for action \"") + info.action_name + + "\" and profile \"" + info.profile_path + + "\". Are the action and profile paths correct?") .data()); m_bindings.insert({interaction_path, sbinding.binding}); + + if (m_subaction_data.find(subaction_path_str) == m_subaction_data.end()) { + std::map::iterator it = + m_subaction_data + .emplace( + std::piecewise_construct, std::make_tuple(subaction_path_str), std::make_tuple()) + .first; + GHOST_XrSubactionData &subaction = it->second; + + CHECK_XR(xrStringToPath(instance, subaction_path_str, &subaction.subaction_path), + (std::string("Failed to get user path \"") + subaction_path_str + "\".").data()); + + if (is_float_action || is_button_action) { + if (is_float_action) { + subaction.float_threshold = binding_info.float_threshold; + } + if (is_button_action) { + subaction.axis_flag = binding_info.axis_flag; + } + } + else if (is_pose_action) { + /* Create action space for pose bindings. */ + subaction.space = std::make_unique(session, + action, + info.action_name, + info.profile_path, + subaction.subaction_path, + subaction_path_str, + binding_info.pose); + } + } } } +XrPath GHOST_XrActionProfile::getProfile() const +{ + return m_profile; +} + +const GHOST_XrSubactionData *GHOST_XrActionProfile::getSubaction(XrPath subaction_path) const +{ + for (auto &[subaction_path_str, subaction] : m_subaction_data) { + if (subaction.subaction_path == subaction_path) { + return &subaction; + } + } + return nullptr; +} + void GHOST_XrActionProfile::getBindings( XrAction action, std::map> &r_bindings) const { @@ -152,6 +200,8 @@ GHOST_XrAction::GHOST_XrAction(XrInstance instance, const GHOST_XrActionInfo &info) : m_type(info.type), m_states(info.states), + m_float_thresholds(info.float_thresholds), + m_axis_flags(info.axis_flags), m_custom_data_( std::make_unique(info.customdata, info.customdata_free_fn)) { @@ -201,52 +251,25 @@ GHOST_XrAction::~GHOST_XrAction() } } -bool GHOST_XrAction::createSpace(XrInstance instance, - XrSession session, - const GHOST_XrActionSpaceInfo &info) -{ - uint32_t subaction_idx = 0; - for (; subaction_idx < info.count_subaction_paths; ++subaction_idx) { - if (m_spaces.find(info.subaction_paths[subaction_idx]) != m_spaces.end()) { - return false; - } - } - - for (subaction_idx = 0; subaction_idx < info.count_subaction_paths; ++subaction_idx) { - m_spaces.emplace(std::piecewise_construct, - std::make_tuple(info.subaction_paths[subaction_idx]), - std::make_tuple(instance, session, m_action, info, subaction_idx)); - } - - return true; -} - -void GHOST_XrAction::destroySpace(const char *subaction_path) -{ - if (m_spaces.find(subaction_path) != m_spaces.end()) { - m_spaces.erase(subaction_path); - } -} - bool GHOST_XrAction::createBinding(XrInstance instance, - const char *profile_path, - const GHOST_XrActionBindingInfo &info) + XrSession session, + const GHOST_XrActionProfileInfo &info) { - if (m_profiles.find(profile_path) != m_profiles.end()) { + if (m_profiles.find(info.profile_path) != m_profiles.end()) { return false; } m_profiles.emplace(std::piecewise_construct, - std::make_tuple(profile_path), - std::make_tuple(instance, m_action, profile_path, info)); + std::make_tuple(info.profile_path), + std::make_tuple(instance, session, m_action, m_type, info)); return true; } -void GHOST_XrAction::destroyBinding(const char *interaction_profile_path) +void GHOST_XrAction::destroyBinding(const char *profile_path) { - if (m_profiles.find(interaction_profile_path) != m_profiles.end()) { - m_profiles.erase(interaction_profile_path); + if (m_profiles.find(profile_path) != m_profiles.end()) { + m_profiles.erase(profile_path); } } @@ -255,6 +278,10 @@ void GHOST_XrAction::updateState(XrSession session, XrSpace reference_space, const XrTime &predicted_display_time) { + const bool is_float_action = (m_type == GHOST_kXrActionTypeFloatInput || + m_type == GHOST_kXrActionTypeVector2fInput); + const bool is_button_action = (is_float_action || m_type == GHOST_kXrActionTypeBooleanInput); + XrActionStateGetInfo state_info{XR_TYPE_ACTION_STATE_GET_INFO}; state_info.action = m_action; @@ -262,6 +289,28 @@ void GHOST_XrAction::updateState(XrSession session, for (size_t subaction_idx = 0; subaction_idx < count_subaction_paths; ++subaction_idx) { state_info.subactionPath = m_subaction_paths[subaction_idx]; + /* Set subaction data based on current interaction profile. */ + XrInteractionProfileState profile_state{XR_TYPE_INTERACTION_PROFILE_STATE}; + CHECK_XR(xrGetCurrentInteractionProfile(session, state_info.subactionPath, &profile_state), + "Failed to get current interaction profile."); + + const GHOST_XrSubactionData *subaction = nullptr; + for (auto &[profile_path, profile] : m_profiles) { + if (profile.getProfile() == profile_state.interactionProfile) { + subaction = profile.getSubaction(state_info.subactionPath); + break; + } + } + + if (subaction != nullptr) { + if (is_float_action) { + m_float_thresholds[subaction_idx] = subaction->float_threshold; + } + if (is_button_action) { + m_axis_flags[subaction_idx] = subaction->axis_flag; + } + } + switch (m_type) { case GHOST_kXrActionTypeBooleanInput: { XrActionStateBoolean state{XR_TYPE_ACTION_STATE_BOOLEAN}; @@ -299,14 +348,9 @@ void GHOST_XrAction::updateState(XrSession session, xrGetActionStatePose(session, &state_info, &state), (std::string("Failed to get state for pose action \"") + action_name + "\".").data()); if (state.isActive) { - XrSpace pose_space = XR_NULL_HANDLE; - for (auto &[path, space] : m_spaces) { - if (space.getSubactionPath() == state_info.subactionPath) { - pose_space = space.getSpace(); - break; - } - } - + XrSpace pose_space = ((subaction != nullptr) && (subaction->space != nullptr)) ? + subaction->space->getSpace() : + XR_NULL_HANDLE; if (pose_space != XR_NULL_HANDLE) { XrSpaceLocation space_location{XR_TYPE_SPACE_LOCATION}; CHECK_XR( diff --git a/intern/ghost/intern/GHOST_XrAction.h b/intern/ghost/intern/GHOST_XrAction.h index 32445c616bd..e2a89e87278 100644 --- a/intern/ghost/intern/GHOST_XrAction.h +++ b/intern/ghost/intern/GHOST_XrAction.h @@ -34,38 +34,53 @@ class GHOST_XrActionSpace { public: GHOST_XrActionSpace() = delete; /* Default constructor for map storage. */ - GHOST_XrActionSpace(XrInstance instance, - XrSession session, + GHOST_XrActionSpace(XrSession session, XrAction action, - const GHOST_XrActionSpaceInfo &info, - uint32_t subaction_idx); + const char *action_name, + const char *profile_path, + XrPath subaction_path, + const char *subaction_path_str, + const GHOST_XrPose &pose); ~GHOST_XrActionSpace(); XrSpace getSpace() const; - const XrPath &getSubactionPath() const; private: XrSpace m_space = XR_NULL_HANDLE; - XrPath m_subaction_path = XR_NULL_PATH; }; /* -------------------------------------------------------------------- */ +typedef struct GHOST_XrSubactionData { + XrPath subaction_path = XR_NULL_PATH; + float float_threshold; + int16_t axis_flag; + std::unique_ptr space = nullptr; +} GHOST_XrSubactionData; + +/* -------------------------------------------------------------------- */ + class GHOST_XrActionProfile { public: GHOST_XrActionProfile() = delete; /* Default constructor for map storage. */ GHOST_XrActionProfile(XrInstance instance, + XrSession session, XrAction action, - const char *profile_path, - const GHOST_XrActionBindingInfo &info); + GHOST_XrActionType type, + const GHOST_XrActionProfileInfo &info); ~GHOST_XrActionProfile() = default; + XrPath getProfile() const; + const GHOST_XrSubactionData *getSubaction(XrPath subaction_path) const; void getBindings(XrAction action, std::map> &r_bindings) const; private: XrPath m_profile = XR_NULL_PATH; - /* Bindings identified by interaction (user (subaction) + component) path. */ + + /** Subaction data identified by user (subaction) path. */ + std::map m_subaction_data; + /** Bindings identified by interaction (user (subaction) + component) path. */ std::map m_bindings; }; @@ -77,12 +92,9 @@ class GHOST_XrAction { GHOST_XrAction(XrInstance instance, XrActionSet action_set, const GHOST_XrActionInfo &info); ~GHOST_XrAction(); - bool createSpace(XrInstance instance, XrSession session, const GHOST_XrActionSpaceInfo &info); - void destroySpace(const char *subaction_path); - bool createBinding(XrInstance instance, - const char *profile_path, - const GHOST_XrActionBindingInfo &info); + XrSession session, + const GHOST_XrActionProfileInfo &info); void destroyBinding(const char *profile_path); void updateState(XrSession session, @@ -105,12 +117,13 @@ class GHOST_XrAction { std::vector m_subaction_paths; /** States for each subaction path. */ void *m_states; + /** Input thresholds/regions for each subaction path. */ + float *m_float_thresholds; + int16_t *m_axis_flags; std::unique_ptr m_custom_data_ = nullptr; /* wmXrAction */ - /* Spaces identified by user (subaction) path. */ - std::map m_spaces; - /* Profiles identified by interaction profile path. */ + /** Profiles identified by interaction profile path. */ std::map m_profiles; }; diff --git a/intern/ghost/intern/GHOST_XrSession.cpp b/intern/ghost/intern/GHOST_XrSession.cpp index 919d11d22a9..a29ec1cc560 100644 --- a/intern/ghost/intern/GHOST_XrSession.cpp +++ b/intern/ghost/intern/GHOST_XrSession.cpp @@ -610,9 +610,9 @@ void GHOST_XrSession::destroyActions(const char *action_set_name, } } -bool GHOST_XrSession::createActionSpaces(const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos) +bool GHOST_XrSession::createActionBindings(const char *action_set_name, + uint32_t count, + const GHOST_XrActionProfileInfo *infos) { GHOST_XrActionSet *action_set = find_action_set(m_oxr.get(), action_set_name); if (action_set == nullptr) { @@ -622,98 +622,37 @@ bool GHOST_XrSession::createActionSpaces(const char *action_set_name, XrInstance instance = m_context->getInstance(); XrSession session = m_oxr->session; - for (uint32_t action_idx = 0; action_idx < count; ++action_idx) { - const GHOST_XrActionSpaceInfo &info = infos[action_idx]; + for (uint32_t profile_idx = 0; profile_idx < count; ++profile_idx) { + const GHOST_XrActionProfileInfo &info = infos[profile_idx]; GHOST_XrAction *action = action_set->findAction(info.action_name); if (action == nullptr) { continue; } - if (!action->createSpace(instance, session, info)) { - return false; - } + action->createBinding(instance, session, info); } return true; } -void GHOST_XrSession::destroyActionSpaces(const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos) +void GHOST_XrSession::destroyActionBindings(const char *action_set_name, + uint32_t count, + const char *const *action_names, + const char *const *profile_paths) { GHOST_XrActionSet *action_set = find_action_set(m_oxr.get(), action_set_name); if (action_set == nullptr) { return; } - for (uint32_t action_idx = 0; action_idx < count; ++action_idx) { - const GHOST_XrActionSpaceInfo &info = infos[action_idx]; - - GHOST_XrAction *action = action_set->findAction(info.action_name); + for (uint32_t i = 0; i < count; ++i) { + GHOST_XrAction *action = action_set->findAction(action_names[i]); if (action == nullptr) { continue; } - for (uint32_t subaction_idx = 0; subaction_idx < info.count_subaction_paths; ++subaction_idx) { - action->destroySpace(info.subaction_paths[subaction_idx]); - } - } -} - -bool GHOST_XrSession::createActionBindings(const char *action_set_name, - uint32_t count, - const GHOST_XrActionProfileInfo *infos) -{ - GHOST_XrActionSet *action_set = find_action_set(m_oxr.get(), action_set_name); - if (action_set == nullptr) { - return false; - } - - XrInstance instance = m_context->getInstance(); - - for (uint32_t profile_idx = 0; profile_idx < count; ++profile_idx) { - const GHOST_XrActionProfileInfo &info = infos[profile_idx]; - const char *profile_path = info.profile_path; - - for (uint32_t binding_idx = 0; binding_idx < info.count_bindings; ++binding_idx) { - const GHOST_XrActionBindingInfo &binding = info.bindings[binding_idx]; - - GHOST_XrAction *action = action_set->findAction(binding.action_name); - if (action == nullptr) { - continue; - } - - action->createBinding(instance, profile_path, binding); - } - } - - return true; -} - -void GHOST_XrSession::destroyActionBindings(const char *action_set_name, - uint32_t count, - const GHOST_XrActionProfileInfo *infos) -{ - GHOST_XrActionSet *action_set = find_action_set(m_oxr.get(), action_set_name); - if (action_set == nullptr) { - return; - } - - for (uint32_t profile_idx = 0; profile_idx < count; ++profile_idx) { - const GHOST_XrActionProfileInfo &info = infos[profile_idx]; - const char *profile_path = info.profile_path; - - for (uint32_t binding_idx = 0; binding_idx < info.count_bindings; ++binding_idx) { - const GHOST_XrActionBindingInfo &binding = info.bindings[binding_idx]; - - GHOST_XrAction *action = action_set->findAction(binding.action_name); - if (action == nullptr) { - continue; - } - - action->destroyBinding(profile_path); - } + action->destroyBinding(profile_paths[i]); } } diff --git a/intern/ghost/intern/GHOST_XrSession.h b/intern/ghost/intern/GHOST_XrSession.h index d448585d14c..cdeef153fb1 100644 --- a/intern/ghost/intern/GHOST_XrSession.h +++ b/intern/ghost/intern/GHOST_XrSession.h @@ -60,18 +60,13 @@ class GHOST_XrSession { void destroyActions(const char *action_set_name, uint32_t count, const char *const *action_names); - bool createActionSpaces(const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos); - void destroyActionSpaces(const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos); bool createActionBindings(const char *action_set_name, uint32_t count, const GHOST_XrActionProfileInfo *infos); void destroyActionBindings(const char *action_set_name, uint32_t count, - const GHOST_XrActionProfileInfo *infos); + const char *const *action_names, + const char *const *profile_paths); bool attachActionSets(); /** diff --git a/source/blender/makesdna/DNA_xr_types.h b/source/blender/makesdna/DNA_xr_types.h index fc00d5eb839..c0928e1519f 100644 --- a/source/blender/makesdna/DNA_xr_types.h +++ b/source/blender/makesdna/DNA_xr_types.h @@ -74,6 +74,15 @@ typedef enum eXrOpFlag { XR_OP_MODAL = 2, } eXrOpFlag; +typedef enum eXrAxisFlag { + /** For axis-based inputs (thumbstick/trackpad/etc). Determines the region for action execution + (mutually exclusive per axis). */ + XR_AXIS0_POS = (1 << 0), + XR_AXIS0_NEG = (1 << 1), + XR_AXIS1_POS = (1 << 2), + XR_AXIS1_NEG = (1 << 3), +} eXrAxisFlag; + #ifdef __cplusplus } #endif diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index e513c49c11b..8b0ceb02b5f 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -203,7 +203,7 @@ if(WITH_XR_OPENXR) list(APPEND SRC xr/intern/wm_xr.c - xr/intern/wm_xr_actions.c + xr/intern/wm_xr_action.c xr/intern/wm_xr_draw.c xr/intern/wm_xr_session.c diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 136c639caea..fb973592a57 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -978,34 +978,24 @@ bool WM_xr_action_create(wmXrData *xr, eXrActionType type, unsigned int count_subaction_paths, const char **subaction_paths, - const float *float_threshold, struct wmOperatorType *ot, struct IDProperty *op_properties, eXrOpFlag op_flag); void WM_xr_action_destroy(wmXrData *xr, const char *action_set_name, const char *action_name); -bool WM_xr_action_space_create(wmXrData *xr, - const char *action_set_name, - const char *action_name, - unsigned int count_subaction_paths, - const char **subaction_paths, - const struct wmXrPose *poses); -void WM_xr_action_space_destroy(wmXrData *xr, - const char *action_set_name, - const char *action_name, - unsigned int count_subaction_paths, - const char **subaction_paths); bool WM_xr_action_binding_create(wmXrData *xr, const char *action_set_name, - const char *profile_path, const char *action_name, - unsigned int count_interaction_paths, - const char **interaction_paths); + const char *profile_path, + unsigned int count_subaction_paths, + const char **subaction_paths, + const char **component_paths, + const float *float_thresholds, + const eXrAxisFlag *axis_flags, + const struct wmXrPose *poses); void WM_xr_action_binding_destroy(wmXrData *xr, const char *action_set_name, - const char *profile_path, const char *action_name, - unsigned int count_interaction_paths, - const char **interaction_paths); + const char *profile_path); /* If action_set_name is NULL, then all action sets will be treated as active. */ bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name); diff --git a/source/blender/windowmanager/xr/intern/wm_xr_action.c b/source/blender/windowmanager/xr/intern/wm_xr_action.c new file mode 100644 index 00000000000..ee4cfcccaa7 --- /dev/null +++ b/source/blender/windowmanager/xr/intern/wm_xr_action.c @@ -0,0 +1,454 @@ +/* + * 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. + */ + +/** \file + * \ingroup wm + * + * \name Window-Manager XR Actions + * + * Uses the Ghost-XR API to manage OpenXR actions. + * All functions are designed to be usable by RNA / the Python API. + */ + +#include "BLI_math.h" + +#include "GHOST_C-api.h" + +#include "MEM_guardedalloc.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "wm_xr_intern.h" + +/* -------------------------------------------------------------------- */ +/** \name XR-Action API + * + * API functions for managing OpenXR actions. + * + * \{ */ + +static wmXrActionSet *action_set_create(const char *action_set_name) +{ + wmXrActionSet *action_set = MEM_callocN(sizeof(*action_set), __func__); + action_set->name = MEM_mallocN(strlen(action_set_name) + 1, "XrActionSet_Name"); + strcpy(action_set->name, action_set_name); + + return action_set; +} + +static void action_set_destroy(void *val) +{ + wmXrActionSet *action_set = val; + + MEM_SAFE_FREE(action_set->name); + + MEM_freeN(action_set); +} + +static wmXrActionSet *action_set_find(wmXrData *xr, const char *action_set_name) +{ + return GHOST_XrGetActionSetCustomdata(xr->runtime->context, action_set_name); +} + +static wmXrAction *action_create(const char *action_name, + eXrActionType type, + unsigned int count_subaction_paths, + const char **subaction_paths, + wmOperatorType *ot, + IDProperty *op_properties, + eXrOpFlag op_flag) +{ + wmXrAction *action = MEM_callocN(sizeof(*action), __func__); + action->name = MEM_mallocN(strlen(action_name) + 1, "XrAction_Name"); + strcpy(action->name, action_name); + action->type = type; + + const unsigned int count = count_subaction_paths; + action->count_subaction_paths = count; + + action->subaction_paths = MEM_mallocN(sizeof(*action->subaction_paths) * count, + "XrAction_SubactionPaths"); + for (unsigned int i = 0; i < count; ++i) { + action->subaction_paths[i] = MEM_mallocN(strlen(subaction_paths[i]) + 1, + "XrAction_SubactionPath"); + strcpy(action->subaction_paths[i], subaction_paths[i]); + } + + size_t size; + switch (type) { + case XR_BOOLEAN_INPUT: + size = sizeof(bool); + break; + case XR_FLOAT_INPUT: + size = sizeof(float); + break; + case XR_VECTOR2F_INPUT: + size = sizeof(float) * 2; + break; + case XR_POSE_INPUT: + size = sizeof(GHOST_XrPose); + break; + case XR_VIBRATION_OUTPUT: + return action; + } + action->states = MEM_calloc_arrayN(count, size, "XrAction_States"); + action->states_prev = MEM_calloc_arrayN(count, size, "XrAction_StatesPrev"); + + const bool is_float_action = (type == XR_FLOAT_INPUT || type == XR_VECTOR2F_INPUT); + const bool is_button_action = (is_float_action || type == XR_BOOLEAN_INPUT); + if (is_float_action) { + action->float_thresholds = MEM_calloc_arrayN( + count, sizeof(*action->float_thresholds), "XrAction_FloatThresholds"); + } + if (is_button_action) { + action->axis_flags = MEM_calloc_arrayN( + count, sizeof(*action->axis_flags), "XrAction_AxisFlags"); + } + + action->ot = ot; + action->op_properties = op_properties; + action->op_flag = op_flag; + + return action; +} + +static void action_destroy(void *val) +{ + wmXrAction *action = val; + + MEM_SAFE_FREE(action->name); + + const unsigned int count = action->count_subaction_paths; + char **subaction_paths = action->subaction_paths; + if (subaction_paths) { + for (unsigned int i = 0; i < count; ++i) { + MEM_SAFE_FREE(subaction_paths[i]); + } + MEM_freeN(subaction_paths); + } + + MEM_SAFE_FREE(action->states); + MEM_SAFE_FREE(action->states_prev); + + MEM_SAFE_FREE(action->float_thresholds); + MEM_SAFE_FREE(action->axis_flags); + + MEM_freeN(action); +} + +static wmXrAction *action_find(wmXrData *xr, const char *action_set_name, const char *action_name) +{ + return GHOST_XrGetActionCustomdata(xr->runtime->context, action_set_name, action_name); +} + +bool WM_xr_action_set_create(wmXrData *xr, const char *action_set_name) +{ + if (action_set_find(xr, action_set_name)) { + return false; + } + + wmXrActionSet *action_set = action_set_create(action_set_name); + + GHOST_XrActionSetInfo info = { + .name = action_set_name, + .customdata_free_fn = action_set_destroy, + .customdata = action_set, + }; + + if (!GHOST_XrCreateActionSet(xr->runtime->context, &info)) { + return false; + } + + return true; +} + +void WM_xr_action_set_destroy(wmXrData *xr, const char *action_set_name) +{ + wmXrActionSet *action_set = action_set_find(xr, action_set_name); + if (!action_set) { + return; + } + + wmXrSessionState *session_state = &xr->runtime->session_state; + + if (action_set == session_state->active_action_set) { + if (action_set->controller_pose_action) { + wm_xr_session_controller_data_clear(session_state); + action_set->controller_pose_action = NULL; + } + if (action_set->active_modal_action) { + action_set->active_modal_action = NULL; + } + session_state->active_action_set = NULL; + } + + GHOST_XrDestroyActionSet(xr->runtime->context, action_set_name); +} + +bool WM_xr_action_create(wmXrData *xr, + const char *action_set_name, + const char *action_name, + eXrActionType type, + unsigned int count_subaction_paths, + const char **subaction_paths, + wmOperatorType *ot, + IDProperty *op_properties, + eXrOpFlag op_flag) +{ + if (action_find(xr, action_set_name, action_name)) { + return false; + } + + wmXrAction *action = action_create(action_name, + type, + count_subaction_paths, + subaction_paths, + ot, + op_properties, + op_flag); + + GHOST_XrActionInfo info = { + .name = action_name, + .count_subaction_paths = count_subaction_paths, + .subaction_paths = subaction_paths, + .states = action->states, + .float_thresholds = action->float_thresholds, + .axis_flags = (int16_t *)action->axis_flags, + .customdata_free_fn = action_destroy, + .customdata = action, + }; + + switch (type) { + case XR_BOOLEAN_INPUT: + info.type = GHOST_kXrActionTypeBooleanInput; + break; + case XR_FLOAT_INPUT: + info.type = GHOST_kXrActionTypeFloatInput; + break; + case XR_VECTOR2F_INPUT: + info.type = GHOST_kXrActionTypeVector2fInput; + break; + case XR_POSE_INPUT: + info.type = GHOST_kXrActionTypePoseInput; + break; + case XR_VIBRATION_OUTPUT: + info.type = GHOST_kXrActionTypeVibrationOutput; + break; + } + + if (!GHOST_XrCreateActions(xr->runtime->context, action_set_name, 1, &info)) { + return false; + } + + return true; +} + +void WM_xr_action_destroy(wmXrData *xr, const char *action_set_name, const char *action_name) +{ + wmXrActionSet *action_set = action_set_find(xr, action_set_name); + if (!action_set) { + return; + } + + wmXrAction *action = action_find(xr, action_set_name, action_name); + if (!action) { + return; + } + + if (action_set->controller_pose_action && + STREQ(action_set->controller_pose_action->name, action_name)) { + if (action_set == xr->runtime->session_state.active_action_set) { + wm_xr_session_controller_data_clear(&xr->runtime->session_state); + } + action_set->controller_pose_action = NULL; + } + if (action_set->active_modal_action && + STREQ(action_set->active_modal_action->name, action_name)) { + action_set->active_modal_action = NULL; + } + + GHOST_XrDestroyActions(xr->runtime->context, action_set_name, 1, &action_name); +} + + +bool WM_xr_action_binding_create(wmXrData *xr, + const char *action_set_name, + const char *action_name, + const char *profile_path, + unsigned int count_subaction_paths, + const char **subaction_paths, + const char **component_paths, + const float *float_thresholds, + const eXrAxisFlag *axis_flags, + const struct wmXrPose *poses) +{ + GHOST_XrActionBindingInfo *binding_infos = MEM_calloc_arrayN( + count_subaction_paths, sizeof(*binding_infos), __func__); + + for (unsigned int i = 0; i < count_subaction_paths; ++i) { + GHOST_XrActionBindingInfo *binding_info = &binding_infos[i]; + binding_info->component_path = component_paths[i]; + if (float_thresholds) { + binding_info->float_threshold = float_thresholds[i]; + } + if (axis_flags) { + binding_info->axis_flag = axis_flags[i]; + } + if (poses) { + copy_v3_v3(binding_info->pose.position, poses[i].position); + copy_qt_qt(binding_info->pose.orientation_quat, poses[i].orientation_quat); + } + } + + GHOST_XrActionProfileInfo profile_info = { + .action_name = action_name, + .profile_path = profile_path, + .count_subaction_paths = count_subaction_paths, + .subaction_paths = subaction_paths, + .bindings = binding_infos, + }; + + bool ret = GHOST_XrCreateActionBindings(xr->runtime->context, action_set_name, 1, &profile_info); + + MEM_freeN(binding_infos); + return ret; +} + +void WM_xr_action_binding_destroy(wmXrData *xr, + const char *action_set_name, + const char *action_name, + const char *profile_path) +{ + GHOST_XrDestroyActionBindings( + xr->runtime->context, action_set_name, 1, &action_name, &profile_path); +} + +bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name) +{ + wmXrActionSet *action_set = action_set_find(xr, action_set_name); + if (!action_set) { + return false; + } + + { + /* Unset active modal action (if any). */ + wmXrActionSet *active_action_set = xr->runtime->session_state.active_action_set; + if (active_action_set) { + wmXrAction *active_modal_action = active_action_set->active_modal_action; + if (active_modal_action) { + if (active_modal_action->active_modal_path) { + active_modal_action->active_modal_path = NULL; + } + active_action_set->active_modal_action = NULL; + } + } + } + + xr->runtime->session_state.active_action_set = action_set; + + if (action_set->controller_pose_action) { + wm_xr_session_controller_data_populate(action_set->controller_pose_action, xr); + } + + return true; +} + +bool WM_xr_controller_pose_action_set(wmXrData *xr, + const char *action_set_name, + const char *action_name) +{ + wmXrActionSet *action_set = action_set_find(xr, action_set_name); + if (!action_set) { + return false; + } + + wmXrAction *action = action_find(xr, action_set_name, action_name); + if (!action) { + return false; + } + + action_set->controller_pose_action = action; + + if (action_set == xr->runtime->session_state.active_action_set) { + wm_xr_session_controller_data_populate(action, xr); + } + + return true; +} + +bool WM_xr_action_state_get(const wmXrData *xr, + const char *action_set_name, + const char *action_name, + const char *subaction_path, + wmXrActionState *r_state) +{ + const wmXrAction *action = action_find((wmXrData *)xr, action_set_name, action_name); + if (!action) { + return false; + } + + r_state->type = (int)action->type; + + /* Find the action state corresponding to the subaction path. */ + for (unsigned int i = 0; i < action->count_subaction_paths; ++i) { + if (STREQ(subaction_path, action->subaction_paths[i])) { + switch (action->type) { + case XR_BOOLEAN_INPUT: + r_state->state_boolean = ((bool *)action->states)[i]; + break; + case XR_FLOAT_INPUT: + r_state->state_float = ((float *)action->states)[i]; + break; + case XR_VECTOR2F_INPUT: + copy_v2_v2(r_state->state_vector2f, ((float(*)[2])action->states)[i]); + break; + case XR_POSE_INPUT: { + const GHOST_XrPose *pose = &((GHOST_XrPose *)action->states)[i]; + copy_v3_v3(r_state->state_pose.position, pose->position); + copy_qt_qt(r_state->state_pose.orientation_quat, pose->orientation_quat); + break; + } + case XR_VIBRATION_OUTPUT: + BLI_assert_unreachable(); + break; + } + return true; + } + } + + return false; +} + +bool WM_xr_haptic_action_apply(wmXrData *xr, + const char *action_set_name, + const char *action_name, + const int64_t *duration, + const float *frequency, + const float *amplitude) +{ + return GHOST_XrApplyHapticAction( + xr->runtime->context, action_set_name, action_name, duration, frequency, amplitude) ? + true : + false; +} + +void WM_xr_haptic_action_stop(wmXrData *xr, const char *action_set_name, const char *action_name) +{ + GHOST_XrStopHapticAction(xr->runtime->context, action_set_name, action_name); +} + +/** \} */ /* XR-Action API */ diff --git a/source/blender/windowmanager/xr/intern/wm_xr_actions.c b/source/blender/windowmanager/xr/intern/wm_xr_actions.c deleted file mode 100644 index 7eabd29baa0..00000000000 --- a/source/blender/windowmanager/xr/intern/wm_xr_actions.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** \file - * \ingroup wm - * - * \name Window-Manager XR Actions - * - * Uses the Ghost-XR API to manage OpenXR actions. - * All functions are designed to be usable by RNA / the Python API. - */ - -#include "BLI_math.h" - -#include "GHOST_C-api.h" - -#include "MEM_guardedalloc.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "wm_xr_intern.h" - -/* -------------------------------------------------------------------- */ -/** \name XR-Action API - * - * API functions for managing OpenXR actions. - * - * \{ */ - -static wmXrActionSet *action_set_create(const char *action_set_name) -{ - wmXrActionSet *action_set = MEM_callocN(sizeof(*action_set), __func__); - action_set->name = MEM_mallocN(strlen(action_set_name) + 1, "XrActionSet_Name"); - strcpy(action_set->name, action_set_name); - - return action_set; -} - -static void action_set_destroy(void *val) -{ - wmXrActionSet *action_set = val; - - MEM_SAFE_FREE(action_set->name); - - MEM_freeN(action_set); -} - -static wmXrActionSet *action_set_find(wmXrData *xr, const char *action_set_name) -{ - return GHOST_XrGetActionSetCustomdata(xr->runtime->context, action_set_name); -} - -static wmXrAction *action_create(const char *action_name, - eXrActionType type, - unsigned int count_subaction_paths, - const char **subaction_paths, - const float *float_threshold, - wmOperatorType *ot, - IDProperty *op_properties, - eXrOpFlag op_flag) -{ - wmXrAction *action = MEM_callocN(sizeof(*action), __func__); - action->name = MEM_mallocN(strlen(action_name) + 1, "XrAction_Name"); - strcpy(action->name, action_name); - action->type = type; - - const unsigned int count = count_subaction_paths; - action->count_subaction_paths = count; - - action->subaction_paths = MEM_mallocN(sizeof(*action->subaction_paths) * count, - "XrAction_SubactionPaths"); - for (unsigned int i = 0; i < count; ++i) { - action->subaction_paths[i] = MEM_mallocN(strlen(subaction_paths[i]) + 1, - "XrAction_SubactionPath"); - strcpy(action->subaction_paths[i], subaction_paths[i]); - } - - size_t size; - switch (type) { - case XR_BOOLEAN_INPUT: - size = sizeof(bool); - break; - case XR_FLOAT_INPUT: - size = sizeof(float); - break; - case XR_VECTOR2F_INPUT: - size = sizeof(float) * 2; - break; - case XR_POSE_INPUT: - size = sizeof(GHOST_XrPose); - break; - case XR_VIBRATION_OUTPUT: - return action; - } - action->states = MEM_calloc_arrayN(count, size, "XrAction_States"); - action->states_prev = MEM_calloc_arrayN(count, size, "XrAction_StatesPrev"); - - if (float_threshold) { - BLI_assert(type == XR_FLOAT_INPUT || type == XR_VECTOR2F_INPUT); - action->float_threshold = *float_threshold; - CLAMP(action->float_threshold, 0.0f, 1.0f); - } - - action->ot = ot; - action->op_properties = op_properties; - action->op_flag = op_flag; - - return action; -} - -static void action_destroy(void *val) -{ - wmXrAction *action = val; - - MEM_SAFE_FREE(action->name); - - const unsigned int count = action->count_subaction_paths; - char **subaction_paths = action->subaction_paths; - if (subaction_paths) { - for (unsigned int i = 0; i < count; ++i) { - MEM_SAFE_FREE(subaction_paths[i]); - } - MEM_freeN(subaction_paths); - } - - MEM_SAFE_FREE(action->states); - MEM_SAFE_FREE(action->states_prev); - - MEM_freeN(action); -} - -static wmXrAction *action_find(wmXrData *xr, const char *action_set_name, const char *action_name) -{ - return GHOST_XrGetActionCustomdata(xr->runtime->context, action_set_name, action_name); -} - -bool WM_xr_action_set_create(wmXrData *xr, const char *action_set_name) -{ - if (action_set_find(xr, action_set_name)) { - return false; - } - - wmXrActionSet *action_set = action_set_create(action_set_name); - - GHOST_XrActionSetInfo info = { - .name = action_set_name, - .customdata_free_fn = action_set_destroy, - .customdata = action_set, - }; - - if (!GHOST_XrCreateActionSet(xr->runtime->context, &info)) { - return false; - } - - return true; -} - -void WM_xr_action_set_destroy(wmXrData *xr, const char *action_set_name) -{ - wmXrActionSet *action_set = action_set_find(xr, action_set_name); - if (!action_set) { - return; - } - - wmXrSessionState *session_state = &xr->runtime->session_state; - - if (action_set == session_state->active_action_set) { - if (action_set->controller_pose_action) { - wm_xr_session_controller_data_clear(session_state); - action_set->controller_pose_action = NULL; - } - if (action_set->active_modal_action) { - action_set->active_modal_action = NULL; - } - session_state->active_action_set = NULL; - } - - GHOST_XrDestroyActionSet(xr->runtime->context, action_set_name); -} - -bool WM_xr_action_create(wmXrData *xr, - const char *action_set_name, - const char *action_name, - eXrActionType type, - unsigned int count_subaction_paths, - const char **subaction_paths, - const float *float_threshold, - wmOperatorType *ot, - IDProperty *op_properties, - eXrOpFlag op_flag) -{ - if (action_find(xr, action_set_name, action_name)) { - return false; - } - - wmXrAction *action = action_create(action_name, - type, - count_subaction_paths, - subaction_paths, - float_threshold, - ot, - op_properties, - op_flag); - - GHOST_XrActionInfo info = { - .name = action_name, - .count_subaction_paths = count_subaction_paths, - .subaction_paths = subaction_paths, - .states = action->states, - .customdata_free_fn = action_destroy, - .customdata = action, - }; - - switch (type) { - case XR_BOOLEAN_INPUT: - info.type = GHOST_kXrActionTypeBooleanInput; - break; - case XR_FLOAT_INPUT: - info.type = GHOST_kXrActionTypeFloatInput; - break; - case XR_VECTOR2F_INPUT: - info.type = GHOST_kXrActionTypeVector2fInput; - break; - case XR_POSE_INPUT: - info.type = GHOST_kXrActionTypePoseInput; - break; - case XR_VIBRATION_OUTPUT: - info.type = GHOST_kXrActionTypeVibrationOutput; - break; - } - - if (!GHOST_XrCreateActions(xr->runtime->context, action_set_name, 1, &info)) { - return false; - } - - return true; -} - -void WM_xr_action_destroy(wmXrData *xr, const char *action_set_name, const char *action_name) -{ - wmXrActionSet *action_set = action_set_find(xr, action_set_name); - if (!action_set) { - return; - } - - if (action_set->controller_pose_action && - STREQ(action_set->controller_pose_action->name, action_name)) { - if (action_set == xr->runtime->session_state.active_action_set) { - wm_xr_session_controller_data_clear(&xr->runtime->session_state); - } - action_set->controller_pose_action = NULL; - } - if (action_set->active_modal_action && - STREQ(action_set->active_modal_action->name, action_name)) { - action_set->active_modal_action = NULL; - } - - wmXrAction *action = action_find(xr, action_set_name, action_name); - if (!action) { - return; - } -} - -bool WM_xr_action_space_create(wmXrData *xr, - const char *action_set_name, - const char *action_name, - unsigned int count_subaction_paths, - const char **subaction_paths, - const wmXrPose *poses) -{ - GHOST_XrActionSpaceInfo info = { - .action_name = action_name, - .count_subaction_paths = count_subaction_paths, - .subaction_paths = subaction_paths, - }; - - GHOST_XrPose *ghost_poses = MEM_malloc_arrayN( - count_subaction_paths, sizeof(*ghost_poses), __func__); - for (unsigned int i = 0; i < count_subaction_paths; ++i) { - const wmXrPose *pose = &poses[i]; - GHOST_XrPose *ghost_pose = &ghost_poses[i]; - copy_v3_v3(ghost_pose->position, pose->position); - copy_qt_qt(ghost_pose->orientation_quat, pose->orientation_quat); - } - info.poses = ghost_poses; - - bool ret = GHOST_XrCreateActionSpaces(xr->runtime->context, action_set_name, 1, &info) ? true : - false; - MEM_freeN(ghost_poses); - return ret; -} - -void WM_xr_action_space_destroy(wmXrData *xr, - const char *action_set_name, - const char *action_name, - unsigned int count_subaction_paths, - const char **subaction_paths) -{ - GHOST_XrActionSpaceInfo info = { - .action_name = action_name, - .count_subaction_paths = count_subaction_paths, - .subaction_paths = subaction_paths, - }; - - GHOST_XrDestroyActionSpaces(xr->runtime->context, action_set_name, 1, &info); -} - -bool WM_xr_action_binding_create(wmXrData *xr, - const char *action_set_name, - const char *profile_path, - const char *action_name, - unsigned int count_interaction_paths, - const char **interaction_paths) -{ - GHOST_XrActionBindingInfo binding_info = { - .action_name = action_name, - .count_interaction_paths = count_interaction_paths, - .interaction_paths = interaction_paths, - }; - - GHOST_XrActionProfileInfo profile_info = { - .profile_path = profile_path, - .count_bindings = 1, - .bindings = &binding_info, - }; - - return GHOST_XrCreateActionBindings(xr->runtime->context, action_set_name, 1, &profile_info); -} - -void WM_xr_action_binding_destroy(wmXrData *xr, - const char *action_set_name, - const char *profile_path, - const char *action_name, - unsigned int count_interaction_paths, - const char **interaction_paths) -{ - GHOST_XrActionBindingInfo binding_info = { - .action_name = action_name, - .count_interaction_paths = count_interaction_paths, - .interaction_paths = interaction_paths, - }; - - GHOST_XrActionProfileInfo profile_info = { - .profile_path = profile_path, - .count_bindings = 1, - .bindings = &binding_info, - }; - - GHOST_XrDestroyActionBindings(xr->runtime->context, action_set_name, 1, &profile_info); -} - -bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name) -{ - wmXrActionSet *action_set = action_set_find(xr, action_set_name); - if (!action_set) { - return false; - } - - { - /* Unset active modal action (if any). */ - wmXrActionSet *active_action_set = xr->runtime->session_state.active_action_set; - if (active_action_set) { - wmXrAction *active_modal_action = active_action_set->active_modal_action; - if (active_modal_action) { - if (active_modal_action->active_modal_path) { - active_modal_action->active_modal_path = NULL; - } - active_action_set->active_modal_action = NULL; - } - } - } - - xr->runtime->session_state.active_action_set = action_set; - - if (action_set->controller_pose_action) { - wm_xr_session_controller_data_populate(action_set->controller_pose_action, xr); - } - - return true; -} - -bool WM_xr_controller_pose_action_set(wmXrData *xr, - const char *action_set_name, - const char *action_name) -{ - wmXrActionSet *action_set = action_set_find(xr, action_set_name); - if (!action_set) { - return false; - } - - wmXrAction *action = action_find(xr, action_set_name, action_name); - if (!action) { - return false; - } - - action_set->controller_pose_action = action; - - if (action_set == xr->runtime->session_state.active_action_set) { - wm_xr_session_controller_data_populate(action, xr); - } - - return true; -} - -bool WM_xr_action_state_get(const wmXrData *xr, - const char *action_set_name, - const char *action_name, - const char *subaction_path, - wmXrActionState *r_state) -{ - const wmXrAction *action = action_find((wmXrData *)xr, action_set_name, action_name); - if (!action) { - return false; - } - - BLI_assert(action->type == (eXrActionType)r_state->type); - - /* Find the action state corresponding to the subaction path. */ - for (unsigned int i = 0; i < action->count_subaction_paths; ++i) { - if (STREQ(subaction_path, action->subaction_paths[i])) { - switch ((eXrActionType)r_state->type) { - case XR_BOOLEAN_INPUT: - r_state->state_boolean = ((bool *)action->states)[i]; - break; - case XR_FLOAT_INPUT: - r_state->state_float = ((float *)action->states)[i]; - break; - case XR_VECTOR2F_INPUT: - copy_v2_v2(r_state->state_vector2f, ((float(*)[2])action->states)[i]); - break; - case XR_POSE_INPUT: { - const GHOST_XrPose *pose = &((GHOST_XrPose *)action->states)[i]; - copy_v3_v3(r_state->state_pose.position, pose->position); - copy_qt_qt(r_state->state_pose.orientation_quat, pose->orientation_quat); - break; - } - case XR_VIBRATION_OUTPUT: - BLI_assert_unreachable(); - break; - } - return true; - } - } - - return false; -} - -bool WM_xr_haptic_action_apply(wmXrData *xr, - const char *action_set_name, - const char *action_name, - const int64_t *duration, - const float *frequency, - const float *amplitude) -{ - return GHOST_XrApplyHapticAction( - xr->runtime->context, action_set_name, action_name, duration, frequency, amplitude) ? - true : - false; -} - -void WM_xr_haptic_action_stop(wmXrData *xr, const char *action_set_name, const char *action_name) -{ - GHOST_XrStopHapticAction(xr->runtime->context, action_set_name, action_name); -} - -/** \} */ /* XR-Action API */ diff --git a/source/blender/windowmanager/xr/intern/wm_xr_intern.h b/source/blender/windowmanager/xr/intern/wm_xr_intern.h index 6415f96e322..4530aeaa428 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_intern.h +++ b/source/blender/windowmanager/xr/intern/wm_xr_intern.h @@ -122,8 +122,9 @@ typedef struct wmXrAction { /** Previous states, stored to determine XR events. */ void *states_prev; - /** Input threshold for float/vector2f actions. */ - float float_threshold; + /** Input thresholds/regions for each subaction path. */ + float *float_thresholds; + eXrAxisFlag *axis_flags; /** The currently active subaction path (if any) for modal actions. */ char **active_modal_path; -- cgit v1.2.3 From 450593ddf0959681b05686368b80963840f297d0 Mon Sep 17 00:00:00 2001 From: Ankit Meel Date: Thu, 5 Aug 2021 11:00:56 +0530 Subject: Cleanup: Fix Clang braced-scalar-init warning --- source/blender/blenkernel/intern/mesh_remesh_voxel.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc index 63b0403dcea..9f5703a015d 100644 --- a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc +++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc @@ -292,7 +292,7 @@ Mesh *BKE_mesh_remesh_voxel(const Mesh *mesh, void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, Mesh *source) { - BVHTreeFromMesh bvhtree = {{nullptr}}; + BVHTreeFromMesh bvhtree = {nullptr}; BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2); MVert *target_verts = (MVert *)CustomData_get_layer(&target->vdata, CD_MVERT); @@ -330,7 +330,7 @@ void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, Mesh *source) void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, Mesh *source) { - BVHTreeFromMesh bvhtree = {{nullptr}}; + BVHTreeFromMesh bvhtree = {nullptr}; const MPoly *target_polys = (const MPoly *)CustomData_get_layer(&target->pdata, CD_MPOLY); const MVert *target_verts = (const MVert *)CustomData_get_layer(&target->vdata, CD_MVERT); @@ -377,7 +377,7 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, Mesh *source) void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source) { - BVHTreeFromMesh bvhtree = {{nullptr}}; + BVHTreeFromMesh bvhtree = {nullptr}; BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2); int tot_color_layer = CustomData_number_of_layers(&source->vdata, CD_PROP_COLOR); -- cgit v1.2.3 From 2b51124d6a59bedf00397d4ef2fd4442c4fddd22 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 5 Aug 2021 16:44:01 +1000 Subject: Fix T89450: Crash slicing BMEditSelSeq Slicing with indices greater than the length of the sequence would crash. --- source/blender/python/bmesh/bmesh_py_types_select.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/source/blender/python/bmesh/bmesh_py_types_select.c b/source/blender/python/bmesh/bmesh_py_types_select.c index 9bb9815f731..99f17bcec8f 100644 --- a/source/blender/python/bmesh/bmesh_py_types_select.c +++ b/source/blender/python/bmesh/bmesh_py_types_select.c @@ -205,7 +205,6 @@ static PyObject *bpy_bmeditselseq_subscript_slice(BPy_BMEditSelSeq *self, Py_ssize_t stop) { int count = 0; - bool ok; PyObject *list; BMEditSelection *ese; @@ -214,30 +213,22 @@ static PyObject *bpy_bmeditselseq_subscript_slice(BPy_BMEditSelSeq *self, list = PyList_New(0); - ese = self->bm->selected.first; - - ok = (ese != NULL); - - if (UNLIKELY(ok == false)) { - return list; - } - - /* first loop up-until the start */ - for (ok = true; ok; ok = ((ese = ese->next) != NULL)) { + /* First loop up-until the start. */ + for (ese = self->bm->selected.first; ese; ese = ese->next) { if (count == start) { break; } count++; } - /* add items until stop */ - do { + /* Add items until stop. */ + for (; ese; ese = ese->next) { PyList_APPEND(list, BPy_BMElem_CreatePyObject(self->bm, &ese->ele->head)); count++; if (count == stop) { break; } - } while ((ese = ese->next)); + } return list; } -- cgit v1.2.3 From d8582d966fe4ae46c82fcbb69d3d0ca62238ea93 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 5 Aug 2021 16:44:03 +1000 Subject: Fix slicing with negative indices Negative indices that remained negative after adding the sequence length caused incorrect slicing. With the default scene for example: bpy.context.scene.objects[-4:2] Gave a different result to: tuple(bpy.context.scene.objects)[-4:2] Clamp indices above zero so loops that step forward works as intended. --- source/blender/python/bmesh/bmesh_py_types.c | 2 ++ source/blender/python/bmesh/bmesh_py_types_customdata.c | 2 ++ source/blender/python/bmesh/bmesh_py_types_select.c | 2 ++ source/blender/python/intern/bpy_rna.c | 4 ++++ 4 files changed, 10 insertions(+) diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 612446e6d19..e5e601e0eb6 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -3241,9 +3241,11 @@ static PyObject *bpy_bmelemseq_subscript(BPy_BMElemSeq *self, PyObject *key) const Py_ssize_t len = bpy_bmelemseq_length(self); if (start < 0) { start += len; + CLAMP_MIN(start, 0); } if (stop < 0) { stop += len; + CLAMP_MIN(stop, 0); } } diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c index ff06cf43026..0aa92158524 100644 --- a/source/blender/python/bmesh/bmesh_py_types_customdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c @@ -843,9 +843,11 @@ static PyObject *bpy_bmlayercollection_subscript(BPy_BMLayerCollection *self, Py const Py_ssize_t len = bpy_bmlayercollection_length(self); if (start < 0) { start += len; + CLAMP_MIN(start, 0); } if (stop < 0) { stop += len; + CLAMP_MIN(stop, 0); } } diff --git a/source/blender/python/bmesh/bmesh_py_types_select.c b/source/blender/python/bmesh/bmesh_py_types_select.c index 99f17bcec8f..b89822a080c 100644 --- a/source/blender/python/bmesh/bmesh_py_types_select.c +++ b/source/blender/python/bmesh/bmesh_py_types_select.c @@ -273,9 +273,11 @@ static PyObject *bpy_bmeditselseq_subscript(BPy_BMEditSelSeq *self, PyObject *ke const Py_ssize_t len = bpy_bmeditselseq_length(self); if (start < 0) { start += len; + CLAMP_MIN(start, 0); } if (stop < 0) { stop += len; + CLAMP_MIN(stop, 0); } } diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index dff96f74d62..ec2e70ad262 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -2825,9 +2825,11 @@ static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject const Py_ssize_t len = (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop); if (start < 0) { start += len; + CLAMP_MIN(start, 0); } if (stop < 0) { stop += len; + CLAMP_MIN(stop, 0); } } @@ -2955,9 +2957,11 @@ static int pyrna_prop_collection_ass_subscript(BPy_PropertyRNA *self, Py_ssize_t len = (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop); if (start < 0) { start += len; + CLAMP_MIN(start, 0); } if (stop < 0) { stop += len; + CLAMP_MIN(stop, 0); } } -- cgit v1.2.3 From f5acfd9c04697ee046297e1c7b36d0cef9e2440a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 5 Aug 2021 16:48:29 +1000 Subject: Cleanup: remove redundant parenthesis --- intern/cycles/kernel/kernel_path.h | 2 +- source/blender/blenkernel/intern/anim_sys.c | 4 ++-- source/blender/blenkernel/intern/autoexec.c | 2 +- source/blender/blenkernel/intern/fluid.c | 2 +- source/blender/blenkernel/intern/lib_override.c | 8 ++++---- source/blender/blenkernel/intern/pbvh.c | 2 +- source/blender/blenkernel/intern/pointcache.c | 2 +- source/blender/blenkernel/intern/scene.c | 8 ++++---- source/blender/blenkernel/intern/studiolight.c | 24 +++++++++++----------- source/blender/blenkernel/intern/tracking_auto.c | 4 ++-- source/blender/blenkernel/intern/writeffmpeg.c | 2 +- source/blender/blenlib/intern/math_geom.c | 8 ++++---- source/blender/blenloader/intern/versioning_260.c | 2 +- .../blender/blenloader/intern/versioning_legacy.c | 2 +- .../operations/COM_CryptomatteOperation.cc | 4 ++-- .../builder/deg_builder_relations_view_layer.cc | 2 +- .../draw/engines/workbench/workbench_private.h | 2 +- source/blender/draw/intern/draw_manager.c | 2 +- source/blender/draw/intern/draw_manager_exec.c | 4 ++-- source/blender/editors/armature/pose_transform.c | 4 ++-- source/blender/editors/asset/intern/asset_ops.cc | 2 +- source/blender/editors/curve/editcurve_add.c | 4 ++-- source/blender/editors/interface/interface.c | 12 +++++------ .../blender/editors/interface/interface_handlers.c | 2 +- source/blender/editors/interface/interface_icons.c | 2 +- source/blender/editors/screen/screen_ops.c | 2 +- source/blender/editors/sculpt_paint/sculpt_uv.c | 4 ++-- source/blender/editors/space_file/fsmenu.c | 2 +- .../editors/space_sequencer/sequencer_draw.c | 2 +- .../editors/space_sequencer/sequencer_proxy.c | 4 ++-- .../editors/space_sequencer/sequencer_view.c | 2 +- .../editors/space_view3d/view3d_navigate_walk.c | 16 +++++++-------- .../blender/editors/space_view3d/view3d_select.c | 2 +- source/blender/editors/transform/transform.c | 2 +- .../editors/transform/transform_convert_armature.c | 2 +- .../editors/transform/transform_snap_sequencer.c | 2 +- source/blender/editors/uvedit/uvedit_select.c | 2 +- .../freestyle/intern/python/BPy_Freestyle.cpp | 2 +- .../freestyle/intern/view_map/ViewMapBuilder.cpp | 10 ++++----- source/blender/io/avi/intern/avi_endian.c | 2 +- .../composite/nodes/node_composite_switchview.c | 2 +- .../blender/python/bmesh/bmesh_py_types_meshdata.c | 6 +++--- source/blender/python/intern/bpy_gizmo_wrap.c | 2 +- source/blender/python/intern/bpy_utils_units.c | 2 +- source/blender/render/intern/pipeline.c | 2 +- source/blender/render/intern/render_result.c | 2 +- .../blender/windowmanager/intern/wm_gesture_ops.c | 2 +- source/creator/creator_args.c | 4 ++-- 48 files changed, 95 insertions(+), 95 deletions(-) diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index ec577fa20b0..92a097de9e1 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -260,7 +260,7 @@ ccl_device_forceinline bool kernel_path_shader_apply(KernelGlobals *kg, PROFILING_INIT(kg, PROFILING_SHADER_APPLY); #ifdef __SHADOW_TRICKS__ - if ((sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) { + if (sd->object_flag & SD_OBJECT_SHADOW_CATCHER) { if (state->flag & PATH_RAY_TRANSPARENT_BACKGROUND) { state->flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_STORE_SHADOW_INFO); diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index fae75762cde..10a865880f2 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -426,7 +426,7 @@ bool BKE_animsys_rna_path_resolve(PointerRNA *ptr, } /* less than 1.0 evaluates to false, use epsilon to avoid float error */ -#define ANIMSYS_FLOAT_AS_BOOL(value) ((value) > ((1.0f - FLT_EPSILON))) +#define ANIMSYS_FLOAT_AS_BOOL(value) ((value) > (1.0f - FLT_EPSILON)) bool BKE_animsys_read_from_rna_path(PathResolvedRNA *anim_rna, float *r_value) { @@ -2625,7 +2625,7 @@ static void animsys_create_action_track_strip(const AnimData *adt, bAction *action = adt->action; - if ((adt->flag & ADT_NLA_EDIT_ON)) { + if (adt->flag & ADT_NLA_EDIT_ON) { action = adt->tmpact; } diff --git a/source/blender/blenkernel/intern/autoexec.c b/source/blender/blenkernel/intern/autoexec.c index 07b096af941..3aec646b024 100644 --- a/source/blender/blenkernel/intern/autoexec.c +++ b/source/blender/blenkernel/intern/autoexec.c @@ -56,7 +56,7 @@ bool BKE_autoexec_match(const char *path) if (path_cmp->path[0] == '\0') { /* pass */ } - else if ((path_cmp->flag & USER_PATHCMP_GLOB)) { + else if (path_cmp->flag & USER_PATHCMP_GLOB) { if (fnmatch(path_cmp->path, path, fnmatch_flags) == 0) { return true; } diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index 92fd220549a..d33697d551e 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -4153,7 +4153,7 @@ static void BKE_fluid_modifier_process( { const int scene_framenr = (int)DEG_get_ctime(depsgraph); - if ((fmd->type & MOD_FLUID_TYPE_FLOW)) { + if (fmd->type & MOD_FLUID_TYPE_FLOW) { BKE_fluid_modifier_processFlow(fmd, depsgraph, scene, ob, me, scene_framenr); } else if (fmd->type & MOD_FLUID_TYPE_EFFEC) { diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 38687fa47b2..072304566e5 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -571,7 +571,7 @@ static void lib_override_linked_group_tag_recursive(LibOverrideGroupTagData *dat * would use one of those. * NOTE: missing IDs (aka placeholders) are never overridden. */ if (ELEM(GS(to_id->name), ID_OB, ID_GR)) { - if ((to_id->tag & LIB_TAG_MISSING)) { + if (to_id->tag & LIB_TAG_MISSING) { to_id->tag |= missing_tag; } else { @@ -604,7 +604,7 @@ static void lib_override_linked_group_tag(LibOverrideGroupTagData *data) const bool is_resync = data->is_resync; BLI_assert(!data->is_override); - if ((id_root->tag & LIB_TAG_MISSING)) { + if (id_root->tag & LIB_TAG_MISSING) { id_root->tag |= data->missing_tag; } else { @@ -654,7 +654,7 @@ static void lib_override_linked_group_tag(LibOverrideGroupTagData *data) if (instantiating_collection == NULL && instantiating_collection_override_candidate != NULL) { - if ((instantiating_collection_override_candidate->id.tag & LIB_TAG_MISSING)) { + if (instantiating_collection_override_candidate->id.tag & LIB_TAG_MISSING) { instantiating_collection_override_candidate->id.tag |= data->missing_tag; } else { @@ -730,7 +730,7 @@ static void lib_override_overrides_group_tag(LibOverrideGroupTagData *data) BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root)); BLI_assert(data->is_override); - if ((id_root->override_library->reference->tag & LIB_TAG_MISSING)) { + if (id_root->override_library->reference->tag & LIB_TAG_MISSING) { id_root->tag |= data->missing_tag; } else { diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 461ffa7765e..ca1fada8c76 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -1026,7 +1026,7 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata, PBVHNode *node = data->nodes[n]; float(*vnors)[3] = data->vnors; - if ((node->flag & PBVH_UpdateNormals)) { + if (node->flag & PBVH_UpdateNormals) { unsigned int mpoly_prev = UINT_MAX; float fn[3]; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index a6adff35a7f..57225872c7e 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -3369,7 +3369,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker) } /* NOTE: breaking baking should leave calculated frames in cache, not clear it */ - if ((cancel || G.is_break)) { + if (cancel || G.is_break) { break; } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 6d60f5e91b4..9dab276af95 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -2178,7 +2178,7 @@ int BKE_scene_base_iter_next( /* exception: empty scene layer */ while ((*scene)->set) { (*scene) = (*scene)->set; - ViewLayer *view_layer_set = BKE_view_layer_default_render((*scene)); + ViewLayer *view_layer_set = BKE_view_layer_default_render(*scene); if (view_layer_set->object_bases.first) { *base = view_layer_set->object_bases.first; *ob = (*base)->object; @@ -2199,7 +2199,7 @@ int BKE_scene_base_iter_next( /* (*scene) is finished, now do the set */ while ((*scene)->set) { (*scene) = (*scene)->set; - ViewLayer *view_layer_set = BKE_view_layer_default_render((*scene)); + ViewLayer *view_layer_set = BKE_view_layer_default_render(*scene); if (view_layer_set->object_bases.first) { *base = view_layer_set->object_bases.first; *ob = (*base)->object; @@ -2898,7 +2898,7 @@ Base *_setlooper_base_step(Scene **sce_iter, ViewLayer *view_layer, Base *base) next_set: /* Reached the end, get the next base in the set. */ while ((*sce_iter = (*sce_iter)->set)) { - ViewLayer *view_layer_set = BKE_view_layer_default_render((*sce_iter)); + ViewLayer *view_layer_set = BKE_view_layer_default_render(*sce_iter); base = (Base *)view_layer_set->object_bases.first; if (base) { @@ -3118,7 +3118,7 @@ bool BKE_scene_multiview_is_render_view_active(const RenderData *rd, const Scene return false; } - if ((srv->viewflag & SCE_VIEW_DISABLE)) { + if (srv->viewflag & SCE_VIEW_DISABLE) { return false; } diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c index dc5162f201e..95436372a65 100644 --- a/source/blender/blenkernel/intern/studiolight.c +++ b/source/blender/blenkernel/intern/studiolight.c @@ -475,7 +475,7 @@ static void studiolight_load_equirect_image(StudioLight *sl) NULL, (failed || (specular_ibuf == NULL)) ? magenta : black, 1, 1, 4); } - if ((sl->flag & STUDIOLIGHT_TYPE_MATCAP)) { + if (sl->flag & STUDIOLIGHT_TYPE_MATCAP) { sl->matcap_diffuse.ibuf = diffuse_ibuf; sl->matcap_specular.ibuf = specular_ibuf; if (specular_ibuf != NULL) { @@ -1192,7 +1192,7 @@ static void studiolight_add_files_from_datafolder(const int folder_id, uint totfile = BLI_filelist_dir_contents(folder, &dir); int i; for (i = 0; i < totfile; i++) { - if ((dir[i].type & S_IFREG)) { + if (dir[i].type & S_IFREG) { studiolight_add_file(dir[i].path, flag); } } @@ -1473,7 +1473,7 @@ struct StudioLight *BKE_studiolight_find_default(int flag) } LISTBASE_FOREACH (StudioLight *, sl, &studiolights) { - if ((sl->flag & flag)) { + if (sl->flag & flag) { return sl; } } @@ -1484,7 +1484,7 @@ struct StudioLight *BKE_studiolight_find(const char *name, int flag) { LISTBASE_FOREACH (StudioLight *, sl, &studiolights) { if (STREQLEN(sl->name, name, FILE_MAXFILE)) { - if ((sl->flag & flag)) { + if (sl->flag & flag) { return sl; } @@ -1542,32 +1542,32 @@ void BKE_studiolight_ensure_flag(StudioLight *sl, int flag) return; } - if ((flag & STUDIOLIGHT_EXTERNAL_IMAGE_LOADED)) { + if (flag & STUDIOLIGHT_EXTERNAL_IMAGE_LOADED) { studiolight_load_equirect_image(sl); } - if ((flag & STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED)) { + if (flag & STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED) { studiolight_calculate_radiance_cubemap_buffers(sl); } - if ((flag & STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED)) { + if (flag & STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED) { if (!studiolight_load_spherical_harmonics_coefficients(sl)) { studiolight_calculate_diffuse_light(sl); } } - if ((flag & STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE)) { + if (flag & STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE) { studiolight_create_equirect_radiance_gputexture(sl); } - if ((flag & STUDIOLIGHT_EQUIRECT_IRRADIANCE_GPUTEXTURE)) { + if (flag & STUDIOLIGHT_EQUIRECT_IRRADIANCE_GPUTEXTURE) { studiolight_create_equirect_irradiance_gputexture(sl); } - if ((flag & STUDIOLIGHT_EQUIRECT_IRRADIANCE_IMAGE_CALCULATED)) { + if (flag & STUDIOLIGHT_EQUIRECT_IRRADIANCE_IMAGE_CALCULATED) { if (!studiolight_load_irradiance_equirect_image(sl)) { studiolight_calculate_irradiance_equirect_image(sl); } } - if ((flag & STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE)) { + if (flag & STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE) { studiolight_create_matcap_diffuse_gputexture(sl); } - if ((flag & STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE)) { + if (flag & STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE) { studiolight_create_matcap_specular_gputexture(sl); } } diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c index f107fc4d6bc..92ff0911cf3 100644 --- a/source/blender/blenkernel/intern/tracking_auto.c +++ b/source/blender/blenkernel/intern/tracking_auto.c @@ -322,7 +322,7 @@ static bool tracking_check_marker_margin(const libmv_Marker *libmv_marker, static bool autotrack_is_marker_usable(const MovieTrackingMarker *marker) { - if ((marker->flag & MARKER_DISABLED)) { + if (marker->flag & MARKER_DISABLED) { return false; } return true; @@ -797,7 +797,7 @@ void BKE_autotrack_context_finish(AutoTrackContext *context) clip, context->start_scene_frame); LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) { - if ((plane_track->flag & PLANE_TRACK_AUTOKEY)) { + if (plane_track->flag & PLANE_TRACK_AUTOKEY) { continue; } for (int track_index = 0; track_index < context->num_all_tracks; track_index++) { diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 9b3103a638b..32057709c38 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -741,7 +741,7 @@ static AVStream *alloc_video_stream(FFMpegContext *context, } } - if ((of->oformat->flags & AVFMT_GLOBALHEADER)) { + if (of->oformat->flags & AVFMT_GLOBALHEADER) { PRINT("Using global header\n"); c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; } diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 823e72a91e5..8afb6b5a2be 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -1787,7 +1787,7 @@ bool isect_ray_tri_v3(const float ray_origin[3], } *r_lambda = f * dot_v3v3(e2, q); - if ((*r_lambda < 0.0f)) { + if (*r_lambda < 0.0f) { return false; } @@ -1864,7 +1864,7 @@ bool isect_ray_tri_epsilon_v3(const float ray_origin[3], } *r_lambda = f * dot_v3v3(e2, q); - if ((*r_lambda < 0.0f)) { + if (*r_lambda < 0.0f) { return false; } @@ -2024,7 +2024,7 @@ bool isect_ray_tri_threshold_v3(const float ray_origin[3], cross_v3_v3v3(q, s, e1); *r_lambda = f * dot_v3v3(e2, q); - if ((*r_lambda < 0.0f)) { + if (*r_lambda < 0.0f) { return false; } @@ -3325,7 +3325,7 @@ bool isect_ray_aabb_v3_simple(const float orig[3], t[5] = (double)(bb_max[2] - orig[2]) * invdirz; hit_dist[0] = (float)fmax(fmax(fmin(t[0], t[1]), fmin(t[2], t[3])), fmin(t[4], t[5])); hit_dist[1] = (float)fmin(fmin(fmax(t[0], t[1]), fmax(t[2], t[3])), fmax(t[4], t[5])); - if ((hit_dist[1] < 0.0f || hit_dist[0] > hit_dist[1])) { + if ((hit_dist[1] < 0.0f) || (hit_dist[0] > hit_dist[1])) { return false; } diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c index 858f5d85a90..7c644fa3b55 100644 --- a/source/blender/blenloader/intern/versioning_260.c +++ b/source/blender/blenloader/intern/versioning_260.c @@ -2390,7 +2390,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain) for (md = ob->modifiers.first; md; md = md->next) { if (md->type == eModifierType_Triangulate) { TriangulateModifierData *tmd = (TriangulateModifierData *)md; - if ((tmd->flag & MOD_TRIANGULATE_BEAUTY)) { + if (tmd->flag & MOD_TRIANGULATE_BEAUTY) { tmd->quad_method = MOD_TRIANGULATE_QUAD_BEAUTY; tmd->ngon_method = MOD_TRIANGULATE_NGON_BEAUTY; } diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index 95cfc9975d7..81371e1c1ed 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -1335,7 +1335,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) ME_OPT_EDGES = (1 << 8), }; - if ((me->flag & ME_SUBSURF)) { + if (me->flag & ME_SUBSURF) { SubsurfModifierData *smd = (SubsurfModifierData *)BKE_modifier_new( eModifierType_Subsurf); diff --git a/source/blender/compositor/operations/COM_CryptomatteOperation.cc b/source/blender/compositor/operations/COM_CryptomatteOperation.cc index 52ae1d6d5b5..1a86fadad76 100644 --- a/source/blender/compositor/operations/COM_CryptomatteOperation.cc +++ b/source/blender/compositor/operations/COM_CryptomatteOperation.cc @@ -57,8 +57,8 @@ void CryptomatteOperation::executePixel(float output[4], int x, int y, void *dat ::memcpy(&m3hash, &input[0], sizeof(uint32_t)); /* Since the red channel is likely to be out of display range, * setting green and blue gives more meaningful images. */ - output[1] = ((float)((m3hash << 8)) / (float)UINT32_MAX); - output[2] = ((float)((m3hash << 16)) / (float)UINT32_MAX); + output[1] = ((float)(m3hash << 8) / (float)UINT32_MAX); + output[2] = ((float)(m3hash << 16) / (float)UINT32_MAX); } for (float hash : m_objectIndex) { if (input[0] == hash) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc index 6527f165552..c37fb1b83a4 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc @@ -65,7 +65,7 @@ void DepsgraphRelationBuilder::build_layer_collections(ListBase *lb) COLLECTION_HIDE_RENDER; for (LayerCollection *lc = (LayerCollection *)lb->first; lc; lc = lc->next) { - if ((lc->collection->flag & visibility_flag)) { + if (lc->collection->flag & visibility_flag) { continue; } if ((lc->flag & LAYER_COLLECTION_EXCLUDE) == 0) { diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 453ef9c7f8e..e17bd7d9956 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -399,7 +399,7 @@ typedef struct WORKBENCH_ViewLayerData { /* inline helper functions */ BLI_INLINE bool workbench_is_specular_highlight_enabled(WORKBENCH_PrivateData *wpd) { - if ((wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT)) { + if (wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) { if (STUDIOLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) { return (wpd->studio_light->flag & STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS) != 0; } diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index a8cbe7b18b5..11e2856147f 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -512,7 +512,7 @@ static void drw_context_state_init(void) if (DST.draw_ctx.object_mode & OB_MODE_POSE) { DST.draw_ctx.object_pose = DST.draw_ctx.obact; } - else if ((DST.draw_ctx.object_mode & OB_MODE_ALL_WEIGHT_PAINT)) { + else if (DST.draw_ctx.object_mode & OB_MODE_ALL_WEIGHT_PAINT) { DST.draw_ctx.object_pose = BKE_object_pose_armature_get(DST.draw_ctx.obact); } else { diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 7f7696d485c..22356a3c57b 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -283,11 +283,11 @@ void DRW_state_reset_ex(DRWState state) static void drw_state_validate(void) { /* Cannot write to stencil buffer without stencil test. */ - if ((DST.state & DRW_STATE_WRITE_STENCIL_ENABLED)) { + if (DST.state & DRW_STATE_WRITE_STENCIL_ENABLED) { BLI_assert(DST.state & DRW_STATE_STENCIL_TEST_ENABLED); } /* Cannot write to depth buffer without depth test. */ - if ((DST.state & DRW_STATE_WRITE_DEPTH)) { + if (DST.state & DRW_STATE_WRITE_DEPTH) { BLI_assert(DST.state & DRW_STATE_DEPTH_TEST_ENABLED); } } diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index 1118e84ef4f..3798ca308ed 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -908,7 +908,7 @@ static int pose_paste_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); /* Recalculate paths if any of the bones have paths... */ - if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) { + if (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) { ED_pose_recalculate_paths(C, scene, ob, POSE_PATH_CALC_RANGE_FULL); } @@ -1219,7 +1219,7 @@ static int pose_clear_transform_generic_exec(bContext *C, ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA); /* now recalculate paths */ - if ((ob_iter->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) { + if (ob_iter->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) { ED_pose_recalculate_paths(C, scene, ob_iter, POSE_PATH_CALC_RANGE_FULL); } diff --git a/source/blender/editors/asset/intern/asset_ops.cc b/source/blender/editors/asset/intern/asset_ops.cc index f18cf9712db..579803f7ff7 100644 --- a/source/blender/editors/asset/intern/asset_ops.cc +++ b/source/blender/editors/asset/intern/asset_ops.cc @@ -110,7 +110,7 @@ void AssetMarkHelper::reportResults(ReportList &reports) const { /* User feedback on failure. */ if (!wasSuccessful()) { - if ((stats.tot_already_asset > 0)) { + if (stats.tot_already_asset > 0) { BKE_report(&reports, RPT_ERROR, "Selected data-blocks are already assets (or do not support use as assets)"); diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c index 2be55accd3a..d1fe162fc4a 100644 --- a/source/blender/editors/curve/editcurve_add.c +++ b/source/blender/editors/curve/editcurve_add.c @@ -431,7 +431,7 @@ Nurb *ED_curve_add_nurbs_primitive( if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0) { ed_editnurb_spin(umat, NULL, obedit, tmp_vec, tmp_cent); } - else if ((U.flag & USER_ADD_VIEWALIGNED)) { + else if (U.flag & USER_ADD_VIEWALIGNED) { ed_editnurb_spin(viewmat, NULL, obedit, zvec, mat[3]); } else { @@ -466,7 +466,7 @@ Nurb *ED_curve_add_nurbs_primitive( if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0) { ed_editnurb_spin(umat, NULL, obedit, tmp_vec, tmp_cent); } - else if ((U.flag & USER_ADD_VIEWALIGNED)) { + else if (U.flag & USER_ADD_VIEWALIGNED) { ed_editnurb_spin(viewmat, NULL, obedit, zvec, mat[3]); } else { diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index d3a3df98d99..fd75be5b847 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -6173,7 +6173,7 @@ int UI_but_return_value_get(uiBut *but) void UI_but_drag_set_id(uiBut *but, ID *id) { but->dragtype = WM_DRAG_ID; - if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) { + if (but->dragflag & UI_BUT_DRAGPOIN_FREE) { WM_drag_data_free(but->dragtype, but->dragpoin); but->dragflag &= ~UI_BUT_DRAGPOIN_FREE; } @@ -6200,7 +6200,7 @@ void UI_but_drag_set_asset(uiBut *but, but->dragtype = WM_DRAG_ASSET; ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesn't draw in button */ - if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) { + if (but->dragflag & UI_BUT_DRAGPOIN_FREE) { WM_drag_data_free(but->dragtype, but->dragpoin); } but->dragpoin = asset_drag; @@ -6212,7 +6212,7 @@ void UI_but_drag_set_asset(uiBut *but, void UI_but_drag_set_rna(uiBut *but, PointerRNA *ptr) { but->dragtype = WM_DRAG_RNA; - if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) { + if (but->dragflag & UI_BUT_DRAGPOIN_FREE) { WM_drag_data_free(but->dragtype, but->dragpoin); but->dragflag &= ~UI_BUT_DRAGPOIN_FREE; } @@ -6222,7 +6222,7 @@ void UI_but_drag_set_rna(uiBut *but, PointerRNA *ptr) void UI_but_drag_set_path(uiBut *but, const char *path, const bool use_free) { but->dragtype = WM_DRAG_PATH; - if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) { + if (but->dragflag & UI_BUT_DRAGPOIN_FREE) { WM_drag_data_free(but->dragtype, but->dragpoin); but->dragflag &= ~UI_BUT_DRAGPOIN_FREE; } @@ -6235,7 +6235,7 @@ void UI_but_drag_set_path(uiBut *but, const char *path, const bool use_free) void UI_but_drag_set_name(uiBut *but, const char *name) { but->dragtype = WM_DRAG_NAME; - if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) { + if (but->dragflag & UI_BUT_DRAGPOIN_FREE) { WM_drag_data_free(but->dragtype, but->dragpoin); but->dragflag &= ~UI_BUT_DRAGPOIN_FREE; } @@ -6253,7 +6253,7 @@ void UI_but_drag_set_image( { but->dragtype = WM_DRAG_PATH; ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesn't draw in button */ - if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) { + if (but->dragflag & UI_BUT_DRAGPOIN_FREE) { WM_drag_data_free(but->dragtype, but->dragpoin); but->dragflag &= ~UI_BUT_DRAGPOIN_FREE; } diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index bfc03a95949..d920ebbe11a 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -6779,7 +6779,7 @@ static bool ui_numedit_but_HSVCIRCLE(uiBut *but, ui_color_picker_hsv_to_rgb(hsv, rgb); - if ((cpicker->use_luminosity_lock)) { + if (cpicker->use_luminosity_lock) { if (!is_zero_v3(rgb)) { normalize_v3_length(rgb, cpicker->luminosity_lock_value); } diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 6755eded05c..2d59bfb92c8 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -1014,7 +1014,7 @@ static void init_iconfile_list(struct ListBase *list) int index = 1; for (int i = 0; i < totfile; i++) { - if ((dir[i].type & S_IFREG)) { + if (dir[i].type & S_IFREG) { const char *filename = dir[i].relname; if (BLI_path_extension_check(filename, ".png")) { diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 0bc2a224a4b..d8cef889a40 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -2906,7 +2906,7 @@ static void areas_do_frame_follow(bContext *C, bool middle) LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { /* do follow here if editor type supports it */ - if ((screen_ctx->redraws_flag & TIME_FOLLOW)) { + if (screen_ctx->redraws_flag & TIME_FOLLOW) { if ((region->regiontype == RGN_TYPE_WINDOW && ELEM(area->spacetype, SPACE_SEQ, SPACE_GRAPH, SPACE_ACTION, SPACE_NLA)) || (area->spacetype == SPACE_CLIP && region->regiontype == RGN_TYPE_PREVIEW)) { diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c index 771e0e1e47b..e5ca5e4defd 100644 --- a/source/blender/editors/sculpt_paint/sculpt_uv.c +++ b/source/blender/editors/sculpt_paint/sculpt_uv.c @@ -190,7 +190,7 @@ static void HC_relaxation_iteration_uv(BMEditMesh *em, /* This is supposed to happen only if "Pin Edges" is on, * since we have initialization on stroke start. * If ever uv brushes get their own mode we should check for toolsettings option too. */ - if ((sculptdata->uv[i].flag & MARK_BOUNDARY)) { + if (sculptdata->uv[i].flag & MARK_BOUNDARY) { continue; } @@ -268,7 +268,7 @@ static void laplacian_relaxation_iteration_uv(BMEditMesh *em, /* This is supposed to happen only if "Pin Edges" is on, * since we have initialization on stroke start. * If ever uv brushes get their own mode we should check for toolsettings option too. */ - if ((sculptdata->uv[i].flag & MARK_BOUNDARY)) { + if (sculptdata->uv[i].flag & MARK_BOUNDARY) { continue; } diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index 2d1151c8f4d..776bb0b3bb7 100644 --- a/source/blender/editors/space_file/fsmenu.c +++ b/source/blender/editors/space_file/fsmenu.c @@ -969,7 +969,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) BLI_join_dirfile(name, sizeof(name), xdg_runtime_dir, "gvfs/"); const uint dir_len = BLI_filelist_dir_contents(name, &dir); for (uint i = 0; i < dir_len; i++) { - if ((dir[i].type & S_IFDIR)) { + if (dir[i].type & S_IFDIR) { const char *dirname = dir[i].relname; if (dirname[0] != '.') { /* Dir names contain a lot of unwanted text. diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 3f8dea8b533..0472e1264ce 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -1139,7 +1139,7 @@ static void draw_seq_strip(const bContext *C, } /* Draw strip offsets when flag is enabled or during "solo preview". */ - if ((sseq->flag & SEQ_SHOW_STRIP_OVERLAY)) { + if (sseq->flag & SEQ_SHOW_STRIP_OVERLAY) { if (!is_single_image && (seq->startofs || seq->endofs) && pixely > 0) { if ((sseq->draw_flag & SEQ_DRAW_OFFSET_EXT) || (seq == special_seq_update)) { draw_sequence_extensions_overlay(scene, seq, pos, pixely); diff --git a/source/blender/editors/space_sequencer/sequencer_proxy.c b/source/blender/editors/space_sequencer/sequencer_proxy.c index 2dcc2d389d9..16d14b5fa72 100644 --- a/source/blender/editors/space_sequencer/sequencer_proxy.c +++ b/source/blender/editors/space_sequencer/sequencer_proxy.c @@ -131,7 +131,7 @@ static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op)) file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list"); LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) { - if ((seq->flag & SELECT)) { + if (seq->flag & SELECT) { ListBase queue = {NULL, NULL}; LinkData *link; short stop = 0, do_update; @@ -197,7 +197,7 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op) } LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) { - if ((seq->flag & SELECT)) { + if (seq->flag & SELECT) { if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE)) { SEQ_proxy_set(seq, turnon); if (seq->strip->proxy == NULL) { diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index c5385e24d2c..a0a9cdd96b1 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -292,7 +292,7 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *op) } for (seq = ed->seqbasep->first; seq; seq = seq->next) { - if ((seq->flag & SELECT)) { + if (seq->flag & SELECT) { xmin = min_ii(xmin, seq->startdisp); xmax = max_ii(xmax, seq->enddisp); diff --git a/source/blender/editors/space_view3d/view3d_navigate_walk.c b/source/blender/editors/space_view3d/view3d_navigate_walk.c index 09936b41a74..1ac241013ed 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_walk.c +++ b/source/blender/editors/space_view3d/view3d_navigate_walk.c @@ -548,7 +548,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->teleport.duration = U.walk_navigation.teleport_time; walk->mouse_speed = U.walk_navigation.mouse_speed; - if ((U.walk_navigation.flag & USER_WALK_GRAVITY)) { + if (U.walk_navigation.flag & USER_WALK_GRAVITY) { walk_navigation_mode_set(walk, WALK_MODE_GRAVITY); } else { @@ -563,7 +563,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->gravity_state = WALK_GRAVITY_STATE_OFF; - if ((walk->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY)) { + if (walk->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { walk->gravity = fabsf(walk->scene->physics_settings.gravity[2]); } else { @@ -1199,11 +1199,11 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) direction = 0; - if ((walk->active_directions & WALK_BIT_FORWARD)) { + if (walk->active_directions & WALK_BIT_FORWARD) { direction += 1; } - if ((walk->active_directions & WALK_BIT_BACKWARD)) { + if (walk->active_directions & WALK_BIT_BACKWARD) { direction -= 1; } @@ -1223,11 +1223,11 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) direction = 0; - if ((walk->active_directions & WALK_BIT_LEFT)) { + if (walk->active_directions & WALK_BIT_LEFT) { direction += 1; } - if ((walk->active_directions & WALK_BIT_RIGHT)) { + if (walk->active_directions & WALK_BIT_RIGHT) { direction -= 1; } @@ -1245,11 +1245,11 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) direction = 0; - if ((walk->active_directions & WALK_BIT_UP)) { + if (walk->active_directions & WALK_BIT_UP) { direction -= 1; } - if ((walk->active_directions & WALK_BIT_DOWN)) { + if (walk->active_directions & WALK_BIT_DOWN) { direction = 1; } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 5ec3e9cae5a..2ce5684e874 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -2156,7 +2156,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, for (a = 0; a < hits; a++) { if (has_bones) { /* skip non-bone objects */ - if ((buffer[4 * a + 3] & 0xFFFF0000)) { + if (buffer[4 * a + 3] & 0xFFFF0000) { if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & 0xFFFF)) { basact = base; } diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index efcf7d587e1..96b84bd2a35 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1828,7 +1828,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { - if ((((Mesh *)(tc->obedit->data))->flag & ME_AUTOSMOOTH)) { + if (((Mesh *)(tc->obedit->data))->flag & ME_AUTOSMOOTH) { BMEditMesh *em = NULL; /* BKE_editmesh_from_object(t->obedit); */ bool do_skip = false; diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c index 1f1b1f8db97..f56d60b7376 100644 --- a/source/blender/editors/transform/transform_convert_armature.c +++ b/source/blender/editors/transform/transform_convert_armature.c @@ -1515,7 +1515,7 @@ int transform_convert_pose_transflags_update(Object *ob, for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { bone = pchan->bone; if (PBONE_VISIBLE(arm, bone)) { - if ((bone->flag & BONE_SELECTED)) { + if (bone->flag & BONE_SELECTED) { bone->flag |= BONE_TRANSFORM; } else { diff --git a/source/blender/editors/transform/transform_snap_sequencer.c b/source/blender/editors/transform/transform_snap_sequencer.c index a1f396eb503..6e926f36fba 100644 --- a/source/blender/editors/transform/transform_snap_sequencer.c +++ b/source/blender/editors/transform/transform_snap_sequencer.c @@ -141,7 +141,7 @@ static SeqCollection *query_snap_targets(const TransInfo *t, SeqCollection *snap const short snap_flag = SEQ_tool_settings_snap_flag_get(t->scene); SeqCollection *snap_targets = SEQ_collection_create(__func__); LISTBASE_FOREACH (Sequence *, seq, seqbase) { - if ((seq->flag & SELECT)) { + if (seq->flag & SELECT) { continue; /* Selected are being transformed. */ } if ((seq->flag & SEQ_MUTE) && (snap_flag & SEQ_SNAP_IGNORE_MUTED)) { diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c index 4c597d80534..5a82cd31112 100644 --- a/source/blender/editors/uvedit/uvedit_select.c +++ b/source/blender/editors/uvedit/uvedit_select.c @@ -3912,7 +3912,7 @@ BMLoop **ED_uvedit_selected_verts(Scene *scene, BMesh *bm, int len_max, int *r_v BM_ITER_ELEM (l_iter, &liter, f, BM_LOOPS_OF_FACE) { if (!BM_elem_flag_test(l_iter, BM_ELEM_TAG)) { const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset); - if ((luv->flag & MLOOPUV_VERTSEL)) { + if (luv->flag & MLOOPUV_VERTSEL) { BM_elem_flag_enable(l_iter->v, BM_ELEM_TAG); verts[verts_len++] = l_iter; diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp index db85292c6c0..2d0021a1fe8 100644 --- a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp +++ b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp @@ -266,7 +266,7 @@ static PyObject *Freestyle_evaluateCurveMappingF(PyObject * /*self*/, PyObject * cumap = (CurveMapping *)py_srna->ptr.data; BKE_curvemapping_init(cumap); /* disable extrapolation if enabled */ - if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE)) { + if (cumap->flag & CUMA_EXTEND_EXTRAPOLATE) { cumap->flag &= ~CUMA_EXTEND_EXTRAPOLATE; BKE_curvemapping_changed(cumap, false); } diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp index afb23690a84..b1aea8bf6cf 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp @@ -527,7 +527,7 @@ static void computeCumulativeVisibility(ViewMap *ioViewMap, fe = fe->nextEdge(); continue; } - if ((maxCard < qiMajority)) { + if (maxCard < qiMajority) { // ARB: change &wFace to wFace and use reference in called function tmpQI = computeVisibility( ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders); @@ -725,7 +725,7 @@ static void computeDetailedVisibility(ViewMap *ioViewMap, fe = fe->nextEdge(); continue; } - if ((maxCard < qiMajority)) { + if (maxCard < qiMajority) { // ARB: change &wFace to wFace and use reference in called function tmpQI = computeVisibility( ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders); @@ -891,7 +891,7 @@ static void computeFastVisibility(ViewMap *ioViewMap, G &grid, real epsilon) continue; } if (even_test) { - if ((maxCard < qiMajority)) { + if (maxCard < qiMajority) { // ARB: change &wFace to wFace and use reference in called function tmpQI = computeVisibility( ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders); @@ -1607,7 +1607,7 @@ void ViewMapBuilder::ComputeRayCastingVisibility(ViewMap *ioViewMap, real epsilo memset(qiClasses, 0, 256 * sizeof(*qiClasses)); set occluders; do { - if ((maxCard < qiMajority)) { + if (maxCard < qiMajority) { tmpQI = ComputeRayCastingVisibility(fe, _Grid, epsilon, occluders, &aFace, timestamp++); #if LOGGING @@ -1763,7 +1763,7 @@ void ViewMapBuilder::ComputeFastRayCastingVisibility(ViewMap *ioViewMap, real ep fe = (*ve)->fedgeA(); do { if (even_test) { - if ((maxCard < qiMajority)) { + if (maxCard < qiMajority) { tmpQI = ComputeRayCastingVisibility(fe, _Grid, epsilon, occluders, &aFace, timestamp++); // ARB: This is an error condition, not an alert condition. diff --git a/source/blender/io/avi/intern/avi_endian.c b/source/blender/io/avi/intern/avi_endian.c index 146206cd917..36cee7bcadc 100644 --- a/source/blender/io/avi/intern/avi_endian.c +++ b/source/blender/io/avi/intern/avi_endian.c @@ -42,7 +42,7 @@ static void invert(int *val) { int tval = *val; - *val = ((tval >> 24)) | ((tval << 8) & 0x00ff0000) | ((tval >> 8) & 0x0000ff00) | ((tval << 24)); + *val = (tval >> 24) | ((tval << 8) & 0x00ff0000) | ((tval >> 8) & 0x0000ff00) | (tval << 24); } static void sinvert(short int *val) diff --git a/source/blender/nodes/composite/nodes/node_composite_switchview.c b/source/blender/nodes/composite/nodes/node_composite_switchview.c index 3ffad8216de..ec5c79cc087 100644 --- a/source/blender/nodes/composite/nodes/node_composite_switchview.c +++ b/source/blender/nodes/composite/nodes/node_composite_switchview.c @@ -132,7 +132,7 @@ static void init_switch_view(const bContext *C, PointerRNA *ptr) for (nr = 0, srv = rd->views.first; srv; srv = srv->next, nr++) { sock = ntreeCompositSwitchViewAddSocket(ntree, node, srv->name); - if ((srv->viewflag & SCE_VIEW_DISABLE)) { + if (srv->viewflag & SCE_VIEW_DISABLE) { sock->flag |= SOCK_HIDDEN; } } diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c index 8f4e07c30d3..d0c745e6a1d 100644 --- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c @@ -443,7 +443,7 @@ static int bpy_bmdeformvert_ass_subscript(BPy_BMDeformVert *self, PyObject *key, } if (value) { - /* dvert[group_index] = 0.5 */ + /* Handle `dvert[group_index] = 0.5`. */ if (i < 0) { PyErr_SetString(PyExc_KeyError, "BMDeformVert[key] = x: " @@ -453,7 +453,7 @@ static int bpy_bmdeformvert_ass_subscript(BPy_BMDeformVert *self, PyObject *key, MDeformWeight *dw = BKE_defvert_ensure_index(self->data, i); const float f = PyFloat_AsDouble(value); - if (f == -1 && PyErr_Occurred()) { // parsed key not a number + if (f == -1 && PyErr_Occurred()) { /* Parsed key not a number. */ PyErr_SetString(PyExc_TypeError, "BMDeformVert[key] = x: " "assigned value not a number"); @@ -463,7 +463,7 @@ static int bpy_bmdeformvert_ass_subscript(BPy_BMDeformVert *self, PyObject *key, dw->weight = clamp_f(f, 0.0f, 1.0f); } else { - /* del dvert[group_index] */ + /* Handle `del dvert[group_index]`. */ MDeformWeight *dw = BKE_defvert_find_index(self->data, i); if (dw == NULL) { diff --git a/source/blender/python/intern/bpy_gizmo_wrap.c b/source/blender/python/intern/bpy_gizmo_wrap.c index 42e0c7d0003..a05ec6b7000 100644 --- a/source/blender/python/intern/bpy_gizmo_wrap.c +++ b/source/blender/python/intern/bpy_gizmo_wrap.c @@ -79,7 +79,7 @@ static bool bpy_gizmotype_target_property_def(wmGizmoType *gzt, PyObject *item) goto fail; } - if ((params.array_length < 1 || params.array_length > RNA_MAX_ARRAY_LENGTH)) { + if ((params.array_length < 1) || (params.array_length > RNA_MAX_ARRAY_LENGTH)) { PyErr_SetString(PyExc_ValueError, "'array_length' out of range"); goto fail; } diff --git a/source/blender/python/intern/bpy_utils_units.c b/source/blender/python/intern/bpy_utils_units.c index aa8cf8f2a9f..62f5a17c4dd 100644 --- a/source/blender/python/intern/bpy_utils_units.c +++ b/source/blender/python/intern/bpy_utils_units.c @@ -114,7 +114,7 @@ static PyObject *py_structseq_from_strings(PyTypeObject *py_type, BLI_assert(py_struct_seq != NULL); for (str_iter = str_items; *str_iter; str_iter++) { - PyStructSequence_SET_ITEM(py_struct_seq, pos++, PyUnicode_FromString((*str_iter))); + PyStructSequence_SET_ITEM(py_struct_seq, pos++, PyUnicode_FromString(*str_iter)); } return py_struct_seq; diff --git a/source/blender/render/intern/pipeline.c b/source/blender/render/intern/pipeline.c index 333ee9ecd33..479ad9209f0 100644 --- a/source/blender/render/intern/pipeline.c +++ b/source/blender/render/intern/pipeline.c @@ -2524,7 +2524,7 @@ void RE_RenderAnim(Render *re, if (G.is_break == true) { /* remove touched file */ if (is_movie == false && do_write_file) { - if ((rd.mode & R_TOUCH)) { + if (rd.mode & R_TOUCH) { if (!is_multiview_name) { if ((BLI_file_size(name) == 0)) { /* BLI_exists(name) is implicit */ diff --git a/source/blender/render/intern/render_result.c b/source/blender/render/intern/render_result.c index 693cddbebbe..091f5964291 100644 --- a/source/blender/render/intern/render_result.c +++ b/source/blender/render/intern/render_result.c @@ -784,7 +784,7 @@ void render_result_views_new(RenderResult *rr, const RenderData *rd) render_result_views_free(rr); /* check renderdata for amount of views */ - if ((rd->scemode & R_MULTIVIEW)) { + if (rd->scemode & R_MULTIVIEW) { for (srv = rd->views.first; srv; srv = srv->next) { if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) { continue; diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.c b/source/blender/windowmanager/intern/wm_gesture_ops.c index 92ca0b87527..1c736647084 100644 --- a/source/blender/windowmanager/intern/wm_gesture_ops.c +++ b/source/blender/windowmanager/intern/wm_gesture_ops.c @@ -585,7 +585,7 @@ void wm_tweakevent_test(bContext *C, const wmEvent *event, int action) } else { /* no tweaks if event was handled */ - if ((action & WM_HANDLER_BREAK)) { + if (action & WM_HANDLER_BREAK) { WM_gesture_end(win, win->tweak); } else { diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index c75174dfff0..0f450624691 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -121,7 +121,7 @@ static bool parse_int_relative(const char *str, *r_err_msg = msg; return false; } - if ((errno == ERANGE) || ((value < INT_MIN || value > INT_MAX))) { + if ((errno == ERANGE) || ((value < INT_MIN) || (value > INT_MAX))) { static const char *msg = "exceeds range"; *r_err_msg = msg; return false; @@ -225,7 +225,7 @@ static bool parse_int_strict_range(const char *str, *r_err_msg = msg; return false; } - if ((errno == ERANGE) || ((value < min || value > max))) { + if ((errno == ERANGE) || ((value < min) || (value > max))) { static const char *msg = "exceeds range"; *r_err_msg = msg; return false; -- cgit v1.2.3 From 647a8bff06bfabeafa01333d4b9d8d8b8ae1c569 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 5 Aug 2021 18:17:56 +1000 Subject: Fix T90256: faces are flat shaded in edit mode with auto smooth Regression in 39b2a7bb7e815e051348bf5c5ec777d091324164. --- source/blender/bmesh/intern/bmesh_mesh_normals.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_mesh_normals.c b/source/blender/bmesh/intern/bmesh_mesh_normals.c index 6504a2de116..8eda38046a1 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_normals.c +++ b/source/blender/bmesh/intern/bmesh_mesh_normals.c @@ -50,8 +50,6 @@ static void bm_edge_tag_from_smooth(const float (*fnos)[3], BMEdge *e, const float split_angle_cos); -static void bm_edge_tag_clear(BMEdge *e); - /* -------------------------------------------------------------------- */ /** \name Update Vertex & Face Normals * \{ */ @@ -866,13 +864,6 @@ static void bm_edge_tag_from_smooth(const float (*fnos)[3], BMEdge *e, const flo } } -static void bm_edge_tag_clear(BMEdge *e) -{ - /* No need for atomics here as this is a single byte. */ - char *hflag_p = &e->head.hflag; - *hflag_p = *hflag_p & ~BM_ELEM_TAG; -} - /** * A version of #bm_edge_tag_from_smooth that sets sharp edges * when they would be considered smooth but exceed the split angle . @@ -941,6 +932,7 @@ static void bm_mesh_loops_calc_normals_for_vert_with_clnors(BMesh *bm, const bool has_clnors = true; LinkNode *loops_of_vert = NULL; int loops_of_vert_count = 0; + /* When false the caller must have already tagged the edges. */ const bool do_edge_tag = (split_angle_cos != EDGE_TAG_FROM_SPLIT_ANGLE_BYPASS); /* The loop with the lowest index. */ @@ -954,13 +946,9 @@ static void bm_mesh_loops_calc_normals_for_vert_with_clnors(BMesh *bm, continue; } - /* Always set as #bm_mesh_loops_calc_normals_for_loop checks the tag. */ if (do_edge_tag) { bm_edge_tag_from_smooth(fnos, e_curr_iter, split_angle_cos); } - else { - bm_edge_tag_clear(e_curr_iter); - } do { /* Radial loops. */ if (l_curr->v != v) { @@ -1053,6 +1041,7 @@ static void bm_mesh_loops_calc_normals_for_vert_without_clnors( { const bool has_clnors = false; const short(*clnors_data)[2] = NULL; + /* When false the caller must have already tagged the edges. */ const bool do_edge_tag = (split_angle_cos != EDGE_TAG_FROM_SPLIT_ANGLE_BYPASS); const int cd_loop_clnors_offset = -1; @@ -1066,13 +1055,9 @@ static void bm_mesh_loops_calc_normals_for_vert_without_clnors( continue; } - /* Always set as #bm_mesh_loops_calc_normals_for_loop checks the tag. */ if (do_edge_tag) { bm_edge_tag_from_smooth(fnos, e_curr_iter, split_angle_cos); } - else { - bm_edge_tag_clear(e_curr_iter); - } do { /* Radial loops. */ if (l_curr->v != v) { @@ -1167,8 +1152,9 @@ static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm, do { BM_elem_index_set(l_curr, index_loop++); /* set_inline */ BM_elem_flag_disable(l_curr, BM_ELEM_TAG); - /* Needed for when #bm_mesh_edges_sharp_tag doesn't run. */ - BM_elem_flag_disable(l_curr->e, BM_ELEM_TAG); + /* Needed for when #bm_mesh_edges_sharp_tag doesn't run. + * Mark smooth if there is no smoothing angle. */ + BM_elem_flag_enable(l_curr->e, BM_ELEM_TAG); } while ((l_curr = l_curr->next) != l_first); } bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); -- cgit v1.2.3 From 03e2f11d48dc4e7bb8124c4c4be3403aea56e0c8 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 5 Aug 2021 11:29:46 +0200 Subject: Fix T89835: Crash after Instancing to Scene after making linked Collection local. Even though the ID itself remain the same after being made local, from depsgraph point of view this is a different ID. Hence we need to tag all of its users for COW update, as well as rebuild depsgraph relationships. Should be also backported to LTS 2.93 (and 2.83 if possible). --- source/blender/blenkernel/intern/lib_id.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 62d29188c5a..5e1027c62af 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -73,6 +73,7 @@ #include "BKE_rigidbody.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" #include "RNA_access.h" @@ -141,7 +142,8 @@ static int lib_id_clear_library_data_users_update_cb(LibraryIDLinkCallbackData * { ID *id = cb_data->user_data; if (*cb_data->id_pointer == id) { - DEG_id_tag_update_ex(cb_data->bmain, cb_data->id_owner, ID_RECALC_TAG_FOR_UNDO); + DEG_id_tag_update_ex( + cb_data->bmain, cb_data->id_owner, ID_RECALC_TAG_FOR_UNDO | ID_RECALC_COPY_ON_WRITE); return IDWALK_RET_STOP_ITER; } return IDWALK_RET_NOP; @@ -193,6 +195,8 @@ static void lib_id_clear_library_data_ex(Main *bmain, ID *id) if (key != NULL) { lib_id_clear_library_data_ex(bmain, &key->id); } + + DEG_relations_tag_update(bmain); } void BKE_lib_id_clear_library_data(Main *bmain, ID *id) -- cgit v1.2.3 From 317f09ebf990ab4a5d033bab61a0aa8816772615 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 28 Jul 2021 17:36:40 +0200 Subject: Fix T90170: `RNA_property_pointer_get` creating data in non-thread-safe way. Protect this accessor with a local static mutex when it needs to create/write data. Ideally accessors should never create or modify data, but there are some cases where this bad behavior is currently unavoidable. This is the case of the Pointer accessor when the actual IDProperty has not yet been created. NOTE: this fixes a memory leak in liboverride diffing process when several different overrides use a same linked reference ID. Differential Revision: https://developer.blender.org/D12060 --- source/blender/makesrna/intern/rna_access.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 46d60bf0da9..c991216da11 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -36,6 +36,7 @@ #include "BLI_dynstr.h" #include "BLI_ghash.h" #include "BLI_math.h" +#include "BLI_threads.h" #include "BLI_utildefines.h" #include "BLF_api.h" @@ -3676,6 +3677,8 @@ PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop) PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; IDProperty *idprop; + static ThreadMutex lock = BLI_MUTEX_INITIALIZER; + BLI_assert(RNA_property_type(prop) == PROP_POINTER); if ((idprop = rna_idproperty_check(&prop, ptr))) { @@ -3695,9 +3698,14 @@ PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop) return pprop->get(ptr); } if (prop->flag & PROP_IDPROPERTY) { - /* XXX temporary hack to add it automatically, reading should - * never do any write ops, to ensure thread safety etc. */ + /* NOTE: While creating/writing data in an accessor is really bad design-wise, this is + * currently very difficult to avoid in that case. So a global mutex is used to keep ensuring + * thread safety. */ + BLI_mutex_lock(&lock); + /* NOTE: We do not need to check again for existence of the pointer after locking here, since + * this is also done in #RNA_property_pointer_add itself. */ RNA_property_pointer_add(ptr, prop); + BLI_mutex_unlock(&lock); return RNA_property_pointer_get(ptr, prop); } return PointerRNA_NULL; -- cgit v1.2.3 From 02e0c6f42e76e2cd5d086bde336789991434eba5 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Thu, 5 Aug 2021 12:10:49 +0200 Subject: Fix T90430: Crash when dragging material Was trying to get asset information even when there was none, i.e. when the material wasn't an asset or not dragged from the Asset Browser. --- source/blender/editors/space_view3d/space_view3d.c | 4 ++-- source/blender/windowmanager/WM_api.h | 2 ++ source/blender/windowmanager/intern/wm_dragdrop.c | 8 ++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 0803b4c4776..72d0c11e192 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -534,8 +534,8 @@ static char *view3d_mat_drop_tooltip(bContext *C, const wmEvent *event, struct wmDropBox *drop) { - wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, ID_MA); - RNA_string_set(drop->ptr, "name", asset_drag->name); + const char *name = WM_drag_get_item_name(drag); + RNA_string_set(drop->ptr, "name", name); return ED_object_ot_drop_named_material_tooltip(C, drop->ptr, event); } diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index fb973592a57..8c1511fd152 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -728,6 +728,8 @@ void WM_drag_free_imported_drag_ID(struct Main *bmain, struct wmDrag *drag, struct wmDropBox *drop); +const char *WM_drag_get_item_name(struct wmDrag *drag); + /* Set OpenGL viewport and scissor */ void wmViewport(const struct rcti *winrct); void wmPartialViewport(rcti *drawrct, const rcti *winrct, const rcti *partialrct); diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c index dcbb502117e..76bb93b681c 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.c +++ b/source/blender/windowmanager/intern/wm_dragdrop.c @@ -469,7 +469,7 @@ static void wm_drop_operator_draw(const char *name, int x, int y) UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, col_fg, col_bg); } -static const char *wm_drag_name(wmDrag *drag) +const char *WM_drag_get_item_name(wmDrag *drag) { switch (drag->type) { case WM_DRAG_ID: { @@ -583,11 +583,11 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect) } if (rect) { - int w = UI_fontstyle_string_width(fstyle, wm_drag_name(drag)); + int w = UI_fontstyle_string_width(fstyle, WM_drag_get_item_name(drag)); drag_rect_minmax(rect, x, y, x + w, y + iconsize); } else { - UI_fontstyle_draw_simple(fstyle, x, y, wm_drag_name(drag), text_col); + UI_fontstyle_draw_simple(fstyle, x, y, WM_drag_get_item_name(drag), text_col); } /* operator name with roundbox */ @@ -614,7 +614,7 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect) } if (rect) { - int w = UI_fontstyle_string_width(fstyle, wm_drag_name(drag)); + int w = UI_fontstyle_string_width(fstyle, WM_drag_get_item_name(drag)); drag_rect_minmax(rect, x, y, x + w, y + iconsize); } else { -- cgit v1.2.3 From ed9759349b3da090d22bd34bc066b72025679dc4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 5 Aug 2021 20:41:23 +1000 Subject: Fix T89214: Smooth Vertices (Laplacian) produces NaN coordinates Vertices with no connected faces would attempt to divide by the combined face area causing a divide by zero. Use the same weight for wire vertices as vertices connected to zero area faces. --- source/blender/bmesh/operators/bmo_smooth_laplacian.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c index b2b93bfd003..31f66ad952f 100644 --- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c +++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c @@ -533,7 +533,10 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) EIG_linear_solver_right_hand_side_add(sys->context, 1, m_vertex_id, v->co[1]); EIG_linear_solver_right_hand_side_add(sys->context, 2, m_vertex_id, v->co[2]); i = m_vertex_id; - if (sys->zerola[i] == 0) { + if ((sys->zerola[i] == 0) && + /* Non zero check is to account for vertices that aren't connected to a selected face. + * Without this wire edges become `nan`, see T89214. */ + (sys->ring_areas[i] != 0.0f)) { w = sys->vweights[i] * sys->ring_areas[i]; sys->vweights[i] = (w == 0.0f) ? 0.0f : -lambda_factor / (4.0f * w); w = sys->vlengths[i]; -- cgit v1.2.3 From f45860fba9c47466a18d92c1621c153aaef7be05 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Thu, 5 Aug 2021 12:52:12 +0200 Subject: Cleanup: Remove unused members in FileSelectParams --- source/blender/makesdna/DNA_space_types.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 7290647dbc6..27d5d83c7cb 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -754,13 +754,7 @@ typedef struct FileSelectParams { /** Max number of levels in dirtree to show at once, 0 to disable recursion. */ short recursion_level; - /* XXX --- still unused -- */ - /** Show font preview. */ - short f_fp; - /** String to use for font preview. */ - char fp_str[8]; - - /* XXX --- end unused -- */ + char _pad4[2]; } FileSelectParams; /** -- cgit v1.2.3 From fb1822ddeb28037544e94862112aa7338a0c278b Mon Sep 17 00:00:00 2001 From: Peter Kim Date: Thu, 5 Aug 2021 21:11:01 +0900 Subject: XR: Controller Data Improvements Provides two key improvements to runtime controller data. 1. Separates controller poses into two components, "grip" and "aim", which are both required to accurately represent the controllers without manual offsets. Following their OpenXR definitions, the grip pose represents the user's hand when holding the controller, and the aim pose represents the controller's aiming source. 2. Runtime controller data is now stored as a dynamic array instead of a fixed array. This makes the API/functionality more adaptable to different systems. Does not bring about any changes for users since only internal runtime functionality is currently affected. Reviewed By: Julian Eisel Differential Revision: http://developer.blender.org/D12073 --- source/blender/windowmanager/WM_api.h | 17 ++- .../blender/windowmanager/xr/intern/wm_xr_action.c | 72 ++++++---- .../blender/windowmanager/xr/intern/wm_xr_draw.c | 32 ++--- .../blender/windowmanager/xr/intern/wm_xr_intern.h | 47 +++--- .../windowmanager/xr/intern/wm_xr_session.c | 160 +++++++++++++++------ 5 files changed, 215 insertions(+), 113 deletions(-) diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 8c1511fd152..7e26d921bd7 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -962,12 +962,18 @@ bool WM_xr_session_state_viewer_pose_rotation_get(const wmXrData *xr, float r_ro bool WM_xr_session_state_viewer_pose_matrix_info_get(const wmXrData *xr, float r_viewmat[4][4], float *r_focal_len); -bool WM_xr_session_state_controller_pose_location_get(const wmXrData *xr, +bool WM_xr_session_state_controller_grip_location_get(const wmXrData *xr, unsigned int subaction_idx, float r_location[3]); -bool WM_xr_session_state_controller_pose_rotation_get(const wmXrData *xr, +bool WM_xr_session_state_controller_grip_rotation_get(const wmXrData *xr, unsigned int subaction_idx, float r_rotation[4]); +bool WM_xr_session_state_controller_aim_location_get(const wmXrData *xr, + unsigned int subaction_idx, + float r_location[3]); +bool WM_xr_session_state_controller_aim_rotation_get(const wmXrData *xr, + unsigned int subaction_idx, + float r_rotation[4]); /* wm_xr_actions.c */ /* XR action functions to be called pre-XR session start. @@ -1002,9 +1008,10 @@ void WM_xr_action_binding_destroy(wmXrData *xr, /* If action_set_name is NULL, then all action sets will be treated as active. */ bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name); -bool WM_xr_controller_pose_action_set(wmXrData *xr, - const char *action_set_name, - const char *action_name); +bool WM_xr_controller_pose_actions_set(wmXrData *xr, + const char *action_set_name, + const char *grip_action_name, + const char *aim_action_name); /* XR action functions to be called post-XR session start. */ bool WM_xr_action_state_get(const wmXrData *xr, diff --git a/source/blender/windowmanager/xr/intern/wm_xr_action.c b/source/blender/windowmanager/xr/intern/wm_xr_action.c index ee4cfcccaa7..8f2de4bbbad 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_action.c +++ b/source/blender/windowmanager/xr/intern/wm_xr_action.c @@ -112,11 +112,11 @@ static wmXrAction *action_create(const char *action_name, const bool is_button_action = (is_float_action || type == XR_BOOLEAN_INPUT); if (is_float_action) { action->float_thresholds = MEM_calloc_arrayN( - count, sizeof(*action->float_thresholds), "XrAction_FloatThresholds"); + count, sizeof(*action->float_thresholds), "XrAction_FloatThresholds"); } if (is_button_action) { action->axis_flags = MEM_calloc_arrayN( - count, sizeof(*action->axis_flags), "XrAction_AxisFlags"); + count, sizeof(*action->axis_flags), "XrAction_AxisFlags"); } action->ot = ot; @@ -186,9 +186,9 @@ void WM_xr_action_set_destroy(wmXrData *xr, const char *action_set_name) wmXrSessionState *session_state = &xr->runtime->session_state; if (action_set == session_state->active_action_set) { - if (action_set->controller_pose_action) { + if (action_set->controller_grip_action || action_set->controller_aim_action) { wm_xr_session_controller_data_clear(session_state); - action_set->controller_pose_action = NULL; + action_set->controller_grip_action = action_set->controller_aim_action = NULL; } if (action_set->active_modal_action) { action_set->active_modal_action = NULL; @@ -213,13 +213,8 @@ bool WM_xr_action_create(wmXrData *xr, return false; } - wmXrAction *action = action_create(action_name, - type, - count_subaction_paths, - subaction_paths, - ot, - op_properties, - op_flag); + wmXrAction *action = action_create( + action_name, type, count_subaction_paths, subaction_paths, ot, op_properties, op_flag); GHOST_XrActionInfo info = { .name = action_name, @@ -269,13 +264,16 @@ void WM_xr_action_destroy(wmXrData *xr, const char *action_set_name, const char return; } - if (action_set->controller_pose_action && - STREQ(action_set->controller_pose_action->name, action_name)) { + if ((action_set->controller_grip_action && + STREQ(action_set->controller_grip_action->name, action_name)) || + (action_set->controller_aim_action && + STREQ(action_set->controller_aim_action->name, action_name))) { if (action_set == xr->runtime->session_state.active_action_set) { wm_xr_session_controller_data_clear(&xr->runtime->session_state); } - action_set->controller_pose_action = NULL; + action_set->controller_grip_action = action_set->controller_aim_action = NULL; } + if (action_set->active_modal_action && STREQ(action_set->active_modal_action->name, action_name)) { action_set->active_modal_action = NULL; @@ -284,7 +282,6 @@ void WM_xr_action_destroy(wmXrData *xr, const char *action_set_name, const char GHOST_XrDestroyActions(xr->runtime->context, action_set_name, 1, &action_name); } - bool WM_xr_action_binding_create(wmXrData *xr, const char *action_set_name, const char *action_name, @@ -297,7 +294,7 @@ bool WM_xr_action_binding_create(wmXrData *xr, const struct wmXrPose *poses) { GHOST_XrActionBindingInfo *binding_infos = MEM_calloc_arrayN( - count_subaction_paths, sizeof(*binding_infos), __func__); + count_subaction_paths, sizeof(*binding_infos), __func__); for (unsigned int i = 0; i < count_subaction_paths; ++i) { GHOST_XrActionBindingInfo *binding_info = &binding_infos[i]; @@ -334,7 +331,7 @@ void WM_xr_action_binding_destroy(wmXrData *xr, const char *profile_path) { GHOST_XrDestroyActionBindings( - xr->runtime->context, action_set_name, 1, &action_name, &profile_path); + xr->runtime->context, action_set_name, 1, &action_name, &profile_path); } bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name) @@ -360,31 +357,54 @@ bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name) xr->runtime->session_state.active_action_set = action_set; - if (action_set->controller_pose_action) { - wm_xr_session_controller_data_populate(action_set->controller_pose_action, xr); + if (action_set->controller_grip_action && action_set->controller_aim_action) { + wm_xr_session_controller_data_populate( + action_set->controller_grip_action, action_set->controller_aim_action, xr); + } + else { + wm_xr_session_controller_data_clear(&xr->runtime->session_state); } return true; } -bool WM_xr_controller_pose_action_set(wmXrData *xr, - const char *action_set_name, - const char *action_name) +bool WM_xr_controller_pose_actions_set(wmXrData *xr, + const char *action_set_name, + const char *grip_action_name, + const char *aim_action_name) { wmXrActionSet *action_set = action_set_find(xr, action_set_name); if (!action_set) { return false; } - wmXrAction *action = action_find(xr, action_set_name, action_name); - if (!action) { + wmXrAction *grip_action = action_find(xr, action_set_name, grip_action_name); + if (!grip_action) { + return false; + } + + wmXrAction *aim_action = action_find(xr, action_set_name, aim_action_name); + if (!aim_action) { return false; } - action_set->controller_pose_action = action; + /* Ensure consistent subaction paths. */ + const unsigned int count = grip_action->count_subaction_paths; + if (count != aim_action->count_subaction_paths) { + return false; + } + + for (unsigned int i = 0; i < count; ++i) { + if (!STREQ(grip_action->subaction_paths[i], aim_action->subaction_paths[i])) { + return false; + } + } + + action_set->controller_grip_action = grip_action; + action_set->controller_aim_action = aim_action; if (action_set == xr->runtime->session_state.active_action_set) { - wm_xr_session_controller_data_populate(action, xr); + wm_xr_session_controller_data_populate(grip_action, aim_action, xr); } return true; diff --git a/source/blender/windowmanager/xr/intern/wm_xr_draw.c b/source/blender/windowmanager/xr/intern/wm_xr_draw.c index 4ac05e339b9..bbb73fc2007 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_draw.c +++ b/source/blender/windowmanager/xr/intern/wm_xr_draw.c @@ -38,18 +38,18 @@ #include "wm_surface.h" #include "wm_xr_intern.h" -void wm_xr_pose_to_viewmat(const GHOST_XrPose *pose, float r_viewmat[4][4]) +void wm_xr_pose_to_mat(const GHOST_XrPose *pose, float r_mat[4][4]) { - float iquat[4]; - invert_qt_qt_normalized(iquat, pose->orientation_quat); - quat_to_mat4(r_viewmat, iquat); - translate_m4(r_viewmat, -pose->position[0], -pose->position[1], -pose->position[2]); + quat_to_mat4(r_mat, pose->orientation_quat); + copy_v3_v3(r_mat[3], pose->position); } -void wm_xr_controller_pose_to_mat(const GHOST_XrPose *pose, float r_mat[4][4]) +void wm_xr_pose_to_imat(const GHOST_XrPose *pose, float r_imat[4][4]) { - quat_to_mat4(r_mat, pose->orientation_quat); - copy_v3_v3(r_mat[3], pose->position); + float iquat[4]; + invert_qt_qt_normalized(iquat, pose->orientation_quat); + quat_to_mat4(r_imat, iquat); + translate_m4(r_imat, -pose->position[0], -pose->position[1], -pose->position[2]); } static void wm_xr_draw_matrices_create(const wmXrDrawData *draw_data, @@ -59,6 +59,7 @@ static void wm_xr_draw_matrices_create(const wmXrDrawData *draw_data, float r_proj_mat[4][4]) { GHOST_XrPose eye_pose; + float eye_inv[4][4], base_inv[4][4]; copy_qt_qt(eye_pose.orientation_quat, draw_view->eye_pose.orientation_quat); copy_v3_v3(eye_pose.position, draw_view->eye_pose.position); @@ -69,6 +70,12 @@ static void wm_xr_draw_matrices_create(const wmXrDrawData *draw_data, sub_v3_v3(eye_pose.position, draw_data->eye_position_ofs); } + wm_xr_pose_to_imat(&eye_pose, eye_inv); + /* Calculate the base pose matrix (in world space!). */ + wm_xr_pose_to_imat(&draw_data->base_pose, base_inv); + + mul_m4_m4m4(r_view_mat, eye_inv, base_inv); + perspective_m4_fov(r_proj_mat, draw_view->fov.angle_left, draw_view->fov.angle_right, @@ -76,15 +83,6 @@ static void wm_xr_draw_matrices_create(const wmXrDrawData *draw_data, draw_view->fov.angle_down, session_settings->clip_start, session_settings->clip_end); - - float eye_mat[4][4]; - float base_mat[4][4]; - - wm_xr_pose_to_viewmat(&eye_pose, eye_mat); - /* Calculate the base pose matrix (in world space!). */ - wm_xr_pose_to_viewmat(&draw_data->base_pose, base_mat); - - mul_m4_m4m4(r_view_mat, eye_mat, base_mat); } static void wm_xr_draw_viewport_buffers_to_active_framebuffer( diff --git a/source/blender/windowmanager/xr/intern/wm_xr_intern.h b/source/blender/windowmanager/xr/intern/wm_xr_intern.h index 4530aeaa428..b6aff1f71f9 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_intern.h +++ b/source/blender/windowmanager/xr/intern/wm_xr_intern.h @@ -26,19 +26,6 @@ struct wmXrActionSet; -typedef struct wmXrControllerData { - /** OpenXR path identifier. Length is dependent on OpenXR's XR_MAX_PATH_LENGTH (256). - This subaction path will later be combined with a component path, and that combined path should - also have a max of XR_MAX_PATH_LENGTH (e.g. subaction_path = /user/hand/left, component_path = - /input/trigger/value, interaction_path = /user/hand/left/input/trigger/value). - */ - char subaction_path[64]; - /** Last known controller pose (in world space) stored for queries. */ - GHOST_XrPose pose; - /** The last known controller matrix, calculated from above's controller pose. */ - float mat[4][4]; -} wmXrControllerData; - typedef struct wmXrSessionState { bool is_started; @@ -65,7 +52,7 @@ typedef struct wmXrSessionState { bool is_view_data_set; /** Last known controller data. */ - wmXrControllerData controllers[2]; + ListBase controllers; /* wmXrController */ /** The currently active action set that will be updated on calls to * wm_xr_session_actions_update(). If NULL, all action sets will be treated as active and @@ -135,14 +122,27 @@ typedef struct wmXrAction { eXrOpFlag op_flag; } wmXrAction; +typedef struct wmXrController { + struct wmXrController *next, *prev; + /** OpenXR path identifier. Length is dependent on OpenXR's XR_MAX_PATH_LENGTH (256). + This subaction path will later be combined with a component path, and that combined path should + also have a max of XR_MAX_PATH_LENGTH (e.g. subaction_path = /user/hand/left, component_path = + /input/trigger/value, interaction_path = /user/hand/left/input/trigger/value). + */ + char subaction_path[64]; + /* Pose (in world space) that represents the user's hand when holding the controller.*/ + GHOST_XrPose grip_pose; + float grip_mat[4][4]; + /* Pose (in world space) that represents the controller's aiming source. */ + GHOST_XrPose aim_pose; + float aim_mat[4][4]; +} wmXrController; + typedef struct wmXrActionSet { char *name; - - /** The XR pose action that determines the controller - * transforms. This is usually identified by the OpenXR path "/grip/pose" or "/aim/pose", - * although it could differ depending on the specification and hardware. */ - wmXrAction *controller_pose_action; - + /** XR pose actions that determine the controller grip/aim transforms. */ + wmXrAction *controller_grip_action; + wmXrAction *controller_aim_action; /** The currently active modal action (if any). */ wmXrAction *active_modal_action; } wmXrActionSet; @@ -165,10 +165,11 @@ void wm_xr_session_gpu_binding_context_destroy(GHOST_ContextHandle context); void wm_xr_session_actions_init(wmXrData *xr); void wm_xr_session_actions_update(wmXrData *xr); -void wm_xr_session_controller_data_populate(const wmXrAction *controller_pose_action, +void wm_xr_session_controller_data_populate(const wmXrAction *grip_action, + const wmXrAction *aim_action, wmXrData *xr); void wm_xr_session_controller_data_clear(wmXrSessionState *state); -void wm_xr_pose_to_viewmat(const GHOST_XrPose *pose, float r_viewmat[4][4]); -void wm_xr_controller_pose_to_mat(const GHOST_XrPose *pose, float r_mat[4][4]); +void wm_xr_pose_to_mat(const GHOST_XrPose *pose, float r_mat[4][4]); +void wm_xr_pose_to_imat(const GHOST_XrPose *pose, float r_imat[4][4]); void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata); diff --git a/source/blender/windowmanager/xr/intern/wm_xr_session.c b/source/blender/windowmanager/xr/intern/wm_xr_session.c index 252f358c798..dd9cac2bb16 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_session.c +++ b/source/blender/windowmanager/xr/intern/wm_xr_session.c @@ -63,6 +63,16 @@ static void wm_xr_session_create_cb(void) wm_xr_session_actions_init(xr_data); } +static void wm_xr_session_controller_data_free(wmXrSessionState *state) +{ + BLI_freelistN(&state->controllers); +} + +static void wm_xr_session_data_free(wmXrSessionState *state) +{ + wm_xr_session_controller_data_free(state); +} + static void wm_xr_session_exit_cb(void *customdata) { wmXrData *xr_data = customdata; @@ -74,6 +84,7 @@ static void wm_xr_session_exit_cb(void *customdata) } /* Free the entire runtime data (including session state and context), to play safe. */ + wm_xr_session_data_free(&xr_data->runtime->session_state); wm_xr_runtime_data_free(&xr_data->runtime); } @@ -338,7 +349,7 @@ void wm_xr_session_state_update(const XrSessionSettings *settings, copy_v3_v3(state->viewer_pose.position, viewer_pose.position); copy_qt_qt(state->viewer_pose.orientation_quat, viewer_pose.orientation_quat); - wm_xr_pose_to_viewmat(&viewer_pose, state->viewer_viewmat); + wm_xr_pose_to_imat(&viewer_pose, state->viewer_viewmat); /* No idea why, but multiplying by two seems to make it match the VR view more. */ state->focal_len = 2.0f * fov_to_focallength(draw_view->fov.angle_right - draw_view->fov.angle_left, @@ -398,32 +409,71 @@ bool WM_xr_session_state_viewer_pose_matrix_info_get(const wmXrData *xr, return true; } -bool WM_xr_session_state_controller_pose_location_get(const wmXrData *xr, +bool WM_xr_session_state_controller_grip_location_get(const wmXrData *xr, unsigned int subaction_idx, float r_location[3]) { if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set || - subaction_idx >= ARRAY_SIZE(xr->runtime->session_state.controllers)) { + (subaction_idx >= BLI_listbase_count(&xr->runtime->session_state.controllers))) { zero_v3(r_location); return false; } - copy_v3_v3(r_location, xr->runtime->session_state.controllers[subaction_idx].pose.position); + const wmXrController *controller = BLI_findlink(&xr->runtime->session_state.controllers, + subaction_idx); + BLI_assert(controller); + copy_v3_v3(r_location, controller->grip_pose.position); return true; } -bool WM_xr_session_state_controller_pose_rotation_get(const wmXrData *xr, +bool WM_xr_session_state_controller_grip_rotation_get(const wmXrData *xr, unsigned int subaction_idx, float r_rotation[4]) { if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set || - subaction_idx >= ARRAY_SIZE(xr->runtime->session_state.controllers)) { + (subaction_idx >= BLI_listbase_count(&xr->runtime->session_state.controllers))) { unit_qt(r_rotation); return false; } - copy_v4_v4(r_rotation, - xr->runtime->session_state.controllers[subaction_idx].pose.orientation_quat); + const wmXrController *controller = BLI_findlink(&xr->runtime->session_state.controllers, + subaction_idx); + BLI_assert(controller); + copy_qt_qt(r_rotation, controller->grip_pose.orientation_quat); + return true; +} + +bool WM_xr_session_state_controller_aim_location_get(const wmXrData *xr, + unsigned int subaction_idx, + float r_location[3]) +{ + if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set || + (subaction_idx >= BLI_listbase_count(&xr->runtime->session_state.controllers))) { + zero_v3(r_location); + return false; + } + + const wmXrController *controller = BLI_findlink(&xr->runtime->session_state.controllers, + subaction_idx); + BLI_assert(controller); + copy_v3_v3(r_location, controller->aim_pose.position); + return true; +} + +bool WM_xr_session_state_controller_aim_rotation_get(const wmXrData *xr, + unsigned int subaction_idx, + float r_rotation[4]) +{ + if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set || + (subaction_idx >= BLI_listbase_count(&xr->runtime->session_state.controllers))) { + unit_qt(r_rotation); + return false; + } + + const wmXrController *controller = BLI_findlink(&xr->runtime->session_state.controllers, + subaction_idx); + BLI_assert(controller); + copy_qt_qt(r_rotation, controller->aim_pose.orientation_quat); return true; } @@ -443,16 +493,34 @@ void wm_xr_session_actions_init(wmXrData *xr) GHOST_XrAttachActionSets(xr->runtime->context); } -static void wm_xr_session_controller_mats_update(const XrSessionSettings *settings, - const wmXrAction *controller_pose_action, +static void wm_xr_session_controller_pose_calc(const GHOST_XrPose *raw_pose, + const float view_ofs[3], + const float base_mat[4][4], + GHOST_XrPose *r_pose, + float r_mat[4][4]) +{ + float m[4][4]; + /* Calculate controller matrix in world space. */ + wm_xr_pose_to_mat(raw_pose, m); + + /* Apply eye position and base pose offsets. */ + sub_v3_v3(m[3], view_ofs); + mul_m4_m4m4(r_mat, base_mat, m); + + /* Save final pose. */ + mat4_to_loc_quat(r_pose->position, r_pose->orientation_quat, r_mat); +} + +static void wm_xr_session_controller_data_update(const XrSessionSettings *settings, + const wmXrAction *grip_action, + const wmXrAction *aim_action, wmXrSessionState *state) { - const unsigned int count = (unsigned int)min_ii( - (int)controller_pose_action->count_subaction_paths, (int)ARRAY_SIZE(state->controllers)); + BLI_assert(grip_action->count_subaction_paths == aim_action->count_subaction_paths); + BLI_assert(grip_action->count_subaction_paths == BLI_listbase_count(&state->controllers)); - float view_ofs[3]; - float base_inv[4][4]; - float tmp[4][4]; + unsigned int subaction_idx = 0; + float view_ofs[3], base_mat[4][4]; if ((settings->flag & XR_SESSION_USE_POSITION_TRACKING) == 0) { copy_v3_v3(view_ofs, state->prev_local_pose.position); @@ -464,22 +532,19 @@ static void wm_xr_session_controller_mats_update(const XrSessionSettings *settin add_v3_v3(view_ofs, state->prev_eye_position_ofs); } - wm_xr_pose_to_viewmat(&state->prev_base_pose, base_inv); - invert_m4(base_inv); - - for (unsigned int i = 0; i < count; ++i) { - wmXrControllerData *controller = &state->controllers[i]; - - /* Calculate controller matrix in world space. */ - wm_xr_controller_pose_to_mat(&((GHOST_XrPose *)controller_pose_action->states)[i], tmp); - - /* Apply eye position and base pose offsets. */ - sub_v3_v3(tmp[3], view_ofs); - mul_m4_m4m4(controller->mat, base_inv, tmp); + wm_xr_pose_to_mat(&state->prev_base_pose, base_mat); - /* Save final pose. */ - mat4_to_loc_quat( - controller->pose.position, controller->pose.orientation_quat, controller->mat); + LISTBASE_FOREACH_INDEX (wmXrController *, controller, &state->controllers, subaction_idx) { + wm_xr_session_controller_pose_calc(&((GHOST_XrPose *)grip_action->states)[subaction_idx], + view_ofs, + base_mat, + &controller->grip_pose, + controller->grip_mat); + wm_xr_session_controller_pose_calc(&((GHOST_XrPose *)aim_action->states)[subaction_idx], + view_ofs, + base_mat, + &controller->aim_pose, + controller->aim_mat); } } @@ -498,33 +563,44 @@ void wm_xr_session_actions_update(wmXrData *xr) return; } - /* Only update controller mats for active action set. */ + /* Only update controller data for active action set. */ if (active_action_set) { - if (active_action_set->controller_pose_action) { - wm_xr_session_controller_mats_update( - &xr->session_settings, active_action_set->controller_pose_action, state); + if (active_action_set->controller_grip_action && active_action_set->controller_aim_action) { + wm_xr_session_controller_data_update(&xr->session_settings, + active_action_set->controller_grip_action, + active_action_set->controller_aim_action, + state); } } } -void wm_xr_session_controller_data_populate(const wmXrAction *controller_pose_action, wmXrData *xr) +void wm_xr_session_controller_data_populate(const wmXrAction *grip_action, + const wmXrAction *aim_action, + wmXrData *xr) { + UNUSED_VARS(aim_action); /* Only used for asserts. */ + wmXrSessionState *state = &xr->runtime->session_state; + ListBase *controllers = &state->controllers; + + BLI_assert(grip_action->count_subaction_paths == aim_action->count_subaction_paths); + const unsigned int count = grip_action->count_subaction_paths; - const unsigned int count = (unsigned int)min_ii( - (int)ARRAY_SIZE(state->controllers), (int)controller_pose_action->count_subaction_paths); + wm_xr_session_controller_data_free(state); for (unsigned int i = 0; i < count; ++i) { - wmXrControllerData *c = &state->controllers[i]; - strcpy(c->subaction_path, controller_pose_action->subaction_paths[i]); - memset(&c->pose, 0, sizeof(c->pose)); - zero_m4(c->mat); + wmXrController *controller = MEM_callocN(sizeof(*controller), __func__); + + BLI_assert(STREQ(grip_action->subaction_paths[i], aim_action->subaction_paths[i])); + strcpy(controller->subaction_path, grip_action->subaction_paths[i]); + + BLI_addtail(controllers, controller); } } void wm_xr_session_controller_data_clear(wmXrSessionState *state) { - memset(state->controllers, 0, sizeof(state->controllers)); + wm_xr_session_controller_data_free(state); } /** \} */ /* XR-Session Actions */ -- cgit v1.2.3 From be6409a74850054d53b6c2f965e03e64e00a622f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 5 Aug 2021 22:32:18 +1000 Subject: Fix fix invalid index use for edit-mesh laplacian smooth Only vertex indices were ensured to be correct. --- .../blender/bmesh/operators/bmo_smooth_laplacian.c | 25 +++++++++------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c index 31f66ad952f..1d72bb893b2 100644 --- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c +++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c @@ -180,7 +180,7 @@ static void init_laplacian_matrix(LaplacianSystem *sys) BMVert *vn; BMVert *vf[4]; - BM_ITER_MESH_INDEX (e, &eiter, sys->bm, BM_EDGES_OF_MESH, j) { + BM_ITER_MESH_INDEX (e, &eiter, sys->bm, BM_EDGES_OF_MESH, i) { if (!BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_boundary(e)) { v1 = e->v1->co; v2 = e->v2->co; @@ -190,7 +190,6 @@ static void init_laplacian_matrix(LaplacianSystem *sys) w1 = len_v3v3(v1, v2); if (w1 > sys->min_area) { w1 = 1.0f / w1; - i = BM_elem_index_get(e); sys->eweights[i] = w1; sys->vlengths[idv1] += w1; sys->vlengths[idv2] += w1; @@ -202,13 +201,13 @@ static void init_laplacian_matrix(LaplacianSystem *sys) } } - BM_ITER_MESH (f, &fiter, sys->bm, BM_FACES_OF_MESH) { + BM_ITER_MESH_INDEX (f, &fiter, sys->bm, BM_FACES_OF_MESH, i) { if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, i) { - vf[i] = vn; + BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, j) { + vf[j] = vn; } - has_4_vert = (i == 4) ? 1 : 0; + has_4_vert = (j == 4) ? 1 : 0; idv1 = BM_elem_index_get(vf[0]); idv2 = BM_elem_index_get(vf[1]); idv3 = BM_elem_index_get(vf[2]); @@ -268,8 +267,6 @@ static void init_laplacian_matrix(LaplacianSystem *sys) } } else { - i = BM_elem_index_get(f); - w1 = cotangent_tri_weight_v3(v1, v2, v3); w2 = cotangent_tri_weight_v3(v2, v3, v1); w3 = cotangent_tri_weight_v3(v3, v1, v2); @@ -302,12 +299,12 @@ static void fill_laplacian_matrix(LaplacianSystem *sys) BMVert *vn; BMVert *vf[4]; - BM_ITER_MESH (f, &fiter, sys->bm, BM_FACES_OF_MESH) { + BM_ITER_MESH_INDEX (f, &fiter, sys->bm, BM_FACES_OF_MESH, i) { if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, i) { - vf[i] = vn; + BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, j) { + vf[j] = vn; } - has_4_vert = (i == 4) ? 1 : 0; + has_4_vert = (j == 4) ? 1 : 0; if (has_4_vert) { idv[0] = BM_elem_index_get(vf[0]); idv[1] = BM_elem_index_get(vf[1]); @@ -344,7 +341,6 @@ static void fill_laplacian_matrix(LaplacianSystem *sys) idv2 = BM_elem_index_get(vf[1]); idv3 = BM_elem_index_get(vf[2]); /* Is ring if number of faces == number of edges around vertice. */ - i = BM_elem_index_get(f); if (!vert_is_boundary(vf[0]) && sys->zerola[idv1] == 0) { EIG_linear_solver_matrix_add( sys->context, idv1, idv2, sys->fweights[i][2] * sys->vweights[idv1]); @@ -366,14 +362,13 @@ static void fill_laplacian_matrix(LaplacianSystem *sys) } } } - BM_ITER_MESH (e, &eiter, sys->bm, BM_EDGES_OF_MESH) { + BM_ITER_MESH_INDEX (e, &eiter, sys->bm, BM_EDGES_OF_MESH, i) { if (!BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_boundary(e)) { v1 = e->v1->co; v2 = e->v2->co; idv1 = BM_elem_index_get(e->v1); idv2 = BM_elem_index_get(e->v2); if (sys->zerola[idv1] == 0 && sys->zerola[idv2] == 0) { - i = BM_elem_index_get(e); EIG_linear_solver_matrix_add( sys->context, idv1, idv2, sys->eweights[i] * sys->vlengths[idv1]); EIG_linear_solver_matrix_add( -- cgit v1.2.3 From 720ea8a67df06ba2242e7771b349cefd753f7ea5 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 5 Aug 2021 14:59:31 +0200 Subject: Fix T89963: crash when library override is applied to an object from a linked scene. LibOverride of scenes is not really supported currently, there are many issues with it. Will disable most user-accessible ways to create such overrides in a following commit. --- source/blender/blenkernel/intern/lib_override.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 072304566e5..67ed7d1b394 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -1599,6 +1599,17 @@ static void lib_override_library_main_resync_on_library_indirect_level( (!ID_IS_LINKED(id) && library_indirect_level != 0)) { continue; } + + /* We cannot resync a scene that is currently active. */ + if (id == &scene->id) { + id->tag &= ~LIB_TAG_LIB_OVERRIDE_NEED_RESYNC; + BKE_reportf(reports->reports, + RPT_WARNING, + "Scene '%s' was not resynced as it is the currently active one", + scene->id.name + 2); + continue; + } + Library *library = id->lib; int level = 0; -- cgit v1.2.3 From 0cff7c2a228589505bd2d66e966e5e84613b2786 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 5 Aug 2021 15:24:46 +0200 Subject: LibOverride: Make it reasonably impossible for users to create overrides of scenes. This is not supported currently,doing so through RNA API remains possible, but from regular UI operations it should not be doable anymore. Ref. T90459. --- source/blender/editors/space_outliner/outliner_tools.c | 12 ++++++++++++ source/blender/makesdna/DNA_ID.h | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 3edb12c5503..e3aec572bd3 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -845,8 +845,20 @@ static void id_override_library_create_fn(bContext *C, if (!ID_IS_LINKED(te->store_elem->id)) { break; } + /* If we'd need to override that arent ID, but it is not overridable, abort. */ + if (!ID_IS_OVERRIDABLE_LIBRARY(te->store_elem->id)) { + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + BKE_reportf(reports, + RPT_WARNING, + "Could not create library override from data-block '%s', one of its parents " + "is not overridable ('%s')", + id_root->name, + te->store_elem->id->name); + return; + } te->store_elem->id->tag |= LIB_TAG_DOIT; } + success = BKE_lib_override_library_create( bmain, CTX_data_scene(C), CTX_data_view_layer(C), id_root, id_reference, NULL); } diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index c9d652ad03d..f7f4b0e6104 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -429,7 +429,8 @@ typedef struct PreviewImage { * BKE_library_override typically (especially due to the check on LIB_TAG_EXTERN). */ #define ID_IS_OVERRIDABLE_LIBRARY(_id) \ (ID_IS_LINKED(_id) && !ID_MISSING(_id) && (((const ID *)(_id))->tag & LIB_TAG_EXTERN) != 0 && \ - (BKE_idtype_get_info_from_id((const ID *)(_id))->flags & IDTYPE_FLAGS_NO_LIBLINKING) == 0) + (BKE_idtype_get_info_from_id((const ID *)(_id))->flags & IDTYPE_FLAGS_NO_LIBLINKING) == 0 && \ + !ELEM(GS(((ID *)(_id))->name), ID_SCE)) /* NOTE: The three checks below do not take into account whether given ID is linked or not (when * chaining overrides over several libraries). User must ensure the ID is not linked itself -- cgit v1.2.3 From e844e9e8f3bb6814e24749316003814156e2e2ce Mon Sep 17 00:00:00 2001 From: Peter Kim Date: Thu, 5 Aug 2021 23:40:17 +0900 Subject: XR Controller Support Step 2: Action Maps Addresses the remaining portions of T77137 (Python API for Controller Interaction), which was partially completed by D10942. Adds an XR "action maps" system for loading XR action data from a Python script. Action maps are accessible via the Python API, and are used to pass default actions to the VR session during the xr_session_start_pre() callback. Since action maps are stored only as runtime data, they will be cleaned up with the rest of the VR runtime data on file read or exit. Reviewed By: Julian Eisel, Hans Goudey Differential Revision: https://developer.blender.org/D10943 --- intern/ghost/GHOST_C-api.h | 16 +- intern/ghost/intern/GHOST_C-api.cpp | 33 +- intern/ghost/intern/GHOST_XrAction.cpp | 64 +- intern/ghost/intern/GHOST_XrAction.h | 8 +- intern/ghost/intern/GHOST_XrSession.cpp | 31 +- intern/ghost/intern/GHOST_XrSession.h | 7 +- source/blender/makesdna/DNA_xr_types.h | 107 +- source/blender/makesrna/intern/rna_xr.c | 1602 +++++++++++++++++++- source/blender/windowmanager/CMakeLists.txt | 1 + source/blender/windowmanager/WM_api.h | 51 +- source/blender/windowmanager/xr/intern/wm_xr.c | 1 + .../blender/windowmanager/xr/intern/wm_xr_action.c | 99 +- .../windowmanager/xr/intern/wm_xr_actionmap.c | 565 +++++++ .../blender/windowmanager/xr/intern/wm_xr_intern.h | 59 +- 14 files changed, 2541 insertions(+), 103 deletions(-) create mode 100644 source/blender/windowmanager/xr/intern/wm_xr_actionmap.c diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index fea5a545807..83c67f83908 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -1102,6 +1102,7 @@ int GHOST_XrSyncActions(GHOST_XrContextHandle xr_context, const char *action_set int GHOST_XrApplyHapticAction(GHOST_XrContextHandle xr_context, const char *action_set_name, const char *action_name, + const char **subaction_path, const int64_t *duration, const float *frequency, const float *amplitude); @@ -1111,7 +1112,8 @@ int GHOST_XrApplyHapticAction(GHOST_XrContextHandle xr_context, */ void GHOST_XrStopHapticAction(GHOST_XrContextHandle xr_context, const char *action_set_name, - const char *action_name); + const char *action_name, + const char **subaction_path); /** * Get action set custom data (owned by Blender, not GHOST). @@ -1126,6 +1128,18 @@ void *GHOST_XrGetActionCustomdata(GHOST_XrContextHandle xr_context, const char *action_set_name, const char *action_name); +/** + * Get the number of actions in an action set. + */ +unsigned int GHOST_XrGetActionCount(GHOST_XrContextHandle xr_context, const char *action_set_name); + +/** + * Get custom data for all actions in an action set. + */ +void GHOST_XrGetActionCustomdataArray(GHOST_XrContextHandle xr_context, + const char *action_set_name, + void **r_customdata_array); + #endif /* WITH_XR_OPENXR */ #ifdef __cplusplus diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index 0bc9be26eb1..b1af5c131ab 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -1005,25 +1005,29 @@ int GHOST_XrSyncActions(GHOST_XrContextHandle xr_contexthandle, const char *acti int GHOST_XrApplyHapticAction(GHOST_XrContextHandle xr_contexthandle, const char *action_set_name, const char *action_name, + const char **subaction_path, const int64_t *duration, const float *frequency, const float *amplitude) { GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; GHOST_XrSession *xr_session = xr_context->getSession(); - GHOST_XR_CAPI_CALL_RET(xr_session->applyHapticAction( - action_set_name, action_name, *duration, *frequency, *amplitude), - xr_context); + GHOST_XR_CAPI_CALL_RET( + xr_session->applyHapticAction( + action_set_name, action_name, subaction_path, *duration, *frequency, *amplitude), + xr_context); return 0; } void GHOST_XrStopHapticAction(GHOST_XrContextHandle xr_contexthandle, const char *action_set_name, - const char *action_name) + const char *action_name, + const char **subaction_path) { GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; GHOST_XrSession *xr_session = xr_context->getSession(); - GHOST_XR_CAPI_CALL(xr_session->stopHapticAction(action_set_name, action_name), xr_context); + GHOST_XR_CAPI_CALL(xr_session->stopHapticAction(action_set_name, action_name, subaction_path), + xr_context); } void *GHOST_XrGetActionSetCustomdata(GHOST_XrContextHandle xr_contexthandle, @@ -1046,4 +1050,23 @@ void *GHOST_XrGetActionCustomdata(GHOST_XrContextHandle xr_contexthandle, return 0; } +unsigned int GHOST_XrGetActionCount(GHOST_XrContextHandle xr_contexthandle, + const char *action_set_name) +{ + GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; + GHOST_XrSession *xr_session = xr_context->getSession(); + GHOST_XR_CAPI_CALL_RET(xr_session->getActionCount(action_set_name), xr_context); + return 0; +} + +void GHOST_XrGetActionCustomdataArray(GHOST_XrContextHandle xr_contexthandle, + const char *action_set_name, + void **r_customdata_array) +{ + GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; + GHOST_XrSession *xr_session = xr_context->getSession(); + GHOST_XR_CAPI_CALL(xr_session->getActionCustomdataArray(action_set_name, r_customdata_array), + xr_context); +} + #endif /* WITH_XR_OPENXR */ diff --git a/intern/ghost/intern/GHOST_XrAction.cpp b/intern/ghost/intern/GHOST_XrAction.cpp index 676a3367ee1..07eb42c14e6 100644 --- a/intern/ghost/intern/GHOST_XrAction.cpp +++ b/intern/ghost/intern/GHOST_XrAction.cpp @@ -208,8 +208,10 @@ GHOST_XrAction::GHOST_XrAction(XrInstance instance, m_subaction_paths.resize(info.count_subaction_paths); for (uint32_t i = 0; i < info.count_subaction_paths; ++i) { - CHECK_XR(xrStringToPath(instance, info.subaction_paths[i], &m_subaction_paths[i]), - (std::string("Failed to get user path \"") + info.subaction_paths[i] + "\".").data()); + const char *subaction_path_str = info.subaction_paths[i]; + CHECK_XR(xrStringToPath(instance, subaction_path_str, &m_subaction_paths[i]), + (std::string("Failed to get user path \"") + subaction_path_str + "\".").data()); + m_subaction_indices.insert({subaction_path_str, i}); } XrActionCreateInfo action_info{XR_TYPE_ACTION_CREATE_INFO}; @@ -373,6 +375,7 @@ void GHOST_XrAction::updateState(XrSession session, void GHOST_XrAction::applyHapticFeedback(XrSession session, const char *action_name, + const char **subaction_path_str, const int64_t &duration, const float &frequency, const float &litude) @@ -386,24 +389,46 @@ void GHOST_XrAction::applyHapticFeedback(XrSession session, XrHapticActionInfo haptic_info{XR_TYPE_HAPTIC_ACTION_INFO}; haptic_info.action = m_action; - for (std::vector::iterator it = m_subaction_paths.begin(); it != m_subaction_paths.end(); - ++it) { - haptic_info.subactionPath = *it; - CHECK_XR(xrApplyHapticFeedback(session, &haptic_info, (const XrHapticBaseHeader *)&vibration), - (std::string("Failed to apply haptic action \"") + action_name + "\".").data()); + if (subaction_path_str != nullptr) { + SubactionIndexMap::iterator it = m_subaction_indices.find(*subaction_path_str); + if (it != m_subaction_indices.end()) { + haptic_info.subactionPath = m_subaction_paths[it->second]; + CHECK_XR( + xrApplyHapticFeedback(session, &haptic_info, (const XrHapticBaseHeader *)&vibration), + (std::string("Failed to apply haptic action \"") + action_name + "\".").data()); + } + } + else { + for (const XrPath &subaction_path : m_subaction_paths) { + haptic_info.subactionPath = subaction_path; + CHECK_XR( + xrApplyHapticFeedback(session, &haptic_info, (const XrHapticBaseHeader *)&vibration), + (std::string("Failed to apply haptic action \"") + action_name + "\".").data()); + } } } -void GHOST_XrAction::stopHapticFeedback(XrSession session, const char *action_name) +void GHOST_XrAction::stopHapticFeedback(XrSession session, + const char *action_name, + const char **subaction_path_str) { XrHapticActionInfo haptic_info{XR_TYPE_HAPTIC_ACTION_INFO}; haptic_info.action = m_action; - for (std::vector::iterator it = m_subaction_paths.begin(); it != m_subaction_paths.end(); - ++it) { - haptic_info.subactionPath = *it; - CHECK_XR(xrStopHapticFeedback(session, &haptic_info), - (std::string("Failed to stop haptic action \"") + action_name + "\".").data()); + if (subaction_path_str != nullptr) { + SubactionIndexMap::iterator it = m_subaction_indices.find(*subaction_path_str); + if (it != m_subaction_indices.end()) { + haptic_info.subactionPath = m_subaction_paths[it->second]; + CHECK_XR(xrStopHapticFeedback(session, &haptic_info), + (std::string("Failed to stop haptic action \"") + action_name + "\".").data()); + } + } + else { + for (const XrPath &subaction_path : m_subaction_paths) { + haptic_info.subactionPath = subaction_path; + CHECK_XR(xrStopHapticFeedback(session, &haptic_info), + (std::string("Failed to stop haptic action \"") + action_name + "\".").data()); + } } } @@ -511,6 +536,19 @@ void *GHOST_XrActionSet::getCustomdata() return m_custom_data_->custom_data_; } +uint32_t GHOST_XrActionSet::getActionCount() const +{ + return (uint32_t)m_actions.size(); +} + +void GHOST_XrActionSet::getActionCustomdataArray(void **r_customdata_array) +{ + uint32_t i = 0; + for (auto &[name, action] : m_actions) { + r_customdata_array[i++] = action.getCustomdata(); + } +} + void GHOST_XrActionSet::getBindings( std::map> &r_bindings) const { diff --git a/intern/ghost/intern/GHOST_XrAction.h b/intern/ghost/intern/GHOST_XrAction.h index e2a89e87278..73a1cd9cd6a 100644 --- a/intern/ghost/intern/GHOST_XrAction.h +++ b/intern/ghost/intern/GHOST_XrAction.h @@ -103,17 +103,21 @@ class GHOST_XrAction { const XrTime &predicted_display_time); void applyHapticFeedback(XrSession session, const char *action_name, + const char **subaction_path, const int64_t &duration, const float &frequency, const float &litude); - void stopHapticFeedback(XrSession session, const char *action_name); + void stopHapticFeedback(XrSession session, const char *action_name, const char **subaction_path); void *getCustomdata(); void getBindings(std::map> &r_bindings) const; private: + using SubactionIndexMap = std::map; + XrAction m_action = XR_NULL_HANDLE; GHOST_XrActionType m_type; + SubactionIndexMap m_subaction_indices; std::vector m_subaction_paths; /** States for each subaction path. */ void *m_states; @@ -145,6 +149,8 @@ class GHOST_XrActionSet { XrActionSet getActionSet() const; void *getCustomdata(); + uint32_t getActionCount() const; + void getActionCustomdataArray(void **r_customdata_array); void getBindings(std::map> &r_bindings) const; private: diff --git a/intern/ghost/intern/GHOST_XrSession.cpp b/intern/ghost/intern/GHOST_XrSession.cpp index a29ec1cc560..a63ce5c9344 100644 --- a/intern/ghost/intern/GHOST_XrSession.cpp +++ b/intern/ghost/intern/GHOST_XrSession.cpp @@ -754,6 +754,7 @@ bool GHOST_XrSession::syncActions(const char *action_set_name) bool GHOST_XrSession::applyHapticAction(const char *action_set_name, const char *action_name, + const char **subaction_path, const int64_t &duration, const float &frequency, const float &litude) @@ -768,12 +769,15 @@ bool GHOST_XrSession::applyHapticAction(const char *action_set_name, return false; } - action->applyHapticFeedback(m_oxr->session, action_name, duration, frequency, amplitude); + action->applyHapticFeedback( + m_oxr->session, action_name, subaction_path, duration, frequency, amplitude); return true; } -void GHOST_XrSession::stopHapticAction(const char *action_set_name, const char *action_name) +void GHOST_XrSession::stopHapticAction(const char *action_set_name, + const char *action_name, + const char **subaction_path) { GHOST_XrActionSet *action_set = find_action_set(m_oxr.get(), action_set_name); if (action_set == nullptr) { @@ -785,7 +789,7 @@ void GHOST_XrSession::stopHapticAction(const char *action_set_name, const char * return; } - action->stopHapticFeedback(m_oxr->session, action_name); + action->stopHapticFeedback(m_oxr->session, action_name, subaction_path); } void *GHOST_XrSession::getActionSetCustomdata(const char *action_set_name) @@ -813,4 +817,25 @@ void *GHOST_XrSession::getActionCustomdata(const char *action_set_name, const ch return action->getCustomdata(); } +uint32_t GHOST_XrSession::getActionCount(const char *action_set_name) +{ + GHOST_XrActionSet *action_set = find_action_set(m_oxr.get(), action_set_name); + if (action_set == nullptr) { + return 0; + } + + return action_set->getActionCount(); +} + +void GHOST_XrSession::getActionCustomdataArray(const char *action_set_name, + void **r_customdata_array) +{ + GHOST_XrActionSet *action_set = find_action_set(m_oxr.get(), action_set_name); + if (action_set == nullptr) { + return; + } + + action_set->getActionCustomdataArray(r_customdata_array); +} + /** \} */ /* Actions */ diff --git a/intern/ghost/intern/GHOST_XrSession.h b/intern/ghost/intern/GHOST_XrSession.h index cdeef153fb1..ec15897058f 100644 --- a/intern/ghost/intern/GHOST_XrSession.h +++ b/intern/ghost/intern/GHOST_XrSession.h @@ -76,14 +76,19 @@ class GHOST_XrSession { bool syncActions(const char *action_set_name = nullptr); bool applyHapticAction(const char *action_set_name, const char *action_name, + const char **subaction_path, const int64_t &duration, const float &frequency, const float &litude); - void stopHapticAction(const char *action_set_name, const char *action_name); + void stopHapticAction(const char *action_set_name, + const char *action_name, + const char **subaction_path); /* Custom data (owned by Blender, not GHOST) accessors. */ void *getActionSetCustomdata(const char *action_set_name); void *getActionCustomdata(const char *action_set_name, const char *action_name); + uint32_t getActionCount(const char *action_set_name); + void getActionCustomdataArray(const char *action_set_name, void **r_customdata_array); private: /** Pointer back to context managing this session. Would be nice to avoid, but needed to access diff --git a/source/blender/makesdna/DNA_xr_types.h b/source/blender/makesdna/DNA_xr_types.h index c0928e1519f..2e348ce6855 100644 --- a/source/blender/makesdna/DNA_xr_types.h +++ b/source/blender/makesdna/DNA_xr_types.h @@ -26,6 +26,8 @@ extern "C" { #endif +/* -------------------------------------------------------------------- */ + typedef struct XrSessionSettings { /** Shading settings, struct shared with 3D-View so settings are the same. */ struct View3DShading shading; @@ -68,21 +70,122 @@ typedef enum eXrActionType { XR_VIBRATION_OUTPUT = 100, } eXrActionType; +/** Determines how XR action operators are executed. */ typedef enum eXrOpFlag { XR_OP_PRESS = 0, XR_OP_RELEASE = 1, XR_OP_MODAL = 2, } eXrOpFlag; +typedef enum eXrActionFlag { + /** Action depends on two subaction paths (i.e. two-handed/bimanual action). */ + XR_ACTION_BIMANUAL = (1 << 0), +} eXrActionFlag; + +typedef enum eXrHapticFlag { + /** Whether to apply haptics to corresponding user paths for an action and its haptic action. */ + XR_HAPTIC_MATCHUSERPATHS = (1 << 0), + /** Determines how haptics will be applied ("repeat" is mutually exclusive with + "press"/"release"). */ + XR_HAPTIC_PRESS = (1 << 1), + XR_HAPTIC_RELEASE = (1 << 2), + XR_HAPTIC_REPEAT = (1 << 3), +} eXrHapticFlag; + +/** For axis-based inputs (thumbstick/trackpad/etc). Determines the region for action execution + * (mutually exclusive per axis). */ typedef enum eXrAxisFlag { - /** For axis-based inputs (thumbstick/trackpad/etc). Determines the region for action execution - (mutually exclusive per axis). */ XR_AXIS0_POS = (1 << 0), XR_AXIS0_NEG = (1 << 1), XR_AXIS1_POS = (1 << 2), XR_AXIS1_NEG = (1 << 3), } eXrAxisFlag; +typedef enum eXrPoseFlag { + /* Pose represents controller grip/aim. */ + XR_POSE_GRIP = (1 << 0), + XR_POSE_AIM = (1 << 1), +} eXrPoseFlag; + +/* -------------------------------------------------------------------- */ + +typedef struct XrActionMapBinding { + struct XrActionMapBinding *next, *prev; + + /** Unique name. */ + char name[64]; /* MAX_NAME */ + + /** OpenXR interaction profile path. */ + char profile[256]; + /** OpenXR component paths. */ + char component_path0[192]; + char component_path1[192]; + + /** Input threshold/region. */ + float float_threshold; + short axis_flag; /* eXrAxisFlag */ + char _pad[2]; + + /** Pose action properties. */ + float pose_location[3]; + float pose_rotation[3]; +} XrActionMapBinding; + +/* -------------------------------------------------------------------- */ + +typedef struct XrActionMapItem { + struct XrActionMapItem *next, *prev; + + /** Unique name. */ + char name[64]; /* MAX_NAME */ + /** Type. */ + char type; /** eXrActionType */ + char _pad[7]; + + /** OpenXR user paths. */ + char user_path0[64]; + char user_path1[64]; + + /** Operator to be called on XR events. */ + char op[64]; /* OP_MAX_TYPENAME */ + /** Operator properties, assigned to ptr->data and can be written to a file. */ + IDProperty *op_properties; + /** RNA pointer to access properties. */ + struct PointerRNA *op_properties_ptr; + + short op_flag; /* eXrOpFlag */ + short action_flag; /* eXrActionFlag */ + short haptic_flag; /* eXrHapticFlag */ + + /** Pose action properties. */ + short pose_flag; /* eXrPoseFlag */ + + /** Haptic properties. */ + char haptic_name[64]; /* MAX_NAME */ + float haptic_duration; + float haptic_frequency; + float haptic_amplitude; + + short selbinding; + char _pad3[2]; + ListBase bindings; /* XrActionMapBinding */ +} XrActionMapItem; + +/* -------------------------------------------------------------------- */ + +typedef struct XrActionMap { + struct XrActionMap *next, *prev; + + /** Unique name. */ + char name[64]; /* MAX_NAME */ + + ListBase items; /* XrActionMapItem */ + short selitem; + char _pad[6]; +} XrActionMap; + +/* -------------------------------------------------------------------- */ + #ifdef __cplusplus } #endif diff --git a/source/blender/makesrna/intern/rna_xr.c b/source/blender/makesrna/intern/rna_xr.c index 56e8418972c..358db14c298 100644 --- a/source/blender/makesrna/intern/rna_xr.c +++ b/source/blender/makesrna/intern/rna_xr.c @@ -18,9 +18,14 @@ * \ingroup RNA */ +#include "BLI_math.h" + +#include "DNA_space_types.h" #include "DNA_view3d_types.h" +#include "DNA_windowmanager_types.h" #include "DNA_xr_types.h" +#include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" @@ -30,10 +35,462 @@ #ifdef RNA_RUNTIME -# include "BLI_math.h" +# include "BLI_listbase.h" # include "WM_api.h" +/* -------------------------------------------------------------------- */ +/** \name XR Action Map + * \{ */ + +static XrActionMapBinding *rna_XrActionMapBinding_new(XrActionMapItem *ami, + const char *name, + bool replace_existing) +{ +# ifdef WITH_XR_OPENXR + return WM_xr_actionmap_binding_new(ami, name, replace_existing); +# else + UNUSED_VARS(ami, name, replace_existing); + return NULL; +# endif +} + +static XrActionMapBinding *rna_XrActionMapBinding_new_from_binding(XrActionMapItem *ami, + XrActionMapBinding *amb_src) +{ +# ifdef WITH_XR_OPENXR + return WM_xr_actionmap_binding_add_copy(ami, amb_src); +# else + UNUSED_VARS(ami, amb_src); + return NULL; +# endif +} + +static void rna_XrActionMapBinding_remove(XrActionMapItem *ami, + ReportList *reports, + PointerRNA *amb_ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapBinding *amb = amb_ptr->data; + if (WM_xr_actionmap_binding_remove(ami, amb) == false) { + BKE_reportf(reports, + RPT_ERROR, + "ActionMapBinding '%s' cannot be removed from '%s'", + amb->name, + ami->name); + return; + } + RNA_POINTER_INVALIDATE(amb_ptr); +# else + UNUSED_VARS(ami, reports, amb_ptr); +# endif +} + +static XrActionMapBinding *rna_XrActionMapBinding_find(XrActionMapItem *ami, const char *name) +{ +# ifdef WITH_XR_OPENXR + return WM_xr_actionmap_binding_find(ami, name); +# else + UNUSED_VARS(ami, name); + return NULL; +# endif +} + +static int rna_XrActionMapBinding_axis0_flag_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapBinding *amb = ptr->data; + if ((amb->axis_flag & XR_AXIS0_POS) != 0) { + return XR_AXIS0_POS; + } + if ((amb->axis_flag & XR_AXIS0_NEG) != 0) { + return XR_AXIS0_NEG; + } +# else + UNUSED_VARS(ptr); +# endif + return 0; +} + +static void rna_XrActionMapBinding_axis0_flag_set(PointerRNA *ptr, int value) +{ +# ifdef WITH_XR_OPENXR + XrActionMapBinding *amb = ptr->data; + amb->axis_flag &= ~(XR_AXIS0_POS | XR_AXIS0_NEG); + amb->axis_flag |= value; +# else + UNUSED_VARS(ptr, value); +# endif +} + +static int rna_XrActionMapBinding_axis1_flag_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapBinding *amb = ptr->data; + if ((amb->axis_flag & XR_AXIS1_POS) != 0) { + return XR_AXIS1_POS; + } + if ((amb->axis_flag & XR_AXIS1_NEG) != 0) { + return XR_AXIS1_NEG; + } +# else + UNUSED_VARS(ptr); +# endif + return 0; +} + +static void rna_XrActionMapBinding_axis1_flag_set(PointerRNA *ptr, int value) +{ +# ifdef WITH_XR_OPENXR + XrActionMapBinding *amb = ptr->data; + amb->axis_flag &= ~(XR_AXIS1_POS | XR_AXIS1_NEG); + amb->axis_flag |= value; +# else + UNUSED_VARS(ptr, value); +# endif +} + +static void rna_XrActionMapBinding_name_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = bmain->wm.first; + if (wm && wm->xr.runtime) { + ListBase *actionmaps = WM_xr_actionmaps_get(wm->xr.runtime); + short idx = WM_xr_actionmap_selected_index_get(wm->xr.runtime); + XrActionMap *actionmap = BLI_findlink(actionmaps, idx); + if (actionmap) { + XrActionMapItem *ami = BLI_findlink(&actionmap->items, actionmap->selitem); + if (ami) { + XrActionMapBinding *amb = ptr->data; + WM_xr_actionmap_binding_ensure_unique(ami, amb); + } + } + } +# else + UNUSED_VARS(bmain, ptr); +# endif +} + +static XrActionMapItem *rna_XrActionMapItem_new(XrActionMap *am, + const char *name, + bool replace_existing) +{ +# ifdef WITH_XR_OPENXR + return WM_xr_actionmap_item_new(am, name, replace_existing); +# else + UNUSED_VARS(am, name, replace_existing); + return NULL; +# endif +} + +static XrActionMapItem *rna_XrActionMapItem_new_from_item(XrActionMap *am, + XrActionMapItem *ami_src) +{ +# ifdef WITH_XR_OPENXR + return WM_xr_actionmap_item_add_copy(am, ami_src); +# else + UNUSED_VARS(am, ami_src); + return NULL; +# endif +} + +static void rna_XrActionMapItem_remove(XrActionMap *am, ReportList *reports, PointerRNA *ami_ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ami_ptr->data; + if (WM_xr_actionmap_item_remove(am, ami) == false) { + BKE_reportf( + reports, RPT_ERROR, "ActionMapItem '%s' cannot be removed from '%s'", ami->name, am->name); + return; + } + RNA_POINTER_INVALIDATE(ami_ptr); +# else + UNUSED_VARS(am, reports, ami_ptr); +# endif +} + +static XrActionMapItem *rna_XrActionMapItem_find(XrActionMap *am, const char *name) +{ +# ifdef WITH_XR_OPENXR + return WM_xr_actionmap_item_find(am, name); +# else + UNUSED_VARS(am, name); + return NULL; +# endif +} + +static void rna_XrActionMapItem_op_name_get(PointerRNA *ptr, char *value) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + if (ami->op[0]) { + if (ami->op_properties_ptr) { + wmOperatorType *ot = WM_operatortype_find(ami->op, 1); + if (ot) { + strcpy(value, WM_operatortype_name(ot, ami->op_properties_ptr)); + return; + } + } + strcpy(value, ami->op); + return; + } +# else + UNUSED_VARS(ptr); +# endif + value[0] = '\0'; +} + +static int rna_XrActionMapItem_op_name_length(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + if (ami->op[0]) { + if (ami->op_properties_ptr) { + wmOperatorType *ot = WM_operatortype_find(ami->op, 1); + if (ot) { + return strlen(WM_operatortype_name(ot, ami->op_properties_ptr)); + } + } + return strlen(ami->op); + } +# else + UNUSED_VARS(ptr); +# endif + return 0; +} + +static PointerRNA rna_XrActionMapItem_op_properties_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + if (ami->op_properties_ptr) { + return *(ami->op_properties_ptr); + } +# else + UNUSED_VARS(ptr); +# endif + return PointerRNA_NULL; +} + +static bool rna_XrActionMapItem_bimanual_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + if ((ami->action_flag & XR_ACTION_BIMANUAL) != 0) { + return true; + } +# else + UNUSED_VARS(ptr); +# endif + return false; +} + +static void rna_XrActionMapItem_bimanual_set(PointerRNA *ptr, bool value) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + if (value) { + ami->action_flag |= XR_ACTION_BIMANUAL; + } + else { + ami->action_flag &= ~XR_ACTION_BIMANUAL; + } +# else + UNUSED_VARS(ptr, value); +# endif +} + +static bool rna_XrActionMapItem_haptic_match_user_paths_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + if ((ami->haptic_flag & XR_HAPTIC_MATCHUSERPATHS) != 0) { + return true; + } +# else + UNUSED_VARS(ptr); +# endif + return false; +} + +static void rna_XrActionMapItem_haptic_match_user_paths_set(PointerRNA *ptr, bool value) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + if (value) { + ami->haptic_flag |= XR_HAPTIC_MATCHUSERPATHS; + } + else { + ami->haptic_flag &= ~XR_HAPTIC_MATCHUSERPATHS; + } +# else + UNUSED_VARS(ptr, value); +# endif +} + +static int rna_XrActionMapItem_haptic_flag_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + if ((ami->haptic_flag & XR_HAPTIC_RELEASE) != 0) { + return ((ami->haptic_flag & XR_HAPTIC_PRESS) != 0) ? (XR_HAPTIC_PRESS | XR_HAPTIC_RELEASE) : + XR_HAPTIC_RELEASE; + } + if ((ami->haptic_flag & XR_HAPTIC_REPEAT) != 0) { + return XR_HAPTIC_REPEAT; + } +# else + UNUSED_VARS(ptr); +# endif + return XR_HAPTIC_PRESS; +} + +static void rna_XrActionMapItem_haptic_flag_set(PointerRNA *ptr, int value) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + ami->haptic_flag &= ~(XR_HAPTIC_PRESS | XR_HAPTIC_RELEASE | XR_HAPTIC_REPEAT); + ami->haptic_flag |= value; +# else + UNUSED_VARS(ptr, value); +# endif +} + +static bool rna_XrActionMapItem_pose_is_controller_grip_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + if ((ami->pose_flag & XR_POSE_GRIP) != 0) { + return true; + } +# else + UNUSED_VARS(ptr); +# endif + return false; +} + +static void rna_XrActionMapItem_pose_is_controller_grip_set(PointerRNA *ptr, bool value) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + SET_FLAG_FROM_TEST(ami->pose_flag, value, XR_POSE_GRIP); +# else + UNUSED_VARS(ptr, value); +# endif +} + +static bool rna_XrActionMapItem_pose_is_controller_aim_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + if ((ami->pose_flag & XR_POSE_AIM) != 0) { + return true; + } +# else + UNUSED_VARS(ptr); +# endif + return false; +} + +static void rna_XrActionMapItem_pose_is_controller_aim_set(PointerRNA *ptr, bool value) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + SET_FLAG_FROM_TEST(ami->pose_flag, value, XR_POSE_AIM); +# else + UNUSED_VARS(ptr, value); +# endif +} + +static void rna_XrActionMapItem_name_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = bmain->wm.first; + if (wm && wm->xr.runtime) { + ListBase *actionmaps = WM_xr_actionmaps_get(wm->xr.runtime); + short idx = WM_xr_actionmap_selected_index_get(wm->xr.runtime); + XrActionMap *actionmap = BLI_findlink(actionmaps, idx); + if (actionmap) { + XrActionMapItem *ami = ptr->data; + WM_xr_actionmap_item_ensure_unique(actionmap, ami); + } + } +# else + UNUSED_VARS(bmain, ptr); +# endif +} + +static void rna_XrActionMapItem_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + WM_xr_actionmap_item_properties_update_ot(ami); +# else + UNUSED_VARS(ptr); +# endif +} + +static XrActionMap *rna_XrActionMap_new(wmXrData *xr, const char *name, bool replace_existing) +{ +# ifdef WITH_XR_OPENXR + return WM_xr_actionmap_new(xr->runtime, name, replace_existing); +# else + UNUSED_VARS(xr, name, replace_existing); + return NULL; +# endif +} + +static XrActionMap *rna_XrActionMap_new_from_actionmap(wmXrData *xr, XrActionMap *am_src) +{ +# ifdef WITH_XR_OPENXR + return WM_xr_actionmap_add_copy(xr->runtime, am_src); +# else + UNUSED_VARS(xr, am_src); + return NULL; +# endif +} + +static void rna_XrActionMap_remove(wmXrData *xr, ReportList *reports, PointerRNA *actionmap_ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMap *actionmap = actionmap_ptr->data; + if (WM_xr_actionmap_remove(xr->runtime, actionmap) == false) { + BKE_reportf(reports, RPT_ERROR, "ActionMap '%s' cannot be removed", actionmap->name); + return; + } + RNA_POINTER_INVALIDATE(actionmap_ptr); +# else + UNUSED_VARS(xr, reports, actionmap_ptr); +# endif +} + +static XrActionMap *rna_XrActionMap_find(wmXrData *xr, const char *name) +{ +# ifdef WITH_XR_OPENXR + return WM_xr_actionmap_find(xr->runtime, name); +# else + UNUSED_VARS(xr, name); + return NULL; +# endif +} + +static void rna_XrActionMap_name_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = bmain->wm.first; + if (wm && wm->xr.runtime) { + XrActionMap *actionmap = ptr->data; + WM_xr_actionmap_ensure_unique(wm->xr.runtime, actionmap); + } +# else + UNUSED_VARS(bmain, ptr); +# endif +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + # ifdef WITH_XR_OPENXR static wmXrData *rna_XrSession_wm_xr_data_get(PointerRNA *ptr) { @@ -49,93 +506,879 @@ static wmXrData *rna_XrSession_wm_xr_data_get(PointerRNA *ptr) } # endif -static bool rna_XrSessionSettings_use_positional_tracking_get(PointerRNA *ptr) +/* -------------------------------------------------------------------- */ +/** \name XR Session Settings + * \{ */ + +static bool rna_XrSessionSettings_use_positional_tracking_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + const wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); + return (xr->session_settings.flag & XR_SESSION_USE_POSITION_TRACKING) != 0; +# else + UNUSED_VARS(ptr); + return false; +# endif +} + +static void rna_XrSessionSettings_use_positional_tracking_set(PointerRNA *ptr, bool value) +{ +# ifdef WITH_XR_OPENXR + wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); + SET_FLAG_FROM_TEST(xr->session_settings.flag, value, XR_SESSION_USE_POSITION_TRACKING); +# else + UNUSED_VARS(ptr, value); +# endif +} + +static bool rna_XrSessionSettings_use_absolute_tracking_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + const wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); + return (xr->session_settings.flag & XR_SESSION_USE_ABSOLUTE_TRACKING) != 0; +# else + UNUSED_VARS(ptr); + return false; +# endif +} + +static void rna_XrSessionSettings_use_absolute_tracking_set(PointerRNA *ptr, bool value) +{ +# ifdef WITH_XR_OPENXR + wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); + SET_FLAG_FROM_TEST(xr->session_settings.flag, value, XR_SESSION_USE_ABSOLUTE_TRACKING); +# else + UNUSED_VARS(ptr, value); +# endif +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name XR Session State + * \{ */ + +static bool rna_XrSessionState_is_running(bContext *C) +{ +# ifdef WITH_XR_OPENXR + const wmWindowManager *wm = CTX_wm_manager(C); + return WM_xr_session_exists(&wm->xr); +# else + UNUSED_VARS(C); + return false; +# endif +} + +static void rna_XrSessionState_reset_to_base_pose(bContext *C) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = CTX_wm_manager(C); + WM_xr_session_base_pose_reset(&wm->xr); +# else + UNUSED_VARS(C); +# endif +} + +static bool rna_XrSessionState_action_set_create(bContext *C, XrActionMap *actionmap) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = CTX_wm_manager(C); + return WM_xr_action_set_create(&wm->xr, actionmap->name); +# else + UNUSED_VARS(C, actionmap); + return false; +# endif +} + +static bool rna_XrSessionState_action_create(bContext *C, + XrActionMap *actionmap, + XrActionMapItem *ami) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = CTX_wm_manager(C); + unsigned int count_subaction_paths = 0; + const char *subaction_paths[2]; + + if (ami->user_path0[0]) { + subaction_paths[0] = ami->user_path0; + ++count_subaction_paths; + + if (ami->user_path1[0]) { + subaction_paths[1] = ami->user_path1; + ++count_subaction_paths; + } + } + else { + if (ami->user_path1[0]) { + subaction_paths[0] = ami->user_path1; + ++count_subaction_paths; + } + else { + return false; + } + } + + const bool is_float_action = (ami->type == XR_FLOAT_INPUT || ami->type == XR_VECTOR2F_INPUT); + const bool is_button_action = (is_float_action || ami->type == XR_BOOLEAN_INPUT); + wmOperatorType *ot = NULL; + IDProperty *op_properties = NULL; + const char *haptic_name = NULL; + int64_t haptic_duration_msec; + + if (is_button_action) { + if (ami->op[0]) { + char idname[OP_MAX_TYPENAME]; + WM_operator_bl_idname(idname, ami->op); + ot = WM_operatortype_find(idname, true); + if (ot) { + op_properties = ami->op_properties; + } + } + + haptic_name = &ami->haptic_name[0]; + haptic_duration_msec = (int64_t)(ami->haptic_duration * 1000.0f); + } + + return WM_xr_action_create(&wm->xr, + actionmap->name, + ami->name, + ami->type, + count_subaction_paths, + subaction_paths, + ot, + op_properties, + is_button_action ? &haptic_name : NULL, + is_button_action ? &haptic_duration_msec : NULL, + is_button_action ? &ami->haptic_frequency : NULL, + is_button_action ? &ami->haptic_amplitude : NULL, + ami->op_flag, + ami->action_flag, + ami->haptic_flag); +# else + UNUSED_VARS(C, actionmap, ami); + return false; +# endif +} + +static bool rna_XrSessionState_action_binding_create(bContext *C, + XrActionMap *actionmap, + XrActionMapItem *ami, + XrActionMapBinding *amb) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = CTX_wm_manager(C); + unsigned int count_subaction_paths = 0; + const char *subaction_paths[2]; + const char *component_paths[2]; + + if (ami->user_path0[0]) { + subaction_paths[0] = ami->user_path0; + component_paths[0] = amb->component_path0; + ++count_subaction_paths; + + if (ami->user_path1[0]) { + subaction_paths[1] = ami->user_path1; + component_paths[1] = amb->component_path1; + ++count_subaction_paths; + } + } + else { + if (ami->user_path1[0]) { + subaction_paths[0] = ami->user_path1; + component_paths[0] = amb->component_path1; + ++count_subaction_paths; + } + else { + return false; + } + } + + const bool is_float_action = (ami->type == XR_FLOAT_INPUT || ami->type == XR_VECTOR2F_INPUT); + const bool is_button_action = (is_float_action || ami->type == XR_BOOLEAN_INPUT); + const bool is_pose_action = (ami->type == XR_POSE_INPUT); + float float_thresholds[2]; + eXrAxisFlag axis_flags[2]; + wmXrPose poses[2]; + + if (is_float_action) { + float_thresholds[0] = float_thresholds[1] = amb->float_threshold; + } + if (is_button_action) { + axis_flags[0] = axis_flags[1] = amb->axis_flag; + } + if (is_pose_action) { + copy_v3_v3(poses[0].position, amb->pose_location); + eul_to_quat(poses[0].orientation_quat, amb->pose_rotation); + normalize_qt(poses[0].orientation_quat); + memcpy(&poses[1], &poses[0], sizeof(poses[1])); + } + + return WM_xr_action_binding_create(&wm->xr, + actionmap->name, + ami->name, + amb->profile, + count_subaction_paths, + subaction_paths, + component_paths, + is_float_action ? float_thresholds : NULL, + is_button_action ? axis_flags : NULL, + is_pose_action ? poses : NULL); +# else + UNUSED_VARS(C, actionmap, ami, amb); + return false; +# endif +} + +bool rna_XrSessionState_active_action_set_set(bContext *C, const char *action_set_name) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = CTX_wm_manager(C); + return WM_xr_active_action_set_set(&wm->xr, action_set_name); +# else + UNUSED_VARS(C, action_set_name); + return false; +# endif +} + +bool rna_XrSessionState_controller_pose_actions_set(bContext *C, + const char *action_set_name, + const char *grip_action_name, + const char *aim_action_name) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = CTX_wm_manager(C); + return WM_xr_controller_pose_actions_set( + &wm->xr, action_set_name, grip_action_name, aim_action_name); +# else + UNUSED_VARS(C, action_set_name, grip_action_name, aim_action_name); + return false; +# endif +} + +void rna_XrSessionState_action_state_get(bContext *C, + const char *action_set_name, + const char *action_name, + const char *user_path, + float r_state[2]) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = CTX_wm_manager(C); + wmXrActionState state; + if (WM_xr_action_state_get(&wm->xr, action_set_name, action_name, user_path, &state)) { + switch (state.type) { + case XR_BOOLEAN_INPUT: + r_state[0] = (float)state.state_boolean; + r_state[1] = 0.0f; + return; + case XR_FLOAT_INPUT: + r_state[0] = state.state_float; + r_state[1] = 0.0f; + return; + case XR_VECTOR2F_INPUT: + copy_v2_v2(r_state, state.state_vector2f); + return; + case XR_POSE_INPUT: + case XR_VIBRATION_OUTPUT: + BLI_assert_unreachable(); + break; + } + } +# else + UNUSED_VARS(C, action_set_name, action_name, user_path); +# endif + zero_v2(r_state); +} + +bool rna_XrSessionState_haptic_action_apply(bContext *C, + const char *action_set_name, + const char *action_name, + const char *user_path, + float duration, + float frequency, + float amplitude) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = CTX_wm_manager(C); + int64_t duration_msec = (int64_t)(duration * 1000.0f); + return WM_xr_haptic_action_apply(&wm->xr, + action_set_name, + action_name, + user_path[0] ? &user_path : NULL, + &duration_msec, + &frequency, + &litude); +# else + UNUSED_VARS(C, action_set_name, action_name, user_path, duration, frequency, amplitude); + return false; +# endif +} + +void rna_XrSessionState_haptic_action_stop(bContext *C, + const char *action_set_name, + const char *action_name, + const char *user_path) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = CTX_wm_manager(C); + WM_xr_haptic_action_stop( + &wm->xr, action_set_name, action_name, user_path[0] ? &user_path : NULL); +# else + UNUSED_VARS(C, action_set_name, action_name, user_path); +# endif +} + +static void rna_XrSessionState_controller_grip_location_get(bContext *C, + int *index, + float *r_values) +{ +# ifdef WITH_XR_OPENXR + const wmWindowManager *wm = CTX_wm_manager(C); + WM_xr_session_state_controller_grip_location_get(&wm->xr, *index, r_values); +# else + UNUSED_VARS(C, index); + zero_v3(r_values); +# endif +} + +static void rna_XrSessionState_controller_grip_rotation_get(bContext *C, + int index, + float *r_values) +{ +# ifdef WITH_XR_OPENXR + const wmWindowManager *wm = CTX_wm_manager(C); + WM_xr_session_state_controller_grip_rotation_get(&wm->xr, index, r_values); +# else + UNUSED_VARS(C, index); + unit_qt(r_values); +# endif +} + +static void rna_XrSessionState_controller_aim_location_get(bContext *C, + int *index, + float *r_values) { # ifdef WITH_XR_OPENXR - const wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); - return (xr->session_settings.flag & XR_SESSION_USE_POSITION_TRACKING) != 0; + const wmWindowManager *wm = CTX_wm_manager(C); + WM_xr_session_state_controller_aim_location_get(&wm->xr, *index, r_values); # else - UNUSED_VARS(ptr); - return false; + UNUSED_VARS(C, index); + zero_v3(r_values); # endif } -static void rna_XrSessionSettings_use_positional_tracking_set(PointerRNA *ptr, bool value) +static void rna_XrSessionState_controller_aim_rotation_get(bContext *C, int index, float *r_values) { # ifdef WITH_XR_OPENXR - wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); - SET_FLAG_FROM_TEST(xr->session_settings.flag, value, XR_SESSION_USE_POSITION_TRACKING); + const wmWindowManager *wm = CTX_wm_manager(C); + WM_xr_session_state_controller_aim_rotation_get(&wm->xr, index, r_values); # else - UNUSED_VARS(ptr, value); + UNUSED_VARS(C, index); + unit_qt(r_values); # endif } -static bool rna_XrSessionSettings_use_absolute_tracking_get(PointerRNA *ptr) +static void rna_XrSessionState_viewer_pose_location_get(PointerRNA *ptr, float *r_values) { # ifdef WITH_XR_OPENXR const wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); - return (xr->session_settings.flag & XR_SESSION_USE_ABSOLUTE_TRACKING) != 0; + WM_xr_session_state_viewer_pose_location_get(xr, r_values); # else UNUSED_VARS(ptr); - return false; + zero_v3(r_values); # endif } -static void rna_XrSessionSettings_use_absolute_tracking_set(PointerRNA *ptr, bool value) +static void rna_XrSessionState_viewer_pose_rotation_get(PointerRNA *ptr, float *r_values) { # ifdef WITH_XR_OPENXR - wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); - SET_FLAG_FROM_TEST(xr->session_settings.flag, value, XR_SESSION_USE_ABSOLUTE_TRACKING); + const wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); + WM_xr_session_state_viewer_pose_rotation_get(xr, r_values); # else - UNUSED_VARS(ptr, value); + UNUSED_VARS(ptr); + unit_qt(r_values); # endif } -static bool rna_XrSessionState_is_running(bContext *C) +static void rna_XrSessionState_actionmaps_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); + ListBase *lb = WM_xr_actionmaps_get(xr->runtime); + rna_iterator_listbase_begin(iter, lb, NULL); +} + +static int rna_XrSessionState_active_actionmap_get(PointerRNA *ptr) { # ifdef WITH_XR_OPENXR - const wmWindowManager *wm = CTX_wm_manager(C); - return WM_xr_session_exists(&wm->xr); + const wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); + return WM_xr_actionmap_active_index_get(xr->runtime); # else - UNUSED_VARS(C); - return false; + UNUSED_VARS(ptr); + return -1; # endif } -static void rna_XrSessionState_reset_to_base_pose(bContext *C) +static void rna_XrSessionState_active_actionmap_set(PointerRNA *ptr, int value) { # ifdef WITH_XR_OPENXR - wmWindowManager *wm = CTX_wm_manager(C); - WM_xr_session_base_pose_reset(&wm->xr); + wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); + WM_xr_actionmap_active_index_set(xr->runtime, (short)value); # else - UNUSED_VARS(C); + UNUSED_VARS(ptr, value); # endif } -static void rna_XrSessionState_viewer_pose_location_get(PointerRNA *ptr, float *r_values) +static int rna_XrSessionState_selected_actionmap_get(PointerRNA *ptr) { # ifdef WITH_XR_OPENXR const wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); - WM_xr_session_state_viewer_pose_location_get(xr, r_values); + return WM_xr_actionmap_selected_index_get(xr->runtime); # else UNUSED_VARS(ptr); - zero_v3(r_values); + return -1; # endif } -static void rna_XrSessionState_viewer_pose_rotation_get(PointerRNA *ptr, float *r_values) +static void rna_XrSessionState_selected_actionmap_set(PointerRNA *ptr, int value) { # ifdef WITH_XR_OPENXR - const wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); - WM_xr_session_state_viewer_pose_rotation_get(xr, r_values); + wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); + WM_xr_actionmap_selected_index_set(xr->runtime, (short)value); # else - UNUSED_VARS(ptr); - unit_qt(r_values); + UNUSED_VARS(ptr, value); # endif } +/** \} */ + #else /* RNA_RUNTIME */ +/* -------------------------------------------------------------------- */ + +static const EnumPropertyItem rna_enum_xr_action_types[] = { + {XR_FLOAT_INPUT, + "FLOAT", + 0, + "Float", + "Float action, representing either a digital or analog button"}, + {XR_VECTOR2F_INPUT, + "VECTOR2D", + 0, + "Vector2D", + "2D float vector action, representing a thumbstick or trackpad"}, + {XR_POSE_INPUT, + "POSE", + 0, + "Pose", + "3D pose action, representing a controller's location and rotation"}, + {XR_VIBRATION_OUTPUT, + "VIBRATION", + 0, + "Vibration", + "Haptic vibration output action, to be applied with a duration, frequency, and amplitude"}, + {0, NULL, 0, NULL, NULL}, +}; + +static const EnumPropertyItem rna_enum_xr_op_flags[] = { + {XR_OP_PRESS, + "PRESS", + 0, + "Press", + "Execute operator on button press (non-modal operators only)"}, + {XR_OP_RELEASE, + "RELEASE", + 0, + "Release", + "Execute operator on button release (non-modal operators only)"}, + {XR_OP_MODAL, "MODAL", 0, "Modal", "Use modal execution (modal operators only)"}, + {0, NULL, 0, NULL, NULL}, +}; + +static const EnumPropertyItem rna_enum_xr_haptic_flags[] = { + {XR_HAPTIC_PRESS, "PRESS", 0, "Press", "Apply haptics on button press"}, + {XR_HAPTIC_RELEASE, "RELEASE", 0, "Release", "Apply haptics on button release"}, + {XR_HAPTIC_PRESS | XR_HAPTIC_RELEASE, + "PRESS_RELEASE", + 0, + "Press Release", + "Apply haptics on button press and release"}, + {XR_HAPTIC_REPEAT, + "REPEAT", + 0, + "Repeat", + "Apply haptics repeatedly for the duration of the button press"}, + {0, NULL, 0, NULL, NULL}, +}; + +static const EnumPropertyItem rna_enum_xr_axis0_flags[] = { + {0, "ANY", 0, "Any", "Use any axis region for operator execution"}, + {XR_AXIS0_POS, + "POSITIVE", + 0, + "Positive", + "Use positive axis region only for operator execution"}, + {XR_AXIS0_NEG, + "NEGATIVE", + 0, + "Negative", + "Use negative axis region only for operator execution"}, + {0, NULL, 0, NULL, NULL}, +}; + +static const EnumPropertyItem rna_enum_xr_axis1_flags[] = { + {0, "ANY", 0, "Any", "Use any axis region for operator execution"}, + {XR_AXIS1_POS, + "POSITIVE", + 0, + "Positive", + "Use positive axis region only for operator execution"}, + {XR_AXIS1_NEG, + "NEGATIVE", + 0, + "Negative", + "Use negative axis region only for operator execution"}, + {0, NULL, 0, NULL, NULL}, +}; + +/* -------------------------------------------------------------------- */ +/** \name XR Action Map + * \{ */ + +static void rna_def_xr_actionmap_bindings(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "XrActionMapBindings"); + srna = RNA_def_struct(brna, "XrActionMapBindings", NULL); + RNA_def_struct_sdna(srna, "XrActionMapItem"); + RNA_def_struct_ui_text(srna, "XR Action Map Bindings", "Collection of XR action map bindings"); + + func = RNA_def_function(srna, "new", "rna_XrActionMapBinding_new"); + parm = RNA_def_string(func, "name", NULL, 0, "Name of the action map binding", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_boolean(func, + "replace_existing", + true, + "Replace Existing", + "Replace any existing binding with the same name"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer( + func, "binding", "XrActionMapBinding", "Binding", "Added action map binding"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "new_from_binding", "rna_XrActionMapBinding_new_from_binding"); + parm = RNA_def_pointer( + func, "binding", "XrActionMapBinding", "Binding", "Binding to use as a reference"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer( + func, "result", "XrActionMapBinding", "Binding", "Added action map binding"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_XrActionMapBinding_remove"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "binding", "XrActionMapBinding", "Binding", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); + + func = RNA_def_function(srna, "find", "rna_XrActionMapBinding_find"); + parm = RNA_def_string(func, "name", NULL, MAX_NAME, "Name", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer(func, + "binding", + "XrActionMapBinding", + "Binding", + "The action map binding with the given name"); + RNA_def_function_return(func, parm); +} + +static void rna_def_xr_actionmap_items(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "XrActionMapItems"); + srna = RNA_def_struct(brna, "XrActionMapItems", NULL); + RNA_def_struct_sdna(srna, "XrActionMap"); + RNA_def_struct_ui_text(srna, "XR Action Map Items", "Collection of XR action map items"); + + func = RNA_def_function(srna, "new", "rna_XrActionMapItem_new"); + parm = RNA_def_string(func, "name", NULL, 0, "Name of the action map item", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_boolean(func, + "replace_existing", + true, + "Replace Existing", + "Replace any existing item with the same name"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer(func, "item", "XrActionMapItem", "Item", "Added action map item"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "new_from_item", "rna_XrActionMapItem_new_from_item"); + parm = RNA_def_pointer(func, "item", "XrActionMapItem", "Item", "Item to use as a reference"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "result", "XrActionMapItem", "Item", "Added action map item"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_XrActionMapItem_remove"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "item", "XrActionMapItem", "Item", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); + + func = RNA_def_function(srna, "find", "rna_XrActionMapItem_find"); + parm = RNA_def_string(func, "name", NULL, MAX_NAME, "Name", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer( + func, "item", "XrActionMapItem", "Item", "The action map item with the given name"); + RNA_def_function_return(func, parm); +} + +static void rna_def_xr_actionmaps(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "XrActionMaps"); + srna = RNA_def_struct(brna, "XrActionMaps", NULL); + RNA_def_struct_sdna(srna, "wmXrData"); + RNA_def_struct_ui_text(srna, "XR Action Maps", "Collection of XR action maps"); + + func = RNA_def_function(srna, "new", "rna_XrActionMap_new"); + parm = RNA_def_string(func, "name", NULL, MAX_NAME, "Name", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_boolean(func, + "replace_existing", + true, + "Replace Existing", + "Replace any existing actionmap with the same name"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer(func, "actionmap", "XrActionMap", "Action Map", "Added action map"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "new_from_actionmap", "rna_XrActionMap_new_from_actionmap"); + parm = RNA_def_pointer( + func, "actionmap", "XrActionMap", "Action Map", "Action map to use as a reference"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "result", "XrActionMap", "Action Map", "Added action map"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_XrActionMap_remove"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "actionmap", "XrActionMap", "Action Map", "Removed action map"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); + + func = RNA_def_function(srna, "find", "rna_XrActionMap_find"); + parm = RNA_def_string(func, "name", NULL, MAX_NAME, "Name", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer( + func, "actionmap", "XrActionMap", "Action Map", "The action map with the given name"); + RNA_def_function_return(func, parm); +} + +static void rna_def_xr_actionmap(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + /* XrActionMap */ + srna = RNA_def_struct(brna, "XrActionMap", NULL); + RNA_def_struct_sdna(srna, "XrActionMap"); + RNA_def_struct_ui_text(srna, "XR Action Map", ""); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Name", "Name of the action map"); + RNA_def_property_update(prop, 0, "rna_XrActionMap_name_update"); + RNA_def_struct_name_property(srna, prop); + + prop = RNA_def_property(srna, "actionmap_items", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "items", NULL); + RNA_def_property_struct_type(prop, "XrActionMapItem"); + RNA_def_property_ui_text( + prop, + "Items", + "Items in the action map, mapping an XR event to an operator, pose, or haptic output"); + rna_def_xr_actionmap_items(brna, prop); + + prop = RNA_def_property(srna, "selected_item", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "selitem"); + RNA_def_property_ui_text(prop, "Selected Item", ""); + + /* XrActionMapItem */ + srna = RNA_def_struct(brna, "XrActionMapItem", NULL); + RNA_def_struct_sdna(srna, "XrActionMapItem"); + RNA_def_struct_ui_text(srna, "XR Action Map Item", ""); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Name", "Name of the action map item"); + RNA_def_property_update(prop, 0, "rna_XrActionMapItem_name_update"); + RNA_def_struct_name_property(srna, prop); + + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_enum_xr_action_types); + RNA_def_property_ui_text(prop, "Type", "Action type"); + RNA_def_property_update(prop, 0, "rna_XrActionMapItem_update"); + + prop = RNA_def_property(srna, "user_path0", PROP_STRING, PROP_NONE); + RNA_def_property_string_maxlength(prop, 64); + RNA_def_property_ui_text(prop, "User Path 0", "OpenXR user path"); + + prop = RNA_def_property(srna, "user_path1", PROP_STRING, PROP_NONE); + RNA_def_property_string_maxlength(prop, 64); + RNA_def_property_ui_text(prop, "User Path 1", "OpenXR user path"); + + prop = RNA_def_property(srna, "op", PROP_STRING, PROP_NONE); + RNA_def_property_string_maxlength(prop, OP_MAX_TYPENAME); + RNA_def_property_ui_text(prop, "Operator", "Identifier of operator to call on action event"); + RNA_def_property_update(prop, 0, "rna_XrActionMapItem_update"); + + prop = RNA_def_property(srna, "op_name", PROP_STRING, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text( + prop, "Operator Name", "Name of operator (translated) to call on action event"); + RNA_def_property_string_funcs( + prop, "rna_XrActionMapItem_op_name_get", "rna_XrActionMapItem_op_name_length", NULL); + + prop = RNA_def_property(srna, "op_properties", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "OperatorProperties"); + RNA_def_property_pointer_funcs(prop, "rna_XrActionMapItem_op_properties_get", NULL, NULL, NULL); + RNA_def_property_ui_text( + prop, "Operator Properties", "Properties to set when the operator is called"); + RNA_def_property_update(prop, 0, "rna_XrActionMapItem_update"); + + prop = RNA_def_property(srna, "op_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "op_flag"); + RNA_def_property_enum_items(prop, rna_enum_xr_op_flags); + RNA_def_property_ui_text(prop, "Operator Mode", "Operator execution mode"); + + prop = RNA_def_property(srna, "bimanual", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs( + prop, "rna_XrActionMapItem_bimanual_get", "rna_XrActionMapItem_bimanual_set"); + RNA_def_property_ui_text( + prop, "Bimanual", "The action depends on the states/poses of both user paths"); + + prop = RNA_def_property(srna, "pose_is_controller_grip", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, + "rna_XrActionMapItem_pose_is_controller_grip_get", + "rna_XrActionMapItem_pose_is_controller_grip_set"); + RNA_def_property_ui_text( + prop, "Is Controller Grip", "The action poses will be used for the VR controller grips"); + + prop = RNA_def_property(srna, "pose_is_controller_aim", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, + "rna_XrActionMapItem_pose_is_controller_aim_get", + "rna_XrActionMapItem_pose_is_controller_aim_set"); + RNA_def_property_ui_text( + prop, "Is Controller Aim", "The action poses will be used for the VR controller aims"); + + prop = RNA_def_property(srna, "haptic_name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text( + prop, "Haptic Name", "Name of the haptic action to apply when executing this action"); + + prop = RNA_def_property(srna, "haptic_match_user_paths", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, + "rna_XrActionMapItem_haptic_match_user_paths_get", + "rna_XrActionMapItem_haptic_match_user_paths_set"); + RNA_def_property_ui_text( + prop, + "Haptic Match User Paths", + "Apply haptics to the same user paths for the haptic action and this action"); + + prop = RNA_def_property(srna, "haptic_duration", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.0, FLT_MAX); + RNA_def_property_ui_text(prop, + "Haptic Duration", + "Haptic duration in seconds. 0.0 is the minimum supported duration"); + + prop = RNA_def_property(srna, "haptic_frequency", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.0, FLT_MAX); + RNA_def_property_ui_text(prop, + "Haptic Frequency", + "Frequency of the haptic vibration in hertz. 0.0 specifies the OpenXR " + "runtime's default frequency"); + + prop = RNA_def_property(srna, "haptic_amplitude", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_ui_text( + prop, "Haptic Amplitude", "Intensity of the haptic vibration, ranging from 0.0 to 1.0"); + + prop = RNA_def_property(srna, "haptic_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_enum_xr_haptic_flags); + RNA_def_property_enum_funcs( + prop, "rna_XrActionMapItem_haptic_flag_get", "rna_XrActionMapItem_haptic_flag_set", NULL); + RNA_def_property_ui_text(prop, "Haptic mode", "Haptic application mode"); + + prop = RNA_def_property(srna, "bindings", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "XrActionMapBinding"); + RNA_def_property_ui_text( + prop, "Bindings", "Bindings for the action map item, mapping the action to an XR input"); + rna_def_xr_actionmap_bindings(brna, prop); + + prop = RNA_def_property(srna, "selected_binding", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "selbinding"); + RNA_def_property_ui_text(prop, "Selected Binding", "Currently selected binding"); + + /* XrActionMapBinding */ + srna = RNA_def_struct(brna, "XrActionMapBinding", NULL); + RNA_def_struct_sdna(srna, "XrActionMapBinding"); + RNA_def_struct_ui_text(srna, "XR Action Map Binding", "Binding in an XR action map item"); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Name", "Name of the action map binding"); + RNA_def_property_update(prop, 0, "rna_XrActionMapBinding_name_update"); + RNA_def_struct_name_property(srna, prop); + + prop = RNA_def_property(srna, "profile", PROP_STRING, PROP_NONE); + RNA_def_property_string_maxlength(prop, 256); + RNA_def_property_ui_text(prop, "Profile", "OpenXR interaction profile path"); + + prop = RNA_def_property(srna, "component_path0", PROP_STRING, PROP_NONE); + RNA_def_property_string_maxlength(prop, 192); + RNA_def_property_ui_text(prop, "Component Path 0", "OpenXR component path"); + + prop = RNA_def_property(srna, "component_path1", PROP_STRING, PROP_NONE); + RNA_def_property_string_maxlength(prop, 192); + RNA_def_property_ui_text(prop, "Component Path 1", "OpenXR component path"); + + prop = RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "float_threshold"); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_ui_text(prop, "Threshold", "Input threshold for button/axis actions"); + + prop = RNA_def_property(srna, "axis0_region", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_enum_xr_axis0_flags); + RNA_def_property_enum_funcs(prop, + "rna_XrActionMapBinding_axis0_flag_get", + "rna_XrActionMapBinding_axis0_flag_set", + NULL); + RNA_def_property_ui_text( + prop, "Axis 0 Region", "Action execution region for the first input axis"); + + prop = RNA_def_property(srna, "axis1_region", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_enum_xr_axis1_flags); + RNA_def_property_enum_funcs(prop, + "rna_XrActionMapBinding_axis1_flag_get", + "rna_XrActionMapBinding_axis1_flag_set", + NULL); + RNA_def_property_ui_text( + prop, "Axis 1 Region", "Action execution region for the second input axis"); + + prop = RNA_def_property(srna, "pose_location", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_ui_text(prop, "Pose Location Offset", ""); + + prop = RNA_def_property(srna, "pose_rotation", PROP_FLOAT, PROP_EULER); + RNA_def_property_ui_text(prop, "Pose Rotation Offset", ""); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name XR Session Settings + * \{ */ + static void rna_def_xr_session_settings(BlenderRNA *brna) { StructRNA *srna; @@ -241,6 +1484,12 @@ static void rna_def_xr_session_settings(BlenderRNA *brna) RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name XR Session State + * \{ */ + static void rna_def_xr_session_state(BlenderRNA *brna) { StructRNA *srna; @@ -265,6 +1514,260 @@ static void rna_def_xr_session_state(BlenderRNA *brna) parm = RNA_def_pointer(func, "context", "Context", "", ""); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + func = RNA_def_function(srna, "action_set_create", "rna_XrSessionState_action_set_create"); + RNA_def_function_ui_description(func, "Create a VR action set"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "actionmap", "XrActionMap", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_boolean(func, "result", 0, "Result", ""); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "action_create", "rna_XrSessionState_action_create"); + RNA_def_function_ui_description(func, "Create a VR action"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "actionmap", "XrActionMap", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "actionmap_item", "XrActionMapItem", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_boolean(func, "result", 0, "Result", ""); + RNA_def_function_return(func, parm); + + func = RNA_def_function( + srna, "action_binding_create", "rna_XrSessionState_action_binding_create"); + RNA_def_function_ui_description(func, "Create a VR action binding"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "actionmap", "XrActionMap", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "actionmap_item", "XrActionMapItem", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "actionmap_binding", "XrActionMapBinding", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_boolean(func, "result", 0, "Result", ""); + RNA_def_function_return(func, parm); + + func = RNA_def_function( + srna, "active_action_set_set", "rna_XrSessionState_active_action_set_set"); + RNA_def_function_ui_description(func, "Set the active VR action set"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, "action_set", NULL, 64, "Action Set", "Action set name"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_boolean(func, "result", 0, "Result", ""); + RNA_def_function_return(func, parm); + + func = RNA_def_function( + srna, "controller_pose_actions_set", "rna_XrSessionState_controller_pose_actions_set"); + RNA_def_function_ui_description(func, "Set the actions that determine the VR controller poses"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, "action_set", NULL, 64, "Action Set", "Action set name"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, + "grip_action", + NULL, + 64, + "Grip Action", + "Name of the action representing the controller grips"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, + "aim_action", + NULL, + 64, + "Aim Action", + "Name of the action representing the controller aims"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_boolean(func, "result", 0, "Result", ""); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "action_state_get", "rna_XrSessionState_action_state_get"); + RNA_def_function_ui_description(func, "Get the current state of a VR action"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, "action_set_name", NULL, 64, "Action Set", "Action set name"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, "action_name", NULL, 64, "Action", "Action name"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, "user_path", NULL, 64, "User Path", "OpenXR user path"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_float_array( + func, + "state", + 2, + NULL, + -FLT_MAX, + FLT_MAX, + "Action State", + "Current state of the VR action. Second float value is only set for 2D vector type actions", + -FLT_MAX, + FLT_MAX); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_OUTPUT); + + func = RNA_def_function(srna, "haptic_action_apply", "rna_XrSessionState_haptic_action_apply"); + RNA_def_function_ui_description(func, "Apply a VR haptic action"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, "action_set_name", NULL, 64, "Action Set", "Action set name"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, "action_name", NULL, 64, "Action", "Action name"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string( + func, + "user_path", + NULL, + 64, + "User Path", + "Optional OpenXR user path. If not set, the action will be applied to all paths"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_float(func, + "duration", + 0.0f, + 0.0f, + FLT_MAX, + "Duration", + "Haptic duration in seconds. 0.0 is the minimum supported duration", + 0.0f, + FLT_MAX); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_float(func, + "frequency", + 0.0f, + 0.0f, + FLT_MAX, + "Frequency", + "Frequency of the haptic vibration in hertz. 0.0 specifies the OpenXR " + "runtime's default frequency", + 0.0f, + FLT_MAX); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_float(func, + "amplitude", + 1.0f, + 0.0f, + 1.0f, + "Amplitude", + "Haptic amplitude, ranging from 0.0 to 1.0", + 0.0f, + 1.0f); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_boolean(func, "result", 0, "Result", ""); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "haptic_action_stop", "rna_XrSessionState_haptic_action_stop"); + RNA_def_function_ui_description(func, "Stop a VR haptic action"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, "action_set_name", NULL, 64, "Action Set", "Action set name"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, "action_name", NULL, 64, "Action", "Action name"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string( + func, + "user_path", + NULL, + 64, + "User Path", + "Optional OpenXR user path. If not set, the action will be stopped for all paths"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + + func = RNA_def_function( + srna, "controller_grip_location_get", "rna_XrSessionState_controller_grip_location_get"); + RNA_def_function_ui_description(func, + "Get the last known controller grip location in world space"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_int(func, "index", 0, 0, 255, "Index", "Controller index", 0, 255); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + RNA_def_float_translation(func, + "location", + 3, + NULL, + -FLT_MAX, + FLT_MAX, + "Location", + "Controller grip location", + -FLT_MAX, + FLT_MAX); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_OUTPUT); + + func = RNA_def_function( + srna, "controller_grip_rotation_get", "rna_XrSessionState_controller_grip_rotation_get"); + RNA_def_function_ui_description( + func, "Get the last known controller grip rotation (quaternion) in world space"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_int(func, "index", 0, 0, 255, "Index", "Controller index", 0, 255); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_float_vector(func, + "rotation", + 4, + NULL, + -FLT_MAX, + FLT_MAX, + "Rotation", + "Controller grip quaternion rotation", + -FLT_MAX, + FLT_MAX); + parm->subtype = PROP_QUATERNION; + RNA_def_property_ui_range(parm, -FLT_MAX, FLT_MAX, 1, 5); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_OUTPUT); + + func = RNA_def_function( + srna, "controller_aim_location_get", "rna_XrSessionState_controller_aim_location_get"); + RNA_def_function_ui_description(func, + "Get the last known controller aim location in world space"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_int(func, "index", 0, 0, 255, "Index", "Controller index", 0, 255); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + RNA_def_float_translation(func, + "location", + 3, + NULL, + -FLT_MAX, + FLT_MAX, + "Location", + "Controller aim location", + -FLT_MAX, + FLT_MAX); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_OUTPUT); + + func = RNA_def_function( + srna, "controller_aim_rotation_get", "rna_XrSessionState_controller_aim_rotation_get"); + RNA_def_function_ui_description( + func, "Get the last known controller aim rotation (quaternion) in world space"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_int(func, "index", 0, 0, 255, "Index", "Controller index", 0, 255); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_float_vector(func, + "rotation", + 4, + NULL, + -FLT_MAX, + FLT_MAX, + "Rotation", + "Controller aim quaternion rotation", + -FLT_MAX, + FLT_MAX); + parm->subtype = PROP_QUATERNION; + RNA_def_property_ui_range(parm, -FLT_MAX, FLT_MAX, 1, 5); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_OUTPUT); + prop = RNA_def_property(srna, "viewer_pose_location", PROP_FLOAT, PROP_TRANSLATION); RNA_def_property_array(prop, 3); RNA_def_property_float_funcs(prop, "rna_XrSessionState_viewer_pose_location_get", NULL, NULL); @@ -282,12 +1785,43 @@ static void rna_def_xr_session_state(BlenderRNA *brna) prop, "Viewer Pose Rotation", "Last known rotation of the viewer pose (center between the eyes) in world space"); + + prop = RNA_def_property(srna, "actionmaps", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_funcs(prop, + "rna_XrSessionState_actionmaps_begin", + "rna_iterator_listbase_next", + "rna_iterator_listbase_end", + "rna_iterator_listbase_get", + NULL, + NULL, + NULL, + NULL); + RNA_def_property_struct_type(prop, "XrActionMap"); + RNA_def_property_ui_text(prop, "XR Action Maps", ""); + rna_def_xr_actionmaps(brna, prop); + + prop = RNA_def_property(srna, "active_actionmap", PROP_INT, PROP_NONE); + RNA_def_property_int_funcs(prop, + "rna_XrSessionState_active_actionmap_get", + "rna_XrSessionState_active_actionmap_set", + NULL); + RNA_def_property_ui_text(prop, "Active Action Map", ""); + + prop = RNA_def_property(srna, "selected_actionmap", PROP_INT, PROP_NONE); + RNA_def_property_int_funcs(prop, + "rna_XrSessionState_selected_actionmap_get", + "rna_XrSessionState_selected_actionmap_set", + NULL); + RNA_def_property_ui_text(prop, "Selected Action Map", ""); } +/** \} */ + void RNA_def_xr(BlenderRNA *brna) { RNA_define_animate_sdna(false); + rna_def_xr_actionmap(brna); rna_def_xr_session_settings(brna); rna_def_xr_session_state(brna); diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index 8b0ceb02b5f..b7fbb9bb82b 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -204,6 +204,7 @@ if(WITH_XR_OPENXR) list(APPEND SRC xr/intern/wm_xr.c xr/intern/wm_xr_action.c + xr/intern/wm_xr_actionmap.c xr/intern/wm_xr_draw.c xr/intern/wm_xr_session.c diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 7e26d921bd7..02e8d42e0ff 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -74,8 +74,7 @@ struct wmNDOFMotionData; #endif #ifdef WITH_XR_OPENXR -struct wmXrActionState; -struct wmXrPose; +struct wmXrRuntimeData; #endif typedef struct wmGizmo wmGizmo; @@ -988,7 +987,13 @@ bool WM_xr_action_create(wmXrData *xr, const char **subaction_paths, struct wmOperatorType *ot, struct IDProperty *op_properties, - eXrOpFlag op_flag); + const char **haptic_name, + const int64_t *haptic_duration, + const float *haptic_frequency, + const float *haptic_amplitude, + eXrOpFlag op_flag, + eXrActionFlag action_flag, + eXrHapticFlag haptic_flag); void WM_xr_action_destroy(wmXrData *xr, const char *action_set_name, const char *action_name); bool WM_xr_action_binding_create(wmXrData *xr, const char *action_set_name, @@ -1022,10 +1027,48 @@ bool WM_xr_action_state_get(const wmXrData *xr, bool WM_xr_haptic_action_apply(wmXrData *xr, const char *action_set_name, const char *action_name, + const char **subaction_path, const int64_t *duration, const float *frequency, const float *amplitude); -void WM_xr_haptic_action_stop(wmXrData *xr, const char *action_set_name, const char *action_name); +void WM_xr_haptic_action_stop(wmXrData *xr, + const char *action_set_name, + const char *action_name, + const char **subaction_path); + +/* wm_xr_actionmap.c */ +XrActionMap *WM_xr_actionmap_new(struct wmXrRuntimeData *runtime, + const char *name, + bool replace_existing); +void WM_xr_actionmap_ensure_unique(struct wmXrRuntimeData *runtime, XrActionMap *actionmap); +XrActionMap *WM_xr_actionmap_add_copy(struct wmXrRuntimeData *runtime, XrActionMap *am_src); +bool WM_xr_actionmap_remove(struct wmXrRuntimeData *runtime, XrActionMap *actionmap); +XrActionMap *WM_xr_actionmap_find(struct wmXrRuntimeData *runtime, const char *name); +void WM_xr_actionmap_clear(XrActionMap *actionmap); +void WM_xr_actionmaps_clear(struct wmXrRuntimeData *runtime); +ListBase *WM_xr_actionmaps_get(struct wmXrRuntimeData *runtime); +short WM_xr_actionmap_active_index_get(const struct wmXrRuntimeData *runtime); +void WM_xr_actionmap_active_index_set(struct wmXrRuntimeData *runtime, short idx); +short WM_xr_actionmap_selected_index_get(const struct wmXrRuntimeData *runtime); +void WM_xr_actionmap_selected_index_set(struct wmXrRuntimeData *runtime, short idx); + +XrActionMapItem *WM_xr_actionmap_item_new(XrActionMap *actionmap, + const char *name, + bool replace_existing); +void WM_xr_actionmap_item_ensure_unique(XrActionMap *actionmap, XrActionMapItem *ami); +XrActionMapItem *WM_xr_actionmap_item_add_copy(XrActionMap *actionmap, XrActionMapItem *ami_src); +bool WM_xr_actionmap_item_remove(XrActionMap *actionmap, XrActionMapItem *ami); +XrActionMapItem *WM_xr_actionmap_item_find(XrActionMap *actionmap, const char *name); +void WM_xr_actionmap_item_properties_update_ot(XrActionMapItem *ami); + +XrActionMapBinding *WM_xr_actionmap_binding_new(XrActionMapItem *ami, + const char *name, + bool replace_existing); +void WM_xr_actionmap_binding_ensure_unique(XrActionMapItem *ami, XrActionMapBinding *amb); +XrActionMapBinding *WM_xr_actionmap_binding_add_copy(XrActionMapItem *ami, + XrActionMapBinding *amb_src); +bool WM_xr_actionmap_binding_remove(XrActionMapItem *ami, XrActionMapBinding *amb); +XrActionMapBinding *WM_xr_actionmap_binding_find(XrActionMapItem *ami, const char *name); #endif /* WITH_XR_OPENXR */ #ifdef __cplusplus diff --git a/source/blender/windowmanager/xr/intern/wm_xr.c b/source/blender/windowmanager/xr/intern/wm_xr.c index 2a67c2bee9f..716a0936a24 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr.c +++ b/source/blender/windowmanager/xr/intern/wm_xr.c @@ -115,6 +115,7 @@ bool wm_xr_init(wmWindowManager *wm) void wm_xr_exit(wmWindowManager *wm) { if (wm->xr.runtime != NULL) { + WM_xr_actionmaps_clear(wm->xr.runtime); wm_xr_runtime_data_free(&wm->xr.runtime); } if (wm->xr.session_settings.shading.prop) { diff --git a/source/blender/windowmanager/xr/intern/wm_xr_action.c b/source/blender/windowmanager/xr/intern/wm_xr_action.c index 8f2de4bbbad..2712fde51a8 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_action.c +++ b/source/blender/windowmanager/xr/intern/wm_xr_action.c @@ -23,6 +23,7 @@ * All functions are designed to be usable by RNA / the Python API. */ +#include "BLI_listbase.h" #include "BLI_math.h" #include "GHOST_C-api.h" @@ -56,6 +57,9 @@ static void action_set_destroy(void *val) MEM_SAFE_FREE(action_set->name); + BLI_freelistN(&action_set->active_modal_actions); + BLI_freelistN(&action_set->active_haptic_actions); + MEM_freeN(action_set); } @@ -70,7 +74,13 @@ static wmXrAction *action_create(const char *action_name, const char **subaction_paths, wmOperatorType *ot, IDProperty *op_properties, - eXrOpFlag op_flag) + const char **haptic_name, + const int64_t *haptic_duration, + const float *haptic_frequency, + const float *haptic_amplitude, + eXrOpFlag op_flag, + eXrActionFlag action_flag, + eXrHapticFlag haptic_flag) { wmXrAction *action = MEM_callocN(sizeof(*action), __func__); action->name = MEM_mallocN(strlen(action_name) + 1, "XrAction_Name"); @@ -121,7 +131,19 @@ static wmXrAction *action_create(const char *action_name, action->ot = ot; action->op_properties = op_properties; + + if (haptic_name) { + BLI_assert(is_button_action); + action->haptic_name = MEM_mallocN(strlen(*haptic_name) + 1, "XrAction_HapticName"); + strcpy(action->haptic_name, *haptic_name); + action->haptic_duration = *haptic_duration; + action->haptic_frequency = *haptic_frequency; + action->haptic_amplitude = *haptic_amplitude; + } + action->op_flag = op_flag; + action->action_flag = action_flag; + action->haptic_flag = haptic_flag; return action; } @@ -147,6 +169,8 @@ static void action_destroy(void *val) MEM_SAFE_FREE(action->float_thresholds); MEM_SAFE_FREE(action->axis_flags); + MEM_SAFE_FREE(action->haptic_name); + MEM_freeN(action); } @@ -190,9 +214,10 @@ void WM_xr_action_set_destroy(wmXrData *xr, const char *action_set_name) wm_xr_session_controller_data_clear(session_state); action_set->controller_grip_action = action_set->controller_aim_action = NULL; } - if (action_set->active_modal_action) { - action_set->active_modal_action = NULL; - } + + BLI_freelistN(&action_set->active_modal_actions); + BLI_freelistN(&action_set->active_haptic_actions); + session_state->active_action_set = NULL; } @@ -207,14 +232,31 @@ bool WM_xr_action_create(wmXrData *xr, const char **subaction_paths, wmOperatorType *ot, IDProperty *op_properties, - eXrOpFlag op_flag) + const char **haptic_name, + const int64_t *haptic_duration, + const float *haptic_frequency, + const float *haptic_amplitude, + eXrOpFlag op_flag, + eXrActionFlag action_flag, + eXrHapticFlag haptic_flag) { if (action_find(xr, action_set_name, action_name)) { return false; } - wmXrAction *action = action_create( - action_name, type, count_subaction_paths, subaction_paths, ot, op_properties, op_flag); + wmXrAction *action = action_create(action_name, + type, + count_subaction_paths, + subaction_paths, + ot, + op_properties, + haptic_name, + haptic_duration, + haptic_frequency, + haptic_amplitude, + op_flag, + action_flag, + haptic_flag); GHOST_XrActionInfo info = { .name = action_name, @@ -274,9 +316,18 @@ void WM_xr_action_destroy(wmXrData *xr, const char *action_set_name, const char action_set->controller_grip_action = action_set->controller_aim_action = NULL; } - if (action_set->active_modal_action && - STREQ(action_set->active_modal_action->name, action_name)) { - action_set->active_modal_action = NULL; + LISTBASE_FOREACH (LinkData *, ld, &action_set->active_modal_actions) { + wmXrAction *active_modal_action = ld->data; + if (STREQ(active_modal_action->name, action_name)) { + BLI_freelinkN(&action_set->active_modal_actions, ld); + break; + } + } + + LISTBASE_FOREACH_MUTABLE (wmXrHapticAction *, ha, &action_set->active_haptic_actions) { + if (STREQ(ha->action->name, action_name)) { + BLI_freelinkN(&action_set->active_haptic_actions, ha); + } } GHOST_XrDestroyActions(xr->runtime->context, action_set_name, 1, &action_name); @@ -342,16 +393,11 @@ bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name) } { - /* Unset active modal action (if any). */ + /* Clear any active modal/haptic actions. */ wmXrActionSet *active_action_set = xr->runtime->session_state.active_action_set; if (active_action_set) { - wmXrAction *active_modal_action = active_action_set->active_modal_action; - if (active_modal_action) { - if (active_modal_action->active_modal_path) { - active_modal_action->active_modal_path = NULL; - } - active_action_set->active_modal_action = NULL; - } + BLI_freelistN(&active_action_set->active_modal_actions); + BLI_freelistN(&active_action_set->active_haptic_actions); } } @@ -456,19 +502,28 @@ bool WM_xr_action_state_get(const wmXrData *xr, bool WM_xr_haptic_action_apply(wmXrData *xr, const char *action_set_name, const char *action_name, + const char **subaction_path, const int64_t *duration, const float *frequency, const float *amplitude) { - return GHOST_XrApplyHapticAction( - xr->runtime->context, action_set_name, action_name, duration, frequency, amplitude) ? + return GHOST_XrApplyHapticAction(xr->runtime->context, + action_set_name, + action_name, + subaction_path, + duration, + frequency, + amplitude) ? true : false; } -void WM_xr_haptic_action_stop(wmXrData *xr, const char *action_set_name, const char *action_name) +void WM_xr_haptic_action_stop(wmXrData *xr, + const char *action_set_name, + const char *action_name, + const char **subaction_path) { - GHOST_XrStopHapticAction(xr->runtime->context, action_set_name, action_name); + GHOST_XrStopHapticAction(xr->runtime->context, action_set_name, action_name, subaction_path); } /** \} */ /* XR-Action API */ diff --git a/source/blender/windowmanager/xr/intern/wm_xr_actionmap.c b/source/blender/windowmanager/xr/intern/wm_xr_actionmap.c new file mode 100644 index 00000000000..7673f2aa212 --- /dev/null +++ b/source/blender/windowmanager/xr/intern/wm_xr_actionmap.c @@ -0,0 +1,565 @@ +/* + * 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. + */ + +/** \file + * \ingroup wm + * + * \name Window-Manager XR Action Maps + * + * XR actionmap API, similar to WM keymap API. + */ + +#include +#include + +#include "BKE_context.h" +#include "BKE_idprop.h" + +#include "BLI_listbase.h" +#include "BLI_string.h" + +#include "GHOST_Types.h" + +#include "MEM_guardedalloc.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "wm_xr_intern.h" + +#define WM_XR_ACTIONMAP_STR_DEFAULT "actionmap" +#define WM_XR_ACTIONMAP_ITEM_STR_DEFAULT "action" +#define WM_XR_ACTIONMAP_BINDING_STR_DEFAULT "binding" + +/* -------------------------------------------------------------------- */ +/** \name Action Map Binding + * + * Binding in an XR action map item, that maps an action to an XR input. + * \{ */ + +XrActionMapBinding *WM_xr_actionmap_binding_new(XrActionMapItem *ami, + const char *name, + bool replace_existing) +{ + XrActionMapBinding *amb_prev = WM_xr_actionmap_binding_find(ami, name); + if (amb_prev && replace_existing) { + return amb_prev; + } + + XrActionMapBinding *amb = MEM_callocN(sizeof(XrActionMapBinding), __func__); + BLI_strncpy(amb->name, name, MAX_NAME); + if (amb_prev) { + WM_xr_actionmap_binding_ensure_unique(ami, amb); + } + + BLI_addtail(&ami->bindings, amb); + + /* Set non-zero threshold by default. */ + amb->float_threshold = 0.3f; + + return amb; +} + +static XrActionMapBinding *wm_xr_actionmap_binding_find_except(XrActionMapItem *ami, + const char *name, + XrActionMapBinding *ambexcept) +{ + LISTBASE_FOREACH (XrActionMapBinding *, amb, &ami->bindings) { + if (STREQLEN(name, amb->name, MAX_NAME) && (amb != ambexcept)) { + return amb; + } + } + return NULL; +} + +/** + * Ensure unique name among all action map bindings. + */ +void WM_xr_actionmap_binding_ensure_unique(XrActionMapItem *ami, XrActionMapBinding *amb) +{ + char name[MAX_NAME]; + char *suffix; + size_t baselen; + size_t idx = 0; + + BLI_strncpy(name, amb->name, MAX_NAME); + baselen = BLI_strnlen(name, MAX_NAME); + suffix = &name[baselen]; + + while (wm_xr_actionmap_binding_find_except(ami, name, amb)) { + if ((baselen + 1) + (log10(++idx) + 1) > MAX_NAME) { + /* Use default base name. */ + BLI_strncpy(name, WM_XR_ACTIONMAP_BINDING_STR_DEFAULT, MAX_NAME); + baselen = BLI_strnlen(name, MAX_NAME); + suffix = &name[baselen]; + idx = 0; + } + else { + BLI_snprintf(suffix, MAX_NAME, "%zu", idx); + } + } + + BLI_strncpy(amb->name, name, MAX_NAME); +} + +static XrActionMapBinding *wm_xr_actionmap_binding_copy(XrActionMapBinding *amb_src) +{ + XrActionMapBinding *amb_dst = MEM_dupallocN(amb_src); + + amb_dst->prev = amb_dst->next = NULL; + + return amb_dst; +} + +XrActionMapBinding *WM_xr_actionmap_binding_add_copy(XrActionMapItem *ami, + XrActionMapBinding *amb_src) +{ + XrActionMapBinding *amb_dst = wm_xr_actionmap_binding_copy(amb_src); + + WM_xr_actionmap_binding_ensure_unique(ami, amb_dst); + + BLI_addtail(&ami->bindings, amb_dst); + + return amb_dst; +} + +bool WM_xr_actionmap_binding_remove(XrActionMapItem *ami, XrActionMapBinding *amb) +{ + int idx = BLI_findindex(&ami->bindings, amb); + + if (idx != -1) { + BLI_freelinkN(&ami->bindings, amb); + + if (BLI_listbase_is_empty(&ami->bindings)) { + ami->selbinding = -1; + } + else { + if (idx <= ami->selbinding) { + if (--ami->selbinding < 0) { + ami->selbinding = 0; + } + } + } + + return true; + } + + return false; +} + +XrActionMapBinding *WM_xr_actionmap_binding_find(XrActionMapItem *ami, const char *name) +{ + LISTBASE_FOREACH (XrActionMapBinding *, amb, &ami->bindings) { + if (STREQLEN(name, amb->name, MAX_NAME)) { + return amb; + } + } + return NULL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Action Map Item + * + * Item in an XR action map, that maps an XR event to an operator, pose, or haptic output. + * \{ */ + +static void wm_xr_actionmap_item_properties_set(XrActionMapItem *ami) +{ + WM_operator_properties_alloc(&(ami->op_properties_ptr), &(ami->op_properties), ami->op); + WM_operator_properties_sanitize(ami->op_properties_ptr, 1); +} + +static void wm_xr_actionmap_item_properties_free(XrActionMapItem *ami) +{ + if (ami->op_properties_ptr) { + WM_operator_properties_free(ami->op_properties_ptr); + MEM_freeN(ami->op_properties_ptr); + ami->op_properties_ptr = NULL; + ami->op_properties = NULL; + } + else { + BLI_assert(ami->op_properties == NULL); + } +} + +/** + * Similar to #wm_xr_actionmap_item_properties_set() + * but checks for the #eXrActionType and #wmOperatorType having changed. + */ +void WM_xr_actionmap_item_properties_update_ot(XrActionMapItem *ami) +{ + switch (ami->type) { + case XR_BOOLEAN_INPUT: + case XR_FLOAT_INPUT: + case XR_VECTOR2F_INPUT: + break; + case XR_POSE_INPUT: + case XR_VIBRATION_OUTPUT: + wm_xr_actionmap_item_properties_free(ami); + memset(ami->op, 0, sizeof(ami->op)); + return; + } + + if (ami->op[0] == 0) { + wm_xr_actionmap_item_properties_free(ami); + return; + } + + if (ami->op_properties_ptr == NULL) { + wm_xr_actionmap_item_properties_set(ami); + } + else { + wmOperatorType *ot = WM_operatortype_find(ami->op, 0); + if (ot) { + if (ot->srna != ami->op_properties_ptr->type) { + /* Matches wm_xr_actionmap_item_properties_set() but doesn't alloc new ptr. */ + WM_operator_properties_create_ptr(ami->op_properties_ptr, ot); + if (ami->op_properties) { + ami->op_properties_ptr->data = ami->op_properties; + } + WM_operator_properties_sanitize(ami->op_properties_ptr, 1); + } + } + else { + wm_xr_actionmap_item_properties_free(ami); + } + } +} + +XrActionMapItem *WM_xr_actionmap_item_new(XrActionMap *actionmap, + const char *name, + bool replace_existing) +{ + XrActionMapItem *ami_prev = WM_xr_actionmap_item_find(actionmap, name); + if (ami_prev && replace_existing) { + wm_xr_actionmap_item_properties_free(ami_prev); + return ami_prev; + } + + XrActionMapItem *ami = MEM_callocN(sizeof(XrActionMapItem), __func__); + BLI_strncpy(ami->name, name, MAX_NAME); + if (ami_prev) { + WM_xr_actionmap_item_ensure_unique(actionmap, ami); + } + + BLI_addtail(&actionmap->items, ami); + + /* Set type to float (button) input by default. */ + ami->type = XR_FLOAT_INPUT; + + return ami; +} + +static XrActionMapItem *wm_xr_actionmap_item_find_except(XrActionMap *actionmap, + const char *name, + const XrActionMapItem *amiexcept) +{ + LISTBASE_FOREACH (XrActionMapItem *, ami, &actionmap->items) { + if (STREQLEN(name, ami->name, MAX_NAME) && (ami != amiexcept)) { + return ami; + } + } + return NULL; +} + +/** + * Ensure unique name among all action map items. + */ +void WM_xr_actionmap_item_ensure_unique(XrActionMap *actionmap, XrActionMapItem *ami) +{ + char name[MAX_NAME]; + char *suffix; + size_t baselen; + size_t idx = 0; + + BLI_strncpy(name, ami->name, MAX_NAME); + baselen = BLI_strnlen(name, MAX_NAME); + suffix = &name[baselen]; + + while (wm_xr_actionmap_item_find_except(actionmap, name, ami)) { + if ((baselen + 1) + (log10(++idx) + 1) > MAX_NAME) { + /* Use default base name. */ + BLI_strncpy(name, WM_XR_ACTIONMAP_ITEM_STR_DEFAULT, MAX_NAME); + baselen = BLI_strnlen(name, MAX_NAME); + suffix = &name[baselen]; + idx = 0; + } + else { + BLI_snprintf(suffix, MAX_NAME, "%zu", idx); + } + } + + BLI_strncpy(ami->name, name, MAX_NAME); +} + +static XrActionMapItem *wm_xr_actionmap_item_copy(XrActionMapItem *ami) +{ + XrActionMapItem *amin = MEM_dupallocN(ami); + + amin->prev = amin->next = NULL; + + if (amin->op_properties) { + amin->op_properties_ptr = MEM_callocN(sizeof(PointerRNA), "wmOpItemPtr"); + WM_operator_properties_create(amin->op_properties_ptr, amin->op); + + amin->op_properties = IDP_CopyProperty(amin->op_properties); + amin->op_properties_ptr->data = amin->op_properties; + } + else { + amin->op_properties = NULL; + amin->op_properties_ptr = NULL; + } + + return amin; +} + +XrActionMapItem *WM_xr_actionmap_item_add_copy(XrActionMap *actionmap, XrActionMapItem *ami_src) +{ + XrActionMapItem *ami_dst = wm_xr_actionmap_item_copy(ami_src); + + WM_xr_actionmap_item_ensure_unique(actionmap, ami_dst); + + BLI_addtail(&actionmap->items, ami_dst); + + return ami_dst; +} + +bool WM_xr_actionmap_item_remove(XrActionMap *actionmap, XrActionMapItem *ami) +{ + int idx = BLI_findindex(&actionmap->items, ami); + + if (idx != -1) { + if (ami->op_properties_ptr) { + WM_operator_properties_free(ami->op_properties_ptr); + MEM_freeN(ami->op_properties_ptr); + } + BLI_freelinkN(&actionmap->items, ami); + + if (BLI_listbase_is_empty(&actionmap->items)) { + actionmap->selitem = -1; + } + else { + if (idx <= actionmap->selitem) { + if (--actionmap->selitem < 0) { + actionmap->selitem = 0; + } + } + } + + return true; + } + + return false; +} + +XrActionMapItem *WM_xr_actionmap_item_find(XrActionMap *actionmap, const char *name) +{ + LISTBASE_FOREACH (XrActionMapItem *, ami, &actionmap->items) { + if (STREQLEN(name, ami->name, MAX_NAME)) { + return ami; + } + } + return NULL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Action Map + * + * List of XR action map items. + * \{ */ + +XrActionMap *WM_xr_actionmap_new(wmXrRuntimeData *runtime, const char *name, bool replace_existing) +{ + XrActionMap *am_prev = WM_xr_actionmap_find(runtime, name); + if (am_prev && replace_existing) { + WM_xr_actionmap_clear(am_prev); + return am_prev; + } + + XrActionMap *am = MEM_callocN(sizeof(struct XrActionMap), __func__); + BLI_strncpy(am->name, name, MAX_NAME); + if (am_prev) { + WM_xr_actionmap_ensure_unique(runtime, am); + } + + BLI_addtail(&runtime->actionmaps, am); + + return am; +} + +static XrActionMap *wm_xr_actionmap_find_except(wmXrRuntimeData *runtime, + const char *name, + const XrActionMap *am_except) +{ + LISTBASE_FOREACH (XrActionMap *, am, &runtime->actionmaps) { + if (STREQLEN(name, am->name, MAX_NAME) && (am != am_except)) { + return am; + } + } + + return NULL; +} + +/** + * Ensure unique name among all action maps. + */ +void WM_xr_actionmap_ensure_unique(wmXrRuntimeData *runtime, XrActionMap *actionmap) +{ + char name[MAX_NAME]; + char *suffix; + size_t baselen; + size_t idx = 0; + + BLI_strncpy(name, actionmap->name, MAX_NAME); + baselen = BLI_strnlen(name, MAX_NAME); + suffix = &name[baselen]; + + while (wm_xr_actionmap_find_except(runtime, name, actionmap)) { + if ((baselen + 1) + (log10(++idx) + 1) > MAX_NAME) { + /* Use default base name. */ + BLI_strncpy(name, WM_XR_ACTIONMAP_STR_DEFAULT, MAX_NAME); + baselen = BLI_strnlen(name, MAX_NAME); + suffix = &name[baselen]; + idx = 0; + } + else { + BLI_snprintf(suffix, MAX_NAME, "%zu", idx); + } + } + + BLI_strncpy(actionmap->name, name, MAX_NAME); +} + +static XrActionMap *wm_xr_actionmap_copy(XrActionMap *am_src) +{ + XrActionMap *am_dst = MEM_dupallocN(am_src); + + am_dst->prev = am_dst->next = NULL; + BLI_listbase_clear(&am_dst->items); + + LISTBASE_FOREACH (XrActionMapItem *, ami, &am_src->items) { + XrActionMapItem *ami_new = wm_xr_actionmap_item_copy(ami); + BLI_addtail(&am_dst->items, ami_new); + } + + return am_dst; +} + +XrActionMap *WM_xr_actionmap_add_copy(wmXrRuntimeData *runtime, XrActionMap *am_src) +{ + XrActionMap *am_dst = wm_xr_actionmap_copy(am_src); + + WM_xr_actionmap_ensure_unique(runtime, am_dst); + + BLI_addtail(&runtime->actionmaps, am_dst); + + return am_dst; +} + +bool WM_xr_actionmap_remove(wmXrRuntimeData *runtime, XrActionMap *actionmap) +{ + int idx = BLI_findindex(&runtime->actionmaps, actionmap); + + if (idx != -1) { + WM_xr_actionmap_clear(actionmap); + BLI_freelinkN(&runtime->actionmaps, actionmap); + + if (BLI_listbase_is_empty(&runtime->actionmaps)) { + runtime->actactionmap = runtime->selactionmap = -1; + } + else { + if (idx <= runtime->actactionmap) { + if (--runtime->actactionmap < 0) { + runtime->actactionmap = 0; + } + } + if (idx <= runtime->selactionmap) { + if (--runtime->selactionmap < 0) { + runtime->selactionmap = 0; + } + } + } + + return true; + } + + return false; +} + +XrActionMap *WM_xr_actionmap_find(wmXrRuntimeData *runtime, const char *name) +{ + LISTBASE_FOREACH (XrActionMap *, am, &runtime->actionmaps) { + if (STREQLEN(name, am->name, MAX_NAME)) { + return am; + } + } + return NULL; +} + +void WM_xr_actionmap_clear(XrActionMap *actionmap) +{ + LISTBASE_FOREACH (XrActionMapItem *, ami, &actionmap->items) { + wm_xr_actionmap_item_properties_free(ami); + } + + BLI_freelistN(&actionmap->items); + + actionmap->selitem = -1; +} + +void WM_xr_actionmaps_clear(wmXrRuntimeData *runtime) +{ + LISTBASE_FOREACH (XrActionMap *, am, &runtime->actionmaps) { + WM_xr_actionmap_clear(am); + } + + BLI_freelistN(&runtime->actionmaps); + + runtime->actactionmap = runtime->selactionmap = -1; +} + +ListBase *WM_xr_actionmaps_get(wmXrRuntimeData *runtime) +{ + return &runtime->actionmaps; +} + +short WM_xr_actionmap_active_index_get(const wmXrRuntimeData *runtime) +{ + return runtime->actactionmap; +} + +void WM_xr_actionmap_active_index_set(wmXrRuntimeData *runtime, short idx) +{ + BLI_assert(idx < BLI_listbase_count(&runtime->actionmaps)); + runtime->actactionmap = idx; +} + +short WM_xr_actionmap_selected_index_get(const wmXrRuntimeData *runtime) +{ + return runtime->selactionmap; +} + +void WM_xr_actionmap_selected_index_set(wmXrRuntimeData *runtime, short idx) +{ + BLI_assert(idx < BLI_listbase_count(&runtime->actionmaps)); + runtime->selactionmap = idx; +} + +/** \} */ diff --git a/source/blender/windowmanager/xr/intern/wm_xr_intern.h b/source/blender/windowmanager/xr/intern/wm_xr_intern.h index b6aff1f71f9..4b1605d0f68 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_intern.h +++ b/source/blender/windowmanager/xr/intern/wm_xr_intern.h @@ -70,6 +70,10 @@ typedef struct wmXrRuntimeData { /** Although this struct is internal, RNA gets a handle to this for state information queries. */ wmXrSessionState session_state; wmXrSessionExitFn exit_fn; + + ListBase actionmaps; /* XrActionMap */ + short actactionmap; + short selactionmap; } wmXrRuntimeData; typedef struct wmXrViewportPair { @@ -99,6 +103,22 @@ typedef struct wmXrDrawData { float eye_position_ofs[3]; /* Local/view space. */ } wmXrDrawData; +typedef struct wmXrController { + struct wmXrController *next, *prev; + /** OpenXR path identifier. Length is dependent on OpenXR's XR_MAX_PATH_LENGTH (256). + This subaction path will later be combined with a component path, and that combined path should + also have a max of XR_MAX_PATH_LENGTH (e.g. subaction_path = /user/hand/left, component_path = + /input/trigger/value, interaction_path = /user/hand/left/input/trigger/value). + */ + char subaction_path[64]; + /* Pose (in world space) that represents the user's hand when holding the controller.*/ + GHOST_XrPose grip_pose; + float grip_mat[4][4]; + /* Pose (in world space) that represents the controller's aiming source. */ + GHOST_XrPose aim_pose; + float aim_mat[4][4]; +} wmXrController; + typedef struct wmXrAction { char *name; eXrActionType type; @@ -119,32 +139,37 @@ typedef struct wmXrAction { /** Operator to be called on XR events. */ struct wmOperatorType *ot; IDProperty *op_properties; + + /** Haptics. */ + char *haptic_name; + int64_t haptic_duration; + float haptic_frequency; + float haptic_amplitude; + + /** Flags. */ eXrOpFlag op_flag; + eXrActionFlag action_flag; + eXrHapticFlag haptic_flag; } wmXrAction; -typedef struct wmXrController { - struct wmXrController *next, *prev; - /** OpenXR path identifier. Length is dependent on OpenXR's XR_MAX_PATH_LENGTH (256). - This subaction path will later be combined with a component path, and that combined path should - also have a max of XR_MAX_PATH_LENGTH (e.g. subaction_path = /user/hand/left, component_path = - /input/trigger/value, interaction_path = /user/hand/left/input/trigger/value). - */ - char subaction_path[64]; - /* Pose (in world space) that represents the user's hand when holding the controller.*/ - GHOST_XrPose grip_pose; - float grip_mat[4][4]; - /* Pose (in world space) that represents the controller's aiming source. */ - GHOST_XrPose aim_pose; - float aim_mat[4][4]; -} wmXrController; +typedef struct wmXrHapticAction { + struct wmXrHapticAction *next, *prev; + wmXrAction *action; + const char **subaction_path; + int64_t time_start; +} wmXrHapticAction; typedef struct wmXrActionSet { char *name; + /** XR pose actions that determine the controller grip/aim transforms. */ wmXrAction *controller_grip_action; wmXrAction *controller_aim_action; - /** The currently active modal action (if any). */ - wmXrAction *active_modal_action; + + /** Currently active modal actions. */ + ListBase active_modal_actions; + /** Currently active haptic actions. */ + ListBase active_haptic_actions; } wmXrActionSet; wmXrRuntimeData *wm_xr_runtime_data_create(void); -- cgit v1.2.3 From cc4e674e41f9ddca9d3b6aee8c21ddcb3fdfea26 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Tue, 3 Aug 2021 13:39:30 -0300 Subject: DRW: New Select Debug Engine This is a simple engine used only to debug the texture of select ids. It is only used when the `WITH_DRAW_DEBUG` option is enabled and the debug value is 31. Reviewed By: fclem Differential Revision: https://developer.blender.org/D5490 --- CMakeLists.txt | 4 + source/blender/blenkernel/BKE_global.h | 1 + source/blender/draw/CMakeLists.txt | 7 ++ .../draw/engines/select/select_debug_engine.c | 135 +++++++++++++++++++++ source/blender/draw/engines/select/select_engine.h | 6 + source/blender/draw/intern/draw_manager.c | 9 ++ 6 files changed, 162 insertions(+) create mode 100644 source/blender/draw/engines/select/select_debug_engine.c diff --git a/CMakeLists.txt b/CMakeLists.txt index b7dfb56ff02..3baebba4678 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -428,6 +428,10 @@ mark_as_advanced(WITH_CYCLES_NETWORK) option(WITH_CUDA_DYNLOAD "Dynamically load CUDA libraries at runtime" ON) mark_as_advanced(WITH_CUDA_DYNLOAD) +# Draw Manager +option(WITH_DRAW_DEBUG "Add extra debug capabilities to Draw Manager" OFF) +mark_as_advanced(WITH_DRAW_DEBUG) + # LLVM option(WITH_LLVM "Use LLVM" OFF) if(APPLE) diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 69c950a86dc..31928b5e80a 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -70,6 +70,7 @@ typedef struct Global { * * -16384 and below: Reserved for python (add-ons) usage. * * -1: Disable faster motion paths computation (since 08/2018). * * 1 - 30: EEVEE debug/stats values (01/2018). + * * 31: Enable the Select Debug Engine. Only available with #WITH_DRAW_DEBUG (08/2021). * * 101: Enable UI debug drawing of fullscreen area's corner widget (10/2014). * * 666: Use quicker batch delete for outliners' delete hierarchy (01/2019). * * 777: Enable UI node panel's sockets polling (11/2011). diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 930d82fa225..257eb80ae0b 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -483,6 +483,13 @@ data_to_c_simple(engines/image/shaders/engine_image_vert.glsl SRC) list(APPEND INC ) +if(WITH_DRAW_DEBUG) + list(APPEND SRC + engines/select/select_debug_engine.c + ) + add_definitions(-DWITH_DRAW_DEBUG) +endif() + if(WITH_MOD_FLUID) list(APPEND INC ../../../intern/mantaflow/extern diff --git a/source/blender/draw/engines/select/select_debug_engine.c b/source/blender/draw/engines/select/select_debug_engine.c new file mode 100644 index 00000000000..ded96be23f3 --- /dev/null +++ b/source/blender/draw/engines/select/select_debug_engine.c @@ -0,0 +1,135 @@ +/* + * 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. + * + * Copyright 2019, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + * + * Engine for debuging the selection map drawing. + */ + +#include "DNA_ID.h" +#include "DNA_vec_types.h" + +#include "DRW_engine.h" +#include "DRW_select_buffer.h" + +#include "draw_cache.h" +#include "draw_manager.h" + +#include "select_engine.h" + +#define SELECT_DEBUG_ENGINE "SELECT_DEBUG_ENGINE" + +/* -------------------------------------------------------------------- */ +/** \name Structs and static variables + * \{ */ + +typedef struct SELECTIDDEBUG_PassList { + struct DRWPass *debug_pass; +} SELECTIDDEBUG_PassList; + +typedef struct SELECTIDDEBUG_Data { + void *engine_type; + DRWViewportEmptyList *fbl; + DRWViewportEmptyList *txl; + SELECTIDDEBUG_PassList *psl; + DRWViewportEmptyList *stl; +} SELECTIDDEBUG_Data; + +static struct { + struct GPUShader *select_debug_sh; +} e_data = {{NULL}}; /* Engine data */ + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Engine Functions + * \{ */ + +static void select_debug_engine_init(void *vedata) +{ + SELECTIDDEBUG_PassList *psl = ((SELECTIDDEBUG_Data *)vedata)->psl; + + if (!e_data.select_debug_sh) { + e_data.select_debug_sh = DRW_shader_create_fullscreen( + "uniform usampler2D image;" + "in vec4 uvcoordsvar;" + "out vec4 fragColor;" + "void main() {" + " uint px = texture(image, uvcoordsvar.xy).r;" + " fragColor = vec4(1.0, 1.0, 1.0, 0.0);" + " if (px != 0u) {" + " fragColor.a = 1.0;" + " px &= 0x3Fu;" + " fragColor.r = ((px >> 0) & 0x3u) / float(0x3u);" + " fragColor.g = ((px >> 2) & 0x3u) / float(0x3u);" + " fragColor.b = ((px >> 4) & 0x3u) / float(0x3u);" + " }" + "}\n", + NULL); + } + + psl->debug_pass = DRW_pass_create("Debug Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA); + GPUTexture *texture_u32 = DRW_engine_select_texture_get(); + if (texture_u32) { + DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.select_debug_sh, psl->debug_pass); + DRW_shgroup_uniform_texture(shgrp, "image", texture_u32); + DRW_shgroup_call_procedural_triangles(shgrp, NULL, 1); + } +} + +static void select_debug_draw_scene(void *vedata) +{ + SELECTIDDEBUG_PassList *psl = ((SELECTIDDEBUG_Data *)vedata)->psl; + DRW_draw_pass(psl->debug_pass); +} + +static void select_debug_engine_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.select_debug_sh); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Engine Type + * \{ */ + +static const DrawEngineDataSize select_debug_data_size = DRW_VIEWPORT_DATA_SIZE( + SELECTIDDEBUG_Data); + +DrawEngineType draw_engine_debug_select_type = { + NULL, + NULL, + N_("Select ID Debug"), + &select_debug_data_size, + &select_debug_engine_init, + &select_debug_engine_free, + NULL, + NULL, + NULL, + &select_debug_draw_scene, + NULL, + NULL, + NULL, + NULL, +}; + +/** \} */ + +#undef SELECT_DEBUG_ENGINE diff --git a/source/blender/draw/engines/select/select_engine.h b/source/blender/draw/engines/select/select_engine.h index 2b35cf6bee5..d6192103178 100644 --- a/source/blender/draw/engines/select/select_engine.h +++ b/source/blender/draw/engines/select/select_engine.h @@ -22,9 +22,15 @@ #pragma once +/* select_engine.c */ extern DrawEngineType draw_engine_select_type; extern RenderEngineType DRW_engine_viewport_select_type; +#ifdef WITH_DRAW_DEBUG +/* select_debug_engine.c */ +extern DrawEngineType draw_engine_debug_select_type; +#endif + struct SELECTID_Context *DRW_select_engine_context_get(void); struct GPUFrameBuffer *DRW_engine_select_framebuffer_get(void); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 11e2856147f..027ab8ce32b 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1281,6 +1281,12 @@ static void drw_engines_enable(ViewLayer *UNUSED(view_layer), use_drw_engine(&draw_engine_gpencil_type); } drw_engines_enable_overlays(); + +#ifdef WITH_DRAW_DEBUG + if (G.debug_value == 31) { + use_drw_engine(&draw_engine_debug_select_type); + } +#endif } static void drw_engines_disable(void) @@ -2940,6 +2946,9 @@ void DRW_engines_register(void) DRW_engine_register(&draw_engine_overlay_type); DRW_engine_register(&draw_engine_select_type); DRW_engine_register(&draw_engine_basic_type); +#ifdef WITH_DRAW_DEBUG + DRW_engine_register(&draw_engine_debug_select_type); +#endif DRW_engine_register(&draw_engine_image_type); DRW_engine_register(DRW_engine_viewport_external_type.draw_engine); -- cgit v1.2.3 From b4f950cbbe5d1306f7bdcff6a288381759e04aeb Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Thu, 5 Aug 2021 17:06:21 +0200 Subject: GPencil: New Caps icons These icons are used to define the type of caps. Designed by: Matias Mendiola Reviewed by: Pablo Vazquez --- release/datafiles/blender_icons.svg | 15 +++++++++++++++ .../datafiles/blender_icons16/icon16_gp_caps_flat.dat | Bin 0 -> 1048 bytes .../datafiles/blender_icons16/icon16_gp_caps_round.dat | Bin 0 -> 1048 bytes .../datafiles/blender_icons32/icon32_gp_caps_flat.dat | Bin 0 -> 4120 bytes .../datafiles/blender_icons32/icon32_gp_caps_round.dat | Bin 0 -> 4120 bytes source/blender/editors/datafiles/CMakeLists.txt | 2 ++ source/blender/editors/include/UI_icons.h | 4 ++-- source/blender/makesrna/intern/rna_brush.c | 4 ++-- 8 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 release/datafiles/blender_icons16/icon16_gp_caps_flat.dat create mode 100644 release/datafiles/blender_icons16/icon16_gp_caps_round.dat create mode 100644 release/datafiles/blender_icons32/icon32_gp_caps_flat.dat create mode 100644 release/datafiles/blender_icons32/icon32_gp_caps_round.dat diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg index 54357550847..c3461fd1bea 100644 --- a/release/datafiles/blender_icons.svg +++ b/release/datafiles/blender_icons.svg @@ -17306,6 +17306,21 @@ d="m 418.85321,140.04954 -2.82,-2.82 a 0.62,0.62 0 0 0 -0.4,-0.18 0.6,0.6 0 0 0 -0.6,0.6 0.62,0.62 0 0 0 0.18,0.43 l 1,1 -9.18,9.12 -1,-1 a 0.62,0.62 0 0 0 -0.4,-0.15 0.6,0.6 0 0 0 -0.6,0.6 0.62,0.62 0 0 0 0.18,0.4 l 2.82,2.82 a 0.6,0.6 0 0 0 0.82,-0.82 l -1,-1 9.18,-9.15 1,1 a 0.6,0.6 0 0 0 0.82,-0.85 z" id="path3261" inkscape:connector-curvature="0" /> + + + + Date: Fri, 6 Aug 2021 00:08:56 +0900 Subject: Fix build error when WITH_XR_OPENXR not defined --- source/blender/makesrna/intern/rna_xr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/makesrna/intern/rna_xr.c b/source/blender/makesrna/intern/rna_xr.c index 358db14c298..57133ebe1c1 100644 --- a/source/blender/makesrna/intern/rna_xr.c +++ b/source/blender/makesrna/intern/rna_xr.c @@ -901,9 +901,13 @@ static void rna_XrSessionState_viewer_pose_rotation_get(PointerRNA *ptr, float * static void rna_XrSessionState_actionmaps_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { +# ifdef WITH_XR_OPENXR wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); ListBase *lb = WM_xr_actionmaps_get(xr->runtime); rna_iterator_listbase_begin(iter, lb, NULL); +# else + UNUSED_VARS(iter, ptr); +# endif } static int rna_XrSessionState_active_actionmap_get(PointerRNA *ptr) -- cgit v1.2.3 From 27b9cb7a1e675930d348300fb11446a0c6d35fde Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Thu, 5 Aug 2021 17:12:11 +0200 Subject: GPencil: New Merge Layer keymap: Shift+Ctrl+M The keymap is available in: Draw, Edit, Sculpt, Weight Paint and Vertex Paint modes. The keymap is not available in Object mode to avoid any conflict. Reviewed By: pepeland Differential Revision: https://developer.blender.org/D12128 --- .../scripts/presets/keyconfig/keymap_data/blender_default.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index a37577e898b..a67c5244611 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -3329,6 +3329,8 @@ def km_grease_pencil_stroke_edit_mode(params): ("gpencil.layer_isolate", {"type": 'NUMPAD_ASTERIX', "value": 'PRESS'}, None), # Move to layer op_menu("GPENCIL_MT_move_to_layer", {"type": 'M', "value": 'PRESS'}), + # Merge Layer + ("gpencil.layer_merge", {"type": 'M', "value": 'PRESS', "shift": True, "ctrl": True}, None), # Transform tools ("transform.translate", {"type": 'G', "value": 'PRESS'}, None), ("transform.translate", {"type": params.select_tweak, "value": 'ANY'}, None), @@ -3427,6 +3429,8 @@ def km_grease_pencil_stroke_paint_mode(params): {"properties": [("unselected", True)]}), # Active layer op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}), + # Merge Layer + ("gpencil.layer_merge", {"type": 'M', "value": 'PRESS', "shift": True, "ctrl": True}, None), # Active material op_menu("GPENCIL_MT_material_active", {"type": 'U', "value": 'PRESS'}), # Keyframe menu @@ -3592,6 +3596,8 @@ def km_grease_pencil_stroke_sculpt_mode(params): ("gpencil.active_frames_delete_all", {"type": 'DEL', "value": 'PRESS', "shift": True}, None), # Active layer op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}), + # Merge Layer + ("gpencil.layer_merge", {"type": 'M', "value": 'PRESS', "shift": True, "ctrl": True}, None), # Keyframe menu op_menu("VIEW3D_MT_gpencil_animation", {"type": 'I', "value": 'PRESS'}), # Context menu @@ -3809,6 +3815,8 @@ def km_grease_pencil_stroke_weight_mode(params): ("gpencil.active_frames_delete_all", {"type": 'DEL', "value": 'PRESS', "shift": True}, None), # Active layer op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}), + # Merge Layer + ("gpencil.layer_merge", {"type": 'M', "value": 'PRESS', "shift": True, "ctrl": True}, None), # Keyframe menu op_menu("VIEW3D_MT_gpencil_animation", {"type": 'I', "value": 'PRESS'}), # Context menu @@ -3873,6 +3881,8 @@ def km_grease_pencil_stroke_vertex_mode(params): ("gpencil.active_frames_delete_all", {"type": 'DEL', "value": 'PRESS', "shift": True}, None), # Active layer op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}), + # Merge Layer + ("gpencil.layer_merge", {"type": 'M', "value": 'PRESS', "shift": True, "ctrl": True}, None), # Keyframe menu op_menu("VIEW3D_MT_gpencil_animation", {"type": 'I', "value": 'PRESS'}), # Vertex Paint context menu -- cgit v1.2.3 From 834523e2391b3c8dab393daa040e135d7b729f86 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 5 Aug 2021 16:48:16 +0200 Subject: Cleanup/Fix RNA array length accessors returning non-zero values in invalid cases. This was apparently done in two places only, with a very cryptic comment (`/* for raw_access, untested */`), and... I cannot see how returning a non-zero length value for an array that does not exist or is not accessible at least, would be anything but an obvious source of issues. Note that both commits adding those lines are from stone ages (2009): rBcbc2c1886dee and rB50e3bb7f5f34. --- source/blender/makesrna/intern/rna_constraint.c | 2 +- source/blender/makesrna/intern/rna_fcurve.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 3064703b02e..a0a0a41b58d 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -715,7 +715,7 @@ static int rna_SplineIKConstraint_joint_bindings_get_length(PointerRNA *ptr, length[0] = ikData->numpoints; } else { - length[0] = 256; /* for raw_access, untested */ + length[0] = 0; } return length[0]; diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index 1f187382980..a38bbd3d6d2 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -809,7 +809,7 @@ static int rna_FModifierGenerator_coefficients_get_length(PointerRNA *ptr, length[0] = gen->arraysize; } else { - length[0] = 100; /* for raw_access, untested */ + length[0] = 0; } return length[0]; -- cgit v1.2.3 From 6c326ba0a24f24763b751483a0ee0cc98abdd921 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 5 Aug 2021 17:17:15 +0200 Subject: Fix T83164: Spline IK `joint_bindings` parameter is broken. Code freeing the array would not properly reset its length value to zero. Note that this corrupted data could also be saved in .blend files, so had to bump fileversion and add some doversion code too. Fix T90166: crash when creating a liboverride. --- source/blender/blenkernel/BKE_blender_version.h | 2 +- source/blender/blenkernel/intern/constraint.c | 4 +- source/blender/blenloader/intern/versioning_300.c | 51 +++++++++++++++++------ source/blender/editors/object/object_constraint.c | 7 +--- 4 files changed, 43 insertions(+), 21 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 0d5835a5eed..5ef56fab9cb 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -39,7 +39,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 16 +#define BLENDER_FILE_SUBVERSION 17 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 022073b0f12..b7e02f06571 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -4616,9 +4616,7 @@ static void splineik_free(bConstraint *con) bSplineIKConstraint *data = con->data; /* binding array */ - if (data->points) { - MEM_freeN(data->points); - } + MEM_SAFE_FREE(data->points); } static void splineik_copy(bConstraint *con, bConstraint *srccon) diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c index 7df4d2d93ec..42af8f4bda2 100644 --- a/source/blender/blenloader/intern/versioning_300.c +++ b/source/blender/blenloader/intern/versioning_300.c @@ -29,6 +29,7 @@ #include "DNA_armature_types.h" #include "DNA_brush_types.h" #include "DNA_collection_types.h" +#include "DNA_constraint_types.h" #include "DNA_curve_types.h" #include "DNA_genfile.h" #include "DNA_listBase.h" @@ -383,6 +384,19 @@ static void do_version_bones_bbone_len_scale(ListBase *lb) } } +static void do_version_constraints_spline_ik_joint_bindings(ListBase *lb) +{ + /* Binding array data could be freed without properly resetting its size data. */ + LISTBASE_FOREACH (bConstraint *, con, lb) { + if (con->type == CONSTRAINT_TYPE_SPLINEIK) { + bSplineIKConstraint *data = (bSplineIKConstraint *)con->data; + if (data->points == NULL) { + data->numpoints = 0; + } + } + } +} + /* NOLINTNEXTLINE: readability-function-size */ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) { @@ -697,18 +711,7 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) BKE_main_id_repair_duplicate_names_listbase(lb); } - /** - * Versioning code until next subversion bump goes here. - * - * \note Be sure to check when bumping the version: - * - "versioning_userdef.c", #blo_do_versions_userdef - * - "versioning_userdef.c", #do_versions_theme - * - * \note Keep this message at the bottom of the function. - */ - { - /* Keep this block, even when empty. */ - + if (!MAIN_VERSION_ATLEAST(bmain, 300, 17)) { if (!DNA_struct_elem_find( fd->filesdna, "View3DOverlay", "float", "normals_constant_screen_size")) { LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) { @@ -722,5 +725,29 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + + /* Fix SplineIK constraint's inconsistency between binding points array and its stored size. */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + /* NOTE: Objects should never have SplineIK constraint, so no need to apply this fix on + * their constraints. */ + if (ob->pose) { + LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { + do_version_constraints_spline_ik_joint_bindings(&pchan->constraints); + } + } + } + } + + /** + * Versioning code until next subversion bump goes here. + * + * \note Be sure to check when bumping the version: + * - "versioning_userdef.c", #blo_do_versions_userdef + * - "versioning_userdef.c", #do_versions_theme + * + * \note Keep this message at the bottom of the function. + */ + { + /* Keep this block, even when empty. */ } } diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 4970338973d..3d0213f1830 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -432,11 +432,8 @@ static void test_constraint( * free the points array and request a rebind... */ if ((data->points == NULL) || (data->numpoints != data->chainlen + 1)) { - /* free the points array */ - if (data->points) { - MEM_freeN(data->points); - data->points = NULL; - } + MEM_SAFE_FREE(data->points); + data->numpoints = 0; /* clear the bound flag, forcing a rebind next time this is evaluated */ data->flag &= ~CONSTRAINT_SPLINEIK_BOUND; -- cgit v1.2.3 From ca64bd0aacdaa9fcf75d693321d4d73c4a6a991a Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 4 Aug 2021 19:43:40 +0200 Subject: Render: move Cycles visibility, holdout and shadow catcher properties to Blender The immediate reason for this is that we want to be able to initialize them to different defaults for light objects, which is hard with Python properties. But in general it is useful to be able to share these with other renderers. As a side effect, Eevee now supports a per-object holdout instead of only per-collection. Differential Revision: https://developer.blender.org/D12133 --- intern/cycles/blender/addon/properties.py | 21 --------- intern/cycles/blender/addon/ui.py | 19 ++++---- intern/cycles/blender/blender_object.cpp | 6 +-- intern/cycles/blender/blender_util.h | 13 +++--- release/scripts/startup/bl_ui/properties_object.py | 4 ++ source/blender/blenkernel/intern/layer.c | 2 +- source/blender/blenkernel/intern/object.c | 6 +++ .../blender/blenloader/intern/versioning_cycles.c | 37 +++++++++++++++ source/blender/makesdna/DNA_object_types.h | 16 +++++-- source/blender/makesrna/intern/rna_object.c | 53 ++++++++++++++++++++++ 10 files changed, 129 insertions(+), 48 deletions(-) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 70efb1054a2..124223635d1 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -1164,12 +1164,6 @@ class CyclesVisibilitySettings(bpy.types.PropertyGroup): @classmethod def register(cls): - bpy.types.Object.cycles_visibility = PointerProperty( - name="Cycles Visibility Settings", - description="Cycles visibility settings", - type=cls, - ) - bpy.types.World.cycles_visibility = PointerProperty( name="Cycles Visibility Settings", description="Cycles visibility settings", @@ -1178,7 +1172,6 @@ class CyclesVisibilitySettings(bpy.types.PropertyGroup): @classmethod def unregister(cls): - del bpy.types.Object.cycles_visibility del bpy.types.World.cycles_visibility @@ -1276,20 +1269,6 @@ class CyclesObjectSettings(bpy.types.PropertyGroup): subtype='DISTANCE', ) - is_shadow_catcher: BoolProperty( - name="Shadow Catcher", - description="Only render shadows on this object, for compositing renders into real footage", - default=False, - ) - - is_holdout: BoolProperty( - name="Holdout", - description="Render objects as a holdout or matte, creating a " - "hole in the image with zero alpha, to fill out in " - "compositing with real footage or another render", - default=False, - ) - @classmethod def register(cls): bpy.types.Object.cycles = PointerProperty( diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index e804f697571..47f7b4c6d73 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1270,10 +1270,9 @@ class CYCLES_OBJECT_PT_visibility(CyclesButtonsPanel, Panel): col.prop(ob, "hide_render", text="Renders", invert_checkbox=True, toggle=False) if has_geometry_visibility(ob): - cob = ob.cycles col = layout.column(heading="Mask") - col.prop(cob, "is_shadow_catcher") - col.prop(cob, "is_holdout") + col.prop(ob, "is_shadow_catcher") + col.prop(ob, "is_holdout") class CYCLES_OBJECT_PT_visibility_ray_visibility(CyclesButtonsPanel, Panel): @@ -1293,19 +1292,17 @@ class CYCLES_OBJECT_PT_visibility_ray_visibility(CyclesButtonsPanel, Panel): scene = context.scene ob = context.object - cob = ob.cycles - visibility = ob.cycles_visibility col = layout.column() - col.prop(visibility, "camera") - col.prop(visibility, "diffuse") - col.prop(visibility, "glossy") - col.prop(visibility, "transmission") - col.prop(visibility, "scatter") + col.prop(ob, "visible_camera", text="Camera") + col.prop(ob, "visible_diffuse", text="Diffuse") + col.prop(ob, "visible_glossy", text="Glossy") + col.prop(ob, "visible_transmission", text="Transmission") + col.prop(ob, "visible_volume_scatter", text="Volume Scatter") if ob.type != 'LIGHT': sub = col.column() - sub.prop(visibility, "shadow") + sub.prop(ob, "visible_shadow", text="Shadow") class CYCLES_OBJECT_PT_visibility_culling(CyclesButtonsPanel, Panel): diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 65b5ac2c58f..4711e0cbe76 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -199,8 +199,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, /* Visibility flags for both parent and child. */ PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles"); - bool use_holdout = get_boolean(cobject, "is_holdout") || - b_parent.holdout_get(PointerRNA_NULL, b_view_layer); + bool use_holdout = b_parent.holdout_get(PointerRNA_NULL, b_view_layer); uint visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL_VISIBILITY; if (b_parent.ptr.data != b_ob.ptr.data) { @@ -287,8 +286,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, object->set_visibility(visibility); - bool is_shadow_catcher = get_boolean(cobject, "is_shadow_catcher"); - object->set_is_shadow_catcher(is_shadow_catcher); + object->set_is_shadow_catcher(b_ob.is_shadow_catcher()); float shadow_terminator_shading_offset = get_float(cobject, "shadow_terminator_offset"); object->set_shadow_terminator_shading_offset(shadow_terminator_shading_offset); diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index 43dbb4105df..2b2188b023d 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -596,15 +596,14 @@ static inline Mesh::SubdivisionType object_subdivision_type(BL::Object &b_ob, static inline uint object_ray_visibility(BL::Object &b_ob) { - PointerRNA cvisibility = RNA_pointer_get(&b_ob.ptr, "cycles_visibility"); uint flag = 0; - flag |= get_boolean(cvisibility, "camera") ? PATH_RAY_CAMERA : 0; - flag |= get_boolean(cvisibility, "diffuse") ? PATH_RAY_DIFFUSE : 0; - flag |= get_boolean(cvisibility, "glossy") ? PATH_RAY_GLOSSY : 0; - flag |= get_boolean(cvisibility, "transmission") ? PATH_RAY_TRANSMIT : 0; - flag |= get_boolean(cvisibility, "shadow") ? PATH_RAY_SHADOW : 0; - flag |= get_boolean(cvisibility, "scatter") ? PATH_RAY_VOLUME_SCATTER : 0; + flag |= b_ob.visible_camera() ? PATH_RAY_CAMERA : 0; + flag |= b_ob.visible_diffuse() ? PATH_RAY_DIFFUSE : 0; + flag |= b_ob.visible_glossy() ? PATH_RAY_GLOSSY : 0; + flag |= b_ob.visible_transmission() ? PATH_RAY_TRANSMIT : 0; + flag |= b_ob.visible_shadow() ? PATH_RAY_SHADOW : 0; + flag |= b_ob.visible_volume_scatter() ? PATH_RAY_VOLUME_SCATTER : 0; return flag; } diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py index 4ea1ec26738..46a16a70dca 100644 --- a/release/scripts/startup/bl_ui/properties_object.py +++ b/release/scripts/startup/bl_ui/properties_object.py @@ -399,6 +399,10 @@ class OBJECT_PT_visibility(ObjectButtonsPanel, Panel): col = layout.column(heading="Grease Pencil") col.prop(ob, "use_grease_pencil_lights", toggle=False) + layout.separator() + col = layout.column(heading="Mask") + col.prop(ob, "is_holdout") + class OBJECT_PT_custom_props(ObjectButtonsPanel, PropertyPanel, Panel): COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'} diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index 5940569ba76..e7d83c668c8 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -1020,7 +1020,7 @@ static void layer_collection_objects_sync(ViewLayer *view_layer, } /* Holdout and indirect only */ - if (layer->flag & LAYER_COLLECTION_HOLDOUT) { + if ((layer->flag & LAYER_COLLECTION_HOLDOUT) || (base->object->visibility_flag & OB_HOLDOUT)) { base->flag_from_collection |= BASE_HOLDOUT; } if (layer->flag & LAYER_COLLECTION_INDIRECT_ONLY) { diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 6a309e040c0..f969ca0ff1c 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2081,6 +2081,12 @@ static void object_init(Object *ob, const short ob_type) if (ob->type == OB_GPENCIL) { ob->dtx |= OB_USE_GPENCIL_LIGHTS; } + + if (ob->type == OB_LAMP) { + /* Lights are invisible to camera rays and are assumed to be a + * shadow catcher by default. */ + ob->visibility_flag |= OB_HIDE_CAMERA | OB_SHADOW_CATCHER; + } } void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name) diff --git a/source/blender/blenloader/intern/versioning_cycles.c b/source/blender/blenloader/intern/versioning_cycles.c index 94ee89c5120..90e6b43f02e 100644 --- a/source/blender/blenloader/intern/versioning_cycles.c +++ b/source/blender/blenloader/intern/versioning_cycles.c @@ -78,6 +78,12 @@ static IDProperty *cycles_properties_from_ID(ID *id) return (idprop) ? IDP_GetPropertyTypeFromGroup(idprop, "cycles", IDP_GROUP) : NULL; } +static IDProperty *cycles_visibility_properties_from_ID(ID *id) +{ + IDProperty *idprop = IDP_GetProperties(id, false); + return (idprop) ? IDP_GetPropertyTypeFromGroup(idprop, "cycles_visibility", IDP_GROUP) : NULL; +} + static IDProperty *cycles_properties_from_view_layer(ViewLayer *view_layer) { IDProperty *idprop = view_layer->id_properties; @@ -1600,4 +1606,35 @@ void do_versions_after_linking_cycles(Main *bmain) } } } + + /* Move visibility from Cycles to Blender. */ + if (!MAIN_VERSION_ATLEAST(bmain, 300, 17)) { + LISTBASE_FOREACH (Object *, object, &bmain->objects) { + IDProperty *cvisibility = cycles_visibility_properties_from_ID(&object->id); + int flag = 0; + + if (cvisibility) { + flag |= cycles_property_boolean(cvisibility, "camera", true) ? 0 : OB_HIDE_CAMERA; + flag |= cycles_property_boolean(cvisibility, "diffuse", true) ? 0 : OB_HIDE_DIFFUSE; + flag |= cycles_property_boolean(cvisibility, "glossy", true) ? 0 : OB_HIDE_GLOSSY; + flag |= cycles_property_boolean(cvisibility, "transmission", true) ? 0 : + OB_HIDE_TRANSMISSION; + flag |= cycles_property_boolean(cvisibility, "scatter", true) ? 0 : OB_HIDE_VOLUME_SCATTER; + flag |= cycles_property_boolean(cvisibility, "shadow", true) ? 0 : OB_HIDE_SHADOW; + } + + IDProperty *cobject = cycles_properties_from_ID(&object->id); + if (cobject) { + flag |= cycles_property_boolean(cobject, "is_holdout", false) ? OB_HOLDOUT : 0; + flag |= cycles_property_boolean(cobject, "is_shadow_catcher", false) ? OB_SHADOW_CATCHER : + 0; + } + + if (object->type == OB_LAMP) { + flag |= OB_HIDE_CAMERA | OB_SHADOW_CATCHER; + } + + object->visibility_flag |= flag; + } + } } diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index a37536f7022..e7091c78f71 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -385,14 +385,14 @@ typedef struct Object { short softflag; /** For restricting view, select, render etc. accessible in outliner. */ - char visibility_flag; + short visibility_flag; - /** Flag for pinning. */ - char shapeflag; /** Current shape key for menu or pinned. */ short shapenr; + /** Flag for pinning. */ + char shapeflag; - char _pad3[2]; + char _pad3[1]; /** Object constraints. */ ListBase constraints; @@ -675,6 +675,14 @@ enum { OB_HIDE_VIEWPORT = 1 << 0, OB_HIDE_SELECT = 1 << 1, OB_HIDE_RENDER = 1 << 2, + OB_HIDE_CAMERA = 1 << 3, + OB_HIDE_DIFFUSE = 1 << 4, + OB_HIDE_GLOSSY = 1 << 5, + OB_HIDE_TRANSMISSION = 1 << 6, + OB_HIDE_VOLUME_SCATTER = 1 << 7, + OB_HIDE_SHADOW = 1 << 8, + OB_HOLDOUT = 1 << 9, + OB_SHADOW_CATCHER = 1 << 10 }; /* ob->shapeflag */ diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index f0b83f3eb46..bef430b0314 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -2963,6 +2963,59 @@ static void rna_def_object_visibility(StructRNA *srna) RNA_def_property_ui_text(prop, "Display Instancer", "Make instancer visible in the viewport"); RNA_def_property_update( prop, NC_OBJECT | ND_DRAW, "rna_Object_duplicator_visibility_flag_update"); + + /* Ray visibility. */ + prop = RNA_def_property(srna, "visible_camera", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "visibility_flag", OB_HIDE_CAMERA); + RNA_def_property_ui_text(prop, "Camera Visibility", "Object visibility to camera rays"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update_draw"); + + prop = RNA_def_property(srna, "visible_diffuse", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "visibility_flag", OB_HIDE_DIFFUSE); + RNA_def_property_ui_text(prop, "Diffuse Visibility", "Object visibility to diffuse rays"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update_draw"); + + prop = RNA_def_property(srna, "visible_glossy", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "visibility_flag", OB_HIDE_GLOSSY); + RNA_def_property_ui_text(prop, "Glossy Visibility", "Object visibility to glossy rays"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update_draw"); + + prop = RNA_def_property(srna, "visible_transmission", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "visibility_flag", OB_HIDE_TRANSMISSION); + RNA_def_property_ui_text( + prop, "Transmission Visibility", "Object visibility to transmission rays"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update_draw"); + + prop = RNA_def_property(srna, "visible_volume_scatter", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "visibility_flag", OB_HIDE_VOLUME_SCATTER); + RNA_def_property_ui_text( + prop, "Volume Scatter Visibility", "Object visibility to volume scattering rays"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update_draw"); + + prop = RNA_def_property(srna, "visible_shadow", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "visibility_flag", OB_HIDE_SHADOW); + RNA_def_property_ui_text(prop, "Shadow Visibility", "Object visibility to shadow rays"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update_draw"); + + /* Holdout and shadow catcher. */ + prop = RNA_def_property(srna, "is_holdout", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "visibility_flag", OB_HOLDOUT); + RNA_def_property_ui_text( + prop, + "Holdout", + "Render objects as a holdout or matte, creating a hole in the image with zero alpha, to " + "fill out in compositing with real footage or another render"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update"); + + prop = RNA_def_property(srna, "is_shadow_catcher", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "visibility_flag", OB_SHADOW_CATCHER); + RNA_def_property_ui_text( + prop, + "Shadow Catcher", + "Only render shadows and reflections on this object, for compositing renders into real " + "footage. Objects with this setting are considered to already exist in the footage, " + "objects without it are synthetic objects being composited into it"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update_draw"); } static void rna_def_object(BlenderRNA *brna) -- cgit v1.2.3 From 8158211198b7a27812ddf90bf0d1df0cd9e55afb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 6 Aug 2021 01:32:04 +1000 Subject: Cleanup: quiet array-parameter warning --- source/blender/makesrna/intern/rna_xr.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/source/blender/makesrna/intern/rna_xr.c b/source/blender/makesrna/intern/rna_xr.c index 57133ebe1c1..9a512e351cb 100644 --- a/source/blender/makesrna/intern/rna_xr.c +++ b/source/blender/makesrna/intern/rna_xr.c @@ -829,7 +829,7 @@ void rna_XrSessionState_haptic_action_stop(bContext *C, static void rna_XrSessionState_controller_grip_location_get(bContext *C, int *index, - float *r_values) + float r_values[3]) { # ifdef WITH_XR_OPENXR const wmWindowManager *wm = CTX_wm_manager(C); @@ -842,7 +842,7 @@ static void rna_XrSessionState_controller_grip_location_get(bContext *C, static void rna_XrSessionState_controller_grip_rotation_get(bContext *C, int index, - float *r_values) + float r_values[4]) { # ifdef WITH_XR_OPENXR const wmWindowManager *wm = CTX_wm_manager(C); @@ -855,7 +855,7 @@ static void rna_XrSessionState_controller_grip_rotation_get(bContext *C, static void rna_XrSessionState_controller_aim_location_get(bContext *C, int *index, - float *r_values) + float r_values[3]) { # ifdef WITH_XR_OPENXR const wmWindowManager *wm = CTX_wm_manager(C); @@ -866,7 +866,9 @@ static void rna_XrSessionState_controller_aim_location_get(bContext *C, # endif } -static void rna_XrSessionState_controller_aim_rotation_get(bContext *C, int index, float *r_values) +static void rna_XrSessionState_controller_aim_rotation_get(bContext *C, + int index, + float r_values[4]) { # ifdef WITH_XR_OPENXR const wmWindowManager *wm = CTX_wm_manager(C); -- cgit v1.2.3 From ff2265f0a9269ad5e95f77ded3c9692d656955c7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 6 Aug 2021 01:36:43 +1000 Subject: Cleanup: comment blocks & spelling --- intern/ghost/intern/GHOST_XrAction.h | 8 ++++---- .../compositor/operations/COM_DilateErodeOperation.cc | 2 +- .../blender/depsgraph/intern/builder/deg_builder_rna.cc | 4 ++-- source/blender/makesdna/DNA_xr_types.h | 16 ++++++++++------ 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/intern/ghost/intern/GHOST_XrAction.h b/intern/ghost/intern/GHOST_XrAction.h index 73a1cd9cd6a..70eaa694ae9 100644 --- a/intern/ghost/intern/GHOST_XrAction.h +++ b/intern/ghost/intern/GHOST_XrAction.h @@ -18,8 +18,8 @@ * \ingroup GHOST */ -/* Note: Requires OpenXR headers to be included before this one for OpenXR types (XrSpace, XrPath, - * etc.). */ +/* NOTE: Requires OpenXR headers to be included before this one for OpenXR types + * (XrSpace, XrPath, etc.). */ #pragma once @@ -78,9 +78,9 @@ class GHOST_XrActionProfile { private: XrPath m_profile = XR_NULL_PATH; - /** Subaction data identified by user (subaction) path. */ + /** Sub-action data identified by user `subaction` path. */ std::map m_subaction_data; - /** Bindings identified by interaction (user (subaction) + component) path. */ + /** Bindings identified by interaction (user `subaction` + component) path. */ std::map m_bindings; }; diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cc b/source/blender/compositor/operations/COM_DilateErodeOperation.cc index e9305e0e192..c67a35b686c 100644 --- a/source/blender/compositor/operations/COM_DilateErodeOperation.cc +++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cc @@ -370,7 +370,7 @@ void *DilateStepOperation::initializeTileData(rcti *rect) int bwidth = rect->xmax - rect->xmin; int bheight = rect->ymax - rect->ymin; - /* NOTE: Cache buffer has original tilesize width, but new height. + /* NOTE: Cache buffer has original tile-size width, but new height. * We have to calculate the additional rows in the first pass, * to have valid data available for the second pass. */ tile_info *result = create_cache(rect->xmin, rect->xmax, ymin, ymax); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc index bdabd67cc07..40e59875832 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc @@ -400,8 +400,8 @@ RNANodeQueryIDData *RNANodeQuery::ensure_id_data(const ID *id) bool rna_prop_affects_parameters_node(const PointerRNA *ptr, const PropertyRNA *prop) { return prop != nullptr && RNA_property_is_idprop(prop) && - /* ID properties in the geometry nodes modifier don't affect that parameters node. Instead - they affect the modifier and therefore the geometry node directly. */ + /* ID properties in the geometry nodes modifier don't affect that parameters node. + * Instead they affect the modifier and therefore the geometry node directly. */ !RNA_struct_is_a(ptr->type, &RNA_NodesModifier); } diff --git a/source/blender/makesdna/DNA_xr_types.h b/source/blender/makesdna/DNA_xr_types.h index 2e348ce6855..a9d427777f7 100644 --- a/source/blender/makesdna/DNA_xr_types.h +++ b/source/blender/makesdna/DNA_xr_types.h @@ -34,7 +34,7 @@ typedef struct XrSessionSettings { char _pad[7]; - char base_pose_type; /* eXRSessionBasePoseType */ + char base_pose_type; /* #eXRSessionBasePoseType */ /** Object to take the location and rotation as base position from. */ Object *base_pose_object; float base_pose_location[3]; @@ -78,22 +78,26 @@ typedef enum eXrOpFlag { } eXrOpFlag; typedef enum eXrActionFlag { - /** Action depends on two subaction paths (i.e. two-handed/bimanual action). */ + /** Action depends on two sub-action paths (i.e. two-handed/bi-manual action). */ XR_ACTION_BIMANUAL = (1 << 0), } eXrActionFlag; typedef enum eXrHapticFlag { /** Whether to apply haptics to corresponding user paths for an action and its haptic action. */ XR_HAPTIC_MATCHUSERPATHS = (1 << 0), - /** Determines how haptics will be applied ("repeat" is mutually exclusive with - "press"/"release"). */ + /** + * Determines how haptics will be applied + * ("repeat" is mutually exclusive with "press"/"release"). + */ XR_HAPTIC_PRESS = (1 << 1), XR_HAPTIC_RELEASE = (1 << 2), XR_HAPTIC_REPEAT = (1 << 3), } eXrHapticFlag; -/** For axis-based inputs (thumbstick/trackpad/etc). Determines the region for action execution - * (mutually exclusive per axis). */ +/** + * For axis-based inputs (thumb-stick/track-pad/etc). + * Determines the region for action execution (mutually exclusive per axis). + */ typedef enum eXrAxisFlag { XR_AXIS0_POS = (1 << 0), XR_AXIS0_NEG = (1 << 1), -- cgit v1.2.3 From 04c24bec07c1671b78d94bfd530230ec533fae8e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 6 Aug 2021 01:42:01 +1000 Subject: Cleanup: replace short with boolean for zero area array Also remove redundant fabsf on the area of a quad/tri & reduce indentation using continue in for loop. --- .../blender/bmesh/operators/bmo_smooth_laplacian.c | 314 +++++++++++---------- .../blender/modifiers/intern/MOD_laplaciansmooth.c | 24 +- 2 files changed, 171 insertions(+), 167 deletions(-) diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c index 1d72bb893b2..eb25923d1d1 100644 --- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c +++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c @@ -44,7 +44,7 @@ struct BLaplacianSystem { int numEdges; /* Number of edges. */ int numFaces; /* Number of faces. */ int numVerts; /* Number of verts. */ - short *zerola; /* Is zero area or length. */ + bool *zerola; /* Is zero area or length. */ /* Pointers to data. */ BMesh *bm; @@ -98,7 +98,7 @@ static void memset_laplacian_system(LaplacianSystem *sys, int val) memset(sys->ring_areas, val, sizeof(float) * sys->numVerts); memset(sys->vlengths, val, sizeof(float) * sys->numVerts); memset(sys->vweights, val, sizeof(float) * sys->numVerts); - memset(sys->zerola, val, sizeof(short) * sys->numVerts); + memset(sys->zerola, val, sizeof(bool) * sys->numVerts); } static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts) @@ -139,7 +139,7 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, in return NULL; } - sys->zerola = MEM_callocN(sizeof(short) * sys->numVerts, "ModLaplSmoothZeloa"); + sys->zerola = MEM_callocN(sizeof(bool) * sys->numVerts, "ModLaplSmoothZeloa"); if (!sys->zerola) { delete_laplacian_system(sys); return NULL; @@ -181,104 +181,107 @@ static void init_laplacian_matrix(LaplacianSystem *sys) BMVert *vf[4]; BM_ITER_MESH_INDEX (e, &eiter, sys->bm, BM_EDGES_OF_MESH, i) { - if (!BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_boundary(e)) { - v1 = e->v1->co; - v2 = e->v2->co; - idv1 = BM_elem_index_get(e->v1); - idv2 = BM_elem_index_get(e->v2); - - w1 = len_v3v3(v1, v2); - if (w1 > sys->min_area) { - w1 = 1.0f / w1; - sys->eweights[i] = w1; - sys->vlengths[idv1] += w1; - sys->vlengths[idv2] += w1; - } - else { - sys->zerola[idv1] = 1; - sys->zerola[idv2] = 1; - } + if (BM_elem_flag_test(e, BM_ELEM_SELECT) || !BM_edge_is_boundary(e)) { + continue; + } + + v1 = e->v1->co; + v2 = e->v2->co; + idv1 = BM_elem_index_get(e->v1); + idv2 = BM_elem_index_get(e->v2); + + w1 = len_v3v3(v1, v2); + if (w1 > sys->min_area) { + w1 = 1.0f / w1; + sys->eweights[i] = w1; + sys->vlengths[idv1] += w1; + sys->vlengths[idv2] += w1; + } + else { + sys->zerola[idv1] = true; + sys->zerola[idv2] = true; } } BM_ITER_MESH_INDEX (f, &fiter, sys->bm, BM_FACES_OF_MESH, i) { - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - - BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, j) { - vf[j] = vn; - } - has_4_vert = (j == 4) ? 1 : 0; - idv1 = BM_elem_index_get(vf[0]); - idv2 = BM_elem_index_get(vf[1]); - idv3 = BM_elem_index_get(vf[2]); - idv4 = has_4_vert ? BM_elem_index_get(vf[3]) : 0; + if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) { + continue; + } - v1 = vf[0]->co; - v2 = vf[1]->co; - v3 = vf[2]->co; - v4 = has_4_vert ? vf[3]->co : NULL; + BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, j) { + vf[j] = vn; + } + has_4_vert = (j == 4) ? 1 : 0; + idv1 = BM_elem_index_get(vf[0]); + idv2 = BM_elem_index_get(vf[1]); + idv3 = BM_elem_index_get(vf[2]); + idv4 = has_4_vert ? BM_elem_index_get(vf[3]) : 0; + + v1 = vf[0]->co; + v2 = vf[1]->co; + v3 = vf[2]->co; + v4 = has_4_vert ? vf[3]->co : NULL; + + if (has_4_vert) { + areaf = area_quad_v3(v1, v2, v3, v4); + } + else { + areaf = area_tri_v3(v1, v2, v3); + } + if (areaf < sys->min_area) { + sys->zerola[idv1] = true; + sys->zerola[idv2] = true; + sys->zerola[idv3] = true; if (has_4_vert) { - areaf = area_quad_v3(v1, v2, v3, v4); - } - else { - areaf = area_tri_v3(v1, v2, v3); - } - - if (fabsf(areaf) < sys->min_area) { - sys->zerola[idv1] = 1; - sys->zerola[idv2] = 1; - sys->zerola[idv3] = 1; - if (has_4_vert) { - sys->zerola[idv4] = 1; - } + sys->zerola[idv4] = true; } + } - sys->ring_areas[idv1] += areaf; - sys->ring_areas[idv2] += areaf; - sys->ring_areas[idv3] += areaf; - if (has_4_vert) { - sys->ring_areas[idv4] += areaf; - } + sys->ring_areas[idv1] += areaf; + sys->ring_areas[idv2] += areaf; + sys->ring_areas[idv3] += areaf; + if (has_4_vert) { + sys->ring_areas[idv4] += areaf; + } - if (has_4_vert) { + if (has_4_vert) { - idv[0] = idv1; - idv[1] = idv2; - idv[2] = idv3; - idv[3] = idv4; + idv[0] = idv1; + idv[1] = idv2; + idv[2] = idv3; + idv[3] = idv4; - for (j = 0; j < 4; j++) { - idv1 = idv[j]; - idv2 = idv[(j + 1) % 4]; - idv3 = idv[(j + 2) % 4]; - idv4 = idv[(j + 3) % 4]; + for (j = 0; j < 4; j++) { + idv1 = idv[j]; + idv2 = idv[(j + 1) % 4]; + idv3 = idv[(j + 2) % 4]; + idv4 = idv[(j + 3) % 4]; - v1 = vf[j]->co; - v2 = vf[(j + 1) % 4]->co; - v3 = vf[(j + 2) % 4]->co; - v4 = vf[(j + 3) % 4]->co; + v1 = vf[j]->co; + v2 = vf[(j + 1) % 4]->co; + v3 = vf[(j + 2) % 4]->co; + v4 = vf[(j + 3) % 4]->co; - w2 = cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2); - w3 = cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3); - w4 = cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1); + w2 = cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2); + w3 = cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3); + w4 = cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1); - sys->vweights[idv1] += (w2 + w3 + w4) / 4.0f; - } + sys->vweights[idv1] += (w2 + w3 + w4) / 4.0f; } - else { - w1 = cotangent_tri_weight_v3(v1, v2, v3); - w2 = cotangent_tri_weight_v3(v2, v3, v1); - w3 = cotangent_tri_weight_v3(v3, v1, v2); + } + else { + w1 = cotangent_tri_weight_v3(v1, v2, v3); + w2 = cotangent_tri_weight_v3(v2, v3, v1); + w3 = cotangent_tri_weight_v3(v3, v1, v2); - sys->fweights[i][0] += w1; - sys->fweights[i][1] += w2; - sys->fweights[i][2] += w3; + sys->fweights[i][0] += w1; + sys->fweights[i][1] += w2; + sys->fweights[i][2] += w3; - sys->vweights[idv1] += w2 + w3; - sys->vweights[idv2] += w1 + w3; - sys->vweights[idv3] += w1 + w2; - } + sys->vweights[idv1] += w2 + w3; + sys->vweights[idv2] += w1 + w3; + sys->vweights[idv3] += w1 + w2; } } } @@ -300,82 +303,83 @@ static void fill_laplacian_matrix(LaplacianSystem *sys) BMVert *vf[4]; BM_ITER_MESH_INDEX (f, &fiter, sys->bm, BM_FACES_OF_MESH, i) { - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, j) { - vf[j] = vn; - } - has_4_vert = (j == 4) ? 1 : 0; - if (has_4_vert) { - idv[0] = BM_elem_index_get(vf[0]); - idv[1] = BM_elem_index_get(vf[1]); - idv[2] = BM_elem_index_get(vf[2]); - idv[3] = BM_elem_index_get(vf[3]); - for (j = 0; j < 4; j++) { - idv1 = idv[j]; - idv2 = idv[(j + 1) % 4]; - idv3 = idv[(j + 2) % 4]; - idv4 = idv[(j + 3) % 4]; - - v1 = vf[j]->co; - v2 = vf[(j + 1) % 4]->co; - v3 = vf[(j + 2) % 4]->co; - v4 = vf[(j + 3) % 4]->co; - - w2 = cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2); - w3 = cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3); - w4 = cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1); - - w2 = w2 / 4.0f; - w3 = w3 / 4.0f; - w4 = w4 / 4.0f; - - if (!vert_is_boundary(vf[j]) && sys->zerola[idv1] == 0) { - EIG_linear_solver_matrix_add(sys->context, idv1, idv2, w2 * sys->vweights[idv1]); - EIG_linear_solver_matrix_add(sys->context, idv1, idv3, w3 * sys->vweights[idv1]); - EIG_linear_solver_matrix_add(sys->context, idv1, idv4, w4 * sys->vweights[idv1]); - } - } - } - else { - idv1 = BM_elem_index_get(vf[0]); - idv2 = BM_elem_index_get(vf[1]); - idv3 = BM_elem_index_get(vf[2]); - /* Is ring if number of faces == number of edges around vertice. */ - if (!vert_is_boundary(vf[0]) && sys->zerola[idv1] == 0) { - EIG_linear_solver_matrix_add( - sys->context, idv1, idv2, sys->fweights[i][2] * sys->vweights[idv1]); - EIG_linear_solver_matrix_add( - sys->context, idv1, idv3, sys->fweights[i][1] * sys->vweights[idv1]); - } - if (!vert_is_boundary(vf[1]) && sys->zerola[idv2] == 0) { - EIG_linear_solver_matrix_add( - sys->context, idv2, idv1, sys->fweights[i][2] * sys->vweights[idv2]); - EIG_linear_solver_matrix_add( - sys->context, idv2, idv3, sys->fweights[i][0] * sys->vweights[idv2]); - } - if (!vert_is_boundary(vf[2]) && sys->zerola[idv3] == 0) { - EIG_linear_solver_matrix_add( - sys->context, idv3, idv1, sys->fweights[i][1] * sys->vweights[idv3]); - EIG_linear_solver_matrix_add( - sys->context, idv3, idv2, sys->fweights[i][0] * sys->vweights[idv3]); + if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) { + continue; + } + + BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, j) { + vf[j] = vn; + } + has_4_vert = (j == 4) ? 1 : 0; + if (has_4_vert) { + idv[0] = BM_elem_index_get(vf[0]); + idv[1] = BM_elem_index_get(vf[1]); + idv[2] = BM_elem_index_get(vf[2]); + idv[3] = BM_elem_index_get(vf[3]); + for (j = 0; j < 4; j++) { + idv1 = idv[j]; + idv2 = idv[(j + 1) % 4]; + idv3 = idv[(j + 2) % 4]; + idv4 = idv[(j + 3) % 4]; + + v1 = vf[j]->co; + v2 = vf[(j + 1) % 4]->co; + v3 = vf[(j + 2) % 4]->co; + v4 = vf[(j + 3) % 4]->co; + + w2 = cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2); + w3 = cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3); + w4 = cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1); + + w2 = w2 / 4.0f; + w3 = w3 / 4.0f; + w4 = w4 / 4.0f; + + if (!vert_is_boundary(vf[j]) && sys->zerola[idv1] == false) { + EIG_linear_solver_matrix_add(sys->context, idv1, idv2, w2 * sys->vweights[idv1]); + EIG_linear_solver_matrix_add(sys->context, idv1, idv3, w3 * sys->vweights[idv1]); + EIG_linear_solver_matrix_add(sys->context, idv1, idv4, w4 * sys->vweights[idv1]); } } } - } - BM_ITER_MESH_INDEX (e, &eiter, sys->bm, BM_EDGES_OF_MESH, i) { - if (!BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_boundary(e)) { - v1 = e->v1->co; - v2 = e->v2->co; - idv1 = BM_elem_index_get(e->v1); - idv2 = BM_elem_index_get(e->v2); - if (sys->zerola[idv1] == 0 && sys->zerola[idv2] == 0) { + else { + idv1 = BM_elem_index_get(vf[0]); + idv2 = BM_elem_index_get(vf[1]); + idv3 = BM_elem_index_get(vf[2]); + /* Is ring if number of faces == number of edges around vertice. */ + if (!vert_is_boundary(vf[0]) && sys->zerola[idv1] == false) { + EIG_linear_solver_matrix_add( + sys->context, idv1, idv2, sys->fweights[i][2] * sys->vweights[idv1]); + EIG_linear_solver_matrix_add( + sys->context, idv1, idv3, sys->fweights[i][1] * sys->vweights[idv1]); + } + if (!vert_is_boundary(vf[1]) && sys->zerola[idv2] == false) { + EIG_linear_solver_matrix_add( + sys->context, idv2, idv1, sys->fweights[i][2] * sys->vweights[idv2]); EIG_linear_solver_matrix_add( - sys->context, idv1, idv2, sys->eweights[i] * sys->vlengths[idv1]); + sys->context, idv2, idv3, sys->fweights[i][0] * sys->vweights[idv2]); + } + if (!vert_is_boundary(vf[2]) && sys->zerola[idv3] == false) { + EIG_linear_solver_matrix_add( + sys->context, idv3, idv1, sys->fweights[i][1] * sys->vweights[idv3]); EIG_linear_solver_matrix_add( - sys->context, idv2, idv1, sys->eweights[i] * sys->vlengths[idv2]); + sys->context, idv3, idv2, sys->fweights[i][0] * sys->vweights[idv3]); } } } + BM_ITER_MESH_INDEX (e, &eiter, sys->bm, BM_EDGES_OF_MESH, i) { + if (BM_elem_flag_test(e, BM_ELEM_SELECT) || !BM_edge_is_boundary(e)) { + continue; + } + idv1 = BM_elem_index_get(e->v1); + idv2 = BM_elem_index_get(e->v2); + if (sys->zerola[idv1] == false && sys->zerola[idv2] == false) { + EIG_linear_solver_matrix_add( + sys->context, idv1, idv2, sys->eweights[i] * sys->vlengths[idv1]); + EIG_linear_solver_matrix_add( + sys->context, idv2, idv1, sys->eweights[i] * sys->vlengths[idv2]); + } + } } static bool vert_is_boundary(BMVert *v) @@ -448,8 +452,8 @@ static void validate_solution( lene = len_v3v3(ve1, ve2); if (lene > leni * SMOOTH_LAPLACIAN_MAX_EDGE_PERCENTAGE || lene < leni * SMOOTH_LAPLACIAN_MIN_EDGE_PERCENTAGE) { - sys->zerola[idv1] = 1; - sys->zerola[idv2] = 1; + sys->zerola[idv1] = true; + sys->zerola[idv2] = true; } } @@ -458,7 +462,7 @@ static void validate_solution( } BMO_ITER (v, &siter, sys->op->slots_in, "verts", BM_VERT) { m_vertex_id = BM_elem_index_get(v); - if (sys->zerola[m_vertex_id] == 0) { + if (sys->zerola[m_vertex_id] == false) { if (usex) { v->co[0] = EIG_linear_solver_variable_get(sys->context, 0, m_vertex_id); } @@ -528,7 +532,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) EIG_linear_solver_right_hand_side_add(sys->context, 1, m_vertex_id, v->co[1]); EIG_linear_solver_right_hand_side_add(sys->context, 2, m_vertex_id, v->co[2]); i = m_vertex_id; - if ((sys->zerola[i] == 0) && + if ((sys->zerola[i] == false) && /* Non zero check is to account for vertices that aren't connected to a selected face. * Without this wire edges become `nan`, see T89214. */ (sys->ring_areas[i] != 0.0f)) { diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c index 63495c4104e..a36a8c386b4 100644 --- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c @@ -66,7 +66,7 @@ struct BLaplacianSystem { int numVerts; /* Number of verts. */ short *numNeFa; /* Number of neighbors faces around vertice. */ short *numNeEd; /* Number of neighbors Edges around vertice. */ - short *zerola; /* Is zero area or length. */ + bool *zerola; /* Is zero area or length. */ /* Pointers to data. */ float (*vertexCos)[3]; @@ -130,7 +130,7 @@ static void memset_laplacian_system(LaplacianSystem *sys, int val) memset(sys->ring_areas, val, sizeof(float) * sys->numVerts); memset(sys->vlengths, val, sizeof(float) * sys->numVerts); memset(sys->vweights, val, sizeof(float) * sys->numVerts); - memset(sys->zerola, val, sizeof(short) * sys->numVerts); + memset(sys->zerola, val, sizeof(bool) * sys->numVerts); } static LaplacianSystem *init_laplacian_system(int a_numEdges, @@ -152,7 +152,7 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, sys->ring_areas = MEM_calloc_arrayN(sys->numVerts, sizeof(float), __func__); sys->vlengths = MEM_calloc_arrayN(sys->numVerts, sizeof(float), __func__); sys->vweights = MEM_calloc_arrayN(sys->numVerts, sizeof(float), __func__); - sys->zerola = MEM_calloc_arrayN(sys->numVerts, sizeof(short), __func__); + sys->zerola = MEM_calloc_arrayN(sys->numVerts, sizeof(bool), __func__); return sys; } @@ -225,8 +225,8 @@ static void init_laplacian_matrix(LaplacianSystem *sys) sys->numNeEd[idv2] = sys->numNeEd[idv2] + 1; w1 = len_v3v3(v1, v2); if (w1 < sys->min_area) { - sys->zerola[idv1] = 1; - sys->zerola[idv2] = 1; + sys->zerola[idv1] = true; + sys->zerola[idv2] = true; } else { w1 = 1.0f / w1; @@ -253,7 +253,7 @@ static void init_laplacian_matrix(LaplacianSystem *sys) areaf = area_tri_v3(v_prev, v_curr, v_next); if (areaf < sys->min_area) { - sys->zerola[l_curr->v] = 1; + sys->zerola[l_curr->v] = true; } sys->ring_areas[l_prev->v] += areaf; @@ -300,7 +300,7 @@ static void fill_laplacian_matrix(LaplacianSystem *sys) const uint l_curr_index = l_curr - sys->mloop; /* Is ring if number of faces == number of edges around vertice. */ - if (sys->numNeEd[l_curr->v] == sys->numNeFa[l_curr->v] && sys->zerola[l_curr->v] == 0) { + if (sys->numNeEd[l_curr->v] == sys->numNeFa[l_curr->v] && sys->zerola[l_curr->v] == false) { EIG_linear_solver_matrix_add(sys->context, l_curr->v, l_next->v, @@ -310,7 +310,7 @@ static void fill_laplacian_matrix(LaplacianSystem *sys) l_prev->v, sys->fweights[l_curr_index][1] * sys->vweights[l_curr->v]); } - if (sys->numNeEd[l_next->v] == sys->numNeFa[l_next->v] && sys->zerola[l_next->v] == 0) { + if (sys->numNeEd[l_next->v] == sys->numNeFa[l_next->v] && sys->zerola[l_next->v] == false) { EIG_linear_solver_matrix_add(sys->context, l_next->v, l_curr->v, @@ -320,7 +320,7 @@ static void fill_laplacian_matrix(LaplacianSystem *sys) l_prev->v, sys->fweights[l_curr_index][0] * sys->vweights[l_next->v]); } - if (sys->numNeEd[l_prev->v] == sys->numNeFa[l_prev->v] && sys->zerola[l_prev->v] == 0) { + if (sys->numNeEd[l_prev->v] == sys->numNeFa[l_prev->v] && sys->zerola[l_prev->v] == false) { EIG_linear_solver_matrix_add(sys->context, l_prev->v, l_curr->v, @@ -338,7 +338,7 @@ static void fill_laplacian_matrix(LaplacianSystem *sys) idv2 = sys->medges[i].v2; /* Is boundary */ if (sys->numNeEd[idv1] != sys->numNeFa[idv1] && sys->numNeEd[idv2] != sys->numNeFa[idv2] && - sys->zerola[idv1] == 0 && sys->zerola[idv2] == 0) { + sys->zerola[idv1] == false && sys->zerola[idv2] == false) { EIG_linear_solver_matrix_add( sys->context, idv1, idv2, sys->eweights[i] * sys->vlengths[idv1]); EIG_linear_solver_matrix_add( @@ -358,7 +358,7 @@ static void validate_solution(LaplacianSystem *sys, short flag, float lambda, fl sys->vert_centroid, sys->vertexCos, sys->mpoly, sys->numPolys, sys->mloop); } for (i = 0; i < sys->numVerts; i++) { - if (sys->zerola[i] == 0) { + if (sys->zerola[i] == false) { lam = sys->numNeEd[i] == sys->numNeFa[i] ? (lambda >= 0.0f ? 1.0f : -1.0f) : (lambda_border >= 0.0f ? 1.0f : -1.0f); if (flag & MOD_LAPLACIANSMOOTH_X) { @@ -442,7 +442,7 @@ static void laplaciansmoothModifier_do( wpaint = 1.0f; } - if (sys->zerola[i] == 0) { + if (sys->zerola[i] == false) { if (smd->flag & MOD_LAPLACIANSMOOTH_NORMALIZED) { w = sys->vweights[i]; sys->vweights[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda) * wpaint / w; -- cgit v1.2.3 From c15635bd8d5483a56107b5c31d8dc0b6a691a767 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 6 Aug 2021 01:42:02 +1000 Subject: BMesh: support laplacian smooth for n-gons Follow the same logic already used by the modifier. --- .../blender/bmesh/operators/bmo_smooth_laplacian.c | 258 ++++++++------------- source/blender/editors/mesh/editmesh_tools.c | 23 -- 2 files changed, 100 insertions(+), 181 deletions(-) diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c index eb25923d1d1..94856701e72 100644 --- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c +++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c @@ -37,12 +37,12 @@ struct BLaplacianSystem { float *eweights; /* Length weights per Edge. */ - float (*fweights)[3]; /* Cotangent weights per face. */ + float (*fweights)[3]; /* Cotangent weights per loop. */ float *ring_areas; /* Total area per ring. */ float *vlengths; /* Total sum of lengths(edges) per vertex. */ float *vweights; /* Total sum of weights per vertex. */ int numEdges; /* Number of edges. */ - int numFaces; /* Number of faces. */ + int numLoops; /* Number of loops. */ int numVerts; /* Number of verts. */ bool *zerola; /* Is zero area or length. */ @@ -57,7 +57,7 @@ struct BLaplacianSystem { typedef struct BLaplacianSystem LaplacianSystem; static bool vert_is_boundary(BMVert *v); -static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts); +static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numLoops, int a_numVerts); static void init_laplacian_matrix(LaplacianSystem *sys); static void delete_laplacian_system(LaplacianSystem *sys); static void delete_void_pointer(void *data); @@ -94,19 +94,19 @@ static void delete_laplacian_system(LaplacianSystem *sys) static void memset_laplacian_system(LaplacianSystem *sys, int val) { memset(sys->eweights, val, sizeof(float) * sys->numEdges); - memset(sys->fweights, val, sizeof(float) * sys->numFaces * 3); + memset(sys->fweights, val, sizeof(float[3]) * sys->numLoops); memset(sys->ring_areas, val, sizeof(float) * sys->numVerts); memset(sys->vlengths, val, sizeof(float) * sys->numVerts); memset(sys->vweights, val, sizeof(float) * sys->numVerts); memset(sys->zerola, val, sizeof(bool) * sys->numVerts); } -static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts) +static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numLoops, int a_numVerts) { LaplacianSystem *sys; sys = MEM_callocN(sizeof(LaplacianSystem), "ModLaplSmoothSystem"); sys->numEdges = a_numEdges; - sys->numFaces = a_numFaces; + sys->numLoops = a_numLoops; sys->numVerts = a_numVerts; sys->eweights = MEM_callocN(sizeof(float) * sys->numEdges, "ModLaplSmoothEWeight"); @@ -115,7 +115,7 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, in return NULL; } - sys->fweights = MEM_callocN(sizeof(float[3]) * sys->numFaces, "ModLaplSmoothFWeight"); + sys->fweights = MEM_callocN(sizeof(float[3]) * sys->numLoops, "ModLaplSmoothFWeight"); if (!sys->fweights) { delete_laplacian_system(sys); return NULL; @@ -166,31 +166,23 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, in static void init_laplacian_matrix(LaplacianSystem *sys) { - float areaf; - float *v1, *v2, *v3, *v4; - float w1, w2, w3, w4; - int i, j; - bool has_4_vert; - uint idv1, idv2, idv3, idv4, idv[4]; BMEdge *e; BMFace *f; BMIter eiter; BMIter fiter; - BMIter vi; - BMVert *vn; - BMVert *vf[4]; + uint i; BM_ITER_MESH_INDEX (e, &eiter, sys->bm, BM_EDGES_OF_MESH, i) { if (BM_elem_flag_test(e, BM_ELEM_SELECT) || !BM_edge_is_boundary(e)) { continue; } - v1 = e->v1->co; - v2 = e->v2->co; - idv1 = BM_elem_index_get(e->v1); - idv2 = BM_elem_index_get(e->v2); + const float *v1 = e->v1->co; + const float *v2 = e->v2->co; + const int idv1 = BM_elem_index_get(e->v1); + const int idv2 = BM_elem_index_get(e->v2); - w1 = len_v3v3(v1, v2); + float w1 = len_v3v3(v1, v2); if (w1 > sys->min_area) { w1 = 1.0f / w1; sys->eweights[i] = w1; @@ -203,176 +195,126 @@ static void init_laplacian_matrix(LaplacianSystem *sys) } } - BM_ITER_MESH_INDEX (f, &fiter, sys->bm, BM_FACES_OF_MESH, i) { + uint l_curr_index = 0; + + BM_ITER_MESH (f, &fiter, sys->bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) { + l_curr_index += f->len; continue; } - BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, j) { - vf[j] = vn; - } - has_4_vert = (j == 4) ? 1 : 0; - idv1 = BM_elem_index_get(vf[0]); - idv2 = BM_elem_index_get(vf[1]); - idv3 = BM_elem_index_get(vf[2]); - idv4 = has_4_vert ? BM_elem_index_get(vf[3]) : 0; - - v1 = vf[0]->co; - v2 = vf[1]->co; - v3 = vf[2]->co; - v4 = has_4_vert ? vf[3]->co : NULL; - - if (has_4_vert) { - areaf = area_quad_v3(v1, v2, v3, v4); - } - else { - areaf = area_tri_v3(v1, v2, v3); - } + BMLoop *l_first = BM_FACE_FIRST_LOOP(f); + BMLoop *l_iter; - if (areaf < sys->min_area) { - sys->zerola[idv1] = true; - sys->zerola[idv2] = true; - sys->zerola[idv3] = true; - if (has_4_vert) { - sys->zerola[idv4] = true; - } - } + l_iter = l_first; + do { + const int vi_prev = BM_elem_index_get(l_iter->prev->v); + const int vi_curr = BM_elem_index_get(l_iter->v); + const int vi_next = BM_elem_index_get(l_iter->next->v); - sys->ring_areas[idv1] += areaf; - sys->ring_areas[idv2] += areaf; - sys->ring_areas[idv3] += areaf; - if (has_4_vert) { - sys->ring_areas[idv4] += areaf; - } - - if (has_4_vert) { - - idv[0] = idv1; - idv[1] = idv2; - idv[2] = idv3; - idv[3] = idv4; + const float *co_prev = l_iter->prev->v->co; + const float *co_curr = l_iter->v->co; + const float *co_next = l_iter->next->v->co; - for (j = 0; j < 4; j++) { - idv1 = idv[j]; - idv2 = idv[(j + 1) % 4]; - idv3 = idv[(j + 2) % 4]; - idv4 = idv[(j + 3) % 4]; + const float areaf = area_tri_v3(co_prev, co_curr, co_next); - v1 = vf[j]->co; - v2 = vf[(j + 1) % 4]->co; - v3 = vf[(j + 2) % 4]->co; - v4 = vf[(j + 3) % 4]->co; + if (areaf < sys->min_area) { + sys->zerola[vi_curr] = true; + } - w2 = cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2); - w3 = cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3); - w4 = cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1); + sys->ring_areas[vi_prev] += areaf; + sys->ring_areas[vi_curr] += areaf; + sys->ring_areas[vi_next] += areaf; - sys->vweights[idv1] += (w2 + w3 + w4) / 4.0f; - } - } - else { - w1 = cotangent_tri_weight_v3(v1, v2, v3); - w2 = cotangent_tri_weight_v3(v2, v3, v1); - w3 = cotangent_tri_weight_v3(v3, v1, v2); + const float w1 = cotangent_tri_weight_v3(co_curr, co_next, co_prev) / 2.0f; + const float w2 = cotangent_tri_weight_v3(co_next, co_prev, co_curr) / 2.0f; + const float w3 = cotangent_tri_weight_v3(co_prev, co_curr, co_next) / 2.0f; - sys->fweights[i][0] += w1; - sys->fweights[i][1] += w2; - sys->fweights[i][2] += w3; + sys->fweights[l_curr_index][0] += w1; + sys->fweights[l_curr_index][1] += w2; + sys->fweights[l_curr_index][2] += w3; - sys->vweights[idv1] += w2 + w3; - sys->vweights[idv2] += w1 + w3; - sys->vweights[idv3] += w1 + w2; - } + sys->vweights[vi_prev] += w1 + w2; + sys->vweights[vi_curr] += w2 + w3; + sys->vweights[vi_next] += w1 + w3; + } while (((void)(l_curr_index += 1), (l_iter = l_iter->next) != l_first)); } } static void fill_laplacian_matrix(LaplacianSystem *sys) { - float *v1, *v2, *v3, *v4; - float w2, w3, w4; - int i, j; - bool has_4_vert; - uint idv1, idv2, idv3, idv4, idv[4]; - BMEdge *e; BMFace *f; BMIter eiter; BMIter fiter; - BMIter vi; - BMVert *vn; - BMVert *vf[4]; + int i; - BM_ITER_MESH_INDEX (f, &fiter, sys->bm, BM_FACES_OF_MESH, i) { + uint l_curr_index = 0; + + BM_ITER_MESH (f, &fiter, sys->bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) { + l_curr_index += f->len; continue; } - BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, j) { - vf[j] = vn; - } - has_4_vert = (j == 4) ? 1 : 0; - if (has_4_vert) { - idv[0] = BM_elem_index_get(vf[0]); - idv[1] = BM_elem_index_get(vf[1]); - idv[2] = BM_elem_index_get(vf[2]); - idv[3] = BM_elem_index_get(vf[3]); - for (j = 0; j < 4; j++) { - idv1 = idv[j]; - idv2 = idv[(j + 1) % 4]; - idv3 = idv[(j + 2) % 4]; - idv4 = idv[(j + 3) % 4]; - - v1 = vf[j]->co; - v2 = vf[(j + 1) % 4]->co; - v3 = vf[(j + 2) % 4]->co; - v4 = vf[(j + 3) % 4]->co; - - w2 = cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2); - w3 = cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3); - w4 = cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1); - - w2 = w2 / 4.0f; - w3 = w3 / 4.0f; - w4 = w4 / 4.0f; - - if (!vert_is_boundary(vf[j]) && sys->zerola[idv1] == false) { - EIG_linear_solver_matrix_add(sys->context, idv1, idv2, w2 * sys->vweights[idv1]); - EIG_linear_solver_matrix_add(sys->context, idv1, idv3, w3 * sys->vweights[idv1]); - EIG_linear_solver_matrix_add(sys->context, idv1, idv4, w4 * sys->vweights[idv1]); - } + BMLoop *l_first = BM_FACE_FIRST_LOOP(f); + BMLoop *l_iter = l_first; + + int vi_prev = BM_elem_index_get(l_iter->prev->v); + int vi_curr = BM_elem_index_get(l_iter->v); + + bool ok_prev = (sys->zerola[vi_prev] == false) && !vert_is_boundary(l_iter->prev->v); + bool ok_curr = (sys->zerola[vi_curr] == false) && !vert_is_boundary(l_iter->v); + + do { + const int vi_next = BM_elem_index_get(l_iter->next->v); + const bool ok_next = (sys->zerola[vi_next] == false) && !vert_is_boundary(l_iter->next->v); + + if (ok_prev) { + EIG_linear_solver_matrix_add(sys->context, + vi_prev, + vi_curr, + sys->fweights[l_curr_index][1] * sys->vweights[vi_prev]); + EIG_linear_solver_matrix_add(sys->context, + vi_prev, + vi_next, + sys->fweights[l_curr_index][0] * sys->vweights[vi_prev]); } - } - else { - idv1 = BM_elem_index_get(vf[0]); - idv2 = BM_elem_index_get(vf[1]); - idv3 = BM_elem_index_get(vf[2]); - /* Is ring if number of faces == number of edges around vertice. */ - if (!vert_is_boundary(vf[0]) && sys->zerola[idv1] == false) { - EIG_linear_solver_matrix_add( - sys->context, idv1, idv2, sys->fweights[i][2] * sys->vweights[idv1]); - EIG_linear_solver_matrix_add( - sys->context, idv1, idv3, sys->fweights[i][1] * sys->vweights[idv1]); + if (ok_curr) { + EIG_linear_solver_matrix_add(sys->context, + vi_curr, + vi_next, + sys->fweights[l_curr_index][2] * sys->vweights[vi_curr]); + EIG_linear_solver_matrix_add(sys->context, + vi_curr, + vi_prev, + sys->fweights[l_curr_index][1] * sys->vweights[vi_curr]); } - if (!vert_is_boundary(vf[1]) && sys->zerola[idv2] == false) { - EIG_linear_solver_matrix_add( - sys->context, idv2, idv1, sys->fweights[i][2] * sys->vweights[idv2]); - EIG_linear_solver_matrix_add( - sys->context, idv2, idv3, sys->fweights[i][0] * sys->vweights[idv2]); + if (ok_next) { + EIG_linear_solver_matrix_add(sys->context, + vi_next, + vi_curr, + sys->fweights[l_curr_index][2] * sys->vweights[vi_next]); + EIG_linear_solver_matrix_add(sys->context, + vi_next, + vi_prev, + sys->fweights[l_curr_index][0] * sys->vweights[vi_next]); } - if (!vert_is_boundary(vf[2]) && sys->zerola[idv3] == false) { - EIG_linear_solver_matrix_add( - sys->context, idv3, idv1, sys->fweights[i][1] * sys->vweights[idv3]); - EIG_linear_solver_matrix_add( - sys->context, idv3, idv2, sys->fweights[i][0] * sys->vweights[idv3]); - } - } + + vi_prev = vi_curr; + vi_curr = vi_next; + + ok_prev = ok_curr; + ok_curr = ok_next; + + } while (((void)(l_curr_index += 1), (l_iter = l_iter->next) != l_first)); } BM_ITER_MESH_INDEX (e, &eiter, sys->bm, BM_EDGES_OF_MESH, i) { if (BM_elem_flag_test(e, BM_ELEM_SELECT) || !BM_edge_is_boundary(e)) { continue; } - idv1 = BM_elem_index_get(e->v1); - idv2 = BM_elem_index_get(e->v2); + const uint idv1 = BM_elem_index_get(e->v1); + const uint idv2 = BM_elem_index_get(e->v2); if (sys->zerola[idv1] == false && sys->zerola[idv2] == false) { EIG_linear_solver_matrix_add( sys->context, idv1, idv2, sys->eweights[i] * sys->vlengths[idv1]); @@ -494,7 +436,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) if (bm->totface == 0) { return; } - sys = init_laplacian_system(bm->totedge, bm->totface, bm->totvert); + sys = init_laplacian_system(bm->totedge, bm->totloop, bm->totvert); if (!sys) { return; } diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 215ce0185f1..1b6643da1aa 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -2748,9 +2748,6 @@ void MESH_OT_vertices_smooth(wmOperatorType *ot) static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) { - BMIter fiter; - BMFace *f; - int tot_invalid = 0; int tot_unselected = 0; ViewLayer *view_layer = CTX_data_view_layer(C); @@ -2777,22 +2774,6 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) if (em->bm->totvertsel == 0) { tot_unselected++; - tot_invalid++; - continue; - } - - bool is_invalid = false; - /* Check if select faces are triangles. */ - BM_ITER_MESH (f, &fiter, em->bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - if (f->len > 4) { - tot_invalid++; - is_invalid = true; - break; - } - } - } - if (is_invalid) { continue; } @@ -2841,10 +2822,6 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_WARNING, "No selected vertex"); return OPERATOR_CANCELLED; } - if (tot_invalid == objects_len) { - BKE_report(op->reports, RPT_WARNING, "Selected faces must be triangles or quads"); - return OPERATOR_CANCELLED; - } return OPERATOR_FINISHED; } -- cgit v1.2.3 From bd44e82b255a231242a1b7ddd59cee7830af20ea Mon Sep 17 00:00:00 2001 From: Eitan Date: Thu, 5 Aug 2021 10:44:59 -0500 Subject: Geometry Nodes: Add more warnings for out of bounds parameters Add warning(info) to nodes that don't work when an input value is out of range. For example, the grid node doesn't work with Vertices X or Verices Y less than 2. These are purposefully added as "Info" warnings, because they don't show in the modifier and they aren't printed to the terminal. Differential Revision: https://developer.blender.org/D11923 --- .../blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc | 1 + source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc | 1 + .../nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc | 1 + source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc | 6 ++++++ .../nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc | 6 ++++++ 5 files changed, 15 insertions(+) diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc index 667e1c931bd..96c6f073ab3 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc @@ -211,6 +211,7 @@ static void geo_node_mesh_primitive_circle_exec(GeoNodeExecParams params) const float radius = params.extract_input("Radius"); const int verts_num = params.extract_input("Vertices"); if (verts_num < 3) { + params.error_message_add(NodeWarningType::Info, TIP_("Vertices must be at least 3")); params.set_output("Geometry", GeometrySet()); return; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc index d46ea2d2050..790a518e584 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc @@ -551,6 +551,7 @@ static void geo_node_mesh_primitive_cone_exec(GeoNodeExecParams params) const int verts_num = params.extract_input("Vertices"); if (verts_num < 3) { + params.error_message_add(NodeWarningType::Info, TIP_("Vertices must be at least 3")); params.set_output("Geometry", GeometrySet()); return; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc index 1767f765da4..b40cb478b03 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc @@ -70,6 +70,7 @@ static void geo_node_mesh_primitive_cylinder_exec(GeoNodeExecParams params) const float depth = params.extract_input("Depth"); const int verts_num = params.extract_input("Vertices"); if (verts_num < 3) { + params.error_message_add(NodeWarningType::Info, TIP_("Vertices must be at least 3")); params.set_output("Geometry", GeometrySet()); return; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc index ac2f5a23a4d..7a97ae8e318 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc @@ -162,6 +162,12 @@ static void geo_node_mesh_primitive_grid_exec(GeoNodeExecParams params) const int verts_x = params.extract_input("Vertices X"); const int verts_y = params.extract_input("Vertices Y"); if (verts_x < 2 || verts_y < 2) { + if (verts_x < 2) { + params.error_message_add(NodeWarningType::Info, TIP_("Vertices X must be at least 2")); + } + if (verts_y < 2) { + params.error_message_add(NodeWarningType::Info, TIP_("Vertices Y must be at least 2")); + } params.set_output("Geometry", GeometrySet()); return; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc index 599c59e4a2e..fe456dc4564 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc @@ -291,6 +291,12 @@ static void geo_node_mesh_primitive_uv_sphere_exec(GeoNodeExecParams params) const int segments_num = params.extract_input("Segments"); const int rings_num = params.extract_input("Rings"); if (segments_num < 3 || rings_num < 2) { + if (segments_num < 3) { + params.error_message_add(NodeWarningType::Info, TIP_("Segments must be at least 3")); + } + if (rings_num < 3) { + params.error_message_add(NodeWarningType::Info, TIP_("Rings must be at least 3")); + } params.set_output("Geometry", GeometrySet()); return; } -- cgit v1.2.3 From 6844f7bedb71883f383bdeff130fd2200750cc54 Mon Sep 17 00:00:00 2001 From: Aaron Carlisle Date: Thu, 5 Aug 2021 13:04:59 -0400 Subject: PyDoc: document how parameter are used for 3D and 2D textures Improves on rB171433e841379e7efad069bbda9880fb271e2fc4 --- source/blender/makesrna/intern/rna_texture_api.c | 28 ++++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/source/blender/makesrna/intern/rna_texture_api.c b/source/blender/makesrna/intern/rna_texture_api.c index c46b9acf986..83c1efd55bc 100644 --- a/source/blender/makesrna/intern/rna_texture_api.c +++ b/source/blender/makesrna/intern/rna_texture_api.c @@ -59,19 +59,23 @@ void RNA_api_texture(StructRNA *srna) PropertyRNA *parm; func = RNA_def_function(srna, "evaluate", "texture_evaluate"); - RNA_def_function_ui_description(func, "Evaluate the texture at the coordinates given"); - - parm = RNA_def_float_vector(func, - "value", - 3, - NULL, - -FLT_MAX, - FLT_MAX, - "The object coordinates (x,y,z) used to generate/map the texture", - "", - -1e4, - 1e4); + RNA_def_function_ui_description( + func, "Evaluate the texture at the a given coordinate and returns the result"); + + parm = RNA_def_float_vector( + func, + "value", + 3, + NULL, + -FLT_MAX, + FLT_MAX, + "The coordinates (x,y,z) of the texture, in case of a 3D texture, the z value is the slice " + "of the texture that is evaluated. For 2D textures such as images, the z value is ignored", + "", + -1e4, + 1e4); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + /* return location and normal */ parm = RNA_def_float_vector( func, -- cgit v1.2.3 From 4dd6c9ad450f773a4bfaaad2d54feee815399ce4 Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Tue, 27 Jul 2021 20:50:26 +0200 Subject: Fix T90236: Sculpt automasking failing when the stroke does not start over the mesh The active geometry element are usually updated by the cursor drawing code (as they are needed for the cursor preview) and when an sculpt operator starts. For brushes, this was not happening. This was making brushes rely by default on the last cursor drawing update, which can be incorrect if the mouse moved after starting the stroke without hovering the active geometry. Reviewed By: JacquesLucke Maniphest Tasks: T90236 Differential Revision: https://developer.blender.org/D12045 --- source/blender/editors/sculpt_paint/sculpt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 83388c1aef2..8264affc465 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -7887,6 +7887,9 @@ static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const f sculpt_update_cache_invariants(C, sd, ss, op, mouse); + SculptCursorGeometryInfo sgi; + SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false); + SCULPT_undo_push_begin(ob, sculpt_tool_name(sd)); return true; -- cgit v1.2.3 From d01781129fab7846a6a03815b0c0b48b2a809c39 Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Tue, 27 Jul 2021 20:26:38 +0200 Subject: Fix T90235: Smooth Brush not working with interior vertices with two adjacent edges The exception to automatically pin vertices of grid corners also has to take into account that the vertex is in a boundary. Reviewed By: JacquesLucke Maniphest Tasks: T90235 Differential Revision: https://developer.blender.org/D12044 --- source/blender/editors/sculpt_paint/sculpt_smooth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c index eabbfe43e03..38165b7622f 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.c +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c @@ -88,7 +88,7 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss, float result[3], SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); /* Do not modify corner vertices. */ - if (neighbor_count <= 2) { + if (neighbor_count <= 2 && is_boundary) { copy_v3_v3(result, SCULPT_vertex_co_get(ss, index)); return; } -- cgit v1.2.3 From cf10eb54cc4bc89e763dc48644c402f7578fa6b2 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Mon, 2 Aug 2021 19:08:12 +0300 Subject: Action Constraint: add Split Channels Mix choices from Copy Transforms Practice shows that when combining actions and direct animation it is usually best to combine location, rotation and scale separately, which is implemented by the Split Channels modes recently introduced in D9469 for Copy Transforms. This completes the same set of 6 choices for the Action Constraint. The default for new constraints is changed to the newly added Before Original (Split Channels) mode. The original patch is motivated by Loic Pinsard, who created an addon that does the equivalent of this feature by splitting the action into two, separating location and rotation+scale. Differential Revision: https://developer.blender.org/D7547 --- source/blender/blenkernel/intern/constraint.c | 30 +++++++++++++- .../blender/editors/transform/transform_convert.c | 5 ++- source/blender/makesdna/DNA_constraint_types.h | 6 +++ source/blender/makesrna/intern/rna_constraint.c | 48 ++++++++++++++++------ 4 files changed, 73 insertions(+), 16 deletions(-) diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index b7e02f06571..0da29ded13d 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -2982,6 +2982,16 @@ static void actcon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targ if (VALID_CONS_TARGET(ct) || data->flag & ACTCON_USE_EVAL_TIME) { switch (data->mix_mode) { + /* Simple matrix multiplication. */ + case ACTCON_MIX_BEFORE_FULL: + mul_m4_m4m4(cob->matrix, ct->matrix, cob->matrix); + break; + + case ACTCON_MIX_AFTER_FULL: + mul_m4_m4m4(cob->matrix, cob->matrix, ct->matrix); + break; + + /* Aligned Inherit Scale emulation. */ case ACTCON_MIX_BEFORE: mul_m4_m4m4_aligned_scale(cob->matrix, ct->matrix, cob->matrix); break; @@ -2990,8 +3000,13 @@ static void actcon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targ mul_m4_m4m4_aligned_scale(cob->matrix, cob->matrix, ct->matrix); break; - case ACTCON_MIX_AFTER_FULL: - mul_m4_m4m4(cob->matrix, cob->matrix, ct->matrix); + /* Fully separate handling of channels. */ + case ACTCON_MIX_BEFORE_SPLIT: + mul_m4_m4m4_split_channels(cob->matrix, ct->matrix, cob->matrix); + break; + + case ACTCON_MIX_AFTER_SPLIT: + mul_m4_m4m4_split_channels(cob->matrix, cob->matrix, ct->matrix); break; default: @@ -5767,6 +5782,17 @@ static bConstraint *add_new_constraint(Object *ob, } break; } + case CONSTRAINT_TYPE_ACTION: { + /* The Before or Split modes require computing in local space, but + * for objects the Local space doesn't make sense (T78462, D6095 etc). + * So only default to Before (Split) if the constraint is on a bone. */ + if (pchan) { + bActionConstraint *data = con->data; + data->mix_mode = ACTCON_MIX_BEFORE_SPLIT; + con->ownspace = CONSTRAINT_SPACE_LOCAL; + } + break; + } } return con; diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index 00fd008151d..e77fedfe143 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -861,10 +861,13 @@ bool constraints_list_needinv(TransInfo *t, ListBase *list) /* The Action constraint only does this in the Before mode. */ bActionConstraint *data = (bActionConstraint *)con->data; - if (ELEM(data->mix_mode, ACTCON_MIX_BEFORE) && + if (ELEM(data->mix_mode, ACTCON_MIX_BEFORE, ACTCON_MIX_BEFORE_FULL) && ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION)) { return true; } + if (ELEM(data->mix_mode, ACTCON_MIX_BEFORE_SPLIT) && ELEM(t->mode, TFM_ROTATION)) { + return true; + } } else if (con->type == CONSTRAINT_TYPE_TRANSFORM) { /* Transform constraint needs it for rotation at least (r.57309), diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index a77fbc9e45e..822b8705c9b 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -901,10 +901,16 @@ typedef enum eActionConstraint_Flags { typedef enum eActionConstraint_MixMode { /* Multiply the action transformation on the right. */ ACTCON_MIX_AFTER_FULL = 0, + /* Multiply the action transformation on the left. */ + ACTCON_MIX_BEFORE_FULL = 3, /* Multiply the action transformation on the right, with anti-shear scale handling. */ ACTCON_MIX_AFTER = 1, /* Multiply the action transformation on the left, with anti-shear scale handling. */ ACTCON_MIX_BEFORE = 2, + /* Separately combine Translation, Rotation and Scale, with rotation on the right. */ + ACTCON_MIX_AFTER_SPLIT = 4, + /* Separately combine Translation, Rotation and Scale, with rotation on the left. */ + ACTCON_MIX_BEFORE_SPLIT = 5, } eActionConstraint_MixMode; /* Locked-Axis Values (Locked Track) */ diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index a0a0a41b58d..e36d052d27c 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -679,7 +679,7 @@ static void rna_ActionConstraint_mix_mode_set(PointerRNA *ptr, int value) acon->mix_mode = value; /* The After mode can be computed in world space for efficiency - * and backward compatibility, while Before requires Local. */ + * and backward compatibility, while Before or Split requires Local. */ if (ELEM(value, ACTCON_MIX_AFTER, ACTCON_MIX_AFTER_FULL)) { con->ownspace = CONSTRAINT_SPACE_WORLD; } @@ -1773,25 +1773,47 @@ static void rna_def_constraint_action(BlenderRNA *brna) }; static const EnumPropertyItem mix_mode_items[] = { + {ACTCON_MIX_BEFORE_FULL, + "BEFORE_FULL", + 0, + "Before Original (Full)", + "Apply the action channels before the original transformation, as if applied to an " + "imaginary parent in Full Inherit Scale mode. Will create shear when combining rotation " + "and non-uniform scale"}, {ACTCON_MIX_BEFORE, "BEFORE", 0, - "Before Original", - "Apply the action channels before the original transformation, " - "as if applied to an imaginary parent with Aligned Inherit Scale"}, - {ACTCON_MIX_AFTER, - "AFTER", + "Before Original (Aligned)", + "Apply the action channels before the original transformation, as if applied to an " + "imaginary parent in Aligned Inherit Scale mode. This effectively uses Full for location " + "and Split Channels for rotation and scale"}, + {ACTCON_MIX_BEFORE_SPLIT, + "BEFORE_SPLIT", 0, - "After Original", - "Apply the action channels after the original transformation, " - "as if applied to an imaginary child with Aligned Inherit Scale"}, + "Before Original (Split Channels)", + "Apply the action channels before the original transformation, handling location, rotation " + "and scale separately"}, + {0, "", 0, NULL, NULL}, {ACTCON_MIX_AFTER_FULL, "AFTER_FULL", 0, - "After Original (Full Scale)", - "Apply the action channels after the original transformation, as if " - "applied to an imaginary child with Full Inherit Scale. This mode " - "can create shear and is provided only for backward compatibility"}, + "After Original (Full)", + "Apply the action channels after the original transformation, as if applied to an " + "imaginary child in Full Inherit Scale mode. Will create shear when combining rotation " + "and non-uniform scale"}, + {ACTCON_MIX_AFTER, + "AFTER", + 0, + "After Original (Aligned)", + "Apply the action channels after the original transformation, as if applied to an " + "imaginary child in Aligned Inherit Scale mode. This effectively uses Full for location " + "and Split Channels for rotation and scale"}, + {ACTCON_MIX_AFTER_SPLIT, + "AFTER_SPLIT", + 0, + "After Original (Split Channels)", + "Apply the action channels after the original transformation, handling location, rotation " + "and scale separately"}, {0, NULL, 0, NULL, NULL}, }; -- cgit v1.2.3 From 89014b51f12779efbd9499f91a86b96c7407b2f7 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Thu, 5 Aug 2021 12:49:55 -0300 Subject: Xcode: support cmake options for grouping in folders The Xcode IDE can also benefit from the options: - WINDOWS_USE_VISUAL_STUDIO_SOURCE_FOLDERS - WINDOWS_USE_VISUAL_STUDIO_PROJECT_FOLDERS So add suport to these options and also renames them as they are no longer limited to just Windows and Visual Studio. Reviewed By: brecht, ankitm Differential Revision: https://developer.blender.org/D12132 --- CMakeLists.txt | 18 ++++++++++++------ build_files/cmake/macros.cmake | 6 +++--- build_files/cmake/platform/platform_win32.cmake | 2 -- intern/cycles/cmake/macros.cmake | 2 +- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3baebba4678..2868324bf46 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -612,12 +612,6 @@ if(WIN32) option(WITH_WINDOWS_FIND_MODULES "Use find_package to locate libraries" OFF) mark_as_advanced(WITH_WINDOWS_FIND_MODULES) - option(WINDOWS_USE_VISUAL_STUDIO_PROJECT_FOLDERS "Organize the visual studio projects according to source folder structure." ON) - mark_as_advanced(WINDOWS_USE_VISUAL_STUDIO_PROJECT_FOLDERS) - - option(WINDOWS_USE_VISUAL_STUDIO_SOURCE_FOLDERS "Organize the source files in filters matching the source folders." ON) - mark_as_advanced(WINDOWS_USE_VISUAL_STUDIO_SOURCE_FOLDERS) - option(WINDOWS_PYTHON_DEBUG "Include the files needed for debugging python scripts with visual studio 2017+." OFF) mark_as_advanced(WINDOWS_PYTHON_DEBUG) @@ -635,6 +629,18 @@ if(WIN32) endif() +if(WIN32 OR XCODE) + option(IDE_GROUP_SOURCES_IN_FOLDERS "Organize the source files in filters matching the source folders." ON) + mark_as_advanced(IDE_GROUP_SOURCES_IN_FOLDERS) + + option(IDE_GROUP_PROJECTS_IN_FOLDERS "Organize the projects according to source folder structure." ON) + mark_as_advanced(IDE_GROUP_PROJECTS_IN_FOLDERS) + + if (IDE_GROUP_PROJECTS_IN_FOLDERS) + set_property(GLOBAL PROPERTY USE_FOLDERS ON) + endif() +endif() + if(UNIX) # See WITH_WINDOWS_SCCACHE for Windows. option(WITH_COMPILER_CCACHE "Use ccache to improve rebuild times (Works with Ninja, Makefiles and Xcode)" OFF) diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index 8ad3f77c7d3..1471aa21505 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -208,7 +208,7 @@ function(blender_source_group ) # if enabled, use the sources directories as filters. - if(WINDOWS_USE_VISUAL_STUDIO_SOURCE_FOLDERS) + if(IDE_GROUP_SOURCES_IN_FOLDERS) foreach(_SRC ${sources}) # remove ../'s get_filename_component(_SRC_DIR ${_SRC} REALPATH) @@ -240,8 +240,8 @@ function(blender_source_group endforeach() endif() - # if enabled, set the FOLDER property for visual studio projects - if(WINDOWS_USE_VISUAL_STUDIO_PROJECT_FOLDERS) + # if enabled, set the FOLDER property for the projects + if(IDE_GROUP_PROJECTS_IN_FOLDERS) get_filename_component(FolderDir ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) string(REPLACE ${CMAKE_SOURCE_DIR} "" FolderDir ${FolderDir}) set_target_properties(${name} PROPERTIES FOLDER ${FolderDir}) diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index 113c41c545b..3773aaaffed 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -57,8 +57,6 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang") endif() endif() -set_property(GLOBAL PROPERTY USE_FOLDERS ${WINDOWS_USE_VISUAL_STUDIO_PROJECT_FOLDERS}) - if(NOT WITH_PYTHON_MODULE) set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT blender) endif() diff --git a/intern/cycles/cmake/macros.cmake b/intern/cycles/cmake/macros.cmake index ff62b816e6c..47196dfd1ce 100644 --- a/intern/cycles/cmake/macros.cmake +++ b/intern/cycles/cmake/macros.cmake @@ -13,7 +13,7 @@ # limitations under the License. function(cycles_set_solution_folder target) - if(WINDOWS_USE_VISUAL_STUDIO_FOLDERS) + if(IDE_GROUP_PROJECTS_IN_FOLDERS) get_filename_component(folderdir ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) string(REPLACE ${CMAKE_SOURCE_DIR} "" folderdir ${folderdir}) set_target_properties(${target} PROPERTIES FOLDER ${folderdir}) -- cgit v1.2.3 From 92edf37997c25444fc2628c8057a87b7e87c5eff Mon Sep 17 00:00:00 2001 From: Himanshi Kalra Date: Fri, 6 Aug 2021 00:03:16 +0530 Subject: Add custom data comparison for generic attributes Generic attributes CD_PROP_* comparison is added in customdata_compare Checks for built-in as well as user created attributes. Reviewed By: JacquesLucke Differential Revision: https://developer.blender.org/D12137 --- source/blender/blenkernel/intern/mesh.c | 95 +++++++++++++++++++++++++++++---- 1 file changed, 86 insertions(+), 9 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 8d74002ad79..b00670aad4c 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -389,6 +389,7 @@ enum { MESHCMP_EDGEUNKNOWN, MESHCMP_VERTCOMISMATCH, MESHCMP_CDLAYERS_MISMATCH, + MESHCMP_ATTRIBUTE_VALUE_MISMATCH, }; static const char *cmpcode_to_str(int code) @@ -416,6 +417,8 @@ static const char *cmpcode_to_str(int code) return "Vertex Coordinate Mismatch"; case MESHCMP_CDLAYERS_MISMATCH: return "CustomData Layer Count Mismatch"; + case MESHCMP_ATTRIBUTE_VALUE_MISMATCH: + return "Attribute Value Mismatch"; default: return "Mesh Comparison Code Unknown"; } @@ -423,13 +426,13 @@ static const char *cmpcode_to_str(int code) /** Thresh is threshold for comparing vertices, UV's, vertex colors, weights, etc. */ static int customdata_compare( - CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2, const float thresh) + CustomData *c1, CustomData *c2, const int total_length, Mesh *m1, Mesh *m2, const float thresh) { const float thresh_sq = thresh * thresh; CustomDataLayer *l1, *l2; - int i, i1 = 0, i2 = 0, tot, j; + int i1 = 0, i2 = 0, tot, j; - for (i = 0; i < c1->totlayer; i++) { + for (int i = 0; i < c1->totlayer; i++) { if (ELEM(c1->layers[i].type, CD_MVERT, CD_MEDGE, @@ -441,7 +444,7 @@ static int customdata_compare( } } - for (i = 0; i < c2->totlayer; i++) { + for (int i = 0; i < c2->totlayer; i++) { if (ELEM(c2->layers[i].type, CD_MVERT, CD_MEDGE, @@ -457,12 +460,86 @@ static int customdata_compare( return MESHCMP_CDLAYERS_MISMATCH; } + l1 = c1->layers; + l2 = c2->layers; + + for (i1 = 0; i1 < c1->totlayer; i1++) { + l1 = c1->layers + i1; + if ((CD_TYPE_AS_MASK(l1->type) & CD_MASK_PROP_ALL) == 0) { + /* Skip non generic attribute layers. */ + continue; + } + + bool found_corresponding_layer = false; + for (i2 = 0; i2 < c2->totlayer; i2++) { + l2 = c2->layers + i2; + if (l1->type != l2->type || !STREQ(l1->name, l2->name)) { + continue; + } + found_corresponding_layer = true; + /* At this point `l1` and `l2` have the same name and type, so they should be compared. */ + + switch (l1->type) { + + case CD_PROP_FLOAT: { + const float *l1_data = l1->data; + const float *l2_data = l2->data; + + for (int i = 0; i < total_length; i++) { + if (fabsf(l1_data[i] - l2_data[i]) > thresh) { + return MESHCMP_ATTRIBUTE_VALUE_MISMATCH; + } + } + break; + } + case CD_PROP_FLOAT2: { + const float(*l1_data)[2] = l1->data; + const float(*l2_data)[2] = l2->data; + + for (int i = 0; i < total_length; i++) { + if (len_squared_v2v2(l1_data[i], l2_data[i]) > thresh_sq) { + return MESHCMP_ATTRIBUTE_VALUE_MISMATCH; + } + } + break; + } + case CD_PROP_FLOAT3: { + const float(*l1_data)[3] = l1->data; + const float(*l2_data)[3] = l2->data; + + for (int i = 0; i < total_length; i++) { + if (len_squared_v3v3(l1_data[i], l2_data[i]) > thresh_sq) { + return MESHCMP_ATTRIBUTE_VALUE_MISMATCH; + } + } + break; + } + default: { + int element_size = CustomData_sizeof(l1->type); + for (int i = 0; i < total_length; i++) { + int offset = element_size * i; + if (!CustomData_data_equals(l1->type, + POINTER_OFFSET(l1->data, offset), + POINTER_OFFSET(l2->data, offset))) { + return MESHCMP_ATTRIBUTE_VALUE_MISMATCH; + } + } + break; + } + } + } + + if (!found_corresponding_layer) { + return MESHCMP_CDLAYERS_MISMATCH; + } + } + l1 = c1->layers; l2 = c2->layers; tot = i1; i1 = 0; i2 = 0; - for (i = 0; i < tot; i++) { + for (int i = 0; i < tot; i++) { while ( i1 < c1->totlayer && !ELEM(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY, CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT)) { @@ -626,19 +703,19 @@ const char *BKE_mesh_cmp(Mesh *me1, Mesh *me2, float thresh) return "Number of loops don't match"; } - if ((c = customdata_compare(&me1->vdata, &me2->vdata, me1, me2, thresh))) { + if ((c = customdata_compare(&me1->vdata, &me2->vdata, me1->totvert, me1, me2, thresh))) { return cmpcode_to_str(c); } - if ((c = customdata_compare(&me1->edata, &me2->edata, me1, me2, thresh))) { + if ((c = customdata_compare(&me1->edata, &me2->edata, me1->totedge, me1, me2, thresh))) { return cmpcode_to_str(c); } - if ((c = customdata_compare(&me1->ldata, &me2->ldata, me1, me2, thresh))) { + if ((c = customdata_compare(&me1->ldata, &me2->ldata, me1->totloop, me1, me2, thresh))) { return cmpcode_to_str(c); } - if ((c = customdata_compare(&me1->pdata, &me2->pdata, me1, me2, thresh))) { + if ((c = customdata_compare(&me1->pdata, &me2->pdata, me1->totpoly, me1, me2, thresh))) { return cmpcode_to_str(c); } -- cgit v1.2.3