diff options
author | Peter Kim <pk15950@gmail.com> | 2022-04-03 05:10:23 +0300 |
---|---|---|
committer | Peter Kim <pk15950@gmail.com> | 2022-04-03 05:10:23 +0300 |
commit | d34e2cc3be677ec0e0a26b4239b1d329e6822819 (patch) | |
tree | fa933856589ff369ed739f38f603fca4f2458987 | |
parent | 07b0b6e9b78c9fc99f563244aec202acda536f2d (diff) | |
parent | 79ff65d07bac0ecf0170542f86dc03a0228b53d5 (diff) |
Merge branch 'master' into xr-dev
665 files changed, 23362 insertions, 7602 deletions
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh index 41c6fa495d8..a9a9e4f4ca0 100755 --- a/build_files/build_environment/install_deps.sh +++ b/build_files/build_environment/install_deps.sh @@ -432,8 +432,8 @@ PYTHON_MODULES_PIP=( ) -BOOST_VERSION="1.73.0" -BOOST_VERSION_SHORT="1.73" +BOOST_VERSION="1.78.0" +BOOST_VERSION_SHORT="1.78" BOOST_VERSION_MIN="1.49" BOOST_VERSION_MEX="2.0" BOOST_FORCE_BUILD=false @@ -442,15 +442,15 @@ BOOST_SKIP=false TBB_VERSION="2020" TBB_VERSION_SHORT="2020" -TBB_VERSION_UPDATE="_U2" # Used for source packages... +TBB_VERSION_UPDATE="_U3" # Used for source packages... TBB_VERSION_MIN="2018" TBB_VERSION_MEX="2022" TBB_FORCE_BUILD=false TBB_FORCE_REBUILD=false TBB_SKIP=false -OCIO_VERSION="2.0.0" -OCIO_VERSION_SHORT="2.0" +OCIO_VERSION="2.1.1" +OCIO_VERSION_SHORT="2.1" OCIO_VERSION_MIN="2.0" OCIO_VERSION_MEX="3.0" OCIO_FORCE_BUILD=false @@ -466,10 +466,10 @@ OPENEXR_FORCE_REBUILD=false OPENEXR_SKIP=false _with_built_openexr=false -OIIO_VERSION="2.2.15.1" -OIIO_VERSION_SHORT="2.2" +OIIO_VERSION="2.3.13.0" +OIIO_VERSION_SHORT="2.3" OIIO_VERSION_MIN="2.1.12" -OIIO_VERSION_MEX="2.3.0" +OIIO_VERSION_MEX="2.4.0" OIIO_FORCE_BUILD=false OIIO_FORCE_REBUILD=false OIIO_SKIP=false @@ -493,7 +493,7 @@ OSL_FORCE_REBUILD=false OSL_SKIP=false # OpenSubdiv needs to be compiled for now -OSD_VERSION="3.4.3" +OSD_VERSION="3.4.4" OSD_VERSION_SHORT="3.4" OSD_VERSION_MIN="3.4" OSD_VERSION_MEX="4.0" @@ -502,19 +502,19 @@ OSD_FORCE_REBUILD=false OSD_SKIP=false # OpenVDB needs to be compiled for now -OPENVDB_BLOSC_VERSION="1.5.0" +OPENVDB_BLOSC_VERSION="1.21.1" -OPENVDB_VERSION="8.0.1" -OPENVDB_VERSION_SHORT="8.0" -OPENVDB_VERSION_MIN="8.0" -OPENVDB_VERSION_MEX="8.1" +OPENVDB_VERSION="9.0.0" +OPENVDB_VERSION_SHORT="9.0" +OPENVDB_VERSION_MIN="9.0" +OPENVDB_VERSION_MEX="9.1" OPENVDB_FORCE_BUILD=false OPENVDB_FORCE_REBUILD=false OPENVDB_SKIP=false # Alembic needs to be compiled for now -ALEMBIC_VERSION="1.7.16" -ALEMBIC_VERSION_SHORT="1.7" +ALEMBIC_VERSION="1.8.3" +ALEMBIC_VERSION_SHORT="1.8" ALEMBIC_VERSION_MIN="1.7" ALEMBIC_VERSION_MEX="2.0" ALEMBIC_FORCE_BUILD=false @@ -537,15 +537,15 @@ OPENCOLLADA_FORCE_BUILD=false OPENCOLLADA_FORCE_REBUILD=false OPENCOLLADA_SKIP=false -EMBREE_VERSION="3.10.0" -EMBREE_VERSION_SHORT="3.10" -EMBREE_VERSION_MIN="3.10" +EMBREE_VERSION="3.13.3" +EMBREE_VERSION_SHORT="3.13" +EMBREE_VERSION_MIN="3.13" EMBREE_VERSION_MEX="4.0" EMBREE_FORCE_BUILD=false EMBREE_FORCE_REBUILD=false EMBREE_SKIP=false -OIDN_VERSION="1.4.1" +OIDN_VERSION="1.4.3" OIDN_VERSION_SHORT="1.4" OIDN_VERSION_MIN="1.4.0" OIDN_VERSION_MEX="1.5" @@ -553,7 +553,7 @@ OIDN_FORCE_BUILD=false OIDN_FORCE_REBUILD=false OIDN_SKIP=false -ISPC_VERSION="1.16.0" +ISPC_VERSION="1.17.0" FFMPEG_VERSION="4.4" FFMPEG_VERSION_SHORT="4.4" @@ -1029,7 +1029,7 @@ OPENEXR_SOURCE_REPO_UID="0ac2ea34c8f3134148a5df4052e40f155b76f6fb" #~ OPENEXR_SOURCE=( "https://github.com/openexr/openexr/archive/$OPENEXR_SOURCE_REPO_UID.tar.gz" ) OIIO_USE_REPO=false -OIIO_SOURCE=( "https://github.com/OpenImageIO/oiio/archive/Release-$OIIO_VERSION.tar.gz" ) +OIIO_SOURCE=( "https://github.com/OpenImageIO/oiio/archive/refs/tags/v$OIIO_VERSION.tar.gz" ) #~ OIIO_SOURCE_REPO=( "https://github.com/OpenImageIO/oiio.git" ) #~ OIIO_SOURCE_REPO_UID="c9e67275a0b248ead96152f6d2221cc0c0f278a4" @@ -2034,7 +2034,7 @@ compile_OIIO() { else download OIIO_SOURCE[@] "$_src.tar.gz" INFO "Unpacking OpenImageIO-$OIIO_VERSION" - tar -C $SRC --transform "s,(.*/?)oiio-Release-[^/]*(.*),\1OpenImageIO-$OIIO_VERSION\2,x" -xf $_src.tar.gz + tar -C $SRC --transform "s,(.*/?)oiio-[^/]*(.*),\1OpenImageIO-$OIIO_VERSION\2,x" -xf $_src.tar.gz fi fi diff --git a/doc/python_api/examples/bpy.types.UIList.1.py b/doc/python_api/examples/bpy.types.UIList.1.py index a8b1cfa85a5..2b2a0d90c3b 100644 --- a/doc/python_api/examples/bpy.types.UIList.1.py +++ b/doc/python_api/examples/bpy.types.UIList.1.py @@ -41,7 +41,7 @@ class MATERIAL_UL_matslots_example(bpy.types.UIList): else: layout.label(text="", translate=False, icon_value=icon) # 'GRID' layout type should be as compact as possible (typically a single icon!). - elif self.layout_type in {'GRID'}: + elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.label(text="", icon_value=icon) diff --git a/doc/python_api/examples/bpy.types.UIList.2.py b/doc/python_api/examples/bpy.types.UIList.2.py index 5f3ecbf116c..05c9e9b3a17 100644 --- a/doc/python_api/examples/bpy.types.UIList.2.py +++ b/doc/python_api/examples/bpy.types.UIList.2.py @@ -73,7 +73,7 @@ class MESH_UL_vgroups_slow(bpy.types.UIList): layout.prop(vgroup, "name", text="", emboss=False, icon_value=icon) icon = 'LOCKED' if vgroup.lock_weight else 'UNLOCKED' layout.prop(vgroup, "lock_weight", text="", icon=icon, emboss=False) - elif self.layout_type in {'GRID'}: + elif self.layout_type == 'GRID': layout.alignment = 'CENTER' if flt_flag & self.VGROUP_EMPTY: layout.enabled = False diff --git a/extern/fmtlib/LICENSE.rst b/extern/fmtlib/LICENSE.rst new file mode 100644 index 00000000000..f0ec3db4d2a --- /dev/null +++ b/extern/fmtlib/LICENSE.rst @@ -0,0 +1,27 @@ +Copyright (c) 2012 - present, Victor Zverovich + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--- Optional exception to the license --- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into a machine-executable object form of such +source code, you may redistribute such embedded portions in such object form +without including the above copyright and permission notices. diff --git a/extern/fmtlib/README.blender b/extern/fmtlib/README.blender new file mode 100644 index 00000000000..98c5684305e --- /dev/null +++ b/extern/fmtlib/README.blender @@ -0,0 +1,8 @@ +Project: {fmt} +URL: https://github.com/fmtlib/fmt +License: MIT +Upstream version: 8.1.1 (b6f4cea) +Local modifications: + +- Took only files needed for Blender: LICENSE, README and include/fmt + folder's core.h, format-inl.h, format.h diff --git a/extern/fmtlib/README.rst b/extern/fmtlib/README.rst new file mode 100644 index 00000000000..394f28d97bb --- /dev/null +++ b/extern/fmtlib/README.rst @@ -0,0 +1,528 @@ +{fmt} +===== + +.. image:: https://github.com/fmtlib/fmt/workflows/linux/badge.svg + :target: https://github.com/fmtlib/fmt/actions?query=workflow%3Alinux + +.. image:: https://github.com/fmtlib/fmt/workflows/macos/badge.svg + :target: https://github.com/fmtlib/fmt/actions?query=workflow%3Amacos + +.. image:: https://github.com/fmtlib/fmt/workflows/windows/badge.svg + :target: https://github.com/fmtlib/fmt/actions?query=workflow%3Awindows + +.. image:: https://ci.appveyor.com/api/projects/status/ehjkiefde6gucy1v?svg=true + :target: https://ci.appveyor.com/project/vitaut/fmt + +.. image:: https://oss-fuzz-build-logs.storage.googleapis.com/badges/fmt.svg + :alt: fmt is continuously fuzzed at oss-fuzz + :target: https://bugs.chromium.org/p/oss-fuzz/issues/list?\ + colspec=ID%20Type%20Component%20Status%20Proj%20Reported%20Owner%20\ + Summary&q=proj%3Dfmt&can=1 + +.. image:: https://img.shields.io/badge/stackoverflow-fmt-blue.svg + :alt: Ask questions at StackOverflow with the tag fmt + :target: https://stackoverflow.com/questions/tagged/fmt + +**{fmt}** is an open-source formatting library providing a fast and safe +alternative to C stdio and C++ iostreams. + +If you like this project, please consider donating to the BYSOL +Foundation that helps victims of political repressions in Belarus: +https://bysol.org/en/bs/general/. + +`Documentation <https://fmt.dev>`__ + +Q&A: ask questions on `StackOverflow with the tag fmt +<https://stackoverflow.com/questions/tagged/fmt>`_. + +Try {fmt} in `Compiler Explorer <https://godbolt.org/z/Eq5763>`_. + +Features +-------- + +* Simple `format API <https://fmt.dev/latest/api.html>`_ with positional arguments + for localization +* Implementation of `C++20 std::format + <https://en.cppreference.com/w/cpp/utility/format>`__ +* `Format string syntax <https://fmt.dev/latest/syntax.html>`_ similar to Python's + `format <https://docs.python.org/3/library/stdtypes.html#str.format>`_ +* Fast IEEE 754 floating-point formatter with correct rounding, shortness and + round-trip guarantees +* Safe `printf implementation + <https://fmt.dev/latest/api.html#printf-formatting>`_ including the POSIX + extension for positional arguments +* Extensibility: `support for user-defined types + <https://fmt.dev/latest/api.html#formatting-user-defined-types>`_ +* High performance: faster than common standard library implementations of + ``(s)printf``, iostreams, ``to_string`` and ``to_chars``, see `Speed tests`_ + and `Converting a hundred million integers to strings per second + <http://www.zverovich.net/2020/06/13/fast-int-to-string-revisited.html>`_ +* Small code size both in terms of source code with the minimum configuration + consisting of just three files, ``core.h``, ``format.h`` and ``format-inl.h``, + and compiled code; see `Compile time and code bloat`_ +* Reliability: the library has an extensive set of `tests + <https://github.com/fmtlib/fmt/tree/master/test>`_ and is `continuously fuzzed + <https://bugs.chromium.org/p/oss-fuzz/issues/list?colspec=ID%20Type%20 + Component%20Status%20Proj%20Reported%20Owner%20Summary&q=proj%3Dfmt&can=1>`_ +* Safety: the library is fully type safe, errors in format strings can be + reported at compile time, automatic memory management prevents buffer overflow + errors +* Ease of use: small self-contained code base, no external dependencies, + permissive MIT `license + <https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_ +* `Portability <https://fmt.dev/latest/index.html#portability>`_ with + consistent output across platforms and support for older compilers +* Clean warning-free codebase even on high warning levels such as + ``-Wall -Wextra -pedantic`` +* Locale-independence by default +* Optional header-only configuration enabled with the ``FMT_HEADER_ONLY`` macro + +See the `documentation <https://fmt.dev>`_ for more details. + +Examples +-------- + +**Print to stdout** (`run <https://godbolt.org/z/Tevcjh>`_) + +.. code:: c++ + + #include <fmt/core.h> + + int main() { + fmt::print("Hello, world!\n"); + } + +**Format a string** (`run <https://godbolt.org/z/oK8h33>`_) + +.. code:: c++ + + std::string s = fmt::format("The answer is {}.", 42); + // s == "The answer is 42." + +**Format a string using positional arguments** (`run <https://godbolt.org/z/Yn7Txe>`_) + +.. code:: c++ + + std::string s = fmt::format("I'd rather be {1} than {0}.", "right", "happy"); + // s == "I'd rather be happy than right." + +**Print chrono durations** (`run <https://godbolt.org/z/K8s4Mc>`_) + +.. code:: c++ + + #include <fmt/chrono.h> + + int main() { + using namespace std::literals::chrono_literals; + fmt::print("Default format: {} {}\n", 42s, 100ms); + fmt::print("strftime-like format: {:%H:%M:%S}\n", 3h + 15min + 30s); + } + +Output:: + + Default format: 42s 100ms + strftime-like format: 03:15:30 + +**Print a container** (`run <https://godbolt.org/z/MjsY7c>`_) + +.. code:: c++ + + #include <vector> + #include <fmt/ranges.h> + + int main() { + std::vector<int> v = {1, 2, 3}; + fmt::print("{}\n", v); + } + +Output:: + + [1, 2, 3] + +**Check a format string at compile time** + +.. code:: c++ + + std::string s = fmt::format("{:d}", "I am not a number"); + +This gives a compile-time error in C++20 because ``d`` is an invalid format +specifier for a string. + +**Write a file from a single thread** + +.. code:: c++ + + #include <fmt/os.h> + + int main() { + auto out = fmt::output_file("guide.txt"); + out.print("Don't {}", "Panic"); + } + +This can be `5 to 9 times faster than fprintf +<http://www.zverovich.net/2020/08/04/optimal-file-buffer-size.html>`_. + +**Print with colors and text styles** + +.. code:: c++ + + #include <fmt/color.h> + + int main() { + fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold, + "Hello, {}!\n", "world"); + fmt::print(fg(fmt::color::floral_white) | bg(fmt::color::slate_gray) | + fmt::emphasis::underline, "Hello, {}!\n", "мир"); + fmt::print(fg(fmt::color::steel_blue) | fmt::emphasis::italic, + "Hello, {}!\n", "世界"); + } + +Output on a modern terminal: + +.. image:: https://user-images.githubusercontent.com/ + 576385/88485597-d312f600-cf2b-11ea-9cbe-61f535a86e28.png + +Benchmarks +---------- + +Speed tests +~~~~~~~~~~~ + +================= ============= =========== +Library Method Run Time, s +================= ============= =========== +libc printf 1.04 +libc++ std::ostream 3.05 +{fmt} 6.1.1 fmt::print 0.75 +Boost Format 1.67 boost::format 7.24 +Folly Format folly::format 2.23 +================= ============= =========== + +{fmt} is the fastest of the benchmarked methods, ~35% faster than ``printf``. + +The above results were generated by building ``tinyformat_test.cpp`` on macOS +10.14.6 with ``clang++ -O3 -DNDEBUG -DSPEED_TEST -DHAVE_FORMAT``, and taking the +best of three runs. In the test, the format string ``"%0.10f:%04d:%+g:%s:%p:%c:%%\n"`` +or equivalent is filled 2,000,000 times with output sent to ``/dev/null``; for +further details refer to the `source +<https://github.com/fmtlib/format-benchmark/blob/master/src/tinyformat-test.cc>`_. + +{fmt} is up to 20-30x faster than ``std::ostringstream`` and ``sprintf`` on +floating-point formatting (`dtoa-benchmark <https://github.com/fmtlib/dtoa-benchmark>`_) +and faster than `double-conversion <https://github.com/google/double-conversion>`_ and +`ryu <https://github.com/ulfjack/ryu>`_: + +.. image:: https://user-images.githubusercontent.com/576385/ + 95684665-11719600-0ba8-11eb-8e5b-972ff4e49428.png + :target: https://fmt.dev/unknown_mac64_clang12.0.html + +Compile time and code bloat +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The script `bloat-test.py +<https://github.com/fmtlib/format-benchmark/blob/master/bloat-test.py>`_ +from `format-benchmark <https://github.com/fmtlib/format-benchmark>`_ +tests compile time and code bloat for nontrivial projects. +It generates 100 translation units and uses ``printf()`` or its alternative +five times in each to simulate a medium sized project. The resulting +executable size and compile time (Apple LLVM version 8.1.0 (clang-802.0.42), +macOS Sierra, best of three) is shown in the following tables. + +**Optimized build (-O3)** + +============= =============== ==================== ================== +Method Compile Time, s Executable size, KiB Stripped size, KiB +============= =============== ==================== ================== +printf 2.6 29 26 +printf+string 16.4 29 26 +iostreams 31.1 59 55 +{fmt} 19.0 37 34 +Boost Format 91.9 226 203 +Folly Format 115.7 101 88 +============= =============== ==================== ================== + +As you can see, {fmt} has 60% less overhead in terms of resulting binary code +size compared to iostreams and comes pretty close to ``printf``. Boost Format +and Folly Format have the largest overheads. + +``printf+string`` is the same as ``printf`` but with extra ``<string>`` +include to measure the overhead of the latter. + +**Non-optimized build** + +============= =============== ==================== ================== +Method Compile Time, s Executable size, KiB Stripped size, KiB +============= =============== ==================== ================== +printf 2.2 33 30 +printf+string 16.0 33 30 +iostreams 28.3 56 52 +{fmt} 18.2 59 50 +Boost Format 54.1 365 303 +Folly Format 79.9 445 430 +============= =============== ==================== ================== + +``libc``, ``lib(std)c++`` and ``libfmt`` are all linked as shared libraries to +compare formatting function overhead only. Boost Format is a +header-only library so it doesn't provide any linkage options. + +Running the tests +~~~~~~~~~~~~~~~~~ + +Please refer to `Building the library`__ for the instructions on how to build +the library and run the unit tests. + +__ https://fmt.dev/latest/usage.html#building-the-library + +Benchmarks reside in a separate repository, +`format-benchmarks <https://github.com/fmtlib/format-benchmark>`_, +so to run the benchmarks you first need to clone this repository and +generate Makefiles with CMake:: + + $ git clone --recursive https://github.com/fmtlib/format-benchmark.git + $ cd format-benchmark + $ cmake . + +Then you can run the speed test:: + + $ make speed-test + +or the bloat test:: + + $ make bloat-test + +Migrating code +-------------- + +`clang-tidy-fmt <https://github.com/mikecrowe/clang-tidy-fmt>`_ provides clang +tidy checks for converting occurrences of ``printf`` and ``fprintf`` to +``fmt::print``. + +Projects using this library +--------------------------- + +* `0 A.D. <https://play0ad.com/>`_: a free, open-source, cross-platform + real-time strategy game + +* `2GIS <https://2gis.ru/>`_: free business listings with a city map + +* `AMPL/MP <https://github.com/ampl/mp>`_: + an open-source library for mathematical programming + +* `Aseprite <https://github.com/aseprite/aseprite>`_: + animated sprite editor & pixel art tool + +* `AvioBook <https://www.aviobook.aero/en>`_: a comprehensive aircraft + operations suite + +* `Blizzard Battle.net <https://battle.net/>`_: an online gaming platform + +* `Celestia <https://celestia.space/>`_: real-time 3D visualization of space + +* `Ceph <https://ceph.com/>`_: a scalable distributed storage system + +* `ccache <https://ccache.dev/>`_: a compiler cache + +* `ClickHouse <https://github.com/ClickHouse/ClickHouse>`_: analytical database + management system + +* `CUAUV <https://cuauv.org/>`_: Cornell University's autonomous underwater + vehicle + +* `Drake <https://drake.mit.edu/>`_: a planning, control, and analysis toolbox + for nonlinear dynamical systems (MIT) + +* `Envoy <https://lyft.github.io/envoy/>`_: C++ L7 proxy and communication bus + (Lyft) + +* `FiveM <https://fivem.net/>`_: a modification framework for GTA V + +* `fmtlog <https://github.com/MengRao/fmtlog>`_: a performant fmtlib-style + logging library with latency in nanoseconds + +* `Folly <https://github.com/facebook/folly>`_: Facebook open-source library + +* `Grand Mountain Adventure + <https://store.steampowered.com/app/1247360/Grand_Mountain_Adventure/>`_: + A beautiful open-world ski & snowboarding game + +* `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_: + Player vs Player Gaming Network with tweaks + +* `KBEngine <https://github.com/kbengine/kbengine>`_: an open-source MMOG server + engine + +* `Keypirinha <https://keypirinha.com/>`_: a semantic launcher for Windows + +* `Kodi <https://kodi.tv/>`_ (formerly xbmc): home theater software + +* `Knuth <https://kth.cash/>`_: high-performance Bitcoin full-node + +* `Microsoft Verona <https://github.com/microsoft/verona>`_: + research programming language for concurrent ownership + +* `MongoDB <https://mongodb.com/>`_: distributed document database + +* `MongoDB Smasher <https://github.com/duckie/mongo_smasher>`_: a small tool to + generate randomized datasets + +* `OpenSpace <https://openspaceproject.com/>`_: an open-source + astrovisualization framework + +* `PenUltima Online (POL) <https://www.polserver.com/>`_: + an MMO server, compatible with most Ultima Online clients + +* `PyTorch <https://github.com/pytorch/pytorch>`_: an open-source machine + learning library + +* `quasardb <https://www.quasardb.net/>`_: a distributed, high-performance, + associative database + +* `Quill <https://github.com/odygrd/quill>`_: asynchronous low-latency logging library + +* `QKW <https://github.com/ravijanjam/qkw>`_: generalizing aliasing to simplify + navigation, and executing complex multi-line terminal command sequences + +* `redis-cerberus <https://github.com/HunanTV/redis-cerberus>`_: a Redis cluster + proxy + +* `redpanda <https://vectorized.io/redpanda>`_: a 10x faster Kafka® replacement + for mission critical systems written in C++ + +* `rpclib <http://rpclib.net/>`_: a modern C++ msgpack-RPC server and client + library + +* `Salesforce Analytics Cloud + <https://www.salesforce.com/analytics-cloud/overview/>`_: + business intelligence software + +* `Scylla <https://www.scylladb.com/>`_: a Cassandra-compatible NoSQL data store + that can handle 1 million transactions per second on a single server + +* `Seastar <http://www.seastar-project.org/>`_: an advanced, open-source C++ + framework for high-performance server applications on modern hardware + +* `spdlog <https://github.com/gabime/spdlog>`_: super fast C++ logging library + +* `Stellar <https://www.stellar.org/>`_: financial platform + +* `Touch Surgery <https://www.touchsurgery.com/>`_: surgery simulator + +* `TrinityCore <https://github.com/TrinityCore/TrinityCore>`_: open-source + MMORPG framework + +* `Windows Terminal <https://github.com/microsoft/terminal>`_: the new Windows + terminal + +`More... <https://github.com/search?q=fmtlib&type=Code>`_ + +If you are aware of other projects using this library, please let me know +by `email <mailto:victor.zverovich@gmail.com>`_ or by submitting an +`issue <https://github.com/fmtlib/fmt/issues>`_. + +Motivation +---------- + +So why yet another formatting library? + +There are plenty of methods for doing this task, from standard ones like +the printf family of function and iostreams to Boost Format and FastFormat +libraries. The reason for creating a new library is that every existing +solution that I found either had serious issues or didn't provide +all the features I needed. + +printf +~~~~~~ + +The good thing about ``printf`` is that it is pretty fast and readily available +being a part of the C standard library. The main drawback is that it +doesn't support user-defined types. ``printf`` also has safety issues although +they are somewhat mitigated with `__attribute__ ((format (printf, ...)) +<https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_ in GCC. +There is a POSIX extension that adds positional arguments required for +`i18n <https://en.wikipedia.org/wiki/Internationalization_and_localization>`_ +to ``printf`` but it is not a part of C99 and may not be available on some +platforms. + +iostreams +~~~~~~~~~ + +The main issue with iostreams is best illustrated with an example: + +.. code:: c++ + + std::cout << std::setprecision(2) << std::fixed << 1.23456 << "\n"; + +which is a lot of typing compared to printf: + +.. code:: c++ + + printf("%.2f\n", 1.23456); + +Matthew Wilson, the author of FastFormat, called this "chevron hell". iostreams +don't support positional arguments by design. + +The good part is that iostreams support user-defined types and are safe although +error handling is awkward. + +Boost Format +~~~~~~~~~~~~ + +This is a very powerful library which supports both ``printf``-like format +strings and positional arguments. Its main drawback is performance. According to +various benchmarks, it is much slower than other methods considered here. Boost +Format also has excessive build times and severe code bloat issues (see +`Benchmarks`_). + +FastFormat +~~~~~~~~~~ + +This is an interesting library which is fast, safe and has positional arguments. +However, it has significant limitations, citing its author: + + Three features that have no hope of being accommodated within the + current design are: + + * Leading zeros (or any other non-space padding) + * Octal/hexadecimal encoding + * Runtime width/alignment specification + +It is also quite big and has a heavy dependency, STLSoft, which might be too +restrictive for using it in some projects. + +Boost Spirit.Karma +~~~~~~~~~~~~~~~~~~ + +This is not really a formatting library but I decided to include it here for +completeness. As iostreams, it suffers from the problem of mixing verbatim text +with arguments. The library is pretty fast, but slower on integer formatting +than ``fmt::format_to`` with format string compilation on Karma's own benchmark, +see `Converting a hundred million integers to strings per second +<http://www.zverovich.net/2020/06/13/fast-int-to-string-revisited.html>`_. + +License +------- + +{fmt} is distributed under the MIT `license +<https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_. + +Documentation License +--------------------- + +The `Format String Syntax <https://fmt.dev/latest/syntax.html>`_ +section in the documentation is based on the one from Python `string module +documentation <https://docs.python.org/3/library/string.html#module-string>`_. +For this reason the documentation is distributed under the Python Software +Foundation license available in `doc/python-license.txt +<https://raw.github.com/fmtlib/fmt/master/doc/python-license.txt>`_. +It only applies if you distribute the documentation of {fmt}. + +Maintainers +----------- + +The {fmt} library is maintained by Victor Zverovich (`vitaut +<https://github.com/vitaut>`_) and Jonathan Müller (`foonathan +<https://github.com/foonathan>`_) with contributions from many other people. +See `Contributors <https://github.com/fmtlib/fmt/graphs/contributors>`_ and +`Releases <https://github.com/fmtlib/fmt/releases>`_ for some of the names. +Let us know if your contribution is not listed or mentioned incorrectly and +we'll make it right. diff --git a/extern/fmtlib/include/fmt/core.h b/extern/fmtlib/include/fmt/core.h new file mode 100644 index 00000000000..92a7aa1df69 --- /dev/null +++ b/extern/fmtlib/include/fmt/core.h @@ -0,0 +1,3236 @@ +// Formatting library for C++ - the core API for char/UTF-8 +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_CORE_H_ +#define FMT_CORE_H_ + +#include <cstddef> // std::byte +#include <cstdio> // std::FILE +#include <cstring> +#include <iterator> +#include <limits> +#include <string> +#include <type_traits> + +// The fmt library version in the form major * 10000 + minor * 100 + patch. +#define FMT_VERSION 80101 + +#if defined(__clang__) && !defined(__ibmxl__) +# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__) +#else +# define FMT_CLANG_VERSION 0 +#endif + +#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) && \ + !defined(__NVCOMPILER) +# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) +#else +# define FMT_GCC_VERSION 0 +#endif + +#ifndef FMT_GCC_PRAGMA +// Workaround _Pragma bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59884. +# if FMT_GCC_VERSION >= 504 +# define FMT_GCC_PRAGMA(arg) _Pragma(arg) +# else +# define FMT_GCC_PRAGMA(arg) +# endif +#endif + +#ifdef __ICL +# define FMT_ICC_VERSION __ICL +#elif defined(__INTEL_COMPILER) +# define FMT_ICC_VERSION __INTEL_COMPILER +#else +# define FMT_ICC_VERSION 0 +#endif + +#ifdef __NVCC__ +# define FMT_NVCC __NVCC__ +#else +# define FMT_NVCC 0 +#endif + +#ifdef _MSC_VER +# define FMT_MSC_VER _MSC_VER +# define FMT_MSC_WARNING(...) __pragma(warning(__VA_ARGS__)) +#else +# define FMT_MSC_VER 0 +# define FMT_MSC_WARNING(...) +#endif + +#ifdef __has_feature +# define FMT_HAS_FEATURE(x) __has_feature(x) +#else +# define FMT_HAS_FEATURE(x) 0 +#endif + +#if defined(__has_include) && \ + (!defined(__INTELLISENSE__) || FMT_MSC_VER > 1900) && \ + (!FMT_ICC_VERSION || FMT_ICC_VERSION >= 1600) +# define FMT_HAS_INCLUDE(x) __has_include(x) +#else +# define FMT_HAS_INCLUDE(x) 0 +#endif + +#ifdef __has_cpp_attribute +# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#else +# define FMT_HAS_CPP_ATTRIBUTE(x) 0 +#endif + +#ifdef _MSVC_LANG +# define FMT_CPLUSPLUS _MSVC_LANG +#else +# define FMT_CPLUSPLUS __cplusplus +#endif + +#define FMT_HAS_CPP14_ATTRIBUTE(attribute) \ + (FMT_CPLUSPLUS >= 201402L && FMT_HAS_CPP_ATTRIBUTE(attribute)) + +#define FMT_HAS_CPP17_ATTRIBUTE(attribute) \ + (FMT_CPLUSPLUS >= 201703L && FMT_HAS_CPP_ATTRIBUTE(attribute)) + +// Check if relaxed C++14 constexpr is supported. +// GCC doesn't allow throw in constexpr until version 6 (bug 67371). +#ifndef FMT_USE_CONSTEXPR +# define FMT_USE_CONSTEXPR \ + (FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VER >= 1912 || \ + (FMT_GCC_VERSION >= 600 && __cplusplus >= 201402L)) && \ + !FMT_NVCC && !FMT_ICC_VERSION +#endif +#if FMT_USE_CONSTEXPR +# define FMT_CONSTEXPR constexpr +# define FMT_CONSTEXPR_DECL constexpr +#else +# define FMT_CONSTEXPR +# define FMT_CONSTEXPR_DECL +#endif + +#if ((__cplusplus >= 202002L) && \ + (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE > 9)) || \ + (__cplusplus >= 201709L && FMT_GCC_VERSION >= 1002) +# define FMT_CONSTEXPR20 constexpr +#else +# define FMT_CONSTEXPR20 +#endif + +// Check if constexpr std::char_traits<>::compare,length is supported. +#if defined(__GLIBCXX__) +# if __cplusplus >= 201703L && defined(_GLIBCXX_RELEASE) && \ + _GLIBCXX_RELEASE >= 7 // GCC 7+ libstdc++ has _GLIBCXX_RELEASE. +# define FMT_CONSTEXPR_CHAR_TRAITS constexpr +# endif +#elif defined(_LIBCPP_VERSION) && __cplusplus >= 201703L && \ + _LIBCPP_VERSION >= 4000 +# define FMT_CONSTEXPR_CHAR_TRAITS constexpr +#elif FMT_MSC_VER >= 1914 && _MSVC_LANG >= 201703L +# define FMT_CONSTEXPR_CHAR_TRAITS constexpr +#endif +#ifndef FMT_CONSTEXPR_CHAR_TRAITS +# define FMT_CONSTEXPR_CHAR_TRAITS +#endif + +// Check if exceptions are disabled. +#ifndef FMT_EXCEPTIONS +# if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || \ + FMT_MSC_VER && !_HAS_EXCEPTIONS +# define FMT_EXCEPTIONS 0 +# else +# define FMT_EXCEPTIONS 1 +# endif +#endif + +// Define FMT_USE_NOEXCEPT to make fmt use noexcept (C++11 feature). +#ifndef FMT_USE_NOEXCEPT +# define FMT_USE_NOEXCEPT 0 +#endif + +#if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \ + FMT_GCC_VERSION >= 408 || FMT_MSC_VER >= 1900 +# define FMT_DETECTED_NOEXCEPT noexcept +# define FMT_HAS_CXX11_NOEXCEPT 1 +#else +# define FMT_DETECTED_NOEXCEPT throw() +# define FMT_HAS_CXX11_NOEXCEPT 0 +#endif + +#ifndef FMT_NOEXCEPT +# if FMT_EXCEPTIONS || FMT_HAS_CXX11_NOEXCEPT +# define FMT_NOEXCEPT FMT_DETECTED_NOEXCEPT +# else +# define FMT_NOEXCEPT +# endif +#endif + +// [[noreturn]] is disabled on MSVC and NVCC because of bogus unreachable code +// warnings. +#if FMT_EXCEPTIONS && FMT_HAS_CPP_ATTRIBUTE(noreturn) && !FMT_MSC_VER && \ + !FMT_NVCC +# define FMT_NORETURN [[noreturn]] +#else +# define FMT_NORETURN +#endif + +#if __cplusplus == 201103L || __cplusplus == 201402L +# if defined(__INTEL_COMPILER) || defined(__PGI) +# define FMT_FALLTHROUGH +# elif defined(__clang__) +# define FMT_FALLTHROUGH [[clang::fallthrough]] +# elif FMT_GCC_VERSION >= 700 && \ + (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 520) +# define FMT_FALLTHROUGH [[gnu::fallthrough]] +# else +# define FMT_FALLTHROUGH +# endif +#elif FMT_HAS_CPP17_ATTRIBUTE(fallthrough) +# define FMT_FALLTHROUGH [[fallthrough]] +#else +# define FMT_FALLTHROUGH +#endif + +#ifndef FMT_NODISCARD +# if FMT_HAS_CPP17_ATTRIBUTE(nodiscard) +# define FMT_NODISCARD [[nodiscard]] +# else +# define FMT_NODISCARD +# endif +#endif + +#ifndef FMT_USE_FLOAT +# define FMT_USE_FLOAT 1 +#endif +#ifndef FMT_USE_DOUBLE +# define FMT_USE_DOUBLE 1 +#endif +#ifndef FMT_USE_LONG_DOUBLE +# define FMT_USE_LONG_DOUBLE 1 +#endif + +#ifndef FMT_INLINE +# if FMT_GCC_VERSION || FMT_CLANG_VERSION +# define FMT_INLINE inline __attribute__((always_inline)) +# else +# define FMT_INLINE inline +# endif +#endif + +#ifndef FMT_DEPRECATED +# if FMT_HAS_CPP14_ATTRIBUTE(deprecated) || FMT_MSC_VER >= 1900 +# define FMT_DEPRECATED [[deprecated]] +# else +# if (defined(__GNUC__) && !defined(__LCC__)) || defined(__clang__) +# define FMT_DEPRECATED __attribute__((deprecated)) +# elif FMT_MSC_VER +# define FMT_DEPRECATED __declspec(deprecated) +# else +# define FMT_DEPRECATED /* deprecated */ +# endif +# endif +#endif + +#ifndef FMT_BEGIN_NAMESPACE +# define FMT_BEGIN_NAMESPACE \ + namespace fmt { \ + inline namespace v8 { +# define FMT_END_NAMESPACE \ + } \ + } +#endif + +#ifndef FMT_MODULE_EXPORT +# define FMT_MODULE_EXPORT +# define FMT_MODULE_EXPORT_BEGIN +# define FMT_MODULE_EXPORT_END +# define FMT_BEGIN_DETAIL_NAMESPACE namespace detail { +# define FMT_END_DETAIL_NAMESPACE } +#endif + +#if !defined(FMT_HEADER_ONLY) && defined(_WIN32) +# define FMT_CLASS_API FMT_MSC_WARNING(suppress : 4275) +# ifdef FMT_EXPORT +# define FMT_API __declspec(dllexport) +# elif defined(FMT_SHARED) +# define FMT_API __declspec(dllimport) +# endif +#else +# define FMT_CLASS_API +# if defined(FMT_EXPORT) || defined(FMT_SHARED) +# if defined(__GNUC__) || defined(__clang__) +# define FMT_API __attribute__((visibility("default"))) +# endif +# endif +#endif +#ifndef FMT_API +# define FMT_API +#endif + +// libc++ supports string_view in pre-c++17. +#if (FMT_HAS_INCLUDE(<string_view>) && \ + (__cplusplus > 201402L || defined(_LIBCPP_VERSION))) || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910) +# include <string_view> +# define FMT_USE_STRING_VIEW +#elif FMT_HAS_INCLUDE("experimental/string_view") && __cplusplus >= 201402L +# include <experimental/string_view> +# define FMT_USE_EXPERIMENTAL_STRING_VIEW +#endif + +#ifndef FMT_UNICODE +# define FMT_UNICODE !FMT_MSC_VER +#endif + +#ifndef FMT_CONSTEVAL +# if ((FMT_GCC_VERSION >= 1000 || FMT_CLANG_VERSION >= 1101) && \ + __cplusplus > 201703L && !defined(__apple_build_version__)) || \ + (defined(__cpp_consteval) && \ + (!FMT_MSC_VER || _MSC_FULL_VER >= 193030704)) +// consteval is broken in MSVC before VS2022 and Apple clang 13. +# define FMT_CONSTEVAL consteval +# define FMT_HAS_CONSTEVAL +# else +# define FMT_CONSTEVAL +# endif +#endif + +#ifndef FMT_USE_NONTYPE_TEMPLATE_PARAMETERS +# if defined(__cpp_nontype_template_args) && \ + ((FMT_GCC_VERSION >= 903 && __cplusplus >= 201709L) || \ + __cpp_nontype_template_args >= 201911L) +# define FMT_USE_NONTYPE_TEMPLATE_PARAMETERS 1 +# else +# define FMT_USE_NONTYPE_TEMPLATE_PARAMETERS 0 +# endif +#endif + +// Enable minimal optimizations for more compact code in debug mode. +FMT_GCC_PRAGMA("GCC push_options") +#ifndef __OPTIMIZE__ +FMT_GCC_PRAGMA("GCC optimize(\"Og\")") +#endif + +FMT_BEGIN_NAMESPACE +FMT_MODULE_EXPORT_BEGIN + +// Implementations of enable_if_t and other metafunctions for older systems. +template <bool B, typename T = void> +using enable_if_t = typename std::enable_if<B, T>::type; +template <bool B, typename T, typename F> +using conditional_t = typename std::conditional<B, T, F>::type; +template <bool B> using bool_constant = std::integral_constant<bool, B>; +template <typename T> +using remove_reference_t = typename std::remove_reference<T>::type; +template <typename T> +using remove_const_t = typename std::remove_const<T>::type; +template <typename T> +using remove_cvref_t = typename std::remove_cv<remove_reference_t<T>>::type; +template <typename T> struct type_identity { using type = T; }; +template <typename T> using type_identity_t = typename type_identity<T>::type; + +struct monostate { + constexpr monostate() {} +}; + +// An enable_if helper to be used in template parameters which results in much +// shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed +// to workaround a bug in MSVC 2019 (see #1140 and #1186). +#ifdef FMT_DOC +# define FMT_ENABLE_IF(...) +#else +# define FMT_ENABLE_IF(...) enable_if_t<(__VA_ARGS__), int> = 0 +#endif + +FMT_BEGIN_DETAIL_NAMESPACE + +// Suppress "unused variable" warnings with the method described in +// https://herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings/. +// (void)var does not work on many Intel compilers. +template <typename... T> FMT_CONSTEXPR void ignore_unused(const T&...) {} + +constexpr FMT_INLINE auto is_constant_evaluated(bool default_value = false) + FMT_NOEXCEPT -> bool { +#ifdef __cpp_lib_is_constant_evaluated + ignore_unused(default_value); + return std::is_constant_evaluated(); +#else + return default_value; +#endif +} + +// A function to suppress "conditional expression is constant" warnings. +template <typename T> constexpr FMT_INLINE auto const_check(T value) -> T { + return value; +} + +FMT_NORETURN FMT_API void assert_fail(const char* file, int line, + const char* message); + +#ifndef FMT_ASSERT +# ifdef NDEBUG +// FMT_ASSERT is not empty to avoid -Werror=empty-body. +# define FMT_ASSERT(condition, message) \ + ::fmt::detail::ignore_unused((condition), (message)) +# else +# define FMT_ASSERT(condition, message) \ + ((condition) /* void() fails with -Winvalid-constexpr on clang 4.0.1 */ \ + ? (void)0 \ + : ::fmt::detail::assert_fail(__FILE__, __LINE__, (message))) +# endif +#endif + +#ifdef __cpp_lib_byte +using byte = std::byte; +#else +enum class byte : unsigned char {}; +#endif + +#if defined(FMT_USE_STRING_VIEW) +template <typename Char> using std_string_view = std::basic_string_view<Char>; +#elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW) +template <typename Char> +using std_string_view = std::experimental::basic_string_view<Char>; +#else +template <typename T> struct std_string_view {}; +#endif + +#ifdef FMT_USE_INT128 +// Do nothing. +#elif defined(__SIZEOF_INT128__) && !FMT_NVCC && \ + !(FMT_CLANG_VERSION && FMT_MSC_VER) +# define FMT_USE_INT128 1 +using int128_t = __int128_t; +using uint128_t = __uint128_t; +template <typename T> inline auto convert_for_visit(T value) -> T { + return value; +} +#else +# define FMT_USE_INT128 0 +#endif +#if !FMT_USE_INT128 +enum class int128_t {}; +enum class uint128_t {}; +// Reduce template instantiations. +template <typename T> inline auto convert_for_visit(T) -> monostate { + return {}; +} +#endif + +// Casts a nonnegative integer to unsigned. +template <typename Int> +FMT_CONSTEXPR auto to_unsigned(Int value) -> + typename std::make_unsigned<Int>::type { + FMT_ASSERT(value >= 0, "negative value"); + return static_cast<typename std::make_unsigned<Int>::type>(value); +} + +FMT_MSC_WARNING(suppress : 4566) constexpr unsigned char micro[] = "\u00B5"; + +constexpr auto is_utf8() -> bool { + // Avoid buggy sign extensions in MSVC's constant evaluation mode. + // https://developercommunity.visualstudio.com/t/C-difference-in-behavior-for-unsigned/1233612 + using uchar = unsigned char; + return FMT_UNICODE || (sizeof(micro) == 3 && uchar(micro[0]) == 0xC2 && + uchar(micro[1]) == 0xB5); +} +FMT_END_DETAIL_NAMESPACE + +/** + An implementation of ``std::basic_string_view`` for pre-C++17. It provides a + subset of the API. ``fmt::basic_string_view`` is used for format strings even + if ``std::string_view`` is available to prevent issues when a library is + compiled with a different ``-std`` option than the client code (which is not + recommended). + */ +template <typename Char> class basic_string_view { + private: + const Char* data_; + size_t size_; + + public: + using value_type = Char; + using iterator = const Char*; + + constexpr basic_string_view() FMT_NOEXCEPT : data_(nullptr), size_(0) {} + + /** Constructs a string reference object from a C string and a size. */ + constexpr basic_string_view(const Char* s, size_t count) FMT_NOEXCEPT + : data_(s), + size_(count) {} + + /** + \rst + Constructs a string reference object from a C string computing + the size with ``std::char_traits<Char>::length``. + \endrst + */ + FMT_CONSTEXPR_CHAR_TRAITS + FMT_INLINE + basic_string_view(const Char* s) + : data_(s), + size_(detail::const_check(std::is_same<Char, char>::value && + !detail::is_constant_evaluated(true)) + ? std::strlen(reinterpret_cast<const char*>(s)) + : std::char_traits<Char>::length(s)) {} + + /** Constructs a string reference from a ``std::basic_string`` object. */ + template <typename Traits, typename Alloc> + FMT_CONSTEXPR basic_string_view( + const std::basic_string<Char, Traits, Alloc>& s) FMT_NOEXCEPT + : data_(s.data()), + size_(s.size()) {} + + template <typename S, FMT_ENABLE_IF(std::is_same< + S, detail::std_string_view<Char>>::value)> + FMT_CONSTEXPR basic_string_view(S s) FMT_NOEXCEPT : data_(s.data()), + size_(s.size()) {} + + /** Returns a pointer to the string data. */ + constexpr auto data() const FMT_NOEXCEPT -> const Char* { return data_; } + + /** Returns the string size. */ + constexpr auto size() const FMT_NOEXCEPT -> size_t { return size_; } + + constexpr auto begin() const FMT_NOEXCEPT -> iterator { return data_; } + constexpr auto end() const FMT_NOEXCEPT -> iterator { return data_ + size_; } + + constexpr auto operator[](size_t pos) const FMT_NOEXCEPT -> const Char& { + return data_[pos]; + } + + FMT_CONSTEXPR void remove_prefix(size_t n) FMT_NOEXCEPT { + data_ += n; + size_ -= n; + } + + // Lexicographically compare this string reference to other. + FMT_CONSTEXPR_CHAR_TRAITS auto compare(basic_string_view other) const -> int { + size_t str_size = size_ < other.size_ ? size_ : other.size_; + int result = std::char_traits<Char>::compare(data_, other.data_, str_size); + if (result == 0) + result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1); + return result; + } + + FMT_CONSTEXPR_CHAR_TRAITS friend auto operator==(basic_string_view lhs, + basic_string_view rhs) + -> bool { + return lhs.compare(rhs) == 0; + } + friend auto operator!=(basic_string_view lhs, basic_string_view rhs) -> bool { + return lhs.compare(rhs) != 0; + } + friend auto operator<(basic_string_view lhs, basic_string_view rhs) -> bool { + return lhs.compare(rhs) < 0; + } + friend auto operator<=(basic_string_view lhs, basic_string_view rhs) -> bool { + return lhs.compare(rhs) <= 0; + } + friend auto operator>(basic_string_view lhs, basic_string_view rhs) -> bool { + return lhs.compare(rhs) > 0; + } + friend auto operator>=(basic_string_view lhs, basic_string_view rhs) -> bool { + return lhs.compare(rhs) >= 0; + } +}; + +using string_view = basic_string_view<char>; + +/** Specifies if ``T`` is a character type. Can be specialized by users. */ +template <typename T> struct is_char : std::false_type {}; +template <> struct is_char<char> : std::true_type {}; + +// Returns a string view of `s`. +template <typename Char, FMT_ENABLE_IF(is_char<Char>::value)> +FMT_INLINE auto to_string_view(const Char* s) -> basic_string_view<Char> { + return s; +} +template <typename Char, typename Traits, typename Alloc> +inline auto to_string_view(const std::basic_string<Char, Traits, Alloc>& s) + -> basic_string_view<Char> { + return s; +} +template <typename Char> +constexpr auto to_string_view(basic_string_view<Char> s) + -> basic_string_view<Char> { + return s; +} +template <typename Char, + FMT_ENABLE_IF(!std::is_empty<detail::std_string_view<Char>>::value)> +inline auto to_string_view(detail::std_string_view<Char> s) + -> basic_string_view<Char> { + return s; +} + +// A base class for compile-time strings. It is defined in the fmt namespace to +// make formatting functions visible via ADL, e.g. format(FMT_STRING("{}"), 42). +struct compile_string {}; + +template <typename S> +struct is_compile_string : std::is_base_of<compile_string, S> {}; + +template <typename S, FMT_ENABLE_IF(is_compile_string<S>::value)> +constexpr auto to_string_view(const S& s) + -> basic_string_view<typename S::char_type> { + return basic_string_view<typename S::char_type>(s); +} + +FMT_BEGIN_DETAIL_NAMESPACE + +void to_string_view(...); +using fmt::to_string_view; + +// Specifies whether S is a string type convertible to fmt::basic_string_view. +// It should be a constexpr function but MSVC 2017 fails to compile it in +// enable_if and MSVC 2015 fails to compile it as an alias template. +template <typename S> +struct is_string : std::is_class<decltype(to_string_view(std::declval<S>()))> { +}; + +template <typename S, typename = void> struct char_t_impl {}; +template <typename S> struct char_t_impl<S, enable_if_t<is_string<S>::value>> { + using result = decltype(to_string_view(std::declval<S>())); + using type = typename result::value_type; +}; + +// Reports a compile-time error if S is not a valid format string. +template <typename..., typename S, FMT_ENABLE_IF(!is_compile_string<S>::value)> +FMT_INLINE void check_format_string(const S&) { +#ifdef FMT_ENFORCE_COMPILE_STRING + static_assert(is_compile_string<S>::value, + "FMT_ENFORCE_COMPILE_STRING requires all format strings to use " + "FMT_STRING."); +#endif +} +template <typename..., typename S, FMT_ENABLE_IF(is_compile_string<S>::value)> +void check_format_string(S); + +FMT_NORETURN FMT_API void throw_format_error(const char* message); + +struct error_handler { + constexpr error_handler() = default; + constexpr error_handler(const error_handler&) = default; + + // This function is intentionally not constexpr to give a compile-time error. + FMT_NORETURN FMT_API void on_error(const char* message); +}; +FMT_END_DETAIL_NAMESPACE + +/** String's character type. */ +template <typename S> using char_t = typename detail::char_t_impl<S>::type; + +/** + \rst + Parsing context consisting of a format string range being parsed and an + argument counter for automatic indexing. + You can use the ``format_parse_context`` type alias for ``char`` instead. + \endrst + */ +template <typename Char, typename ErrorHandler = detail::error_handler> +class basic_format_parse_context : private ErrorHandler { + private: + basic_string_view<Char> format_str_; + int next_arg_id_; + + public: + using char_type = Char; + using iterator = typename basic_string_view<Char>::iterator; + + explicit constexpr basic_format_parse_context( + basic_string_view<Char> format_str, ErrorHandler eh = {}, + int next_arg_id = 0) + : ErrorHandler(eh), format_str_(format_str), next_arg_id_(next_arg_id) {} + + /** + Returns an iterator to the beginning of the format string range being + parsed. + */ + constexpr auto begin() const FMT_NOEXCEPT -> iterator { + return format_str_.begin(); + } + + /** + Returns an iterator past the end of the format string range being parsed. + */ + constexpr auto end() const FMT_NOEXCEPT -> iterator { + return format_str_.end(); + } + + /** Advances the begin iterator to ``it``. */ + FMT_CONSTEXPR void advance_to(iterator it) { + format_str_.remove_prefix(detail::to_unsigned(it - begin())); + } + + /** + Reports an error if using the manual argument indexing; otherwise returns + the next argument index and switches to the automatic indexing. + */ + FMT_CONSTEXPR auto next_arg_id() -> int { + // Don't check if the argument id is valid to avoid overhead and because it + // will be checked during formatting anyway. + if (next_arg_id_ >= 0) return next_arg_id_++; + on_error("cannot switch from manual to automatic argument indexing"); + return 0; + } + + /** + Reports an error if using the automatic argument indexing; otherwise + switches to the manual indexing. + */ + FMT_CONSTEXPR void check_arg_id(int) { + if (next_arg_id_ > 0) + on_error("cannot switch from automatic to manual argument indexing"); + else + next_arg_id_ = -1; + } + + FMT_CONSTEXPR void check_arg_id(basic_string_view<Char>) {} + + FMT_CONSTEXPR void on_error(const char* message) { + ErrorHandler::on_error(message); + } + + constexpr auto error_handler() const -> ErrorHandler { return *this; } +}; + +using format_parse_context = basic_format_parse_context<char>; + +template <typename Context> class basic_format_arg; +template <typename Context> class basic_format_args; +template <typename Context> class dynamic_format_arg_store; + +// A formatter for objects of type T. +template <typename T, typename Char = char, typename Enable = void> +struct formatter { + // A deleted default constructor indicates a disabled formatter. + formatter() = delete; +}; + +// Specifies if T has an enabled formatter specialization. A type can be +// formattable even if it doesn't have a formatter e.g. via a conversion. +template <typename T, typename Context> +using has_formatter = + std::is_constructible<typename Context::template formatter_type<T>>; + +// Checks whether T is a container with contiguous storage. +template <typename T> struct is_contiguous : std::false_type {}; +template <typename Char> +struct is_contiguous<std::basic_string<Char>> : std::true_type {}; + +class appender; + +FMT_BEGIN_DETAIL_NAMESPACE + +template <typename Context, typename T> +constexpr auto has_const_formatter_impl(T*) + -> decltype(typename Context::template formatter_type<T>().format( + std::declval<const T&>(), std::declval<Context&>()), + true) { + return true; +} +template <typename Context> +constexpr auto has_const_formatter_impl(...) -> bool { + return false; +} +template <typename T, typename Context> +constexpr auto has_const_formatter() -> bool { + return has_const_formatter_impl<Context>(static_cast<T*>(nullptr)); +} + +// Extracts a reference to the container from back_insert_iterator. +template <typename Container> +inline auto get_container(std::back_insert_iterator<Container> it) + -> Container& { + using bi_iterator = std::back_insert_iterator<Container>; + struct accessor : bi_iterator { + accessor(bi_iterator iter) : bi_iterator(iter) {} + using bi_iterator::container; + }; + return *accessor(it).container; +} + +template <typename Char, typename InputIt, typename OutputIt> +FMT_CONSTEXPR auto copy_str(InputIt begin, InputIt end, OutputIt out) + -> OutputIt { + while (begin != end) *out++ = static_cast<Char>(*begin++); + return out; +} + +template <typename Char, typename T, typename U, + FMT_ENABLE_IF( + std::is_same<remove_const_t<T>, U>::value&& is_char<U>::value)> +FMT_CONSTEXPR auto copy_str(T* begin, T* end, U* out) -> U* { + if (is_constant_evaluated()) return copy_str<Char, T*, U*>(begin, end, out); + auto size = to_unsigned(end - begin); + memcpy(out, begin, size * sizeof(U)); + return out + size; +} + +/** + \rst + A contiguous memory buffer with an optional growing ability. It is an internal + class and shouldn't be used directly, only via `~fmt::basic_memory_buffer`. + \endrst + */ +template <typename T> class buffer { + private: + T* ptr_; + size_t size_; + size_t capacity_; + + protected: + // Don't initialize ptr_ since it is not accessed to save a few cycles. + FMT_MSC_WARNING(suppress : 26495) + buffer(size_t sz) FMT_NOEXCEPT : size_(sz), capacity_(sz) {} + + FMT_CONSTEXPR20 buffer(T* p = nullptr, size_t sz = 0, + size_t cap = 0) FMT_NOEXCEPT : ptr_(p), + size_(sz), + capacity_(cap) {} + + FMT_CONSTEXPR20 ~buffer() = default; + buffer(buffer&&) = default; + + /** Sets the buffer data and capacity. */ + FMT_CONSTEXPR void set(T* buf_data, size_t buf_capacity) FMT_NOEXCEPT { + ptr_ = buf_data; + capacity_ = buf_capacity; + } + + /** Increases the buffer capacity to hold at least *capacity* elements. */ + virtual FMT_CONSTEXPR20 void grow(size_t capacity) = 0; + + public: + using value_type = T; + using const_reference = const T&; + + buffer(const buffer&) = delete; + void operator=(const buffer&) = delete; + + auto begin() FMT_NOEXCEPT -> T* { return ptr_; } + auto end() FMT_NOEXCEPT -> T* { return ptr_ + size_; } + + auto begin() const FMT_NOEXCEPT -> const T* { return ptr_; } + auto end() const FMT_NOEXCEPT -> const T* { return ptr_ + size_; } + + /** Returns the size of this buffer. */ + constexpr auto size() const FMT_NOEXCEPT -> size_t { return size_; } + + /** Returns the capacity of this buffer. */ + constexpr auto capacity() const FMT_NOEXCEPT -> size_t { return capacity_; } + + /** Returns a pointer to the buffer data. */ + FMT_CONSTEXPR auto data() FMT_NOEXCEPT -> T* { return ptr_; } + + /** Returns a pointer to the buffer data. */ + FMT_CONSTEXPR auto data() const FMT_NOEXCEPT -> const T* { return ptr_; } + + /** Clears this buffer. */ + void clear() { size_ = 0; } + + // Tries resizing the buffer to contain *count* elements. If T is a POD type + // the new elements may not be initialized. + FMT_CONSTEXPR20 void try_resize(size_t count) { + try_reserve(count); + size_ = count <= capacity_ ? count : capacity_; + } + + // Tries increasing the buffer capacity to *new_capacity*. It can increase the + // capacity by a smaller amount than requested but guarantees there is space + // for at least one additional element either by increasing the capacity or by + // flushing the buffer if it is full. + FMT_CONSTEXPR20 void try_reserve(size_t new_capacity) { + if (new_capacity > capacity_) grow(new_capacity); + } + + FMT_CONSTEXPR20 void push_back(const T& value) { + try_reserve(size_ + 1); + ptr_[size_++] = value; + } + + /** Appends data to the end of the buffer. */ + template <typename U> void append(const U* begin, const U* end); + + template <typename I> FMT_CONSTEXPR auto operator[](I index) -> T& { + return ptr_[index]; + } + template <typename I> + FMT_CONSTEXPR auto operator[](I index) const -> const T& { + return ptr_[index]; + } +}; + +struct buffer_traits { + explicit buffer_traits(size_t) {} + auto count() const -> size_t { return 0; } + auto limit(size_t size) -> size_t { return size; } +}; + +class fixed_buffer_traits { + private: + size_t count_ = 0; + size_t limit_; + + public: + explicit fixed_buffer_traits(size_t limit) : limit_(limit) {} + auto count() const -> size_t { return count_; } + auto limit(size_t size) -> size_t { + size_t n = limit_ > count_ ? limit_ - count_ : 0; + count_ += size; + return size < n ? size : n; + } +}; + +// A buffer that writes to an output iterator when flushed. +template <typename OutputIt, typename T, typename Traits = buffer_traits> +class iterator_buffer final : public Traits, public buffer<T> { + private: + OutputIt out_; + enum { buffer_size = 256 }; + T data_[buffer_size]; + + protected: + FMT_CONSTEXPR20 void grow(size_t) override { + if (this->size() == buffer_size) flush(); + } + + void flush() { + auto size = this->size(); + this->clear(); + out_ = copy_str<T>(data_, data_ + this->limit(size), out_); + } + + public: + explicit iterator_buffer(OutputIt out, size_t n = buffer_size) + : Traits(n), buffer<T>(data_, 0, buffer_size), out_(out) {} + iterator_buffer(iterator_buffer&& other) + : Traits(other), buffer<T>(data_, 0, buffer_size), out_(other.out_) {} + ~iterator_buffer() { flush(); } + + auto out() -> OutputIt { + flush(); + return out_; + } + auto count() const -> size_t { return Traits::count() + this->size(); } +}; + +template <typename T> +class iterator_buffer<T*, T, fixed_buffer_traits> final + : public fixed_buffer_traits, + public buffer<T> { + private: + T* out_; + enum { buffer_size = 256 }; + T data_[buffer_size]; + + protected: + FMT_CONSTEXPR20 void grow(size_t) override { + if (this->size() == this->capacity()) flush(); + } + + void flush() { + size_t n = this->limit(this->size()); + if (this->data() == out_) { + out_ += n; + this->set(data_, buffer_size); + } + this->clear(); + } + + public: + explicit iterator_buffer(T* out, size_t n = buffer_size) + : fixed_buffer_traits(n), buffer<T>(out, 0, n), out_(out) {} + iterator_buffer(iterator_buffer&& other) + : fixed_buffer_traits(other), + buffer<T>(std::move(other)), + out_(other.out_) { + if (this->data() != out_) { + this->set(data_, buffer_size); + this->clear(); + } + } + ~iterator_buffer() { flush(); } + + auto out() -> T* { + flush(); + return out_; + } + auto count() const -> size_t { + return fixed_buffer_traits::count() + this->size(); + } +}; + +template <typename T> class iterator_buffer<T*, T> final : public buffer<T> { + protected: + FMT_CONSTEXPR20 void grow(size_t) override {} + + public: + explicit iterator_buffer(T* out, size_t = 0) : buffer<T>(out, 0, ~size_t()) {} + + auto out() -> T* { return &*this->end(); } +}; + +// A buffer that writes to a container with the contiguous storage. +template <typename Container> +class iterator_buffer<std::back_insert_iterator<Container>, + enable_if_t<is_contiguous<Container>::value, + typename Container::value_type>> + final : public buffer<typename Container::value_type> { + private: + Container& container_; + + protected: + FMT_CONSTEXPR20 void grow(size_t capacity) override { + container_.resize(capacity); + this->set(&container_[0], capacity); + } + + public: + explicit iterator_buffer(Container& c) + : buffer<typename Container::value_type>(c.size()), container_(c) {} + explicit iterator_buffer(std::back_insert_iterator<Container> out, size_t = 0) + : iterator_buffer(get_container(out)) {} + auto out() -> std::back_insert_iterator<Container> { + return std::back_inserter(container_); + } +}; + +// A buffer that counts the number of code units written discarding the output. +template <typename T = char> class counting_buffer final : public buffer<T> { + private: + enum { buffer_size = 256 }; + T data_[buffer_size]; + size_t count_ = 0; + + protected: + FMT_CONSTEXPR20 void grow(size_t) override { + if (this->size() != buffer_size) return; + count_ += this->size(); + this->clear(); + } + + public: + counting_buffer() : buffer<T>(data_, 0, buffer_size) {} + + auto count() -> size_t { return count_ + this->size(); } +}; + +template <typename T> +using buffer_appender = conditional_t<std::is_same<T, char>::value, appender, + std::back_insert_iterator<buffer<T>>>; + +// Maps an output iterator to a buffer. +template <typename T, typename OutputIt> +auto get_buffer(OutputIt out) -> iterator_buffer<OutputIt, T> { + return iterator_buffer<OutputIt, T>(out); +} + +template <typename Buffer> +auto get_iterator(Buffer& buf) -> decltype(buf.out()) { + return buf.out(); +} +template <typename T> auto get_iterator(buffer<T>& buf) -> buffer_appender<T> { + return buffer_appender<T>(buf); +} + +template <typename T, typename Char = char, typename Enable = void> +struct fallback_formatter { + fallback_formatter() = delete; +}; + +// Specifies if T has an enabled fallback_formatter specialization. +template <typename T, typename Char> +using has_fallback_formatter = + std::is_constructible<fallback_formatter<T, Char>>; + +struct view {}; + +template <typename Char, typename T> struct named_arg : view { + const Char* name; + const T& value; + named_arg(const Char* n, const T& v) : name(n), value(v) {} +}; + +template <typename Char> struct named_arg_info { + const Char* name; + int id; +}; + +template <typename T, typename Char, size_t NUM_ARGS, size_t NUM_NAMED_ARGS> +struct arg_data { + // args_[0].named_args points to named_args_ to avoid bloating format_args. + // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning. + T args_[1 + (NUM_ARGS != 0 ? NUM_ARGS : +1)]; + named_arg_info<Char> named_args_[NUM_NAMED_ARGS]; + + template <typename... U> + arg_data(const U&... init) : args_{T(named_args_, NUM_NAMED_ARGS), init...} {} + arg_data(const arg_data& other) = delete; + auto args() const -> const T* { return args_ + 1; } + auto named_args() -> named_arg_info<Char>* { return named_args_; } +}; + +template <typename T, typename Char, size_t NUM_ARGS> +struct arg_data<T, Char, NUM_ARGS, 0> { + // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning. + T args_[NUM_ARGS != 0 ? NUM_ARGS : +1]; + + template <typename... U> + FMT_CONSTEXPR FMT_INLINE arg_data(const U&... init) : args_{init...} {} + FMT_CONSTEXPR FMT_INLINE auto args() const -> const T* { return args_; } + FMT_CONSTEXPR FMT_INLINE auto named_args() -> std::nullptr_t { + return nullptr; + } +}; + +template <typename Char> +inline void init_named_args(named_arg_info<Char>*, int, int) {} + +template <typename T> struct is_named_arg : std::false_type {}; +template <typename T> struct is_statically_named_arg : std::false_type {}; + +template <typename T, typename Char> +struct is_named_arg<named_arg<Char, T>> : std::true_type {}; + +template <typename Char, typename T, typename... Tail, + FMT_ENABLE_IF(!is_named_arg<T>::value)> +void init_named_args(named_arg_info<Char>* named_args, int arg_count, + int named_arg_count, const T&, const Tail&... args) { + init_named_args(named_args, arg_count + 1, named_arg_count, args...); +} + +template <typename Char, typename T, typename... Tail, + FMT_ENABLE_IF(is_named_arg<T>::value)> +void init_named_args(named_arg_info<Char>* named_args, int arg_count, + int named_arg_count, const T& arg, const Tail&... args) { + named_args[named_arg_count++] = {arg.name, arg_count}; + init_named_args(named_args, arg_count + 1, named_arg_count, args...); +} + +template <typename... Args> +FMT_CONSTEXPR FMT_INLINE void init_named_args(std::nullptr_t, int, int, + const Args&...) {} + +template <bool B = false> constexpr auto count() -> size_t { return B ? 1 : 0; } +template <bool B1, bool B2, bool... Tail> constexpr auto count() -> size_t { + return (B1 ? 1 : 0) + count<B2, Tail...>(); +} + +template <typename... Args> constexpr auto count_named_args() -> size_t { + return count<is_named_arg<Args>::value...>(); +} + +template <typename... Args> +constexpr auto count_statically_named_args() -> size_t { + return count<is_statically_named_arg<Args>::value...>(); +} + +enum class type { + none_type, + // Integer types should go first, + int_type, + uint_type, + long_long_type, + ulong_long_type, + int128_type, + uint128_type, + bool_type, + char_type, + last_integer_type = char_type, + // followed by floating-point types. + float_type, + double_type, + long_double_type, + last_numeric_type = long_double_type, + cstring_type, + string_type, + pointer_type, + custom_type +}; + +// Maps core type T to the corresponding type enum constant. +template <typename T, typename Char> +struct type_constant : std::integral_constant<type, type::custom_type> {}; + +#define FMT_TYPE_CONSTANT(Type, constant) \ + template <typename Char> \ + struct type_constant<Type, Char> \ + : std::integral_constant<type, type::constant> {} + +FMT_TYPE_CONSTANT(int, int_type); +FMT_TYPE_CONSTANT(unsigned, uint_type); +FMT_TYPE_CONSTANT(long long, long_long_type); +FMT_TYPE_CONSTANT(unsigned long long, ulong_long_type); +FMT_TYPE_CONSTANT(int128_t, int128_type); +FMT_TYPE_CONSTANT(uint128_t, uint128_type); +FMT_TYPE_CONSTANT(bool, bool_type); +FMT_TYPE_CONSTANT(Char, char_type); +FMT_TYPE_CONSTANT(float, float_type); +FMT_TYPE_CONSTANT(double, double_type); +FMT_TYPE_CONSTANT(long double, long_double_type); +FMT_TYPE_CONSTANT(const Char*, cstring_type); +FMT_TYPE_CONSTANT(basic_string_view<Char>, string_type); +FMT_TYPE_CONSTANT(const void*, pointer_type); + +constexpr bool is_integral_type(type t) { + return t > type::none_type && t <= type::last_integer_type; +} + +constexpr bool is_arithmetic_type(type t) { + return t > type::none_type && t <= type::last_numeric_type; +} + +struct unformattable {}; +struct unformattable_char : unformattable {}; +struct unformattable_const : unformattable {}; +struct unformattable_pointer : unformattable {}; + +template <typename Char> struct string_value { + const Char* data; + size_t size; +}; + +template <typename Char> struct named_arg_value { + const named_arg_info<Char>* data; + size_t size; +}; + +template <typename Context> struct custom_value { + using parse_context = typename Context::parse_context_type; + void* value; + void (*format)(void* arg, parse_context& parse_ctx, Context& ctx); +}; + +// A formatting argument value. +template <typename Context> class value { + public: + using char_type = typename Context::char_type; + + union { + monostate no_value; + int int_value; + unsigned uint_value; + long long long_long_value; + unsigned long long ulong_long_value; + int128_t int128_value; + uint128_t uint128_value; + bool bool_value; + char_type char_value; + float float_value; + double double_value; + long double long_double_value; + const void* pointer; + string_value<char_type> string; + custom_value<Context> custom; + named_arg_value<char_type> named_args; + }; + + constexpr FMT_INLINE value() : no_value() {} + constexpr FMT_INLINE value(int val) : int_value(val) {} + constexpr FMT_INLINE value(unsigned val) : uint_value(val) {} + constexpr FMT_INLINE value(long long val) : long_long_value(val) {} + constexpr FMT_INLINE value(unsigned long long val) : ulong_long_value(val) {} + FMT_INLINE value(int128_t val) : int128_value(val) {} + FMT_INLINE value(uint128_t val) : uint128_value(val) {} + constexpr FMT_INLINE value(float val) : float_value(val) {} + constexpr FMT_INLINE value(double val) : double_value(val) {} + FMT_INLINE value(long double val) : long_double_value(val) {} + constexpr FMT_INLINE value(bool val) : bool_value(val) {} + constexpr FMT_INLINE value(char_type val) : char_value(val) {} + FMT_CONSTEXPR FMT_INLINE value(const char_type* val) { + string.data = val; + if (is_constant_evaluated()) string.size = {}; + } + FMT_CONSTEXPR FMT_INLINE value(basic_string_view<char_type> val) { + string.data = val.data(); + string.size = val.size(); + } + FMT_INLINE value(const void* val) : pointer(val) {} + FMT_INLINE value(const named_arg_info<char_type>* args, size_t size) + : named_args{args, size} {} + + template <typename T> FMT_CONSTEXPR FMT_INLINE value(T& val) { + using value_type = remove_cvref_t<T>; + custom.value = const_cast<value_type*>(&val); + // Get the formatter type through the context to allow different contexts + // have different extension points, e.g. `formatter<T>` for `format` and + // `printf_formatter<T>` for `printf`. + custom.format = format_custom_arg< + value_type, + conditional_t<has_formatter<value_type, Context>::value, + typename Context::template formatter_type<value_type>, + fallback_formatter<value_type, char_type>>>; + } + value(unformattable); + value(unformattable_char); + value(unformattable_const); + value(unformattable_pointer); + + private: + // Formats an argument of a custom type, such as a user-defined class. + template <typename T, typename Formatter> + static void format_custom_arg(void* arg, + typename Context::parse_context_type& parse_ctx, + Context& ctx) { + auto f = Formatter(); + parse_ctx.advance_to(f.parse(parse_ctx)); + using qualified_type = + conditional_t<has_const_formatter<T, Context>(), const T, T>; + ctx.advance_to(f.format(*static_cast<qualified_type*>(arg), ctx)); + } +}; + +template <typename Context, typename T> +FMT_CONSTEXPR auto make_arg(const T& value) -> basic_format_arg<Context>; + +// To minimize the number of types we need to deal with, long is translated +// either to int or to long long depending on its size. +enum { long_short = sizeof(long) == sizeof(int) }; +using long_type = conditional_t<long_short, int, long long>; +using ulong_type = conditional_t<long_short, unsigned, unsigned long long>; + +// Maps formatting arguments to core types. +// arg_mapper reports errors by returning unformattable instead of using +// static_assert because it's used in the is_formattable trait. +template <typename Context> struct arg_mapper { + using char_type = typename Context::char_type; + + FMT_CONSTEXPR FMT_INLINE auto map(signed char val) -> int { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(unsigned char val) -> unsigned { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(short val) -> int { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(unsigned short val) -> unsigned { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(int val) -> int { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(unsigned val) -> unsigned { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(long val) -> long_type { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(unsigned long val) -> ulong_type { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(long long val) -> long long { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(unsigned long long val) + -> unsigned long long { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(int128_t val) -> int128_t { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(uint128_t val) -> uint128_t { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(bool val) -> bool { return val; } + + template <typename T, FMT_ENABLE_IF(std::is_same<T, char>::value || + std::is_same<T, char_type>::value)> + FMT_CONSTEXPR FMT_INLINE auto map(T val) -> char_type { + return val; + } + template <typename T, enable_if_t<(std::is_same<T, wchar_t>::value || +#ifdef __cpp_char8_t + std::is_same<T, char8_t>::value || +#endif + std::is_same<T, char16_t>::value || + std::is_same<T, char32_t>::value) && + !std::is_same<T, char_type>::value, + int> = 0> + FMT_CONSTEXPR FMT_INLINE auto map(T) -> unformattable_char { + return {}; + } + + FMT_CONSTEXPR FMT_INLINE auto map(float val) -> float { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(double val) -> double { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(long double val) -> long double { + return val; + } + + FMT_CONSTEXPR FMT_INLINE auto map(char_type* val) -> const char_type* { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(const char_type* val) -> const char_type* { + return val; + } + template <typename T, + FMT_ENABLE_IF(is_string<T>::value && !std::is_pointer<T>::value && + std::is_same<char_type, char_t<T>>::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T& val) + -> basic_string_view<char_type> { + return to_string_view(val); + } + template <typename T, + FMT_ENABLE_IF(is_string<T>::value && !std::is_pointer<T>::value && + !std::is_same<char_type, char_t<T>>::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T&) -> unformattable_char { + return {}; + } + template <typename T, + FMT_ENABLE_IF( + std::is_constructible<basic_string_view<char_type>, T>::value && + !is_string<T>::value && !has_formatter<T, Context>::value && + !has_fallback_formatter<T, char_type>::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T& val) + -> basic_string_view<char_type> { + return basic_string_view<char_type>(val); + } + template < + typename T, + FMT_ENABLE_IF( + std::is_constructible<std_string_view<char_type>, T>::value && + !std::is_constructible<basic_string_view<char_type>, T>::value && + !is_string<T>::value && !has_formatter<T, Context>::value && + !has_fallback_formatter<T, char_type>::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T& val) + -> basic_string_view<char_type> { + return std_string_view<char_type>(val); + } + + using cstring_result = conditional_t<std::is_same<char_type, char>::value, + const char*, unformattable_pointer>; + + FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(const signed char* val) + -> cstring_result { + return map(reinterpret_cast<const char*>(val)); + } + FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(const unsigned char* val) + -> cstring_result { + return map(reinterpret_cast<const char*>(val)); + } + FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(signed char* val) + -> cstring_result { + return map(reinterpret_cast<const char*>(val)); + } + FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(unsigned char* val) + -> cstring_result { + return map(reinterpret_cast<const char*>(val)); + } + + FMT_CONSTEXPR FMT_INLINE auto map(void* val) -> const void* { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(const void* val) -> const void* { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(std::nullptr_t val) -> const void* { + return val; + } + + // We use SFINAE instead of a const T* parameter to avoid conflicting with + // the C array overload. + template < + typename T, + FMT_ENABLE_IF( + std::is_member_pointer<T>::value || + std::is_function<typename std::remove_pointer<T>::type>::value || + (std::is_convertible<const T&, const void*>::value && + !std::is_convertible<const T&, const char_type*>::value))> + FMT_CONSTEXPR auto map(const T&) -> unformattable_pointer { + return {}; + } + + template <typename T, std::size_t N, + FMT_ENABLE_IF(!std::is_same<T, wchar_t>::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T (&values)[N]) -> const T (&)[N] { + return values; + } + + template <typename T, + FMT_ENABLE_IF( + std::is_enum<T>::value&& std::is_convertible<T, int>::value && + !has_formatter<T, Context>::value && + !has_fallback_formatter<T, char_type>::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T& val) + -> decltype(std::declval<arg_mapper>().map( + static_cast<typename std::underlying_type<T>::type>(val))) { + return map(static_cast<typename std::underlying_type<T>::type>(val)); + } + + FMT_CONSTEXPR FMT_INLINE auto map(detail::byte val) -> unsigned { + return map(static_cast<unsigned char>(val)); + } + + template <typename T, typename U = remove_cvref_t<T>> + struct formattable + : bool_constant<has_const_formatter<U, Context>() || + !std::is_const<remove_reference_t<T>>::value || + has_fallback_formatter<U, char_type>::value> {}; + +#if FMT_MSC_VER != 0 && FMT_MSC_VER < 1910 + // Workaround a bug in MSVC. + template <typename T> FMT_CONSTEXPR FMT_INLINE auto do_map(T&& val) -> T& { + return val; + } +#else + template <typename T, FMT_ENABLE_IF(formattable<T>::value)> + FMT_CONSTEXPR FMT_INLINE auto do_map(T&& val) -> T& { + return val; + } + template <typename T, FMT_ENABLE_IF(!formattable<T>::value)> + FMT_CONSTEXPR FMT_INLINE auto do_map(T&&) -> unformattable_const { + return {}; + } +#endif + + template <typename T, typename U = remove_cvref_t<T>, + FMT_ENABLE_IF(!is_string<U>::value && !is_char<U>::value && + !std::is_array<U>::value && + (has_formatter<U, Context>::value || + has_fallback_formatter<U, char_type>::value))> + FMT_CONSTEXPR FMT_INLINE auto map(T&& val) + -> decltype(this->do_map(std::forward<T>(val))) { + return do_map(std::forward<T>(val)); + } + + template <typename T, FMT_ENABLE_IF(is_named_arg<T>::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T& named_arg) + -> decltype(std::declval<arg_mapper>().map(named_arg.value)) { + return map(named_arg.value); + } + + auto map(...) -> unformattable { return {}; } +}; + +// A type constant after applying arg_mapper<Context>. +template <typename T, typename Context> +using mapped_type_constant = + type_constant<decltype(arg_mapper<Context>().map(std::declval<const T&>())), + typename Context::char_type>; + +enum { packed_arg_bits = 4 }; +// Maximum number of arguments with packed types. +enum { max_packed_args = 62 / packed_arg_bits }; +enum : unsigned long long { is_unpacked_bit = 1ULL << 63 }; +enum : unsigned long long { has_named_args_bit = 1ULL << 62 }; + +FMT_END_DETAIL_NAMESPACE + +// An output iterator that appends to a buffer. +// It is used to reduce symbol sizes for the common case. +class appender : public std::back_insert_iterator<detail::buffer<char>> { + using base = std::back_insert_iterator<detail::buffer<char>>; + + template <typename T> + friend auto get_buffer(appender out) -> detail::buffer<char>& { + return detail::get_container(out); + } + + public: + using std::back_insert_iterator<detail::buffer<char>>::back_insert_iterator; + appender(base it) FMT_NOEXCEPT : base(it) {} + using _Unchecked_type = appender; // Mark iterator as checked. + + auto operator++() FMT_NOEXCEPT -> appender& { return *this; } + + auto operator++(int) FMT_NOEXCEPT -> appender { return *this; } +}; + +// A formatting argument. It is a trivially copyable/constructible type to +// allow storage in basic_memory_buffer. +template <typename Context> class basic_format_arg { + private: + detail::value<Context> value_; + detail::type type_; + + template <typename ContextType, typename T> + friend FMT_CONSTEXPR auto detail::make_arg(const T& value) + -> basic_format_arg<ContextType>; + + template <typename Visitor, typename Ctx> + friend FMT_CONSTEXPR auto visit_format_arg(Visitor&& vis, + const basic_format_arg<Ctx>& arg) + -> decltype(vis(0)); + + friend class basic_format_args<Context>; + friend class dynamic_format_arg_store<Context>; + + using char_type = typename Context::char_type; + + template <typename T, typename Char, size_t NUM_ARGS, size_t NUM_NAMED_ARGS> + friend struct detail::arg_data; + + basic_format_arg(const detail::named_arg_info<char_type>* args, size_t size) + : value_(args, size) {} + + public: + class handle { + public: + explicit handle(detail::custom_value<Context> custom) : custom_(custom) {} + + void format(typename Context::parse_context_type& parse_ctx, + Context& ctx) const { + custom_.format(custom_.value, parse_ctx, ctx); + } + + private: + detail::custom_value<Context> custom_; + }; + + constexpr basic_format_arg() : type_(detail::type::none_type) {} + + constexpr explicit operator bool() const FMT_NOEXCEPT { + return type_ != detail::type::none_type; + } + + auto type() const -> detail::type { return type_; } + + auto is_integral() const -> bool { return detail::is_integral_type(type_); } + auto is_arithmetic() const -> bool { + return detail::is_arithmetic_type(type_); + } +}; + +/** + \rst + Visits an argument dispatching to the appropriate visit method based on + the argument type. For example, if the argument type is ``double`` then + ``vis(value)`` will be called with the value of type ``double``. + \endrst + */ +template <typename Visitor, typename Context> +FMT_CONSTEXPR FMT_INLINE auto visit_format_arg( + Visitor&& vis, const basic_format_arg<Context>& arg) -> decltype(vis(0)) { + switch (arg.type_) { + case detail::type::none_type: + break; + case detail::type::int_type: + return vis(arg.value_.int_value); + case detail::type::uint_type: + return vis(arg.value_.uint_value); + case detail::type::long_long_type: + return vis(arg.value_.long_long_value); + case detail::type::ulong_long_type: + return vis(arg.value_.ulong_long_value); + case detail::type::int128_type: + return vis(detail::convert_for_visit(arg.value_.int128_value)); + case detail::type::uint128_type: + return vis(detail::convert_for_visit(arg.value_.uint128_value)); + case detail::type::bool_type: + return vis(arg.value_.bool_value); + case detail::type::char_type: + return vis(arg.value_.char_value); + case detail::type::float_type: + return vis(arg.value_.float_value); + case detail::type::double_type: + return vis(arg.value_.double_value); + case detail::type::long_double_type: + return vis(arg.value_.long_double_value); + case detail::type::cstring_type: + return vis(arg.value_.string.data); + case detail::type::string_type: + using sv = basic_string_view<typename Context::char_type>; + return vis(sv(arg.value_.string.data, arg.value_.string.size)); + case detail::type::pointer_type: + return vis(arg.value_.pointer); + case detail::type::custom_type: + return vis(typename basic_format_arg<Context>::handle(arg.value_.custom)); + } + return vis(monostate()); +} + +FMT_BEGIN_DETAIL_NAMESPACE + +template <typename Char, typename InputIt> +auto copy_str(InputIt begin, InputIt end, appender out) -> appender { + get_container(out).append(begin, end); + return out; +} + +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 500 +// A workaround for gcc 4.8 to make void_t work in a SFINAE context. +template <typename... Ts> struct void_t_impl { using type = void; }; +template <typename... Ts> +using void_t = typename detail::void_t_impl<Ts...>::type; +#else +template <typename...> using void_t = void; +#endif + +template <typename It, typename T, typename Enable = void> +struct is_output_iterator : std::false_type {}; + +template <typename It, typename T> +struct is_output_iterator< + It, T, + void_t<typename std::iterator_traits<It>::iterator_category, + decltype(*std::declval<It>() = std::declval<T>())>> + : std::true_type {}; + +template <typename OutputIt> +struct is_back_insert_iterator : std::false_type {}; +template <typename Container> +struct is_back_insert_iterator<std::back_insert_iterator<Container>> + : std::true_type {}; + +template <typename OutputIt> +struct is_contiguous_back_insert_iterator : std::false_type {}; +template <typename Container> +struct is_contiguous_back_insert_iterator<std::back_insert_iterator<Container>> + : is_contiguous<Container> {}; +template <> +struct is_contiguous_back_insert_iterator<appender> : std::true_type {}; + +// A type-erased reference to an std::locale to avoid heavy <locale> include. +class locale_ref { + private: + const void* locale_; // A type-erased pointer to std::locale. + + public: + constexpr locale_ref() : locale_(nullptr) {} + template <typename Locale> explicit locale_ref(const Locale& loc); + + explicit operator bool() const FMT_NOEXCEPT { return locale_ != nullptr; } + + template <typename Locale> auto get() const -> Locale; +}; + +template <typename> constexpr auto encode_types() -> unsigned long long { + return 0; +} + +template <typename Context, typename Arg, typename... Args> +constexpr auto encode_types() -> unsigned long long { + return static_cast<unsigned>(mapped_type_constant<Arg, Context>::value) | + (encode_types<Context, Args...>() << packed_arg_bits); +} + +template <typename Context, typename T> +FMT_CONSTEXPR auto make_arg(const T& value) -> basic_format_arg<Context> { + basic_format_arg<Context> arg; + arg.type_ = mapped_type_constant<T, Context>::value; + arg.value_ = arg_mapper<Context>().map(value); + return arg; +} + +// The type template parameter is there to avoid an ODR violation when using +// a fallback formatter in one translation unit and an implicit conversion in +// another (not recommended). +template <bool IS_PACKED, typename Context, type, typename T, + FMT_ENABLE_IF(IS_PACKED)> +FMT_CONSTEXPR FMT_INLINE auto make_arg(T&& val) -> value<Context> { + const auto& arg = arg_mapper<Context>().map(std::forward<T>(val)); + + constexpr bool formattable_char = + !std::is_same<decltype(arg), const unformattable_char&>::value; + static_assert(formattable_char, "Mixing character types is disallowed."); + + constexpr bool formattable_const = + !std::is_same<decltype(arg), const unformattable_const&>::value; + static_assert(formattable_const, "Cannot format a const argument."); + + // Formatting of arbitrary pointers is disallowed. If you want to output + // a pointer cast it to "void *" or "const void *". In particular, this + // forbids formatting of "[const] volatile char *" which is printed as bool + // by iostreams. + constexpr bool formattable_pointer = + !std::is_same<decltype(arg), const unformattable_pointer&>::value; + static_assert(formattable_pointer, + "Formatting of non-void pointers is disallowed."); + + constexpr bool formattable = + !std::is_same<decltype(arg), const unformattable&>::value; + static_assert( + formattable, + "Cannot format an argument. To make type T formattable provide a " + "formatter<T> specialization: https://fmt.dev/latest/api.html#udt"); + return {arg}; +} + +template <bool IS_PACKED, typename Context, type, typename T, + FMT_ENABLE_IF(!IS_PACKED)> +inline auto make_arg(const T& value) -> basic_format_arg<Context> { + return make_arg<Context>(value); +} +FMT_END_DETAIL_NAMESPACE + +// Formatting context. +template <typename OutputIt, typename Char> class basic_format_context { + public: + /** The character type for the output. */ + using char_type = Char; + + private: + OutputIt out_; + basic_format_args<basic_format_context> args_; + detail::locale_ref loc_; + + public: + using iterator = OutputIt; + using format_arg = basic_format_arg<basic_format_context>; + using parse_context_type = basic_format_parse_context<Char>; + template <typename T> using formatter_type = formatter<T, char_type>; + + basic_format_context(basic_format_context&&) = default; + basic_format_context(const basic_format_context&) = delete; + void operator=(const basic_format_context&) = delete; + /** + Constructs a ``basic_format_context`` object. References to the arguments are + stored in the object so make sure they have appropriate lifetimes. + */ + constexpr basic_format_context( + OutputIt out, basic_format_args<basic_format_context> ctx_args, + detail::locale_ref loc = detail::locale_ref()) + : out_(out), args_(ctx_args), loc_(loc) {} + + constexpr auto arg(int id) const -> format_arg { return args_.get(id); } + FMT_CONSTEXPR auto arg(basic_string_view<char_type> name) -> format_arg { + return args_.get(name); + } + FMT_CONSTEXPR auto arg_id(basic_string_view<char_type> name) -> int { + return args_.get_id(name); + } + auto args() const -> const basic_format_args<basic_format_context>& { + return args_; + } + + FMT_CONSTEXPR auto error_handler() -> detail::error_handler { return {}; } + void on_error(const char* message) { error_handler().on_error(message); } + + // Returns an iterator to the beginning of the output range. + FMT_CONSTEXPR auto out() -> iterator { return out_; } + + // Advances the begin iterator to ``it``. + void advance_to(iterator it) { + if (!detail::is_back_insert_iterator<iterator>()) out_ = it; + } + + FMT_CONSTEXPR auto locale() -> detail::locale_ref { return loc_; } +}; + +template <typename Char> +using buffer_context = + basic_format_context<detail::buffer_appender<Char>, Char>; +using format_context = buffer_context<char>; + +// Workaround an alias issue: https://stackoverflow.com/q/62767544/471164. +#define FMT_BUFFER_CONTEXT(Char) \ + basic_format_context<detail::buffer_appender<Char>, Char> + +template <typename T, typename Char = char> +using is_formattable = bool_constant< + !std::is_base_of<detail::unformattable, + decltype(detail::arg_mapper<buffer_context<Char>>().map( + std::declval<T>()))>::value && + !detail::has_fallback_formatter<T, Char>::value>; + +/** + \rst + An array of references to arguments. It can be implicitly converted into + `~fmt::basic_format_args` for passing into type-erased formatting functions + such as `~fmt::vformat`. + \endrst + */ +template <typename Context, typename... Args> +class format_arg_store +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 + // Workaround a GCC template argument substitution bug. + : public basic_format_args<Context> +#endif +{ + private: + static const size_t num_args = sizeof...(Args); + static const size_t num_named_args = detail::count_named_args<Args...>(); + static const bool is_packed = num_args <= detail::max_packed_args; + + using value_type = conditional_t<is_packed, detail::value<Context>, + basic_format_arg<Context>>; + + detail::arg_data<value_type, typename Context::char_type, num_args, + num_named_args> + data_; + + friend class basic_format_args<Context>; + + static constexpr unsigned long long desc = + (is_packed ? detail::encode_types<Context, Args...>() + : detail::is_unpacked_bit | num_args) | + (num_named_args != 0 + ? static_cast<unsigned long long>(detail::has_named_args_bit) + : 0); + + public: + template <typename... T> + FMT_CONSTEXPR FMT_INLINE format_arg_store(T&&... args) + : +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 + basic_format_args<Context>(*this), +#endif + data_{detail::make_arg< + is_packed, Context, + detail::mapped_type_constant<remove_cvref_t<T>, Context>::value>( + std::forward<T>(args))...} { + detail::init_named_args(data_.named_args(), 0, 0, args...); + } +}; + +/** + \rst + Constructs a `~fmt::format_arg_store` object that contains references to + arguments and can be implicitly converted to `~fmt::format_args`. `Context` + can be omitted in which case it defaults to `~fmt::context`. + See `~fmt::arg` for lifetime considerations. + \endrst + */ +template <typename Context = format_context, typename... Args> +constexpr auto make_format_args(Args&&... args) + -> format_arg_store<Context, remove_cvref_t<Args>...> { + return {std::forward<Args>(args)...}; +} + +/** + \rst + Returns a named argument to be used in a formatting function. + It should only be used in a call to a formatting function or + `dynamic_format_arg_store::push_back`. + + **Example**:: + + fmt::print("Elapsed time: {s:.2f} seconds", fmt::arg("s", 1.23)); + \endrst + */ +template <typename Char, typename T> +inline auto arg(const Char* name, const T& arg) -> detail::named_arg<Char, T> { + static_assert(!detail::is_named_arg<T>(), "nested named arguments"); + return {name, arg}; +} + +/** + \rst + A view of a collection of formatting arguments. To avoid lifetime issues it + should only be used as a parameter type in type-erased functions such as + ``vformat``:: + + void vlog(string_view format_str, format_args args); // OK + format_args args = make_format_args(42); // Error: dangling reference + \endrst + */ +template <typename Context> class basic_format_args { + public: + using size_type = int; + using format_arg = basic_format_arg<Context>; + + private: + // A descriptor that contains information about formatting arguments. + // If the number of arguments is less or equal to max_packed_args then + // argument types are passed in the descriptor. This reduces binary code size + // per formatting function call. + unsigned long long desc_; + union { + // If is_packed() returns true then argument values are stored in values_; + // otherwise they are stored in args_. This is done to improve cache + // locality and reduce compiled code size since storing larger objects + // may require more code (at least on x86-64) even if the same amount of + // data is actually copied to stack. It saves ~10% on the bloat test. + const detail::value<Context>* values_; + const format_arg* args_; + }; + + constexpr auto is_packed() const -> bool { + return (desc_ & detail::is_unpacked_bit) == 0; + } + auto has_named_args() const -> bool { + return (desc_ & detail::has_named_args_bit) != 0; + } + + FMT_CONSTEXPR auto type(int index) const -> detail::type { + int shift = index * detail::packed_arg_bits; + unsigned int mask = (1 << detail::packed_arg_bits) - 1; + return static_cast<detail::type>((desc_ >> shift) & mask); + } + + constexpr FMT_INLINE basic_format_args(unsigned long long desc, + const detail::value<Context>* values) + : desc_(desc), values_(values) {} + constexpr basic_format_args(unsigned long long desc, const format_arg* args) + : desc_(desc), args_(args) {} + + public: + constexpr basic_format_args() : desc_(0), args_(nullptr) {} + + /** + \rst + Constructs a `basic_format_args` object from `~fmt::format_arg_store`. + \endrst + */ + template <typename... Args> + constexpr FMT_INLINE basic_format_args( + const format_arg_store<Context, Args...>& store) + : basic_format_args(format_arg_store<Context, Args...>::desc, + store.data_.args()) {} + + /** + \rst + Constructs a `basic_format_args` object from + `~fmt::dynamic_format_arg_store`. + \endrst + */ + constexpr FMT_INLINE basic_format_args( + const dynamic_format_arg_store<Context>& store) + : basic_format_args(store.get_types(), store.data()) {} + + /** + \rst + Constructs a `basic_format_args` object from a dynamic set of arguments. + \endrst + */ + constexpr basic_format_args(const format_arg* args, int count) + : basic_format_args(detail::is_unpacked_bit | detail::to_unsigned(count), + args) {} + + /** Returns the argument with the specified id. */ + FMT_CONSTEXPR auto get(int id) const -> format_arg { + format_arg arg; + if (!is_packed()) { + if (id < max_size()) arg = args_[id]; + return arg; + } + if (id >= detail::max_packed_args) return arg; + arg.type_ = type(id); + if (arg.type_ == detail::type::none_type) return arg; + arg.value_ = values_[id]; + return arg; + } + + template <typename Char> + auto get(basic_string_view<Char> name) const -> format_arg { + int id = get_id(name); + return id >= 0 ? get(id) : format_arg(); + } + + template <typename Char> + auto get_id(basic_string_view<Char> name) const -> int { + if (!has_named_args()) return -1; + const auto& named_args = + (is_packed() ? values_[-1] : args_[-1].value_).named_args; + for (size_t i = 0; i < named_args.size; ++i) { + if (named_args.data[i].name == name) return named_args.data[i].id; + } + return -1; + } + + auto max_size() const -> int { + unsigned long long max_packed = detail::max_packed_args; + return static_cast<int>(is_packed() ? max_packed + : desc_ & ~detail::is_unpacked_bit); + } +}; + +/** An alias to ``basic_format_args<format_context>``. */ +// A separate type would result in shorter symbols but break ABI compatibility +// between clang and gcc on ARM (#1919). +using format_args = basic_format_args<format_context>; + +// We cannot use enum classes as bit fields because of a gcc bug +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414. +namespace align { +enum type { none, left, right, center, numeric }; +} +using align_t = align::type; +namespace sign { +enum type { none, minus, plus, space }; +} +using sign_t = sign::type; + +FMT_BEGIN_DETAIL_NAMESPACE + +// Workaround an array initialization issue in gcc 4.8. +template <typename Char> struct fill_t { + private: + enum { max_size = 4 }; + Char data_[max_size] = {Char(' '), Char(0), Char(0), Char(0)}; + unsigned char size_ = 1; + + public: + FMT_CONSTEXPR void operator=(basic_string_view<Char> s) { + auto size = s.size(); + if (size > max_size) return throw_format_error("invalid fill"); + for (size_t i = 0; i < size; ++i) data_[i] = s[i]; + size_ = static_cast<unsigned char>(size); + } + + constexpr auto size() const -> size_t { return size_; } + constexpr auto data() const -> const Char* { return data_; } + + FMT_CONSTEXPR auto operator[](size_t index) -> Char& { return data_[index]; } + FMT_CONSTEXPR auto operator[](size_t index) const -> const Char& { + return data_[index]; + } +}; +FMT_END_DETAIL_NAMESPACE + +enum class presentation_type : unsigned char { + none, + // Integer types should go first, + dec, // 'd' + oct, // 'o' + hex_lower, // 'x' + hex_upper, // 'X' + bin_lower, // 'b' + bin_upper, // 'B' + hexfloat_lower, // 'a' + hexfloat_upper, // 'A' + exp_lower, // 'e' + exp_upper, // 'E' + fixed_lower, // 'f' + fixed_upper, // 'F' + general_lower, // 'g' + general_upper, // 'G' + chr, // 'c' + string, // 's' + pointer // 'p' +}; + +// Format specifiers for built-in and string types. +template <typename Char> struct basic_format_specs { + int width; + int precision; + presentation_type type; + align_t align : 4; + sign_t sign : 3; + bool alt : 1; // Alternate form ('#'). + bool localized : 1; + detail::fill_t<Char> fill; + + constexpr basic_format_specs() + : width(0), + precision(-1), + type(presentation_type::none), + align(align::none), + sign(sign::none), + alt(false), + localized(false) {} +}; + +using format_specs = basic_format_specs<char>; + +FMT_BEGIN_DETAIL_NAMESPACE + +enum class arg_id_kind { none, index, name }; + +// An argument reference. +template <typename Char> struct arg_ref { + FMT_CONSTEXPR arg_ref() : kind(arg_id_kind::none), val() {} + + FMT_CONSTEXPR explicit arg_ref(int index) + : kind(arg_id_kind::index), val(index) {} + FMT_CONSTEXPR explicit arg_ref(basic_string_view<Char> name) + : kind(arg_id_kind::name), val(name) {} + + FMT_CONSTEXPR auto operator=(int idx) -> arg_ref& { + kind = arg_id_kind::index; + val.index = idx; + return *this; + } + + arg_id_kind kind; + union value { + FMT_CONSTEXPR value(int id = 0) : index{id} {} + FMT_CONSTEXPR value(basic_string_view<Char> n) : name(n) {} + + int index; + basic_string_view<Char> name; + } val; +}; + +// Format specifiers with width and precision resolved at formatting rather +// than parsing time to allow re-using the same parsed specifiers with +// different sets of arguments (precompilation of format strings). +template <typename Char> +struct dynamic_format_specs : basic_format_specs<Char> { + arg_ref<Char> width_ref; + arg_ref<Char> precision_ref; +}; + +struct auto_id {}; + +// A format specifier handler that sets fields in basic_format_specs. +template <typename Char> class specs_setter { + protected: + basic_format_specs<Char>& specs_; + + public: + explicit FMT_CONSTEXPR specs_setter(basic_format_specs<Char>& specs) + : specs_(specs) {} + + FMT_CONSTEXPR specs_setter(const specs_setter& other) + : specs_(other.specs_) {} + + FMT_CONSTEXPR void on_align(align_t align) { specs_.align = align; } + FMT_CONSTEXPR void on_fill(basic_string_view<Char> fill) { + specs_.fill = fill; + } + FMT_CONSTEXPR void on_sign(sign_t s) { specs_.sign = s; } + FMT_CONSTEXPR void on_hash() { specs_.alt = true; } + FMT_CONSTEXPR void on_localized() { specs_.localized = true; } + + FMT_CONSTEXPR void on_zero() { + if (specs_.align == align::none) specs_.align = align::numeric; + specs_.fill[0] = Char('0'); + } + + FMT_CONSTEXPR void on_width(int width) { specs_.width = width; } + FMT_CONSTEXPR void on_precision(int precision) { + specs_.precision = precision; + } + FMT_CONSTEXPR void end_precision() {} + + FMT_CONSTEXPR void on_type(presentation_type type) { specs_.type = type; } +}; + +// Format spec handler that saves references to arguments representing dynamic +// width and precision to be resolved at formatting time. +template <typename ParseContext> +class dynamic_specs_handler + : public specs_setter<typename ParseContext::char_type> { + public: + using char_type = typename ParseContext::char_type; + + FMT_CONSTEXPR dynamic_specs_handler(dynamic_format_specs<char_type>& specs, + ParseContext& ctx) + : specs_setter<char_type>(specs), specs_(specs), context_(ctx) {} + + FMT_CONSTEXPR dynamic_specs_handler(const dynamic_specs_handler& other) + : specs_setter<char_type>(other), + specs_(other.specs_), + context_(other.context_) {} + + template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) { + specs_.width_ref = make_arg_ref(arg_id); + } + + template <typename Id> FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) { + specs_.precision_ref = make_arg_ref(arg_id); + } + + FMT_CONSTEXPR void on_error(const char* message) { + context_.on_error(message); + } + + private: + dynamic_format_specs<char_type>& specs_; + ParseContext& context_; + + using arg_ref_type = arg_ref<char_type>; + + FMT_CONSTEXPR auto make_arg_ref(int arg_id) -> arg_ref_type { + context_.check_arg_id(arg_id); + return arg_ref_type(arg_id); + } + + FMT_CONSTEXPR auto make_arg_ref(auto_id) -> arg_ref_type { + return arg_ref_type(context_.next_arg_id()); + } + + FMT_CONSTEXPR auto make_arg_ref(basic_string_view<char_type> arg_id) + -> arg_ref_type { + context_.check_arg_id(arg_id); + basic_string_view<char_type> format_str( + context_.begin(), to_unsigned(context_.end() - context_.begin())); + return arg_ref_type(arg_id); + } +}; + +template <typename Char> constexpr bool is_ascii_letter(Char c) { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); +} + +// Converts a character to ASCII. Returns a number > 127 on conversion failure. +template <typename Char, FMT_ENABLE_IF(std::is_integral<Char>::value)> +constexpr auto to_ascii(Char value) -> Char { + return value; +} +template <typename Char, FMT_ENABLE_IF(std::is_enum<Char>::value)> +constexpr auto to_ascii(Char value) -> + typename std::underlying_type<Char>::type { + return value; +} + +template <typename Char> +FMT_CONSTEXPR auto code_point_length(const Char* begin) -> int { + if (const_check(sizeof(Char) != 1)) return 1; + auto lengths = + "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0\0\0\2\2\2\2\3\3\4"; + int len = lengths[static_cast<unsigned char>(*begin) >> 3]; + + // Compute the pointer to the next character early so that the next + // iteration can start working on the next character. Neither Clang + // nor GCC figure out this reordering on their own. + return len + !len; +} + +// Return the result via the out param to workaround gcc bug 77539. +template <bool IS_CONSTEXPR, typename T, typename Ptr = const T*> +FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr& out) -> bool { + for (out = first; out != last; ++out) { + if (*out == value) return true; + } + return false; +} + +template <> +inline auto find<false, char>(const char* first, const char* last, char value, + const char*& out) -> bool { + out = static_cast<const char*>( + std::memchr(first, value, to_unsigned(last - first))); + return out != nullptr; +} + +// Parses the range [begin, end) as an unsigned integer. This function assumes +// that the range is non-empty and the first character is a digit. +template <typename Char> +FMT_CONSTEXPR auto parse_nonnegative_int(const Char*& begin, const Char* end, + int error_value) noexcept -> int { + FMT_ASSERT(begin != end && '0' <= *begin && *begin <= '9', ""); + unsigned value = 0, prev = 0; + auto p = begin; + do { + prev = value; + value = value * 10 + unsigned(*p - '0'); + ++p; + } while (p != end && '0' <= *p && *p <= '9'); + auto num_digits = p - begin; + begin = p; + if (num_digits <= std::numeric_limits<int>::digits10) + return static_cast<int>(value); + // Check for overflow. + const unsigned max = to_unsigned((std::numeric_limits<int>::max)()); + return num_digits == std::numeric_limits<int>::digits10 + 1 && + prev * 10ull + unsigned(p[-1] - '0') <= max + ? static_cast<int>(value) + : error_value; +} + +// Parses fill and alignment. +template <typename Char, typename Handler> +FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end, + Handler&& handler) -> const Char* { + FMT_ASSERT(begin != end, ""); + auto align = align::none; + auto p = begin + code_point_length(begin); + if (p >= end) p = begin; + for (;;) { + switch (to_ascii(*p)) { + case '<': + align = align::left; + break; + case '>': + align = align::right; + break; + case '^': + align = align::center; + break; + default: + break; + } + if (align != align::none) { + if (p != begin) { + auto c = *begin; + if (c == '{') + return handler.on_error("invalid fill character '{'"), begin; + handler.on_fill(basic_string_view<Char>(begin, to_unsigned(p - begin))); + begin = p + 1; + } else + ++begin; + handler.on_align(align); + break; + } else if (p == begin) { + break; + } + p = begin; + } + return begin; +} + +template <typename Char> FMT_CONSTEXPR bool is_name_start(Char c) { + return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || '_' == c; +} + +template <typename Char, typename IDHandler> +FMT_CONSTEXPR auto do_parse_arg_id(const Char* begin, const Char* end, + IDHandler&& handler) -> const Char* { + FMT_ASSERT(begin != end, ""); + Char c = *begin; + if (c >= '0' && c <= '9') { + int index = 0; + if (c != '0') + index = + parse_nonnegative_int(begin, end, (std::numeric_limits<int>::max)()); + else + ++begin; + if (begin == end || (*begin != '}' && *begin != ':')) + handler.on_error("invalid format string"); + else + handler(index); + return begin; + } + if (!is_name_start(c)) { + handler.on_error("invalid format string"); + return begin; + } + auto it = begin; + do { + ++it; + } while (it != end && (is_name_start(c = *it) || ('0' <= c && c <= '9'))); + handler(basic_string_view<Char>(begin, to_unsigned(it - begin))); + return it; +} + +template <typename Char, typename IDHandler> +FMT_CONSTEXPR FMT_INLINE auto parse_arg_id(const Char* begin, const Char* end, + IDHandler&& handler) -> const Char* { + Char c = *begin; + if (c != '}' && c != ':') return do_parse_arg_id(begin, end, handler); + handler(); + return begin; +} + +template <typename Char, typename Handler> +FMT_CONSTEXPR auto parse_width(const Char* begin, const Char* end, + Handler&& handler) -> const Char* { + using detail::auto_id; + struct width_adapter { + Handler& handler; + + FMT_CONSTEXPR void operator()() { handler.on_dynamic_width(auto_id()); } + FMT_CONSTEXPR void operator()(int id) { handler.on_dynamic_width(id); } + FMT_CONSTEXPR void operator()(basic_string_view<Char> id) { + handler.on_dynamic_width(id); + } + FMT_CONSTEXPR void on_error(const char* message) { + if (message) handler.on_error(message); + } + }; + + FMT_ASSERT(begin != end, ""); + if ('0' <= *begin && *begin <= '9') { + int width = parse_nonnegative_int(begin, end, -1); + if (width != -1) + handler.on_width(width); + else + handler.on_error("number is too big"); + } else if (*begin == '{') { + ++begin; + if (begin != end) begin = parse_arg_id(begin, end, width_adapter{handler}); + if (begin == end || *begin != '}') + return handler.on_error("invalid format string"), begin; + ++begin; + } + return begin; +} + +template <typename Char, typename Handler> +FMT_CONSTEXPR auto parse_precision(const Char* begin, const Char* end, + Handler&& handler) -> const Char* { + using detail::auto_id; + struct precision_adapter { + Handler& handler; + + FMT_CONSTEXPR void operator()() { handler.on_dynamic_precision(auto_id()); } + FMT_CONSTEXPR void operator()(int id) { handler.on_dynamic_precision(id); } + FMT_CONSTEXPR void operator()(basic_string_view<Char> id) { + handler.on_dynamic_precision(id); + } + FMT_CONSTEXPR void on_error(const char* message) { + if (message) handler.on_error(message); + } + }; + + ++begin; + auto c = begin != end ? *begin : Char(); + if ('0' <= c && c <= '9') { + auto precision = parse_nonnegative_int(begin, end, -1); + if (precision != -1) + handler.on_precision(precision); + else + handler.on_error("number is too big"); + } else if (c == '{') { + ++begin; + if (begin != end) + begin = parse_arg_id(begin, end, precision_adapter{handler}); + if (begin == end || *begin++ != '}') + return handler.on_error("invalid format string"), begin; + } else { + return handler.on_error("missing precision specifier"), begin; + } + handler.end_precision(); + return begin; +} + +template <typename Char> +FMT_CONSTEXPR auto parse_presentation_type(Char type) -> presentation_type { + switch (to_ascii(type)) { + case 'd': + return presentation_type::dec; + case 'o': + return presentation_type::oct; + case 'x': + return presentation_type::hex_lower; + case 'X': + return presentation_type::hex_upper; + case 'b': + return presentation_type::bin_lower; + case 'B': + return presentation_type::bin_upper; + case 'a': + return presentation_type::hexfloat_lower; + case 'A': + return presentation_type::hexfloat_upper; + case 'e': + return presentation_type::exp_lower; + case 'E': + return presentation_type::exp_upper; + case 'f': + return presentation_type::fixed_lower; + case 'F': + return presentation_type::fixed_upper; + case 'g': + return presentation_type::general_lower; + case 'G': + return presentation_type::general_upper; + case 'c': + return presentation_type::chr; + case 's': + return presentation_type::string; + case 'p': + return presentation_type::pointer; + default: + return presentation_type::none; + } +} + +// Parses standard format specifiers and sends notifications about parsed +// components to handler. +template <typename Char, typename SpecHandler> +FMT_CONSTEXPR FMT_INLINE auto parse_format_specs(const Char* begin, + const Char* end, + SpecHandler&& handler) + -> const Char* { + if (1 < end - begin && begin[1] == '}' && is_ascii_letter(*begin) && + *begin != 'L') { + presentation_type type = parse_presentation_type(*begin++); + if (type == presentation_type::none) + handler.on_error("invalid type specifier"); + handler.on_type(type); + return begin; + } + + if (begin == end) return begin; + + begin = parse_align(begin, end, handler); + if (begin == end) return begin; + + // Parse sign. + switch (to_ascii(*begin)) { + case '+': + handler.on_sign(sign::plus); + ++begin; + break; + case '-': + handler.on_sign(sign::minus); + ++begin; + break; + case ' ': + handler.on_sign(sign::space); + ++begin; + break; + default: + break; + } + if (begin == end) return begin; + + if (*begin == '#') { + handler.on_hash(); + if (++begin == end) return begin; + } + + // Parse zero flag. + if (*begin == '0') { + handler.on_zero(); + if (++begin == end) return begin; + } + + begin = parse_width(begin, end, handler); + if (begin == end) return begin; + + // Parse precision. + if (*begin == '.') { + begin = parse_precision(begin, end, handler); + if (begin == end) return begin; + } + + if (*begin == 'L') { + handler.on_localized(); + ++begin; + } + + // Parse type. + if (begin != end && *begin != '}') { + presentation_type type = parse_presentation_type(*begin++); + if (type == presentation_type::none) + handler.on_error("invalid type specifier"); + handler.on_type(type); + } + return begin; +} + +template <typename Char, typename Handler> +FMT_CONSTEXPR auto parse_replacement_field(const Char* begin, const Char* end, + Handler&& handler) -> const Char* { + struct id_adapter { + Handler& handler; + int arg_id; + + FMT_CONSTEXPR void operator()() { arg_id = handler.on_arg_id(); } + FMT_CONSTEXPR void operator()(int id) { arg_id = handler.on_arg_id(id); } + FMT_CONSTEXPR void operator()(basic_string_view<Char> id) { + arg_id = handler.on_arg_id(id); + } + FMT_CONSTEXPR void on_error(const char* message) { + if (message) handler.on_error(message); + } + }; + + ++begin; + if (begin == end) return handler.on_error("invalid format string"), end; + if (*begin == '}') { + handler.on_replacement_field(handler.on_arg_id(), begin); + } else if (*begin == '{') { + handler.on_text(begin, begin + 1); + } else { + auto adapter = id_adapter{handler, 0}; + begin = parse_arg_id(begin, end, adapter); + Char c = begin != end ? *begin : Char(); + if (c == '}') { + handler.on_replacement_field(adapter.arg_id, begin); + } else if (c == ':') { + begin = handler.on_format_specs(adapter.arg_id, begin + 1, end); + if (begin == end || *begin != '}') + return handler.on_error("unknown format specifier"), end; + } else { + return handler.on_error("missing '}' in format string"), end; + } + } + return begin + 1; +} + +template <bool IS_CONSTEXPR, typename Char, typename Handler> +FMT_CONSTEXPR FMT_INLINE void parse_format_string( + basic_string_view<Char> format_str, Handler&& handler) { + // Workaround a name-lookup bug in MSVC's modules implementation. + using detail::find; + + auto begin = format_str.data(); + auto end = begin + format_str.size(); + if (end - begin < 32) { + // Use a simple loop instead of memchr for small strings. + const Char* p = begin; + while (p != end) { + auto c = *p++; + if (c == '{') { + handler.on_text(begin, p - 1); + begin = p = parse_replacement_field(p - 1, end, handler); + } else if (c == '}') { + if (p == end || *p != '}') + return handler.on_error("unmatched '}' in format string"); + handler.on_text(begin, p); + begin = ++p; + } + } + handler.on_text(begin, end); + return; + } + struct writer { + FMT_CONSTEXPR void operator()(const Char* pbegin, const Char* pend) { + if (pbegin == pend) return; + for (;;) { + const Char* p = nullptr; + if (!find<IS_CONSTEXPR>(pbegin, pend, Char('}'), p)) + return handler_.on_text(pbegin, pend); + ++p; + if (p == pend || *p != '}') + return handler_.on_error("unmatched '}' in format string"); + handler_.on_text(pbegin, p); + pbegin = p + 1; + } + } + Handler& handler_; + } write{handler}; + while (begin != end) { + // Doing two passes with memchr (one for '{' and another for '}') is up to + // 2.5x faster than the naive one-pass implementation on big format strings. + const Char* p = begin; + if (*begin != '{' && !find<IS_CONSTEXPR>(begin + 1, end, Char('{'), p)) + return write(begin, end); + write(begin, p); + begin = parse_replacement_field(p, end, handler); + } +} + +template <typename T, typename ParseContext> +FMT_CONSTEXPR auto parse_format_specs(ParseContext& ctx) + -> decltype(ctx.begin()) { + using char_type = typename ParseContext::char_type; + using context = buffer_context<char_type>; + using mapped_type = conditional_t< + mapped_type_constant<T, context>::value != type::custom_type, + decltype(arg_mapper<context>().map(std::declval<const T&>())), T>; + auto f = conditional_t<has_formatter<mapped_type, context>::value, + formatter<mapped_type, char_type>, + fallback_formatter<T, char_type>>(); + return f.parse(ctx); +} + +// A parse context with extra argument id checks. It is only used at compile +// time because adding checks at runtime would introduce substantial overhead +// and would be redundant since argument ids are checked when arguments are +// retrieved anyway. +template <typename Char, typename ErrorHandler = error_handler> +class compile_parse_context + : public basic_format_parse_context<Char, ErrorHandler> { + private: + int num_args_; + using base = basic_format_parse_context<Char, ErrorHandler>; + + public: + explicit FMT_CONSTEXPR compile_parse_context( + basic_string_view<Char> format_str, + int num_args = (std::numeric_limits<int>::max)(), ErrorHandler eh = {}) + : base(format_str, eh), num_args_(num_args) {} + + FMT_CONSTEXPR auto next_arg_id() -> int { + int id = base::next_arg_id(); + if (id >= num_args_) this->on_error("argument not found"); + return id; + } + + FMT_CONSTEXPR void check_arg_id(int id) { + base::check_arg_id(id); + if (id >= num_args_) this->on_error("argument not found"); + } + using base::check_arg_id; +}; + +template <typename ErrorHandler> +FMT_CONSTEXPR void check_int_type_spec(presentation_type type, + ErrorHandler&& eh) { + if (type > presentation_type::bin_upper && type != presentation_type::chr) + eh.on_error("invalid type specifier"); +} + +// Checks char specs and returns true if the type spec is char (and not int). +template <typename Char, typename ErrorHandler = error_handler> +FMT_CONSTEXPR auto check_char_specs(const basic_format_specs<Char>& specs, + ErrorHandler&& eh = {}) -> bool { + if (specs.type != presentation_type::none && + specs.type != presentation_type::chr) { + check_int_type_spec(specs.type, eh); + return false; + } + if (specs.align == align::numeric || specs.sign != sign::none || specs.alt) + eh.on_error("invalid format specifier for char"); + return true; +} + +// A floating-point presentation format. +enum class float_format : unsigned char { + general, // General: exponent notation or fixed point based on magnitude. + exp, // Exponent notation with the default precision of 6, e.g. 1.2e-3. + fixed, // Fixed point with the default precision of 6, e.g. 0.0012. + hex +}; + +struct float_specs { + int precision; + float_format format : 8; + sign_t sign : 8; + bool upper : 1; + bool locale : 1; + bool binary32 : 1; + bool fallback : 1; + bool showpoint : 1; +}; + +template <typename ErrorHandler = error_handler, typename Char> +FMT_CONSTEXPR auto parse_float_type_spec(const basic_format_specs<Char>& specs, + ErrorHandler&& eh = {}) + -> float_specs { + auto result = float_specs(); + result.showpoint = specs.alt; + result.locale = specs.localized; + switch (specs.type) { + case presentation_type::none: + result.format = float_format::general; + break; + case presentation_type::general_upper: + result.upper = true; + FMT_FALLTHROUGH; + case presentation_type::general_lower: + result.format = float_format::general; + break; + case presentation_type::exp_upper: + result.upper = true; + FMT_FALLTHROUGH; + case presentation_type::exp_lower: + result.format = float_format::exp; + result.showpoint |= specs.precision != 0; + break; + case presentation_type::fixed_upper: + result.upper = true; + FMT_FALLTHROUGH; + case presentation_type::fixed_lower: + result.format = float_format::fixed; + result.showpoint |= specs.precision != 0; + break; + case presentation_type::hexfloat_upper: + result.upper = true; + FMT_FALLTHROUGH; + case presentation_type::hexfloat_lower: + result.format = float_format::hex; + break; + default: + eh.on_error("invalid type specifier"); + break; + } + return result; +} + +template <typename ErrorHandler = error_handler> +FMT_CONSTEXPR auto check_cstring_type_spec(presentation_type type, + ErrorHandler&& eh = {}) -> bool { + if (type == presentation_type::none || type == presentation_type::string) + return true; + if (type != presentation_type::pointer) eh.on_error("invalid type specifier"); + return false; +} + +template <typename ErrorHandler = error_handler> +FMT_CONSTEXPR void check_string_type_spec(presentation_type type, + ErrorHandler&& eh = {}) { + if (type != presentation_type::none && type != presentation_type::string) + eh.on_error("invalid type specifier"); +} + +template <typename ErrorHandler> +FMT_CONSTEXPR void check_pointer_type_spec(presentation_type type, + ErrorHandler&& eh) { + if (type != presentation_type::none && type != presentation_type::pointer) + eh.on_error("invalid type specifier"); +} + +// A parse_format_specs handler that checks if specifiers are consistent with +// the argument type. +template <typename Handler> class specs_checker : public Handler { + private: + detail::type arg_type_; + + FMT_CONSTEXPR void require_numeric_argument() { + if (!is_arithmetic_type(arg_type_)) + this->on_error("format specifier requires numeric argument"); + } + + public: + FMT_CONSTEXPR specs_checker(const Handler& handler, detail::type arg_type) + : Handler(handler), arg_type_(arg_type) {} + + FMT_CONSTEXPR void on_align(align_t align) { + if (align == align::numeric) require_numeric_argument(); + Handler::on_align(align); + } + + FMT_CONSTEXPR void on_sign(sign_t s) { + require_numeric_argument(); + if (is_integral_type(arg_type_) && arg_type_ != type::int_type && + arg_type_ != type::long_long_type && arg_type_ != type::char_type) { + this->on_error("format specifier requires signed argument"); + } + Handler::on_sign(s); + } + + FMT_CONSTEXPR void on_hash() { + require_numeric_argument(); + Handler::on_hash(); + } + + FMT_CONSTEXPR void on_localized() { + require_numeric_argument(); + Handler::on_localized(); + } + + FMT_CONSTEXPR void on_zero() { + require_numeric_argument(); + Handler::on_zero(); + } + + FMT_CONSTEXPR void end_precision() { + if (is_integral_type(arg_type_) || arg_type_ == type::pointer_type) + this->on_error("precision not allowed for this argument type"); + } +}; + +constexpr int invalid_arg_index = -1; + +#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS +template <int N, typename T, typename... Args, typename Char> +constexpr auto get_arg_index_by_name(basic_string_view<Char> name) -> int { + if constexpr (detail::is_statically_named_arg<T>()) { + if (name == T::name) return N; + } + if constexpr (sizeof...(Args) > 0) + return get_arg_index_by_name<N + 1, Args...>(name); + (void)name; // Workaround an MSVC bug about "unused" parameter. + return invalid_arg_index; +} +#endif + +template <typename... Args, typename Char> +FMT_CONSTEXPR auto get_arg_index_by_name(basic_string_view<Char> name) -> int { +#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS + if constexpr (sizeof...(Args) > 0) + return get_arg_index_by_name<0, Args...>(name); +#endif + (void)name; + return invalid_arg_index; +} + +template <typename Char, typename ErrorHandler, typename... Args> +class format_string_checker { + private: + using parse_context_type = compile_parse_context<Char, ErrorHandler>; + enum { num_args = sizeof...(Args) }; + + // Format specifier parsing function. + using parse_func = const Char* (*)(parse_context_type&); + + parse_context_type context_; + parse_func parse_funcs_[num_args > 0 ? num_args : 1]; + + public: + explicit FMT_CONSTEXPR format_string_checker( + basic_string_view<Char> format_str, ErrorHandler eh) + : context_(format_str, num_args, eh), + parse_funcs_{&parse_format_specs<Args, parse_context_type>...} {} + + FMT_CONSTEXPR void on_text(const Char*, const Char*) {} + + FMT_CONSTEXPR auto on_arg_id() -> int { return context_.next_arg_id(); } + FMT_CONSTEXPR auto on_arg_id(int id) -> int { + return context_.check_arg_id(id), id; + } + FMT_CONSTEXPR auto on_arg_id(basic_string_view<Char> id) -> int { +#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS + auto index = get_arg_index_by_name<Args...>(id); + if (index == invalid_arg_index) on_error("named argument is not found"); + return context_.check_arg_id(index), index; +#else + (void)id; + on_error("compile-time checks for named arguments require C++20 support"); + return 0; +#endif + } + + FMT_CONSTEXPR void on_replacement_field(int, const Char*) {} + + FMT_CONSTEXPR auto on_format_specs(int id, const Char* begin, const Char*) + -> const Char* { + context_.advance_to(context_.begin() + (begin - &*context_.begin())); + // id >= 0 check is a workaround for gcc 10 bug (#2065). + return id >= 0 && id < num_args ? parse_funcs_[id](context_) : begin; + } + + FMT_CONSTEXPR void on_error(const char* message) { + context_.on_error(message); + } +}; + +template <typename... Args, typename S, + enable_if_t<(is_compile_string<S>::value), int>> +void check_format_string(S format_str) { + FMT_CONSTEXPR auto s = to_string_view(format_str); + using checker = format_string_checker<typename S::char_type, error_handler, + remove_cvref_t<Args>...>; + FMT_CONSTEXPR bool invalid_format = + (parse_format_string<true>(s, checker(s, {})), true); + ignore_unused(invalid_format); +} + +template <typename Char> +void vformat_to( + buffer<Char>& buf, basic_string_view<Char> fmt, + basic_format_args<FMT_BUFFER_CONTEXT(type_identity_t<Char>)> args, + locale_ref loc = {}); + +FMT_API void vprint_mojibake(std::FILE*, string_view, format_args); +#ifndef _WIN32 +inline void vprint_mojibake(std::FILE*, string_view, format_args) {} +#endif +FMT_END_DETAIL_NAMESPACE + +// A formatter specialization for the core types corresponding to detail::type +// constants. +template <typename T, typename Char> +struct formatter<T, Char, + enable_if_t<detail::type_constant<T, Char>::value != + detail::type::custom_type>> { + private: + detail::dynamic_format_specs<Char> specs_; + + public: + // Parses format specifiers stopping either at the end of the range or at the + // terminating '}'. + template <typename ParseContext> + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + auto begin = ctx.begin(), end = ctx.end(); + if (begin == end) return begin; + using handler_type = detail::dynamic_specs_handler<ParseContext>; + auto type = detail::type_constant<T, Char>::value; + auto checker = + detail::specs_checker<handler_type>(handler_type(specs_, ctx), type); + auto it = detail::parse_format_specs(begin, end, checker); + auto eh = ctx.error_handler(); + switch (type) { + case detail::type::none_type: + FMT_ASSERT(false, "invalid argument type"); + break; + case detail::type::bool_type: + if (specs_.type == presentation_type::none || + specs_.type == presentation_type::string) { + break; + } + FMT_FALLTHROUGH; + case detail::type::int_type: + case detail::type::uint_type: + case detail::type::long_long_type: + case detail::type::ulong_long_type: + case detail::type::int128_type: + case detail::type::uint128_type: + detail::check_int_type_spec(specs_.type, eh); + break; + case detail::type::char_type: + detail::check_char_specs(specs_, eh); + break; + case detail::type::float_type: + if (detail::const_check(FMT_USE_FLOAT)) + detail::parse_float_type_spec(specs_, eh); + else + FMT_ASSERT(false, "float support disabled"); + break; + case detail::type::double_type: + if (detail::const_check(FMT_USE_DOUBLE)) + detail::parse_float_type_spec(specs_, eh); + else + FMT_ASSERT(false, "double support disabled"); + break; + case detail::type::long_double_type: + if (detail::const_check(FMT_USE_LONG_DOUBLE)) + detail::parse_float_type_spec(specs_, eh); + else + FMT_ASSERT(false, "long double support disabled"); + break; + case detail::type::cstring_type: + detail::check_cstring_type_spec(specs_.type, eh); + break; + case detail::type::string_type: + detail::check_string_type_spec(specs_.type, eh); + break; + case detail::type::pointer_type: + detail::check_pointer_type_spec(specs_.type, eh); + break; + case detail::type::custom_type: + // Custom format specifiers are checked in parse functions of + // formatter specializations. + break; + } + return it; + } + + template <typename FormatContext> + FMT_CONSTEXPR auto format(const T& val, FormatContext& ctx) const + -> decltype(ctx.out()); +}; + +template <typename Char> struct basic_runtime { basic_string_view<Char> str; }; + +/** A compile-time format string. */ +template <typename Char, typename... Args> class basic_format_string { + private: + basic_string_view<Char> str_; + + public: + template <typename S, + FMT_ENABLE_IF( + std::is_convertible<const S&, basic_string_view<Char>>::value)> + FMT_CONSTEVAL FMT_INLINE basic_format_string(const S& s) : str_(s) { + static_assert( + detail::count< + (std::is_base_of<detail::view, remove_reference_t<Args>>::value && + std::is_reference<Args>::value)...>() == 0, + "passing views as lvalues is disallowed"); +#ifdef FMT_HAS_CONSTEVAL + if constexpr (detail::count_named_args<Args...>() == + detail::count_statically_named_args<Args...>()) { + using checker = detail::format_string_checker<Char, detail::error_handler, + remove_cvref_t<Args>...>; + detail::parse_format_string<true>(str_, checker(s, {})); + } +#else + detail::check_format_string<Args...>(s); +#endif + } + basic_format_string(basic_runtime<Char> r) : str_(r.str) {} + + FMT_INLINE operator basic_string_view<Char>() const { return str_; } +}; + +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 +// Workaround broken conversion on older gcc. +template <typename... Args> using format_string = string_view; +template <typename S> auto runtime(const S& s) -> basic_string_view<char_t<S>> { + return s; +} +#else +template <typename... Args> +using format_string = basic_format_string<char, type_identity_t<Args>...>; +/** + \rst + Creates a runtime format string. + + **Example**:: + + // Check format string at runtime instead of compile-time. + fmt::print(fmt::runtime("{:d}"), "I am not a number"); + \endrst + */ +template <typename S> auto runtime(const S& s) -> basic_runtime<char_t<S>> { + return {{s}}; +} +#endif + +FMT_API auto vformat(string_view fmt, format_args args) -> std::string; + +/** + \rst + Formats ``args`` according to specifications in ``fmt`` and returns the result + as a string. + + **Example**:: + + #include <fmt/core.h> + std::string message = fmt::format("The answer is {}.", 42); + \endrst +*/ +template <typename... T> +FMT_NODISCARD FMT_INLINE auto format(format_string<T...> fmt, T&&... args) + -> std::string { + return vformat(fmt, fmt::make_format_args(args...)); +} + +/** Formats a string and writes the output to ``out``. */ +template <typename OutputIt, + FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)> +auto vformat_to(OutputIt out, string_view fmt, format_args args) -> OutputIt { + using detail::get_buffer; + auto&& buf = get_buffer<char>(out); + detail::vformat_to(buf, fmt, args, {}); + return detail::get_iterator(buf); +} + +/** + \rst + Formats ``args`` according to specifications in ``fmt``, writes the result to + the output iterator ``out`` and returns the iterator past the end of the output + range. `format_to` does not append a terminating null character. + + **Example**:: + + auto out = std::vector<char>(); + fmt::format_to(std::back_inserter(out), "{}", 42); + \endrst + */ +template <typename OutputIt, typename... T, + FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)> +FMT_INLINE auto format_to(OutputIt out, format_string<T...> fmt, T&&... args) + -> OutputIt { + return vformat_to(out, fmt, fmt::make_format_args(args...)); +} + +template <typename OutputIt> struct format_to_n_result { + /** Iterator past the end of the output range. */ + OutputIt out; + /** Total (not truncated) output size. */ + size_t size; +}; + +template <typename OutputIt, typename... T, + FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)> +auto vformat_to_n(OutputIt out, size_t n, string_view fmt, format_args args) + -> format_to_n_result<OutputIt> { + using traits = detail::fixed_buffer_traits; + auto buf = detail::iterator_buffer<OutputIt, char, traits>(out, n); + detail::vformat_to(buf, fmt, args, {}); + return {buf.out(), buf.count()}; +} + +/** + \rst + Formats ``args`` according to specifications in ``fmt``, writes up to ``n`` + characters of the result to the output iterator ``out`` and returns the total + (not truncated) output size and the iterator past the end of the output range. + `format_to_n` does not append a terminating null character. + \endrst + */ +template <typename OutputIt, typename... T, + FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)> +FMT_INLINE auto format_to_n(OutputIt out, size_t n, format_string<T...> fmt, + T&&... args) -> format_to_n_result<OutputIt> { + return vformat_to_n(out, n, fmt, fmt::make_format_args(args...)); +} + +/** Returns the number of chars in the output of ``format(fmt, args...)``. */ +template <typename... T> +FMT_NODISCARD FMT_INLINE auto formatted_size(format_string<T...> fmt, + T&&... args) -> size_t { + auto buf = detail::counting_buffer<>(); + detail::vformat_to(buf, string_view(fmt), fmt::make_format_args(args...), {}); + return buf.count(); +} + +FMT_API void vprint(string_view fmt, format_args args); +FMT_API void vprint(std::FILE* f, string_view fmt, format_args args); + +/** + \rst + Formats ``args`` according to specifications in ``fmt`` and writes the output + to ``stdout``. + + **Example**:: + + fmt::print("Elapsed time: {0:.2f} seconds", 1.23); + \endrst + */ +template <typename... T> +FMT_INLINE void print(format_string<T...> fmt, T&&... args) { + const auto& vargs = fmt::make_format_args(args...); + return detail::is_utf8() ? vprint(fmt, vargs) + : detail::vprint_mojibake(stdout, fmt, vargs); +} + +/** + \rst + Formats ``args`` according to specifications in ``fmt`` and writes the + output to the file ``f``. + + **Example**:: + + fmt::print(stderr, "Don't {}!", "panic"); + \endrst + */ +template <typename... T> +FMT_INLINE void print(std::FILE* f, format_string<T...> fmt, T&&... args) { + const auto& vargs = fmt::make_format_args(args...); + return detail::is_utf8() ? vprint(f, fmt, vargs) + : detail::vprint_mojibake(f, fmt, vargs); +} + +FMT_MODULE_EXPORT_END +FMT_GCC_PRAGMA("GCC pop_options") +FMT_END_NAMESPACE + +#ifdef FMT_HEADER_ONLY +# include "format.h" +#endif +#endif // FMT_CORE_H_ diff --git a/extern/fmtlib/include/fmt/format-inl.h b/extern/fmtlib/include/fmt/format-inl.h new file mode 100644 index 00000000000..2c51c50aeb2 --- /dev/null +++ b/extern/fmtlib/include/fmt/format-inl.h @@ -0,0 +1,2643 @@ +// Formatting library for C++ - implementation +// +// Copyright (c) 2012 - 2016, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_FORMAT_INL_H_ +#define FMT_FORMAT_INL_H_ + +#include <algorithm> +#include <cctype> +#include <cerrno> // errno +#include <climits> +#include <cmath> +#include <cstdarg> +#include <cstring> // std::memmove +#include <cwchar> +#include <exception> + +#ifndef FMT_STATIC_THOUSANDS_SEPARATOR +# include <locale> +#endif + +#ifdef _WIN32 +# include <io.h> // _isatty +#endif + +#include "format.h" + +FMT_BEGIN_NAMESPACE +namespace detail { + +FMT_FUNC void assert_fail(const char* file, int line, const char* message) { + // Use unchecked std::fprintf to avoid triggering another assertion when + // writing to stderr fails + std::fprintf(stderr, "%s:%d: assertion failed: %s", file, line, message); + // Chosen instead of std::abort to satisfy Clang in CUDA mode during device + // code pass. + std::terminate(); +} + +FMT_FUNC void throw_format_error(const char* message) { + FMT_THROW(format_error(message)); +} + +#ifndef _MSC_VER +# define FMT_SNPRINTF snprintf +#else // _MSC_VER +inline int fmt_snprintf(char* buffer, size_t size, const char* format, ...) { + va_list args; + va_start(args, format); + int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args); + va_end(args); + return result; +} +# define FMT_SNPRINTF fmt_snprintf +#endif // _MSC_VER + +FMT_FUNC void format_error_code(detail::buffer<char>& out, int error_code, + string_view message) FMT_NOEXCEPT { + // Report error code making sure that the output fits into + // inline_buffer_size to avoid dynamic memory allocation and potential + // bad_alloc. + out.try_resize(0); + static const char SEP[] = ": "; + static const char ERROR_STR[] = "error "; + // Subtract 2 to account for terminating null characters in SEP and ERROR_STR. + size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2; + auto abs_value = static_cast<uint32_or_64_or_128_t<int>>(error_code); + if (detail::is_negative(error_code)) { + abs_value = 0 - abs_value; + ++error_code_size; + } + error_code_size += detail::to_unsigned(detail::count_digits(abs_value)); + auto it = buffer_appender<char>(out); + if (message.size() <= inline_buffer_size - error_code_size) + format_to(it, FMT_STRING("{}{}"), message, SEP); + format_to(it, FMT_STRING("{}{}"), ERROR_STR, error_code); + FMT_ASSERT(out.size() <= inline_buffer_size, ""); +} + +FMT_FUNC void report_error(format_func func, int error_code, + const char* message) FMT_NOEXCEPT { + memory_buffer full_message; + func(full_message, error_code, message); + // Don't use fwrite_fully because the latter may throw. + if (std::fwrite(full_message.data(), full_message.size(), 1, stderr) > 0) + std::fputc('\n', stderr); +} + +// A wrapper around fwrite that throws on error. +inline void fwrite_fully(const void* ptr, size_t size, size_t count, + FILE* stream) { + size_t written = std::fwrite(ptr, size, count, stream); + if (written < count) FMT_THROW(system_error(errno, "cannot write to file")); +} + +#ifndef FMT_STATIC_THOUSANDS_SEPARATOR +template <typename Locale> +locale_ref::locale_ref(const Locale& loc) : locale_(&loc) { + static_assert(std::is_same<Locale, std::locale>::value, ""); +} + +template <typename Locale> Locale locale_ref::get() const { + static_assert(std::is_same<Locale, std::locale>::value, ""); + return locale_ ? *static_cast<const std::locale*>(locale_) : std::locale(); +} + +template <typename Char> +FMT_FUNC auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char> { + auto& facet = std::use_facet<std::numpunct<Char>>(loc.get<std::locale>()); + auto grouping = facet.grouping(); + auto thousands_sep = grouping.empty() ? Char() : facet.thousands_sep(); + return {std::move(grouping), thousands_sep}; +} +template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref loc) { + return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>()) + .decimal_point(); +} +#else +template <typename Char> +FMT_FUNC auto thousands_sep_impl(locale_ref) -> thousands_sep_result<Char> { + return {"\03", FMT_STATIC_THOUSANDS_SEPARATOR}; +} +template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref) { + return '.'; +} +#endif +} // namespace detail + +#if !FMT_MSC_VER +FMT_API FMT_FUNC format_error::~format_error() FMT_NOEXCEPT = default; +#endif + +FMT_FUNC std::system_error vsystem_error(int error_code, string_view format_str, + format_args args) { + auto ec = std::error_code(error_code, std::generic_category()); + return std::system_error(ec, vformat(format_str, args)); +} + +namespace detail { + +template <> FMT_FUNC int count_digits<4>(detail::fallback_uintptr n) { + // fallback_uintptr is always stored in little endian. + int i = static_cast<int>(sizeof(void*)) - 1; + while (i > 0 && n.value[i] == 0) --i; + auto char_digits = std::numeric_limits<unsigned char>::digits / 4; + return i >= 0 ? i * char_digits + count_digits<4, unsigned>(n.value[i]) : 1; +} + +// log10(2) = 0x0.4d104d427de7fbcc... +static constexpr uint64_t log10_2_significand = 0x4d104d427de7fbcc; + +template <typename T = void> struct basic_impl_data { + // Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340. + // These are generated by support/compute-powers.py. + static constexpr uint64_t pow10_significands[87] = { + 0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76, 0x8b16fb203055ac76, + 0xcf42894a5dce35ea, 0x9a6bb0aa55653b2d, 0xe61acf033d1a45df, + 0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f, 0xbe5691ef416bd60c, + 0x8dd01fad907ffc3c, 0xd3515c2831559a83, 0x9d71ac8fada6c9b5, + 0xea9c227723ee8bcb, 0xaecc49914078536d, 0x823c12795db6ce57, + 0xc21094364dfb5637, 0x9096ea6f3848984f, 0xd77485cb25823ac7, + 0xa086cfcd97bf97f4, 0xef340a98172aace5, 0xb23867fb2a35b28e, + 0x84c8d4dfd2c63f3b, 0xc5dd44271ad3cdba, 0x936b9fcebb25c996, + 0xdbac6c247d62a584, 0xa3ab66580d5fdaf6, 0xf3e2f893dec3f126, + 0xb5b5ada8aaff80b8, 0x87625f056c7c4a8b, 0xc9bcff6034c13053, + 0x964e858c91ba2655, 0xdff9772470297ebd, 0xa6dfbd9fb8e5b88f, + 0xf8a95fcf88747d94, 0xb94470938fa89bcf, 0x8a08f0f8bf0f156b, + 0xcdb02555653131b6, 0x993fe2c6d07b7fac, 0xe45c10c42a2b3b06, + 0xaa242499697392d3, 0xfd87b5f28300ca0e, 0xbce5086492111aeb, + 0x8cbccc096f5088cc, 0xd1b71758e219652c, 0x9c40000000000000, + 0xe8d4a51000000000, 0xad78ebc5ac620000, 0x813f3978f8940984, + 0xc097ce7bc90715b3, 0x8f7e32ce7bea5c70, 0xd5d238a4abe98068, + 0x9f4f2726179a2245, 0xed63a231d4c4fb27, 0xb0de65388cc8ada8, + 0x83c7088e1aab65db, 0xc45d1df942711d9a, 0x924d692ca61be758, + 0xda01ee641a708dea, 0xa26da3999aef774a, 0xf209787bb47d6b85, + 0xb454e4a179dd1877, 0x865b86925b9bc5c2, 0xc83553c5c8965d3d, + 0x952ab45cfa97a0b3, 0xde469fbd99a05fe3, 0xa59bc234db398c25, + 0xf6c69a72a3989f5c, 0xb7dcbf5354e9bece, 0x88fcf317f22241e2, + 0xcc20ce9bd35c78a5, 0x98165af37b2153df, 0xe2a0b5dc971f303a, + 0xa8d9d1535ce3b396, 0xfb9b7cd9a4a7443c, 0xbb764c4ca7a44410, + 0x8bab8eefb6409c1a, 0xd01fef10a657842c, 0x9b10a4e5e9913129, + 0xe7109bfba19c0c9d, 0xac2820d9623bf429, 0x80444b5e7aa7cf85, + 0xbf21e44003acdd2d, 0x8e679c2f5e44ff8f, 0xd433179d9c8cb841, + 0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9, 0xaf87023b9bf0ee6b, + }; + +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wnarrowing" +#endif + // Binary exponents of pow(10, k), for k = -348, -340, ..., 340, corresponding + // to significands above. + static constexpr int16_t pow10_exponents[87] = { + -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954, + -927, -901, -874, -847, -821, -794, -768, -741, -715, -688, -661, + -635, -608, -582, -555, -529, -502, -475, -449, -422, -396, -369, + -343, -316, -289, -263, -236, -210, -183, -157, -130, -103, -77, + -50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216, + 242, 269, 295, 322, 348, 375, 402, 428, 455, 481, 508, + 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800, + 827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066}; +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 +# pragma GCC diagnostic pop +#endif + + static constexpr uint64_t power_of_10_64[20] = { + 1, FMT_POWERS_OF_10(1ULL), FMT_POWERS_OF_10(1000000000ULL), + 10000000000000000000ULL}; +}; + +// This is a struct rather than an alias to avoid shadowing warnings in gcc. +struct impl_data : basic_impl_data<> {}; + +#if __cplusplus < 201703L +template <typename T> +constexpr uint64_t basic_impl_data<T>::pow10_significands[]; +template <typename T> constexpr int16_t basic_impl_data<T>::pow10_exponents[]; +template <typename T> constexpr uint64_t basic_impl_data<T>::power_of_10_64[]; +#endif + +template <typename T> struct bits { + static FMT_CONSTEXPR_DECL const int value = + static_cast<int>(sizeof(T) * std::numeric_limits<unsigned char>::digits); +}; + +// Returns the number of significand bits in Float excluding the implicit bit. +template <typename Float> constexpr int num_significand_bits() { + // Subtract 1 to account for an implicit most significant bit in the + // normalized form. + return std::numeric_limits<Float>::digits - 1; +} + +// A floating-point number f * pow(2, e). +struct fp { + uint64_t f; + int e; + + static constexpr const int num_significand_bits = bits<decltype(f)>::value; + + constexpr fp() : f(0), e(0) {} + constexpr fp(uint64_t f_val, int e_val) : f(f_val), e(e_val) {} + + // Constructs fp from an IEEE754 floating-point number. It is a template to + // prevent compile errors on systems where n is not IEEE754. + template <typename Float> explicit FMT_CONSTEXPR fp(Float n) { assign(n); } + + template <typename Float> + using is_supported = bool_constant<sizeof(Float) == sizeof(uint64_t) || + sizeof(Float) == sizeof(uint32_t)>; + + // Assigns d to this and return true iff predecessor is closer than successor. + template <typename Float, FMT_ENABLE_IF(is_supported<Float>::value)> + FMT_CONSTEXPR bool assign(Float n) { + // Assume float is in the format [sign][exponent][significand]. + const int num_float_significand_bits = + detail::num_significand_bits<Float>(); + const uint64_t implicit_bit = 1ULL << num_float_significand_bits; + const uint64_t significand_mask = implicit_bit - 1; + constexpr bool is_double = sizeof(Float) == sizeof(uint64_t); + auto u = bit_cast<conditional_t<is_double, uint64_t, uint32_t>>(n); + f = u & significand_mask; + const uint64_t exponent_mask = (~0ULL >> 1) & ~significand_mask; + int biased_e = + static_cast<int>((u & exponent_mask) >> num_float_significand_bits); + // The predecessor is closer if n is a normalized power of 2 (f == 0) other + // than the smallest normalized number (biased_e > 1). + bool is_predecessor_closer = f == 0 && biased_e > 1; + if (biased_e != 0) + f += implicit_bit; + else + biased_e = 1; // Subnormals use biased exponent 1 (min exponent). + const int exponent_bias = std::numeric_limits<Float>::max_exponent - 1; + e = biased_e - exponent_bias - num_float_significand_bits; + return is_predecessor_closer; + } + + template <typename Float, FMT_ENABLE_IF(!is_supported<Float>::value)> + bool assign(Float) { + FMT_ASSERT(false, ""); + return false; + } +}; + +// Normalizes the value converted from double and multiplied by (1 << SHIFT). +template <int SHIFT = 0> FMT_CONSTEXPR fp normalize(fp value) { + // Handle subnormals. + const uint64_t implicit_bit = 1ULL << num_significand_bits<double>(); + const auto shifted_implicit_bit = implicit_bit << SHIFT; + while ((value.f & shifted_implicit_bit) == 0) { + value.f <<= 1; + --value.e; + } + // Subtract 1 to account for hidden bit. + const auto offset = + fp::num_significand_bits - num_significand_bits<double>() - SHIFT - 1; + value.f <<= offset; + value.e -= offset; + return value; +} + +inline bool operator==(fp x, fp y) { return x.f == y.f && x.e == y.e; } + +// Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking. +FMT_CONSTEXPR inline uint64_t multiply(uint64_t lhs, uint64_t rhs) { +#if FMT_USE_INT128 + auto product = static_cast<__uint128_t>(lhs) * rhs; + auto f = static_cast<uint64_t>(product >> 64); + return (static_cast<uint64_t>(product) & (1ULL << 63)) != 0 ? f + 1 : f; +#else + // Multiply 32-bit parts of significands. + uint64_t mask = (1ULL << 32) - 1; + uint64_t a = lhs >> 32, b = lhs & mask; + uint64_t c = rhs >> 32, d = rhs & mask; + uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d; + // Compute mid 64-bit of result and round. + uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31); + return ac + (ad >> 32) + (bc >> 32) + (mid >> 32); +#endif +} + +FMT_CONSTEXPR inline fp operator*(fp x, fp y) { + return {multiply(x.f, y.f), x.e + y.e + 64}; +} + +// Returns a cached power of 10 `c_k = c_k.f * pow(2, c_k.e)` such that its +// (binary) exponent satisfies `min_exponent <= c_k.e <= min_exponent + 28`. +FMT_CONSTEXPR inline fp get_cached_power(int min_exponent, + int& pow10_exponent) { + const int shift = 32; + const auto significand = static_cast<int64_t>(log10_2_significand); + int index = static_cast<int>( + ((min_exponent + fp::num_significand_bits - 1) * (significand >> shift) + + ((int64_t(1) << shift) - 1)) // ceil + >> 32 // arithmetic shift + ); + // Decimal exponent of the first (smallest) cached power of 10. + const int first_dec_exp = -348; + // Difference between 2 consecutive decimal exponents in cached powers of 10. + const int dec_exp_step = 8; + index = (index - first_dec_exp - 1) / dec_exp_step + 1; + pow10_exponent = first_dec_exp + index * dec_exp_step; + return {impl_data::pow10_significands[index], + impl_data::pow10_exponents[index]}; +} + +// A simple accumulator to hold the sums of terms in bigint::square if uint128_t +// is not available. +struct accumulator { + uint64_t lower; + uint64_t upper; + + constexpr accumulator() : lower(0), upper(0) {} + constexpr explicit operator uint32_t() const { + return static_cast<uint32_t>(lower); + } + + FMT_CONSTEXPR void operator+=(uint64_t n) { + lower += n; + if (lower < n) ++upper; + } + FMT_CONSTEXPR void operator>>=(int shift) { + FMT_ASSERT(shift == 32, ""); + (void)shift; + lower = (upper << 32) | (lower >> 32); + upper >>= 32; + } +}; + +class bigint { + private: + // A bigint is stored as an array of bigits (big digits), with bigit at index + // 0 being the least significant one. + using bigit = uint32_t; + using double_bigit = uint64_t; + enum { bigits_capacity = 32 }; + basic_memory_buffer<bigit, bigits_capacity> bigits_; + int exp_; + + FMT_CONSTEXPR20 bigit operator[](int index) const { + return bigits_[to_unsigned(index)]; + } + FMT_CONSTEXPR20 bigit& operator[](int index) { + return bigits_[to_unsigned(index)]; + } + + static FMT_CONSTEXPR_DECL const int bigit_bits = bits<bigit>::value; + + friend struct formatter<bigint>; + + FMT_CONSTEXPR20 void subtract_bigits(int index, bigit other, bigit& borrow) { + auto result = static_cast<double_bigit>((*this)[index]) - other - borrow; + (*this)[index] = static_cast<bigit>(result); + borrow = static_cast<bigit>(result >> (bigit_bits * 2 - 1)); + } + + FMT_CONSTEXPR20 void remove_leading_zeros() { + int num_bigits = static_cast<int>(bigits_.size()) - 1; + while (num_bigits > 0 && (*this)[num_bigits] == 0) --num_bigits; + bigits_.resize(to_unsigned(num_bigits + 1)); + } + + // Computes *this -= other assuming aligned bigints and *this >= other. + FMT_CONSTEXPR20 void subtract_aligned(const bigint& other) { + FMT_ASSERT(other.exp_ >= exp_, "unaligned bigints"); + FMT_ASSERT(compare(*this, other) >= 0, ""); + bigit borrow = 0; + int i = other.exp_ - exp_; + for (size_t j = 0, n = other.bigits_.size(); j != n; ++i, ++j) + subtract_bigits(i, other.bigits_[j], borrow); + while (borrow > 0) subtract_bigits(i, 0, borrow); + remove_leading_zeros(); + } + + FMT_CONSTEXPR20 void multiply(uint32_t value) { + const double_bigit wide_value = value; + bigit carry = 0; + for (size_t i = 0, n = bigits_.size(); i < n; ++i) { + double_bigit result = bigits_[i] * wide_value + carry; + bigits_[i] = static_cast<bigit>(result); + carry = static_cast<bigit>(result >> bigit_bits); + } + if (carry != 0) bigits_.push_back(carry); + } + + FMT_CONSTEXPR20 void multiply(uint64_t value) { + const bigit mask = ~bigit(0); + const double_bigit lower = value & mask; + const double_bigit upper = value >> bigit_bits; + double_bigit carry = 0; + for (size_t i = 0, n = bigits_.size(); i < n; ++i) { + double_bigit result = bigits_[i] * lower + (carry & mask); + carry = + bigits_[i] * upper + (result >> bigit_bits) + (carry >> bigit_bits); + bigits_[i] = static_cast<bigit>(result); + } + while (carry != 0) { + bigits_.push_back(carry & mask); + carry >>= bigit_bits; + } + } + + public: + FMT_CONSTEXPR20 bigint() : exp_(0) {} + explicit bigint(uint64_t n) { assign(n); } + FMT_CONSTEXPR20 ~bigint() { + FMT_ASSERT(bigits_.capacity() <= bigits_capacity, ""); + } + + bigint(const bigint&) = delete; + void operator=(const bigint&) = delete; + + FMT_CONSTEXPR20 void assign(const bigint& other) { + auto size = other.bigits_.size(); + bigits_.resize(size); + auto data = other.bigits_.data(); + std::copy(data, data + size, make_checked(bigits_.data(), size)); + exp_ = other.exp_; + } + + FMT_CONSTEXPR20 void assign(uint64_t n) { + size_t num_bigits = 0; + do { + bigits_[num_bigits++] = n & ~bigit(0); + n >>= bigit_bits; + } while (n != 0); + bigits_.resize(num_bigits); + exp_ = 0; + } + + FMT_CONSTEXPR20 int num_bigits() const { + return static_cast<int>(bigits_.size()) + exp_; + } + + FMT_NOINLINE FMT_CONSTEXPR20 bigint& operator<<=(int shift) { + FMT_ASSERT(shift >= 0, ""); + exp_ += shift / bigit_bits; + shift %= bigit_bits; + if (shift == 0) return *this; + bigit carry = 0; + for (size_t i = 0, n = bigits_.size(); i < n; ++i) { + bigit c = bigits_[i] >> (bigit_bits - shift); + bigits_[i] = (bigits_[i] << shift) + carry; + carry = c; + } + if (carry != 0) bigits_.push_back(carry); + return *this; + } + + template <typename Int> FMT_CONSTEXPR20 bigint& operator*=(Int value) { + FMT_ASSERT(value > 0, ""); + multiply(uint32_or_64_or_128_t<Int>(value)); + return *this; + } + + friend FMT_CONSTEXPR20 int compare(const bigint& lhs, const bigint& rhs) { + int num_lhs_bigits = lhs.num_bigits(), num_rhs_bigits = rhs.num_bigits(); + if (num_lhs_bigits != num_rhs_bigits) + return num_lhs_bigits > num_rhs_bigits ? 1 : -1; + int i = static_cast<int>(lhs.bigits_.size()) - 1; + int j = static_cast<int>(rhs.bigits_.size()) - 1; + int end = i - j; + if (end < 0) end = 0; + for (; i >= end; --i, --j) { + bigit lhs_bigit = lhs[i], rhs_bigit = rhs[j]; + if (lhs_bigit != rhs_bigit) return lhs_bigit > rhs_bigit ? 1 : -1; + } + if (i != j) return i > j ? 1 : -1; + return 0; + } + + // Returns compare(lhs1 + lhs2, rhs). + friend FMT_CONSTEXPR20 int add_compare(const bigint& lhs1, const bigint& lhs2, + const bigint& rhs) { + int max_lhs_bigits = (std::max)(lhs1.num_bigits(), lhs2.num_bigits()); + int num_rhs_bigits = rhs.num_bigits(); + if (max_lhs_bigits + 1 < num_rhs_bigits) return -1; + if (max_lhs_bigits > num_rhs_bigits) return 1; + auto get_bigit = [](const bigint& n, int i) -> bigit { + return i >= n.exp_ && i < n.num_bigits() ? n[i - n.exp_] : 0; + }; + double_bigit borrow = 0; + int min_exp = (std::min)((std::min)(lhs1.exp_, lhs2.exp_), rhs.exp_); + for (int i = num_rhs_bigits - 1; i >= min_exp; --i) { + double_bigit sum = + static_cast<double_bigit>(get_bigit(lhs1, i)) + get_bigit(lhs2, i); + bigit rhs_bigit = get_bigit(rhs, i); + if (sum > rhs_bigit + borrow) return 1; + borrow = rhs_bigit + borrow - sum; + if (borrow > 1) return -1; + borrow <<= bigit_bits; + } + return borrow != 0 ? -1 : 0; + } + + // Assigns pow(10, exp) to this bigint. + FMT_CONSTEXPR20 void assign_pow10(int exp) { + FMT_ASSERT(exp >= 0, ""); + if (exp == 0) return assign(1); + // Find the top bit. + int bitmask = 1; + while (exp >= bitmask) bitmask <<= 1; + bitmask >>= 1; + // pow(10, exp) = pow(5, exp) * pow(2, exp). First compute pow(5, exp) by + // repeated squaring and multiplication. + assign(5); + bitmask >>= 1; + while (bitmask != 0) { + square(); + if ((exp & bitmask) != 0) *this *= 5; + bitmask >>= 1; + } + *this <<= exp; // Multiply by pow(2, exp) by shifting. + } + + FMT_CONSTEXPR20 void square() { + int num_bigits = static_cast<int>(bigits_.size()); + int num_result_bigits = 2 * num_bigits; + basic_memory_buffer<bigit, bigits_capacity> n(std::move(bigits_)); + bigits_.resize(to_unsigned(num_result_bigits)); + using accumulator_t = conditional_t<FMT_USE_INT128, uint128_t, accumulator>; + auto sum = accumulator_t(); + for (int bigit_index = 0; bigit_index < num_bigits; ++bigit_index) { + // Compute bigit at position bigit_index of the result by adding + // cross-product terms n[i] * n[j] such that i + j == bigit_index. + for (int i = 0, j = bigit_index; j >= 0; ++i, --j) { + // Most terms are multiplied twice which can be optimized in the future. + sum += static_cast<double_bigit>(n[i]) * n[j]; + } + (*this)[bigit_index] = static_cast<bigit>(sum); + sum >>= bits<bigit>::value; // Compute the carry. + } + // Do the same for the top half. + for (int bigit_index = num_bigits; bigit_index < num_result_bigits; + ++bigit_index) { + for (int j = num_bigits - 1, i = bigit_index - j; i < num_bigits;) + sum += static_cast<double_bigit>(n[i++]) * n[j--]; + (*this)[bigit_index] = static_cast<bigit>(sum); + sum >>= bits<bigit>::value; + } + remove_leading_zeros(); + exp_ *= 2; + } + + // If this bigint has a bigger exponent than other, adds trailing zero to make + // exponents equal. This simplifies some operations such as subtraction. + FMT_CONSTEXPR20 void align(const bigint& other) { + int exp_difference = exp_ - other.exp_; + if (exp_difference <= 0) return; + int num_bigits = static_cast<int>(bigits_.size()); + bigits_.resize(to_unsigned(num_bigits + exp_difference)); + for (int i = num_bigits - 1, j = i + exp_difference; i >= 0; --i, --j) + bigits_[j] = bigits_[i]; + std::uninitialized_fill_n(bigits_.data(), exp_difference, 0); + exp_ -= exp_difference; + } + + // Divides this bignum by divisor, assigning the remainder to this and + // returning the quotient. + FMT_CONSTEXPR20 int divmod_assign(const bigint& divisor) { + FMT_ASSERT(this != &divisor, ""); + if (compare(*this, divisor) < 0) return 0; + FMT_ASSERT(divisor.bigits_[divisor.bigits_.size() - 1u] != 0, ""); + align(divisor); + int quotient = 0; + do { + subtract_aligned(divisor); + ++quotient; + } while (compare(*this, divisor) >= 0); + return quotient; + } +}; + +enum class round_direction { unknown, up, down }; + +// Given the divisor (normally a power of 10), the remainder = v % divisor for +// some number v and the error, returns whether v should be rounded up, down, or +// whether the rounding direction can't be determined due to error. +// error should be less than divisor / 2. +FMT_CONSTEXPR inline round_direction get_round_direction(uint64_t divisor, + uint64_t remainder, + uint64_t error) { + FMT_ASSERT(remainder < divisor, ""); // divisor - remainder won't overflow. + FMT_ASSERT(error < divisor, ""); // divisor - error won't overflow. + FMT_ASSERT(error < divisor - error, ""); // error * 2 won't overflow. + // Round down if (remainder + error) * 2 <= divisor. + if (remainder <= divisor - remainder && error * 2 <= divisor - remainder * 2) + return round_direction::down; + // Round up if (remainder - error) * 2 >= divisor. + if (remainder >= error && + remainder - error >= divisor - (remainder - error)) { + return round_direction::up; + } + return round_direction::unknown; +} + +namespace digits { +enum result { + more, // Generate more digits. + done, // Done generating digits. + error // Digit generation cancelled due to an error. +}; +} + +struct gen_digits_handler { + char* buf; + int size; + int precision; + int exp10; + bool fixed; + + FMT_CONSTEXPR digits::result on_digit(char digit, uint64_t divisor, + uint64_t remainder, uint64_t error, + bool integral) { + FMT_ASSERT(remainder < divisor, ""); + buf[size++] = digit; + if (!integral && error >= remainder) return digits::error; + if (size < precision) return digits::more; + if (!integral) { + // Check if error * 2 < divisor with overflow prevention. + // The check is not needed for the integral part because error = 1 + // and divisor > (1 << 32) there. + if (error >= divisor || error >= divisor - error) return digits::error; + } else { + FMT_ASSERT(error == 1 && divisor > 2, ""); + } + auto dir = get_round_direction(divisor, remainder, error); + if (dir != round_direction::up) + return dir == round_direction::down ? digits::done : digits::error; + ++buf[size - 1]; + for (int i = size - 1; i > 0 && buf[i] > '9'; --i) { + buf[i] = '0'; + ++buf[i - 1]; + } + if (buf[0] > '9') { + buf[0] = '1'; + if (fixed) + buf[size++] = '0'; + else + ++exp10; + } + return digits::done; + } +}; + +// Generates output using the Grisu digit-gen algorithm. +// error: the size of the region (lower, upper) outside of which numbers +// definitely do not round to value (Delta in Grisu3). +FMT_INLINE FMT_CONSTEXPR20 digits::result grisu_gen_digits( + fp value, uint64_t error, int& exp, gen_digits_handler& handler) { + const fp one(1ULL << -value.e, value.e); + // The integral part of scaled value (p1 in Grisu) = value / one. It cannot be + // zero because it contains a product of two 64-bit numbers with MSB set (due + // to normalization) - 1, shifted right by at most 60 bits. + auto integral = static_cast<uint32_t>(value.f >> -one.e); + FMT_ASSERT(integral != 0, ""); + FMT_ASSERT(integral == value.f >> -one.e, ""); + // The fractional part of scaled value (p2 in Grisu) c = value % one. + uint64_t fractional = value.f & (one.f - 1); + exp = count_digits(integral); // kappa in Grisu. + // Non-fixed formats require at least one digit and no precision adjustment. + if (handler.fixed) { + // Adjust fixed precision by exponent because it is relative to decimal + // point. + int precision_offset = exp + handler.exp10; + if (precision_offset > 0 && + handler.precision > max_value<int>() - precision_offset) { + FMT_THROW(format_error("number is too big")); + } + handler.precision += precision_offset; + // Check if precision is satisfied just by leading zeros, e.g. + // format("{:.2f}", 0.001) gives "0.00" without generating any digits. + if (handler.precision <= 0) { + if (handler.precision < 0) return digits::done; + // Divide by 10 to prevent overflow. + uint64_t divisor = impl_data::power_of_10_64[exp - 1] << -one.e; + auto dir = get_round_direction(divisor, value.f / 10, error * 10); + if (dir == round_direction::unknown) return digits::error; + handler.buf[handler.size++] = dir == round_direction::up ? '1' : '0'; + return digits::done; + } + } + // Generate digits for the integral part. This can produce up to 10 digits. + do { + uint32_t digit = 0; + auto divmod_integral = [&](uint32_t divisor) { + digit = integral / divisor; + integral %= divisor; + }; + // This optimization by Milo Yip reduces the number of integer divisions by + // one per iteration. + switch (exp) { + case 10: + divmod_integral(1000000000); + break; + case 9: + divmod_integral(100000000); + break; + case 8: + divmod_integral(10000000); + break; + case 7: + divmod_integral(1000000); + break; + case 6: + divmod_integral(100000); + break; + case 5: + divmod_integral(10000); + break; + case 4: + divmod_integral(1000); + break; + case 3: + divmod_integral(100); + break; + case 2: + divmod_integral(10); + break; + case 1: + digit = integral; + integral = 0; + break; + default: + FMT_ASSERT(false, "invalid number of digits"); + } + --exp; + auto remainder = (static_cast<uint64_t>(integral) << -one.e) + fractional; + auto result = handler.on_digit(static_cast<char>('0' + digit), + impl_data::power_of_10_64[exp] << -one.e, + remainder, error, true); + if (result != digits::more) return result; + } while (exp > 0); + // Generate digits for the fractional part. + for (;;) { + fractional *= 10; + error *= 10; + char digit = static_cast<char>('0' + (fractional >> -one.e)); + fractional &= one.f - 1; + --exp; + auto result = handler.on_digit(digit, one.f, fractional, error, false); + if (result != digits::more) return result; + } +} + +// A 128-bit integer type used internally, +struct uint128_wrapper { + uint128_wrapper() = default; + +#if FMT_USE_INT128 + uint128_t internal_; + + constexpr uint128_wrapper(uint64_t high, uint64_t low) FMT_NOEXCEPT + : internal_{static_cast<uint128_t>(low) | + (static_cast<uint128_t>(high) << 64)} {} + + constexpr uint128_wrapper(uint128_t u) : internal_{u} {} + + constexpr uint64_t high() const FMT_NOEXCEPT { + return uint64_t(internal_ >> 64); + } + constexpr uint64_t low() const FMT_NOEXCEPT { return uint64_t(internal_); } + + uint128_wrapper& operator+=(uint64_t n) FMT_NOEXCEPT { + internal_ += n; + return *this; + } +#else + uint64_t high_; + uint64_t low_; + + constexpr uint128_wrapper(uint64_t high, uint64_t low) FMT_NOEXCEPT + : high_{high}, + low_{low} {} + + constexpr uint64_t high() const FMT_NOEXCEPT { return high_; } + constexpr uint64_t low() const FMT_NOEXCEPT { return low_; } + + uint128_wrapper& operator+=(uint64_t n) FMT_NOEXCEPT { +# if defined(_MSC_VER) && defined(_M_X64) + unsigned char carry = _addcarry_u64(0, low_, n, &low_); + _addcarry_u64(carry, high_, 0, &high_); + return *this; +# else + uint64_t sum = low_ + n; + high_ += (sum < low_ ? 1 : 0); + low_ = sum; + return *this; +# endif + } +#endif +}; + +// Implementation of Dragonbox algorithm: https://github.com/jk-jeon/dragonbox. +namespace dragonbox { +// Computes 128-bit result of multiplication of two 64-bit unsigned integers. +inline uint128_wrapper umul128(uint64_t x, uint64_t y) FMT_NOEXCEPT { +#if FMT_USE_INT128 + return static_cast<uint128_t>(x) * static_cast<uint128_t>(y); +#elif defined(_MSC_VER) && defined(_M_X64) + uint128_wrapper result; + result.low_ = _umul128(x, y, &result.high_); + return result; +#else + const uint64_t mask = (uint64_t(1) << 32) - uint64_t(1); + + uint64_t a = x >> 32; + uint64_t b = x & mask; + uint64_t c = y >> 32; + uint64_t d = y & mask; + + uint64_t ac = a * c; + uint64_t bc = b * c; + uint64_t ad = a * d; + uint64_t bd = b * d; + + uint64_t intermediate = (bd >> 32) + (ad & mask) + (bc & mask); + + return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32), + (intermediate << 32) + (bd & mask)}; +#endif +} + +// Computes upper 64 bits of multiplication of two 64-bit unsigned integers. +inline uint64_t umul128_upper64(uint64_t x, uint64_t y) FMT_NOEXCEPT { +#if FMT_USE_INT128 + auto p = static_cast<uint128_t>(x) * static_cast<uint128_t>(y); + return static_cast<uint64_t>(p >> 64); +#elif defined(_MSC_VER) && defined(_M_X64) + return __umulh(x, y); +#else + return umul128(x, y).high(); +#endif +} + +// Computes upper 64 bits of multiplication of a 64-bit unsigned integer and a +// 128-bit unsigned integer. +inline uint64_t umul192_upper64(uint64_t x, uint128_wrapper y) FMT_NOEXCEPT { + uint128_wrapper g0 = umul128(x, y.high()); + g0 += umul128_upper64(x, y.low()); + return g0.high(); +} + +// Computes upper 32 bits of multiplication of a 32-bit unsigned integer and a +// 64-bit unsigned integer. +inline uint32_t umul96_upper32(uint32_t x, uint64_t y) FMT_NOEXCEPT { + return static_cast<uint32_t>(umul128_upper64(x, y)); +} + +// Computes middle 64 bits of multiplication of a 64-bit unsigned integer and a +// 128-bit unsigned integer. +inline uint64_t umul192_middle64(uint64_t x, uint128_wrapper y) FMT_NOEXCEPT { + uint64_t g01 = x * y.high(); + uint64_t g10 = umul128_upper64(x, y.low()); + return g01 + g10; +} + +// Computes lower 64 bits of multiplication of a 32-bit unsigned integer and a +// 64-bit unsigned integer. +inline uint64_t umul96_lower64(uint32_t x, uint64_t y) FMT_NOEXCEPT { + return x * y; +} + +// Computes floor(log10(pow(2, e))) for e in [-1700, 1700] using the method from +// https://fmt.dev/papers/Grisu-Exact.pdf#page=5, section 3.4. +inline int floor_log10_pow2(int e) FMT_NOEXCEPT { + FMT_ASSERT(e <= 1700 && e >= -1700, "too large exponent"); + const int shift = 22; + return (e * static_cast<int>(log10_2_significand >> (64 - shift))) >> shift; +} + +// Various fast log computations. +inline int floor_log2_pow10(int e) FMT_NOEXCEPT { + FMT_ASSERT(e <= 1233 && e >= -1233, "too large exponent"); + const uint64_t log2_10_integer_part = 3; + const uint64_t log2_10_fractional_digits = 0x5269e12f346e2bf9; + const int shift_amount = 19; + return (e * static_cast<int>( + (log2_10_integer_part << shift_amount) | + (log2_10_fractional_digits >> (64 - shift_amount)))) >> + shift_amount; +} +inline int floor_log10_pow2_minus_log10_4_over_3(int e) FMT_NOEXCEPT { + FMT_ASSERT(e <= 1700 && e >= -1700, "too large exponent"); + const uint64_t log10_4_over_3_fractional_digits = 0x1ffbfc2bbc780375; + const int shift_amount = 22; + return (e * static_cast<int>(log10_2_significand >> (64 - shift_amount)) - + static_cast<int>(log10_4_over_3_fractional_digits >> + (64 - shift_amount))) >> + shift_amount; +} + +// Returns true iff x is divisible by pow(2, exp). +inline bool divisible_by_power_of_2(uint32_t x, int exp) FMT_NOEXCEPT { + FMT_ASSERT(exp >= 1, ""); + FMT_ASSERT(x != 0, ""); +#ifdef FMT_BUILTIN_CTZ + return FMT_BUILTIN_CTZ(x) >= exp; +#else + return exp < num_bits<uint32_t>() && x == ((x >> exp) << exp); +#endif +} +inline bool divisible_by_power_of_2(uint64_t x, int exp) FMT_NOEXCEPT { + FMT_ASSERT(exp >= 1, ""); + FMT_ASSERT(x != 0, ""); +#ifdef FMT_BUILTIN_CTZLL + return FMT_BUILTIN_CTZLL(x) >= exp; +#else + return exp < num_bits<uint64_t>() && x == ((x >> exp) << exp); +#endif +} + +// Table entry type for divisibility test. +template <typename T> struct divtest_table_entry { + T mod_inv; + T max_quotient; +}; + +// Returns true iff x is divisible by pow(5, exp). +inline bool divisible_by_power_of_5(uint32_t x, int exp) FMT_NOEXCEPT { + FMT_ASSERT(exp <= 10, "too large exponent"); + static constexpr const divtest_table_entry<uint32_t> divtest_table[] = { + {0x00000001, 0xffffffff}, {0xcccccccd, 0x33333333}, + {0xc28f5c29, 0x0a3d70a3}, {0x26e978d5, 0x020c49ba}, + {0x3afb7e91, 0x0068db8b}, {0x0bcbe61d, 0x0014f8b5}, + {0x68c26139, 0x000431bd}, {0xae8d46a5, 0x0000d6bf}, + {0x22e90e21, 0x00002af3}, {0x3a2e9c6d, 0x00000897}, + {0x3ed61f49, 0x000001b7}}; + return x * divtest_table[exp].mod_inv <= divtest_table[exp].max_quotient; +} +inline bool divisible_by_power_of_5(uint64_t x, int exp) FMT_NOEXCEPT { + FMT_ASSERT(exp <= 23, "too large exponent"); + static constexpr const divtest_table_entry<uint64_t> divtest_table[] = { + {0x0000000000000001, 0xffffffffffffffff}, + {0xcccccccccccccccd, 0x3333333333333333}, + {0x8f5c28f5c28f5c29, 0x0a3d70a3d70a3d70}, + {0x1cac083126e978d5, 0x020c49ba5e353f7c}, + {0xd288ce703afb7e91, 0x0068db8bac710cb2}, + {0x5d4e8fb00bcbe61d, 0x0014f8b588e368f0}, + {0x790fb65668c26139, 0x000431bde82d7b63}, + {0xe5032477ae8d46a5, 0x0000d6bf94d5e57a}, + {0xc767074b22e90e21, 0x00002af31dc46118}, + {0x8e47ce423a2e9c6d, 0x0000089705f4136b}, + {0x4fa7f60d3ed61f49, 0x000001b7cdfd9d7b}, + {0x0fee64690c913975, 0x00000057f5ff85e5}, + {0x3662e0e1cf503eb1, 0x000000119799812d}, + {0xa47a2cf9f6433fbd, 0x0000000384b84d09}, + {0x54186f653140a659, 0x00000000b424dc35}, + {0x7738164770402145, 0x0000000024075f3d}, + {0xe4a4d1417cd9a041, 0x000000000734aca5}, + {0xc75429d9e5c5200d, 0x000000000170ef54}, + {0xc1773b91fac10669, 0x000000000049c977}, + {0x26b172506559ce15, 0x00000000000ec1e4}, + {0xd489e3a9addec2d1, 0x000000000002f394}, + {0x90e860bb892c8d5d, 0x000000000000971d}, + {0x502e79bf1b6f4f79, 0x0000000000001e39}, + {0xdcd618596be30fe5, 0x000000000000060b}}; + return x * divtest_table[exp].mod_inv <= divtest_table[exp].max_quotient; +} + +// Replaces n by floor(n / pow(5, N)) returning true if and only if n is +// divisible by pow(5, N). +// Precondition: n <= 2 * pow(5, N + 1). +template <int N> +bool check_divisibility_and_divide_by_pow5(uint32_t& n) FMT_NOEXCEPT { + static constexpr struct { + uint32_t magic_number; + int bits_for_comparison; + uint32_t threshold; + int shift_amount; + } infos[] = {{0xcccd, 16, 0x3333, 18}, {0xa429, 8, 0x0a, 20}}; + constexpr auto info = infos[N - 1]; + n *= info.magic_number; + const uint32_t comparison_mask = (1u << info.bits_for_comparison) - 1; + bool result = (n & comparison_mask) <= info.threshold; + n >>= info.shift_amount; + return result; +} + +// Computes floor(n / pow(10, N)) for small n and N. +// Precondition: n <= pow(10, N + 1). +template <int N> uint32_t small_division_by_pow10(uint32_t n) FMT_NOEXCEPT { + static constexpr struct { + uint32_t magic_number; + int shift_amount; + uint32_t divisor_times_10; + } infos[] = {{0xcccd, 19, 100}, {0xa3d8, 22, 1000}}; + constexpr auto info = infos[N - 1]; + FMT_ASSERT(n <= info.divisor_times_10, "n is too large"); + return n * info.magic_number >> info.shift_amount; +} + +// Computes floor(n / 10^(kappa + 1)) (float) +inline uint32_t divide_by_10_to_kappa_plus_1(uint32_t n) FMT_NOEXCEPT { + return n / float_info<float>::big_divisor; +} +// Computes floor(n / 10^(kappa + 1)) (double) +inline uint64_t divide_by_10_to_kappa_plus_1(uint64_t n) FMT_NOEXCEPT { + return umul128_upper64(n, 0x83126e978d4fdf3c) >> 9; +} + +// Various subroutines using pow10 cache +template <class T> struct cache_accessor; + +template <> struct cache_accessor<float> { + using carrier_uint = float_info<float>::carrier_uint; + using cache_entry_type = uint64_t; + + static uint64_t get_cached_power(int k) FMT_NOEXCEPT { + FMT_ASSERT(k >= float_info<float>::min_k && k <= float_info<float>::max_k, + "k is out of range"); + static constexpr const uint64_t pow10_significands[] = { + 0x81ceb32c4b43fcf5, 0xa2425ff75e14fc32, 0xcad2f7f5359a3b3f, + 0xfd87b5f28300ca0e, 0x9e74d1b791e07e49, 0xc612062576589ddb, + 0xf79687aed3eec552, 0x9abe14cd44753b53, 0xc16d9a0095928a28, + 0xf1c90080baf72cb2, 0x971da05074da7bef, 0xbce5086492111aeb, + 0xec1e4a7db69561a6, 0x9392ee8e921d5d08, 0xb877aa3236a4b44a, + 0xe69594bec44de15c, 0x901d7cf73ab0acda, 0xb424dc35095cd810, + 0xe12e13424bb40e14, 0x8cbccc096f5088cc, 0xafebff0bcb24aaff, + 0xdbe6fecebdedd5bf, 0x89705f4136b4a598, 0xabcc77118461cefd, + 0xd6bf94d5e57a42bd, 0x8637bd05af6c69b6, 0xa7c5ac471b478424, + 0xd1b71758e219652c, 0x83126e978d4fdf3c, 0xa3d70a3d70a3d70b, + 0xcccccccccccccccd, 0x8000000000000000, 0xa000000000000000, + 0xc800000000000000, 0xfa00000000000000, 0x9c40000000000000, + 0xc350000000000000, 0xf424000000000000, 0x9896800000000000, + 0xbebc200000000000, 0xee6b280000000000, 0x9502f90000000000, + 0xba43b74000000000, 0xe8d4a51000000000, 0x9184e72a00000000, + 0xb5e620f480000000, 0xe35fa931a0000000, 0x8e1bc9bf04000000, + 0xb1a2bc2ec5000000, 0xde0b6b3a76400000, 0x8ac7230489e80000, + 0xad78ebc5ac620000, 0xd8d726b7177a8000, 0x878678326eac9000, + 0xa968163f0a57b400, 0xd3c21bcecceda100, 0x84595161401484a0, + 0xa56fa5b99019a5c8, 0xcecb8f27f4200f3a, 0x813f3978f8940984, + 0xa18f07d736b90be5, 0xc9f2c9cd04674ede, 0xfc6f7c4045812296, + 0x9dc5ada82b70b59d, 0xc5371912364ce305, 0xf684df56c3e01bc6, + 0x9a130b963a6c115c, 0xc097ce7bc90715b3, 0xf0bdc21abb48db20, + 0x96769950b50d88f4, 0xbc143fa4e250eb31, 0xeb194f8e1ae525fd, + 0x92efd1b8d0cf37be, 0xb7abc627050305ad, 0xe596b7b0c643c719, + 0x8f7e32ce7bea5c6f, 0xb35dbf821ae4f38b, 0xe0352f62a19e306e}; + return pow10_significands[k - float_info<float>::min_k]; + } + + static carrier_uint compute_mul(carrier_uint u, + const cache_entry_type& cache) FMT_NOEXCEPT { + return umul96_upper32(u, cache); + } + + static uint32_t compute_delta(const cache_entry_type& cache, + int beta_minus_1) FMT_NOEXCEPT { + return static_cast<uint32_t>(cache >> (64 - 1 - beta_minus_1)); + } + + static bool compute_mul_parity(carrier_uint two_f, + const cache_entry_type& cache, + int beta_minus_1) FMT_NOEXCEPT { + FMT_ASSERT(beta_minus_1 >= 1, ""); + FMT_ASSERT(beta_minus_1 < 64, ""); + + return ((umul96_lower64(two_f, cache) >> (64 - beta_minus_1)) & 1) != 0; + } + + static carrier_uint compute_left_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT { + return static_cast<carrier_uint>( + (cache - (cache >> (float_info<float>::significand_bits + 2))) >> + (64 - float_info<float>::significand_bits - 1 - beta_minus_1)); + } + + static carrier_uint compute_right_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT { + return static_cast<carrier_uint>( + (cache + (cache >> (float_info<float>::significand_bits + 1))) >> + (64 - float_info<float>::significand_bits - 1 - beta_minus_1)); + } + + static carrier_uint compute_round_up_for_shorter_interval_case( + const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT { + return (static_cast<carrier_uint>( + cache >> + (64 - float_info<float>::significand_bits - 2 - beta_minus_1)) + + 1) / + 2; + } +}; + +template <> struct cache_accessor<double> { + using carrier_uint = float_info<double>::carrier_uint; + using cache_entry_type = uint128_wrapper; + + static uint128_wrapper get_cached_power(int k) FMT_NOEXCEPT { + FMT_ASSERT(k >= float_info<double>::min_k && k <= float_info<double>::max_k, + "k is out of range"); + + static constexpr const uint128_wrapper pow10_significands[] = { +#if FMT_USE_FULL_CACHE_DRAGONBOX + {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b}, + {0x9faacf3df73609b1, 0x77b191618c54e9ad}, + {0xc795830d75038c1d, 0xd59df5b9ef6a2418}, + {0xf97ae3d0d2446f25, 0x4b0573286b44ad1e}, + {0x9becce62836ac577, 0x4ee367f9430aec33}, + {0xc2e801fb244576d5, 0x229c41f793cda740}, + {0xf3a20279ed56d48a, 0x6b43527578c11110}, + {0x9845418c345644d6, 0x830a13896b78aaaa}, + {0xbe5691ef416bd60c, 0x23cc986bc656d554}, + {0xedec366b11c6cb8f, 0x2cbfbe86b7ec8aa9}, + {0x94b3a202eb1c3f39, 0x7bf7d71432f3d6aa}, + {0xb9e08a83a5e34f07, 0xdaf5ccd93fb0cc54}, + {0xe858ad248f5c22c9, 0xd1b3400f8f9cff69}, + {0x91376c36d99995be, 0x23100809b9c21fa2}, + {0xb58547448ffffb2d, 0xabd40a0c2832a78b}, + {0xe2e69915b3fff9f9, 0x16c90c8f323f516d}, + {0x8dd01fad907ffc3b, 0xae3da7d97f6792e4}, + {0xb1442798f49ffb4a, 0x99cd11cfdf41779d}, + {0xdd95317f31c7fa1d, 0x40405643d711d584}, + {0x8a7d3eef7f1cfc52, 0x482835ea666b2573}, + {0xad1c8eab5ee43b66, 0xda3243650005eed0}, + {0xd863b256369d4a40, 0x90bed43e40076a83}, + {0x873e4f75e2224e68, 0x5a7744a6e804a292}, + {0xa90de3535aaae202, 0x711515d0a205cb37}, + {0xd3515c2831559a83, 0x0d5a5b44ca873e04}, + {0x8412d9991ed58091, 0xe858790afe9486c3}, + {0xa5178fff668ae0b6, 0x626e974dbe39a873}, + {0xce5d73ff402d98e3, 0xfb0a3d212dc81290}, + {0x80fa687f881c7f8e, 0x7ce66634bc9d0b9a}, + {0xa139029f6a239f72, 0x1c1fffc1ebc44e81}, + {0xc987434744ac874e, 0xa327ffb266b56221}, + {0xfbe9141915d7a922, 0x4bf1ff9f0062baa9}, + {0x9d71ac8fada6c9b5, 0x6f773fc3603db4aa}, + {0xc4ce17b399107c22, 0xcb550fb4384d21d4}, + {0xf6019da07f549b2b, 0x7e2a53a146606a49}, + {0x99c102844f94e0fb, 0x2eda7444cbfc426e}, + {0xc0314325637a1939, 0xfa911155fefb5309}, + {0xf03d93eebc589f88, 0x793555ab7eba27cb}, + {0x96267c7535b763b5, 0x4bc1558b2f3458df}, + {0xbbb01b9283253ca2, 0x9eb1aaedfb016f17}, + {0xea9c227723ee8bcb, 0x465e15a979c1cadd}, + {0x92a1958a7675175f, 0x0bfacd89ec191eca}, + {0xb749faed14125d36, 0xcef980ec671f667c}, + {0xe51c79a85916f484, 0x82b7e12780e7401b}, + {0x8f31cc0937ae58d2, 0xd1b2ecb8b0908811}, + {0xb2fe3f0b8599ef07, 0x861fa7e6dcb4aa16}, + {0xdfbdcece67006ac9, 0x67a791e093e1d49b}, + {0x8bd6a141006042bd, 0xe0c8bb2c5c6d24e1}, + {0xaecc49914078536d, 0x58fae9f773886e19}, + {0xda7f5bf590966848, 0xaf39a475506a899f}, + {0x888f99797a5e012d, 0x6d8406c952429604}, + {0xaab37fd7d8f58178, 0xc8e5087ba6d33b84}, + {0xd5605fcdcf32e1d6, 0xfb1e4a9a90880a65}, + {0x855c3be0a17fcd26, 0x5cf2eea09a550680}, + {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f}, + {0xd0601d8efc57b08b, 0xf13b94daf124da27}, + {0x823c12795db6ce57, 0x76c53d08d6b70859}, + {0xa2cb1717b52481ed, 0x54768c4b0c64ca6f}, + {0xcb7ddcdda26da268, 0xa9942f5dcf7dfd0a}, + {0xfe5d54150b090b02, 0xd3f93b35435d7c4d}, + {0x9efa548d26e5a6e1, 0xc47bc5014a1a6db0}, + {0xc6b8e9b0709f109a, 0x359ab6419ca1091c}, + {0xf867241c8cc6d4c0, 0xc30163d203c94b63}, + {0x9b407691d7fc44f8, 0x79e0de63425dcf1e}, + {0xc21094364dfb5636, 0x985915fc12f542e5}, + {0xf294b943e17a2bc4, 0x3e6f5b7b17b2939e}, + {0x979cf3ca6cec5b5a, 0xa705992ceecf9c43}, + {0xbd8430bd08277231, 0x50c6ff782a838354}, + {0xece53cec4a314ebd, 0xa4f8bf5635246429}, + {0x940f4613ae5ed136, 0x871b7795e136be9a}, + {0xb913179899f68584, 0x28e2557b59846e40}, + {0xe757dd7ec07426e5, 0x331aeada2fe589d0}, + {0x9096ea6f3848984f, 0x3ff0d2c85def7622}, + {0xb4bca50b065abe63, 0x0fed077a756b53aa}, + {0xe1ebce4dc7f16dfb, 0xd3e8495912c62895}, + {0x8d3360f09cf6e4bd, 0x64712dd7abbbd95d}, + {0xb080392cc4349dec, 0xbd8d794d96aacfb4}, + {0xdca04777f541c567, 0xecf0d7a0fc5583a1}, + {0x89e42caaf9491b60, 0xf41686c49db57245}, + {0xac5d37d5b79b6239, 0x311c2875c522ced6}, + {0xd77485cb25823ac7, 0x7d633293366b828c}, + {0x86a8d39ef77164bc, 0xae5dff9c02033198}, + {0xa8530886b54dbdeb, 0xd9f57f830283fdfd}, + {0xd267caa862a12d66, 0xd072df63c324fd7c}, + {0x8380dea93da4bc60, 0x4247cb9e59f71e6e}, + {0xa46116538d0deb78, 0x52d9be85f074e609}, + {0xcd795be870516656, 0x67902e276c921f8c}, + {0x806bd9714632dff6, 0x00ba1cd8a3db53b7}, + {0xa086cfcd97bf97f3, 0x80e8a40eccd228a5}, + {0xc8a883c0fdaf7df0, 0x6122cd128006b2ce}, + {0xfad2a4b13d1b5d6c, 0x796b805720085f82}, + {0x9cc3a6eec6311a63, 0xcbe3303674053bb1}, + {0xc3f490aa77bd60fc, 0xbedbfc4411068a9d}, + {0xf4f1b4d515acb93b, 0xee92fb5515482d45}, + {0x991711052d8bf3c5, 0x751bdd152d4d1c4b}, + {0xbf5cd54678eef0b6, 0xd262d45a78a0635e}, + {0xef340a98172aace4, 0x86fb897116c87c35}, + {0x9580869f0e7aac0e, 0xd45d35e6ae3d4da1}, + {0xbae0a846d2195712, 0x8974836059cca10a}, + {0xe998d258869facd7, 0x2bd1a438703fc94c}, + {0x91ff83775423cc06, 0x7b6306a34627ddd0}, + {0xb67f6455292cbf08, 0x1a3bc84c17b1d543}, + {0xe41f3d6a7377eeca, 0x20caba5f1d9e4a94}, + {0x8e938662882af53e, 0x547eb47b7282ee9d}, + {0xb23867fb2a35b28d, 0xe99e619a4f23aa44}, + {0xdec681f9f4c31f31, 0x6405fa00e2ec94d5}, + {0x8b3c113c38f9f37e, 0xde83bc408dd3dd05}, + {0xae0b158b4738705e, 0x9624ab50b148d446}, + {0xd98ddaee19068c76, 0x3badd624dd9b0958}, + {0x87f8a8d4cfa417c9, 0xe54ca5d70a80e5d7}, + {0xa9f6d30a038d1dbc, 0x5e9fcf4ccd211f4d}, + {0xd47487cc8470652b, 0x7647c32000696720}, + {0x84c8d4dfd2c63f3b, 0x29ecd9f40041e074}, + {0xa5fb0a17c777cf09, 0xf468107100525891}, + {0xcf79cc9db955c2cc, 0x7182148d4066eeb5}, + {0x81ac1fe293d599bf, 0xc6f14cd848405531}, + {0xa21727db38cb002f, 0xb8ada00e5a506a7d}, + {0xca9cf1d206fdc03b, 0xa6d90811f0e4851d}, + {0xfd442e4688bd304a, 0x908f4a166d1da664}, + {0x9e4a9cec15763e2e, 0x9a598e4e043287ff}, + {0xc5dd44271ad3cdba, 0x40eff1e1853f29fe}, + {0xf7549530e188c128, 0xd12bee59e68ef47d}, + {0x9a94dd3e8cf578b9, 0x82bb74f8301958cf}, + {0xc13a148e3032d6e7, 0xe36a52363c1faf02}, + {0xf18899b1bc3f8ca1, 0xdc44e6c3cb279ac2}, + {0x96f5600f15a7b7e5, 0x29ab103a5ef8c0ba}, + {0xbcb2b812db11a5de, 0x7415d448f6b6f0e8}, + {0xebdf661791d60f56, 0x111b495b3464ad22}, + {0x936b9fcebb25c995, 0xcab10dd900beec35}, + {0xb84687c269ef3bfb, 0x3d5d514f40eea743}, + {0xe65829b3046b0afa, 0x0cb4a5a3112a5113}, + {0x8ff71a0fe2c2e6dc, 0x47f0e785eaba72ac}, + {0xb3f4e093db73a093, 0x59ed216765690f57}, + {0xe0f218b8d25088b8, 0x306869c13ec3532d}, + {0x8c974f7383725573, 0x1e414218c73a13fc}, + {0xafbd2350644eeacf, 0xe5d1929ef90898fb}, + {0xdbac6c247d62a583, 0xdf45f746b74abf3a}, + {0x894bc396ce5da772, 0x6b8bba8c328eb784}, + {0xab9eb47c81f5114f, 0x066ea92f3f326565}, + {0xd686619ba27255a2, 0xc80a537b0efefebe}, + {0x8613fd0145877585, 0xbd06742ce95f5f37}, + {0xa798fc4196e952e7, 0x2c48113823b73705}, + {0xd17f3b51fca3a7a0, 0xf75a15862ca504c6}, + {0x82ef85133de648c4, 0x9a984d73dbe722fc}, + {0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebbb}, + {0xcc963fee10b7d1b3, 0x318df905079926a9}, + {0xffbbcfe994e5c61f, 0xfdf17746497f7053}, + {0x9fd561f1fd0f9bd3, 0xfeb6ea8bedefa634}, + {0xc7caba6e7c5382c8, 0xfe64a52ee96b8fc1}, + {0xf9bd690a1b68637b, 0x3dfdce7aa3c673b1}, + {0x9c1661a651213e2d, 0x06bea10ca65c084f}, + {0xc31bfa0fe5698db8, 0x486e494fcff30a63}, + {0xf3e2f893dec3f126, 0x5a89dba3c3efccfb}, + {0x986ddb5c6b3a76b7, 0xf89629465a75e01d}, + {0xbe89523386091465, 0xf6bbb397f1135824}, + {0xee2ba6c0678b597f, 0x746aa07ded582e2d}, + {0x94db483840b717ef, 0xa8c2a44eb4571cdd}, + {0xba121a4650e4ddeb, 0x92f34d62616ce414}, + {0xe896a0d7e51e1566, 0x77b020baf9c81d18}, + {0x915e2486ef32cd60, 0x0ace1474dc1d122f}, + {0xb5b5ada8aaff80b8, 0x0d819992132456bb}, + {0xe3231912d5bf60e6, 0x10e1fff697ed6c6a}, + {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2}, + {0xb1736b96b6fd83b3, 0xbd308ff8a6b17cb3}, + {0xddd0467c64bce4a0, 0xac7cb3f6d05ddbdf}, + {0x8aa22c0dbef60ee4, 0x6bcdf07a423aa96c}, + {0xad4ab7112eb3929d, 0x86c16c98d2c953c7}, + {0xd89d64d57a607744, 0xe871c7bf077ba8b8}, + {0x87625f056c7c4a8b, 0x11471cd764ad4973}, + {0xa93af6c6c79b5d2d, 0xd598e40d3dd89bd0}, + {0xd389b47879823479, 0x4aff1d108d4ec2c4}, + {0x843610cb4bf160cb, 0xcedf722a585139bb}, + {0xa54394fe1eedb8fe, 0xc2974eb4ee658829}, + {0xce947a3da6a9273e, 0x733d226229feea33}, + {0x811ccc668829b887, 0x0806357d5a3f5260}, + {0xa163ff802a3426a8, 0xca07c2dcb0cf26f8}, + {0xc9bcff6034c13052, 0xfc89b393dd02f0b6}, + {0xfc2c3f3841f17c67, 0xbbac2078d443ace3}, + {0x9d9ba7832936edc0, 0xd54b944b84aa4c0e}, + {0xc5029163f384a931, 0x0a9e795e65d4df12}, + {0xf64335bcf065d37d, 0x4d4617b5ff4a16d6}, + {0x99ea0196163fa42e, 0x504bced1bf8e4e46}, + {0xc06481fb9bcf8d39, 0xe45ec2862f71e1d7}, + {0xf07da27a82c37088, 0x5d767327bb4e5a4d}, + {0x964e858c91ba2655, 0x3a6a07f8d510f870}, + {0xbbe226efb628afea, 0x890489f70a55368c}, + {0xeadab0aba3b2dbe5, 0x2b45ac74ccea842f}, + {0x92c8ae6b464fc96f, 0x3b0b8bc90012929e}, + {0xb77ada0617e3bbcb, 0x09ce6ebb40173745}, + {0xe55990879ddcaabd, 0xcc420a6a101d0516}, + {0x8f57fa54c2a9eab6, 0x9fa946824a12232e}, + {0xb32df8e9f3546564, 0x47939822dc96abfa}, + {0xdff9772470297ebd, 0x59787e2b93bc56f8}, + {0x8bfbea76c619ef36, 0x57eb4edb3c55b65b}, + {0xaefae51477a06b03, 0xede622920b6b23f2}, + {0xdab99e59958885c4, 0xe95fab368e45ecee}, + {0x88b402f7fd75539b, 0x11dbcb0218ebb415}, + {0xaae103b5fcd2a881, 0xd652bdc29f26a11a}, + {0xd59944a37c0752a2, 0x4be76d3346f04960}, + {0x857fcae62d8493a5, 0x6f70a4400c562ddc}, + {0xa6dfbd9fb8e5b88e, 0xcb4ccd500f6bb953}, + {0xd097ad07a71f26b2, 0x7e2000a41346a7a8}, + {0x825ecc24c873782f, 0x8ed400668c0c28c9}, + {0xa2f67f2dfa90563b, 0x728900802f0f32fb}, + {0xcbb41ef979346bca, 0x4f2b40a03ad2ffba}, + {0xfea126b7d78186bc, 0xe2f610c84987bfa9}, + {0x9f24b832e6b0f436, 0x0dd9ca7d2df4d7ca}, + {0xc6ede63fa05d3143, 0x91503d1c79720dbc}, + {0xf8a95fcf88747d94, 0x75a44c6397ce912b}, + {0x9b69dbe1b548ce7c, 0xc986afbe3ee11abb}, + {0xc24452da229b021b, 0xfbe85badce996169}, + {0xf2d56790ab41c2a2, 0xfae27299423fb9c4}, + {0x97c560ba6b0919a5, 0xdccd879fc967d41b}, + {0xbdb6b8e905cb600f, 0x5400e987bbc1c921}, + {0xed246723473e3813, 0x290123e9aab23b69}, + {0x9436c0760c86e30b, 0xf9a0b6720aaf6522}, + {0xb94470938fa89bce, 0xf808e40e8d5b3e6a}, + {0xe7958cb87392c2c2, 0xb60b1d1230b20e05}, + {0x90bd77f3483bb9b9, 0xb1c6f22b5e6f48c3}, + {0xb4ecd5f01a4aa828, 0x1e38aeb6360b1af4}, + {0xe2280b6c20dd5232, 0x25c6da63c38de1b1}, + {0x8d590723948a535f, 0x579c487e5a38ad0f}, + {0xb0af48ec79ace837, 0x2d835a9df0c6d852}, + {0xdcdb1b2798182244, 0xf8e431456cf88e66}, + {0x8a08f0f8bf0f156b, 0x1b8e9ecb641b5900}, + {0xac8b2d36eed2dac5, 0xe272467e3d222f40}, + {0xd7adf884aa879177, 0x5b0ed81dcc6abb10}, + {0x86ccbb52ea94baea, 0x98e947129fc2b4ea}, + {0xa87fea27a539e9a5, 0x3f2398d747b36225}, + {0xd29fe4b18e88640e, 0x8eec7f0d19a03aae}, + {0x83a3eeeef9153e89, 0x1953cf68300424ad}, + {0xa48ceaaab75a8e2b, 0x5fa8c3423c052dd8}, + {0xcdb02555653131b6, 0x3792f412cb06794e}, + {0x808e17555f3ebf11, 0xe2bbd88bbee40bd1}, + {0xa0b19d2ab70e6ed6, 0x5b6aceaeae9d0ec5}, + {0xc8de047564d20a8b, 0xf245825a5a445276}, + {0xfb158592be068d2e, 0xeed6e2f0f0d56713}, + {0x9ced737bb6c4183d, 0x55464dd69685606c}, + {0xc428d05aa4751e4c, 0xaa97e14c3c26b887}, + {0xf53304714d9265df, 0xd53dd99f4b3066a9}, + {0x993fe2c6d07b7fab, 0xe546a8038efe402a}, + {0xbf8fdb78849a5f96, 0xde98520472bdd034}, + {0xef73d256a5c0f77c, 0x963e66858f6d4441}, + {0x95a8637627989aad, 0xdde7001379a44aa9}, + {0xbb127c53b17ec159, 0x5560c018580d5d53}, + {0xe9d71b689dde71af, 0xaab8f01e6e10b4a7}, + {0x9226712162ab070d, 0xcab3961304ca70e9}, + {0xb6b00d69bb55c8d1, 0x3d607b97c5fd0d23}, + {0xe45c10c42a2b3b05, 0x8cb89a7db77c506b}, + {0x8eb98a7a9a5b04e3, 0x77f3608e92adb243}, + {0xb267ed1940f1c61c, 0x55f038b237591ed4}, + {0xdf01e85f912e37a3, 0x6b6c46dec52f6689}, + {0x8b61313bbabce2c6, 0x2323ac4b3b3da016}, + {0xae397d8aa96c1b77, 0xabec975e0a0d081b}, + {0xd9c7dced53c72255, 0x96e7bd358c904a22}, + {0x881cea14545c7575, 0x7e50d64177da2e55}, + {0xaa242499697392d2, 0xdde50bd1d5d0b9ea}, + {0xd4ad2dbfc3d07787, 0x955e4ec64b44e865}, + {0x84ec3c97da624ab4, 0xbd5af13bef0b113f}, + {0xa6274bbdd0fadd61, 0xecb1ad8aeacdd58f}, + {0xcfb11ead453994ba, 0x67de18eda5814af3}, + {0x81ceb32c4b43fcf4, 0x80eacf948770ced8}, + {0xa2425ff75e14fc31, 0xa1258379a94d028e}, + {0xcad2f7f5359a3b3e, 0x096ee45813a04331}, + {0xfd87b5f28300ca0d, 0x8bca9d6e188853fd}, + {0x9e74d1b791e07e48, 0x775ea264cf55347e}, + {0xc612062576589dda, 0x95364afe032a819e}, + {0xf79687aed3eec551, 0x3a83ddbd83f52205}, + {0x9abe14cd44753b52, 0xc4926a9672793543}, + {0xc16d9a0095928a27, 0x75b7053c0f178294}, + {0xf1c90080baf72cb1, 0x5324c68b12dd6339}, + {0x971da05074da7bee, 0xd3f6fc16ebca5e04}, + {0xbce5086492111aea, 0x88f4bb1ca6bcf585}, + {0xec1e4a7db69561a5, 0x2b31e9e3d06c32e6}, + {0x9392ee8e921d5d07, 0x3aff322e62439fd0}, + {0xb877aa3236a4b449, 0x09befeb9fad487c3}, + {0xe69594bec44de15b, 0x4c2ebe687989a9b4}, + {0x901d7cf73ab0acd9, 0x0f9d37014bf60a11}, + {0xb424dc35095cd80f, 0x538484c19ef38c95}, + {0xe12e13424bb40e13, 0x2865a5f206b06fba}, + {0x8cbccc096f5088cb, 0xf93f87b7442e45d4}, + {0xafebff0bcb24aafe, 0xf78f69a51539d749}, + {0xdbe6fecebdedd5be, 0xb573440e5a884d1c}, + {0x89705f4136b4a597, 0x31680a88f8953031}, + {0xabcc77118461cefc, 0xfdc20d2b36ba7c3e}, + {0xd6bf94d5e57a42bc, 0x3d32907604691b4d}, + {0x8637bd05af6c69b5, 0xa63f9a49c2c1b110}, + {0xa7c5ac471b478423, 0x0fcf80dc33721d54}, + {0xd1b71758e219652b, 0xd3c36113404ea4a9}, + {0x83126e978d4fdf3b, 0x645a1cac083126ea}, + {0xa3d70a3d70a3d70a, 0x3d70a3d70a3d70a4}, + {0xcccccccccccccccc, 0xcccccccccccccccd}, + {0x8000000000000000, 0x0000000000000000}, + {0xa000000000000000, 0x0000000000000000}, + {0xc800000000000000, 0x0000000000000000}, + {0xfa00000000000000, 0x0000000000000000}, + {0x9c40000000000000, 0x0000000000000000}, + {0xc350000000000000, 0x0000000000000000}, + {0xf424000000000000, 0x0000000000000000}, + {0x9896800000000000, 0x0000000000000000}, + {0xbebc200000000000, 0x0000000000000000}, + {0xee6b280000000000, 0x0000000000000000}, + {0x9502f90000000000, 0x0000000000000000}, + {0xba43b74000000000, 0x0000000000000000}, + {0xe8d4a51000000000, 0x0000000000000000}, + {0x9184e72a00000000, 0x0000000000000000}, + {0xb5e620f480000000, 0x0000000000000000}, + {0xe35fa931a0000000, 0x0000000000000000}, + {0x8e1bc9bf04000000, 0x0000000000000000}, + {0xb1a2bc2ec5000000, 0x0000000000000000}, + {0xde0b6b3a76400000, 0x0000000000000000}, + {0x8ac7230489e80000, 0x0000000000000000}, + {0xad78ebc5ac620000, 0x0000000000000000}, + {0xd8d726b7177a8000, 0x0000000000000000}, + {0x878678326eac9000, 0x0000000000000000}, + {0xa968163f0a57b400, 0x0000000000000000}, + {0xd3c21bcecceda100, 0x0000000000000000}, + {0x84595161401484a0, 0x0000000000000000}, + {0xa56fa5b99019a5c8, 0x0000000000000000}, + {0xcecb8f27f4200f3a, 0x0000000000000000}, + {0x813f3978f8940984, 0x4000000000000000}, + {0xa18f07d736b90be5, 0x5000000000000000}, + {0xc9f2c9cd04674ede, 0xa400000000000000}, + {0xfc6f7c4045812296, 0x4d00000000000000}, + {0x9dc5ada82b70b59d, 0xf020000000000000}, + {0xc5371912364ce305, 0x6c28000000000000}, + {0xf684df56c3e01bc6, 0xc732000000000000}, + {0x9a130b963a6c115c, 0x3c7f400000000000}, + {0xc097ce7bc90715b3, 0x4b9f100000000000}, + {0xf0bdc21abb48db20, 0x1e86d40000000000}, + {0x96769950b50d88f4, 0x1314448000000000}, + {0xbc143fa4e250eb31, 0x17d955a000000000}, + {0xeb194f8e1ae525fd, 0x5dcfab0800000000}, + {0x92efd1b8d0cf37be, 0x5aa1cae500000000}, + {0xb7abc627050305ad, 0xf14a3d9e40000000}, + {0xe596b7b0c643c719, 0x6d9ccd05d0000000}, + {0x8f7e32ce7bea5c6f, 0xe4820023a2000000}, + {0xb35dbf821ae4f38b, 0xdda2802c8a800000}, + {0xe0352f62a19e306e, 0xd50b2037ad200000}, + {0x8c213d9da502de45, 0x4526f422cc340000}, + {0xaf298d050e4395d6, 0x9670b12b7f410000}, + {0xdaf3f04651d47b4c, 0x3c0cdd765f114000}, + {0x88d8762bf324cd0f, 0xa5880a69fb6ac800}, + {0xab0e93b6efee0053, 0x8eea0d047a457a00}, + {0xd5d238a4abe98068, 0x72a4904598d6d880}, + {0x85a36366eb71f041, 0x47a6da2b7f864750}, + {0xa70c3c40a64e6c51, 0x999090b65f67d924}, + {0xd0cf4b50cfe20765, 0xfff4b4e3f741cf6d}, + {0x82818f1281ed449f, 0xbff8f10e7a8921a4}, + {0xa321f2d7226895c7, 0xaff72d52192b6a0d}, + {0xcbea6f8ceb02bb39, 0x9bf4f8a69f764490}, + {0xfee50b7025c36a08, 0x02f236d04753d5b4}, + {0x9f4f2726179a2245, 0x01d762422c946590}, + {0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef5}, + {0xf8ebad2b84e0d58b, 0xd2e0898765a7deb2}, + {0x9b934c3b330c8577, 0x63cc55f49f88eb2f}, + {0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fb}, + {0xf316271c7fc3908a, 0x8bef464e3945ef7a}, + {0x97edd871cfda3a56, 0x97758bf0e3cbb5ac}, + {0xbde94e8e43d0c8ec, 0x3d52eeed1cbea317}, + {0xed63a231d4c4fb27, 0x4ca7aaa863ee4bdd}, + {0x945e455f24fb1cf8, 0x8fe8caa93e74ef6a}, + {0xb975d6b6ee39e436, 0xb3e2fd538e122b44}, + {0xe7d34c64a9c85d44, 0x60dbbca87196b616}, + {0x90e40fbeea1d3a4a, 0xbc8955e946fe31cd}, + {0xb51d13aea4a488dd, 0x6babab6398bdbe41}, + {0xe264589a4dcdab14, 0xc696963c7eed2dd1}, + {0x8d7eb76070a08aec, 0xfc1e1de5cf543ca2}, + {0xb0de65388cc8ada8, 0x3b25a55f43294bcb}, + {0xdd15fe86affad912, 0x49ef0eb713f39ebe}, + {0x8a2dbf142dfcc7ab, 0x6e3569326c784337}, + {0xacb92ed9397bf996, 0x49c2c37f07965404}, + {0xd7e77a8f87daf7fb, 0xdc33745ec97be906}, + {0x86f0ac99b4e8dafd, 0x69a028bb3ded71a3}, + {0xa8acd7c0222311bc, 0xc40832ea0d68ce0c}, + {0xd2d80db02aabd62b, 0xf50a3fa490c30190}, + {0x83c7088e1aab65db, 0x792667c6da79e0fa}, + {0xa4b8cab1a1563f52, 0x577001b891185938}, + {0xcde6fd5e09abcf26, 0xed4c0226b55e6f86}, + {0x80b05e5ac60b6178, 0x544f8158315b05b4}, + {0xa0dc75f1778e39d6, 0x696361ae3db1c721}, + {0xc913936dd571c84c, 0x03bc3a19cd1e38e9}, + {0xfb5878494ace3a5f, 0x04ab48a04065c723}, + {0x9d174b2dcec0e47b, 0x62eb0d64283f9c76}, + {0xc45d1df942711d9a, 0x3ba5d0bd324f8394}, + {0xf5746577930d6500, 0xca8f44ec7ee36479}, + {0x9968bf6abbe85f20, 0x7e998b13cf4e1ecb}, + {0xbfc2ef456ae276e8, 0x9e3fedd8c321a67e}, + {0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101e}, + {0x95d04aee3b80ece5, 0xbba1f1d158724a12}, + {0xbb445da9ca61281f, 0x2a8a6e45ae8edc97}, + {0xea1575143cf97226, 0xf52d09d71a3293bd}, + {0x924d692ca61be758, 0x593c2626705f9c56}, + {0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836c}, + {0xe498f455c38b997a, 0x0b6dfb9c0f956447}, + {0x8edf98b59a373fec, 0x4724bd4189bd5eac}, + {0xb2977ee300c50fe7, 0x58edec91ec2cb657}, + {0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ed}, + {0x8b865b215899f46c, 0xbd79e0d20082ee74}, + {0xae67f1e9aec07187, 0xecd8590680a3aa11}, + {0xda01ee641a708de9, 0xe80e6f4820cc9495}, + {0x884134fe908658b2, 0x3109058d147fdcdd}, + {0xaa51823e34a7eede, 0xbd4b46f0599fd415}, + {0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91a}, + {0x850fadc09923329e, 0x03e2cf6bc604ddb0}, + {0xa6539930bf6bff45, 0x84db8346b786151c}, + {0xcfe87f7cef46ff16, 0xe612641865679a63}, + {0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07e}, + {0xa26da3999aef7749, 0xe3be5e330f38f09d}, + {0xcb090c8001ab551c, 0x5cadf5bfd3072cc5}, + {0xfdcb4fa002162a63, 0x73d9732fc7c8f7f6}, + {0x9e9f11c4014dda7e, 0x2867e7fddcdd9afa}, + {0xc646d63501a1511d, 0xb281e1fd541501b8}, + {0xf7d88bc24209a565, 0x1f225a7ca91a4226}, + {0x9ae757596946075f, 0x3375788de9b06958}, + {0xc1a12d2fc3978937, 0x0052d6b1641c83ae}, + {0xf209787bb47d6b84, 0xc0678c5dbd23a49a}, + {0x9745eb4d50ce6332, 0xf840b7ba963646e0}, + {0xbd176620a501fbff, 0xb650e5a93bc3d898}, + {0xec5d3fa8ce427aff, 0xa3e51f138ab4cebe}, + {0x93ba47c980e98cdf, 0xc66f336c36b10137}, + {0xb8a8d9bbe123f017, 0xb80b0047445d4184}, + {0xe6d3102ad96cec1d, 0xa60dc059157491e5}, + {0x9043ea1ac7e41392, 0x87c89837ad68db2f}, + {0xb454e4a179dd1877, 0x29babe4598c311fb}, + {0xe16a1dc9d8545e94, 0xf4296dd6fef3d67a}, + {0x8ce2529e2734bb1d, 0x1899e4a65f58660c}, + {0xb01ae745b101e9e4, 0x5ec05dcff72e7f8f}, + {0xdc21a1171d42645d, 0x76707543f4fa1f73}, + {0x899504ae72497eba, 0x6a06494a791c53a8}, + {0xabfa45da0edbde69, 0x0487db9d17636892}, + {0xd6f8d7509292d603, 0x45a9d2845d3c42b6}, + {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b2}, + {0xa7f26836f282b732, 0x8e6cac7768d7141e}, + {0xd1ef0244af2364ff, 0x3207d795430cd926}, + {0x8335616aed761f1f, 0x7f44e6bd49e807b8}, + {0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a6}, + {0xcd036837130890a1, 0x36dba887c37a8c0f}, + {0x802221226be55a64, 0xc2494954da2c9789}, + {0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6c}, + {0xc83553c5c8965d3d, 0x6f92829494e5acc7}, + {0xfa42a8b73abbf48c, 0xcb772339ba1f17f9}, + {0x9c69a97284b578d7, 0xff2a760414536efb}, + {0xc38413cf25e2d70d, 0xfef5138519684aba}, + {0xf46518c2ef5b8cd1, 0x7eb258665fc25d69}, + {0x98bf2f79d5993802, 0xef2f773ffbd97a61}, + {0xbeeefb584aff8603, 0xaafb550ffacfd8fa}, + {0xeeaaba2e5dbf6784, 0x95ba2a53f983cf38}, + {0x952ab45cfa97a0b2, 0xdd945a747bf26183}, + {0xba756174393d88df, 0x94f971119aeef9e4}, + {0xe912b9d1478ceb17, 0x7a37cd5601aab85d}, + {0x91abb422ccb812ee, 0xac62e055c10ab33a}, + {0xb616a12b7fe617aa, 0x577b986b314d6009}, + {0xe39c49765fdf9d94, 0xed5a7e85fda0b80b}, + {0x8e41ade9fbebc27d, 0x14588f13be847307}, + {0xb1d219647ae6b31c, 0x596eb2d8ae258fc8}, + {0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bb}, + {0x8aec23d680043bee, 0x25de7bb9480d5854}, + {0xada72ccc20054ae9, 0xaf561aa79a10ae6a}, + {0xd910f7ff28069da4, 0x1b2ba1518094da04}, + {0x87aa9aff79042286, 0x90fb44d2f05d0842}, + {0xa99541bf57452b28, 0x353a1607ac744a53}, + {0xd3fa922f2d1675f2, 0x42889b8997915ce8}, + {0x847c9b5d7c2e09b7, 0x69956135febada11}, + {0xa59bc234db398c25, 0x43fab9837e699095}, + {0xcf02b2c21207ef2e, 0x94f967e45e03f4bb}, + {0x8161afb94b44f57d, 0x1d1be0eebac278f5}, + {0xa1ba1ba79e1632dc, 0x6462d92a69731732}, + {0xca28a291859bbf93, 0x7d7b8f7503cfdcfe}, + {0xfcb2cb35e702af78, 0x5cda735244c3d43e}, + {0x9defbf01b061adab, 0x3a0888136afa64a7}, + {0xc56baec21c7a1916, 0x088aaa1845b8fdd0}, + {0xf6c69a72a3989f5b, 0x8aad549e57273d45}, + {0x9a3c2087a63f6399, 0x36ac54e2f678864b}, + {0xc0cb28a98fcf3c7f, 0x84576a1bb416a7dd}, + {0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d5}, + {0x969eb7c47859e743, 0x9f644ae5a4b1b325}, + {0xbc4665b596706114, 0x873d5d9f0dde1fee}, + {0xeb57ff22fc0c7959, 0xa90cb506d155a7ea}, + {0x9316ff75dd87cbd8, 0x09a7f12442d588f2}, + {0xb7dcbf5354e9bece, 0x0c11ed6d538aeb2f}, + {0xe5d3ef282a242e81, 0x8f1668c8a86da5fa}, + {0x8fa475791a569d10, 0xf96e017d694487bc}, + {0xb38d92d760ec4455, 0x37c981dcc395a9ac}, + {0xe070f78d3927556a, 0x85bbe253f47b1417}, + {0x8c469ab843b89562, 0x93956d7478ccec8e}, + {0xaf58416654a6babb, 0x387ac8d1970027b2}, + {0xdb2e51bfe9d0696a, 0x06997b05fcc0319e}, + {0x88fcf317f22241e2, 0x441fece3bdf81f03}, + {0xab3c2fddeeaad25a, 0xd527e81cad7626c3}, + {0xd60b3bd56a5586f1, 0x8a71e223d8d3b074}, + {0x85c7056562757456, 0xf6872d5667844e49}, + {0xa738c6bebb12d16c, 0xb428f8ac016561db}, + {0xd106f86e69d785c7, 0xe13336d701beba52}, + {0x82a45b450226b39c, 0xecc0024661173473}, + {0xa34d721642b06084, 0x27f002d7f95d0190}, + {0xcc20ce9bd35c78a5, 0x31ec038df7b441f4}, + {0xff290242c83396ce, 0x7e67047175a15271}, + {0x9f79a169bd203e41, 0x0f0062c6e984d386}, + {0xc75809c42c684dd1, 0x52c07b78a3e60868}, + {0xf92e0c3537826145, 0xa7709a56ccdf8a82}, + {0x9bbcc7a142b17ccb, 0x88a66076400bb691}, + {0xc2abf989935ddbfe, 0x6acff893d00ea435}, + {0xf356f7ebf83552fe, 0x0583f6b8c4124d43}, + {0x98165af37b2153de, 0xc3727a337a8b704a}, + {0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5c}, + {0xeda2ee1c7064130c, 0x1162def06f79df73}, + {0x9485d4d1c63e8be7, 0x8addcb5645ac2ba8}, + {0xb9a74a0637ce2ee1, 0x6d953e2bd7173692}, + {0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0437}, + {0x910ab1d4db9914a0, 0x1d9c9892400a22a2}, + {0xb54d5e4a127f59c8, 0x2503beb6d00cab4b}, + {0xe2a0b5dc971f303a, 0x2e44ae64840fd61d}, + {0x8da471a9de737e24, 0x5ceaecfed289e5d2}, + {0xb10d8e1456105dad, 0x7425a83e872c5f47}, + {0xdd50f1996b947518, 0xd12f124e28f77719}, + {0x8a5296ffe33cc92f, 0x82bd6b70d99aaa6f}, + {0xace73cbfdc0bfb7b, 0x636cc64d1001550b}, + {0xd8210befd30efa5a, 0x3c47f7e05401aa4e}, + {0x8714a775e3e95c78, 0x65acfaec34810a71}, + {0xa8d9d1535ce3b396, 0x7f1839a741a14d0d}, + {0xd31045a8341ca07c, 0x1ede48111209a050}, + {0x83ea2b892091e44d, 0x934aed0aab460432}, + {0xa4e4b66b68b65d60, 0xf81da84d5617853f}, + {0xce1de40642e3f4b9, 0x36251260ab9d668e}, + {0x80d2ae83e9ce78f3, 0xc1d72b7c6b426019}, + {0xa1075a24e4421730, 0xb24cf65b8612f81f}, + {0xc94930ae1d529cfc, 0xdee033f26797b627}, + {0xfb9b7cd9a4a7443c, 0x169840ef017da3b1}, + {0x9d412e0806e88aa5, 0x8e1f289560ee864e}, + {0xc491798a08a2ad4e, 0xf1a6f2bab92a27e2}, + {0xf5b5d7ec8acb58a2, 0xae10af696774b1db}, + {0x9991a6f3d6bf1765, 0xacca6da1e0a8ef29}, + {0xbff610b0cc6edd3f, 0x17fd090a58d32af3}, + {0xeff394dcff8a948e, 0xddfc4b4cef07f5b0}, + {0x95f83d0a1fb69cd9, 0x4abdaf101564f98e}, + {0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f1}, + {0xea53df5fd18d5513, 0x84c86189216dc5ed}, + {0x92746b9be2f8552c, 0x32fd3cf5b4e49bb4}, + {0xb7118682dbb66a77, 0x3fbc8c33221dc2a1}, + {0xe4d5e82392a40515, 0x0fabaf3feaa5334a}, + {0x8f05b1163ba6832d, 0x29cb4d87f2a7400e}, + {0xb2c71d5bca9023f8, 0x743e20e9ef511012}, + {0xdf78e4b2bd342cf6, 0x914da9246b255416}, + {0x8bab8eefb6409c1a, 0x1ad089b6c2f7548e}, + {0xae9672aba3d0c320, 0xa184ac2473b529b1}, + {0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741e}, + {0x8865899617fb1871, 0x7e2fa67c7a658892}, + {0xaa7eebfb9df9de8d, 0xddbb901b98feeab7}, + {0xd51ea6fa85785631, 0x552a74227f3ea565}, + {0x8533285c936b35de, 0xd53a88958f87275f}, + {0xa67ff273b8460356, 0x8a892abaf368f137}, + {0xd01fef10a657842c, 0x2d2b7569b0432d85}, + {0x8213f56a67f6b29b, 0x9c3b29620e29fc73}, + {0xa298f2c501f45f42, 0x8349f3ba91b47b8f}, + {0xcb3f2f7642717713, 0x241c70a936219a73}, + {0xfe0efb53d30dd4d7, 0xed238cd383aa0110}, + {0x9ec95d1463e8a506, 0xf4363804324a40aa}, + {0xc67bb4597ce2ce48, 0xb143c6053edcd0d5}, + {0xf81aa16fdc1b81da, 0xdd94b7868e94050a}, + {0x9b10a4e5e9913128, 0xca7cf2b4191c8326}, + {0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f0}, + {0xf24a01a73cf2dccf, 0xbc633b39673c8cec}, + {0x976e41088617ca01, 0xd5be0503e085d813}, + {0xbd49d14aa79dbc82, 0x4b2d8644d8a74e18}, + {0xec9c459d51852ba2, 0xddf8e7d60ed1219e}, + {0x93e1ab8252f33b45, 0xcabb90e5c942b503}, + {0xb8da1662e7b00a17, 0x3d6a751f3b936243}, + {0xe7109bfba19c0c9d, 0x0cc512670a783ad4}, + {0x906a617d450187e2, 0x27fb2b80668b24c5}, + {0xb484f9dc9641e9da, 0xb1f9f660802dedf6}, + {0xe1a63853bbd26451, 0x5e7873f8a0396973}, + {0x8d07e33455637eb2, 0xdb0b487b6423e1e8}, + {0xb049dc016abc5e5f, 0x91ce1a9a3d2cda62}, + {0xdc5c5301c56b75f7, 0x7641a140cc7810fb}, + {0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9d}, + {0xac2820d9623bf429, 0x546345fa9fbdcd44}, + {0xd732290fbacaf133, 0xa97c177947ad4095}, + {0x867f59a9d4bed6c0, 0x49ed8eabcccc485d}, + {0xa81f301449ee8c70, 0x5c68f256bfff5a74}, + {0xd226fc195c6a2f8c, 0x73832eec6fff3111}, + {0x83585d8fd9c25db7, 0xc831fd53c5ff7eab}, + {0xa42e74f3d032f525, 0xba3e7ca8b77f5e55}, + {0xcd3a1230c43fb26f, 0x28ce1bd2e55f35eb}, + {0x80444b5e7aa7cf85, 0x7980d163cf5b81b3}, + {0xa0555e361951c366, 0xd7e105bcc332621f}, + {0xc86ab5c39fa63440, 0x8dd9472bf3fefaa7}, + {0xfa856334878fc150, 0xb14f98f6f0feb951}, + {0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d3}, + {0xc3b8358109e84f07, 0x0a862f80ec4700c8}, + {0xf4a642e14c6262c8, 0xcd27bb612758c0fa}, + {0x98e7e9cccfbd7dbd, 0x8038d51cb897789c}, + {0xbf21e44003acdd2c, 0xe0470a63e6bd56c3}, + {0xeeea5d5004981478, 0x1858ccfce06cac74}, + {0x95527a5202df0ccb, 0x0f37801e0c43ebc8}, + {0xbaa718e68396cffd, 0xd30560258f54e6ba}, + {0xe950df20247c83fd, 0x47c6b82ef32a2069}, + {0x91d28b7416cdd27e, 0x4cdc331d57fa5441}, + {0xb6472e511c81471d, 0xe0133fe4adf8e952}, + {0xe3d8f9e563a198e5, 0x58180fddd97723a6}, + {0x8e679c2f5e44ff8f, 0x570f09eaa7ea7648}, + {0xb201833b35d63f73, 0x2cd2cc6551e513da}, + {0xde81e40a034bcf4f, 0xf8077f7ea65e58d1}, + {0x8b112e86420f6191, 0xfb04afaf27faf782}, + {0xadd57a27d29339f6, 0x79c5db9af1f9b563}, + {0xd94ad8b1c7380874, 0x18375281ae7822bc}, + {0x87cec76f1c830548, 0x8f2293910d0b15b5}, + {0xa9c2794ae3a3c69a, 0xb2eb3875504ddb22}, + {0xd433179d9c8cb841, 0x5fa60692a46151eb}, + {0x849feec281d7f328, 0xdbc7c41ba6bcd333}, + {0xa5c7ea73224deff3, 0x12b9b522906c0800}, + {0xcf39e50feae16bef, 0xd768226b34870a00}, + {0x81842f29f2cce375, 0xe6a1158300d46640}, + {0xa1e53af46f801c53, 0x60495ae3c1097fd0}, + {0xca5e89b18b602368, 0x385bb19cb14bdfc4}, + {0xfcf62c1dee382c42, 0x46729e03dd9ed7b5}, + {0x9e19db92b4e31ba9, 0x6c07a2c26a8346d1}, + {0xc5a05277621be293, 0xc7098b7305241885}, + { 0xf70867153aa2db38, + 0xb8cbee4fc66d1ea7 } +#else + {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b}, + {0xce5d73ff402d98e3, 0xfb0a3d212dc81290}, + {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f}, + {0x86a8d39ef77164bc, 0xae5dff9c02033198}, + {0xd98ddaee19068c76, 0x3badd624dd9b0958}, + {0xafbd2350644eeacf, 0xe5d1929ef90898fb}, + {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2}, + {0xe55990879ddcaabd, 0xcc420a6a101d0516}, + {0xb94470938fa89bce, 0xf808e40e8d5b3e6a}, + {0x95a8637627989aad, 0xdde7001379a44aa9}, + {0xf1c90080baf72cb1, 0x5324c68b12dd6339}, + {0xc350000000000000, 0x0000000000000000}, + {0x9dc5ada82b70b59d, 0xf020000000000000}, + {0xfee50b7025c36a08, 0x02f236d04753d5b4}, + {0xcde6fd5e09abcf26, 0xed4c0226b55e6f86}, + {0xa6539930bf6bff45, 0x84db8346b786151c}, + {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b2}, + {0xd910f7ff28069da4, 0x1b2ba1518094da04}, + {0xaf58416654a6babb, 0x387ac8d1970027b2}, + {0x8da471a9de737e24, 0x5ceaecfed289e5d2}, + {0xe4d5e82392a40515, 0x0fabaf3feaa5334a}, + {0xb8da1662e7b00a17, 0x3d6a751f3b936243}, + { 0x95527a5202df0ccb, + 0x0f37801e0c43ebc8 } +#endif + }; + +#if FMT_USE_FULL_CACHE_DRAGONBOX + return pow10_significands[k - float_info<double>::min_k]; +#else + static constexpr const uint64_t powers_of_5_64[] = { + 0x0000000000000001, 0x0000000000000005, 0x0000000000000019, + 0x000000000000007d, 0x0000000000000271, 0x0000000000000c35, + 0x0000000000003d09, 0x000000000001312d, 0x000000000005f5e1, + 0x00000000001dcd65, 0x00000000009502f9, 0x0000000002e90edd, + 0x000000000e8d4a51, 0x0000000048c27395, 0x000000016bcc41e9, + 0x000000071afd498d, 0x0000002386f26fc1, 0x000000b1a2bc2ec5, + 0x000003782dace9d9, 0x00001158e460913d, 0x000056bc75e2d631, + 0x0001b1ae4d6e2ef5, 0x000878678326eac9, 0x002a5a058fc295ed, + 0x00d3c21bcecceda1, 0x0422ca8b0a00a425, 0x14adf4b7320334b9}; + + static constexpr const uint32_t pow10_recovery_errors[] = { + 0x50001400, 0x54044100, 0x54014555, 0x55954415, 0x54115555, 0x00000001, + 0x50000000, 0x00104000, 0x54010004, 0x05004001, 0x55555544, 0x41545555, + 0x54040551, 0x15445545, 0x51555514, 0x10000015, 0x00101100, 0x01100015, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04450514, 0x45414110, + 0x55555145, 0x50544050, 0x15040155, 0x11054140, 0x50111514, 0x11451454, + 0x00400541, 0x00000000, 0x55555450, 0x10056551, 0x10054011, 0x55551014, + 0x69514555, 0x05151109, 0x00155555}; + + static const int compression_ratio = 27; + + // Compute base index. + int cache_index = (k - float_info<double>::min_k) / compression_ratio; + int kb = cache_index * compression_ratio + float_info<double>::min_k; + int offset = k - kb; + + // Get base cache. + uint128_wrapper base_cache = pow10_significands[cache_index]; + if (offset == 0) return base_cache; + + // Compute the required amount of bit-shift. + int alpha = floor_log2_pow10(kb + offset) - floor_log2_pow10(kb) - offset; + FMT_ASSERT(alpha > 0 && alpha < 64, "shifting error detected"); + + // Try to recover the real cache. + uint64_t pow5 = powers_of_5_64[offset]; + uint128_wrapper recovered_cache = umul128(base_cache.high(), pow5); + uint128_wrapper middle_low = + umul128(base_cache.low() - (kb < 0 ? 1u : 0u), pow5); + + recovered_cache += middle_low.high(); + + uint64_t high_to_middle = recovered_cache.high() << (64 - alpha); + uint64_t middle_to_low = recovered_cache.low() << (64 - alpha); + + recovered_cache = + uint128_wrapper{(recovered_cache.low() >> alpha) | high_to_middle, + ((middle_low.low() >> alpha) | middle_to_low)}; + + if (kb < 0) recovered_cache += 1; + + // Get error. + int error_idx = (k - float_info<double>::min_k) / 16; + uint32_t error = (pow10_recovery_errors[error_idx] >> + ((k - float_info<double>::min_k) % 16) * 2) & + 0x3; + + // Add the error back. + FMT_ASSERT(recovered_cache.low() + error >= recovered_cache.low(), ""); + return {recovered_cache.high(), recovered_cache.low() + error}; +#endif + } + + static carrier_uint compute_mul(carrier_uint u, + const cache_entry_type& cache) FMT_NOEXCEPT { + return umul192_upper64(u, cache); + } + + static uint32_t compute_delta(cache_entry_type const& cache, + int beta_minus_1) FMT_NOEXCEPT { + return static_cast<uint32_t>(cache.high() >> (64 - 1 - beta_minus_1)); + } + + static bool compute_mul_parity(carrier_uint two_f, + const cache_entry_type& cache, + int beta_minus_1) FMT_NOEXCEPT { + FMT_ASSERT(beta_minus_1 >= 1, ""); + FMT_ASSERT(beta_minus_1 < 64, ""); + + return ((umul192_middle64(two_f, cache) >> (64 - beta_minus_1)) & 1) != 0; + } + + static carrier_uint compute_left_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT { + return (cache.high() - + (cache.high() >> (float_info<double>::significand_bits + 2))) >> + (64 - float_info<double>::significand_bits - 1 - beta_minus_1); + } + + static carrier_uint compute_right_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT { + return (cache.high() + + (cache.high() >> (float_info<double>::significand_bits + 1))) >> + (64 - float_info<double>::significand_bits - 1 - beta_minus_1); + } + + static carrier_uint compute_round_up_for_shorter_interval_case( + const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT { + return ((cache.high() >> + (64 - float_info<double>::significand_bits - 2 - beta_minus_1)) + + 1) / + 2; + } +}; + +// Various integer checks +template <class T> +bool is_left_endpoint_integer_shorter_interval(int exponent) FMT_NOEXCEPT { + return exponent >= + float_info< + T>::case_shorter_interval_left_endpoint_lower_threshold && + exponent <= + float_info<T>::case_shorter_interval_left_endpoint_upper_threshold; +} +template <class T> +bool is_endpoint_integer(typename float_info<T>::carrier_uint two_f, + int exponent, int minus_k) FMT_NOEXCEPT { + if (exponent < float_info<T>::case_fc_pm_half_lower_threshold) return false; + // For k >= 0. + if (exponent <= float_info<T>::case_fc_pm_half_upper_threshold) return true; + // For k < 0. + if (exponent > float_info<T>::divisibility_check_by_5_threshold) return false; + return divisible_by_power_of_5(two_f, minus_k); +} + +template <class T> +bool is_center_integer(typename float_info<T>::carrier_uint two_f, int exponent, + int minus_k) FMT_NOEXCEPT { + // Exponent for 5 is negative. + if (exponent > float_info<T>::divisibility_check_by_5_threshold) return false; + if (exponent > float_info<T>::case_fc_upper_threshold) + return divisible_by_power_of_5(two_f, minus_k); + // Both exponents are nonnegative. + if (exponent >= float_info<T>::case_fc_lower_threshold) return true; + // Exponent for 2 is negative. + return divisible_by_power_of_2(two_f, minus_k - exponent + 1); +} + +// Remove trailing zeros from n and return the number of zeros removed (float) +FMT_INLINE int remove_trailing_zeros(uint32_t& n) FMT_NOEXCEPT { +#ifdef FMT_BUILTIN_CTZ + int t = FMT_BUILTIN_CTZ(n); +#else + int t = ctz(n); +#endif + if (t > float_info<float>::max_trailing_zeros) + t = float_info<float>::max_trailing_zeros; + + const uint32_t mod_inv1 = 0xcccccccd; + const uint32_t max_quotient1 = 0x33333333; + const uint32_t mod_inv2 = 0xc28f5c29; + const uint32_t max_quotient2 = 0x0a3d70a3; + + int s = 0; + for (; s < t - 1; s += 2) { + if (n * mod_inv2 > max_quotient2) break; + n *= mod_inv2; + } + if (s < t && n * mod_inv1 <= max_quotient1) { + n *= mod_inv1; + ++s; + } + n >>= s; + return s; +} + +// Removes trailing zeros and returns the number of zeros removed (double) +FMT_INLINE int remove_trailing_zeros(uint64_t& n) FMT_NOEXCEPT { +#ifdef FMT_BUILTIN_CTZLL + int t = FMT_BUILTIN_CTZLL(n); +#else + int t = ctzll(n); +#endif + if (t > float_info<double>::max_trailing_zeros) + t = float_info<double>::max_trailing_zeros; + // Divide by 10^8 and reduce to 32-bits + // Since ret_value.significand <= (2^64 - 1) / 1000 < 10^17, + // both of the quotient and the r should fit in 32-bits + + const uint32_t mod_inv1 = 0xcccccccd; + const uint32_t max_quotient1 = 0x33333333; + const uint64_t mod_inv8 = 0xc767074b22e90e21; + const uint64_t max_quotient8 = 0x00002af31dc46118; + + // If the number is divisible by 1'0000'0000, work with the quotient + if (t >= 8) { + auto quotient_candidate = n * mod_inv8; + + if (quotient_candidate <= max_quotient8) { + auto quotient = static_cast<uint32_t>(quotient_candidate >> 8); + + int s = 8; + for (; s < t; ++s) { + if (quotient * mod_inv1 > max_quotient1) break; + quotient *= mod_inv1; + } + quotient >>= (s - 8); + n = quotient; + return s; + } + } + + // Otherwise, work with the remainder + auto quotient = static_cast<uint32_t>(n / 100000000); + auto remainder = static_cast<uint32_t>(n - 100000000 * quotient); + + if (t == 0 || remainder * mod_inv1 > max_quotient1) { + return 0; + } + remainder *= mod_inv1; + + if (t == 1 || remainder * mod_inv1 > max_quotient1) { + n = (remainder >> 1) + quotient * 10000000ull; + return 1; + } + remainder *= mod_inv1; + + if (t == 2 || remainder * mod_inv1 > max_quotient1) { + n = (remainder >> 2) + quotient * 1000000ull; + return 2; + } + remainder *= mod_inv1; + + if (t == 3 || remainder * mod_inv1 > max_quotient1) { + n = (remainder >> 3) + quotient * 100000ull; + return 3; + } + remainder *= mod_inv1; + + if (t == 4 || remainder * mod_inv1 > max_quotient1) { + n = (remainder >> 4) + quotient * 10000ull; + return 4; + } + remainder *= mod_inv1; + + if (t == 5 || remainder * mod_inv1 > max_quotient1) { + n = (remainder >> 5) + quotient * 1000ull; + return 5; + } + remainder *= mod_inv1; + + if (t == 6 || remainder * mod_inv1 > max_quotient1) { + n = (remainder >> 6) + quotient * 100ull; + return 6; + } + remainder *= mod_inv1; + + n = (remainder >> 7) + quotient * 10ull; + return 7; +} + +// The main algorithm for shorter interval case +template <class T> +FMT_INLINE decimal_fp<T> shorter_interval_case(int exponent) FMT_NOEXCEPT { + decimal_fp<T> ret_value; + // Compute k and beta + const int minus_k = floor_log10_pow2_minus_log10_4_over_3(exponent); + const int beta_minus_1 = exponent + floor_log2_pow10(-minus_k); + + // Compute xi and zi + using cache_entry_type = typename cache_accessor<T>::cache_entry_type; + const cache_entry_type cache = cache_accessor<T>::get_cached_power(-minus_k); + + auto xi = cache_accessor<T>::compute_left_endpoint_for_shorter_interval_case( + cache, beta_minus_1); + auto zi = cache_accessor<T>::compute_right_endpoint_for_shorter_interval_case( + cache, beta_minus_1); + + // If the left endpoint is not an integer, increase it + if (!is_left_endpoint_integer_shorter_interval<T>(exponent)) ++xi; + + // Try bigger divisor + ret_value.significand = zi / 10; + + // If succeed, remove trailing zeros if necessary and return + if (ret_value.significand * 10 >= xi) { + ret_value.exponent = minus_k + 1; + ret_value.exponent += remove_trailing_zeros(ret_value.significand); + return ret_value; + } + + // Otherwise, compute the round-up of y + ret_value.significand = + cache_accessor<T>::compute_round_up_for_shorter_interval_case( + cache, beta_minus_1); + ret_value.exponent = minus_k; + + // When tie occurs, choose one of them according to the rule + if (exponent >= float_info<T>::shorter_interval_tie_lower_threshold && + exponent <= float_info<T>::shorter_interval_tie_upper_threshold) { + ret_value.significand = ret_value.significand % 2 == 0 + ? ret_value.significand + : ret_value.significand - 1; + } else if (ret_value.significand < xi) { + ++ret_value.significand; + } + return ret_value; +} + +template <typename T> decimal_fp<T> to_decimal(T x) FMT_NOEXCEPT { + // Step 1: integer promotion & Schubfach multiplier calculation. + + using carrier_uint = typename float_info<T>::carrier_uint; + using cache_entry_type = typename cache_accessor<T>::cache_entry_type; + auto br = bit_cast<carrier_uint>(x); + + // Extract significand bits and exponent bits. + const carrier_uint significand_mask = + (static_cast<carrier_uint>(1) << float_info<T>::significand_bits) - 1; + carrier_uint significand = (br & significand_mask); + int exponent = static_cast<int>((br & exponent_mask<T>()) >> + float_info<T>::significand_bits); + + if (exponent != 0) { // Check if normal. + exponent += float_info<T>::exponent_bias - float_info<T>::significand_bits; + + // Shorter interval case; proceed like Schubfach. + if (significand == 0) return shorter_interval_case<T>(exponent); + + significand |= + (static_cast<carrier_uint>(1) << float_info<T>::significand_bits); + } else { + // Subnormal case; the interval is always regular. + if (significand == 0) return {0, 0}; + exponent = float_info<T>::min_exponent - float_info<T>::significand_bits; + } + + const bool include_left_endpoint = (significand % 2 == 0); + const bool include_right_endpoint = include_left_endpoint; + + // Compute k and beta. + const int minus_k = floor_log10_pow2(exponent) - float_info<T>::kappa; + const cache_entry_type cache = cache_accessor<T>::get_cached_power(-minus_k); + const int beta_minus_1 = exponent + floor_log2_pow10(-minus_k); + + // Compute zi and deltai + // 10^kappa <= deltai < 10^(kappa + 1) + const uint32_t deltai = cache_accessor<T>::compute_delta(cache, beta_minus_1); + const carrier_uint two_fc = significand << 1; + const carrier_uint two_fr = two_fc | 1; + const carrier_uint zi = + cache_accessor<T>::compute_mul(two_fr << beta_minus_1, cache); + + // Step 2: Try larger divisor; remove trailing zeros if necessary + + // Using an upper bound on zi, we might be able to optimize the division + // better than the compiler; we are computing zi / big_divisor here + decimal_fp<T> ret_value; + ret_value.significand = divide_by_10_to_kappa_plus_1(zi); + uint32_t r = static_cast<uint32_t>(zi - float_info<T>::big_divisor * + ret_value.significand); + + if (r > deltai) { + goto small_divisor_case_label; + } else if (r < deltai) { + // Exclude the right endpoint if necessary + if (r == 0 && !include_right_endpoint && + is_endpoint_integer<T>(two_fr, exponent, minus_k)) { + --ret_value.significand; + r = float_info<T>::big_divisor; + goto small_divisor_case_label; + } + } else { + // r == deltai; compare fractional parts + // Check conditions in the order different from the paper + // to take advantage of short-circuiting + const carrier_uint two_fl = two_fc - 1; + if ((!include_left_endpoint || + !is_endpoint_integer<T>(two_fl, exponent, minus_k)) && + !cache_accessor<T>::compute_mul_parity(two_fl, cache, beta_minus_1)) { + goto small_divisor_case_label; + } + } + ret_value.exponent = minus_k + float_info<T>::kappa + 1; + + // We may need to remove trailing zeros + ret_value.exponent += remove_trailing_zeros(ret_value.significand); + return ret_value; + + // Step 3: Find the significand with the smaller divisor + +small_divisor_case_label: + ret_value.significand *= 10; + ret_value.exponent = minus_k + float_info<T>::kappa; + + const uint32_t mask = (1u << float_info<T>::kappa) - 1; + auto dist = r - (deltai / 2) + (float_info<T>::small_divisor / 2); + + // Is dist divisible by 2^kappa? + if ((dist & mask) == 0) { + const bool approx_y_parity = + ((dist ^ (float_info<T>::small_divisor / 2)) & 1) != 0; + dist >>= float_info<T>::kappa; + + // Is dist divisible by 5^kappa? + if (check_divisibility_and_divide_by_pow5<float_info<T>::kappa>(dist)) { + ret_value.significand += dist; + + // Check z^(f) >= epsilon^(f) + // We have either yi == zi - epsiloni or yi == (zi - epsiloni) - 1, + // where yi == zi - epsiloni if and only if z^(f) >= epsilon^(f) + // Since there are only 2 possibilities, we only need to care about the + // parity. Also, zi and r should have the same parity since the divisor + // is an even number + if (cache_accessor<T>::compute_mul_parity(two_fc, cache, beta_minus_1) != + approx_y_parity) { + --ret_value.significand; + } else { + // If z^(f) >= epsilon^(f), we might have a tie + // when z^(f) == epsilon^(f), or equivalently, when y is an integer + if (is_center_integer<T>(two_fc, exponent, minus_k)) { + ret_value.significand = ret_value.significand % 2 == 0 + ? ret_value.significand + : ret_value.significand - 1; + } + } + } + // Is dist not divisible by 5^kappa? + else { + ret_value.significand += dist; + } + } + // Is dist not divisible by 2^kappa? + else { + // Since we know dist is small, we might be able to optimize the division + // better than the compiler; we are computing dist / small_divisor here + ret_value.significand += + small_division_by_pow10<float_info<T>::kappa>(dist); + } + return ret_value; +} +} // namespace dragonbox + +// Formats a floating-point number using a variation of the Fixed-Precision +// Positive Floating-Point Printout ((FPP)^2) algorithm by Steele & White: +// https://fmt.dev/papers/p372-steele.pdf. +FMT_CONSTEXPR20 inline void format_dragon(fp value, bool is_predecessor_closer, + int num_digits, buffer<char>& buf, + int& exp10) { + bigint numerator; // 2 * R in (FPP)^2. + bigint denominator; // 2 * S in (FPP)^2. + // lower and upper are differences between value and corresponding boundaries. + bigint lower; // (M^- in (FPP)^2). + bigint upper_store; // upper's value if different from lower. + bigint* upper = nullptr; // (M^+ in (FPP)^2). + // Shift numerator and denominator by an extra bit or two (if lower boundary + // is closer) to make lower and upper integers. This eliminates multiplication + // by 2 during later computations. + int shift = is_predecessor_closer ? 2 : 1; + uint64_t significand = value.f << shift; + if (value.e >= 0) { + numerator.assign(significand); + numerator <<= value.e; + lower.assign(1); + lower <<= value.e; + if (shift != 1) { + upper_store.assign(1); + upper_store <<= value.e + 1; + upper = &upper_store; + } + denominator.assign_pow10(exp10); + denominator <<= shift; + } else if (exp10 < 0) { + numerator.assign_pow10(-exp10); + lower.assign(numerator); + if (shift != 1) { + upper_store.assign(numerator); + upper_store <<= 1; + upper = &upper_store; + } + numerator *= significand; + denominator.assign(1); + denominator <<= shift - value.e; + } else { + numerator.assign(significand); + denominator.assign_pow10(exp10); + denominator <<= shift - value.e; + lower.assign(1); + if (shift != 1) { + upper_store.assign(1ULL << 1); + upper = &upper_store; + } + } + // Invariant: value == (numerator / denominator) * pow(10, exp10). + if (num_digits < 0) { + // Generate the shortest representation. + if (!upper) upper = &lower; + bool even = (value.f & 1) == 0; + num_digits = 0; + char* data = buf.data(); + for (;;) { + int digit = numerator.divmod_assign(denominator); + bool low = compare(numerator, lower) - even < 0; // numerator <[=] lower. + // numerator + upper >[=] pow10: + bool high = add_compare(numerator, *upper, denominator) + even > 0; + data[num_digits++] = static_cast<char>('0' + digit); + if (low || high) { + if (!low) { + ++data[num_digits - 1]; + } else if (high) { + int result = add_compare(numerator, numerator, denominator); + // Round half to even. + if (result > 0 || (result == 0 && (digit % 2) != 0)) + ++data[num_digits - 1]; + } + buf.try_resize(to_unsigned(num_digits)); + exp10 -= num_digits - 1; + return; + } + numerator *= 10; + lower *= 10; + if (upper != &lower) *upper *= 10; + } + } + // Generate the given number of digits. + exp10 -= num_digits - 1; + if (num_digits == 0) { + denominator *= 10; + auto digit = add_compare(numerator, numerator, denominator) > 0 ? '1' : '0'; + buf.push_back(digit); + return; + } + buf.try_resize(to_unsigned(num_digits)); + for (int i = 0; i < num_digits - 1; ++i) { + int digit = numerator.divmod_assign(denominator); + buf[i] = static_cast<char>('0' + digit); + numerator *= 10; + } + int digit = numerator.divmod_assign(denominator); + auto result = add_compare(numerator, numerator, denominator); + if (result > 0 || (result == 0 && (digit % 2) != 0)) { + if (digit == 9) { + const auto overflow = '0' + 10; + buf[num_digits - 1] = overflow; + // Propagate the carry. + for (int i = num_digits - 1; i > 0 && buf[i] == overflow; --i) { + buf[i] = '0'; + ++buf[i - 1]; + } + if (buf[0] == overflow) { + buf[0] = '1'; + ++exp10; + } + return; + } + ++digit; + } + buf[num_digits - 1] = static_cast<char>('0' + digit); +} + +template <typename Float> +FMT_HEADER_ONLY_CONSTEXPR20 int format_float(Float value, int precision, + float_specs specs, + buffer<char>& buf) { + // float is passed as double to reduce the number of instantiations. + static_assert(!std::is_same<Float, float>::value, ""); + FMT_ASSERT(value >= 0, "value is negative"); + + const bool fixed = specs.format == float_format::fixed; + if (value <= 0) { // <= instead of == to silence a warning. + if (precision <= 0 || !fixed) { + buf.push_back('0'); + return 0; + } + buf.try_resize(to_unsigned(precision)); + fill_n(buf.data(), precision, '0'); + return -precision; + } + + if (specs.fallback) return snprintf_float(value, precision, specs, buf); + + if (!is_constant_evaluated() && precision < 0) { + // Use Dragonbox for the shortest format. + if (specs.binary32) { + auto dec = dragonbox::to_decimal(static_cast<float>(value)); + write<char>(buffer_appender<char>(buf), dec.significand); + return dec.exponent; + } + auto dec = dragonbox::to_decimal(static_cast<double>(value)); + write<char>(buffer_appender<char>(buf), dec.significand); + return dec.exponent; + } + + int exp = 0; + bool use_dragon = true; + if (is_fast_float<Float>()) { + // Use Grisu + Dragon4 for the given precision: + // https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf. + const int min_exp = -60; // alpha in Grisu. + int cached_exp10 = 0; // K in Grisu. + fp normalized = normalize(fp(value)); + const auto cached_pow = get_cached_power( + min_exp - (normalized.e + fp::num_significand_bits), cached_exp10); + normalized = normalized * cached_pow; + gen_digits_handler handler{buf.data(), 0, precision, -cached_exp10, fixed}; + if (grisu_gen_digits(normalized, 1, exp, handler) != digits::error && + !is_constant_evaluated()) { + exp += handler.exp10; + buf.try_resize(to_unsigned(handler.size)); + use_dragon = false; + } else { + exp += handler.size - cached_exp10 - 1; + precision = handler.precision; + } + } + if (use_dragon) { + auto f = fp(); + bool is_predecessor_closer = + specs.binary32 ? f.assign(static_cast<float>(value)) : f.assign(value); + // Limit precision to the maximum possible number of significant digits in + // an IEEE754 double because we don't need to generate zeros. + const int max_double_digits = 767; + if (precision > max_double_digits) precision = max_double_digits; + format_dragon(f, is_predecessor_closer, precision, buf, exp); + } + if (!fixed && !specs.showpoint) { + // Remove trailing zeros. + auto num_digits = buf.size(); + while (num_digits > 0 && buf[num_digits - 1] == '0') { + --num_digits; + ++exp; + } + buf.try_resize(num_digits); + } + return exp; +} + +template <typename T> +int snprintf_float(T value, int precision, float_specs specs, + buffer<char>& buf) { + // Buffer capacity must be non-zero, otherwise MSVC's vsnprintf_s will fail. + FMT_ASSERT(buf.capacity() > buf.size(), "empty buffer"); + static_assert(!std::is_same<T, float>::value, ""); + + // Subtract 1 to account for the difference in precision since we use %e for + // both general and exponent format. + if (specs.format == float_format::general || + specs.format == float_format::exp) + precision = (precision >= 0 ? precision : 6) - 1; + + // Build the format string. + enum { max_format_size = 7 }; // The longest format is "%#.*Le". + char format[max_format_size]; + char* format_ptr = format; + *format_ptr++ = '%'; + if (specs.showpoint && specs.format == float_format::hex) *format_ptr++ = '#'; + if (precision >= 0) { + *format_ptr++ = '.'; + *format_ptr++ = '*'; + } + if (std::is_same<T, long double>()) *format_ptr++ = 'L'; + *format_ptr++ = specs.format != float_format::hex + ? (specs.format == float_format::fixed ? 'f' : 'e') + : (specs.upper ? 'A' : 'a'); + *format_ptr = '\0'; + + // Format using snprintf. + auto offset = buf.size(); + for (;;) { + auto begin = buf.data() + offset; + auto capacity = buf.capacity() - offset; +#ifdef FMT_FUZZ + if (precision > 100000) + throw std::runtime_error( + "fuzz mode - avoid large allocation inside snprintf"); +#endif + // Suppress the warning about a nonliteral format string. + // Cannot use auto because of a bug in MinGW (#1532). + int (*snprintf_ptr)(char*, size_t, const char*, ...) = FMT_SNPRINTF; + int result = precision >= 0 + ? snprintf_ptr(begin, capacity, format, precision, value) + : snprintf_ptr(begin, capacity, format, value); + if (result < 0) { + // The buffer will grow exponentially. + buf.try_reserve(buf.capacity() + 1); + continue; + } + auto size = to_unsigned(result); + // Size equal to capacity means that the last character was truncated. + if (size >= capacity) { + buf.try_reserve(size + offset + 1); // Add 1 for the terminating '\0'. + continue; + } + auto is_digit = [](char c) { return c >= '0' && c <= '9'; }; + if (specs.format == float_format::fixed) { + if (precision == 0) { + buf.try_resize(size); + return 0; + } + // Find and remove the decimal point. + auto end = begin + size, p = end; + do { + --p; + } while (is_digit(*p)); + int fraction_size = static_cast<int>(end - p - 1); + std::memmove(p, p + 1, to_unsigned(fraction_size)); + buf.try_resize(size - 1); + return -fraction_size; + } + if (specs.format == float_format::hex) { + buf.try_resize(size + offset); + return 0; + } + // Find and parse the exponent. + auto end = begin + size, exp_pos = end; + do { + --exp_pos; + } while (*exp_pos != 'e'); + char sign = exp_pos[1]; + FMT_ASSERT(sign == '+' || sign == '-', ""); + int exp = 0; + auto p = exp_pos + 2; // Skip 'e' and sign. + do { + FMT_ASSERT(is_digit(*p), ""); + exp = exp * 10 + (*p++ - '0'); + } while (p != end); + if (sign == '-') exp = -exp; + int fraction_size = 0; + if (exp_pos != begin + 1) { + // Remove trailing zeros. + auto fraction_end = exp_pos - 1; + while (*fraction_end == '0') --fraction_end; + // Move the fractional part left to get rid of the decimal point. + fraction_size = static_cast<int>(fraction_end - begin - 1); + std::memmove(begin + 1, begin + 2, to_unsigned(fraction_size)); + } + buf.try_resize(to_unsigned(fraction_size) + offset + 1); + return exp - fraction_size; + } +} +} // namespace detail + +template <> struct formatter<detail::bigint> { + FMT_CONSTEXPR format_parse_context::iterator parse( + format_parse_context& ctx) { + return ctx.begin(); + } + + format_context::iterator format(const detail::bigint& n, + format_context& ctx) { + auto out = ctx.out(); + bool first = true; + for (auto i = n.bigits_.size(); i > 0; --i) { + auto value = n.bigits_[i - 1u]; + if (first) { + out = format_to(out, FMT_STRING("{:x}"), value); + first = false; + continue; + } + out = format_to(out, FMT_STRING("{:08x}"), value); + } + if (n.exp_ > 0) + out = format_to(out, FMT_STRING("p{}"), + n.exp_ * detail::bigint::bigit_bits); + return out; + } +}; + +FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) { + for_each_codepoint(s, [this](uint32_t cp, string_view) { + if (cp == invalid_code_point) FMT_THROW(std::runtime_error("invalid utf8")); + if (cp <= 0xFFFF) { + buffer_.push_back(static_cast<wchar_t>(cp)); + } else { + cp -= 0x10000; + buffer_.push_back(static_cast<wchar_t>(0xD800 + (cp >> 10))); + buffer_.push_back(static_cast<wchar_t>(0xDC00 + (cp & 0x3FF))); + } + return true; + }); + buffer_.push_back(0); +} + +FMT_FUNC void format_system_error(detail::buffer<char>& out, int error_code, + const char* message) FMT_NOEXCEPT { + FMT_TRY { + auto ec = std::error_code(error_code, std::generic_category()); + write(std::back_inserter(out), std::system_error(ec, message).what()); + return; + } + FMT_CATCH(...) {} + format_error_code(out, error_code, message); +} + +FMT_FUNC void report_system_error(int error_code, + const char* message) FMT_NOEXCEPT { + report_error(format_system_error, error_code, message); +} + +// DEPRECATED! +// This function is defined here and not inline for ABI compatiblity. +FMT_FUNC void detail::error_handler::on_error(const char* message) { + throw_format_error(message); +} + +FMT_FUNC std::string vformat(string_view fmt, format_args args) { + // Don't optimize the "{}" case to keep the binary size small and because it + // can be better optimized in fmt::format anyway. + auto buffer = memory_buffer(); + detail::vformat_to(buffer, fmt, args); + return to_string(buffer); +} + +#ifdef _WIN32 +namespace detail { +using dword = conditional_t<sizeof(long) == 4, unsigned long, unsigned>; +extern "C" __declspec(dllimport) int __stdcall WriteConsoleW( // + void*, const void*, dword, dword*, void*); +} // namespace detail +#endif + +namespace detail { +FMT_FUNC void print(std::FILE* f, string_view text) { +#ifdef _WIN32 + auto fd = _fileno(f); + if (_isatty(fd)) { + detail::utf8_to_utf16 u16(string_view(text.data(), text.size())); + auto written = detail::dword(); + if (detail::WriteConsoleW(reinterpret_cast<void*>(_get_osfhandle(fd)), + u16.c_str(), static_cast<uint32_t>(u16.size()), + &written, nullptr)) { + return; + } + // Fallback to fwrite on failure. It can happen if the output has been + // redirected to NUL. + } +#endif + detail::fwrite_fully(text.data(), 1, text.size(), f); +} +} // namespace detail + +FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) { + memory_buffer buffer; + detail::vformat_to(buffer, format_str, args); + detail::print(f, {buffer.data(), buffer.size()}); +} + +#ifdef _WIN32 +// Print assuming legacy (non-Unicode) encoding. +FMT_FUNC void detail::vprint_mojibake(std::FILE* f, string_view format_str, + format_args args) { + memory_buffer buffer; + detail::vformat_to(buffer, format_str, + basic_format_args<buffer_context<char>>(args)); + fwrite_fully(buffer.data(), 1, buffer.size(), f); +} +#endif + +FMT_FUNC void vprint(string_view format_str, format_args args) { + vprint(stdout, format_str, args); +} + +FMT_END_NAMESPACE + +#endif // FMT_FORMAT_INL_H_ diff --git a/extern/fmtlib/include/fmt/format.h b/extern/fmtlib/include/fmt/format.h new file mode 100644 index 00000000000..ee69651ca54 --- /dev/null +++ b/extern/fmtlib/include/fmt/format.h @@ -0,0 +1,3104 @@ +/* + Formatting library for C++ + + Copyright (c) 2012 - present, Victor Zverovich + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + --- Optional exception to the license --- + + As an exception, if, as a result of your compiling your source code, portions + of this Software are embedded into a machine-executable object form of such + source code, you may redistribute such embedded portions in such object form + without including the above copyright and permission notices. + */ + +#ifndef FMT_FORMAT_H_ +#define FMT_FORMAT_H_ + +#include <cmath> // std::signbit +#include <cstdint> // uint32_t +#include <limits> // std::numeric_limits +#include <memory> // std::uninitialized_copy +#include <stdexcept> // std::runtime_error +#include <system_error> // std::system_error +#include <utility> // std::swap + +#ifdef __cpp_lib_bit_cast +# include <bit> // std::bitcast +#endif + +#include "core.h" + +#if FMT_GCC_VERSION +# define FMT_GCC_VISIBILITY_HIDDEN __attribute__((visibility("hidden"))) +#else +# define FMT_GCC_VISIBILITY_HIDDEN +#endif + +#ifdef __NVCC__ +# define FMT_CUDA_VERSION (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__) +#else +# define FMT_CUDA_VERSION 0 +#endif + +#ifdef __has_builtin +# define FMT_HAS_BUILTIN(x) __has_builtin(x) +#else +# define FMT_HAS_BUILTIN(x) 0 +#endif + +#if FMT_GCC_VERSION || FMT_CLANG_VERSION +# define FMT_NOINLINE __attribute__((noinline)) +#else +# define FMT_NOINLINE +#endif + +#if FMT_MSC_VER +# define FMT_MSC_DEFAULT = default +#else +# define FMT_MSC_DEFAULT +#endif + +#ifndef FMT_THROW +# if FMT_EXCEPTIONS +# if FMT_MSC_VER || FMT_NVCC +FMT_BEGIN_NAMESPACE +namespace detail { +template <typename Exception> inline void do_throw(const Exception& x) { + // Silence unreachable code warnings in MSVC and NVCC because these + // are nearly impossible to fix in a generic code. + volatile bool b = true; + if (b) throw x; +} +} // namespace detail +FMT_END_NAMESPACE +# define FMT_THROW(x) detail::do_throw(x) +# else +# define FMT_THROW(x) throw x +# endif +# else +# define FMT_THROW(x) \ + do { \ + FMT_ASSERT(false, (x).what()); \ + } while (false) +# endif +#endif + +#if FMT_EXCEPTIONS +# define FMT_TRY try +# define FMT_CATCH(x) catch (x) +#else +# define FMT_TRY if (true) +# define FMT_CATCH(x) if (false) +#endif + +#ifndef FMT_MAYBE_UNUSED +# if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused) +# define FMT_MAYBE_UNUSED [[maybe_unused]] +# else +# define FMT_MAYBE_UNUSED +# endif +#endif + +// Workaround broken [[deprecated]] in the Intel, PGI and NVCC compilers. +#if FMT_ICC_VERSION || defined(__PGI) || FMT_NVCC +# define FMT_DEPRECATED_ALIAS +#else +# define FMT_DEPRECATED_ALIAS FMT_DEPRECATED +#endif + +#ifndef FMT_USE_USER_DEFINED_LITERALS +// EDG based compilers (Intel, NVIDIA, Elbrus, etc), GCC and MSVC support UDLs. +# if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 407 || \ + FMT_MSC_VER >= 1900) && \ + (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= /* UDL feature */ 480) +# define FMT_USE_USER_DEFINED_LITERALS 1 +# else +# define FMT_USE_USER_DEFINED_LITERALS 0 +# endif +#endif + +// Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of +// integer formatter template instantiations to just one by only using the +// largest integer type. This results in a reduction in binary size but will +// cause a decrease in integer formatting performance. +#if !defined(FMT_REDUCE_INT_INSTANTIATIONS) +# define FMT_REDUCE_INT_INSTANTIATIONS 0 +#endif + +// __builtin_clz is broken in clang with Microsoft CodeGen: +// https://github.com/fmtlib/fmt/issues/519. +#if !FMT_MSC_VER +# if FMT_HAS_BUILTIN(__builtin_clz) || FMT_GCC_VERSION || FMT_ICC_VERSION +# define FMT_BUILTIN_CLZ(n) __builtin_clz(n) +# endif +# if FMT_HAS_BUILTIN(__builtin_clzll) || FMT_GCC_VERSION || FMT_ICC_VERSION +# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n) +# endif +#endif + +// __builtin_ctz is broken in Intel Compiler Classic on Windows: +// https://github.com/fmtlib/fmt/issues/2510. +#ifndef __ICL +# if FMT_HAS_BUILTIN(__builtin_ctz) || FMT_GCC_VERSION || FMT_ICC_VERSION +# define FMT_BUILTIN_CTZ(n) __builtin_ctz(n) +# endif +# if FMT_HAS_BUILTIN(__builtin_ctzll) || FMT_GCC_VERSION || FMT_ICC_VERSION +# define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n) +# endif +#endif + +#if FMT_MSC_VER +# include <intrin.h> // _BitScanReverse[64], _BitScanForward[64], _umul128 +#endif + +// Some compilers masquerade as both MSVC and GCC-likes or otherwise support +// __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the +// MSVC intrinsics if the clz and clzll builtins are not available. +#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) && !defined(FMT_BUILTIN_CTZLL) +FMT_BEGIN_NAMESPACE +namespace detail { +// Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning. +# if !defined(__clang__) +# pragma intrinsic(_BitScanForward) +# pragma intrinsic(_BitScanReverse) +# if defined(_WIN64) +# pragma intrinsic(_BitScanForward64) +# pragma intrinsic(_BitScanReverse64) +# endif +# endif + +inline auto clz(uint32_t x) -> int { + unsigned long r = 0; + _BitScanReverse(&r, x); + FMT_ASSERT(x != 0, ""); + // Static analysis complains about using uninitialized data + // "r", but the only way that can happen is if "x" is 0, + // which the callers guarantee to not happen. + FMT_MSC_WARNING(suppress : 6102) + return 31 ^ static_cast<int>(r); +} +# define FMT_BUILTIN_CLZ(n) detail::clz(n) + +inline auto clzll(uint64_t x) -> int { + unsigned long r = 0; +# ifdef _WIN64 + _BitScanReverse64(&r, x); +# else + // Scan the high 32 bits. + if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32))) return 63 ^ (r + 32); + // Scan the low 32 bits. + _BitScanReverse(&r, static_cast<uint32_t>(x)); +# endif + FMT_ASSERT(x != 0, ""); + FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning. + return 63 ^ static_cast<int>(r); +} +# define FMT_BUILTIN_CLZLL(n) detail::clzll(n) + +inline auto ctz(uint32_t x) -> int { + unsigned long r = 0; + _BitScanForward(&r, x); + FMT_ASSERT(x != 0, ""); + FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning. + return static_cast<int>(r); +} +# define FMT_BUILTIN_CTZ(n) detail::ctz(n) + +inline auto ctzll(uint64_t x) -> int { + unsigned long r = 0; + FMT_ASSERT(x != 0, ""); + FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning. +# ifdef _WIN64 + _BitScanForward64(&r, x); +# else + // Scan the low 32 bits. + if (_BitScanForward(&r, static_cast<uint32_t>(x))) return static_cast<int>(r); + // Scan the high 32 bits. + _BitScanForward(&r, static_cast<uint32_t>(x >> 32)); + r += 32; +# endif + return static_cast<int>(r); +} +# define FMT_BUILTIN_CTZLL(n) detail::ctzll(n) +} // namespace detail +FMT_END_NAMESPACE +#endif + +#ifdef FMT_HEADER_ONLY +# define FMT_HEADER_ONLY_CONSTEXPR20 FMT_CONSTEXPR20 +#else +# define FMT_HEADER_ONLY_CONSTEXPR20 +#endif + +FMT_BEGIN_NAMESPACE +namespace detail { + +template <typename Streambuf> class formatbuf : public Streambuf { + private: + using char_type = typename Streambuf::char_type; + using streamsize = decltype(std::declval<Streambuf>().sputn(nullptr, 0)); + using int_type = typename Streambuf::int_type; + using traits_type = typename Streambuf::traits_type; + + buffer<char_type>& buffer_; + + public: + explicit formatbuf(buffer<char_type>& buf) : buffer_(buf) {} + + protected: + // The put area is always empty. This makes the implementation simpler and has + // the advantage that the streambuf and the buffer are always in sync and + // sputc never writes into uninitialized memory. A disadvantage is that each + // call to sputc always results in a (virtual) call to overflow. There is no + // disadvantage here for sputn since this always results in a call to xsputn. + + auto overflow(int_type ch) -> int_type override { + if (!traits_type::eq_int_type(ch, traits_type::eof())) + buffer_.push_back(static_cast<char_type>(ch)); + return ch; + } + + auto xsputn(const char_type* s, streamsize count) -> streamsize override { + buffer_.append(s, s + count); + return count; + } +}; + +// Implementation of std::bit_cast for pre-C++20. +template <typename To, typename From> +FMT_CONSTEXPR20 auto bit_cast(const From& from) -> To { + static_assert(sizeof(To) == sizeof(From), "size mismatch"); +#ifdef __cpp_lib_bit_cast + if (is_constant_evaluated()) return std::bit_cast<To>(from); +#endif + auto to = To(); + std::memcpy(&to, &from, sizeof(to)); + return to; +} + +inline auto is_big_endian() -> bool { +#ifdef _WIN32 + return false; +#elif defined(__BIG_ENDIAN__) + return true; +#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) + return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__; +#else + struct bytes { + char data[sizeof(int)]; + }; + return bit_cast<bytes>(1).data[0] == 0; +#endif +} + +// A fallback implementation of uintptr_t for systems that lack it. +struct fallback_uintptr { + unsigned char value[sizeof(void*)]; + + fallback_uintptr() = default; + explicit fallback_uintptr(const void* p) { + *this = bit_cast<fallback_uintptr>(p); + if (const_check(is_big_endian())) { + for (size_t i = 0, j = sizeof(void*) - 1; i < j; ++i, --j) + std::swap(value[i], value[j]); + } + } +}; +#ifdef UINTPTR_MAX +using uintptr_t = ::uintptr_t; +inline auto to_uintptr(const void* p) -> uintptr_t { + return bit_cast<uintptr_t>(p); +} +#else +using uintptr_t = fallback_uintptr; +inline auto to_uintptr(const void* p) -> fallback_uintptr { + return fallback_uintptr(p); +} +#endif + +// Returns the largest possible value for type T. Same as +// std::numeric_limits<T>::max() but shorter and not affected by the max macro. +template <typename T> constexpr auto max_value() -> T { + return (std::numeric_limits<T>::max)(); +} +template <typename T> constexpr auto num_bits() -> int { + return std::numeric_limits<T>::digits; +} +// std::numeric_limits<T>::digits may return 0 for 128-bit ints. +template <> constexpr auto num_bits<int128_t>() -> int { return 128; } +template <> constexpr auto num_bits<uint128_t>() -> int { return 128; } +template <> constexpr auto num_bits<fallback_uintptr>() -> int { + return static_cast<int>(sizeof(void*) * + std::numeric_limits<unsigned char>::digits); +} + +FMT_INLINE void assume(bool condition) { + (void)condition; +#if FMT_HAS_BUILTIN(__builtin_assume) + __builtin_assume(condition); +#endif +} + +// An approximation of iterator_t for pre-C++20 systems. +template <typename T> +using iterator_t = decltype(std::begin(std::declval<T&>())); +template <typename T> using sentinel_t = decltype(std::end(std::declval<T&>())); + +// A workaround for std::string not having mutable data() until C++17. +template <typename Char> +inline auto get_data(std::basic_string<Char>& s) -> Char* { + return &s[0]; +} +template <typename Container> +inline auto get_data(Container& c) -> typename Container::value_type* { + return c.data(); +} + +#if defined(_SECURE_SCL) && _SECURE_SCL +// Make a checked iterator to avoid MSVC warnings. +template <typename T> using checked_ptr = stdext::checked_array_iterator<T*>; +template <typename T> +constexpr auto make_checked(T* p, size_t size) -> checked_ptr<T> { + return {p, size}; +} +#else +template <typename T> using checked_ptr = T*; +template <typename T> constexpr auto make_checked(T* p, size_t) -> T* { + return p; +} +#endif + +// Attempts to reserve space for n extra characters in the output range. +// Returns a pointer to the reserved range or a reference to it. +template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)> +#if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION +__attribute__((no_sanitize("undefined"))) +#endif +inline auto +reserve(std::back_insert_iterator<Container> it, size_t n) + -> checked_ptr<typename Container::value_type> { + Container& c = get_container(it); + size_t size = c.size(); + c.resize(size + n); + return make_checked(get_data(c) + size, n); +} + +template <typename T> +inline auto reserve(buffer_appender<T> it, size_t n) -> buffer_appender<T> { + buffer<T>& buf = get_container(it); + buf.try_reserve(buf.size() + n); + return it; +} + +template <typename Iterator> +constexpr auto reserve(Iterator& it, size_t) -> Iterator& { + return it; +} + +template <typename OutputIt> +using reserve_iterator = + remove_reference_t<decltype(reserve(std::declval<OutputIt&>(), 0))>; + +template <typename T, typename OutputIt> +constexpr auto to_pointer(OutputIt, size_t) -> T* { + return nullptr; +} +template <typename T> auto to_pointer(buffer_appender<T> it, size_t n) -> T* { + buffer<T>& buf = get_container(it); + auto size = buf.size(); + if (buf.capacity() < size + n) return nullptr; + buf.try_resize(size + n); + return buf.data() + size; +} + +template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)> +inline auto base_iterator(std::back_insert_iterator<Container>& it, + checked_ptr<typename Container::value_type>) + -> std::back_insert_iterator<Container> { + return it; +} + +template <typename Iterator> +constexpr auto base_iterator(Iterator, Iterator it) -> Iterator { + return it; +} + +// <algorithm> is spectacularly slow to compile in C++20 so use a simple fill_n +// instead (#1998). +template <typename OutputIt, typename Size, typename T> +FMT_CONSTEXPR auto fill_n(OutputIt out, Size count, const T& value) + -> OutputIt { + for (Size i = 0; i < count; ++i) *out++ = value; + return out; +} +template <typename T, typename Size> +FMT_CONSTEXPR20 auto fill_n(T* out, Size count, char value) -> T* { + if (is_constant_evaluated()) { + return fill_n<T*, Size, T>(out, count, value); + } + std::memset(out, value, to_unsigned(count)); + return out + count; +} + +#ifdef __cpp_char8_t +using char8_type = char8_t; +#else +enum char8_type : unsigned char {}; +#endif + +template <typename OutChar, typename InputIt, typename OutputIt> +FMT_CONSTEXPR FMT_NOINLINE auto copy_str_noinline(InputIt begin, InputIt end, + OutputIt out) -> OutputIt { + return copy_str<OutChar>(begin, end, out); +} + +// A public domain branchless UTF-8 decoder by Christopher Wellons: +// https://github.com/skeeto/branchless-utf8 +/* Decode the next character, c, from s, reporting errors in e. + * + * Since this is a branchless decoder, four bytes will be read from the + * buffer regardless of the actual length of the next character. This + * means the buffer _must_ have at least three bytes of zero padding + * following the end of the data stream. + * + * Errors are reported in e, which will be non-zero if the parsed + * character was somehow invalid: invalid byte sequence, non-canonical + * encoding, or a surrogate half. + * + * The function returns a pointer to the next character. When an error + * occurs, this pointer will be a guess that depends on the particular + * error, but it will always advance at least one byte. + */ +FMT_CONSTEXPR inline auto utf8_decode(const char* s, uint32_t* c, int* e) + -> const char* { + constexpr const int masks[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07}; + constexpr const uint32_t mins[] = {4194304, 0, 128, 2048, 65536}; + constexpr const int shiftc[] = {0, 18, 12, 6, 0}; + constexpr const int shifte[] = {0, 6, 4, 2, 0}; + + int len = code_point_length(s); + const char* next = s + len; + + // Assume a four-byte character and load four bytes. Unused bits are + // shifted out. + *c = uint32_t(s[0] & masks[len]) << 18; + *c |= uint32_t(s[1] & 0x3f) << 12; + *c |= uint32_t(s[2] & 0x3f) << 6; + *c |= uint32_t(s[3] & 0x3f) << 0; + *c >>= shiftc[len]; + + // Accumulate the various error conditions. + using uchar = unsigned char; + *e = (*c < mins[len]) << 6; // non-canonical encoding + *e |= ((*c >> 11) == 0x1b) << 7; // surrogate half? + *e |= (*c > 0x10FFFF) << 8; // out of range? + *e |= (uchar(s[1]) & 0xc0) >> 2; + *e |= (uchar(s[2]) & 0xc0) >> 4; + *e |= uchar(s[3]) >> 6; + *e ^= 0x2a; // top two bits of each tail byte correct? + *e >>= shifte[len]; + + return next; +} + +constexpr uint32_t invalid_code_point = ~uint32_t(); + +// Invokes f(cp, sv) for every code point cp in s with sv being the string view +// corresponding to the code point. cp is invalid_code_point on error. +template <typename F> +FMT_CONSTEXPR void for_each_codepoint(string_view s, F f) { + auto decode = [f](const char* buf_ptr, const char* ptr) { + auto cp = uint32_t(); + auto error = 0; + auto end = utf8_decode(buf_ptr, &cp, &error); + bool result = f(error ? invalid_code_point : cp, + string_view(ptr, to_unsigned(end - buf_ptr))); + return result ? end : nullptr; + }; + auto p = s.data(); + const size_t block_size = 4; // utf8_decode always reads blocks of 4 chars. + if (s.size() >= block_size) { + for (auto end = p + s.size() - block_size + 1; p < end;) { + p = decode(p, p); + if (!p) return; + } + } + if (auto num_chars_left = s.data() + s.size() - p) { + char buf[2 * block_size - 1] = {}; + copy_str<char>(p, p + num_chars_left, buf); + const char* buf_ptr = buf; + do { + auto end = decode(buf_ptr, p); + if (!end) return; + p += end - buf_ptr; + buf_ptr = end; + } while (buf_ptr - buf < num_chars_left); + } +} + +template <typename Char> +inline auto compute_width(basic_string_view<Char> s) -> size_t { + return s.size(); +} + +// Computes approximate display width of a UTF-8 string. +FMT_CONSTEXPR inline size_t compute_width(string_view s) { + size_t num_code_points = 0; + // It is not a lambda for compatibility with C++14. + struct count_code_points { + size_t* count; + FMT_CONSTEXPR auto operator()(uint32_t cp, string_view) const -> bool { + *count += detail::to_unsigned( + 1 + + (cp >= 0x1100 && + (cp <= 0x115f || // Hangul Jamo init. consonants + cp == 0x2329 || // LEFT-POINTING ANGLE BRACKET + cp == 0x232a || // RIGHT-POINTING ANGLE BRACKET + // CJK ... Yi except IDEOGRAPHIC HALF FILL SPACE: + (cp >= 0x2e80 && cp <= 0xa4cf && cp != 0x303f) || + (cp >= 0xac00 && cp <= 0xd7a3) || // Hangul Syllables + (cp >= 0xf900 && cp <= 0xfaff) || // CJK Compatibility Ideographs + (cp >= 0xfe10 && cp <= 0xfe19) || // Vertical Forms + (cp >= 0xfe30 && cp <= 0xfe6f) || // CJK Compatibility Forms + (cp >= 0xff00 && cp <= 0xff60) || // Fullwidth Forms + (cp >= 0xffe0 && cp <= 0xffe6) || // Fullwidth Forms + (cp >= 0x20000 && cp <= 0x2fffd) || // CJK + (cp >= 0x30000 && cp <= 0x3fffd) || + // Miscellaneous Symbols and Pictographs + Emoticons: + (cp >= 0x1f300 && cp <= 0x1f64f) || + // Supplemental Symbols and Pictographs: + (cp >= 0x1f900 && cp <= 0x1f9ff)))); + return true; + } + }; + for_each_codepoint(s, count_code_points{&num_code_points}); + return num_code_points; +} + +inline auto compute_width(basic_string_view<char8_type> s) -> size_t { + return compute_width(basic_string_view<char>( + reinterpret_cast<const char*>(s.data()), s.size())); +} + +template <typename Char> +inline auto code_point_index(basic_string_view<Char> s, size_t n) -> size_t { + size_t size = s.size(); + return n < size ? n : size; +} + +// Calculates the index of the nth code point in a UTF-8 string. +inline auto code_point_index(basic_string_view<char8_type> s, size_t n) + -> size_t { + const char8_type* data = s.data(); + size_t num_code_points = 0; + for (size_t i = 0, size = s.size(); i != size; ++i) { + if ((data[i] & 0xc0) != 0x80 && ++num_code_points > n) return i; + } + return s.size(); +} + +template <typename T, bool = std::is_floating_point<T>::value> +struct is_fast_float : bool_constant<std::numeric_limits<T>::is_iec559 && + sizeof(T) <= sizeof(double)> {}; +template <typename T> struct is_fast_float<T, false> : std::false_type {}; + +#ifndef FMT_USE_FULL_CACHE_DRAGONBOX +# define FMT_USE_FULL_CACHE_DRAGONBOX 0 +#endif + +template <typename T> +template <typename U> +void buffer<T>::append(const U* begin, const U* end) { + while (begin != end) { + auto count = to_unsigned(end - begin); + try_reserve(size_ + count); + auto free_cap = capacity_ - size_; + if (free_cap < count) count = free_cap; + std::uninitialized_copy_n(begin, count, make_checked(ptr_ + size_, count)); + size_ += count; + begin += count; + } +} + +template <typename T, typename Enable = void> +struct is_locale : std::false_type {}; +template <typename T> +struct is_locale<T, void_t<decltype(T::classic())>> : std::true_type {}; +} // namespace detail + +FMT_MODULE_EXPORT_BEGIN + +// The number of characters to store in the basic_memory_buffer object itself +// to avoid dynamic memory allocation. +enum { inline_buffer_size = 500 }; + +/** + \rst + A dynamically growing memory buffer for trivially copyable/constructible types + with the first ``SIZE`` elements stored in the object itself. + + You can use the ``memory_buffer`` type alias for ``char`` instead. + + **Example**:: + + auto out = fmt::memory_buffer(); + format_to(std::back_inserter(out), "The answer is {}.", 42); + + This will append the following output to the ``out`` object: + + .. code-block:: none + + The answer is 42. + + The output can be converted to an ``std::string`` with ``to_string(out)``. + \endrst + */ +template <typename T, size_t SIZE = inline_buffer_size, + typename Allocator = std::allocator<T>> +class basic_memory_buffer final : public detail::buffer<T> { + private: + T store_[SIZE]; + + // Don't inherit from Allocator avoid generating type_info for it. + Allocator alloc_; + + // Deallocate memory allocated by the buffer. + FMT_CONSTEXPR20 void deallocate() { + T* data = this->data(); + if (data != store_) alloc_.deallocate(data, this->capacity()); + } + + protected: + FMT_CONSTEXPR20 void grow(size_t size) override; + + public: + using value_type = T; + using const_reference = const T&; + + FMT_CONSTEXPR20 explicit basic_memory_buffer( + const Allocator& alloc = Allocator()) + : alloc_(alloc) { + this->set(store_, SIZE); + if (detail::is_constant_evaluated()) { + detail::fill_n(store_, SIZE, T{}); + } + } + FMT_CONSTEXPR20 ~basic_memory_buffer() { deallocate(); } + + private: + // Move data from other to this buffer. + FMT_CONSTEXPR20 void move(basic_memory_buffer& other) { + alloc_ = std::move(other.alloc_); + T* data = other.data(); + size_t size = other.size(), capacity = other.capacity(); + if (data == other.store_) { + this->set(store_, capacity); + if (detail::is_constant_evaluated()) { + detail::copy_str<T>(other.store_, other.store_ + size, + detail::make_checked(store_, capacity)); + } else { + std::uninitialized_copy(other.store_, other.store_ + size, + detail::make_checked(store_, capacity)); + } + } else { + this->set(data, capacity); + // Set pointer to the inline array so that delete is not called + // when deallocating. + other.set(other.store_, 0); + } + this->resize(size); + } + + public: + /** + \rst + Constructs a :class:`fmt::basic_memory_buffer` object moving the content + of the other object to it. + \endrst + */ + FMT_CONSTEXPR20 basic_memory_buffer(basic_memory_buffer&& other) + FMT_NOEXCEPT { + move(other); + } + + /** + \rst + Moves the content of the other ``basic_memory_buffer`` object to this one. + \endrst + */ + auto operator=(basic_memory_buffer&& other) FMT_NOEXCEPT + -> basic_memory_buffer& { + FMT_ASSERT(this != &other, ""); + deallocate(); + move(other); + return *this; + } + + // Returns a copy of the allocator associated with this buffer. + auto get_allocator() const -> Allocator { return alloc_; } + + /** + Resizes the buffer to contain *count* elements. If T is a POD type new + elements may not be initialized. + */ + FMT_CONSTEXPR20 void resize(size_t count) { this->try_resize(count); } + + /** Increases the buffer capacity to *new_capacity*. */ + void reserve(size_t new_capacity) { this->try_reserve(new_capacity); } + + // Directly append data into the buffer + using detail::buffer<T>::append; + template <typename ContiguousRange> + void append(const ContiguousRange& range) { + append(range.data(), range.data() + range.size()); + } +}; + +template <typename T, size_t SIZE, typename Allocator> +FMT_CONSTEXPR20 void basic_memory_buffer<T, SIZE, Allocator>::grow( + size_t size) { +#ifdef FMT_FUZZ + if (size > 5000) throw std::runtime_error("fuzz mode - won't grow that much"); +#endif + const size_t max_size = std::allocator_traits<Allocator>::max_size(alloc_); + size_t old_capacity = this->capacity(); + size_t new_capacity = old_capacity + old_capacity / 2; + if (size > new_capacity) + new_capacity = size; + else if (new_capacity > max_size) + new_capacity = size > max_size ? size : max_size; + T* old_data = this->data(); + T* new_data = + std::allocator_traits<Allocator>::allocate(alloc_, new_capacity); + // The following code doesn't throw, so the raw pointer above doesn't leak. + std::uninitialized_copy(old_data, old_data + this->size(), + detail::make_checked(new_data, new_capacity)); + this->set(new_data, new_capacity); + // deallocate must not throw according to the standard, but even if it does, + // the buffer already uses the new storage and will deallocate it in + // destructor. + if (old_data != store_) alloc_.deallocate(old_data, old_capacity); +} + +using memory_buffer = basic_memory_buffer<char>; + +template <typename T, size_t SIZE, typename Allocator> +struct is_contiguous<basic_memory_buffer<T, SIZE, Allocator>> : std::true_type { +}; + +namespace detail { +FMT_API void print(std::FILE*, string_view); +} + +/** A formatting error such as invalid format string. */ +FMT_CLASS_API +class FMT_API format_error : public std::runtime_error { + public: + explicit format_error(const char* message) : std::runtime_error(message) {} + explicit format_error(const std::string& message) + : std::runtime_error(message) {} + format_error(const format_error&) = default; + format_error& operator=(const format_error&) = default; + format_error(format_error&&) = default; + format_error& operator=(format_error&&) = default; + ~format_error() FMT_NOEXCEPT override FMT_MSC_DEFAULT; +}; + +/** + \rst + Constructs a `~fmt::format_arg_store` object that contains references + to arguments and can be implicitly converted to `~fmt::format_args`. + If ``fmt`` is a compile-time string then `make_args_checked` checks + its validity at compile time. + \endrst + */ +template <typename... Args, typename S, typename Char = char_t<S>> +FMT_INLINE auto make_args_checked(const S& fmt, + const remove_reference_t<Args>&... args) + -> format_arg_store<buffer_context<Char>, remove_reference_t<Args>...> { + static_assert( + detail::count<( + std::is_base_of<detail::view, remove_reference_t<Args>>::value && + std::is_reference<Args>::value)...>() == 0, + "passing views as lvalues is disallowed"); + detail::check_format_string<Args...>(fmt); + return {args...}; +} + +// compile-time support +namespace detail_exported { +#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS +template <typename Char, size_t N> struct fixed_string { + constexpr fixed_string(const Char (&str)[N]) { + detail::copy_str<Char, const Char*, Char*>(static_cast<const Char*>(str), + str + N, data); + } + Char data[N]{}; +}; +#endif + +// Converts a compile-time string to basic_string_view. +template <typename Char, size_t N> +constexpr auto compile_string_to_view(const Char (&s)[N]) + -> basic_string_view<Char> { + // Remove trailing NUL character if needed. Won't be present if this is used + // with a raw character array (i.e. not defined as a string). + return {s, N - (std::char_traits<Char>::to_int_type(s[N - 1]) == 0 ? 1 : 0)}; +} +template <typename Char> +constexpr auto compile_string_to_view(detail::std_string_view<Char> s) + -> basic_string_view<Char> { + return {s.data(), s.size()}; +} +} // namespace detail_exported + +FMT_BEGIN_DETAIL_NAMESPACE + +template <typename T> struct is_integral : std::is_integral<T> {}; +template <> struct is_integral<int128_t> : std::true_type {}; +template <> struct is_integral<uint128_t> : std::true_type {}; + +template <typename T> +using is_signed = + std::integral_constant<bool, std::numeric_limits<T>::is_signed || + std::is_same<T, int128_t>::value>; + +// Returns true if value is negative, false otherwise. +// Same as `value < 0` but doesn't produce warnings if T is an unsigned type. +template <typename T, FMT_ENABLE_IF(is_signed<T>::value)> +FMT_CONSTEXPR auto is_negative(T value) -> bool { + return value < 0; +} +template <typename T, FMT_ENABLE_IF(!is_signed<T>::value)> +FMT_CONSTEXPR auto is_negative(T) -> bool { + return false; +} + +template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)> +FMT_CONSTEXPR auto is_supported_floating_point(T) -> uint16_t { + return (std::is_same<T, float>::value && FMT_USE_FLOAT) || + (std::is_same<T, double>::value && FMT_USE_DOUBLE) || + (std::is_same<T, long double>::value && FMT_USE_LONG_DOUBLE); +} + +// Smallest of uint32_t, uint64_t, uint128_t that is large enough to +// represent all values of an integral type T. +template <typename T> +using uint32_or_64_or_128_t = + conditional_t<num_bits<T>() <= 32 && !FMT_REDUCE_INT_INSTANTIATIONS, + uint32_t, + conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>>; +template <typename T> +using uint64_or_128_t = conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>; + +#define FMT_POWERS_OF_10(factor) \ + factor * 10, (factor)*100, (factor)*1000, (factor)*10000, (factor)*100000, \ + (factor)*1000000, (factor)*10000000, (factor)*100000000, \ + (factor)*1000000000 + +// Converts value in the range [0, 100) to a string. +constexpr const char* digits2(size_t value) { + // GCC generates slightly better code when value is pointer-size. + return &"0001020304050607080910111213141516171819" + "2021222324252627282930313233343536373839" + "4041424344454647484950515253545556575859" + "6061626364656667686970717273747576777879" + "8081828384858687888990919293949596979899"[value * 2]; +} + +// Sign is a template parameter to workaround a bug in gcc 4.8. +template <typename Char, typename Sign> constexpr Char sign(Sign s) { +#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 604 + static_assert(std::is_same<Sign, sign_t>::value, ""); +#endif + return static_cast<Char>("\0-+ "[s]); +} + +template <typename T> FMT_CONSTEXPR auto count_digits_fallback(T n) -> int { + int count = 1; + for (;;) { + // Integer division is slow so do it for a group of four digits instead + // of for every digit. The idea comes from the talk by Alexandrescu + // "Three Optimization Tips for C++". See speed-test for a comparison. + if (n < 10) return count; + if (n < 100) return count + 1; + if (n < 1000) return count + 2; + if (n < 10000) return count + 3; + n /= 10000u; + count += 4; + } +} +#if FMT_USE_INT128 +FMT_CONSTEXPR inline auto count_digits(uint128_t n) -> int { + return count_digits_fallback(n); +} +#endif + +#ifdef FMT_BUILTIN_CLZLL +// It is a separate function rather than a part of count_digits to workaround +// the lack of static constexpr in constexpr functions. +inline auto do_count_digits(uint64_t n) -> int { + // This has comparable performance to the version by Kendall Willets + // (https://github.com/fmtlib/format-benchmark/blob/master/digits10) + // but uses smaller tables. + // Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)). + static constexpr uint8_t bsr2log10[] = { + 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, + 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, + 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15, + 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20}; + auto t = bsr2log10[FMT_BUILTIN_CLZLL(n | 1) ^ 63]; + static constexpr const uint64_t zero_or_powers_of_10[] = { + 0, 0, FMT_POWERS_OF_10(1U), FMT_POWERS_OF_10(1000000000ULL), + 10000000000000000000ULL}; + return t - (n < zero_or_powers_of_10[t]); +} +#endif + +// Returns the number of decimal digits in n. Leading zeros are not counted +// except for n == 0 in which case count_digits returns 1. +FMT_CONSTEXPR20 inline auto count_digits(uint64_t n) -> int { +#ifdef FMT_BUILTIN_CLZLL + if (!is_constant_evaluated()) { + return do_count_digits(n); + } +#endif + return count_digits_fallback(n); +} + +// Counts the number of digits in n. BITS = log2(radix). +template <int BITS, typename UInt> +FMT_CONSTEXPR auto count_digits(UInt n) -> int { +#ifdef FMT_BUILTIN_CLZ + if (num_bits<UInt>() == 32) + return (FMT_BUILTIN_CLZ(static_cast<uint32_t>(n) | 1) ^ 31) / BITS + 1; +#endif + // Lambda avoids unreachable code warnings from NVHPC. + return [](UInt m) { + int num_digits = 0; + do { + ++num_digits; + } while ((m >>= BITS) != 0); + return num_digits; + }(n); +} + +template <> auto count_digits<4>(detail::fallback_uintptr n) -> int; + +#ifdef FMT_BUILTIN_CLZ +// It is a separate function rather than a part of count_digits to workaround +// the lack of static constexpr in constexpr functions. +FMT_INLINE auto do_count_digits(uint32_t n) -> int { +// An optimization by Kendall Willets from https://bit.ly/3uOIQrB. +// This increments the upper 32 bits (log10(T) - 1) when >= T is added. +# define FMT_INC(T) (((sizeof(# T) - 1ull) << 32) - T) + static constexpr uint64_t table[] = { + FMT_INC(0), FMT_INC(0), FMT_INC(0), // 8 + FMT_INC(10), FMT_INC(10), FMT_INC(10), // 64 + FMT_INC(100), FMT_INC(100), FMT_INC(100), // 512 + FMT_INC(1000), FMT_INC(1000), FMT_INC(1000), // 4096 + FMT_INC(10000), FMT_INC(10000), FMT_INC(10000), // 32k + FMT_INC(100000), FMT_INC(100000), FMT_INC(100000), // 256k + FMT_INC(1000000), FMT_INC(1000000), FMT_INC(1000000), // 2048k + FMT_INC(10000000), FMT_INC(10000000), FMT_INC(10000000), // 16M + FMT_INC(100000000), FMT_INC(100000000), FMT_INC(100000000), // 128M + FMT_INC(1000000000), FMT_INC(1000000000), FMT_INC(1000000000), // 1024M + FMT_INC(1000000000), FMT_INC(1000000000) // 4B + }; + auto inc = table[FMT_BUILTIN_CLZ(n | 1) ^ 31]; + return static_cast<int>((n + inc) >> 32); +} +#endif + +// Optional version of count_digits for better performance on 32-bit platforms. +FMT_CONSTEXPR20 inline auto count_digits(uint32_t n) -> int { +#ifdef FMT_BUILTIN_CLZ + if (!is_constant_evaluated()) { + return do_count_digits(n); + } +#endif + return count_digits_fallback(n); +} + +template <typename Int> constexpr auto digits10() FMT_NOEXCEPT -> int { + return std::numeric_limits<Int>::digits10; +} +template <> constexpr auto digits10<int128_t>() FMT_NOEXCEPT -> int { + return 38; +} +template <> constexpr auto digits10<uint128_t>() FMT_NOEXCEPT -> int { + return 38; +} + +template <typename Char> struct thousands_sep_result { + std::string grouping; + Char thousands_sep; +}; + +template <typename Char> +FMT_API auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char>; +template <typename Char> +inline auto thousands_sep(locale_ref loc) -> thousands_sep_result<Char> { + auto result = thousands_sep_impl<char>(loc); + return {result.grouping, Char(result.thousands_sep)}; +} +template <> +inline auto thousands_sep(locale_ref loc) -> thousands_sep_result<wchar_t> { + return thousands_sep_impl<wchar_t>(loc); +} + +template <typename Char> +FMT_API auto decimal_point_impl(locale_ref loc) -> Char; +template <typename Char> inline auto decimal_point(locale_ref loc) -> Char { + return Char(decimal_point_impl<char>(loc)); +} +template <> inline auto decimal_point(locale_ref loc) -> wchar_t { + return decimal_point_impl<wchar_t>(loc); +} + +// Compares two characters for equality. +template <typename Char> auto equal2(const Char* lhs, const char* rhs) -> bool { + return lhs[0] == Char(rhs[0]) && lhs[1] == Char(rhs[1]); +} +inline auto equal2(const char* lhs, const char* rhs) -> bool { + return memcmp(lhs, rhs, 2) == 0; +} + +// Copies two characters from src to dst. +template <typename Char> +FMT_CONSTEXPR20 FMT_INLINE void copy2(Char* dst, const char* src) { + if (!is_constant_evaluated() && sizeof(Char) == sizeof(char)) { + memcpy(dst, src, 2); + return; + } + *dst++ = static_cast<Char>(*src++); + *dst = static_cast<Char>(*src); +} + +template <typename Iterator> struct format_decimal_result { + Iterator begin; + Iterator end; +}; + +// Formats a decimal unsigned integer value writing into out pointing to a +// buffer of specified size. The caller must ensure that the buffer is large +// enough. +template <typename Char, typename UInt> +FMT_CONSTEXPR20 auto format_decimal(Char* out, UInt value, int size) + -> format_decimal_result<Char*> { + FMT_ASSERT(size >= count_digits(value), "invalid digit count"); + out += size; + Char* end = out; + while (value >= 100) { + // Integer division is slow so do it for a group of two digits instead + // of for every digit. The idea comes from the talk by Alexandrescu + // "Three Optimization Tips for C++". See speed-test for a comparison. + out -= 2; + copy2(out, digits2(static_cast<size_t>(value % 100))); + value /= 100; + } + if (value < 10) { + *--out = static_cast<Char>('0' + value); + return {out, end}; + } + out -= 2; + copy2(out, digits2(static_cast<size_t>(value))); + return {out, end}; +} + +template <typename Char, typename UInt, typename Iterator, + FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<Iterator>>::value)> +inline auto format_decimal(Iterator out, UInt value, int size) + -> format_decimal_result<Iterator> { + // Buffer is large enough to hold all digits (digits10 + 1). + Char buffer[digits10<UInt>() + 1]; + auto end = format_decimal(buffer, value, size).end; + return {out, detail::copy_str_noinline<Char>(buffer, end, out)}; +} + +template <unsigned BASE_BITS, typename Char, typename UInt> +FMT_CONSTEXPR auto format_uint(Char* buffer, UInt value, int num_digits, + bool upper = false) -> Char* { + buffer += num_digits; + Char* end = buffer; + do { + const char* digits = upper ? "0123456789ABCDEF" : "0123456789abcdef"; + unsigned digit = (value & ((1 << BASE_BITS) - 1)); + *--buffer = static_cast<Char>(BASE_BITS < 4 ? static_cast<char>('0' + digit) + : digits[digit]); + } while ((value >>= BASE_BITS) != 0); + return end; +} + +template <unsigned BASE_BITS, typename Char> +auto format_uint(Char* buffer, detail::fallback_uintptr n, int num_digits, + bool = false) -> Char* { + auto char_digits = std::numeric_limits<unsigned char>::digits / 4; + int start = (num_digits + char_digits - 1) / char_digits - 1; + if (int start_digits = num_digits % char_digits) { + unsigned value = n.value[start--]; + buffer = format_uint<BASE_BITS>(buffer, value, start_digits); + } + for (; start >= 0; --start) { + unsigned value = n.value[start]; + buffer += char_digits; + auto p = buffer; + for (int i = 0; i < char_digits; ++i) { + unsigned digit = (value & ((1 << BASE_BITS) - 1)); + *--p = static_cast<Char>("0123456789abcdef"[digit]); + value >>= BASE_BITS; + } + } + return buffer; +} + +template <unsigned BASE_BITS, typename Char, typename It, typename UInt> +inline auto format_uint(It out, UInt value, int num_digits, bool upper = false) + -> It { + if (auto ptr = to_pointer<Char>(out, to_unsigned(num_digits))) { + format_uint<BASE_BITS>(ptr, value, num_digits, upper); + return out; + } + // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1). + char buffer[num_bits<UInt>() / BASE_BITS + 1]; + format_uint<BASE_BITS>(buffer, value, num_digits, upper); + return detail::copy_str_noinline<Char>(buffer, buffer + num_digits, out); +} + +// A converter from UTF-8 to UTF-16. +class utf8_to_utf16 { + private: + basic_memory_buffer<wchar_t> buffer_; + + public: + FMT_API explicit utf8_to_utf16(string_view s); + operator basic_string_view<wchar_t>() const { return {&buffer_[0], size()}; } + auto size() const -> size_t { return buffer_.size() - 1; } + auto c_str() const -> const wchar_t* { return &buffer_[0]; } + auto str() const -> std::wstring { return {&buffer_[0], size()}; } +}; + +namespace dragonbox { + +// Type-specific information that Dragonbox uses. +template <class T> struct float_info; + +template <> struct float_info<float> { + using carrier_uint = uint32_t; + static const int significand_bits = 23; + static const int exponent_bits = 8; + static const int min_exponent = -126; + static const int max_exponent = 127; + static const int exponent_bias = -127; + static const int decimal_digits = 9; + static const int kappa = 1; + static const int big_divisor = 100; + static const int small_divisor = 10; + static const int min_k = -31; + static const int max_k = 46; + static const int cache_bits = 64; + static const int divisibility_check_by_5_threshold = 39; + static const int case_fc_pm_half_lower_threshold = -1; + static const int case_fc_pm_half_upper_threshold = 6; + static const int case_fc_lower_threshold = -2; + static const int case_fc_upper_threshold = 6; + static const int case_shorter_interval_left_endpoint_lower_threshold = 2; + static const int case_shorter_interval_left_endpoint_upper_threshold = 3; + static const int shorter_interval_tie_lower_threshold = -35; + static const int shorter_interval_tie_upper_threshold = -35; + static const int max_trailing_zeros = 7; +}; + +template <> struct float_info<double> { + using carrier_uint = uint64_t; + static const int significand_bits = 52; + static const int exponent_bits = 11; + static const int min_exponent = -1022; + static const int max_exponent = 1023; + static const int exponent_bias = -1023; + static const int decimal_digits = 17; + static const int kappa = 2; + static const int big_divisor = 1000; + static const int small_divisor = 100; + static const int min_k = -292; + static const int max_k = 326; + static const int cache_bits = 128; + static const int divisibility_check_by_5_threshold = 86; + static const int case_fc_pm_half_lower_threshold = -2; + static const int case_fc_pm_half_upper_threshold = 9; + static const int case_fc_lower_threshold = -4; + static const int case_fc_upper_threshold = 9; + static const int case_shorter_interval_left_endpoint_lower_threshold = 2; + static const int case_shorter_interval_left_endpoint_upper_threshold = 3; + static const int shorter_interval_tie_lower_threshold = -77; + static const int shorter_interval_tie_upper_threshold = -77; + static const int max_trailing_zeros = 16; +}; + +template <typename T> struct decimal_fp { + using significand_type = typename float_info<T>::carrier_uint; + significand_type significand; + int exponent; +}; + +template <typename T> +FMT_API auto to_decimal(T x) FMT_NOEXCEPT -> decimal_fp<T>; +} // namespace dragonbox + +template <typename T> +constexpr auto exponent_mask() -> + typename dragonbox::float_info<T>::carrier_uint { + using uint = typename dragonbox::float_info<T>::carrier_uint; + return ((uint(1) << dragonbox::float_info<T>::exponent_bits) - 1) + << dragonbox::float_info<T>::significand_bits; +} + +// Writes the exponent exp in the form "[+-]d{2,3}" to buffer. +template <typename Char, typename It> +FMT_CONSTEXPR auto write_exponent(int exp, It it) -> It { + FMT_ASSERT(-10000 < exp && exp < 10000, "exponent out of range"); + if (exp < 0) { + *it++ = static_cast<Char>('-'); + exp = -exp; + } else { + *it++ = static_cast<Char>('+'); + } + if (exp >= 100) { + const char* top = digits2(to_unsigned(exp / 100)); + if (exp >= 1000) *it++ = static_cast<Char>(top[0]); + *it++ = static_cast<Char>(top[1]); + exp %= 100; + } + const char* d = digits2(to_unsigned(exp)); + *it++ = static_cast<Char>(d[0]); + *it++ = static_cast<Char>(d[1]); + return it; +} + +template <typename T> +FMT_HEADER_ONLY_CONSTEXPR20 auto format_float(T value, int precision, + float_specs specs, + buffer<char>& buf) -> int; + +// Formats a floating-point number with snprintf. +template <typename T> +auto snprintf_float(T value, int precision, float_specs specs, + buffer<char>& buf) -> int; + +template <typename T> constexpr auto promote_float(T value) -> T { + return value; +} +constexpr auto promote_float(float value) -> double { + return static_cast<double>(value); +} + +template <typename OutputIt, typename Char> +FMT_NOINLINE FMT_CONSTEXPR auto fill(OutputIt it, size_t n, + const fill_t<Char>& fill) -> OutputIt { + auto fill_size = fill.size(); + if (fill_size == 1) return detail::fill_n(it, n, fill[0]); + auto data = fill.data(); + for (size_t i = 0; i < n; ++i) + it = copy_str<Char>(data, data + fill_size, it); + return it; +} + +// Writes the output of f, padded according to format specifications in specs. +// size: output size in code units. +// width: output display width in (terminal) column positions. +template <align::type align = align::left, typename OutputIt, typename Char, + typename F> +FMT_CONSTEXPR auto write_padded(OutputIt out, + const basic_format_specs<Char>& specs, + size_t size, size_t width, F&& f) -> OutputIt { + static_assert(align == align::left || align == align::right, ""); + unsigned spec_width = to_unsigned(specs.width); + size_t padding = spec_width > width ? spec_width - width : 0; + // Shifts are encoded as string literals because static constexpr is not + // supported in constexpr functions. + auto* shifts = align == align::left ? "\x1f\x1f\x00\x01" : "\x00\x1f\x00\x01"; + size_t left_padding = padding >> shifts[specs.align]; + size_t right_padding = padding - left_padding; + auto it = reserve(out, size + padding * specs.fill.size()); + if (left_padding != 0) it = fill(it, left_padding, specs.fill); + it = f(it); + if (right_padding != 0) it = fill(it, right_padding, specs.fill); + return base_iterator(out, it); +} + +template <align::type align = align::left, typename OutputIt, typename Char, + typename F> +constexpr auto write_padded(OutputIt out, const basic_format_specs<Char>& specs, + size_t size, F&& f) -> OutputIt { + return write_padded<align>(out, specs, size, size, f); +} + +template <align::type align = align::left, typename Char, typename OutputIt> +FMT_CONSTEXPR auto write_bytes(OutputIt out, string_view bytes, + const basic_format_specs<Char>& specs) + -> OutputIt { + return write_padded<align>( + out, specs, bytes.size(), [bytes](reserve_iterator<OutputIt> it) { + const char* data = bytes.data(); + return copy_str<Char>(data, data + bytes.size(), it); + }); +} + +template <typename Char, typename OutputIt, typename UIntPtr> +auto write_ptr(OutputIt out, UIntPtr value, + const basic_format_specs<Char>* specs) -> OutputIt { + int num_digits = count_digits<4>(value); + auto size = to_unsigned(num_digits) + size_t(2); + auto write = [=](reserve_iterator<OutputIt> it) { + *it++ = static_cast<Char>('0'); + *it++ = static_cast<Char>('x'); + return format_uint<4, Char>(it, value, num_digits); + }; + return specs ? write_padded<align::right>(out, *specs, size, write) + : base_iterator(out, write(reserve(out, size))); +} + +template <typename Char, typename OutputIt> +FMT_CONSTEXPR auto write_char(OutputIt out, Char value, + const basic_format_specs<Char>& specs) + -> OutputIt { + return write_padded(out, specs, 1, [=](reserve_iterator<OutputIt> it) { + *it++ = value; + return it; + }); +} +template <typename Char, typename OutputIt> +FMT_CONSTEXPR auto write(OutputIt out, Char value, + const basic_format_specs<Char>& specs, + locale_ref loc = {}) -> OutputIt { + return check_char_specs(specs) + ? write_char(out, value, specs) + : write(out, static_cast<int>(value), specs, loc); +} + +// Data for write_int that doesn't depend on output iterator type. It is used to +// avoid template code bloat. +template <typename Char> struct write_int_data { + size_t size; + size_t padding; + + FMT_CONSTEXPR write_int_data(int num_digits, unsigned prefix, + const basic_format_specs<Char>& specs) + : size((prefix >> 24) + to_unsigned(num_digits)), padding(0) { + if (specs.align == align::numeric) { + auto width = to_unsigned(specs.width); + if (width > size) { + padding = width - size; + size = width; + } + } else if (specs.precision > num_digits) { + size = (prefix >> 24) + to_unsigned(specs.precision); + padding = to_unsigned(specs.precision - num_digits); + } + } +}; + +// Writes an integer in the format +// <left-padding><prefix><numeric-padding><digits><right-padding> +// where <digits> are written by write_digits(it). +// prefix contains chars in three lower bytes and the size in the fourth byte. +template <typename OutputIt, typename Char, typename W> +FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, int num_digits, + unsigned prefix, + const basic_format_specs<Char>& specs, + W write_digits) -> OutputIt { + // Slightly faster check for specs.width == 0 && specs.precision == -1. + if ((specs.width | (specs.precision + 1)) == 0) { + auto it = reserve(out, to_unsigned(num_digits) + (prefix >> 24)); + if (prefix != 0) { + for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8) + *it++ = static_cast<Char>(p & 0xff); + } + return base_iterator(out, write_digits(it)); + } + auto data = write_int_data<Char>(num_digits, prefix, specs); + return write_padded<align::right>( + out, specs, data.size, [=](reserve_iterator<OutputIt> it) { + for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8) + *it++ = static_cast<Char>(p & 0xff); + it = detail::fill_n(it, data.padding, static_cast<Char>('0')); + return write_digits(it); + }); +} + +template <typename Char> class digit_grouping { + private: + thousands_sep_result<Char> sep_; + + struct next_state { + std::string::const_iterator group; + int pos; + }; + next_state initial_state() const { return {sep_.grouping.begin(), 0}; } + + // Returns the next digit group separator position. + int next(next_state& state) const { + if (!sep_.thousands_sep) return max_value<int>(); + if (state.group == sep_.grouping.end()) + return state.pos += sep_.grouping.back(); + if (*state.group <= 0 || *state.group == max_value<char>()) + return max_value<int>(); + state.pos += *state.group++; + return state.pos; + } + + public: + explicit digit_grouping(locale_ref loc, bool localized = true) { + if (localized) + sep_ = thousands_sep<Char>(loc); + else + sep_.thousands_sep = Char(); + } + explicit digit_grouping(thousands_sep_result<Char> sep) : sep_(sep) {} + + Char separator() const { return sep_.thousands_sep; } + + int count_separators(int num_digits) const { + int count = 0; + auto state = initial_state(); + while (num_digits > next(state)) ++count; + return count; + } + + // Applies grouping to digits and write the output to out. + template <typename Out, typename C> + Out apply(Out out, basic_string_view<C> digits) const { + auto num_digits = static_cast<int>(digits.size()); + auto separators = basic_memory_buffer<int>(); + separators.push_back(0); + auto state = initial_state(); + while (int i = next(state)) { + if (i >= num_digits) break; + separators.push_back(i); + } + for (int i = 0, sep_index = static_cast<int>(separators.size() - 1); + i < num_digits; ++i) { + if (num_digits - i == separators[sep_index]) { + *out++ = separator(); + --sep_index; + } + *out++ = static_cast<Char>(digits[to_unsigned(i)]); + } + return out; + } +}; + +template <typename OutputIt, typename UInt, typename Char> +auto write_int_localized(OutputIt out, UInt value, unsigned prefix, + const basic_format_specs<Char>& specs, + const digit_grouping<Char>& grouping) -> OutputIt { + static_assert(std::is_same<uint64_or_128_t<UInt>, UInt>::value, ""); + int num_digits = count_digits(value); + char digits[40]; + format_decimal(digits, value, num_digits); + unsigned size = to_unsigned((prefix != 0 ? 1 : 0) + num_digits + + grouping.count_separators(num_digits)); + return write_padded<align::right>( + out, specs, size, size, [&](reserve_iterator<OutputIt> it) { + if (prefix != 0) *it++ = static_cast<Char>(prefix); + return grouping.apply(it, string_view(digits, to_unsigned(num_digits))); + }); +} + +template <typename OutputIt, typename UInt, typename Char> +auto write_int_localized(OutputIt& out, UInt value, unsigned prefix, + const basic_format_specs<Char>& specs, locale_ref loc) + -> bool { + auto grouping = digit_grouping<Char>(loc); + out = write_int_localized(out, value, prefix, specs, grouping); + return true; +} + +FMT_CONSTEXPR inline void prefix_append(unsigned& prefix, unsigned value) { + prefix |= prefix != 0 ? value << 8 : value; + prefix += (1u + (value > 0xff ? 1 : 0)) << 24; +} + +template <typename UInt> struct write_int_arg { + UInt abs_value; + unsigned prefix; +}; + +template <typename T> +FMT_CONSTEXPR auto make_write_int_arg(T value, sign_t sign) + -> write_int_arg<uint32_or_64_or_128_t<T>> { + auto prefix = 0u; + auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value); + if (is_negative(value)) { + prefix = 0x01000000 | '-'; + abs_value = 0 - abs_value; + } else { + constexpr const unsigned prefixes[4] = {0, 0, 0x1000000u | '+', + 0x1000000u | ' '}; + prefix = prefixes[sign]; + } + return {abs_value, prefix}; +} + +template <typename Char, typename OutputIt, typename T> +FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, write_int_arg<T> arg, + const basic_format_specs<Char>& specs, + locale_ref loc) -> OutputIt { + static_assert(std::is_same<T, uint32_or_64_or_128_t<T>>::value, ""); + auto abs_value = arg.abs_value; + auto prefix = arg.prefix; + switch (specs.type) { + case presentation_type::none: + case presentation_type::dec: { + if (specs.localized && + write_int_localized(out, static_cast<uint64_or_128_t<T>>(abs_value), + prefix, specs, loc)) { + return out; + } + auto num_digits = count_digits(abs_value); + return write_int( + out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) { + return format_decimal<Char>(it, abs_value, num_digits).end; + }); + } + case presentation_type::hex_lower: + case presentation_type::hex_upper: { + bool upper = specs.type == presentation_type::hex_upper; + if (specs.alt) + prefix_append(prefix, unsigned(upper ? 'X' : 'x') << 8 | '0'); + int num_digits = count_digits<4>(abs_value); + return write_int( + out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) { + return format_uint<4, Char>(it, abs_value, num_digits, upper); + }); + } + case presentation_type::bin_lower: + case presentation_type::bin_upper: { + bool upper = specs.type == presentation_type::bin_upper; + if (specs.alt) + prefix_append(prefix, unsigned(upper ? 'B' : 'b') << 8 | '0'); + int num_digits = count_digits<1>(abs_value); + return write_int(out, num_digits, prefix, specs, + [=](reserve_iterator<OutputIt> it) { + return format_uint<1, Char>(it, abs_value, num_digits); + }); + } + case presentation_type::oct: { + int num_digits = count_digits<3>(abs_value); + // Octal prefix '0' is counted as a digit, so only add it if precision + // is not greater than the number of digits. + if (specs.alt && specs.precision <= num_digits && abs_value != 0) + prefix_append(prefix, '0'); + return write_int(out, num_digits, prefix, specs, + [=](reserve_iterator<OutputIt> it) { + return format_uint<3, Char>(it, abs_value, num_digits); + }); + } + case presentation_type::chr: + return write_char(out, static_cast<Char>(abs_value), specs); + default: + throw_format_error("invalid type specifier"); + } + return out; +} +template <typename Char, typename OutputIt, typename T> +FMT_CONSTEXPR FMT_NOINLINE auto write_int_noinline( + OutputIt out, write_int_arg<T> arg, const basic_format_specs<Char>& specs, + locale_ref loc) -> OutputIt { + return write_int(out, arg, specs, loc); +} +template <typename Char, typename OutputIt, typename T, + FMT_ENABLE_IF(is_integral<T>::value && + !std::is_same<T, bool>::value && + std::is_same<OutputIt, buffer_appender<Char>>::value)> +FMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value, + const basic_format_specs<Char>& specs, + locale_ref loc) -> OutputIt { + return write_int_noinline(out, make_write_int_arg(value, specs.sign), specs, + loc); +} +// An inlined version of write used in format string compilation. +template <typename Char, typename OutputIt, typename T, + FMT_ENABLE_IF(is_integral<T>::value && + !std::is_same<T, bool>::value && + !std::is_same<OutputIt, buffer_appender<Char>>::value)> +FMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value, + const basic_format_specs<Char>& specs, + locale_ref loc) -> OutputIt { + return write_int(out, make_write_int_arg(value, specs.sign), specs, loc); +} + +template <typename Char, typename OutputIt> +FMT_CONSTEXPR auto write(OutputIt out, basic_string_view<Char> s, + const basic_format_specs<Char>& specs) -> OutputIt { + auto data = s.data(); + auto size = s.size(); + if (specs.precision >= 0 && to_unsigned(specs.precision) < size) + size = code_point_index(s, to_unsigned(specs.precision)); + auto width = + specs.width != 0 ? compute_width(basic_string_view<Char>(data, size)) : 0; + return write_padded(out, specs, size, width, + [=](reserve_iterator<OutputIt> it) { + return copy_str<Char>(data, data + size, it); + }); +} +template <typename Char, typename OutputIt> +FMT_CONSTEXPR auto write(OutputIt out, + basic_string_view<type_identity_t<Char>> s, + const basic_format_specs<Char>& specs, locale_ref) + -> OutputIt { + check_string_type_spec(specs.type); + return write(out, s, specs); +} +template <typename Char, typename OutputIt> +FMT_CONSTEXPR auto write(OutputIt out, const Char* s, + const basic_format_specs<Char>& specs, locale_ref) + -> OutputIt { + return check_cstring_type_spec(specs.type) + ? write(out, basic_string_view<Char>(s), specs, {}) + : write_ptr<Char>(out, to_uintptr(s), &specs); +} + +template <typename Char, typename OutputIt> +FMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isinf, + basic_format_specs<Char> specs, + const float_specs& fspecs) -> OutputIt { + auto str = + isinf ? (fspecs.upper ? "INF" : "inf") : (fspecs.upper ? "NAN" : "nan"); + constexpr size_t str_size = 3; + auto sign = fspecs.sign; + auto size = str_size + (sign ? 1 : 0); + // Replace '0'-padding with space for non-finite values. + const bool is_zero_fill = + specs.fill.size() == 1 && *specs.fill.data() == static_cast<Char>('0'); + if (is_zero_fill) specs.fill[0] = static_cast<Char>(' '); + return write_padded(out, specs, size, [=](reserve_iterator<OutputIt> it) { + if (sign) *it++ = detail::sign<Char>(sign); + return copy_str<Char>(str, str + str_size, it); + }); +} + +// A decimal floating-point number significand * pow(10, exp). +struct big_decimal_fp { + const char* significand; + int significand_size; + int exponent; +}; + +constexpr auto get_significand_size(const big_decimal_fp& fp) -> int { + return fp.significand_size; +} +template <typename T> +inline auto get_significand_size(const dragonbox::decimal_fp<T>& fp) -> int { + return count_digits(fp.significand); +} + +template <typename Char, typename OutputIt> +constexpr auto write_significand(OutputIt out, const char* significand, + int significand_size) -> OutputIt { + return copy_str<Char>(significand, significand + significand_size, out); +} +template <typename Char, typename OutputIt, typename UInt> +inline auto write_significand(OutputIt out, UInt significand, + int significand_size) -> OutputIt { + return format_decimal<Char>(out, significand, significand_size).end; +} +template <typename Char, typename OutputIt, typename T, typename Grouping> +FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand, + int significand_size, int exponent, + const Grouping& grouping) -> OutputIt { + if (!grouping.separator()) { + out = write_significand<Char>(out, significand, significand_size); + return detail::fill_n(out, exponent, static_cast<Char>('0')); + } + auto buffer = memory_buffer(); + write_significand<char>(appender(buffer), significand, significand_size); + detail::fill_n(appender(buffer), exponent, '0'); + return grouping.apply(out, string_view(buffer.data(), buffer.size())); +} + +template <typename Char, typename UInt, + FMT_ENABLE_IF(std::is_integral<UInt>::value)> +inline auto write_significand(Char* out, UInt significand, int significand_size, + int integral_size, Char decimal_point) -> Char* { + if (!decimal_point) + return format_decimal(out, significand, significand_size).end; + out += significand_size + 1; + Char* end = out; + int floating_size = significand_size - integral_size; + for (int i = floating_size / 2; i > 0; --i) { + out -= 2; + copy2(out, digits2(significand % 100)); + significand /= 100; + } + if (floating_size % 2 != 0) { + *--out = static_cast<Char>('0' + significand % 10); + significand /= 10; + } + *--out = decimal_point; + format_decimal(out - integral_size, significand, integral_size); + return end; +} + +template <typename OutputIt, typename UInt, typename Char, + FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<OutputIt>>::value)> +inline auto write_significand(OutputIt out, UInt significand, + int significand_size, int integral_size, + Char decimal_point) -> OutputIt { + // Buffer is large enough to hold digits (digits10 + 1) and a decimal point. + Char buffer[digits10<UInt>() + 2]; + auto end = write_significand(buffer, significand, significand_size, + integral_size, decimal_point); + return detail::copy_str_noinline<Char>(buffer, end, out); +} + +template <typename OutputIt, typename Char> +FMT_CONSTEXPR auto write_significand(OutputIt out, const char* significand, + int significand_size, int integral_size, + Char decimal_point) -> OutputIt { + out = detail::copy_str_noinline<Char>(significand, + significand + integral_size, out); + if (!decimal_point) return out; + *out++ = decimal_point; + return detail::copy_str_noinline<Char>(significand + integral_size, + significand + significand_size, out); +} + +template <typename OutputIt, typename Char, typename T, typename Grouping> +FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand, + int significand_size, int integral_size, + Char decimal_point, + const Grouping& grouping) -> OutputIt { + if (!grouping.separator()) { + return write_significand(out, significand, significand_size, integral_size, + decimal_point); + } + auto buffer = basic_memory_buffer<Char>(); + write_significand(buffer_appender<Char>(buffer), significand, + significand_size, integral_size, decimal_point); + grouping.apply( + out, basic_string_view<Char>(buffer.data(), to_unsigned(integral_size))); + return detail::copy_str_noinline<Char>(buffer.data() + integral_size, + buffer.end(), out); +} + +template <typename OutputIt, typename DecimalFP, typename Char, + typename Grouping = digit_grouping<Char>> +FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP& fp, + const basic_format_specs<Char>& specs, + float_specs fspecs, locale_ref loc) + -> OutputIt { + auto significand = fp.significand; + int significand_size = get_significand_size(fp); + constexpr Char zero = static_cast<Char>('0'); + auto sign = fspecs.sign; + size_t size = to_unsigned(significand_size) + (sign ? 1 : 0); + using iterator = reserve_iterator<OutputIt>; + + Char decimal_point = + fspecs.locale ? detail::decimal_point<Char>(loc) : static_cast<Char>('.'); + + int output_exp = fp.exponent + significand_size - 1; + auto use_exp_format = [=]() { + if (fspecs.format == float_format::exp) return true; + if (fspecs.format != float_format::general) return false; + // Use the fixed notation if the exponent is in [exp_lower, exp_upper), + // e.g. 0.0001 instead of 1e-04. Otherwise use the exponent notation. + const int exp_lower = -4, exp_upper = 16; + return output_exp < exp_lower || + output_exp >= (fspecs.precision > 0 ? fspecs.precision : exp_upper); + }; + if (use_exp_format()) { + int num_zeros = 0; + if (fspecs.showpoint) { + num_zeros = fspecs.precision - significand_size; + if (num_zeros < 0) num_zeros = 0; + size += to_unsigned(num_zeros); + } else if (significand_size == 1) { + decimal_point = Char(); + } + auto abs_output_exp = output_exp >= 0 ? output_exp : -output_exp; + int exp_digits = 2; + if (abs_output_exp >= 100) exp_digits = abs_output_exp >= 1000 ? 4 : 3; + + size += to_unsigned((decimal_point ? 1 : 0) + 2 + exp_digits); + char exp_char = fspecs.upper ? 'E' : 'e'; + auto write = [=](iterator it) { + if (sign) *it++ = detail::sign<Char>(sign); + // Insert a decimal point after the first digit and add an exponent. + it = write_significand(it, significand, significand_size, 1, + decimal_point); + if (num_zeros > 0) it = detail::fill_n(it, num_zeros, zero); + *it++ = static_cast<Char>(exp_char); + return write_exponent<Char>(output_exp, it); + }; + return specs.width > 0 ? write_padded<align::right>(out, specs, size, write) + : base_iterator(out, write(reserve(out, size))); + } + + int exp = fp.exponent + significand_size; + if (fp.exponent >= 0) { + // 1234e5 -> 123400000[.0+] + size += to_unsigned(fp.exponent); + int num_zeros = fspecs.precision - exp; +#ifdef FMT_FUZZ + if (num_zeros > 5000) + throw std::runtime_error("fuzz mode - avoiding excessive cpu use"); +#endif + if (fspecs.showpoint) { + if (num_zeros <= 0 && fspecs.format != float_format::fixed) num_zeros = 1; + if (num_zeros > 0) size += to_unsigned(num_zeros) + 1; + } + auto grouping = Grouping(loc, fspecs.locale); + size += to_unsigned(grouping.count_separators(significand_size)); + return write_padded<align::right>(out, specs, size, [&](iterator it) { + if (sign) *it++ = detail::sign<Char>(sign); + it = write_significand<Char>(it, significand, significand_size, + fp.exponent, grouping); + if (!fspecs.showpoint) return it; + *it++ = decimal_point; + return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it; + }); + } else if (exp > 0) { + // 1234e-2 -> 12.34[0+] + int num_zeros = fspecs.showpoint ? fspecs.precision - significand_size : 0; + size += 1 + to_unsigned(num_zeros > 0 ? num_zeros : 0); + auto grouping = Grouping(loc, fspecs.locale); + size += to_unsigned(grouping.count_separators(significand_size)); + return write_padded<align::right>(out, specs, size, [&](iterator it) { + if (sign) *it++ = detail::sign<Char>(sign); + it = write_significand(it, significand, significand_size, exp, + decimal_point, grouping); + return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it; + }); + } + // 1234e-6 -> 0.001234 + int num_zeros = -exp; + if (significand_size == 0 && fspecs.precision >= 0 && + fspecs.precision < num_zeros) { + num_zeros = fspecs.precision; + } + bool pointy = num_zeros != 0 || significand_size != 0 || fspecs.showpoint; + size += 1 + (pointy ? 1 : 0) + to_unsigned(num_zeros); + return write_padded<align::right>(out, specs, size, [&](iterator it) { + if (sign) *it++ = detail::sign<Char>(sign); + *it++ = zero; + if (!pointy) return it; + *it++ = decimal_point; + it = detail::fill_n(it, num_zeros, zero); + return write_significand<Char>(it, significand, significand_size); + }); +} + +template <typename Char> class fallback_digit_grouping { + public: + constexpr fallback_digit_grouping(locale_ref, bool) {} + + constexpr Char separator() const { return Char(); } + + constexpr int count_separators(int) const { return 0; } + + template <typename Out, typename C> + constexpr Out apply(Out out, basic_string_view<C>) const { + return out; + } +}; + +template <typename OutputIt, typename DecimalFP, typename Char> +FMT_CONSTEXPR20 auto write_float(OutputIt out, const DecimalFP& fp, + const basic_format_specs<Char>& specs, + float_specs fspecs, locale_ref loc) + -> OutputIt { + if (is_constant_evaluated()) { + return do_write_float<OutputIt, DecimalFP, Char, + fallback_digit_grouping<Char>>(out, fp, specs, fspecs, + loc); + } else { + return do_write_float(out, fp, specs, fspecs, loc); + } +} + +template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)> +FMT_CONSTEXPR20 bool isinf(T value) { + if (is_constant_evaluated()) { +#if defined(__cpp_if_constexpr) + if constexpr (std::numeric_limits<double>::is_iec559) { + auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value)); + constexpr auto significand_bits = + dragonbox::float_info<double>::significand_bits; + return (bits & exponent_mask<double>()) && + !(bits & ((uint64_t(1) << significand_bits) - 1)); + } +#endif + } + return std::isinf(value); +} + +template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)> +FMT_CONSTEXPR20 bool isfinite(T value) { + if (is_constant_evaluated()) { +#if defined(__cpp_if_constexpr) + if constexpr (std::numeric_limits<double>::is_iec559) { + auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value)); + return (bits & exponent_mask<double>()) != exponent_mask<double>(); + } +#endif + } + return std::isfinite(value); +} + +template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)> +FMT_INLINE FMT_CONSTEXPR bool signbit(T value) { + if (is_constant_evaluated()) { +#ifdef __cpp_if_constexpr + if constexpr (std::numeric_limits<double>::is_iec559) { + auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value)); + return (bits & (uint64_t(1) << (num_bits<uint64_t>() - 1))) != 0; + } +#endif + } + return std::signbit(value); +} + +template <typename Char, typename OutputIt, typename T, + FMT_ENABLE_IF(std::is_floating_point<T>::value)> +FMT_CONSTEXPR20 auto write(OutputIt out, T value, + basic_format_specs<Char> specs, locale_ref loc = {}) + -> OutputIt { + if (const_check(!is_supported_floating_point(value))) return out; + float_specs fspecs = parse_float_type_spec(specs); + fspecs.sign = specs.sign; + if (detail::signbit(value)) { // value < 0 is false for NaN so use signbit. + fspecs.sign = sign::minus; + value = -value; + } else if (fspecs.sign == sign::minus) { + fspecs.sign = sign::none; + } + + if (!detail::isfinite(value)) + return write_nonfinite(out, detail::isinf(value), specs, fspecs); + + if (specs.align == align::numeric && fspecs.sign) { + auto it = reserve(out, 1); + *it++ = detail::sign<Char>(fspecs.sign); + out = base_iterator(out, it); + fspecs.sign = sign::none; + if (specs.width != 0) --specs.width; + } + + memory_buffer buffer; + if (fspecs.format == float_format::hex) { + if (fspecs.sign) buffer.push_back(detail::sign<char>(fspecs.sign)); + snprintf_float(promote_float(value), specs.precision, fspecs, buffer); + return write_bytes<align::right>(out, {buffer.data(), buffer.size()}, + specs); + } + int precision = specs.precision >= 0 || specs.type == presentation_type::none + ? specs.precision + : 6; + if (fspecs.format == float_format::exp) { + if (precision == max_value<int>()) + throw_format_error("number is too big"); + else + ++precision; + } + if (const_check(std::is_same<T, float>())) fspecs.binary32 = true; + if (!is_fast_float<T>()) fspecs.fallback = true; + int exp = format_float(promote_float(value), precision, fspecs, buffer); + fspecs.precision = precision; + auto fp = big_decimal_fp{buffer.data(), static_cast<int>(buffer.size()), exp}; + return write_float(out, fp, specs, fspecs, loc); +} + +template <typename Char, typename OutputIt, typename T, + FMT_ENABLE_IF(is_fast_float<T>::value)> +FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt { + if (is_constant_evaluated()) { + return write(out, value, basic_format_specs<Char>()); + } + + if (const_check(!is_supported_floating_point(value))) return out; + + using floaty = conditional_t<std::is_same<T, long double>::value, double, T>; + using uint = typename dragonbox::float_info<floaty>::carrier_uint; + auto bits = bit_cast<uint>(value); + + auto fspecs = float_specs(); + if (detail::signbit(value)) { + fspecs.sign = sign::minus; + value = -value; + } + + constexpr auto specs = basic_format_specs<Char>(); + uint mask = exponent_mask<floaty>(); + if ((bits & mask) == mask) + return write_nonfinite(out, std::isinf(value), specs, fspecs); + + auto dec = dragonbox::to_decimal(static_cast<floaty>(value)); + return write_float(out, dec, specs, fspecs, {}); +} + +template <typename Char, typename OutputIt, typename T, + FMT_ENABLE_IF(std::is_floating_point<T>::value && + !is_fast_float<T>::value)> +inline auto write(OutputIt out, T value) -> OutputIt { + return write(out, value, basic_format_specs<Char>()); +} + +template <typename Char, typename OutputIt> +auto write(OutputIt out, monostate, basic_format_specs<Char> = {}, + locale_ref = {}) -> OutputIt { + FMT_ASSERT(false, ""); + return out; +} + +template <typename Char, typename OutputIt> +FMT_CONSTEXPR auto write(OutputIt out, basic_string_view<Char> value) + -> OutputIt { + auto it = reserve(out, value.size()); + it = copy_str_noinline<Char>(value.begin(), value.end(), it); + return base_iterator(out, it); +} + +template <typename Char, typename OutputIt, typename T, + FMT_ENABLE_IF(is_string<T>::value)> +constexpr auto write(OutputIt out, const T& value) -> OutputIt { + return write<Char>(out, to_string_view(value)); +} + +template <typename Char, typename OutputIt, typename T, + FMT_ENABLE_IF(is_integral<T>::value && + !std::is_same<T, bool>::value && + !std::is_same<T, Char>::value)> +FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt { + auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value); + bool negative = is_negative(value); + // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer. + if (negative) abs_value = ~abs_value + 1; + int num_digits = count_digits(abs_value); + auto size = (negative ? 1 : 0) + static_cast<size_t>(num_digits); + auto it = reserve(out, size); + if (auto ptr = to_pointer<Char>(it, size)) { + if (negative) *ptr++ = static_cast<Char>('-'); + format_decimal<Char>(ptr, abs_value, num_digits); + return out; + } + if (negative) *it++ = static_cast<Char>('-'); + it = format_decimal<Char>(it, abs_value, num_digits).end; + return base_iterator(out, it); +} + +// FMT_ENABLE_IF() condition separated to workaround an MSVC bug. +template < + typename Char, typename OutputIt, typename T, + bool check = + std::is_enum<T>::value && !std::is_same<T, Char>::value && + mapped_type_constant<T, basic_format_context<OutputIt, Char>>::value != + type::custom_type, + FMT_ENABLE_IF(check)> +FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt { + return write<Char>( + out, static_cast<typename std::underlying_type<T>::type>(value)); +} + +template <typename Char, typename OutputIt, typename T, + FMT_ENABLE_IF(std::is_same<T, bool>::value)> +FMT_CONSTEXPR auto write(OutputIt out, T value, + const basic_format_specs<Char>& specs = {}, + locale_ref = {}) -> OutputIt { + return specs.type != presentation_type::none && + specs.type != presentation_type::string + ? write(out, value ? 1 : 0, specs, {}) + : write_bytes(out, value ? "true" : "false", specs); +} + +template <typename Char, typename OutputIt> +FMT_CONSTEXPR auto write(OutputIt out, Char value) -> OutputIt { + auto it = reserve(out, 1); + *it++ = value; + return base_iterator(out, it); +} + +template <typename Char, typename OutputIt> +FMT_CONSTEXPR_CHAR_TRAITS auto write(OutputIt out, const Char* value) + -> OutputIt { + if (!value) { + throw_format_error("string pointer is null"); + } else { + out = write(out, basic_string_view<Char>(value)); + } + return out; +} + +template <typename Char, typename OutputIt, typename T, + FMT_ENABLE_IF(std::is_same<T, void>::value)> +auto write(OutputIt out, const T* value, + const basic_format_specs<Char>& specs = {}, locale_ref = {}) + -> OutputIt { + check_pointer_type_spec(specs.type, error_handler()); + return write_ptr<Char>(out, to_uintptr(value), &specs); +} + +// A write overload that handles implicit conversions. +template <typename Char, typename OutputIt, typename T, + typename Context = basic_format_context<OutputIt, Char>> +FMT_CONSTEXPR auto write(OutputIt out, const T& value) -> enable_if_t< + std::is_class<T>::value && !is_string<T>::value && + !std::is_same<T, Char>::value && + !std::is_same<const T&, + decltype(arg_mapper<Context>().map(value))>::value, + OutputIt> { + return write<Char>(out, arg_mapper<Context>().map(value)); +} + +template <typename Char, typename OutputIt, typename T, + typename Context = basic_format_context<OutputIt, Char>> +FMT_CONSTEXPR auto write(OutputIt out, const T& value) + -> enable_if_t<mapped_type_constant<T, Context>::value == type::custom_type, + OutputIt> { + using formatter_type = + conditional_t<has_formatter<T, Context>::value, + typename Context::template formatter_type<T>, + fallback_formatter<T, Char>>; + auto ctx = Context(out, {}, {}); + return formatter_type().format(value, ctx); +} + +// An argument visitor that formats the argument and writes it via the output +// iterator. It's a class and not a generic lambda for compatibility with C++11. +template <typename Char> struct default_arg_formatter { + using iterator = buffer_appender<Char>; + using context = buffer_context<Char>; + + iterator out; + basic_format_args<context> args; + locale_ref loc; + + template <typename T> auto operator()(T value) -> iterator { + return write<Char>(out, value); + } + auto operator()(typename basic_format_arg<context>::handle h) -> iterator { + basic_format_parse_context<Char> parse_ctx({}); + context format_ctx(out, args, loc); + h.format(parse_ctx, format_ctx); + return format_ctx.out(); + } +}; + +template <typename Char> struct arg_formatter { + using iterator = buffer_appender<Char>; + using context = buffer_context<Char>; + + iterator out; + const basic_format_specs<Char>& specs; + locale_ref locale; + + template <typename T> + FMT_CONSTEXPR FMT_INLINE auto operator()(T value) -> iterator { + return detail::write(out, value, specs, locale); + } + auto operator()(typename basic_format_arg<context>::handle) -> iterator { + // User-defined types are handled separately because they require access + // to the parse context. + return out; + } +}; + +template <typename Char> struct custom_formatter { + basic_format_parse_context<Char>& parse_ctx; + buffer_context<Char>& ctx; + + void operator()( + typename basic_format_arg<buffer_context<Char>>::handle h) const { + h.format(parse_ctx, ctx); + } + template <typename T> void operator()(T) const {} +}; + +template <typename T> +using is_integer = + bool_constant<is_integral<T>::value && !std::is_same<T, bool>::value && + !std::is_same<T, char>::value && + !std::is_same<T, wchar_t>::value>; + +template <typename ErrorHandler> class width_checker { + public: + explicit FMT_CONSTEXPR width_checker(ErrorHandler& eh) : handler_(eh) {} + + template <typename T, FMT_ENABLE_IF(is_integer<T>::value)> + FMT_CONSTEXPR auto operator()(T value) -> unsigned long long { + if (is_negative(value)) handler_.on_error("negative width"); + return static_cast<unsigned long long>(value); + } + + template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)> + FMT_CONSTEXPR auto operator()(T) -> unsigned long long { + handler_.on_error("width is not integer"); + return 0; + } + + private: + ErrorHandler& handler_; +}; + +template <typename ErrorHandler> class precision_checker { + public: + explicit FMT_CONSTEXPR precision_checker(ErrorHandler& eh) : handler_(eh) {} + + template <typename T, FMT_ENABLE_IF(is_integer<T>::value)> + FMT_CONSTEXPR auto operator()(T value) -> unsigned long long { + if (is_negative(value)) handler_.on_error("negative precision"); + return static_cast<unsigned long long>(value); + } + + template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)> + FMT_CONSTEXPR auto operator()(T) -> unsigned long long { + handler_.on_error("precision is not integer"); + return 0; + } + + private: + ErrorHandler& handler_; +}; + +template <template <typename> class Handler, typename FormatArg, + typename ErrorHandler> +FMT_CONSTEXPR auto get_dynamic_spec(FormatArg arg, ErrorHandler eh) -> int { + unsigned long long value = visit_format_arg(Handler<ErrorHandler>(eh), arg); + if (value > to_unsigned(max_value<int>())) eh.on_error("number is too big"); + return static_cast<int>(value); +} + +template <typename Context, typename ID> +FMT_CONSTEXPR auto get_arg(Context& ctx, ID id) -> + typename Context::format_arg { + auto arg = ctx.arg(id); + if (!arg) ctx.on_error("argument not found"); + return arg; +} + +// The standard format specifier handler with checking. +template <typename Char> class specs_handler : public specs_setter<Char> { + private: + basic_format_parse_context<Char>& parse_context_; + buffer_context<Char>& context_; + + // This is only needed for compatibility with gcc 4.4. + using format_arg = basic_format_arg<buffer_context<Char>>; + + FMT_CONSTEXPR auto get_arg(auto_id) -> format_arg { + return detail::get_arg(context_, parse_context_.next_arg_id()); + } + + FMT_CONSTEXPR auto get_arg(int arg_id) -> format_arg { + parse_context_.check_arg_id(arg_id); + return detail::get_arg(context_, arg_id); + } + + FMT_CONSTEXPR auto get_arg(basic_string_view<Char> arg_id) -> format_arg { + parse_context_.check_arg_id(arg_id); + return detail::get_arg(context_, arg_id); + } + + public: + FMT_CONSTEXPR specs_handler(basic_format_specs<Char>& specs, + basic_format_parse_context<Char>& parse_ctx, + buffer_context<Char>& ctx) + : specs_setter<Char>(specs), parse_context_(parse_ctx), context_(ctx) {} + + template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) { + this->specs_.width = get_dynamic_spec<width_checker>( + get_arg(arg_id), context_.error_handler()); + } + + template <typename Id> FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) { + this->specs_.precision = get_dynamic_spec<precision_checker>( + get_arg(arg_id), context_.error_handler()); + } + + void on_error(const char* message) { context_.on_error(message); } +}; + +template <template <typename> class Handler, typename Context> +FMT_CONSTEXPR void handle_dynamic_spec(int& value, + arg_ref<typename Context::char_type> ref, + Context& ctx) { + switch (ref.kind) { + case arg_id_kind::none: + break; + case arg_id_kind::index: + value = detail::get_dynamic_spec<Handler>(ctx.arg(ref.val.index), + ctx.error_handler()); + break; + case arg_id_kind::name: + value = detail::get_dynamic_spec<Handler>(ctx.arg(ref.val.name), + ctx.error_handler()); + break; + } +} + +#define FMT_STRING_IMPL(s, base, explicit) \ + [] { \ + /* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \ + /* Use a macro-like name to avoid shadowing warnings. */ \ + struct FMT_GCC_VISIBILITY_HIDDEN FMT_COMPILE_STRING : base { \ + using char_type = fmt::remove_cvref_t<decltype(s[0])>; \ + FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit \ + operator fmt::basic_string_view<char_type>() const { \ + return fmt::detail_exported::compile_string_to_view<char_type>(s); \ + } \ + }; \ + return FMT_COMPILE_STRING(); \ + }() + +/** + \rst + Constructs a compile-time format string from a string literal *s*. + + **Example**:: + + // A compile-time error because 'd' is an invalid specifier for strings. + std::string s = fmt::format(FMT_STRING("{:d}"), "foo"); + \endrst + */ +#define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::compile_string, ) + +#if FMT_USE_USER_DEFINED_LITERALS +template <typename Char> struct udl_formatter { + basic_string_view<Char> str; + + template <typename... T> + auto operator()(T&&... args) const -> std::basic_string<Char> { + return vformat(str, fmt::make_args_checked<T...>(str, args...)); + } +}; + +# if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS +template <typename T, typename Char, size_t N, + fmt::detail_exported::fixed_string<Char, N> Str> +struct statically_named_arg : view { + static constexpr auto name = Str.data; + + const T& value; + statically_named_arg(const T& v) : value(v) {} +}; + +template <typename T, typename Char, size_t N, + fmt::detail_exported::fixed_string<Char, N> Str> +struct is_named_arg<statically_named_arg<T, Char, N, Str>> : std::true_type {}; + +template <typename T, typename Char, size_t N, + fmt::detail_exported::fixed_string<Char, N> Str> +struct is_statically_named_arg<statically_named_arg<T, Char, N, Str>> + : std::true_type {}; + +template <typename Char, size_t N, + fmt::detail_exported::fixed_string<Char, N> Str> +struct udl_arg { + template <typename T> auto operator=(T&& value) const { + return statically_named_arg<T, Char, N, Str>(std::forward<T>(value)); + } +}; +# else +template <typename Char> struct udl_arg { + const Char* str; + + template <typename T> auto operator=(T&& value) const -> named_arg<Char, T> { + return {str, std::forward<T>(value)}; + } +}; +# endif +#endif // FMT_USE_USER_DEFINED_LITERALS + +template <typename Locale, typename Char> +auto vformat(const Locale& loc, basic_string_view<Char> format_str, + basic_format_args<buffer_context<type_identity_t<Char>>> args) + -> std::basic_string<Char> { + basic_memory_buffer<Char> buffer; + detail::vformat_to(buffer, format_str, args, detail::locale_ref(loc)); + return {buffer.data(), buffer.size()}; +} + +using format_func = void (*)(detail::buffer<char>&, int, const char*); + +FMT_API void format_error_code(buffer<char>& out, int error_code, + string_view message) FMT_NOEXCEPT; + +FMT_API void report_error(format_func func, int error_code, + const char* message) FMT_NOEXCEPT; +FMT_END_DETAIL_NAMESPACE + +FMT_API auto vsystem_error(int error_code, string_view format_str, + format_args args) -> std::system_error; + +/** + \rst + Constructs :class:`std::system_error` with a message formatted with + ``fmt::format(fmt, args...)``. + *error_code* is a system error code as given by ``errno``. + + **Example**:: + + // This throws std::system_error with the description + // cannot open file 'madeup': No such file or directory + // or similar (system message may vary). + const char* filename = "madeup"; + std::FILE* file = std::fopen(filename, "r"); + if (!file) + throw fmt::system_error(errno, "cannot open file '{}'", filename); + \endrst +*/ +template <typename... T> +auto system_error(int error_code, format_string<T...> fmt, T&&... args) + -> std::system_error { + return vsystem_error(error_code, fmt, fmt::make_format_args(args...)); +} + +/** + \rst + Formats an error message for an error returned by an operating system or a + language runtime, for example a file opening error, and writes it to *out*. + The format is the same as the one used by ``std::system_error(ec, message)`` + where ``ec`` is ``std::error_code(error_code, std::generic_category()})``. + It is implementation-defined but normally looks like: + + .. parsed-literal:: + *<message>*: *<system-message>* + + where *<message>* is the passed message and *<system-message>* is the system + message corresponding to the error code. + *error_code* is a system error code as given by ``errno``. + \endrst + */ +FMT_API void format_system_error(detail::buffer<char>& out, int error_code, + const char* message) FMT_NOEXCEPT; + +// Reports a system error without throwing an exception. +// Can be used to report errors from destructors. +FMT_API void report_system_error(int error_code, + const char* message) FMT_NOEXCEPT; + +/** Fast integer formatter. */ +class format_int { + private: + // Buffer should be large enough to hold all digits (digits10 + 1), + // a sign and a null character. + enum { buffer_size = std::numeric_limits<unsigned long long>::digits10 + 3 }; + mutable char buffer_[buffer_size]; + char* str_; + + template <typename UInt> auto format_unsigned(UInt value) -> char* { + auto n = static_cast<detail::uint32_or_64_or_128_t<UInt>>(value); + return detail::format_decimal(buffer_, n, buffer_size - 1).begin; + } + + template <typename Int> auto format_signed(Int value) -> char* { + auto abs_value = static_cast<detail::uint32_or_64_or_128_t<Int>>(value); + bool negative = value < 0; + if (negative) abs_value = 0 - abs_value; + auto begin = format_unsigned(abs_value); + if (negative) *--begin = '-'; + return begin; + } + + public: + explicit format_int(int value) : str_(format_signed(value)) {} + explicit format_int(long value) : str_(format_signed(value)) {} + explicit format_int(long long value) : str_(format_signed(value)) {} + explicit format_int(unsigned value) : str_(format_unsigned(value)) {} + explicit format_int(unsigned long value) : str_(format_unsigned(value)) {} + explicit format_int(unsigned long long value) + : str_(format_unsigned(value)) {} + + /** Returns the number of characters written to the output buffer. */ + auto size() const -> size_t { + return detail::to_unsigned(buffer_ - str_ + buffer_size - 1); + } + + /** + Returns a pointer to the output buffer content. No terminating null + character is appended. + */ + auto data() const -> const char* { return str_; } + + /** + Returns a pointer to the output buffer content with terminating null + character appended. + */ + auto c_str() const -> const char* { + buffer_[buffer_size - 1] = '\0'; + return str_; + } + + /** + \rst + Returns the content of the output buffer as an ``std::string``. + \endrst + */ + auto str() const -> std::string { return std::string(str_, size()); } +}; + +template <typename T, typename Char> +template <typename FormatContext> +FMT_CONSTEXPR FMT_INLINE auto +formatter<T, Char, + enable_if_t<detail::type_constant<T, Char>::value != + detail::type::custom_type>>::format(const T& val, + FormatContext& ctx) + const -> decltype(ctx.out()) { + if (specs_.width_ref.kind != detail::arg_id_kind::none || + specs_.precision_ref.kind != detail::arg_id_kind::none) { + auto specs = specs_; + detail::handle_dynamic_spec<detail::width_checker>(specs.width, + specs.width_ref, ctx); + detail::handle_dynamic_spec<detail::precision_checker>( + specs.precision, specs.precision_ref, ctx); + return detail::write<Char>(ctx.out(), val, specs, ctx.locale()); + } + return detail::write<Char>(ctx.out(), val, specs_, ctx.locale()); +} + +#define FMT_FORMAT_AS(Type, Base) \ + template <typename Char> \ + struct formatter<Type, Char> : formatter<Base, Char> { \ + template <typename FormatContext> \ + auto format(Type const& val, FormatContext& ctx) const \ + -> decltype(ctx.out()) { \ + return formatter<Base, Char>::format(static_cast<Base>(val), ctx); \ + } \ + } + +FMT_FORMAT_AS(signed char, int); +FMT_FORMAT_AS(unsigned char, unsigned); +FMT_FORMAT_AS(short, int); +FMT_FORMAT_AS(unsigned short, unsigned); +FMT_FORMAT_AS(long, long long); +FMT_FORMAT_AS(unsigned long, unsigned long long); +FMT_FORMAT_AS(Char*, const Char*); +FMT_FORMAT_AS(std::basic_string<Char>, basic_string_view<Char>); +FMT_FORMAT_AS(std::nullptr_t, const void*); +FMT_FORMAT_AS(detail::byte, unsigned char); +FMT_FORMAT_AS(detail::std_string_view<Char>, basic_string_view<Char>); + +template <typename Char> +struct formatter<void*, Char> : formatter<const void*, Char> { + template <typename FormatContext> + auto format(void* val, FormatContext& ctx) const -> decltype(ctx.out()) { + return formatter<const void*, Char>::format(val, ctx); + } +}; + +template <typename Char, size_t N> +struct formatter<Char[N], Char> : formatter<basic_string_view<Char>, Char> { + template <typename FormatContext> + FMT_CONSTEXPR auto format(const Char* val, FormatContext& ctx) const + -> decltype(ctx.out()) { + return formatter<basic_string_view<Char>, Char>::format(val, ctx); + } +}; + +// A formatter for types known only at run time such as variant alternatives. +// +// Usage: +// using variant = std::variant<int, std::string>; +// template <> +// struct formatter<variant>: dynamic_formatter<> { +// auto format(const variant& v, format_context& ctx) { +// return visit([&](const auto& val) { +// return dynamic_formatter<>::format(val, ctx); +// }, v); +// } +// }; +template <typename Char = char> class dynamic_formatter { + private: + detail::dynamic_format_specs<Char> specs_; + const Char* format_str_; + + struct null_handler : detail::error_handler { + void on_align(align_t) {} + void on_sign(sign_t) {} + void on_hash() {} + }; + + template <typename Context> void handle_specs(Context& ctx) { + detail::handle_dynamic_spec<detail::width_checker>(specs_.width, + specs_.width_ref, ctx); + detail::handle_dynamic_spec<detail::precision_checker>( + specs_.precision, specs_.precision_ref, ctx); + } + + public: + template <typename ParseContext> + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + format_str_ = ctx.begin(); + // Checks are deferred to formatting time when the argument type is known. + detail::dynamic_specs_handler<ParseContext> handler(specs_, ctx); + return detail::parse_format_specs(ctx.begin(), ctx.end(), handler); + } + + template <typename T, typename FormatContext> + auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) { + handle_specs(ctx); + detail::specs_checker<null_handler> checker( + null_handler(), detail::mapped_type_constant<T, FormatContext>::value); + checker.on_align(specs_.align); + if (specs_.sign != sign::none) checker.on_sign(specs_.sign); + if (specs_.alt) checker.on_hash(); + if (specs_.precision >= 0) checker.end_precision(); + return detail::write<Char>(ctx.out(), val, specs_, ctx.locale()); + } +}; + +/** + \rst + Converts ``p`` to ``const void*`` for pointer formatting. + + **Example**:: + + auto s = fmt::format("{}", fmt::ptr(p)); + \endrst + */ +template <typename T> auto ptr(T p) -> const void* { + static_assert(std::is_pointer<T>::value, ""); + return detail::bit_cast<const void*>(p); +} +template <typename T> auto ptr(const std::unique_ptr<T>& p) -> const void* { + return p.get(); +} +template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* { + return p.get(); +} + +class bytes { + private: + string_view data_; + friend struct formatter<bytes>; + + public: + explicit bytes(string_view data) : data_(data) {} +}; + +template <> struct formatter<bytes> { + private: + detail::dynamic_format_specs<char> specs_; + + public: + template <typename ParseContext> + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + using handler_type = detail::dynamic_specs_handler<ParseContext>; + detail::specs_checker<handler_type> handler(handler_type(specs_, ctx), + detail::type::string_type); + auto it = parse_format_specs(ctx.begin(), ctx.end(), handler); + detail::check_string_type_spec(specs_.type, ctx.error_handler()); + return it; + } + + template <typename FormatContext> + auto format(bytes b, FormatContext& ctx) -> decltype(ctx.out()) { + detail::handle_dynamic_spec<detail::width_checker>(specs_.width, + specs_.width_ref, ctx); + detail::handle_dynamic_spec<detail::precision_checker>( + specs_.precision, specs_.precision_ref, ctx); + return detail::write_bytes(ctx.out(), b.data_, specs_); + } +}; + +// group_digits_view is not derived from view because it copies the argument. +template <typename T> struct group_digits_view { T value; }; + +/** + \rst + Returns a view that formats an integer value using ',' as a locale-independent + thousands separator. + + **Example**:: + + fmt::print("{}", fmt::group_digits(12345)); + // Output: "12,345" + \endrst + */ +template <typename T> auto group_digits(T value) -> group_digits_view<T> { + return {value}; +} + +template <typename T> struct formatter<group_digits_view<T>> : formatter<T> { + private: + detail::dynamic_format_specs<char> specs_; + + public: + template <typename ParseContext> + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + using handler_type = detail::dynamic_specs_handler<ParseContext>; + detail::specs_checker<handler_type> handler(handler_type(specs_, ctx), + detail::type::int_type); + auto it = parse_format_specs(ctx.begin(), ctx.end(), handler); + detail::check_string_type_spec(specs_.type, ctx.error_handler()); + return it; + } + + template <typename FormatContext> + auto format(group_digits_view<T> t, FormatContext& ctx) + -> decltype(ctx.out()) { + detail::handle_dynamic_spec<detail::width_checker>(specs_.width, + specs_.width_ref, ctx); + detail::handle_dynamic_spec<detail::precision_checker>( + specs_.precision, specs_.precision_ref, ctx); + return detail::write_int_localized( + ctx.out(), static_cast<detail::uint64_or_128_t<T>>(t.value), 0, specs_, + detail::digit_grouping<char>({"\3", ','})); + } +}; + +template <typename It, typename Sentinel, typename Char = char> +struct join_view : detail::view { + It begin; + Sentinel end; + basic_string_view<Char> sep; + + join_view(It b, Sentinel e, basic_string_view<Char> s) + : begin(b), end(e), sep(s) {} +}; + +template <typename It, typename Sentinel, typename Char> +using arg_join FMT_DEPRECATED_ALIAS = join_view<It, Sentinel, Char>; + +template <typename It, typename Sentinel, typename Char> +struct formatter<join_view<It, Sentinel, Char>, Char> { + private: + using value_type = +#ifdef __cpp_lib_ranges + std::iter_value_t<It>; +#else + typename std::iterator_traits<It>::value_type; +#endif + using context = buffer_context<Char>; + using mapper = detail::arg_mapper<context>; + + template <typename T, FMT_ENABLE_IF(has_formatter<T, context>::value)> + static auto map(const T& value) -> const T& { + return value; + } + template <typename T, FMT_ENABLE_IF(!has_formatter<T, context>::value)> + static auto map(const T& value) -> decltype(mapper().map(value)) { + return mapper().map(value); + } + + using formatter_type = + conditional_t<is_formattable<value_type, Char>::value, + formatter<remove_cvref_t<decltype(map( + std::declval<const value_type&>()))>, + Char>, + detail::fallback_formatter<value_type, Char>>; + + formatter_type value_formatter_; + + public: + template <typename ParseContext> + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return value_formatter_.parse(ctx); + } + + template <typename FormatContext> + auto format(const join_view<It, Sentinel, Char>& value, FormatContext& ctx) + -> decltype(ctx.out()) { + auto it = value.begin; + auto out = ctx.out(); + if (it != value.end) { + out = value_formatter_.format(map(*it), ctx); + ++it; + while (it != value.end) { + out = detail::copy_str<Char>(value.sep.begin(), value.sep.end(), out); + ctx.advance_to(out); + out = value_formatter_.format(map(*it), ctx); + ++it; + } + } + return out; + } +}; + +/** + Returns a view that formats the iterator range `[begin, end)` with elements + separated by `sep`. + */ +template <typename It, typename Sentinel> +auto join(It begin, Sentinel end, string_view sep) -> join_view<It, Sentinel> { + return {begin, end, sep}; +} + +/** + \rst + Returns a view that formats `range` with elements separated by `sep`. + + **Example**:: + + std::vector<int> v = {1, 2, 3}; + fmt::print("{}", fmt::join(v, ", ")); + // Output: "1, 2, 3" + + ``fmt::join`` applies passed format specifiers to the range elements:: + + fmt::print("{:02}", fmt::join(v, ", ")); + // Output: "01, 02, 03" + \endrst + */ +template <typename Range> +auto join(Range&& range, string_view sep) + -> join_view<detail::iterator_t<Range>, detail::sentinel_t<Range>> { + return join(std::begin(range), std::end(range), sep); +} + +/** + \rst + Converts *value* to ``std::string`` using the default format for type *T*. + + **Example**:: + + #include <fmt/format.h> + + std::string answer = fmt::to_string(42); + \endrst + */ +template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)> +inline auto to_string(const T& value) -> std::string { + auto result = std::string(); + detail::write<char>(std::back_inserter(result), value); + return result; +} + +template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)> +FMT_NODISCARD inline auto to_string(T value) -> std::string { + // The buffer should be large enough to store the number including the sign + // or "false" for bool. + constexpr int max_size = detail::digits10<T>() + 2; + char buffer[max_size > 5 ? static_cast<unsigned>(max_size) : 5]; + char* begin = buffer; + return std::string(begin, detail::write<char>(begin, value)); +} + +template <typename Char, size_t SIZE> +FMT_NODISCARD auto to_string(const basic_memory_buffer<Char, SIZE>& buf) + -> std::basic_string<Char> { + auto size = buf.size(); + detail::assume(size < std::basic_string<Char>().max_size()); + return std::basic_string<Char>(buf.data(), size); +} + +FMT_BEGIN_DETAIL_NAMESPACE + +template <typename Char> +void vformat_to( + buffer<Char>& buf, basic_string_view<Char> fmt, + basic_format_args<FMT_BUFFER_CONTEXT(type_identity_t<Char>)> args, + locale_ref loc) { + // workaround for msvc bug regarding name-lookup in module + // link names into function scope + using detail::arg_formatter; + using detail::buffer_appender; + using detail::custom_formatter; + using detail::default_arg_formatter; + using detail::get_arg; + using detail::locale_ref; + using detail::parse_format_specs; + using detail::specs_checker; + using detail::specs_handler; + using detail::to_unsigned; + using detail::type; + using detail::write; + auto out = buffer_appender<Char>(buf); + if (fmt.size() == 2 && equal2(fmt.data(), "{}")) { + auto arg = args.get(0); + if (!arg) error_handler().on_error("argument not found"); + visit_format_arg(default_arg_formatter<Char>{out, args, loc}, arg); + return; + } + + struct format_handler : error_handler { + basic_format_parse_context<Char> parse_context; + buffer_context<Char> context; + + format_handler(buffer_appender<Char> out, basic_string_view<Char> str, + basic_format_args<buffer_context<Char>> args, locale_ref loc) + : parse_context(str), context(out, args, loc) {} + + void on_text(const Char* begin, const Char* end) { + auto text = basic_string_view<Char>(begin, to_unsigned(end - begin)); + context.advance_to(write<Char>(context.out(), text)); + } + + FMT_CONSTEXPR auto on_arg_id() -> int { + return parse_context.next_arg_id(); + } + FMT_CONSTEXPR auto on_arg_id(int id) -> int { + return parse_context.check_arg_id(id), id; + } + FMT_CONSTEXPR auto on_arg_id(basic_string_view<Char> id) -> int { + int arg_id = context.arg_id(id); + if (arg_id < 0) on_error("argument not found"); + return arg_id; + } + + FMT_INLINE void on_replacement_field(int id, const Char*) { + auto arg = get_arg(context, id); + context.advance_to(visit_format_arg( + default_arg_formatter<Char>{context.out(), context.args(), + context.locale()}, + arg)); + } + + auto on_format_specs(int id, const Char* begin, const Char* end) + -> const Char* { + auto arg = get_arg(context, id); + if (arg.type() == type::custom_type) { + parse_context.advance_to(parse_context.begin() + + (begin - &*parse_context.begin())); + visit_format_arg(custom_formatter<Char>{parse_context, context}, arg); + return parse_context.begin(); + } + auto specs = basic_format_specs<Char>(); + specs_checker<specs_handler<Char>> handler( + specs_handler<Char>(specs, parse_context, context), arg.type()); + begin = parse_format_specs(begin, end, handler); + if (begin == end || *begin != '}') + on_error("missing '}' in format string"); + auto f = arg_formatter<Char>{context.out(), specs, context.locale()}; + context.advance_to(visit_format_arg(f, arg)); + return begin; + } + }; + detail::parse_format_string<false>(fmt, format_handler(out, fmt, args, loc)); +} + +#ifndef FMT_HEADER_ONLY +extern template FMT_API auto thousands_sep_impl<char>(locale_ref) + -> thousands_sep_result<char>; +extern template FMT_API auto thousands_sep_impl<wchar_t>(locale_ref) + -> thousands_sep_result<wchar_t>; +extern template FMT_API auto decimal_point_impl(locale_ref) -> char; +extern template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t; +extern template auto format_float<double>(double value, int precision, + float_specs specs, buffer<char>& buf) + -> int; +extern template auto format_float<long double>(long double value, int precision, + float_specs specs, + buffer<char>& buf) -> int; +void snprintf_float(float, int, float_specs, buffer<char>&) = delete; +extern template auto snprintf_float<double>(double value, int precision, + float_specs specs, + buffer<char>& buf) -> int; +extern template auto snprintf_float<long double>(long double value, + int precision, + float_specs specs, + buffer<char>& buf) -> int; +#endif // FMT_HEADER_ONLY + +FMT_END_DETAIL_NAMESPACE + +#if FMT_USE_USER_DEFINED_LITERALS +inline namespace literals { +/** + \rst + User-defined literal equivalent of :func:`fmt::arg`. + + **Example**:: + + using namespace fmt::literals; + fmt::print("Elapsed time: {s:.2f} seconds", "s"_a=1.23); + \endrst + */ +# if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS +template <detail_exported::fixed_string Str> +constexpr auto operator""_a() + -> detail::udl_arg<remove_cvref_t<decltype(Str.data[0])>, + sizeof(Str.data) / sizeof(decltype(Str.data[0])), Str> { + return {}; +} +# else +constexpr auto operator"" _a(const char* s, size_t) -> detail::udl_arg<char> { + return {s}; +} +# endif + +// DEPRECATED! +// User-defined literal equivalent of fmt::format. +FMT_DEPRECATED constexpr auto operator"" _format(const char* s, size_t n) + -> detail::udl_formatter<char> { + return {{s, n}}; +} +} // namespace literals +#endif // FMT_USE_USER_DEFINED_LITERALS + +template <typename Locale, FMT_ENABLE_IF(detail::is_locale<Locale>::value)> +inline auto vformat(const Locale& loc, string_view fmt, format_args args) + -> std::string { + return detail::vformat(loc, fmt, args); +} + +template <typename Locale, typename... T, + FMT_ENABLE_IF(detail::is_locale<Locale>::value)> +inline auto format(const Locale& loc, format_string<T...> fmt, T&&... args) + -> std::string { + return vformat(loc, string_view(fmt), fmt::make_format_args(args...)); +} + +template <typename... T, size_t SIZE, typename Allocator> +FMT_DEPRECATED auto format_to(basic_memory_buffer<char, SIZE, Allocator>& buf, + format_string<T...> fmt, T&&... args) + -> appender { + detail::vformat_to(buf, string_view(fmt), fmt::make_format_args(args...)); + return appender(buf); +} + +template <typename OutputIt, typename Locale, + FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value&& + detail::is_locale<Locale>::value)> +auto vformat_to(OutputIt out, const Locale& loc, string_view fmt, + format_args args) -> OutputIt { + using detail::get_buffer; + auto&& buf = get_buffer<char>(out); + detail::vformat_to(buf, fmt, args, detail::locale_ref(loc)); + return detail::get_iterator(buf); +} + +template <typename OutputIt, typename Locale, typename... T, + FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value&& + detail::is_locale<Locale>::value)> +FMT_INLINE auto format_to(OutputIt out, const Locale& loc, + format_string<T...> fmt, T&&... args) -> OutputIt { + return vformat_to(out, loc, fmt, fmt::make_format_args(args...)); +} + +FMT_MODULE_EXPORT_END +FMT_END_NAMESPACE + +#ifdef FMT_DEPRECATED_INCLUDE_XCHAR +# include "xchar.h" +#endif + +#ifdef FMT_HEADER_ONLY +# define FMT_FUNC inline +# include "format-inl.h" +#else +# define FMT_FUNC +#endif + +#endif // FMT_FORMAT_H_ diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index 48dd26cc622..b7713dc7110 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -228,6 +228,10 @@ def list_render_passes(scene, srl): else: yield (aov.name, "RGB", 'COLOR') + # Light groups. + for lightgroup in srl.lightgroups: + yield ("Combined_%s" % lightgroup.name, "RGB", 'COLOR') + def register_passes(engine, scene, view_layer): for name, channelids, channeltype in list_render_passes(scene, view_layer): diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 24cc5735c96..51b3b3d2bcb 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -1012,6 +1012,12 @@ class CyclesLightSettings(bpy.types.PropertyGroup): "note that this will make the light invisible", default=False, ) + is_caustics_light: BoolProperty( + name="Shadow Caustics", + description="Generate approximate caustics in shadows of refractive surfaces. " + "Lights, caster and receiver objects must have shadow caustics options set to enable this", + default=False, + ) @classmethod def register(cls): @@ -1028,6 +1034,12 @@ class CyclesLightSettings(bpy.types.PropertyGroup): class CyclesWorldSettings(bpy.types.PropertyGroup): + is_caustics_light: BoolProperty( + name="Shadow Caustics", + description="Generate approximate caustics in shadows of refractive surfaces. " + "Lights, caster and receiver objects must have shadow caustics options set to enable this", + default=False, + ) sampling_method: EnumProperty( name="Sampling Method", description="How to sample the background light", @@ -1226,6 +1238,21 @@ class CyclesObjectSettings(bpy.types.PropertyGroup): subtype='DISTANCE', ) + is_caustics_caster: BoolProperty( + name="Cast Shadow Caustics", + description="With refractive materials, generate approximate caustics in shadows of this object. " + "Up to 10 bounces inside this object are taken into account. Lights, caster and receiver objects " + "must have shadow caustics options set to enable this", + default=False, + ) + + is_caustics_receiver: BoolProperty( + name="Receive Shadow Caustics", + description="Receive approximate caustics from refractive materials in shadows on this object. " + "Lights, caster and receiver objects must have shadow caustics options set to enable this", + 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 1f50f3da7ae..c97afa86fad 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -12,7 +12,7 @@ from bpy.types import Panel from bl_ui.properties_grease_pencil_common import GreasePencilSimplifyPanel from bl_ui.properties_render import draw_hair_settings -from bl_ui.properties_view_layer import ViewLayerCryptomattePanel, ViewLayerAOVPanel +from bl_ui.properties_view_layer import ViewLayerCryptomattePanel, ViewLayerAOVPanel, ViewLayerLightgroupsPanel class CyclesPresetPanel(PresetPanel, Panel): COMPAT_ENGINES = {'CYCLES'} @@ -883,6 +883,12 @@ class CYCLES_RENDER_PT_passes_aov(CyclesButtonsPanel, ViewLayerAOVPanel): bl_parent_id = "CYCLES_RENDER_PT_passes" +class CYCLES_RENDER_PT_passes_lightgroups(CyclesButtonsPanel, ViewLayerLightgroupsPanel): + bl_label = "Light Groups" + bl_context = "view_layer" + bl_parent_id = "CYCLES_RENDER_PT_passes" + + class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel): bl_label = "Post Processing" bl_options = {'DEFAULT_CLOSED'} @@ -1093,6 +1099,10 @@ class CYCLES_OBJECT_PT_shading_shadow_terminator(CyclesButtonsPanel, Panel): bl_parent_id = "CYCLES_OBJECT_PT_shading" bl_context = "object" + @classmethod + def poll(cls, context): + return context.object.type != 'LIGHT' + def draw(self, context): layout = self.layout layout.use_property_split = True @@ -1110,6 +1120,10 @@ class CYCLES_OBJECT_PT_shading_gi_approximation(CyclesButtonsPanel, Panel): bl_parent_id = "CYCLES_OBJECT_PT_shading" bl_context = "object" + @classmethod + def poll(cls, context): + return context.object.type != 'LIGHT' + def draw(self, context): layout = self.layout layout.use_property_split = True @@ -1125,6 +1139,45 @@ class CYCLES_OBJECT_PT_shading_gi_approximation(CyclesButtonsPanel, Panel): col.prop(cob, "ao_distance") +class CYCLES_OBJECT_PT_shading_caustics(CyclesButtonsPanel, Panel): + bl_label = "Caustics" + bl_parent_id = "CYCLES_OBJECT_PT_shading" + bl_context = "object" + + @classmethod + def poll(cls, context): + return CyclesButtonsPanel.poll(context) and not use_metal(context) and context.object.type != 'LIGHT' + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + + col = layout.column() + + ob = context.object + cob = ob.cycles + col.prop(cob, "is_caustics_caster") + col.prop(cob, "is_caustics_receiver") + + +class CYCLES_OBJECT_PT_lightgroup(CyclesButtonsPanel, Panel): + bl_label = "Light Group" + bl_parent_id = "CYCLES_OBJECT_PT_shading" + bl_context = "object" + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + ob = context.object + + view_layer = context.view_layer + + col = layout.column(align=True) + col.prop_search(ob, "lightgroup", view_layer, "lightgroups", text="Light Group") + + class CYCLES_OBJECT_PT_visibility(CyclesButtonsPanel, Panel): bl_label = "Visibility" bl_context = "object" @@ -1300,6 +1353,8 @@ class CYCLES_LIGHT_PT_light(CyclesButtonsPanel, Panel): sub.active = not (light.type == 'AREA' and clamp.is_portal) sub.prop(clamp, "cast_shadow") sub.prop(clamp, "use_multiple_importance_sampling", text="Multiple Importance") + if not use_metal(context): + sub.prop(clamp, "is_caustics_light", text="Shadow Caustics") if light.type == 'AREA': col.prop(clamp, "is_portal", text="Portal") @@ -1375,10 +1430,14 @@ class CYCLES_WORLD_PT_surface(CyclesButtonsPanel, Panel): layout.use_property_split = True world = context.world + view_layer = context.view_layer if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'): layout.prop(world, "color") + col = layout.column(align=True) + col.prop_search(world, "lightgroup", view_layer, "lightgroups", text="Light Group") + class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel): bl_label = "Volume" @@ -1496,6 +1555,8 @@ class CYCLES_WORLD_PT_settings_surface(CyclesButtonsPanel, Panel): subsub.active = cworld.sampling_method == 'MANUAL' subsub.prop(cworld, "sample_map_resolution") sub.prop(cworld, "max_bounces") + sub.prop(cworld, "is_caustics_light", text="Shadow Caustics") + class CYCLES_WORLD_PT_settings_volume(CyclesButtonsPanel, Panel): @@ -2183,6 +2244,7 @@ classes = ( CYCLES_RENDER_PT_passes_light, CYCLES_RENDER_PT_passes_crypto, CYCLES_RENDER_PT_passes_aov, + CYCLES_RENDER_PT_passes_lightgroups, CYCLES_RENDER_PT_filter, CYCLES_RENDER_PT_override, CYCLES_PT_post_processing, @@ -2193,6 +2255,8 @@ classes = ( CYCLES_OBJECT_PT_shading, CYCLES_OBJECT_PT_shading_shadow_terminator, CYCLES_OBJECT_PT_shading_gi_approximation, + CYCLES_OBJECT_PT_shading_caustics, + CYCLES_OBJECT_PT_lightgroup, CYCLES_OBJECT_PT_visibility, CYCLES_OBJECT_PT_visibility_ray_visibility, CYCLES_OBJECT_PT_visibility_culling, diff --git a/intern/cycles/blender/light.cpp b/intern/cycles/blender/light.cpp index bdfbdfd8618..5359fa13505 100644 --- a/intern/cycles/blender/light.cpp +++ b/intern/cycles/blender/light.cpp @@ -114,6 +114,9 @@ void BlenderSync::sync_light(BL::Object &b_parent, light->set_cast_shadow(get_boolean(clight, "cast_shadow")); light->set_use_mis(get_boolean(clight, "use_multiple_importance_sampling")); + /* caustics light */ + light->set_use_caustics(get_boolean(clight, "is_caustics_light")); + light->set_max_bounces(get_int(clight, "max_bounces")); if (b_ob_info.real_object != b_ob_info.iter_object) { @@ -140,6 +143,9 @@ void BlenderSync::sync_light(BL::Object &b_parent, light->set_use_scatter((visibility & PATH_RAY_VOLUME_SCATTER) != 0); light->set_is_shadow_catcher(b_ob_info.real_object.is_shadow_catcher()); + /* lightgroup */ + light->set_lightgroup(ustring(b_ob_info.real_object.lightgroup())); + /* tag */ light->tag_update(scene); } @@ -176,6 +182,9 @@ void BlenderSync::sync_background_light(BL::SpaceView3D &b_v3d, bool use_portal) /* force enable light again when world is resynced */ light->set_is_enabled(true); + /* caustic light */ + light->set_use_caustics(get_boolean(cworld, "is_caustics_light")); + light->tag_update(scene); light_map.set_recalc(b_world); } diff --git a/intern/cycles/blender/object.cpp b/intern/cycles/blender/object.cpp index 3a95746d149..d8f236e0641 100644 --- a/intern/cycles/blender/object.cpp +++ b/intern/cycles/blender/object.cpp @@ -298,6 +298,12 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, } object->set_ao_distance(ao_distance); + bool is_caustics_caster = get_boolean(cobject, "is_caustics_caster"); + object->set_is_caustics_caster(is_caustics_caster); + + bool is_caustics_receiver = get_boolean(cobject, "is_caustics_receiver"); + object->set_is_caustics_receiver(is_caustics_receiver); + /* sync the asset name for Cryptomatte */ BL::Object parent = b_ob.parent(); ustring parent_name; @@ -337,6 +343,9 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, object->set_random_id(hash_uint2(hash_string(object->name.c_str()), 0)); } + /* lightgroup */ + object->set_lightgroup(ustring(b_ob.lightgroup())); + object->tag_update(scene); } @@ -621,10 +630,8 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph, bool has_subdivision_modifier = false; BL::MeshSequenceCacheModifier b_mesh_cache(PointerRNA_NULL); - /* Experimental as Blender does not have good support for procedurals at the moment, also - * only available in preview renders since currently do not have a good cache policy, the - * data being loaded at once for all the frames. */ - if (experimental && b_v3d) { + /* Experimental as Blender does not have good support for procedurals at the moment. */ + if (experimental) { b_mesh_cache = object_mesh_cache_find(b_ob, &has_subdivision_modifier); use_procedural = b_mesh_cache && b_mesh_cache.cache_file().use_render_procedural(); } diff --git a/intern/cycles/blender/shader.cpp b/intern/cycles/blender/shader.cpp index 224cbea85f3..d3527567b96 100644 --- a/intern/cycles/blender/shader.cpp +++ b/intern/cycles/blender/shader.cpp @@ -1532,6 +1532,8 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, background->set_use_shader(view_layer.use_background_shader || viewport_parameters.use_custom_shader()); + background->set_lightgroup(ustring(b_world ? b_world.lightgroup() : "")); + background->tag_update(scene); } diff --git a/intern/cycles/blender/sync.cpp b/intern/cycles/blender/sync.cpp index 8af2ee7a435..bd6bfafedeb 100644 --- a/intern/cycles/blender/sync.cpp +++ b/intern/cycles/blender/sync.cpp @@ -745,6 +745,20 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v } } + /* Light Group passes. */ + BL::ViewLayer::lightgroups_iterator b_lightgroup_iter; + for (b_view_layer.lightgroups.begin(b_lightgroup_iter); + b_lightgroup_iter != b_view_layer.lightgroups.end(); + ++b_lightgroup_iter) { + BL::Lightgroup b_lightgroup(*b_lightgroup_iter); + + string name = string_printf("Combined_%s", b_lightgroup.name().c_str()); + + b_engine.add_pass(name.c_str(), 3, "RGB", b_view_layer.name().c_str()); + Pass *pass = pass_add(scene, PASS_COMBINED, name.c_str(), PassMode::NOISY); + pass->set_lightgroup(ustring(b_lightgroup.name())); + } + scene->film->set_pass_alpha_threshold(b_view_layer.pass_alpha_threshold()); } diff --git a/intern/cycles/integrator/pass_accessor.cpp b/intern/cycles/integrator/pass_accessor.cpp index 0be3cf6860b..05318b7545b 100644 --- a/intern/cycles/integrator/pass_accessor.cpp +++ b/intern/cycles/integrator/pass_accessor.cpp @@ -18,7 +18,11 @@ CCL_NAMESPACE_BEGIN */ PassAccessor::PassAccessInfo::PassAccessInfo(const BufferPass &pass) - : type(pass.type), mode(pass.mode), include_albedo(pass.include_albedo), offset(pass.offset) + : type(pass.type), + mode(pass.mode), + include_albedo(pass.include_albedo), + is_lightgroup(!pass.lightgroup.empty()), + offset(pass.offset) { } @@ -127,7 +131,8 @@ bool PassAccessor::get_render_tile_pixels(const RenderBuffers *render_buffers, const PassType type = pass_access_info_.type; const PassMode mode = pass_access_info_.mode; - const PassInfo pass_info = Pass::get_info(type, pass_access_info_.include_albedo); + const PassInfo pass_info = Pass::get_info( + type, pass_access_info_.include_albedo, pass_access_info_.is_lightgroup); int num_written_components = pass_info.num_components; if (pass_info.num_components == 1) { @@ -215,8 +220,8 @@ void PassAccessor::init_kernel_film_convert(KernelFilmConvert *kfilm_convert, const Destination &destination) const { const PassMode mode = pass_access_info_.mode; - const PassInfo &pass_info = Pass::get_info(pass_access_info_.type, - pass_access_info_.include_albedo); + const PassInfo &pass_info = Pass::get_info( + pass_access_info_.type, pass_access_info_.include_albedo, pass_access_info_.is_lightgroup); kfilm_convert->pass_offset = pass_access_info_.offset; kfilm_convert->pass_stride = buffer_params.pass_stride; @@ -279,8 +284,8 @@ bool PassAccessor::set_render_tile_pixels(RenderBuffers *render_buffers, const S return false; } - const PassInfo pass_info = Pass::get_info(pass_access_info_.type, - pass_access_info_.include_albedo); + const PassInfo pass_info = Pass::get_info( + pass_access_info_.type, pass_access_info_.include_albedo, pass_access_info_.is_lightgroup); const BufferParams &buffer_params = render_buffers->params; diff --git a/intern/cycles/integrator/pass_accessor.h b/intern/cycles/integrator/pass_accessor.h index 7de1d03961b..683d3a35272 100644 --- a/intern/cycles/integrator/pass_accessor.h +++ b/intern/cycles/integrator/pass_accessor.h @@ -28,6 +28,7 @@ class PassAccessor { PassType type = PASS_NONE; PassMode mode = PassMode::NOISY; bool include_albedo = false; + bool is_lightgroup = false; int offset = -1; /* For the shadow catcher matte pass: whether to approximate shadow catcher pass into its diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 6e3ac1bd32f..cfd503a621d 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -223,6 +223,7 @@ set(SRC_KERNEL_INTEGRATOR_HEADERS integrator/intersect_subsurface.h integrator/intersect_volume_stack.h integrator/megakernel.h + integrator/mnee.h integrator/path_state.h integrator/shade_background.h integrator/shade_light.h diff --git a/intern/cycles/kernel/device/cuda/compat.h b/intern/cycles/kernel/device/cuda/compat.h index b392455c740..51e1381d552 100644 --- a/intern/cycles/kernel/device/cuda/compat.h +++ b/intern/cycles/kernel/device/cuda/compat.h @@ -76,10 +76,11 @@ typedef unsigned long long uint64_t; /* GPU texture objects */ typedef unsigned long long CUtexObject; -typedef CUtexObject ccl_gpu_tex_object; +typedef CUtexObject ccl_gpu_tex_object_2D; +typedef CUtexObject ccl_gpu_tex_object_3D; template<typename T> -ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object texobj, +ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object_2D texobj, const float x, const float y) { @@ -87,7 +88,7 @@ ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object tex } template<typename T> -ccl_device_forceinline T ccl_gpu_tex_object_read_3D(const ccl_gpu_tex_object texobj, +ccl_device_forceinline T ccl_gpu_tex_object_read_3D(const ccl_gpu_tex_object_3D texobj, const float x, const float y, const float z) diff --git a/intern/cycles/kernel/device/cuda/config.h b/intern/cycles/kernel/device/cuda/config.h index 1f66bb0175a..88149e92ec9 100644 --- a/intern/cycles/kernel/device/cuda/config.h +++ b/intern/cycles/kernel/device/cuda/config.h @@ -88,6 +88,7 @@ extern "C" __global__ void __launch_bounds__(block_num_threads) #define ccl_gpu_kernel_signature(name, ...) kernel_gpu_##name(__VA_ARGS__) +#define ccl_gpu_kernel_postfix #define ccl_gpu_kernel_call(x) x diff --git a/intern/cycles/kernel/device/gpu/image.h b/intern/cycles/kernel/device/gpu/image.h index 83e7aa869c1..c5bc7d88e02 100644 --- a/intern/cycles/kernel/device/gpu/image.h +++ b/intern/cycles/kernel/device/gpu/image.h @@ -56,7 +56,7 @@ ccl_device_noinline T kernel_tex_image_interp_bicubic(ccl_global const TextureIn float x, float y) { - ccl_gpu_tex_object tex = (ccl_gpu_tex_object)info.data; + ccl_gpu_tex_object_2D tex = (ccl_gpu_tex_object_2D)info.data; x = (x * info.width) - 0.5f; y = (y * info.height) - 0.5f; @@ -85,7 +85,7 @@ template<typename T> ccl_device_noinline T kernel_tex_image_interp_tricubic(ccl_global const TextureInfo &info, float x, float y, float z) { - ccl_gpu_tex_object tex = (ccl_gpu_tex_object)info.data; + ccl_gpu_tex_object_3D tex = (ccl_gpu_tex_object_3D)info.data; x = (x * info.width) - 0.5f; y = (y * info.height) - 0.5f; @@ -190,7 +190,7 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, int id, float x, flo return kernel_tex_image_interp_bicubic<float4>(info, x, y); } else { - ccl_gpu_tex_object tex = (ccl_gpu_tex_object)info.data; + ccl_gpu_tex_object_2D tex = (ccl_gpu_tex_object_2D)info.data; return ccl_gpu_tex_object_read_2D<float4>(tex, x, y); } } @@ -202,7 +202,7 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, int id, float x, flo f = kernel_tex_image_interp_bicubic<float>(info, x, y); } else { - ccl_gpu_tex_object tex = (ccl_gpu_tex_object)info.data; + ccl_gpu_tex_object_2D tex = (ccl_gpu_tex_object_2D)info.data; f = ccl_gpu_tex_object_read_2D<float>(tex, x, y); } @@ -245,7 +245,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg, return kernel_tex_image_interp_tricubic<float4>(info, x, y, z); } else { - ccl_gpu_tex_object tex = (ccl_gpu_tex_object)info.data; + ccl_gpu_tex_object_3D tex = (ccl_gpu_tex_object_3D)info.data; return ccl_gpu_tex_object_read_3D<float4>(tex, x, y, z); } } @@ -256,7 +256,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg, f = kernel_tex_image_interp_tricubic<float>(info, x, y, z); } else { - ccl_gpu_tex_object tex = (ccl_gpu_tex_object)info.data; + ccl_gpu_tex_object_3D tex = (ccl_gpu_tex_object_3D)info.data; f = ccl_gpu_tex_object_read_3D<float>(tex, x, y, z); } diff --git a/intern/cycles/kernel/device/gpu/kernel.h b/intern/cycles/kernel/device/gpu/kernel.h index 26ab99766ad..82b51843864 100644 --- a/intern/cycles/kernel/device/gpu/kernel.h +++ b/intern/cycles/kernel/device/gpu/kernel.h @@ -58,6 +58,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) INTEGRATOR_STATE_WRITE(state, shadow_path, queued_kernel) = 0; } } +ccl_gpu_kernel_postfix ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_signature(integrator_init_from_camera, @@ -89,6 +90,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_call( integrator_init_from_camera(nullptr, state, tile, render_buffer, x, y, sample)); } +ccl_gpu_kernel_postfix ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_signature(integrator_init_from_bake, @@ -120,6 +122,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_call( integrator_init_from_bake(nullptr, state, tile, render_buffer, x, y, sample)); } +ccl_gpu_kernel_postfix ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_signature(integrator_intersect_closest, @@ -134,6 +137,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_call(integrator_intersect_closest(NULL, state, render_buffer)); } } +ccl_gpu_kernel_postfix ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_signature(integrator_intersect_shadow, @@ -147,6 +151,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_call(integrator_intersect_shadow(NULL, state)); } } +ccl_gpu_kernel_postfix ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_signature(integrator_intersect_subsurface, @@ -160,6 +165,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_call(integrator_intersect_subsurface(NULL, state)); } } +ccl_gpu_kernel_postfix ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_signature(integrator_intersect_volume_stack, @@ -173,6 +179,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_call(integrator_intersect_volume_stack(NULL, state)); } } +ccl_gpu_kernel_postfix ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_signature(integrator_shade_background, @@ -187,6 +194,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_call(integrator_shade_background(NULL, state, render_buffer)); } } +ccl_gpu_kernel_postfix ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_signature(integrator_shade_light, @@ -201,6 +209,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_call(integrator_shade_light(NULL, state, render_buffer)); } } +ccl_gpu_kernel_postfix ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_signature(integrator_shade_shadow, @@ -215,6 +224,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_call(integrator_shade_shadow(NULL, state, render_buffer)); } } +ccl_gpu_kernel_postfix ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_signature(integrator_shade_surface, @@ -229,6 +239,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_call(integrator_shade_surface(NULL, state, render_buffer)); } } +ccl_gpu_kernel_postfix #ifdef __KERNEL_METAL__ constant int __dummy_constant [[function_constant(0)]]; @@ -256,6 +267,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) #endif } } +ccl_gpu_kernel_postfix ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_signature(integrator_shade_volume, @@ -270,6 +282,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_call(integrator_shade_volume(NULL, state, render_buffer)); } } +ccl_gpu_kernel_postfix ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE) ccl_gpu_kernel_signature(integrator_queued_paths_array, @@ -288,6 +301,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE) num_indices, ccl_gpu_kernel_lambda_pass); } +ccl_gpu_kernel_postfix ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE) ccl_gpu_kernel_signature(integrator_queued_shadow_paths_array, @@ -306,6 +320,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE) num_indices, ccl_gpu_kernel_lambda_pass); } +ccl_gpu_kernel_postfix ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE) ccl_gpu_kernel_signature(integrator_active_paths_array, @@ -321,6 +336,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE) num_indices, ccl_gpu_kernel_lambda_pass); } +ccl_gpu_kernel_postfix ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE) ccl_gpu_kernel_signature(integrator_terminated_paths_array, @@ -337,6 +353,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE) num_indices, ccl_gpu_kernel_lambda_pass); } +ccl_gpu_kernel_postfix ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE) ccl_gpu_kernel_signature(integrator_terminated_shadow_paths_array, @@ -353,6 +370,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE) num_indices, ccl_gpu_kernel_lambda_pass); } +ccl_gpu_kernel_postfix ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE) ccl_gpu_kernel_signature(integrator_sorted_paths_array, @@ -380,6 +398,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE) key_prefix_sum, ccl_gpu_kernel_lambda_pass); } +ccl_gpu_kernel_postfix ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE) ccl_gpu_kernel_signature(integrator_compact_paths_array, @@ -399,6 +418,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE) num_indices, ccl_gpu_kernel_lambda_pass); } +ccl_gpu_kernel_postfix ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE) ccl_gpu_kernel_signature(integrator_compact_states, @@ -416,6 +436,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE) ccl_gpu_kernel_call(integrator_state_move(NULL, to_state, from_state)); } } +ccl_gpu_kernel_postfix ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE) ccl_gpu_kernel_signature(integrator_compact_shadow_paths_array, @@ -435,6 +456,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE) num_indices, ccl_gpu_kernel_lambda_pass); } +ccl_gpu_kernel_postfix ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE) ccl_gpu_kernel_signature(integrator_compact_shadow_states, @@ -452,12 +474,14 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE) ccl_gpu_kernel_call(integrator_shadow_state_move(NULL, to_state, from_state)); } } +ccl_gpu_kernel_postfix ccl_gpu_kernel_threads(GPU_PARALLEL_PREFIX_SUM_DEFAULT_BLOCK_SIZE) ccl_gpu_kernel_signature( prefix_sum, ccl_global int *counter, ccl_global int *prefix_sum, int num_values) { gpu_parallel_prefix_sum(ccl_gpu_global_id_x(), counter, prefix_sum, num_values); } +ccl_gpu_kernel_postfix /* -------------------------------------------------------------------- * Adaptive sampling. @@ -494,6 +518,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) atomic_fetch_and_add_uint32(num_active_pixels, popcount(num_active_pixels_mask)); } } +ccl_gpu_kernel_postfix ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_signature(adaptive_sampling_filter_x, @@ -512,6 +537,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) kernel_adaptive_sampling_filter_x(NULL, render_buffer, sy + y, sx, sw, offset, stride)); } } +ccl_gpu_kernel_postfix ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_signature(adaptive_sampling_filter_y, @@ -530,6 +556,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) kernel_adaptive_sampling_filter_y(NULL, render_buffer, sx + x, sy, sh, offset, stride)); } } +ccl_gpu_kernel_postfix /* -------------------------------------------------------------------- * Cryptomatte. @@ -546,6 +573,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_call(kernel_cryptomatte_post(nullptr, render_buffer, pixel_index)); } } +ccl_gpu_kernel_postfix /* -------------------------------------------------------------------- * Film. @@ -627,6 +655,7 @@ ccl_device_inline void kernel_gpu_film_convert_half_write(ccl_global uchar4 *rgb \ FILM_GET_PASS_PIXEL_F32(variant, input_channel_count); \ } \ + ccl_gpu_kernel_postfix \ \ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) \ ccl_gpu_kernel_signature(film_convert_##variant##_half_rgba, \ @@ -666,7 +695,8 @@ ccl_device_inline void kernel_gpu_film_convert_half_write(ccl_global uchar4 *rgb const half4 half_pixel = float4_to_half4_display( \ make_float4(pixel[0], pixel[1], pixel[2], pixel[3])); \ kernel_gpu_film_convert_half_write(rgba, rgba_offset, rgba_stride, x, y, half_pixel); \ - } + } \ + ccl_gpu_kernel_postfix /* 1 channel inputs */ KERNEL_FILM_CONVERT_VARIANT(depth, 1) @@ -706,6 +736,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_call(kernel_displace_evaluate(NULL, input, output, offset + i)); } } +ccl_gpu_kernel_postfix /* Background */ @@ -721,6 +752,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_call(kernel_background_evaluate(NULL, input, output, offset + i)); } } +ccl_gpu_kernel_postfix /* Curve Shadow Transparency */ @@ -737,6 +769,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) kernel_curve_shadow_transparency_evaluate(NULL, input, output, offset + i)); } } +ccl_gpu_kernel_postfix /* -------------------------------------------------------------------- * Denoising. @@ -770,6 +803,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) color_out[1] = clamp(color_out[1], 0.0f, 10000.0f); color_out[2] = clamp(color_out[2], 0.0f, 10000.0f); } +ccl_gpu_kernel_postfix ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_signature(filter_guiding_preprocess, @@ -849,6 +883,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) flow_out[1] = -motion_in[1] * pixel_scale; } } +ccl_gpu_kernel_postfix ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_signature(filter_guiding_set_fake_albedo, @@ -877,6 +912,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) albedo_out[1] = 0.5f; albedo_out[2] = 0.5f; } +ccl_gpu_kernel_postfix ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) ccl_gpu_kernel_signature(filter_color_postprocess, @@ -936,6 +972,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) denoised_pixel[3] = 0; } } +ccl_gpu_kernel_postfix /* -------------------------------------------------------------------- * Shadow catcher. @@ -961,3 +998,4 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) atomic_fetch_and_add_uint32(num_possible_splits, popcount(can_split_mask)); } } +ccl_gpu_kernel_postfix diff --git a/intern/cycles/kernel/device/hip/compat.h b/intern/cycles/kernel/device/hip/compat.h index 29fbc119cd1..9c93d87fd87 100644 --- a/intern/cycles/kernel/device/hip/compat.h +++ b/intern/cycles/kernel/device/hip/compat.h @@ -73,10 +73,11 @@ typedef unsigned long long uint64_t; #define ccl_gpu_ballot(predicate) __ballot(predicate) /* GPU texture objects */ -typedef hipTextureObject_t ccl_gpu_tex_object; +typedef hipTextureObject_t ccl_gpu_tex_object_2D; +typedef hipTextureObject_t ccl_gpu_tex_object_3D; template<typename T> -ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object texobj, +ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object_2D texobj, const float x, const float y) { @@ -84,7 +85,7 @@ ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object tex } template<typename T> -ccl_device_forceinline T ccl_gpu_tex_object_read_3D(const ccl_gpu_tex_object texobj, +ccl_device_forceinline T ccl_gpu_tex_object_read_3D(const ccl_gpu_tex_object_3D texobj, const float x, const float y, const float z) diff --git a/intern/cycles/kernel/device/hip/config.h b/intern/cycles/kernel/device/hip/config.h index a5a5924d5e0..c7e7306d628 100644 --- a/intern/cycles/kernel/device/hip/config.h +++ b/intern/cycles/kernel/device/hip/config.h @@ -31,6 +31,7 @@ extern "C" __global__ void __launch_bounds__(block_num_threads) #define ccl_gpu_kernel_signature(name, ...) kernel_gpu_##name(__VA_ARGS__) +#define ccl_gpu_kernel_postfix #define ccl_gpu_kernel_call(x) x diff --git a/intern/cycles/kernel/device/metal/compat.h b/intern/cycles/kernel/device/metal/compat.h index c12987c0a91..4e309f16c08 100644 --- a/intern/cycles/kernel/device/metal/compat.h +++ b/intern/cycles/kernel/device/metal/compat.h @@ -132,6 +132,7 @@ void kernel_gpu_##name::run(thread MetalKernelContext& context, \ uint simd_group_index, \ uint num_simd_groups) ccl_global const +#define ccl_gpu_kernel_postfix #define ccl_gpu_kernel_call(x) context.x /* define a function object where "func" is the lambda body, and additional parameters are used to specify captured state */ diff --git a/intern/cycles/kernel/device/metal/context_begin.h b/intern/cycles/kernel/device/metal/context_begin.h index 4c9d6b6e405..99cb1e3826e 100644 --- a/intern/cycles/kernel/device/metal/context_begin.h +++ b/intern/cycles/kernel/device/metal/context_begin.h @@ -19,17 +19,18 @@ class MetalKernelContext { {} /* texture fetch adapter functions */ - typedef uint64_t ccl_gpu_tex_object; + typedef uint64_t ccl_gpu_tex_object_2D; + typedef uint64_t ccl_gpu_tex_object_3D; template<typename T> inline __attribute__((__always_inline__)) - T ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object tex, float x, float y) const { + T ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object_2D tex, float x, float y) const { kernel_assert(0); return 0; } template<typename T> inline __attribute__((__always_inline__)) - T ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object tex, float x, float y, float z) const { + T ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object_3D tex, float x, float y, float z) const { kernel_assert(0); return 0; } @@ -37,14 +38,14 @@ class MetalKernelContext { // texture2d template<> inline __attribute__((__always_inline__)) - float4 ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object tex, float x, float y) const { + float4 ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object_2D tex, float x, float y) const { const uint tid(tex); const uint sid(tex >> 32); return metal_ancillaries->textures_2d[tid].tex.sample(metal_samplers[sid], float2(x, y)); } template<> inline __attribute__((__always_inline__)) - float ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object tex, float x, float y) const { + float ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object_2D tex, float x, float y) const { const uint tid(tex); const uint sid(tex >> 32); return metal_ancillaries->textures_2d[tid].tex.sample(metal_samplers[sid], float2(x, y)).x; @@ -53,14 +54,14 @@ class MetalKernelContext { // texture3d template<> inline __attribute__((__always_inline__)) - float4 ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object tex, float x, float y, float z) const { + float4 ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object_3D tex, float x, float y, float z) const { const uint tid(tex); const uint sid(tex >> 32); return metal_ancillaries->textures_3d[tid].tex.sample(metal_samplers[sid], float3(x, y, z)); } template<> inline __attribute__((__always_inline__)) - float ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object tex, float x, float y, float z) const { + float ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object_3D tex, float x, float y, float z) const { const uint tid(tex); const uint sid(tex >> 32); return metal_ancillaries->textures_3d[tid].tex.sample(metal_samplers[sid], float3(x, y, z)).x; diff --git a/intern/cycles/kernel/device/optix/compat.h b/intern/cycles/kernel/device/optix/compat.h index ae7a0309e51..aa4a6321a8b 100644 --- a/intern/cycles/kernel/device/optix/compat.h +++ b/intern/cycles/kernel/device/optix/compat.h @@ -78,10 +78,11 @@ typedef unsigned long long uint64_t; /* GPU texture objects */ typedef unsigned long long CUtexObject; -typedef CUtexObject ccl_gpu_tex_object; +typedef CUtexObject ccl_gpu_tex_object_2D; +typedef CUtexObject ccl_gpu_tex_object_3D; template<typename T> -ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object texobj, +ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object_2D texobj, const float x, const float y) { @@ -89,7 +90,7 @@ ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object tex } template<typename T> -ccl_device_forceinline T ccl_gpu_tex_object_read_3D(const ccl_gpu_tex_object texobj, +ccl_device_forceinline T ccl_gpu_tex_object_read_3D(const ccl_gpu_tex_object_3D texobj, const float x, const float y, const float z) diff --git a/intern/cycles/kernel/film/accumulate.h b/intern/cycles/kernel/film/accumulate.h index d6a385a4bff..e10acfd7eb5 100644 --- a/intern/cycles/kernel/film/accumulate.h +++ b/intern/cycles/kernel/film/accumulate.h @@ -320,12 +320,13 @@ ccl_device_inline void kernel_accum_combined_transparent_pass(KernelGlobals kg, } /* Write background or emission to appropriate pass. */ -ccl_device_inline void kernel_accum_emission_or_background_pass(KernelGlobals kg, - ConstIntegratorState state, - float3 contribution, - ccl_global float *ccl_restrict - buffer, - const int pass) +ccl_device_inline void kernel_accum_emission_or_background_pass( + KernelGlobals kg, + ConstIntegratorState state, + float3 contribution, + ccl_global float *ccl_restrict buffer, + const int pass, + const int lightgroup = LIGHTGROUP_NONE) { if (!(kernel_data.film.light_pass_flag & PASS_ANY)) { return; @@ -347,6 +348,11 @@ ccl_device_inline void kernel_accum_emission_or_background_pass(KernelGlobals kg } # endif /* __DENOISING_FEATURES__ */ + if (lightgroup != LIGHTGROUP_NONE && kernel_data.film.pass_lightgroup != PASS_UNUSED) { + kernel_write_pass_float3(buffer + kernel_data.film.pass_lightgroup + 3 * lightgroup, + contribution); + } + if (!(path_flag & PATH_RAY_ANY_PASS)) { /* Directly visible, write to emission or background pass. */ pass_offset = pass; @@ -449,6 +455,13 @@ ccl_device_inline void kernel_accum_light(KernelGlobals kg, return; } + /* Write lightgroup pass. LIGHTGROUP_NONE is ~0 so decode from unsigned to signed */ + const int lightgroup = (int)(INTEGRATOR_STATE(state, shadow_path, lightgroup)) - 1; + if (lightgroup != LIGHTGROUP_NONE && kernel_data.film.pass_lightgroup != PASS_UNUSED) { + kernel_write_pass_float3(buffer + kernel_data.film.pass_lightgroup + 3 * lightgroup, + contribution); + } + if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) { int pass_offset = PASS_UNUSED; @@ -566,15 +579,20 @@ ccl_device_inline void kernel_accum_background(KernelGlobals kg, kernel_accum_combined_transparent_pass( kg, path_flag, sample, contribution, transparent, buffer); } - kernel_accum_emission_or_background_pass( - kg, state, contribution, buffer, kernel_data.film.pass_background); + kernel_accum_emission_or_background_pass(kg, + state, + contribution, + buffer, + kernel_data.film.pass_background, + kernel_data.background.lightgroup); } /* Write emission to render buffer. */ ccl_device_inline void kernel_accum_emission(KernelGlobals kg, ConstIntegratorState state, const float3 L, - ccl_global float *ccl_restrict render_buffer) + ccl_global float *ccl_restrict render_buffer, + const int lightgroup = LIGHTGROUP_NONE) { float3 contribution = L; kernel_accum_clamp(kg, &contribution, INTEGRATOR_STATE(state, path, bounce) - 1); @@ -585,7 +603,7 @@ ccl_device_inline void kernel_accum_emission(KernelGlobals kg, kernel_accum_combined_pass(kg, path_flag, sample, contribution, buffer); kernel_accum_emission_or_background_pass( - kg, state, contribution, buffer, kernel_data.film.pass_emission); + kg, state, contribution, buffer, kernel_data.film.pass_emission, lightgroup); } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/geom/object.h b/intern/cycles/kernel/geom/object.h index 86c57c84b47..3faab7fa905 100644 --- a/intern/cycles/kernel/geom/object.h +++ b/intern/cycles/kernel/geom/object.h @@ -283,6 +283,26 @@ ccl_device_inline float object_pass_id(KernelGlobals kg, int object) return kernel_tex_fetch(__objects, object).pass_id; } +/* Lightgroup of lamp */ + +ccl_device_inline int lamp_lightgroup(KernelGlobals kg, int lamp) +{ + if (lamp == LAMP_NONE) + return LIGHTGROUP_NONE; + + return kernel_tex_fetch(__lights, lamp).lightgroup; +} + +/* Lightgroup of object */ + +ccl_device_inline int object_lightgroup(KernelGlobals kg, int object) +{ + if (object == OBJECT_NONE) + return LIGHTGROUP_NONE; + + return kernel_tex_fetch(__objects, object).lightgroup; +} + /* Per lamp random number for shader variation */ ccl_device_inline float lamp_random_number(KernelGlobals kg, int lamp) diff --git a/intern/cycles/kernel/integrator/init_from_bake.h b/intern/cycles/kernel/integrator/init_from_bake.h index b84059d6676..d6047bd2288 100644 --- a/intern/cycles/kernel/integrator/init_from_bake.h +++ b/intern/cycles/kernel/integrator/init_from_bake.h @@ -230,7 +230,11 @@ ccl_device bool integrator_init_from_bake(KernelGlobals kg, /* Setup next kernel to execute. */ const int shader_index = shader & SHADER_MASK; const int shader_flags = kernel_tex_fetch(__shaders, shader_index).flags; - if (shader_flags & SD_HAS_RAYTRACE) { + const bool use_caustics = kernel_data.integrator.use_caustics && + (object_flag & SD_OBJECT_CAUSTICS); + const bool use_raytrace_kernel = (shader_flags & SD_HAS_RAYTRACE) || use_caustics; + + if (use_raytrace_kernel) { INTEGRATOR_PATH_INIT_SORTED(DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE, shader_index); } else { diff --git a/intern/cycles/kernel/integrator/intersect_closest.h b/intern/cycles/kernel/integrator/intersect_closest.h index 9fcbf89c579..b8ce625c11b 100644 --- a/intern/cycles/kernel/integrator/intersect_closest.h +++ b/intern/cycles/kernel/integrator/intersect_closest.h @@ -123,7 +123,9 @@ ccl_device_forceinline void integrator_split_shadow_catcher( /* Continue with shading shadow catcher surface. */ const int shader = intersection_get_shader(kg, isect); const int flags = kernel_tex_fetch(__shaders, shader).flags; - const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE); + const bool use_caustics = kernel_data.integrator.use_caustics && + (object_flags & SD_OBJECT_CAUSTICS); + const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE) || use_caustics; if (use_raytrace_kernel) { INTEGRATOR_PATH_INIT_SORTED(DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE, shader); @@ -145,7 +147,10 @@ ccl_device_forceinline void integrator_intersect_next_kernel_after_shadow_catche const int shader = intersection_get_shader(kg, &isect); const int flags = kernel_tex_fetch(__shaders, shader).flags; - const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE); + const int object_flags = intersection_get_object_flags(kg, &isect); + const bool use_caustics = kernel_data.integrator.use_caustics && + (object_flags & SD_OBJECT_CAUSTICS); + const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE) || use_caustics; if (use_raytrace_kernel) { INTEGRATOR_PATH_NEXT_SORTED( @@ -214,7 +219,10 @@ ccl_device_forceinline void integrator_intersect_next_kernel( const int flags = kernel_tex_fetch(__shaders, shader).flags; if (!integrator_intersect_terminate(kg, state, flags)) { - const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE); + const int object_flags = intersection_get_object_flags(kg, isect); + const bool use_caustics = kernel_data.integrator.use_caustics && + (object_flags & SD_OBJECT_CAUSTICS); + const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE) || use_caustics; if (use_raytrace_kernel) { INTEGRATOR_PATH_NEXT_SORTED( current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE, shader); @@ -261,7 +269,10 @@ ccl_device_forceinline void integrator_intersect_next_kernel_after_volume( /* Hit a surface, continue with surface kernel unless terminated. */ const int shader = intersection_get_shader(kg, isect); const int flags = kernel_tex_fetch(__shaders, shader).flags; - const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE); + const int object_flags = intersection_get_object_flags(kg, isect); + const bool use_caustics = kernel_data.integrator.use_caustics && + (object_flags & SD_OBJECT_CAUSTICS); + const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE) || use_caustics; if (use_raytrace_kernel) { INTEGRATOR_PATH_NEXT_SORTED( @@ -328,12 +339,37 @@ ccl_device void integrator_intersect_closest(KernelGlobals kg, isect.prim = PRIM_NONE; } + /* Setup mnee flag to signal last intersection with a caster */ + const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag); + +#ifdef __MNEE__ + /* Path culling logic for MNEE (removes fireflies at the cost of bias) */ + if (kernel_data.integrator.use_caustics) { + /* The following firefly removal mechanism works by culling light connections when + * a ray comes from a caustic caster directly after bouncing off a different caustic + * receiver */ + bool from_caustic_caster = false; + bool from_caustic_receiver = false; + if (!(path_flag & PATH_RAY_CAMERA) && last_isect_object != OBJECT_NONE) { + const int object_flags = kernel_tex_fetch(__object_flag, last_isect_object); + from_caustic_receiver = (object_flags & SD_OBJECT_CAUSTICS_RECEIVER); + from_caustic_caster = (object_flags & SD_OBJECT_CAUSTICS_CASTER); + } + + bool has_receiver_ancestor = INTEGRATOR_STATE(state, path, mnee) & PATH_MNEE_RECEIVER_ANCESTOR; + INTEGRATOR_STATE_WRITE(state, path, mnee) &= ~PATH_MNEE_CULL_LIGHT_CONNECTION; + if (from_caustic_caster && has_receiver_ancestor) + INTEGRATOR_STATE_WRITE(state, path, mnee) |= PATH_MNEE_CULL_LIGHT_CONNECTION; + if (from_caustic_receiver) + INTEGRATOR_STATE_WRITE(state, path, mnee) |= PATH_MNEE_RECEIVER_ANCESTOR; + } +#endif /* __MNEE__ */ + /* Light intersection for MIS. */ if (kernel_data.integrator.use_lamp_mis) { /* NOTE: if we make lights visible to camera rays, we'll need to initialize * these in the path_state_init. */ const int last_type = INTEGRATOR_STATE(state, isect, type); - const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag); hit = lights_intersect( kg, state, &ray, &isect, last_isect_prim, last_isect_object, last_type, path_flag) || hit; diff --git a/intern/cycles/kernel/integrator/mnee.h b/intern/cycles/kernel/integrator/mnee.h new file mode 100644 index 00000000000..af2032c9b99 --- /dev/null +++ b/intern/cycles/kernel/integrator/mnee.h @@ -0,0 +1,1150 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright 2011-2022 Blender Foundation */ + +#ifdef __MNEE__ + +# include "kernel/light/sample.h" + +/* + * Manifold Next Event Estimation + * + * This code adds manifold next event estimation through refractive surface(s) as a new sampling + * technique for direct lighting, i.e. finding the point on the refractive surface(s) along the + * path to a light sample, which satisfies fermat's principle for a given microfacet normal and + * the path's end points. This technique involves walking on the "specular manifold" using a pseudo + * newton solver. Such a manifold is defined by the specular constraint matrix from the manifold + * exploration framework [2]. For each refractive interface, this constraint is defined by + * enforcing that the generalized half-vector projection onto the interface local tangent plane is + * null. The newton solver guides the walk by linearizing the manifold locally before reprojecting + * the linear solution onto the refractive surface. See paper [1] for more details about + * the technique itself and [3] for the half-vector light transport formulation, from which it is + * derived. + * + * [1] Manifold Next Event Estimation + * Johannes Hanika, Marc Droske, and Luca Fascione. 2015. + * Comput. Graph. Forum 34, 4 (July 2015), 87–97. + * https://jo.dreggn.org/home/2015_mnee.pdf + * + * [2] Manifold exploration: a Markov Chain Monte Carlo technique for rendering scenes with + * difficult specular transport Wenzel Jakob and Steve Marschner. 2012. ACM Trans. Graph. 31, 4, + * Article 58 (July 2012), 13 pages. + * https://www.cs.cornell.edu/projects/manifolds-sg12/ + * + * [3] The Natural-Constraint Representation of the Path Space for Efficient Light Transport + * Simulation Anton S. Kaplanyan, Johannes Hanika, and Carsten Dachsbacher. 2014. ACM Trans. Graph. + * 33, 4, Article 102 (July 2014), 13 pages. + * https://cg.ivd.kit.edu/english/HSLT.php + */ + +# define MNEE_MAX_ITERATIONS 50 +# define MNEE_MAX_INTERSECTION_COUNT 10 +# define MNEE_SOLVER_THRESHOLD 0.001f +# define MNEE_MAX_CAUSTIC_CASTERS 6 +# define MNEE_MIN_DISTANCE 0.001f +# define MNEE_MIN_DETERMINANT 0.0001f +# define MNEE_PROJECTION_DISTANCE_MULTIPLIER 2.f + +CCL_NAMESPACE_BEGIN + +/* Manifold struct containing the local differential geometry quantity */ +typedef ccl_private struct ManifoldVertex { + /* Position and partials */ + float3 p; + float3 dp_du; + float3 dp_dv; + + /* Normal and partials */ + float3 n; + float3 ng; + float3 dn_du; + float3 dn_dv; + + /* geometric info */ + float2 uv; + int object; + int prim; + int shader; + + /* closure info */ + float eta; + ccl_private ShaderClosure *bsdf; + float2 n_offset; + + /* constraint and its derivative matrices */ + float2 constraint; + float4 a; + float4 b; + float4 c; +} ManifoldVertex; + +/* Multiplication of a 2x2 matrix encoded in a row-major order float4 by a vector */ +ccl_device_inline float2 mat22_mult(const float4 a, const float2 b) +{ + return make_float2(a.x * b.x + a.y * b.y, a.z * b.x + a.w * b.y); +} + +/* Multiplication of 2x2 matrices encoded in a row-major order float4 */ +ccl_device_inline float4 mat22_mult(const float4 a, const float4 b) +{ + return make_float4( + a.x * b.x + a.y * b.z, a.x * b.y + a.y * b.w, a.z * b.x + a.w * b.z, a.z * b.y + a.w * b.w); +} + +/* Determinant of a 2x2 matrix encoded in a row-major order float4 */ +ccl_device_inline float mat22_determinant(const float4 m) +{ + return m.x * m.w - m.y * m.z; +} + +/* Inverse of a 2x2 matrix encoded in a row-major order float4 */ +ccl_device_inline float mat22_inverse(const float4 m, ccl_private float4& m_inverse) +{ + float det = mat22_determinant(m); + if (fabsf(det) < MNEE_MIN_DETERMINANT) + return 0.f; + m_inverse = make_float4(m.w, -m.y, -m.z, m.x) / det; + return det; +} + +/* Update light sample */ +ccl_device_forceinline void mnee_update_light_sample(KernelGlobals kg, + const float3 P, + ccl_private LightSample *ls) +{ + /* correct light sample position/direction and pdf + * NOTE: preserve pdf in area measure */ + const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, ls->lamp); + + if (ls->type == LIGHT_POINT || ls->type == LIGHT_SPOT) { + ls->D = normalize_len(ls->P - P, &ls->t); + ls->Ng = -ls->D; + + float2 uv = map_to_sphere(ls->Ng); + ls->u = uv.x; + ls->v = uv.y; + + float invarea = klight->spot.invarea; + ls->eval_fac = (0.25f * M_1_PI_F) * invarea; + ls->pdf = invarea; + + if (ls->type == LIGHT_SPOT) { + /* spot light attenuation */ + float3 dir = make_float3(klight->spot.dir[0], klight->spot.dir[1], klight->spot.dir[2]); + ls->eval_fac *= spot_light_attenuation( + dir, klight->spot.spot_angle, klight->spot.spot_smooth, ls->Ng); + } + } + else if (ls->type == LIGHT_AREA) { + ls->D = normalize_len(ls->P - P, &ls->t); + ls->pdf = fabsf(klight->area.invarea); + } +} + +/* Compute orthonormal basis + * https://graphics.pixar.com/library/OrthonormalB/paper.pdf */ +ccl_device_forceinline void mnee_make_orthonormals(const float3 n, + ccl_private float3 *dp_du, + ccl_private float3 *dp_dv) +{ + if (n.z < 0.0f) { + const float a = 1.0f / (1.0f - n.z); + const float b = n.x * n.y * a; + *dp_du = make_float3(1.0f - n.x * n.x * a, -b, n.x); + *dp_dv = make_float3(b, n.y * n.y * a - 1.0f, -n.y); + } + else { + const float a = 1.0f / (1.0f + n.z); + const float b = -n.x * n.y * a; + *dp_du = make_float3(1.0f - n.x * n.x * a, b, -n.x); + *dp_dv = make_float3(b, 1.0f - n.y * n.y * a, -n.y); + } +} + +/* Manifold vertex setup from ray and intersection data */ +ccl_device_forceinline void mnee_setup_manifold_vertex(KernelGlobals kg, + ccl_private ManifoldVertex *vtx, + ccl_private ShaderClosure *bsdf, + const float eta, + const float2 n_offset, + ccl_private const Ray *ray, + ccl_private const Intersection *isect, + ccl_private ShaderData *sd_vtx) +{ + sd_vtx->object = (isect->object == OBJECT_NONE) ? kernel_tex_fetch(__prim_object, isect->prim) : + isect->object; + + sd_vtx->type = isect->type; + sd_vtx->flag = 0; + sd_vtx->object_flag = kernel_tex_fetch(__object_flag, sd_vtx->object); + + /* matrices and time */ + shader_setup_object_transforms(kg, sd_vtx, ray->time); + sd_vtx->time = ray->time; + + sd_vtx->prim = isect->prim; + sd_vtx->ray_length = isect->t; + + sd_vtx->u = isect->u; + sd_vtx->v = isect->v; + + sd_vtx->shader = kernel_tex_fetch(__tri_shader, sd_vtx->prim); + + float3 verts[3]; + float3 normals[3]; + uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd_vtx->prim); + + if (sd_vtx->type & PRIMITIVE_TRIANGLE) { + /* Static triangle. */ + + /* Load triangle vertices. */ + verts[0] = kernel_tex_fetch(__tri_verts, tri_vindex.w + 0); + verts[1] = kernel_tex_fetch(__tri_verts, tri_vindex.w + 1); + verts[2] = kernel_tex_fetch(__tri_verts, tri_vindex.w + 2); + + /* Vectors. */ + sd_vtx->P = triangle_point_from_uv(kg, sd_vtx, isect->object, isect->prim, isect->u, isect->v); + + /* Smooth normal. */ + if (sd_vtx->shader & SHADER_SMOOTH_NORMAL) { + /* Load triangle vertices. */ + normals[0] = kernel_tex_fetch(__tri_vnormal, tri_vindex.x); + normals[1] = kernel_tex_fetch(__tri_vnormal, tri_vindex.y); + normals[2] = kernel_tex_fetch(__tri_vnormal, tri_vindex.z); + } + } + else { /* if (sd_vtx->type & PRIMITIVE_MOTION_TRIANGLE) */ + /* Motion triangle. */ + + /* Get motion info. */ + int numsteps, numverts; + object_motion_info(kg, sd_vtx->object, &numsteps, &numverts, NULL); + + /* Figure out which steps we need to fetch and their interpolation factor. */ + int maxstep = numsteps * 2; + int step = min((int)(sd_vtx->time * maxstep), maxstep - 1); + float t = sd_vtx->time * maxstep - step; + + /* Find attribute. */ + int offset = intersection_find_attribute(kg, sd_vtx->object, ATTR_STD_MOTION_VERTEX_POSITION); + kernel_assert(offset != ATTR_STD_NOT_FOUND); + + /* Fetch vertex coordinates. */ + float3 next_verts[3]; + uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd_vtx->prim); + motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts); + motion_triangle_verts_for_step( + kg, tri_vindex, offset, numverts, numsteps, step + 1, next_verts); + + /* Interpolate between steps. */ + verts[0] = (1.0f - t) * verts[0] + t * next_verts[0]; + verts[1] = (1.0f - t) * verts[1] + t * next_verts[1]; + verts[2] = (1.0f - t) * verts[2] + t * next_verts[2]; + + /* Compute refined position. */ + sd_vtx->P = motion_triangle_point_from_uv( + kg, sd_vtx, isect->object, isect->prim, isect->u, isect->v, verts); + + /* Compute smooth normal. */ + if (sd_vtx->shader & SHADER_SMOOTH_NORMAL) { + /* Find attribute. */ + int offset = intersection_find_attribute(kg, sd_vtx->object, ATTR_STD_MOTION_VERTEX_NORMAL); + kernel_assert(offset != ATTR_STD_NOT_FOUND); + + /* Fetch vertex coordinates. */ + float3 next_normals[3]; + motion_triangle_normals_for_step(kg, tri_vindex, offset, numverts, numsteps, step, normals); + motion_triangle_normals_for_step( + kg, tri_vindex, offset, numverts, numsteps, step + 1, next_normals); + + /* Interpolate between steps. */ + normals[0] = (1.0f - t) * normals[0] + t * next_normals[0]; + normals[1] = (1.0f - t) * normals[1] + t * next_normals[1]; + normals[2] = (1.0f - t) * normals[2] + t * next_normals[2]; + } + } + + /* manifold vertex position */ + vtx->p = sd_vtx->P; + + if (!(sd_vtx->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) { + /* Instance transform. */ + object_position_transform_auto(kg, sd_vtx, &verts[0]); + object_position_transform_auto(kg, sd_vtx, &verts[1]); + object_position_transform_auto(kg, sd_vtx, &verts[2]); + object_normal_transform_auto(kg, sd_vtx, &normals[0]); + object_normal_transform_auto(kg, sd_vtx, &normals[1]); + object_normal_transform_auto(kg, sd_vtx, &normals[2]); + } + + /* Tangent space (position derivatives) wrt barycentric (u, v). */ + vtx->dp_du = verts[0] - verts[2]; + vtx->dp_dv = verts[1] - verts[2]; + + /* Geometric normal. */ + vtx->ng = normalize(cross(vtx->dp_du, vtx->dp_dv)); + if (sd_vtx->object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) + vtx->ng = -vtx->ng; + + /* Shading normal. */ + if (!(sd_vtx->shader & SHADER_SMOOTH_NORMAL)) { + vtx->n = vtx->ng; + vtx->dn_du = vtx->dn_dv = zero_float3(); + } + else { + /* Interpolate normals between vertices. */ + float n_len; + vtx->n = normalize_len(normals[0] * sd_vtx->u + normals[1] * sd_vtx->v + + normals[2] * (1.0f - sd_vtx->u - sd_vtx->v), + &n_len); + + /* Shading normal derivatives wrt barycentric (u, v) + * we calculate the derivative of n = |u*n0 + v*n1 + (1-u-v)*n2| using: + * d/du [f(u)/|f(u)|] = [d/du f(u)]/|f(u)| - f(u)/|f(u)|^3 <f(u), d/du f(u)>. */ + const float inv_n_len = 1.f / n_len; + vtx->dn_du = inv_n_len * (normals[0] - normals[2]); + vtx->dn_dv = inv_n_len * (normals[1] - normals[2]); + vtx->dn_du -= vtx->n * dot(vtx->n, vtx->dn_du); + vtx->dn_dv -= vtx->n * dot(vtx->n, vtx->dn_dv); + } + + /* dp_du and dp_dv need to be continuous across triangles for the h normal + * offset to yield a consistent halfvector while walking on the manifold. + * It's usually best to rely on the mesh uv layout, which is assumed to be + * continuous across the mesh. */ + float2 duv0, duv1; + bool found_uv = false; + AttributeDescriptor uv_desc = find_attribute(kg, sd_vtx, ATTR_STD_GENERATED); + if (uv_desc.offset != ATTR_STD_NOT_FOUND) { + float3 uvs[3]; + uvs[0] = kernel_tex_fetch(__attributes_float3, uv_desc.offset + tri_vindex.x); + uvs[1] = kernel_tex_fetch(__attributes_float3, uv_desc.offset + tri_vindex.y); + uvs[2] = kernel_tex_fetch(__attributes_float3, uv_desc.offset + tri_vindex.z); + duv0 = make_float2(uvs[0].x - uvs[2].x, uvs[0].y - uvs[2].y); + duv1 = make_float2(uvs[1].x - uvs[2].x, uvs[1].y - uvs[2].y); + found_uv = true; + } + else { + uv_desc = find_attribute(kg, sd_vtx, ATTR_STD_UV); + if (uv_desc.offset != ATTR_STD_NOT_FOUND) { + float2 uvs[3]; + uvs[0] = kernel_tex_fetch(__attributes_float2, uv_desc.offset + tri_vindex.x); + uvs[1] = kernel_tex_fetch(__attributes_float2, uv_desc.offset + tri_vindex.y); + uvs[2] = kernel_tex_fetch(__attributes_float2, uv_desc.offset + tri_vindex.z); + duv0 = make_float2(uvs[0].x - uvs[2].x, uvs[0].y - uvs[2].y); + duv1 = make_float2(uvs[1].x - uvs[2].x, uvs[1].y - uvs[2].y); + found_uv = true; + } + } + if (found_uv) { + const float det = duv0.x * duv1.y - duv0.y * duv1.x; + if (det != 0.f) { + const float inv_det = 1.f / det; + + /* Tangent space (position derivatives) wrt texture (u, v). */ + const float3 dp_du = vtx->dp_du; + const float3 dp_dv = vtx->dp_dv; + vtx->dp_du = (duv1.y * dp_du - duv0.y * dp_dv) * inv_det; + vtx->dp_dv = (-duv1.x * dp_du + duv0.x * dp_dv) * inv_det; + + /* Shading normal derivatives wrt texture (u, v). */ + const float3 dn_du = vtx->dn_du; + const float3 dn_dv = vtx->dn_dv; + vtx->dn_du = (duv1.y * dn_du - duv0.y * dn_dv) * inv_det; + vtx->dn_dv = (-duv1.x * dn_du + duv0.x * dn_dv) * inv_det; + } + } + + /* Orthonormalize (dp_du,dp_dv) using a linear transformation, which + * we use on (dn_du,dn_dv) as well so the new (u,v) are consistent. */ + const float inv_len_dp_du = 1.f / len(vtx->dp_du); + vtx->dp_du *= inv_len_dp_du; + vtx->dn_du *= inv_len_dp_du; + const float dpdu_dot_dpdv = dot(vtx->dp_du, vtx->dp_dv); + const float3 dp_dv = vtx->dp_dv - dpdu_dot_dpdv * vtx->dp_du; + const float3 dn_dv = vtx->dn_dv - dpdu_dot_dpdv * vtx->dn_du; + const float inv_len_dp_dv = 1.f / len(dp_dv); + vtx->dp_dv = dp_dv * inv_len_dp_dv; + vtx->dn_dv = dn_dv * inv_len_dp_dv; + + /* Initialize constraint and its derivates. */ + vtx->a = vtx->c = zero_float4(); + vtx->b = make_float4(1.f, 0.f, 0.f, 1.f); + vtx->constraint = zero_float2(); + vtx->n_offset = n_offset; + + /* Closure information. */ + vtx->bsdf = bsdf; + vtx->eta = eta; + + /* Geometric information. */ + vtx->uv = make_float2(isect->u, isect->v); + vtx->object = sd_vtx->object; + vtx->prim = sd_vtx->prim; + vtx->shader = sd_vtx->shader; +} + +/* Compute constraint derivatives. */ +ccl_device_forceinline bool mnee_compute_constraint_derivatives( + int vertex_count, + ccl_private ManifoldVertex *vertices, + ccl_private const float3 &surface_sample_pos, + const bool light_fixed_direction, + const float3 light_sample) +{ + for (int vi = 0; vi < vertex_count; vi++) { + ccl_private ManifoldVertex &v = vertices[vi]; + + /* Direction toward surface sample. */ + float3 wi = (vi == 0) ? surface_sample_pos - v.p : vertices[vi - 1].p - v.p; + float ili = len(wi); + if (ili < MNEE_MIN_DISTANCE) + return false; + ili = 1.f / ili; + wi *= ili; + + /* Direction toward light sample. */ + float3 wo = (vi == vertex_count - 1) ? + (light_fixed_direction ? light_sample : light_sample - v.p) : + vertices[vi + 1].p - v.p; + float ilo = len(wo); + if (ilo < MNEE_MIN_DISTANCE) + return false; + ilo = 1.f / ilo; + wo *= ilo; + + /* Invert ior if coming from inside. */ + float eta = v.eta; + if (dot(wi, v.ng) < .0f) + eta = 1.f / eta; + + /* Half vector. */ + float3 H = -(wi + eta * wo); + float ilh = 1.f / len(H); + H *= ilh; + + ilo *= eta * ilh; + ili *= ilh; + + /* Local shading frame. */ + float dp_du_dot_n = dot(v.dp_du, v.n); + float3 s = v.dp_du - dp_du_dot_n * v.n; + float inv_len_s = 1.f / len(s); + s *= inv_len_s; + float3 t = cross(v.n, s); + + float3 dH_du, dH_dv; + + /* Constraint derivatives wrt previous vertex. */ + if (vi > 0) { + ccl_private ManifoldVertex &v_prev = vertices[vi - 1]; + dH_du = (v_prev.dp_du - wi * dot(wi, v_prev.dp_du)) * ili; + dH_dv = (v_prev.dp_dv - wi * dot(wi, v_prev.dp_dv)) * ili; + dH_du -= H * dot(dH_du, H); + dH_dv -= H * dot(dH_dv, H); + dH_du = -dH_du; + dH_dv = -dH_dv; + + v.a = make_float4(dot(dH_du, s), dot(dH_dv, s), dot(dH_du, t), dot(dH_dv, t)); + } + + /* Constraint derivatives wrt current vertex. */ + if (vi == vertex_count - 1 && light_fixed_direction) { + dH_du = ili * (-v.dp_du + wi * dot(wi, v.dp_du)); + dH_dv = ili * (-v.dp_dv + wi * dot(wi, v.dp_dv)); + } + else { + dH_du = -v.dp_du * (ili + ilo) + wi * (dot(wi, v.dp_du) * ili) + + wo * (dot(wo, v.dp_du) * ilo); + dH_dv = -v.dp_dv * (ili + ilo) + wi * (dot(wi, v.dp_dv) * ili) + + wo * (dot(wo, v.dp_dv) * ilo); + } + dH_du -= H * dot(dH_du, H); + dH_dv -= H * dot(dH_dv, H); + dH_du = -dH_du; + dH_dv = -dH_dv; + + float3 ds_du = -inv_len_s * (dot(v.dp_du, v.dn_du) * v.n + dp_du_dot_n * v.dn_du); + float3 ds_dv = -inv_len_s * (dot(v.dp_du, v.dn_dv) * v.n + dp_du_dot_n * v.dn_dv); + ds_du -= s * dot(s, ds_du); + ds_dv -= s * dot(s, ds_dv); + float3 dt_du = cross(v.dn_du, s) + cross(v.n, ds_du); + float3 dt_dv = cross(v.dn_dv, s) + cross(v.n, ds_dv); + + v.b = make_float4(dot(dH_du, s) + dot(H, ds_du), + dot(dH_dv, s) + dot(H, ds_dv), + dot(dH_du, t) + dot(H, dt_du), + dot(dH_dv, t) + dot(H, dt_dv)); + + /* Constraint derivatives wrt next vertex. */ + if (vi < vertex_count - 1) { + ccl_private ManifoldVertex &v_next = vertices[vi + 1]; + dH_du = (v_next.dp_du - wo * dot(wo, v_next.dp_du)) * ilo; + dH_dv = (v_next.dp_dv - wo * dot(wo, v_next.dp_dv)) * ilo; + dH_du -= H * dot(dH_du, H); + dH_dv -= H * dot(dH_dv, H); + dH_du = -dH_du; + dH_dv = -dH_dv; + + v.c = make_float4(dot(dH_du, s), dot(dH_dv, s), dot(dH_du, t), dot(dH_dv, t)); + } + + /* Constraint vector wrt. the local shading frame. */ + v.constraint = make_float2(dot(s, H), dot(t, H)) - v.n_offset; + } + return true; +} + +/* Invert (block) constraint derivative matrix and solve linear system so we can map dh back to dx: + * dh / dx = A + * dx = inverse(A) x dh + * to use for specular specular manifold walk + * (See for example http://faculty.washington.edu/finlayso/ebook/algebraic/advanced/LUtri.htm + * for block tridiagonal matrix based linear system solve) */ +ccl_device_forceinline bool mnee_solve_matrix_h_to_x(int vertex_count, + ccl_private ManifoldVertex *vertices, + ccl_private float2 *dx) +{ + float4 Li[MNEE_MAX_CAUSTIC_CASTERS]; + float2 C[MNEE_MAX_CAUSTIC_CASTERS]; + + /* Block tridiagonal LU factorization. */ + float4 Lk = vertices[0].b; + if (mat22_inverse(Lk, Li[0]) == 0.f) + return false; + + C[0] = vertices[0].constraint; + + for (int k = 1; k < vertex_count; k++) { + float4 A = mat22_mult(vertices[k].a, Li[k - 1]); + + Lk = vertices[k].b - mat22_mult(A, vertices[k - 1].c); + if (mat22_inverse(Lk, Li[k]) == 0.f) + return false; + + C[k] = vertices[k].constraint - mat22_mult(A, C[k - 1]); + } + + dx[vertex_count - 1] = mat22_mult(Li[vertex_count - 1], C[vertex_count - 1]); + for (int k = vertex_count - 2; k > -1; k--) + dx[k] = mat22_mult(Li[k], C[k] - mat22_mult(vertices[k].c, dx[k + 1])); + + return true; +} + +/* Newton solver to walk on specular manifold. */ +ccl_device_forceinline bool mnee_newton_solver(KernelGlobals kg, + ccl_private const ShaderData *sd, + ccl_private ShaderData *sd_vtx, + ccl_private const LightSample *ls, + int vertex_count, + ccl_private ManifoldVertex *vertices) +{ + float2 dx[MNEE_MAX_CAUSTIC_CASTERS]; + ManifoldVertex tentative[MNEE_MAX_CAUSTIC_CASTERS]; + + Ray projection_ray; + projection_ray.self.light_object = OBJECT_NONE; + projection_ray.self.light_prim = PRIM_NONE; + projection_ray.dP = differential_make_compact(sd->dP); + projection_ray.dD = differential_zero_compact(); + projection_ray.time = sd->time; + Intersection projection_isect; + + const bool light_fixed_direction = (ls->t == FLT_MAX); + const float3 light_sample = light_fixed_direction ? ls->D : ls->P; + + /* We start gently, potentially ramping up to beta = 1, since target configurations + * far from the seed path can send the proposed solution further than the linearized + * local differential geometric quantities are meant for (especially dn/du and dn/dv). */ + float beta = .1f; + bool reduce_stepsize = false; + bool resolve_constraint = true; + for (int iteration = 0; iteration < MNEE_MAX_ITERATIONS; iteration++) { + if (resolve_constraint) { + /* Calculate constraintand its derivatives for vertices. */ + if (!mnee_compute_constraint_derivatives( + vertex_count, vertices, sd->P, light_fixed_direction, light_sample)) + return false; + + /* Calculate constraint norm. */ + float constraint_norm = 0.f; + for (int vi = 0; vi < vertex_count; vi++) + constraint_norm = fmaxf(constraint_norm, len(vertices[vi].constraint)); + + /* Return if solve successful. */ + if (constraint_norm < MNEE_SOLVER_THRESHOLD) + return true; + + /* Invert derivative matrix. */ + if (!mnee_solve_matrix_h_to_x(vertex_count, vertices, dx)) + return false; + } + + /* Construct tentative new vertices and project back onto surface. */ + for (int vi = 0; vi < vertex_count; vi++) { + ccl_private ManifoldVertex &mv = vertices[vi]; + + /* Tentative new position on linearized manifold (tangent plane). */ + float3 tentative_p = mv.p - beta * (dx[vi].x * mv.dp_du + dx[vi].y * mv.dp_dv); + + /* For certain configs, the first solve ends up below the receiver. */ + if (vi == 0) { + const float3 wo = tentative_p - sd->P; + if (dot(sd->Ng, wo) <= 0.f) { + /* Change direction for the 1st interface. */ + tentative_p = mv.p + beta * (dx[vi].x * mv.dp_du + dx[vi].y * mv.dp_dv); + } + } + + /* Project tentative point from tangent plane back to surface + * we ignore all other intersections since this tentative path could lead + * valid to a valid path even if occluded. */ + if (vi == 0) { + projection_ray.self.object = sd->object; + projection_ray.self.prim = sd->prim; + projection_ray.P = sd->P; + } + else { + ccl_private const ManifoldVertex &pv = vertices[vi - 1]; + projection_ray.self.object = pv.object; + projection_ray.self.prim = pv.prim; + projection_ray.P = pv.p; + } + projection_ray.D = normalize_len(tentative_p - projection_ray.P, &projection_ray.t); + projection_ray.t *= MNEE_PROJECTION_DISTANCE_MULTIPLIER; + + bool projection_success = false; + for (int isect_count = 0; isect_count < MNEE_MAX_INTERSECTION_COUNT; isect_count++) { + bool hit = scene_intersect(kg, &projection_ray, PATH_RAY_TRANSMIT, &projection_isect); + if (!hit) + break; + + int hit_object = (projection_isect.object == OBJECT_NONE) ? + kernel_tex_fetch(__prim_object, projection_isect.prim) : + projection_isect.object; + + if (hit_object == mv.object) { + projection_success = true; + break; + } + + projection_ray.self.object = projection_isect.object; + projection_ray.self.prim = projection_isect.prim; + projection_ray.P += projection_isect.t * projection_ray.D; + projection_ray.t -= projection_isect.t; + } + if (!projection_success) { + reduce_stepsize = true; + break; + } + + /* Setup corrected manifold vertex. */ + mnee_setup_manifold_vertex(kg, + &tentative[vi], + mv.bsdf, + mv.eta, + mv.n_offset, + &projection_ray, + &projection_isect, + sd_vtx); + } + + /* Check that tentative path is still transmissive. */ + if (!reduce_stepsize) { + for (int vi = 0; vi < vertex_count; vi++) { + ccl_private ManifoldVertex &tv = tentative[vi]; + + /* Direction toward surface sample. */ + const float3 wi = (vi == 0 ? sd->P : tentative[vi - 1].p) - tv.p; + /* Direction toward light sample. */ + const float3 wo = (vi == vertex_count - 1) ? light_fixed_direction ? ls->D : ls->P - tv.p : + tentative[vi + 1].p - tv.p; + + if (dot(tv.n, wi) * dot(tv.n, wo) >= 0.f) { + reduce_stepsize = true; + break; + } + } + } + + if (reduce_stepsize) { + /* Adjust step if can't land on right surface. */ + reduce_stepsize = false; + resolve_constraint = false; + beta *= .5f; + continue; + } + + /* Copy tentative vertices to main vertex list. */ + for (int vi = 0; vi < vertex_count; vi++) + vertices[vi] = tentative[vi]; + + /* Increase the step to get back to 1. */ + resolve_constraint = true; + beta = min(1.f, 2.f * beta); + } + + return false; +} + +/* Sample bsdf in half-vector measure. */ +ccl_device_forceinline float2 +mnee_sample_bsdf_dh(ClosureType type, float alpha_x, float alpha_y, float sample_u, float sample_v) +{ + float alpha2; + float cos_phi, sin_phi; + + if (alpha_x == alpha_y) { + float phi = sample_v * M_2PI_F; + fast_sincosf(phi, &sin_phi, &cos_phi); + alpha2 = alpha_x * alpha_x; + } + else { + float phi = atanf(alpha_y / alpha_x * tanf(M_2PI_F * sample_v + M_PI_2_F)); + if (sample_v > .5f) + phi += M_PI_F; + fast_sincosf(phi, &sin_phi, &cos_phi); + float alpha_x2 = alpha_x * alpha_x; + float alpha_y2 = alpha_y * alpha_y; + alpha2 = 1.f / (cos_phi * cos_phi / alpha_x2 + sin_phi * sin_phi / alpha_y2); + } + + /* Map sampled angles to micro-normal direction h. */ + float tan2_theta = alpha2; + if (type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) { + tan2_theta *= -logf(1.0f - sample_u); + } + else { /* if (type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID || type == + CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_FRESNEL_ID) */ + tan2_theta *= sample_u / (1.0f - sample_u); + } + float cos2_theta = 1.0f / (1.0f + tan2_theta); + float sin_theta = safe_sqrtf(1.0f - cos2_theta); + return make_float2(cos_phi * sin_theta, sin_phi * sin_theta); +} + +/* Evaluate product term inside eq.6 at solution interface vi + * divided by corresponding sampled pdf: + * fr(vi)_do / pdf_dh(vi) x |do/dh| x |n.wo / n.h| + * We assume here that the pdf (in half-vector measure) is the same as + * the one calculation when sampling the microfacet normals from the + * specular chain above: this allows us to simplify the bsdf weight */ +ccl_device_forceinline float3 mnee_eval_bsdf_contribution(ccl_private ShaderClosure *closure, + float3 wi, + float3 wo) +{ + ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)closure; + + float cosNO = dot(bsdf->N, wi); + float cosNI = dot(bsdf->N, wo); + + float3 Ht = normalize(-(bsdf->ior * wo + wi)); + float cosHO = dot(Ht, wi); + + float alpha2 = bsdf->alpha_x * bsdf->alpha_y; + float cosThetaM = dot(bsdf->N, Ht); + + float G; + if (bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) { + /* Eq. 26, 27: now calculate G1(i,m) and G1(o,m). */ + G = bsdf_beckmann_G1(bsdf->alpha_x, cosNO) * bsdf_beckmann_G1(bsdf->alpha_x, cosNI); + } + else { /* if (type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID || type == + CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_FRESNEL_ID) */ + /* Eq. 34: now calculate G1(i,m) and G1(o,m). */ + G = (2.f / (1.f + safe_sqrtf(1.f + alpha2 * (1.f - cosNO * cosNO) / (cosNO * cosNO)))) * + (2.f / (1.f + safe_sqrtf(1.f + alpha2 * (1.f - cosNI * cosNI) / (cosNI * cosNI)))); + } + + /* + * bsdf_do = (1 - F) * D_do * G * |h.wi| / (n.wi * n.wo) + * pdf_dh = D_dh * cosThetaM + * D_do = D_dh * |dh/do| + * + * contribution = bsdf_do * |do/dh| * |n.wo / n.h| / pdf_dh + * = (1 - F) * G * |h.wi / (n.wi * n.h^2)| + */ + return bsdf->weight * G * fabsf(cosHO / (cosNO * sqr(cosThetaM))); +} + +/* Compute transfer matrix determinant |T1| = |dx1/dxn| (and |dh/dx| in the process) */ +ccl_device_forceinline bool mnee_compute_transfer_matrix(ccl_private const ShaderData *sd, + ccl_private const LightSample *ls, + int vertex_count, + ccl_private ManifoldVertex *vertices, + ccl_private float *dx1_dxlight, + ccl_private float *dh_dx) +{ + /* Simplified block tridiagonal LU factorization. */ + float4 Li; + float4 U[MNEE_MAX_CAUSTIC_CASTERS - 1]; + + float4 Lk = vertices[0].b; + float Lk_det = mat22_inverse(Lk, Li); + if (Lk_det == 0.f) + return false; + + float det_dh_dx = Lk_det; + + for (int k = 1; k < vertex_count; k++) { + U[k - 1] = mat22_mult(Li, vertices[k - 1].c); + + Lk = vertices[k].b - mat22_mult(vertices[k].a, U[k - 1]); + Lk_det = mat22_inverse(Lk, Li); + if (Lk_det == 0.f) + return false; + + det_dh_dx *= Lk_det; + } + + /* Fill out constraint derivatives wrt light vertex param. */ + + /* Local shading frame at last free vertex. */ + int mi = vertex_count - 1; + ccl_private const ManifoldVertex &m = vertices[mi]; + + float3 s = normalize(m.dp_du - dot(m.dp_du, m.n) * m.n); + float3 t = cross(m.n, s); + + /* Local differential geometry. */ + float3 dp_du, dp_dv; + mnee_make_orthonormals(ls->Ng, &dp_du, &dp_dv); + + /* Direction toward surface sample. */ + float3 wi = vertex_count == 1 ? sd->P - m.p : vertices[mi - 1].p - m.p; + float ili = 1.f / len(wi); + wi *= ili; + + /* Invert ior if coming from inside. */ + float eta = m.eta; + if (dot(wi, m.ng) < .0f) + eta = 1.f / eta; + + float dxn_dwn; + float4 dc_dlight; + + if (ls->t == FLT_MAX) { + /* Constant direction toward light sample. */ + float3 wo = ls->D; + + /* Half vector. */ + float3 H = -(wi + eta * wo); + float ilh = 1.f / len(H); + H *= ilh; + + float ilo = -eta * ilh; + + float cos_theta = dot(wo, m.n); + float sin_theta = safe_sqrtf(1.f - sqr(cos_theta)); + float cos_phi = dot(wo, s); + float sin_phi = safe_sqrtf(1.f - sqr(cos_phi)); + + /* Wo = (cos_phi * sin_theta) * s + (sin_phi * sin_theta) * t + cos_theta * n. */ + float3 dH_dtheta = ilo * (cos_theta * (cos_phi * s + sin_phi * t) - sin_theta * m.n); + float3 dH_dphi = ilo * sin_theta * (-sin_phi * s + cos_phi * t); + dH_dtheta -= H * dot(dH_dtheta, H); + dH_dphi -= H * dot(dH_dphi, H); + + /* constraint derivatives wrt light direction expressed + * in spherical coordinates (theta, phi). */ + dc_dlight = make_float4( + dot(dH_dtheta, s), dot(dH_dphi, s), dot(dH_dtheta, t), dot(dH_dphi, t)); + + /* Jacobian to convert dtheta x dphi to dw measure. */ + dxn_dwn = 1.f / fmaxf(MNEE_MIN_DISTANCE, fabsf(sin_theta)); + } + else { + /* Direction toward light sample. */ + float3 wo = ls->P - m.p; + float ilo = 1.f / len(wo); + wo *= ilo; + + /* Half vector. */ + float3 H = -(wi + eta * wo); + float ilh = 1.f / len(H); + H *= ilh; + + ilo *= eta * ilh; + + float3 dH_du = (dp_du - wo * dot(wo, dp_du)) * ilo; + float3 dH_dv = (dp_dv - wo * dot(wo, dp_dv)) * ilo; + dH_du -= H * dot(dH_du, H); + dH_dv -= H * dot(dH_dv, H); + dH_du = -dH_du; + dH_dv = -dH_dv; + + dc_dlight = make_float4(dot(dH_du, s), dot(dH_dv, s), dot(dH_du, t), dot(dH_dv, t)); + + /* Neutral value since dc_dlight is already in the desired vertex area measure. */ + dxn_dwn = 1.f; + } + + /* Compute transfer matrix. */ + float4 Tp = -mat22_mult(Li, dc_dlight); + for (int k = vertex_count - 2; k > -1; k--) + Tp = -mat22_mult(U[k], Tp); + + *dx1_dxlight = fabsf(mat22_determinant(Tp)) * dxn_dwn; + *dh_dx = fabsf(det_dh_dx); + return true; +} + +/* Calculate the path contribution. */ +ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg, + IntegratorState state, + ccl_private ShaderData *sd, + ccl_private ShaderData *sd_mnee, + ccl_private LightSample *ls, + int vertex_count, + ccl_private ManifoldVertex *vertices, + ccl_private BsdfEval *throughput) +{ + float wo_len; + float3 wo = normalize_len(vertices[0].p - sd->P, &wo_len); + + /* Initialize throughput and evaluate receiver bsdf * |n.wo|. */ + shader_bsdf_eval(kg, sd, wo, false, throughput, ls->shader); + + /* Update light sample with new position / direct.ion + * and keep pdf in vertex area measure */ + mnee_update_light_sample(kg, vertices[vertex_count - 1].p, ls); + + /* Evaluate light sam.ple + * in case the light has a node-based shader: + * 1. sd_mnee will be used to store light data, which is why we need to do + * this evaluation here. sd_mnee needs to contain the solution's last + * interface data at the end of the call for the shadow ray setup to work. + * 2. ls needs to contain the last interface data for the light shader to + * evaluate properly */ + float3 light_eval = light_sample_shader_eval(kg, state, sd_mnee, ls, sd->time); + bsdf_eval_mul3(throughput, light_eval / ls->pdf); + + /* Generalized geometry term. */ + + float dh_dx; + float dx1_dxlight; + if (!mnee_compute_transfer_matrix(sd, ls, vertex_count, vertices, &dx1_dxlight, &dh_dx)) + return false; + + /* Receiver bsdf eval above already contains |n.wo|. */ + const float dw0_dx1 = fabsf(dot(wo, vertices[0].n)) / sqr(wo_len); + + const float G = dw0_dx1 * dx1_dxlight; + bsdf_eval_mul(throughput, G); + + /* Specular reflectance. */ + + /* Probe ray / isect. */ + Ray probe_ray; + probe_ray.self.light_object = ls->object; + probe_ray.self.light_prim = ls->prim; + probe_ray.dP = differential_make_compact(sd->dP); + probe_ray.dD = differential_zero_compact(); + probe_ray.time = sd->time; + Intersection probe_isect; + + probe_ray.self.object = sd->object; + probe_ray.self.prim = sd->prim; + probe_ray.P = sd->P; + + float3 wi; + float wi_len; + for (int vi = 0; vi < vertex_count; vi++) { + ccl_private const ManifoldVertex &v = vertices[vi]; + + /* Check visiblity. */ + probe_ray.D = normalize_len(v.p - probe_ray.P, &probe_ray.t); + if (scene_intersect(kg, &probe_ray, PATH_RAY_TRANSMIT, &probe_isect)) { + int hit_object = (probe_isect.object == OBJECT_NONE) ? + kernel_tex_fetch(__prim_object, probe_isect.prim) : + probe_isect.object; + /* Test whether the ray hit the appropriate object at its intended location. */ + if (hit_object != v.object || fabsf(probe_ray.t - probe_isect.t) > MNEE_MIN_DISTANCE) + return false; + } + probe_ray.self.object = v.object; + probe_ray.self.prim = v.prim; + probe_ray.P = v.p; + + /* Set view looking dir. */ + wi = -wo; + wi_len = wo_len; + + /* Setup shader data for vertex vi. */ + shader_setup_from_sample(kg, + sd_mnee, + v.p, + v.n, + wi, + v.shader, + v.object, + v.prim, + v.uv.x, + v.uv.y, + wi_len, + sd->time, + false, + LAMP_NONE); + + /* Evaluate shader nodes at solution vi. */ + shader_eval_surface<KERNEL_FEATURE_NODE_MASK_SURFACE_SHADOW>( + kg, state, sd_mnee, NULL, PATH_RAY_DIFFUSE, true); + + /* Set light looking dir. */ + wo = (vi == vertex_count - 1) ? (ls->t == FLT_MAX ? ls->D : ls->P - v.p) : + vertices[vi + 1].p - v.p; + wo = normalize_len(wo, &wo_len); + + /* Evaluate product term inside eq.6 at solution interface. vi + * divided by corresponding sampled pdf: + * fr(vi)_do / pdf_dh(vi) x |do/dh| x |n.wo / n.h| */ + float3 bsdf_contribution = mnee_eval_bsdf_contribution(v.bsdf, wi, wo); + bsdf_eval_mul3(throughput, bsdf_contribution); + } + + return true; +} + +/* Manifold next event estimation path sampling. */ +ccl_device_forceinline bool kernel_path_mnee_sample(KernelGlobals kg, + IntegratorState state, + ccl_private ShaderData *sd, + ccl_private ShaderData *sd_mnee, + ccl_private const RNGState *rng_state, + ccl_private LightSample *ls, + ccl_private BsdfEval *throughput) +{ + /* + * 1. send seed ray from shading point to light sample position (or along sampled light + * direction), making sure it intersects a caustic caster at least once, ignoring all other + * intersections (the final path could be valid even though objects could occlude the light + * this seed point), building an array of manifold vertices. + */ + + /* Setup probe ray. */ + Ray probe_ray; + probe_ray.self.object = sd->object; + probe_ray.self.prim = sd->prim; + probe_ray.self.light_object = ls->object; + probe_ray.self.light_prim = ls->prim; + probe_ray.P = sd->P; + if (ls->t == FLT_MAX) { + /* Distant / env light. */ + probe_ray.D = ls->D; + probe_ray.t = ls->t; + } + else { + /* Other lights, avoid self-intersection. */ + probe_ray.D = ls->P - probe_ray.P; + probe_ray.D = normalize_len(probe_ray.D, &probe_ray.t); + } + probe_ray.dP = differential_make_compact(sd->dP); + probe_ray.dD = differential_zero_compact(); + probe_ray.time = sd->time; + Intersection probe_isect; + + ManifoldVertex vertices[MNEE_MAX_CAUSTIC_CASTERS]; + + int vertex_count = 0; + for (int isect_count = 0; isect_count < MNEE_MAX_INTERSECTION_COUNT; isect_count++) { + bool hit = scene_intersect(kg, &probe_ray, PATH_RAY_TRANSMIT, &probe_isect); + if (!hit) + break; + + const int object_flags = intersection_get_object_flags(kg, &probe_isect); + if (object_flags & SD_OBJECT_CAUSTICS_CASTER) { + + /* Do we have enough slots. */ + if (vertex_count >= MNEE_MAX_CAUSTIC_CASTERS) + return false; + + ccl_private ManifoldVertex &mv = vertices[vertex_count++]; + + /* Setup shader data on caustic caster and evaluate context. */ + shader_setup_from_ray(kg, sd_mnee, &probe_ray, &probe_isect); + + /* Last bool argument is the MNEE flag (for TINY_MAX_CLOSURE cap in kernel_shader.h). */ + shader_eval_surface<KERNEL_FEATURE_NODE_MASK_SURFACE_SHADOW>( + kg, state, sd_mnee, NULL, PATH_RAY_DIFFUSE, true); + + /* get and sample refraction bsdf. */ + bool found_transimissive_microfacet_bsdf = false; + for (int ci = 0; ci < sd_mnee->num_closure; ci++) { + ccl_private ShaderClosure *bsdf = &sd_mnee->closure[ci]; + if (bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID || + bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID) { + + found_transimissive_microfacet_bsdf = true; + ccl_private MicrofacetBsdf *microfacet_bsdf = (ccl_private MicrofacetBsdf *)bsdf; + + /* Figure out appropriate index of refraction ratio. */ + const float eta = (sd_mnee->flag & SD_BACKFACING) ? 1.0f / microfacet_bsdf->ior : + microfacet_bsdf->ior; + + /* Sample transmissive microfacet bsdf. */ + float bsdf_u, bsdf_v; + path_state_rng_2D(kg, rng_state, PRNG_BSDF_U, &bsdf_u, &bsdf_v); + float2 h = mnee_sample_bsdf_dh( + bsdf->type, microfacet_bsdf->alpha_x, microfacet_bsdf->alpha_y, bsdf_u, bsdf_v); + + /* Setup differential geometry on vertex. */ + mnee_setup_manifold_vertex(kg, &mv, bsdf, eta, h, &probe_ray, &probe_isect, sd_mnee); + break; + } + } + if (!found_transimissive_microfacet_bsdf) + return false; + } + + probe_ray.self.object = probe_isect.object; + probe_ray.self.prim = probe_isect.prim; + probe_ray.P += probe_isect.t * probe_ray.D; + if (ls->t != FLT_MAX) + probe_ray.t -= probe_isect.t; + }; + + /* Mark the manifold walk invalid to keep mollification on by default. */ + INTEGRATOR_STATE_WRITE(state, path, mnee) &= ~PATH_MNEE_VALID; + + if (vertex_count == 0) + return false; + + /* Check whether the transmission depth limit is reached before continuing. */ + const int transmission_bounce = INTEGRATOR_STATE(state, path, transmission_bounce) + + vertex_count; + if (transmission_bounce >= kernel_data.integrator.max_transmission_bounce) + return false; + + /* Check whether the diffuse depth limit is reached before continuing. */ + const int diffuse_bounce = INTEGRATOR_STATE(state, path, diffuse_bounce) + 1; + if (diffuse_bounce >= kernel_data.integrator.max_diffuse_bounce) + return false; + + /* Check whether the overall depth limit is reached before continuing. */ + const int bounce = INTEGRATOR_STATE(state, path, bounce) + diffuse_bounce + transmission_bounce; + if (bounce >= kernel_data.integrator.max_bounce) + return false; + + /* Mark the manifold walk valid to turn off mollification regardless of how successful the walk + * is: this is noticeable when another mnee is performed deeper in the path, for an internally + * reflected ray for example. If mollification was active for the reflection, a clear + * discontinuity is visible between direct and indirect contributions */ + INTEGRATOR_STATE_WRITE(state, path, mnee) |= PATH_MNEE_VALID; + + /* 2. Walk on the specular manifold to find vertices on the + * casters that satisfy snell's law for each interface + */ + if (mnee_newton_solver(kg, sd, sd_mnee, ls, vertex_count, vertices)) { + /* 3. If a solution exists, calculate contribution of the corresponding path */ + if (!mnee_path_contribution(kg, state, sd, sd_mnee, ls, vertex_count, vertices, throughput)) + return false; + + return true; + } + + return false; +} + +CCL_NAMESPACE_END + +#endif /* __MNEE__ */ diff --git a/intern/cycles/kernel/integrator/path_state.h b/intern/cycles/kernel/integrator/path_state.h index e6bdf21499c..ec93ac6d46f 100644 --- a/intern/cycles/kernel/integrator/path_state.h +++ b/intern/cycles/kernel/integrator/path_state.h @@ -57,6 +57,10 @@ ccl_device_inline void path_state_init_integrator(KernelGlobals kg, INTEGRATOR_STATE_WRITE(state, path, continuation_probability) = 1.0f; INTEGRATOR_STATE_WRITE(state, path, throughput) = make_float3(1.0f, 1.0f, 1.0f); +#ifdef __MNEE__ + INTEGRATOR_STATE_WRITE(state, path, mnee) = 0; +#endif + INTEGRATOR_STATE_WRITE(state, isect, object) = OBJECT_NONE; INTEGRATOR_STATE_WRITE(state, isect, prim) = PRIM_NONE; diff --git a/intern/cycles/kernel/integrator/shade_background.h b/intern/cycles/kernel/integrator/shade_background.h index 69dc3dc772d..62b3ce1c15c 100644 --- a/intern/cycles/kernel/integrator/shade_background.h +++ b/intern/cycles/kernel/integrator/shade_background.h @@ -101,6 +101,22 @@ ccl_device_inline void integrate_background(KernelGlobals kg, #endif } +#ifdef __MNEE__ + if (INTEGRATOR_STATE(state, path, mnee) & PATH_MNEE_CULL_LIGHT_CONNECTION) { + if (kernel_data.background.use_mis) { + for (int lamp = 0; lamp < kernel_data.integrator.num_all_lights; lamp++) { + /* This path should have been resolved with mnee, it will + * generate a firefly for small lights since it is improbable. */ + const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp); + if (klight->type == LIGHT_BACKGROUND && klight->use_caustics) { + eval_background = false; + break; + } + } + } + } +#endif /* __MNEE__ */ + /* Evaluate background shader. */ float3 L = (eval_background) ? integrator_eval_background_shader(kg, state, render_buffer) : zero_float3(); @@ -140,6 +156,16 @@ ccl_device_inline void integrate_distant_lights(KernelGlobals kg, } #endif +#ifdef __MNEE__ + if (INTEGRATOR_STATE(state, path, mnee) & PATH_MNEE_CULL_LIGHT_CONNECTION) { + /* This path should have been resolved with mnee, it will + * generate a firefly for small lights since it is improbable. */ + const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp); + if (klight->use_caustics) + return; + } +#endif /* __MNEE__ */ + /* Evaluate light shader. */ /* TODO: does aliasing like this break automatic SoA in CUDA? */ ShaderDataTinyStorage emission_sd_storage; @@ -160,7 +186,8 @@ ccl_device_inline void integrate_distant_lights(KernelGlobals kg, /* Write to render buffer. */ const float3 throughput = INTEGRATOR_STATE(state, path, throughput); - kernel_accum_emission(kg, state, throughput * light_eval, render_buffer); + kernel_accum_emission( + kg, state, throughput * light_eval, render_buffer, kernel_data.background.lightgroup); } } } diff --git a/intern/cycles/kernel/integrator/shade_light.h b/intern/cycles/kernel/integrator/shade_light.h index 4a519a76ed0..be926c78439 100644 --- a/intern/cycles/kernel/integrator/shade_light.h +++ b/intern/cycles/kernel/integrator/shade_light.h @@ -78,7 +78,7 @@ ccl_device_inline void integrate_light(KernelGlobals kg, /* Write to render buffer. */ const float3 throughput = INTEGRATOR_STATE(state, path, throughput); - kernel_accum_emission(kg, state, throughput * light_eval, render_buffer); + kernel_accum_emission(kg, state, throughput * light_eval, render_buffer, ls.group); } ccl_device void integrator_shade_light(KernelGlobals kg, diff --git a/intern/cycles/kernel/integrator/shade_surface.h b/intern/cycles/kernel/integrator/shade_surface.h index df9af6ca107..a9bf3b5b432 100644 --- a/intern/cycles/kernel/integrator/shade_surface.h +++ b/intern/cycles/kernel/integrator/shade_surface.h @@ -6,6 +6,8 @@ #include "kernel/film/accumulate.h" #include "kernel/film/passes.h" +#include "kernel/integrator/mnee.h" + #include "kernel/integrator/path_state.h" #include "kernel/integrator/shader_eval.h" #include "kernel/integrator/subsurface.h" @@ -85,13 +87,15 @@ ccl_device_forceinline void integrate_surface_emission(KernelGlobals kg, } const float3 throughput = INTEGRATOR_STATE(state, path, throughput); - kernel_accum_emission(kg, state, throughput * L, render_buffer); + kernel_accum_emission( + kg, state, throughput * L, render_buffer, object_lightgroup(kg, sd->object)); } #endif /* __EMISSION__ */ #ifdef __EMISSION__ /* Path tracing: sample point on light and evaluate light shader, then * queue shadow ray to be traced. */ +template<uint node_feature_mask> ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg, IntegratorState state, ccl_private ShaderData *sd, @@ -124,34 +128,65 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg, * integrate_surface_bounce, evaluate the BSDF, and only then evaluate * the light shader. This could also move to its own kernel, for * non-constant light sources. */ - ShaderDataTinyStorage emission_sd_storage; + ShaderDataCausticsStorage emission_sd_storage; ccl_private ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage); - const float3 light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, sd->time); - if (is_zero(light_eval)) { - return; - } - - /* Evaluate BSDF. */ - const bool is_transmission = shader_bsdf_is_transmission(sd, ls.D); + Ray ray ccl_optional_struct_init; BsdfEval bsdf_eval ccl_optional_struct_init; - const float bsdf_pdf = shader_bsdf_eval(kg, sd, ls.D, is_transmission, &bsdf_eval, ls.shader); - bsdf_eval_mul3(&bsdf_eval, light_eval / ls.pdf); + const bool is_transmission = shader_bsdf_is_transmission(sd, ls.D); - if (ls.shader & SHADER_USE_MIS) { - const float mis_weight = light_sample_mis_weight_nee(kg, ls.pdf, bsdf_pdf); - bsdf_eval_mul(&bsdf_eval, mis_weight); +# ifdef __MNEE__ + bool skip_nee = false; + IF_KERNEL_NODES_FEATURE(RAYTRACE) + { + if (ls.lamp != LAMP_NONE) { + /* Is this a caustic light? */ + const bool use_caustics = kernel_tex_fetch(__lights, ls.lamp).use_caustics; + if (use_caustics) { + /* Are we on a caustic caster? */ + if (is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_CASTER)) + return; + + /* Are we on a caustic receiver? */ + if (!is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_RECEIVER)) + skip_nee = kernel_path_mnee_sample( + kg, state, sd, emission_sd, rng_state, &ls, &bsdf_eval); + } + } + } + if (skip_nee) { + /* Create shadow ray after successful manifold walk: + * emission_sd contains the last interface intersection and + * the light sample ls has been updated */ + light_sample_to_surface_shadow_ray(kg, emission_sd, &ls, &ray); } + else +# endif /* __MNEE__ */ + { + const float3 light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, sd->time); + if (is_zero(light_eval)) { + return; + } - /* Path termination. */ - const float terminate = path_state_rng_light_termination(kg, rng_state); - if (light_sample_terminate(kg, &ls, &bsdf_eval, terminate)) { - return; + /* Evaluate BSDF. */ + const float bsdf_pdf = shader_bsdf_eval(kg, sd, ls.D, is_transmission, &bsdf_eval, ls.shader); + bsdf_eval_mul3(&bsdf_eval, light_eval / ls.pdf); + + if (ls.shader & SHADER_USE_MIS) { + const float mis_weight = light_sample_mis_weight_nee(kg, ls.pdf, bsdf_pdf); + bsdf_eval_mul(&bsdf_eval, mis_weight); + } + + /* Path termination. */ + const float terminate = path_state_rng_light_termination(kg, rng_state); + if (light_sample_terminate(kg, &ls, &bsdf_eval, terminate)) { + return; + } + + /* Create shadow ray. */ + light_sample_to_surface_shadow_ray(kg, sd, &ls, &ray); } - /* Create shadow ray. */ - Ray ray ccl_optional_struct_init; - light_sample_to_surface_shadow_ray(kg, sd, &ls, &ray); const bool is_light = light_sample_is_light(&ls); /* Branch off shadow kernel. */ @@ -224,6 +259,12 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg, if (kernel_data.kernel_features & KERNEL_FEATURE_SHADOW_PASS) { INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, unshadowed_throughput) = throughput; } + + /* Write Lightgroup, +1 as lightgroup is int but we need to encode into a uint8_t. */ + INTEGRATOR_STATE_WRITE( + shadow_state, shadow_path, lightgroup) = (ls.type != LIGHT_BACKGROUND) ? + ls.group + 1 : + kernel_data.background.lightgroup + 1; } #endif @@ -501,7 +542,7 @@ ccl_device bool integrate_surface(KernelGlobals kg, /* Direct light. */ PROFILING_EVENT(PROFILING_SHADE_SURFACE_DIRECT_LIGHT); - integrate_surface_direct_light(kg, state, &sd, &rng_state); + integrate_surface_direct_light<node_feature_mask>(kg, state, &sd, &rng_state); #if defined(__AO__) /* Ambient occlusion pass. */ diff --git a/intern/cycles/kernel/integrator/shade_volume.h b/intern/cycles/kernel/integrator/shade_volume.h index acda4b8e9d1..4a5015946aa 100644 --- a/intern/cycles/kernel/integrator/shade_volume.h +++ b/intern/cycles/kernel/integrator/shade_volume.h @@ -653,7 +653,8 @@ ccl_device_forceinline void volume_integrate_heterogeneous( /* Write accumulated emission. */ if (!is_zero(accum_emission)) { - kernel_accum_emission(kg, state, accum_emission, render_buffer); + kernel_accum_emission( + kg, state, accum_emission, render_buffer, object_lightgroup(kg, sd->object)); } # ifdef __DENOISING_FEATURES__ @@ -833,6 +834,12 @@ ccl_device_forceinline void integrate_volume_direct_light( INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, unshadowed_throughput) = throughput; } + /* Write Lightgroup, +1 as lightgroup is int but we need to encode into a uint8_t. */ + INTEGRATOR_STATE_WRITE( + shadow_state, shadow_path, lightgroup) = (ls->type != LIGHT_BACKGROUND) ? + ls->group + 1 : + kernel_data.background.lightgroup + 1; + integrator_state_copy_volume_stack_to_shadow(kg, shadow_state, state); } # endif diff --git a/intern/cycles/kernel/integrator/shader_eval.h b/intern/cycles/kernel/integrator/shader_eval.h index ce76f7a3a90..3066fb661a1 100644 --- a/intern/cycles/kernel/integrator/shader_eval.h +++ b/intern/cycles/kernel/integrator/shader_eval.h @@ -157,7 +157,11 @@ ccl_device_inline void shader_prepare_surface_closures(KernelGlobals kg, * * Blurring of bsdf after bounces, for rays that have a small likelihood * of following this particular path (diffuse, rough glossy) */ - if (kernel_data.integrator.filter_glossy != FLT_MAX) { + if (kernel_data.integrator.filter_glossy != FLT_MAX +#ifdef __MNEE__ + && !(INTEGRATOR_STATE(state, path, mnee) & PATH_MNEE_VALID) +#endif + ) { float blur_pdf = kernel_data.integrator.filter_glossy * INTEGRATOR_STATE(state, path, min_ray_pdf); @@ -605,7 +609,8 @@ ccl_device void shader_eval_surface(KernelGlobals kg, ConstIntegratorGenericState state, ccl_private ShaderData *ccl_restrict sd, ccl_global float *ccl_restrict buffer, - uint32_t path_flag) + uint32_t path_flag, + bool use_caustics_storage = false) { /* If path is being terminated, we are tracing a shadow ray or evaluating * emission, then we don't need to store closures. The emission and shadow @@ -615,7 +620,7 @@ ccl_device void shader_eval_surface(KernelGlobals kg, max_closures = 0; } else { - max_closures = kernel_data.max_closures; + max_closures = use_caustics_storage ? CAUSTICS_MAX_CLOSURE : kernel_data.max_closures; } sd->num_closure = 0; diff --git a/intern/cycles/kernel/integrator/shadow_state_template.h b/intern/cycles/kernel/integrator/shadow_state_template.h index 9308df53e46..eaee65ada40 100644 --- a/intern/cycles/kernel/integrator/shadow_state_template.h +++ b/intern/cycles/kernel/integrator/shadow_state_template.h @@ -38,6 +38,8 @@ KERNEL_STRUCT_MEMBER(shadow_path, packed_float3, pass_diffuse_weight, KERNEL_FEA KERNEL_STRUCT_MEMBER(shadow_path, packed_float3, pass_glossy_weight, KERNEL_FEATURE_LIGHT_PASSES) /* Number of intersections found by ray-tracing. */ KERNEL_STRUCT_MEMBER(shadow_path, uint16_t, num_hits, KERNEL_FEATURE_PATH_TRACING) +/* Light group. */ +KERNEL_STRUCT_MEMBER(shadow_path, uint8_t, lightgroup, KERNEL_FEATURE_PATH_TRACING) KERNEL_STRUCT_END(shadow_path) /********************************** Shadow Ray *******************************/ diff --git a/intern/cycles/kernel/integrator/state_template.h b/intern/cycles/kernel/integrator/state_template.h index 6eac38b1af9..e7e6db037b0 100644 --- a/intern/cycles/kernel/integrator/state_template.h +++ b/intern/cycles/kernel/integrator/state_template.h @@ -34,6 +34,8 @@ KERNEL_STRUCT_MEMBER(path, uint32_t, rng_hash, KERNEL_FEATURE_PATH_TRACING) KERNEL_STRUCT_MEMBER(path, uint16_t, rng_offset, KERNEL_FEATURE_PATH_TRACING) /* enum PathRayFlag */ KERNEL_STRUCT_MEMBER(path, uint32_t, flag, KERNEL_FEATURE_PATH_TRACING) +/* enum PathRayMNEE */ +KERNEL_STRUCT_MEMBER(path, uint8_t, mnee, KERNEL_FEATURE_PATH_TRACING) /* Multiple importance sampling * The PDF of BSDF sampling at the last scatter point, and distance to the * last scatter point minus the last ray segment. This distance lets us diff --git a/intern/cycles/kernel/integrator/subsurface.h b/intern/cycles/kernel/integrator/subsurface.h index fa468e337c7..2391cc2356d 100644 --- a/intern/cycles/kernel/integrator/subsurface.h +++ b/intern/cycles/kernel/integrator/subsurface.h @@ -171,7 +171,12 @@ ccl_device_inline bool subsurface_scatter(KernelGlobals kg, IntegratorState stat const int shader = intersection_get_shader(kg, &ss_isect.hits[0]); const int shader_flags = kernel_tex_fetch(__shaders, shader).flags; - if (shader_flags & SD_HAS_RAYTRACE) { + const int object_flags = intersection_get_object_flags(kg, &ss_isect.hits[0]); + const bool use_caustics = kernel_data.integrator.use_caustics && + (object_flags & SD_OBJECT_CAUSTICS); + const bool use_raytrace_kernel = (shader_flags & SD_HAS_RAYTRACE) || use_caustics; + + if (use_raytrace_kernel) { INTEGRATOR_PATH_NEXT_SORTED(DEVICE_KERNEL_INTEGRATOR_INTERSECT_SUBSURFACE, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE, shader); diff --git a/intern/cycles/kernel/light/light.h b/intern/cycles/kernel/light/light.h index b08b4ebc068..1df1615ed99 100644 --- a/intern/cycles/kernel/light/light.h +++ b/intern/cycles/kernel/light/light.h @@ -23,6 +23,7 @@ typedef struct LightSample { int prim; /* primitive id for triangle/curve lights */ int shader; /* shader id */ int lamp; /* lamp id */ + int group; /* lightgroup */ LightType type; /* type of light */ } LightSample; @@ -52,6 +53,7 @@ ccl_device_inline bool light_sample(KernelGlobals kg, ls->lamp = lamp; ls->u = randu; ls->v = randv; + ls->group = lamp_lightgroup(kg, lamp); if (in_volume_segment && (type == LIGHT_DISTANT || type == LIGHT_BACKGROUND)) { /* Distant lights in a volume get a dummy sample, position will not actually @@ -246,6 +248,15 @@ ccl_device bool lights_intersect(KernelGlobals kg, if (!(klight->shader_id & SHADER_USE_MIS)) { continue; } + +#ifdef __MNEE__ + /* This path should have been resolved with mnee, it will + * generate a firefly for small lights since it is improbable. */ + if ((INTEGRATOR_STATE(state, path, mnee) & PATH_MNEE_CULL_LIGHT_CONNECTION) && + klight->use_caustics) { + continue; + } +#endif } if (path_flag & PATH_RAY_SHADOW_CATCHER_PASS) { @@ -404,6 +415,7 @@ ccl_device bool light_sample_from_distant_ray(KernelGlobals kg, ls->P = -ray_D; ls->Ng = -ray_D; ls->D = ray_D; + ls->group = lamp_lightgroup(kg, lamp); /* compute pdf */ float invarea = klight->distant.invarea; @@ -432,13 +444,14 @@ ccl_device bool light_sample_from_intersection(KernelGlobals kg, ls->t = isect->t; ls->P = ray_P + ray_D * ls->t; ls->D = ray_D; + ls->group = lamp_lightgroup(kg, lamp); if (type == LIGHT_SPOT) { const float3 center = make_float3(klight->co[0], klight->co[1], klight->co[2]); const float3 dir = make_float3(klight->spot.dir[0], klight->spot.dir[1], klight->spot.dir[2]); /* the normal of the oriented disk */ const float3 lightN = normalize(ray_P - center); - /* we set the light normal to the outgoing direction to support texturing*/ + /* We set the light normal to the outgoing direction to support texturing. */ ls->Ng = -ls->D; float invarea = klight->spot.invarea; @@ -467,7 +480,7 @@ ccl_device bool light_sample_from_intersection(KernelGlobals kg, const float3 center = make_float3(klight->co[0], klight->co[1], klight->co[2]); const float3 lighN = normalize(ray_P - center); - /* we set the light normal to the outgoing direction to support texturing*/ + /* We set the light normal to the outgoing direction to support texturing. */ ls->Ng = -ls->D; float invarea = klight->spot.invarea; @@ -697,6 +710,7 @@ ccl_device_forceinline void triangle_light_sample(KernelGlobals kg, ls->lamp = LAMP_NONE; ls->shader |= SHADER_USE_MIS; ls->type = LIGHT_TRIANGLE; + ls->group = object_lightgroup(kg, object); float distance_to_plane = fabsf(dot(N0, V[0] - P) / dot(N0, N0)); diff --git a/intern/cycles/kernel/svm/closure.h b/intern/cycles/kernel/svm/closure.h index 68ddc2fa306..88b44cdbacf 100644 --- a/intern/cycles/kernel/svm/closure.h +++ b/intern/cycles/kernel/svm/closure.h @@ -395,8 +395,10 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, if (kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0) # endif { + /* This is to prevent mnee from receiving a null bsdf. */ + float refraction_fresnel = fmaxf(0.0001f, 1.0f - fresnel); ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( - sd, sizeof(MicrofacetBsdf), base_color * glass_weight * (1.0f - fresnel)); + sd, sizeof(MicrofacetBsdf), base_color * glass_weight * refraction_fresnel); if (bsdf) { bsdf->N = N; bsdf->T = make_float3(0.0f, 0.0f, 0.0f); @@ -674,8 +676,10 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, if (kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0) #endif { + /* This is to prevent mnee from receiving a null bsdf. */ + float refraction_fresnel = fmaxf(0.0001f, 1.0f - fresnel); ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( - sd, sizeof(MicrofacetBsdf), weight * (1.0f - fresnel)); + sd, sizeof(MicrofacetBsdf), weight * refraction_fresnel); if (bsdf) { bsdf->N = N; diff --git a/intern/cycles/kernel/svm/sky.h b/intern/cycles/kernel/svm/sky.h index 632a866830b..a72d4dd3ba7 100644 --- a/intern/cycles/kernel/svm/sky.h +++ b/intern/cycles/kernel/svm/sky.h @@ -113,24 +113,25 @@ ccl_device float3 sky_radiance_hosek(KernelGlobals kg, /* Nishita improved sky model */ ccl_device float3 geographical_to_direction(float lat, float lon) { - return make_float3(cos(lat) * cos(lon), cos(lat) * sin(lon), sin(lat)); + return make_float3(cosf(lat) * cosf(lon), cosf(lat) * sinf(lon), sinf(lat)); } ccl_device float3 sky_radiance_nishita(KernelGlobals kg, float3 dir, + float3 pixel_bottom, + float3 pixel_top, ccl_private float *nishita_data, uint texture_id) { /* definitions */ - float sun_elevation = nishita_data[6]; - float sun_rotation = nishita_data[7]; - float angular_diameter = nishita_data[8]; - float sun_intensity = nishita_data[9]; + float sun_elevation = nishita_data[0]; + float sun_rotation = nishita_data[1]; + float angular_diameter = nishita_data[2]; + float sun_intensity = nishita_data[3]; bool sun_disc = (angular_diameter >= 0.0f); float3 xyz; /* convert dir to spherical coordinates */ float2 direction = direction_to_spherical(dir); - /* render above the horizon */ if (dir.z >= 0.0f) { /* definitions */ @@ -142,8 +143,6 @@ ccl_device float3 sky_radiance_nishita(KernelGlobals kg, /* if ray inside sun disc render it, otherwise render sky */ if (sun_disc && sun_dir_angle < half_angular) { /* get 2 pixels data */ - float3 pixel_bottom = make_float3(nishita_data[0], nishita_data[1], nishita_data[2]); - float3 pixel_top = make_float3(nishita_data[3], nishita_data[4], nishita_data[5]); float y; /* sun interpolation */ @@ -292,27 +291,26 @@ ccl_device_noinline int svm_node_tex_sky( /* Nishita */ else { /* Define variables */ - float nishita_data[10]; + float nishita_data[4]; float4 data = read_node_float(kg, &offset); - nishita_data[0] = data.x; - nishita_data[1] = data.y; - nishita_data[2] = data.z; - nishita_data[3] = data.w; + float3 pixel_bottom = make_float3(data.x, data.y, data.z); + float3 pixel_top; + pixel_top.x = data.w; data = read_node_float(kg, &offset); - nishita_data[4] = data.x; - nishita_data[5] = data.y; - nishita_data[6] = data.z; - nishita_data[7] = data.w; + pixel_top.y = data.x; + pixel_top.z = data.y; + nishita_data[0] = data.z; + nishita_data[1] = data.w; data = read_node_float(kg, &offset); - nishita_data[8] = data.x; - nishita_data[9] = data.y; + nishita_data[2] = data.x; + nishita_data[3] = data.y; uint texture_id = __float_as_uint(data.z); /* Compute Sky */ - f = sky_radiance_nishita(kg, dir, nishita_data, texture_id); + f = sky_radiance_nishita(kg, dir, pixel_bottom, pixel_top, nishita_data, texture_id); } stack_store_float3(stack, out_offset, f); diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h index 07d4a95780b..9d9daaa0dda 100644 --- a/intern/cycles/kernel/types.h +++ b/intern/cycles/kernel/types.h @@ -46,6 +46,7 @@ CCL_NAMESPACE_BEGIN #define LAMP_NONE (~0) #define ID_NONE (0.0f) #define PASS_UNUSED (~0) +#define LIGHTGROUP_NONE (~0) #define INTEGRATOR_SHADOW_ISECT_SIZE_CPU 1024U #define INTEGRATOR_SHADOW_ISECT_SIZE_GPU 4U @@ -102,6 +103,12 @@ CCL_NAMESPACE_BEGIN # undef __BAKING__ #endif /* __KERNEL_GPU_RAYTRACING__ */ +/* MNEE currently causes "Compute function exceeds available temporary registers" + * on Metal, disabled for now. */ +#ifndef __KERNEL_METAL__ +# define __MNEE__ +#endif + /* Scene-based selective features compilation. */ #ifdef __KERNEL_FEATURES__ # if !(__KERNEL_FEATURES & KERNEL_FEATURE_CAMERA_MOTION) @@ -293,6 +300,13 @@ enum PathRayFlag : uint32_t { PATH_RAY_SHADOW_CATCHER_BACKGROUND = (1U << 31U), }; +// 8bit enum, just in case we need to move more variables in it +enum PathRayMNEE { + PATH_MNEE_VALID = (1U << 0U), + PATH_MNEE_RECEIVER_ANCESTOR = (1U << 1U), + PATH_MNEE_CULL_LIGHT_CONNECTION = (1U << 2U), +}; + /* Configure ray visibility bits for rays and objects respectively, * to make shadow catchers work. * @@ -649,6 +663,17 @@ typedef struct AttributeDescriptor { # define MAX_CLOSURE __MAX_CLOSURE__ #endif +/* For manifold next event estimation, we need space to store and evaluate + * 2 closures (with extra data) on the refractive interfaces, in addition + * to keeping the full sd at the current shading point. We need 4 because a + * refractive bsdf is instanced with a companion reflection bsdf, even though + * we only need the refractive one, and each of them requires 2 slots. */ +#ifndef __CAUSTICS_MAX_CLOSURE__ +# define CAUSTICS_MAX_CLOSURE 4 +#else +# define CAUSTICS_MAX_CLOSURE __CAUSTICS_MAX_CLOSURE__ +#endif + #ifndef __MAX_VOLUME_STACK_SIZE__ # define MAX_VOLUME_STACK_SIZE 32 #else @@ -779,11 +804,18 @@ enum ShaderDataObjectFlag { SD_OBJECT_SHADOW_CATCHER = (1 << 7), /* object has volume attributes */ SD_OBJECT_HAS_VOLUME_ATTRIBUTES = (1 << 8), + /* object is caustics caster */ + SD_OBJECT_CAUSTICS_CASTER = (1 << 9), + /* object is caustics receiver */ + SD_OBJECT_CAUSTICS_RECEIVER = (1 << 10), + + /* object is using caustics */ + SD_OBJECT_CAUSTICS = (SD_OBJECT_CAUSTICS_CASTER | SD_OBJECT_CAUSTICS_RECEIVER), SD_OBJECT_FLAGS = (SD_OBJECT_HOLDOUT_MASK | SD_OBJECT_MOTION | SD_OBJECT_TRANSFORM_APPLIED | SD_OBJECT_NEGATIVE_SCALE_APPLIED | SD_OBJECT_HAS_VOLUME | SD_OBJECT_INTERSECTS_VOLUME | SD_OBJECT_SHADOW_CATCHER | - SD_OBJECT_HAS_VOLUME_ATTRIBUTES) + SD_OBJECT_HAS_VOLUME_ATTRIBUTES | SD_OBJECT_CAUSTICS) }; typedef struct ccl_align(16) ShaderData @@ -882,6 +914,15 @@ typedef struct ccl_align(16) ShaderDataTinyStorage char pad[sizeof(ShaderData) - sizeof(ShaderClosure) * MAX_CLOSURE]; } ShaderDataTinyStorage; + +/* ShaderDataCausticsStorage needs the same alignment as ShaderData, or else + * the pointer cast in AS_SHADER_DATA invokes undefined behavior. */ +typedef struct ccl_align(16) ShaderDataCausticsStorage +{ + char pad[sizeof(ShaderData) - sizeof(ShaderClosure) * (MAX_CLOSURE - CAUSTICS_MAX_CLOSURE)]; +} +ShaderDataCausticsStorage; + #define AS_SHADER_DATA(shader_data_tiny_storage) \ ((ccl_private ShaderData *)shader_data_tiny_storage) @@ -1068,6 +1109,7 @@ typedef struct KernelFilm { int pass_aov_color; int pass_aov_value; + int pass_lightgroup; /* XYZ to rendering color space transform. float4 instead of float3 to * ensure consistent padding/alignment across devices. */ @@ -1152,8 +1194,10 @@ typedef struct KernelBackground { int use_mis; + int lightgroup; + /* Padding */ - int pad1, pad2, pad3; + int pad1, pad2; } KernelBackground; static_assert_align(KernelBackground, 16); @@ -1201,6 +1245,9 @@ typedef struct KernelIntegrator { /* mis */ int use_lamp_mis; + /* caustics */ + int use_caustics; + /* sampler */ int sampling_pattern; @@ -1219,7 +1266,7 @@ typedef struct KernelIntegrator { int direct_light_sampling_type; /* padding */ - int pad1, pad2; + int pad1; } KernelIntegrator; static_assert_align(KernelIntegrator, 16); @@ -1329,9 +1376,12 @@ typedef struct KernelObject { float ao_distance; + int lightgroup; + uint visibility; int primitive_type; - int pad[2]; + + int pad1; } KernelObject; static_assert_align(KernelObject, 16); @@ -1383,7 +1433,8 @@ typedef struct KernelLight { float max_bounces; float random; float strength[3]; - float pad1, pad2; + int use_caustics; + int lightgroup; Transform tfm; Transform itfm; union { diff --git a/intern/cycles/scene/background.cpp b/intern/cycles/scene/background.cpp index 1c3a9f9358d..bffc8895bfd 100644 --- a/intern/cycles/scene/background.cpp +++ b/intern/cycles/scene/background.cpp @@ -32,6 +32,8 @@ NODE_DEFINE(Background) SOCKET_NODE(shader, "Shader", Shader::get_node_type()); + SOCKET_STRING(lightgroup, "Light Group", ustring()); + return type; } @@ -101,6 +103,15 @@ void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene kbackground->surface_shader |= SHADER_EXCLUDE_CAMERA; } + /* Light group. */ + auto it = scene->lightgroups.find(lightgroup); + if (it != scene->lightgroups.end()) { + kbackground->lightgroup = it->second; + } + else { + kbackground->lightgroup = LIGHTGROUP_NONE; + } + clear_modified(); } diff --git a/intern/cycles/scene/background.h b/intern/cycles/scene/background.h index bbffce6e30a..50b4368d708 100644 --- a/intern/cycles/scene/background.h +++ b/intern/cycles/scene/background.h @@ -30,6 +30,8 @@ class Background : public Node { NODE_SOCKET_API(float, volume_step_size) + NODE_SOCKET_API(ustring, lightgroup) + Background(); ~Background(); diff --git a/intern/cycles/scene/film.cpp b/intern/cycles/scene/film.cpp index e17c839d60b..c3b126544c4 100644 --- a/intern/cycles/scene/film.cpp +++ b/intern/cycles/scene/film.cpp @@ -175,6 +175,7 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) kfilm->pass_volume_direct = PASS_UNUSED; kfilm->pass_volume_indirect = PASS_UNUSED; kfilm->pass_shadow = PASS_UNUSED; + kfilm->pass_lightgroup = PASS_UNUSED; /* Mark passes as unused so that the kernel knows the pass is inaccessible. */ kfilm->pass_denoising_normal = PASS_UNUSED; @@ -189,6 +190,7 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) bool have_cryptomatte = false; bool have_aov_color = false; bool have_aov_value = false; + bool have_lightgroup = false; for (size_t i = 0; i < scene->passes.size(); i++) { const Pass *pass = scene->passes[i]; @@ -223,6 +225,15 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) assert(pass->get_type() <= PASS_CATEGORY_BAKE_END); } + if (pass->get_lightgroup() != ustring()) { + if (!have_lightgroup) { + kfilm->pass_lightgroup = kfilm->pass_stride; + have_lightgroup = true; + } + kfilm->pass_stride += pass->get_info().num_components; + continue; + } + switch (pass->get_type()) { case PASS_COMBINED: kfilm->pass_combined = kfilm->pass_stride; @@ -414,6 +425,26 @@ int Film::get_aov_offset(Scene *scene, string name, bool &is_color) return -1; } +bool Film::update_lightgroups(Scene *scene) +{ + map<ustring, int> lightgroups; + int i = 0; + foreach (const Pass *pass, scene->passes) { + ustring lightgroup = pass->get_lightgroup(); + if (!lightgroup.empty()) { + if (!lightgroups.count(lightgroup)) { + lightgroups[lightgroup] = i++; + } + } + } + if (scene->lightgroups != lightgroups) { + scene->lightgroups = lightgroups; + return true; + } + + return false; +} + void Film::update_passes(Scene *scene, bool add_sample_count_pass) { const Background *background = scene->background; @@ -580,11 +611,19 @@ void Film::remove_auto_passes(Scene *scene) static bool compare_pass_order(const Pass *a, const Pass *b) { + /* On the highest level, sort by number of components. + * Within passes of the same component count, sort so that all non-lightgroup passes come first. + * Within that group, sort by type. */ const int num_components_a = a->get_info().num_components; const int num_components_b = b->get_info().num_components; if (num_components_a == num_components_b) { - return (a->get_type() < b->get_type()); + const int is_lightgroup_a = !a->get_lightgroup().empty(); + const int is_lightgroup_b = !b->get_lightgroup().empty(); + if (is_lightgroup_a == is_lightgroup_b) { + return (a->get_type() < b->get_type()); + } + return is_lightgroup_b; } return num_components_a > num_components_b; diff --git a/intern/cycles/scene/film.h b/intern/cycles/scene/film.h index 43597b0fc79..f1e3237eb9e 100644 --- a/intern/cycles/scene/film.h +++ b/intern/cycles/scene/film.h @@ -68,6 +68,8 @@ class Film : public Node { int get_aov_offset(Scene *scene, string name, bool &is_color); + bool update_lightgroups(Scene *scene); + /* Update passes so that they contain all passes required for the configured functionality. * * If `add_sample_count_pass` is true then the SAMPLE_COUNT pass is ensured to be added. */ diff --git a/intern/cycles/scene/light.cpp b/intern/cycles/scene/light.cpp index 68779a3ce02..5e311d3051f 100644 --- a/intern/cycles/scene/light.cpp +++ b/intern/cycles/scene/light.cpp @@ -123,6 +123,7 @@ NODE_DEFINE(Light) SOCKET_BOOLEAN(use_glossy, "Use Glossy", true); SOCKET_BOOLEAN(use_transmission, "Use Transmission", true); SOCKET_BOOLEAN(use_scatter, "Use Scatter", true); + SOCKET_BOOLEAN(use_caustics, "Shadow Caustics", false); SOCKET_INT(max_bounces, "Max Bounces", 1024); SOCKET_UINT(random_id, "Random ID", 0); @@ -133,6 +134,8 @@ NODE_DEFINE(Light) SOCKET_NODE(shader, "Shader", Shader::get_node_type()); + SOCKET_STRING(lightgroup, "Light Group", ustring()); + return type; } @@ -896,10 +899,19 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc klights[light_index].max_bounces = max_bounces; klights[light_index].random = random; + klights[light_index].use_caustics = light->use_caustics; klights[light_index].tfm = light->tfm; klights[light_index].itfm = transform_inverse(light->tfm); + auto it = scene->lightgroups.find(light->lightgroup); + if (it != scene->lightgroups.end()) { + klights[light_index].lightgroup = it->second; + } + else { + klights[light_index].lightgroup = LIGHTGROUP_NONE; + } + light_index++; } diff --git a/intern/cycles/scene/light.h b/intern/cycles/scene/light.h index 3519b76cf51..5b852f210fc 100644 --- a/intern/cycles/scene/light.h +++ b/intern/cycles/scene/light.h @@ -61,6 +61,7 @@ class Light : public Node { NODE_SOCKET_API(bool, use_glossy) NODE_SOCKET_API(bool, use_transmission) NODE_SOCKET_API(bool, use_scatter) + NODE_SOCKET_API(bool, use_caustics) NODE_SOCKET_API(bool, is_shadow_catcher) NODE_SOCKET_API(bool, is_portal) @@ -70,6 +71,8 @@ class Light : public Node { NODE_SOCKET_API(int, max_bounces) NODE_SOCKET_API(uint, random_id) + NODE_SOCKET_API(ustring, lightgroup) + void tag_update(Scene *scene); /* Check whether the light has contribution the scene. */ diff --git a/intern/cycles/scene/object.cpp b/intern/cycles/scene/object.cpp index fda9a211e60..55d89fc3673 100644 --- a/intern/cycles/scene/object.cpp +++ b/intern/cycles/scene/object.cpp @@ -90,11 +90,16 @@ NODE_DEFINE(Object) SOCKET_BOOLEAN(is_shadow_catcher, "Shadow Catcher", false); + SOCKET_BOOLEAN(is_caustics_caster, "Cast Shadow Caustics", false); + SOCKET_BOOLEAN(is_caustics_receiver, "Receive Shadow Caustics", false); + 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); + SOCKET_STRING(lightgroup, "Light Group", ustring()); + return type; } @@ -390,7 +395,8 @@ static float object_volume_density(const Transform &tfm, Geometry *geom) void ObjectManager::device_update_object_transform(UpdateObjectTransformState *state, Object *ob, - bool update_all) + bool update_all, + const Scene *scene) { KernelObject &kobject = state->objects[ob->index]; Transform *object_motion_pass = state->object_motion_pass; @@ -510,6 +516,14 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s kobject.visibility = ob->visibility_for_tracing(); kobject.primitive_type = geom->primitive_type(); + /* Object shadow caustics flag */ + if (ob->is_caustics_caster) { + flag |= SD_OBJECT_CAUSTICS_CASTER; + } + if (ob->is_caustics_receiver) { + flag |= SD_OBJECT_CAUSTICS_RECEIVER; + } + /* Object flag. */ if (ob->use_holdout) { flag |= SD_OBJECT_HOLDOUT_MASK; @@ -521,6 +535,15 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s if (geom->geometry_type == Geometry::HAIR) { state->have_curves = true; } + + /* Light group. */ + auto it = scene->lightgroups.find(ob->lightgroup); + if (it != scene->lightgroups.end()) { + kobject.lightgroup = it->second; + } + else { + kobject.lightgroup = LIGHTGROUP_NONE; + } } void ObjectManager::device_update_prim_offsets(Device *device, DeviceScene *dscene, Scene *scene) @@ -607,7 +630,7 @@ void ObjectManager::device_update_transforms(DeviceScene *dscene, Scene *scene, [&](const blocked_range<size_t> &r) { for (size_t i = r.begin(); i != r.end(); i++) { Object *ob = state.scene->objects[i]; - device_update_object_transform(&state, ob, update_all); + device_update_object_transform(&state, ob, update_all, scene); } }); diff --git a/intern/cycles/scene/object.h b/intern/cycles/scene/object.h index 55689ccfa58..c41f1416180 100644 --- a/intern/cycles/scene/object.h +++ b/intern/cycles/scene/object.h @@ -55,6 +55,9 @@ class Object : public Node { NODE_SOCKET_API(float, shadow_terminator_shading_offset) NODE_SOCKET_API(float, shadow_terminator_geometry_offset) + NODE_SOCKET_API(bool, is_caustics_caster) + NODE_SOCKET_API(bool, is_caustics_receiver) + NODE_SOCKET_API(float3, dupli_generated) NODE_SOCKET_API(float2, dupli_uv) @@ -63,6 +66,8 @@ class Object : public Node { NODE_SOCKET_API(float, ao_distance) + NODE_SOCKET_API(ustring, lightgroup) + /* Set during device update. */ bool intersects_volume; @@ -166,7 +171,8 @@ class ObjectManager { protected: void device_update_object_transform(UpdateObjectTransformState *state, Object *ob, - bool update_all); + bool update_all, + const Scene *scene); void device_update_object_transform_task(UpdateObjectTransformState *state); bool device_update_object_transform_pop_work(UpdateObjectTransformState *state, int *start_index, diff --git a/intern/cycles/scene/pass.cpp b/intern/cycles/scene/pass.cpp index 41730cb189d..5f5b19e710d 100644 --- a/intern/cycles/scene/pass.cpp +++ b/intern/cycles/scene/pass.cpp @@ -124,6 +124,7 @@ NODE_DEFINE(Pass) SOCKET_ENUM(mode, "Mode", *pass_mode_enum, static_cast<int>(PassMode::DENOISED)); SOCKET_STRING(name, "Name", ustring()); SOCKET_BOOLEAN(include_albedo, "Include Albedo", false); + SOCKET_STRING(lightgroup, "Light Group", ustring()); return type; } @@ -134,7 +135,7 @@ Pass::Pass() : Node(get_node_type()), is_auto_(false) PassInfo Pass::get_info() const { - return get_info(type, include_albedo); + return get_info(type, include_albedo, !lightgroup.empty()); } bool Pass::is_written() const @@ -142,7 +143,7 @@ bool Pass::is_written() const return get_info().is_written; } -PassInfo Pass::get_info(const PassType type, const bool include_albedo) +PassInfo Pass::get_info(const PassType type, const bool include_albedo, const bool is_lightgroup) { PassInfo pass_info; @@ -157,9 +158,9 @@ PassInfo Pass::get_info(const PassType type, const bool include_albedo) pass_info.num_components = 0; break; case PASS_COMBINED: - pass_info.num_components = 4; + pass_info.num_components = is_lightgroup ? 3 : 4; pass_info.use_exposure = true; - pass_info.support_denoise = true; + pass_info.support_denoise = !is_lightgroup; break; case PASS_DEPTH: pass_info.num_components = 1; @@ -369,13 +370,16 @@ const Pass *Pass::find(const vector<Pass *> &passes, const string &name) return nullptr; } -const Pass *Pass::find(const vector<Pass *> &passes, PassType type, PassMode mode) +const Pass *Pass::find(const vector<Pass *> &passes, + PassType type, + PassMode mode, + const ustring &lightgroup) { for (const Pass *pass : passes) { - if (pass->get_type() != type || pass->get_mode() != mode) { + if (pass->get_type() != type || pass->get_mode() != mode || + pass->get_lightgroup() != lightgroup) { continue; } - return pass; } diff --git a/intern/cycles/scene/pass.h b/intern/cycles/scene/pass.h index c12df007b5d..e0689eba688 100644 --- a/intern/cycles/scene/pass.h +++ b/intern/cycles/scene/pass.h @@ -53,6 +53,7 @@ class Pass : public Node { NODE_SOCKET_API(PassMode, mode) NODE_SOCKET_API(ustring, name) NODE_SOCKET_API(bool, include_albedo) + NODE_SOCKET_API(ustring, lightgroup) Pass(); @@ -72,7 +73,9 @@ class Pass : public Node { static const NodeEnum *get_type_enum(); static const NodeEnum *get_mode_enum(); - static PassInfo get_info(PassType type, const bool include_albedo = false); + static PassInfo get_info(PassType type, + const bool include_albedo = false, + const bool is_lightgroup = false); static bool contains(const vector<Pass *> &passes, PassType type); @@ -80,7 +83,8 @@ class Pass : public Node { static const Pass *find(const vector<Pass *> &passes, const string &name); static const Pass *find(const vector<Pass *> &passes, PassType type, - PassMode mode = PassMode::NOISY); + PassMode mode = PassMode::NOISY, + const ustring &lightgroup = ustring()); /* Returns PASS_UNUSED if there is no corresponding pass. */ static int get_offset(const vector<Pass *> &passes, const Pass *pass); diff --git a/intern/cycles/scene/scene.cpp b/intern/cycles/scene/scene.cpp index 2199b2351d0..b6b53004816 100644 --- a/intern/cycles/scene/scene.cpp +++ b/intern/cycles/scene/scene.cpp @@ -251,6 +251,11 @@ void Scene::device_update(Device *device_, Progress &progress) * - Lookup tables are done a second time to handle film tables */ + if (film->update_lightgroups(this)) { + light_manager->tag_update(this, ccl::LightManager::LIGHT_MODIFIED); + object_manager->tag_update(this, ccl::ObjectManager::OBJECT_MODIFIED); + } + progress.set_status("Updating Shaders"); shader_manager->device_update(device, &dscene, this, progress); @@ -489,7 +494,21 @@ void Scene::update_kernel_features() if (use_motion && camera->use_motion()) { kernel_features |= KERNEL_FEATURE_CAMERA_MOTION; } + + /* Figure out whether the scene will use shader raytrace we need at least + * one caustic light, one caustic caster and one caustic receiver to use + * and enable the mnee code path. */ + bool has_caustics_receiver = false; + bool has_caustics_caster = false; + bool has_caustics_light = false; + foreach (Object *object, objects) { + if (object->get_is_caustics_caster()) { + has_caustics_caster = true; + } + else if (object->get_is_caustics_receiver()) { + has_caustics_receiver = true; + } Geometry *geom = object->get_geometry(); if (use_motion) { if (object->use_motion() || geom->get_use_motion_blur()) { @@ -518,6 +537,18 @@ void Scene::update_kernel_features() } } + foreach (Light *light, lights) { + if (light->get_use_caustics()) { + has_caustics_light = true; + } + } + + dscene.data.integrator.use_caustics = false; + if (has_caustics_caster && has_caustics_receiver && has_caustics_light) { + dscene.data.integrator.use_caustics = true; + kernel_features |= KERNEL_FEATURE_NODE_RAYTRACE; + } + if (bake_manager->get_baking()) { kernel_features |= KERNEL_FEATURE_BAKING; } diff --git a/intern/cycles/scene/scene.h b/intern/cycles/scene/scene.h index e1b36899302..9e3e8d61b80 100644 --- a/intern/cycles/scene/scene.h +++ b/intern/cycles/scene/scene.h @@ -197,6 +197,9 @@ class Scene : public NodeOwner { /* Optional name. Is used for logging and reporting. */ string name; + /* Maps from Light group names to their pass ID. */ + map<ustring, int> lightgroups; + /* data */ BVH *bvh; Camera *camera; diff --git a/intern/cycles/session/buffers.cpp b/intern/cycles/session/buffers.cpp index f9893ed1e1c..3bbc205ca7a 100644 --- a/intern/cycles/session/buffers.cpp +++ b/intern/cycles/session/buffers.cpp @@ -49,6 +49,7 @@ NODE_DEFINE(BufferPass) SOCKET_ENUM(mode, "Mode", *pass_mode_enum, static_cast<int>(PassMode::DENOISED)); SOCKET_STRING(name, "Name", ustring()); SOCKET_BOOLEAN(include_albedo, "Include Albedo", false); + SOCKET_STRING(lightgroup, "Light Group", ustring()); SOCKET_INT(offset, "Offset", -1); @@ -64,13 +65,14 @@ BufferPass::BufferPass(const Pass *scene_pass) type(scene_pass->get_type()), mode(scene_pass->get_mode()), name(scene_pass->get_name()), - include_albedo(scene_pass->get_include_albedo()) + include_albedo(scene_pass->get_include_albedo()), + lightgroup(scene_pass->get_lightgroup()) { } PassInfo BufferPass::get_info() const { - return Pass::get_info(type, include_albedo); + return Pass::get_info(type, include_albedo, !lightgroup.empty()); } /* -------------------------------------------------------------------- diff --git a/intern/cycles/session/buffers.h b/intern/cycles/session/buffers.h index 1c4ec81e427..a8278388a28 100644 --- a/intern/cycles/session/buffers.h +++ b/intern/cycles/session/buffers.h @@ -30,6 +30,7 @@ class BufferPass : public Node { PassMode mode = PassMode::NOISY; ustring name; bool include_albedo = false; + ustring lightgroup; int offset = -1; @@ -49,7 +50,8 @@ class BufferPass : public Node { inline bool operator==(const BufferPass &other) const { return type == other.type && mode == other.mode && name == other.name && - include_albedo == other.include_albedo && offset == other.offset; + include_albedo == other.include_albedo && lightgroup == other.lightgroup && + offset == other.offset; } inline bool operator!=(const BufferPass &other) const { diff --git a/intern/cycles/util/debug.h b/intern/cycles/util/debug.h index 23a055cf52f..3565fdea17f 100644 --- a/intern/cycles/util/debug.h +++ b/intern/cycles/util/debug.h @@ -87,7 +87,7 @@ class DebugFlags { /* Reset flags to their defaults. */ void reset(); - /* Whether adaptive feature based runtime compile is enabled or not.*/ + /* Whether adaptive feature based runtime compile is enabled or not. */ bool adaptive_compile; }; @@ -110,7 +110,7 @@ class DebugFlags { /* Reset flags to their defaults. */ void reset(); - /* Whether adaptive feature based runtime compile is enabled or not.*/ + /* Whether adaptive feature based runtime compile is enabled or not. */ bool adaptive_compile; }; diff --git a/intern/cycles/util/math_float2.h b/intern/cycles/util/math_float2.h index d6b47052720..542dad93467 100644 --- a/intern/cycles/util/math_float2.h +++ b/intern/cycles/util/math_float2.h @@ -40,7 +40,7 @@ ccl_device_inline float average(const float2 &a); ccl_device_inline float distance(const float2 &a, const float2 &b); ccl_device_inline float dot(const float2 &a, const float2 &b); ccl_device_inline float cross(const float2 &a, const float2 &b); -ccl_device_inline float len(const float2 &a); +ccl_device_inline float len(const float2 a); ccl_device_inline float2 normalize(const float2 &a); ccl_device_inline float2 normalize_len(const float2 &a, float *t); ccl_device_inline float2 safe_normalize(const float2 &a); @@ -187,11 +187,6 @@ ccl_device_inline float cross(const float2 &a, const float2 &b) return (a.x * b.y - a.y * b.x); } -ccl_device_inline float len(const float2 &a) -{ - return sqrtf(dot(a, a)); -} - ccl_device_inline float2 normalize(const float2 &a) { return a / len(a); @@ -251,6 +246,11 @@ ccl_device_inline float2 floor(const float2 &a) #endif /* !__KERNEL_METAL__ */ +ccl_device_inline float len(const float2 a) +{ + return sqrtf(dot(a, a)); +} + ccl_device_inline float2 safe_divide_float2_float(const float2 a, const float b) { return (b != 0.0f) ? a / b : zero_float2(); diff --git a/intern/cycles/util/texture.h b/intern/cycles/util/texture.h index 33ff349704b..e8bb058a3c9 100644 --- a/intern/cycles/util/texture.h +++ b/intern/cycles/util/texture.h @@ -15,7 +15,7 @@ CCL_NAMESPACE_BEGIN #define TEX_IMAGE_MISSING_A 1 /* Interpolation types for textures - * cuda also use texture space to store other objects */ + * CUDA also use texture space to store other objects. */ typedef enum InterpolationType { INTERPOLATION_NONE = -1, INTERPOLATION_LINEAR = 0, diff --git a/intern/ghost/intern/GHOST_WindowViewCocoa.h b/intern/ghost/intern/GHOST_WindowViewCocoa.h index 635c0052a3a..58c029620da 100644 --- a/intern/ghost/intern/GHOST_WindowViewCocoa.h +++ b/intern/ghost/intern/GHOST_WindowViewCocoa.h @@ -64,7 +64,7 @@ ime.event.target_end = -1; /* Register a function to be executed when Input Method is changed using - * 'Control + Space' or language-specific keys (such as 'Eisu / Kana' key for Japanese).*/ + * 'Control + Space' or language-specific keys (such as 'Eisu / Kana' key for Japanese). */ NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; [center addObserver:self selector:@selector(ImeDidChangeCallback:) diff --git a/intern/rigidbody/RBI_api.h b/intern/rigidbody/RBI_api.h index 4065240a704..791a4a6ac05 100644 --- a/intern/rigidbody/RBI_api.h +++ b/intern/rigidbody/RBI_api.h @@ -246,8 +246,8 @@ void RB_shape_trimesh_update(rbCollisionShape *shape, float *vertices, int num_verts, int vert_stride, - float min[3], - float max[3]); + const float min[3], + const float max[3]); /* ********************************** */ /* Constraints */ diff --git a/intern/rigidbody/rb_bullet_api.cpp b/intern/rigidbody/rb_bullet_api.cpp index 88b146384e1..ac8026be41b 100644 --- a/intern/rigidbody/rb_bullet_api.cpp +++ b/intern/rigidbody/rb_bullet_api.cpp @@ -802,8 +802,8 @@ void RB_shape_trimesh_update(rbCollisionShape *shape, float *vertices, int num_verts, int vert_stride, - float min[3], - float max[3]) + const float min[3], + const float max[3]) { if (shape->mesh == NULL || num_verts != shape->mesh->num_vertices) { return; diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg index 6de808a9386..6f0216176d7 100644 --- a/release/datafiles/blender_icons.svg +++ b/release/datafiles/blender_icons.svg @@ -7719,7 +7719,7 @@ <g style="display:inline;fill:#ffffff;enable-background:new" id="g13475" - transform="translate(-20)"> + transform="translate(-21)"> <path sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccccccc" mask="none" @@ -7741,7 +7741,7 @@ </g> <g style="display:inline;fill:#ffffff;enable-background:new" - transform="matrix(-1,0,0,1,90,-231)" + transform="matrix(-1,0,0,1,89,-231)" id="g12197"> <path inkscape:connector-curvature="0" @@ -8569,7 +8569,7 @@ <g style="display:inline;fill:#ffffff;enable-background:new" id="g12259" - transform="matrix(0,-1,-1,0,313,-85.999995)" + transform="matrix(0,-1,-1,0,312,-85.999995)" inkscape:export-filename="blender_icons.png" inkscape:export-xdpi="96" inkscape:export-ydpi="96"> @@ -8823,7 +8823,7 @@ <g style="display:inline;fill:#ffffff;enable-background:new" id="g12761" - transform="translate(72.999998)" + transform="translate(71.999998)" inkscape:export-filename="blender_icons.png" inkscape:export-xdpi="96" inkscape:export-ydpi="96"> @@ -10405,7 +10405,7 @@ sodipodi:nodetypes="sssss" /> </g> <g - transform="translate(0.97000661)" + transform="translate(-0.02999339)" style="display:inline;fill:#ffffff;enable-background:new" id="g14346"> <path @@ -10995,7 +10995,7 @@ inkscape:connector-curvature="0" /> <g style="display:inline;fill:#ffffff;enable-background:new" - transform="translate(-188,168)" + transform="translate(-189,168)" id="g21028"> <path inkscape:connector-curvature="0" @@ -11064,7 +11064,7 @@ <g style="display:inline;fill:#ffffff;enable-background:new" id="g19653" - transform="translate(-626.99987,42.000005)"> + transform="translate(-627.99987,42.000005)"> <path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 143.13867,515.0332 c -0.49613,-0.0451 -1.03862,0.15972 -1.49219,0.61328 l -1.75,1.75 c -0.19519,0.19527 -0.19519,0.51177 0,0.70704 l 3,3 c 0.19527,0.19519 0.51177,0.19519 0.70704,0 l 1.75,-1.75 c 0.45356,-0.45357 0.65838,-0.99606 0.61328,-1.49219 -0.0451,-0.49613 -0.30436,-0.90592 -0.61328,-1.21485 l -1,-1 c -0.30893,-0.30892 -0.71872,-0.56817 -1.21485,-0.61328 z m -4.39648,3.7168 a 0.50005,0.50005 0 0 0 -0.34571,0.14648 l -0.25,0.25 a 0.50005,0.50005 0 0 0 0,0.70704 l 3,3 a 0.50005,0.50005 0 0 0 0.70704,0 l 0.25,-0.25 a 0.50005,0.50005 0 0 0 0,-0.70704 l -3,-3 A 0.50005,0.50005 0 0 0 138.74219,518.75 Z m -1.25196,2.24609 a 0.50005,0.50005 0 0 0 -0.34375,0.15039 l -4.25,4.25 c -0.83838,0.83839 -1.06879,1.7573 -0.80273,2.4668 C 132.35981,528.57278 133.04167,529 133.75,529 H 138 c 1.00042,0 2,-0.79793 2,-2 v -3.5 a 0.50005,0.50005 0 1 0 -1,0 v 3.5 c 0,0.66505 -0.50442,1 -1,1 h -4.25 c -0.29167,0 -0.60981,-0.19778 -0.71875,-0.48828 -0.10894,-0.2905 -0.0893,-0.74659 0.57227,-1.4082 l 4.25,-4.25 a 0.50005,0.50005 0 0 0 -0.36329,-0.85743 z" @@ -11396,7 +11396,7 @@ <g style="display:inline;fill:#ffffff;enable-background:new" id="g22292" - transform="translate(-87.000002,-170)"> + transform="translate(-88.000002,-170)"> <g transform="translate(20,10)" id="g22287" @@ -12431,11 +12431,6 @@ id="path24010-2" inkscape:connector-curvature="0" /> </g> - <path - style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.6;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" - d="m 310.57031,473.01758 c -0.79787,-0.038 -1.57177,0.27684 -2.16015,0.86523 l -1.48633,1.48828 c -0.61577,0.57533 -0.93433,1.35407 -0.89258,2.1543 a 0.50005,0.50005 0 1 0 0.99805,-0.0508 c -0.0269,-0.51495 0.15566,-0.98016 0.57617,-1.37305 a 0.50005,0.50005 0 0 0 0.0117,-0.0117 l 1.5,-1.5 c 0.41161,-0.41161 0.88966,-0.59872 1.40429,-0.57422 0.51464,0.0245 1.08439,0.26993 1.63868,0.82422 0.55479,0.5548 0.80954,1.13546 0.83789,1.65235 0.0283,0.51688 -0.15241,0.9848 -0.57422,1.3789 a 0.50005,0.50005 0 0 0 -0.0137,0.0117 l -1.5,1.5 c -0.41213,0.41213 -0.87694,0.60352 -1.39649,0.60352 a 0.50005,0.50005 0 1 0 0,1 c 0.78067,0 1.52491,-0.31788 2.10352,-0.89649 l 1.48828,-1.48828 c 0.61768,-0.57711 0.9366,-1.36125 0.89258,-2.16406 -0.044,-0.80281 -0.43566,-1.60948 -1.13086,-2.30469 -0.69571,-0.69571 -1.49901,-1.07724 -2.29688,-1.11523 z m -1.08008,3.97851 a 0.50005,0.50005 0 0 0 -0.34375,0.15039 l -5,5 a 0.50005,0.50005 0 1 0 0.70704,0.70704 l 5,-5 a 0.50005,0.50005 0 0 0 -0.36329,-0.85743 z m -4.92968,2.02149 c -0.80753,-0.0482 -1.5954,0.26944 -2.17578,0.89062 l -1.48829,1.48828 c -0.58838,0.58839 -0.90322,1.36034 -0.86523,2.15821 0.038,0.79787 0.41952,1.60311 1.11523,2.29883 0.69521,0.6952 1.50384,1.08487 2.30664,1.1289 0.80281,0.044 1.585,-0.27294 2.16211,-0.89062 l 1.48829,-1.48828 C 307.68213,484.0249 308,483.28067 308,482.5 a 0.50005,0.50005 0 1 0 -1,0 c 0,0.51955 -0.19139,0.98436 -0.60352,1.39648 l -1.5,1.5 a 0.50005,0.50005 0 0 0 -0.0117,0.0117 c -0.39411,0.42182 -0.86007,0.60452 -1.37696,0.57618 -0.51688,-0.0283 -1.0995,-0.2831 -1.65429,-0.8379 -0.55429,-0.55428 -0.79776,-1.12404 -0.82227,-1.63867 -0.0245,-0.51463 0.16065,-0.99268 0.57227,-1.40429 l 1.5,-1.5 a 0.50005,0.50005 0 0 0 0.0117,-0.0117 c 0.39634,-0.4242 0.86629,-0.60725 1.38672,-0.57618 a 0.50005,0.50005 0 1 0 0.0586,-0.99804 z" - id="path23281" - inkscape:connector-curvature="0" /> <g style="display:inline;fill:#ffffff;enable-background:new" id="g23341" @@ -13044,7 +13039,7 @@ inkscape:export-ydpi="96" inkscape:export-xdpi="96" inkscape:export-filename="blender_icons.png" - transform="translate(-20,168)" + transform="translate(-21,168)" id="g15951-6" style="display:inline;opacity:1;fill:#ffffff;enable-background:new"> <path @@ -14438,7 +14433,7 @@ <path id="path16385" style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" - d="m 516.5,432 c -0.1326,2e-5 -0.25976,0.0527 -0.35352,0.14647 L 514.29297,434 H 511.5 c -0.27613,3e-5 -0.49997,0.22387 -0.5,0.5 v 8 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 h 6.45312 0.004 c 0.0131,-8.2e-4 0.0261,-0.002 0.0391,-0.004 0.004,5e-5 0.008,5e-5 0.0117,0 0.0143,0.002 0.0286,0.003 0.043,0.004 h 0.006 5.44336 c 0.27613,-3e-5 0.49997,-0.22387 0.5,-0.5 v -8 c -3e-5,-0.27613 -0.22387,-0.49997 -0.5,-0.5 h -1.79297 l -1.85351,-1.85353 C 519.76,432.05268 519.6327,431.99995 519.5,432 Z m 1.49781,1.99804 c 2.21589,-3.2e-4 4.00185,1.7855 4.00195,4.00196 -9e-4,2.19736 -1.75841,3.97457 -3.95508,4 -0.0131,8.2e-4 -0.0261,0.002 -0.0391,0.004 -0.0149,-0.002 -0.0299,-0.003 -0.0449,-0.004 -10e-4,0 -0.003,0 -0.004,0 -2.19824,-0.0228 -3.95803,-1.80057 -3.95898,-4 9e-5,-2.21578 1.78479,-4.00131 4,-4.00196 z M 517.99805,435 C 516.34742,435 515,436.34922 515,438 c 0,1.65079 1.34742,3 2.99805,3 1.65063,0 3,-1.34921 3,-3 0,-1.65078 -1.34937,-3 -3,-3 z m 0,1 c 1.11009,0 2,0.88955 2,2 0,1.11045 -0.88991,2 -2,2 C 516.88796,440 516,439.11045 516,438 c 0,-1.11045 0.88796,-2 1.99805,-2 z" + d="m 515.5,432 c -0.1326,2e-5 -0.25976,0.0527 -0.35352,0.14647 L 513.29297,434 H 510.5 c -0.27613,3e-5 -0.49997,0.22387 -0.5,0.5 v 8 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 h 6.45312 0.004 c 0.0131,-8.2e-4 0.0261,-0.002 0.0391,-0.004 0.004,5e-5 0.008,5e-5 0.0117,0 0.0143,0.002 0.0286,0.003 0.043,0.004 h 0.006 5.44336 c 0.27613,-3e-5 0.49997,-0.22387 0.5,-0.5 v -8 c -3e-5,-0.27613 -0.22387,-0.49997 -0.5,-0.5 h -1.79297 l -1.85351,-1.85353 C 518.76,432.05268 518.6327,431.99995 518.5,432 Z m 1.49781,1.99804 c 2.21589,-3.2e-4 4.00185,1.7855 4.00195,4.00196 -9e-4,2.19736 -1.75841,3.97457 -3.95508,4 -0.0131,8.2e-4 -0.0261,0.002 -0.0391,0.004 -0.0149,-0.002 -0.0299,-0.003 -0.0449,-0.004 -10e-4,0 -0.003,0 -0.004,0 -2.19824,-0.0228 -3.95803,-1.80057 -3.95898,-4 9e-5,-2.21578 1.78479,-4.00131 4,-4.00196 z M 516.99805,435 C 515.34742,435 514,436.34922 514,438 c 0,1.65079 1.34742,3 2.99805,3 1.65063,0 3,-1.34921 3,-3 0,-1.65078 -1.34937,-3 -3,-3 z m 0,1 c 1.11009,0 2,0.88955 2,2 0,1.11045 -0.88991,2 -2,2 C 515.88796,440 515,439.11045 515,438 c 0,-1.11045 0.88796,-2 1.99805,-2 z" inkscape:connector-curvature="0" /> <path inkscape:connector-curvature="0" @@ -14448,18 +14443,18 @@ <path inkscape:connector-curvature="0" id="path22635-0-9" - d="m 495.5,432 a 0.50005,0.50005 0 0 0 -0.35352,0.14648 L 493.29297,434 H 490.5 a 0.50005,0.50005 0 0 0 -0.5,0.5 v 8 a 0.50005,0.50005 0 0 0 0.5,0.5 h 12 a 0.50005,0.50005 0 0 0 0.5,-0.5 v -8 a 0.50005,0.50005 0 0 0 -0.5,-0.5 h -1.79297 l -1.85351,-1.85352 A 0.50005,0.50005 0 0 0 498.5,432 Z m 0.20703,1 h 2.58594 l 1.85351,1.85352 A 0.50005,0.50005 0 0 0 500.5,435 h 1.5 v 7 h -11 v -7 h 2.5 a 0.50005,0.50005 0 0 0 0.35352,-0.14648 z m -0.46094,2.74414 a 0.50005,0.50005 0 0 0 -0.34961,0.85938 l 1.39649,1.39648 -1.39649,1.39648 a 0.50005,0.50005 0 1 0 0.70704,0.70704 L 497,438.70703 l 1.39648,1.39649 a 0.50005,0.50005 0 1 0 0.70704,-0.70704 L 497.70703,438 l 1.39649,-1.39648 a 0.50005,0.50005 0 1 0 -0.70704,-0.70704 L 497,437.29297 l -1.39648,-1.39649 a 0.50005,0.50005 0 0 0 -0.35743,-0.15234 z" + d="m 494.5,432 a 0.50005,0.50005 0 0 0 -0.35352,0.14648 L 492.29297,434 H 489.5 a 0.50005,0.50005 0 0 0 -0.5,0.5 v 8 a 0.50005,0.50005 0 0 0 0.5,0.5 h 12 a 0.50005,0.50005 0 0 0 0.5,-0.5 v -8 a 0.50005,0.50005 0 0 0 -0.5,-0.5 h -1.79297 l -1.85351,-1.85352 A 0.50005,0.50005 0 0 0 497.5,432 Z m 0.20703,1 h 2.58594 l 1.85351,1.85352 A 0.50005,0.50005 0 0 0 499.5,435 h 1.5 v 7 h -11 v -7 h 2.5 a 0.50005,0.50005 0 0 0 0.35352,-0.14648 z m -0.46094,2.74414 a 0.50005,0.50005 0 0 0 -0.34961,0.85938 l 1.39649,1.39648 -1.39649,1.39648 a 0.50005,0.50005 0 1 0 0.70704,0.70704 L 496,438.70703 l 1.39648,1.39649 a 0.50005,0.50005 0 1 0 0.70704,-0.70704 L 496.70703,438 l 1.39649,-1.39648 a 0.50005,0.50005 0 1 0 -0.70704,-0.70704 L 496,437.29297 l -1.39648,-1.39649 a 0.50005,0.50005 0 0 0 -0.35743,-0.15234 z" style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.6;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" /> <path sodipodi:nodetypes="ccccccccc" inkscape:connector-curvature="0" id="path19969-0" - d="m 471.49125,433 c -0.3497,0.006 -0.58488,0.36077 -0.45507,0.68555 l 4,10.00195 c 0.1779,0.45034 0.82806,0.4102 0.94922,-0.0586 l 1.17578,-4.46875 4.46679,-1.17578 c 0.46499,-0.12321 0.50486,-0.76769 0.0586,-0.94727 l -10,-4.00195 c -0.0621,-0.0247 -0.12852,-0.0366 -0.19532,-0.0351 z" + d="m 470.49125,433 c -0.3497,0.006 -0.58488,0.36077 -0.45507,0.68555 l 4,10.00195 c 0.1779,0.45034 0.82806,0.4102 0.94922,-0.0586 l 1.17578,-4.46875 4.46679,-1.17578 c 0.46499,-0.12321 0.50486,-0.76769 0.0586,-0.94727 l -10,-4.00195 c -0.0621,-0.0247 -0.12852,-0.0366 -0.19532,-0.0351 z" style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" /> <path inkscape:connector-curvature="0" id="path19971-4" - d="m 450.49078,433 a 0.50005,0.50005 0 0 0 -0.45507,0.68555 l 4,10.00195 a 0.50050292,0.50050292 0 1 0 0.92968,-0.37109 l -3.5664,-8.91797 8.91601,3.5664 a 0.50005,0.50005 0 1 0 0.3711,-0.92773 l -10,-4.00195 A 0.50005,0.50005 0 0 0 450.49078,433 Z" + d="m 449.49078,433 a 0.50005,0.50005 0 0 0 -0.45507,0.68555 l 4,10.00195 a 0.50050292,0.50050292 0 1 0 0.92968,-0.37109 l -3.5664,-8.91797 8.91601,3.5664 a 0.50005,0.50005 0 1 0 0.3711,-0.92773 l -10,-4.00195 A 0.50005,0.50005 0 0 0 449.49078,433 Z" style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.6;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" /> <g transform="translate(37.00977,-1667.9941)" @@ -14570,7 +14565,7 @@ <path inkscape:connector-curvature="0" id="path13646-9" - d="m 406.50195,437 a 0.50005,0.50005 0 0 0 -0.33203,0.84375 c 1.3239,1.43817 3.0824,4.1582 6.3457,4.1582 3.26331,0 5.02376,-2.72003 6.34766,-4.1582 a 0.50037481,0.50037481 0 1 0 -0.73633,-0.67773 c -1.43556,1.55946 -2.90607,3.83593 -5.61133,3.83593 -2.70525,0 -4.17576,-2.27647 -5.61132,-3.83593 A 0.50005,0.50005 0 0 0 406.50195,437 Z" + d="m 405.50174,437 a 0.50005,0.50005 0 0 0 -0.33203,0.84375 c 1.3239,1.43817 3.0824,4.1582 6.3457,4.1582 3.26331,0 5.02376,-2.72003 6.34766,-4.1582 a 0.50037481,0.50037481 0 1 0 -0.73633,-0.67773 c -1.43556,1.55946 -2.90607,3.83593 -5.61133,3.83593 -2.70525,0 -4.17576,-2.27647 -5.61132,-3.83593 A 0.50005,0.50005 0 0 0 405.50174,437 Z" style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.6;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" /> <g transform="translate(315,-0.999996)" @@ -14623,7 +14618,7 @@ <path inkscape:connector-curvature="0" style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" - d="m 433.5,433 c -3.27784,-9.4e-4 -5.036,2.7211 -6.36328,4.16211 -0.17644,0.19146 -0.17644,0.48627 0,0.67773 1.3275,1.44124 3.08593,4.15993 6.36328,4.16211 3.27801,0.002 5.03608,-2.72118 6.36328,-4.16211 0.17644,-0.19146 0.17644,-0.48627 0,-0.67773 C 438.53587,435.72096 436.77755,433.00094 433.5,433 Z m 0,1 a 3.4999952,3.4999933 0 0 1 3.5,3.5 3.4999952,3.4999933 0 0 1 -3.5,3.5 3.4999952,3.4999933 0 0 1 -3.5,-3.5 3.4999952,3.4999933 0 0 1 3.5,-3.5 z m 0,2 a 1.4999952,1.4999944 0 0 0 -1.5,1.5 1.4999952,1.4999944 0 0 0 1.5,1.5 1.4999952,1.4999944 0 0 0 1.5,-1.5 1.4999952,1.4999944 0 0 0 -1.5,-1.5 z" + d="m 432.49961,433 c -3.27784,-9.4e-4 -5.036,2.7211 -6.36328,4.16211 -0.17644,0.19146 -0.17644,0.48627 0,0.67773 1.3275,1.44124 3.08593,4.15993 6.36328,4.16211 3.27801,0.002 5.03608,-2.72118 6.36328,-4.16211 0.17644,-0.19146 0.17644,-0.48627 0,-0.67773 -1.32741,-1.44115 -3.08573,-4.16117 -6.36328,-4.16211 z m 0,1 a 3.4999952,3.4999933 0 0 1 3.5,3.5 3.4999952,3.4999933 0 0 1 -3.5,3.5 3.4999952,3.4999933 0 0 1 -3.5,-3.5 3.4999952,3.4999933 0 0 1 3.5,-3.5 z m 0,2 a 1.4999952,1.4999944 0 0 0 -1.5,1.5 1.4999952,1.4999944 0 0 0 1.5,1.5 1.4999952,1.4999944 0 0 0 1.5,-1.5 1.4999952,1.4999944 0 0 0 -1.5,-1.5 z" id="path19347-7" /> <g id="g19953" @@ -15552,22 +15547,22 @@ </g> <path id="path22885-3-7" - d="m 538.4922,557 c -0.1299,0 -0.2539,0.055 -0.3457,0.1465 -1.4018,1.4018 -2.9571,1.8535 -5.6465,1.8535 -0.2761,0 -0.5,0.2239 -0.5,0.5 v 3 c 0,2.4627 0.6805,4.0682 1.7871,5.2754 1.1066,1.2072 2.5736,2.0242 4.1777,3.1348 0.084,0.058 0.1832,0.09 0.2852,0.09 h 0.5 c 0.102,-2e-4 0.2015,-0.032 0.2852,-0.09 1.6041,-1.1106 3.0711,-1.9276 4.1777,-3.1348 C 544.3195,566.5682 545,564.9627 545,562.5 v -3 c 0,-0.2761 -0.2239,-0.5 -0.5,-0.5 -2.6894,0 -4.2447,-0.4517 -5.6465,-1.8535 -0.096,-0.096 -0.226,-0.1486 -0.3613,-0.1465 z m 3.4766,3.9902 a 1.0001,1.0001 0 0 1 0.8124,1.6348 l -4,5 a 1.0001,1.0001 0 0 1 -1.4882,0.082 l -2,-2 a 1.0001,1.0001 0 1 1 1.414,-1.414 l 1.209,1.209 3.3028,-4.127 a 1.0001,1.0001 0 0 1 0.75,-0.3848 z" + d="m 537.4922,557 c -0.1299,0 -0.2539,0.055 -0.3457,0.1465 -1.4018,1.4018 -2.9571,1.8535 -5.6465,1.8535 -0.2761,0 -0.5,0.2239 -0.5,0.5 v 3 c 0,2.4627 0.6805,4.0682 1.7871,5.2754 1.1066,1.2072 2.5736,2.0242 4.1777,3.1348 0.084,0.058 0.1832,0.09 0.2852,0.09 h 0.5 c 0.102,-2e-4 0.2015,-0.032 0.2852,-0.09 1.6041,-1.1106 3.0711,-1.9276 4.1777,-3.1348 C 543.3195,566.5682 544,564.9627 544,562.5 v -3 c 0,-0.2761 -0.2239,-0.5 -0.5,-0.5 -2.6894,0 -4.2447,-0.4517 -5.6465,-1.8535 -0.096,-0.096 -0.226,-0.1486 -0.3613,-0.1465 z m 3.4766,3.9902 a 1.0001,1.0001 0 0 1 0.8124,1.6348 l -4,5 a 1.0001,1.0001 0 0 1 -1.4882,0.082 l -2,-2 a 1.0001,1.0001 0 1 1 1.414,-1.414 l 1.209,1.209 3.3028,-4.127 a 1.0001,1.0001 0 0 1 0.75,-0.3848 z" style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" inkscape:connector-curvature="0" /> <path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.6;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" - d="m 517.49219,557 a 0.50005,0.50005 0 0 0 -0.34571,0.14648 C 515.74469,558.54828 514.18939,559 511.5,559 a 0.50005,0.50005 0 0 0 -0.5,0.5 v 3 c 0,2.46272 0.6805,4.06818 1.78711,5.27539 1.10661,1.20722 2.57356,2.02419 4.17773,3.13477 A 0.50005,0.50005 0 0 0 517.25,571 h 0.5 a 0.50005,0.50005 0 0 0 0.28516,-0.0898 c 1.60417,-1.11058 3.07112,-1.92755 4.17773,-3.13477 C 523.3195,566.56818 524,564.96272 524,562.5 v -3 a 0.50005,0.50005 0 0 0 -0.5,-0.5 c -2.68939,0 -4.24469,-0.45172 -5.64648,-1.85352 A 0.50005,0.50005 0 0 0 517.49219,557 Z m 0.008,1.07031 c 1.42533,1.26825 3.16641,1.79779 5.5,1.86524 V 562.5 c 0,2.28728 -0.5695,3.55682 -1.52539,4.59961 -0.92707,1.01135 -2.30655,1.81425 -3.88867,2.90039 h -0.17188 c -1.58212,-1.08614 -2.9616,-1.88904 -3.88867,-2.90039 C 512.5695,566.05682 512,564.78728 512,562.5 v -2.56445 c 2.33359,-0.0675 4.07467,-0.59699 5.5,-1.86524 z" + d="m 516.49219,557 a 0.50005,0.50005 0 0 0 -0.34571,0.14648 C 514.74469,558.54828 513.18939,559 510.5,559 a 0.50005,0.50005 0 0 0 -0.5,0.5 v 3 c 0,2.46272 0.6805,4.06818 1.78711,5.27539 1.10661,1.20722 2.57356,2.02419 4.17773,3.13477 A 0.50005,0.50005 0 0 0 516.25,571 h 0.5 a 0.50005,0.50005 0 0 0 0.28516,-0.0898 c 1.60417,-1.11058 3.07112,-1.92755 4.17773,-3.13477 C 522.3195,566.56818 523,564.96272 523,562.5 v -3 a 0.50005,0.50005 0 0 0 -0.5,-0.5 c -2.68939,0 -4.24469,-0.45172 -5.64648,-1.85352 A 0.50005,0.50005 0 0 0 516.49219,557 Z m 0.008,1.07031 c 1.42533,1.26825 3.16641,1.79779 5.5,1.86524 V 562.5 c 0,2.28728 -0.5695,3.55682 -1.52539,4.59961 -0.92707,1.01135 -2.30655,1.81425 -3.88867,2.90039 h -0.17188 c -1.58212,-1.08614 -2.9616,-1.88904 -3.88867,-2.90039 C 511.5695,566.05682 511,564.78728 511,562.5 v -2.56445 c 2.33359,-0.0675 4.07467,-0.59699 5.5,-1.86524 z" id="path22877-22-0" inkscape:connector-curvature="0" /> <path inkscape:connector-curvature="0" - d="m 513,414.00018 h 9 v 5 h -9 z m -1.5,-2 c -0.27613,3e-5 -0.49997,0.22387 -0.5,0.5 v 8 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 h 5.5 v 1 h -2.5 c -0.67616,-0.01 -0.67616,1.00956 0,1 h 6 c 0.6573,-0.009 0.6573,-0.9907 0,-1 H 518 v -1 h 5.5 c 0.27613,-3e-5 0.49997,-0.22387 0.5,-0.5 v -8 c -3e-5,-0.27613 -0.22387,-0.49997 -0.5,-0.5 z m 0.5,1 h 11 v 7 h -11 z" + d="m 512,414.00018 h 9 v 5 h -9 z m -1.5,-2 c -0.27613,3e-5 -0.49997,0.22387 -0.5,0.5 v 8 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 h 5.5 v 1 h -2.5 c -0.67616,-0.01 -0.67616,1.00956 0,1 h 6 c 0.6573,-0.009 0.6573,-0.9907 0,-1 H 517 v -1 h 5.5 c 0.27613,-3e-5 0.49997,-0.22387 0.5,-0.5 v -8 c -3e-5,-0.27613 -0.22387,-0.49997 -0.5,-0.5 z m 0.5,1 h 11 v 7 h -11 z" style="opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke" id="rect22324-2" /> <path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.6;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" - d="m 490.5,412 c -0.27613,3e-5 -0.49997,0.22387 -0.5,0.5 v 8 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 h 5.5 v 1 h -2.5 c -0.67616,-0.01 -0.67616,1.00956 0,1 h 6 c 0.6573,-0.009 0.6573,-0.9907 0,-1 H 497 v -1 h 5.5 c 0.27613,-3e-5 0.49997,-0.22387 0.5,-0.5 v -8 c -3e-5,-0.27613 -0.22387,-0.49997 -0.5,-0.5 z m 0.5,1 h 11 v 7 h -11 z" + d="m 489.5,412 c -0.27613,3e-5 -0.49997,0.22387 -0.5,0.5 v 8 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 h 5.5 v 1 h -2.5 c -0.67616,-0.01 -0.67616,1.00956 0,1 h 6 c 0.6573,-0.009 0.6573,-0.9907 0,-1 H 496 v -1 h 5.5 c 0.27613,-3e-5 0.49997,-0.22387 0.5,-0.5 v -8 c -3e-5,-0.27613 -0.22387,-0.49997 -0.5,-0.5 z m 0.5,1 h 11 v 7 h -11 z" id="path22338-8" inkscape:connector-curvature="0" sodipodi:nodetypes="cccccccccccccccccccccc" /> @@ -15646,11 +15641,11 @@ <path inkscape:connector-curvature="0" style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" - d="m 542.77344,306 a 1.0001,1.0001 0 0 0 -0.41211,0.0781 l -4.74024,2 a 1.0004654,1.0004654 0 1 0 0.77735,1.84376 l 1.54883,-0.65235 -2.69532,5.375 -2.78906,-2.30078 a 1.50015,1.50015 0 1 0 -1.9082,2.3125 l 4.24023,3.5 a 1.50015,1.50015 0 0 0 2.29688,-0.48437 l 3.53711,-7.0586 0.41015,1.63086 a 1.0001,1.0001 0 1 0 1.93946,-0.48828 l -1.25977,-5 A 1.0001,1.0001 0 0 0 542.77344,306 Z" + d="m 541.77363,306 a 1.0001,1.0001 0 0 0 -0.41211,0.0781 l -4.74024,2 a 1.0004654,1.0004654 0 1 0 0.77735,1.84376 l 1.54883,-0.65235 -2.69532,5.375 -2.78906,-2.30078 a 1.50015,1.50015 0 1 0 -1.9082,2.3125 l 4.24023,3.5 a 1.50015,1.50015 0 0 0 2.29688,-0.48437 l 3.53711,-7.0586 0.41015,1.63086 a 1.0001,1.0001 0 1 0 1.93946,-0.48828 l -1.25977,-5 A 1.0001,1.0001 0 0 0 541.77363,306 Z" id="path25427-8" /> <path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.6;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" - d="m 521.51367,306 a 0.50005,0.50005 0 0 0 -0.23633,0.0527 l -4,2 a 0.50005,0.50005 0 1 0 0.44532,0.89454 l 2.8164,-1.40821 -4.20508,8.1875 -4.52148,-3.61718 a 0.50024018,0.50024018 0 1 0 -0.625,0.78124 l 5,4 a 0.50005,0.50005 0 0 0 0.75781,-0.1621 l 4.4375,-8.64063 0.63281,2.5332 a 0.50005,0.50005 0 1 0 0.96876,-0.24218 l -1,-4 A 0.50005,0.50005 0 0 0 521.51367,306 Z" + d="m 520.51395,306 a 0.50005,0.50005 0 0 0 -0.23633,0.0527 l -4,2 a 0.50005,0.50005 0 1 0 0.44532,0.89454 l 2.8164,-1.40821 -4.20508,8.1875 -4.52148,-3.61718 a 0.50024018,0.50024018 0 1 0 -0.625,0.78124 l 5,4 a 0.50005,0.50005 0 0 0 0.75781,-0.1621 l 4.4375,-8.64063 0.63281,2.5332 a 0.50005,0.50005 0 1 0 0.96876,-0.24218 l -1,-4 A 0.50005,0.50005 0 0 0 520.51395,306 Z" id="path25488-0" inkscape:connector-curvature="0" /> <g @@ -17355,21 +17350,21 @@ id="g905"> <g transform="matrix(0.6740384,0,0,0.6740384,192.80592,-339.68227)" - style="display:inline;opacity:0.99;fill:#ffffff;stroke-width:1.07692;enable-background:new" + style="display:inline;opacity:0.99;fill:#ffffff;stroke-width:1.07692;enable-background:new" id="g8599-6-7" - inkscape:export-filename="blender_icons.png" - inkscape:export-xdpi="96" - inkscape:export-ydpi="96"> - <path + inkscape:export-filename="blender_icons.png" + inkscape:export-xdpi="96" + inkscape:export-ydpi="96"> + <path id="path8597-7-0" d="m 331.87142,629.24052 c 0,0.81936 -0.66423,1.48359 -1.48359,1.48359 -0.81937,0 -1.4836,-0.66422 -1.4836,-1.48359 0,-0.81937 0.66423,-1.4836 1.4836,-1.4836 0.81937,0 1.48359,0.66423 1.48359,1.4836 z" style="opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.72218;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke" inkscape:connector-curvature="0" sodipodi:nodetypes="sssss" /> - </g> - <path + </g> + <path sodipodi:nodetypes="cccccccccczzcczzzzz" - inkscape:connector-curvature="0" + inkscape:connector-curvature="0" id="path8595-5-9" d="m 414.93725,78.999996 c -0.65344,-0.653443 -1.58833,0.255453 -0.88297,0.960812 L 415.18167,81 h -4.6057 c -0.88913,-0.01822 -0.88913,1.018254 0,1 l 2.19337,-0.004 -0.006,0.004 -3.27651,2.873468 c -0.64989,0.580999 0.2216,1.555837 0.87149,0.97484 L 412.00004,84.45 c 0,1.651946 1.15621,3.581251 3.47506,3.550001 C 417.79395,87.968751 419,86.250706 419,84.45 c 0,-1.800705 -1.00462,-2.558141 -1.45954,-3.013074 z M 415.5,82.2 c 1.22478,0 2.25,0.945047 2.25,2.25 0,1.304953 -1.05311,2.25 -2.25,2.25 -1.19689,0 -2.25,-0.960585 -2.25,-2.25 0,-1.289415 1.02522,-2.25 2.25,-2.25 z" style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.3066;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> @@ -17431,25 +17426,25 @@ d="m 414.93725,78.992499 c -0.65344,-0.653443 -1.58833,0.255453 -0.88297,0.960812 l 1.12739,1.039192 h -4.6057 c -0.88913,-0.01822 -0.88913,1.018254 0,1 l 2.19337,-0.004 -0.006,0.004 -3.27651,2.873468 c -0.64989,0.580999 0.2216,1.555837 0.87149,0.97484 l 1.64161,-1.398308 c 0,1.651946 1.15632,3.581251 3.47517,3.550001 2.31885,-0.03125 3.5249,-1.749295 3.5249,-3.550001 0,-1.800705 -1.00462,-2.558141 -1.45954,-3.013074 z M 415.5,82.192503 c 1.22478,0 2.25,0.945047 2.25,2.25 0,1.304953 -1.05311,2.25 -2.25,2.25 -1.19689,0 -2.25,-0.960585 -2.25,-2.25 0,-1.289415 1.02522,-2.25 2.25,-2.25 z" style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.3066;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> </g> - <g + <g transform="translate(19.000003)" id="g28228-3-3" style="display:inline;opacity:0.6;stroke:#ffffff;enable-background:new" - inkscape:export-filename="blender_icons.png" - inkscape:export-xdpi="96" - inkscape:export-ydpi="96"> + inkscape:export-filename="blender_icons.png" + inkscape:export-xdpi="96" + inkscape:export-ydpi="96"> <g id="g28217-6-6" transform="translate(338.99999,-439.99995)" style="display:inline;opacity:0.99;stroke:#ffffff;enable-background:new"> - <path - inkscape:connector-curvature="0" + <path + inkscape:connector-curvature="0" id="path28215-0" transform="translate(-337.99999,439.99995)" d="m 501.49219,52.992188 c -0.27615,0.0043 -0.49651,0.223792 -0.49219,0.499938 v 1 c -0.01,0.676161 1.00956,0.676161 1,0 v -1 c 0.004,-0.282265 -0.22554,-0.504353 -0.50781,-0.499938 z m -7.00781,0.0067 c -0.12718,0.004 -0.248,0.0564 -0.3379,0.146484 l -4,4.001116 c -0.10126,0.101337 -0.1304,0.223491 -0.13086,0.345704 L 490,57.507812 v 1.984314 c -0.01,0.676161 1.00956,0.676161 1,0 v -1.5 h 3.5 c 0.27613,-3e-5 0.49997,-0.22387 0.5,-0.5 v -3.5 h 1.5 c 0.67616,0.0096 0.67616,-1.002805 0,-0.993242 h -2 v 0.002 c -0.005,-5e-6 -0.0101,-0.0021 -0.0156,-0.002 z m 4.01562,-0.0068 c -0.67616,-0.0096 -0.67616,1.009563 0,1 h 1 c 0.67616,0.0096 0.67616,-1.009563 0,-1 z m 2.99219,3.000062 c -0.27615,0.0043 -0.49651,0.223792 -0.49219,0.499938 v 1 c -0.01,0.676161 1.00956,0.676161 1,0 v -1 c 0.004,-0.282265 -0.22554,-0.504353 -0.50781,-0.499938 z m -11,5 c -0.27615,0.0043 -0.49651,0.223792 -0.49219,0.499938 v 1 c -0.01,0.676161 1.00956,0.676161 1,0 v -1 c 0.004,-0.282265 -0.22554,-0.504353 -0.50781,-0.499938 z m 0,3 c -0.27615,0.0043 -0.49651,0.223792 -0.49219,0.499938 v 1 c -0.01,0.676161 1.00956,0.676161 1,0 v -1 c 0.004,-0.282265 -0.22554,-0.504353 -0.50781,-0.499938 z M 492.5,65.992126 c -0.67616,-0.0096 -0.67616,1.009563 0,1 h 1 c 0.67616,0.0096 0.67616,-1.009563 0,-1 z m 3,0 c -0.67616,-0.0096 -0.67616,1.009563 0,1 h 1 c 0.67616,0.0096 0.67616,-1.009563 0,-1 z" style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" /> - </g> + </g> </g> </g> </g> @@ -17471,10 +17466,10 @@ inkscape:connector-curvature="0" sodipodi:nodetypes="cccccccscccccccccccccccc" /> </g> - <path + <path sodipodi:nodetypes="csscccccccccccssscccc" style="opacity:0.6;fill:#ffffff" - inkscape:connector-curvature="0" + inkscape:connector-curvature="0" id="path2-6" d="m 469,101 v 7.5 c 0,0.276 0.224,0.5 0.5,0.5 h 11 c 0.30423,0 0.5,-0.22782 0.5,-0.5 v -4 c 0,-0.65459 -1,-0.65682 -1,0 v 3.5 h -10 v -7 z m 4.48081,-6 c -0.151,0.004 -0.293,0.077 -0.384,0.197 l -3.95,3.949 c -0.314,0.315 -0.091,0.854 0.354,0.854 h 4 c 0.276,0 0.5,-0.224 0.5,-0.5 V 96 H 480.5 c 0.68512,0 0.64092,-1 0,-1 z" /> </g> diff --git a/release/datafiles/blender_icons16/icon16_editmode_hlt.dat b/release/datafiles/blender_icons16/icon16_editmode_hlt.dat Binary files differindex a29abf4e4c8..69d4e3bc4a9 100644 --- a/release/datafiles/blender_icons16/icon16_editmode_hlt.dat +++ b/release/datafiles/blender_icons16/icon16_editmode_hlt.dat diff --git a/release/datafiles/blender_icons16/icon16_fake_user_off.dat b/release/datafiles/blender_icons16/icon16_fake_user_off.dat Binary files differindex a40ac7a148e..1807949b579 100644 --- a/release/datafiles/blender_icons16/icon16_fake_user_off.dat +++ b/release/datafiles/blender_icons16/icon16_fake_user_off.dat diff --git a/release/datafiles/blender_icons16/icon16_fake_user_on.dat b/release/datafiles/blender_icons16/icon16_fake_user_on.dat Binary files differindex ea1176dacc3..d7f5a678d40 100644 --- a/release/datafiles/blender_icons16/icon16_fake_user_on.dat +++ b/release/datafiles/blender_icons16/icon16_fake_user_on.dat diff --git a/release/datafiles/blender_icons16/icon16_force_boid.dat b/release/datafiles/blender_icons16/icon16_force_boid.dat Binary files differindex f719054d84a..71f89bd7c04 100644 --- a/release/datafiles/blender_icons16/icon16_force_boid.dat +++ b/release/datafiles/blender_icons16/icon16_force_boid.dat diff --git a/release/datafiles/blender_icons16/icon16_hide_off.dat b/release/datafiles/blender_icons16/icon16_hide_off.dat Binary files differindex e6917365472..5de3e7d5b00 100644 --- a/release/datafiles/blender_icons16/icon16_hide_off.dat +++ b/release/datafiles/blender_icons16/icon16_hide_off.dat diff --git a/release/datafiles/blender_icons16/icon16_hide_on.dat b/release/datafiles/blender_icons16/icon16_hide_on.dat Binary files differindex 6303cd53ccf..7930a98a873 100644 --- a/release/datafiles/blender_icons16/icon16_hide_on.dat +++ b/release/datafiles/blender_icons16/icon16_hide_on.dat diff --git a/release/datafiles/blender_icons16/icon16_indirect_only_off.dat b/release/datafiles/blender_icons16/icon16_indirect_only_off.dat Binary files differindex 58f89be44f6..f7c6c6094e3 100644 --- a/release/datafiles/blender_icons16/icon16_indirect_only_off.dat +++ b/release/datafiles/blender_icons16/icon16_indirect_only_off.dat diff --git a/release/datafiles/blender_icons16/icon16_indirect_only_on.dat b/release/datafiles/blender_icons16/icon16_indirect_only_on.dat Binary files differindex 2b2b73455ce..d7e504adf0a 100644 --- a/release/datafiles/blender_icons16/icon16_indirect_only_on.dat +++ b/release/datafiles/blender_icons16/icon16_indirect_only_on.dat diff --git a/release/datafiles/blender_icons16/icon16_library_data_indirect.dat b/release/datafiles/blender_icons16/icon16_library_data_indirect.dat Binary files differdeleted file mode 100644 index 78c012bb755..00000000000 --- a/release/datafiles/blender_icons16/icon16_library_data_indirect.dat +++ /dev/null diff --git a/release/datafiles/blender_icons16/icon16_object_datamode.dat b/release/datafiles/blender_icons16/icon16_object_datamode.dat Binary files differindex 28293424510..2d2545d372a 100644 --- a/release/datafiles/blender_icons16/icon16_object_datamode.dat +++ b/release/datafiles/blender_icons16/icon16_object_datamode.dat diff --git a/release/datafiles/blender_icons16/icon16_particlemode.dat b/release/datafiles/blender_icons16/icon16_particlemode.dat Binary files differindex 1a32156a7b8..b5e1321d5f0 100644 --- a/release/datafiles/blender_icons16/icon16_particlemode.dat +++ b/release/datafiles/blender_icons16/icon16_particlemode.dat diff --git a/release/datafiles/blender_icons16/icon16_pose_hlt.dat b/release/datafiles/blender_icons16/icon16_pose_hlt.dat Binary files differindex 3a59a1c9274..fd3fd905d21 100644 --- a/release/datafiles/blender_icons16/icon16_pose_hlt.dat +++ b/release/datafiles/blender_icons16/icon16_pose_hlt.dat diff --git a/release/datafiles/blender_icons16/icon16_restrict_render_off.dat b/release/datafiles/blender_icons16/icon16_restrict_render_off.dat Binary files differindex 5eab5eaa538..db720670903 100644 --- a/release/datafiles/blender_icons16/icon16_restrict_render_off.dat +++ b/release/datafiles/blender_icons16/icon16_restrict_render_off.dat diff --git a/release/datafiles/blender_icons16/icon16_restrict_render_on.dat b/release/datafiles/blender_icons16/icon16_restrict_render_on.dat Binary files differindex 29bebb2ee75..3db7aa2bb86 100644 --- a/release/datafiles/blender_icons16/icon16_restrict_render_on.dat +++ b/release/datafiles/blender_icons16/icon16_restrict_render_on.dat diff --git a/release/datafiles/blender_icons16/icon16_restrict_select_off.dat b/release/datafiles/blender_icons16/icon16_restrict_select_off.dat Binary files differindex fa8bbcb3a04..26bc4f16244 100644 --- a/release/datafiles/blender_icons16/icon16_restrict_select_off.dat +++ b/release/datafiles/blender_icons16/icon16_restrict_select_off.dat diff --git a/release/datafiles/blender_icons16/icon16_restrict_select_on.dat b/release/datafiles/blender_icons16/icon16_restrict_select_on.dat Binary files differindex 8fd1bcc97ab..eb106e5f4b1 100644 --- a/release/datafiles/blender_icons16/icon16_restrict_select_on.dat +++ b/release/datafiles/blender_icons16/icon16_restrict_select_on.dat diff --git a/release/datafiles/blender_icons16/icon16_restrict_view_off.dat b/release/datafiles/blender_icons16/icon16_restrict_view_off.dat Binary files differindex 7b116a56356..717d8d04f32 100644 --- a/release/datafiles/blender_icons16/icon16_restrict_view_off.dat +++ b/release/datafiles/blender_icons16/icon16_restrict_view_off.dat diff --git a/release/datafiles/blender_icons16/icon16_restrict_view_on.dat b/release/datafiles/blender_icons16/icon16_restrict_view_on.dat Binary files differindex 60ed6d0ef42..54fda79d24e 100644 --- a/release/datafiles/blender_icons16/icon16_restrict_view_on.dat +++ b/release/datafiles/blender_icons16/icon16_restrict_view_on.dat diff --git a/release/datafiles/blender_icons16/icon16_sculptmode_hlt.dat b/release/datafiles/blender_icons16/icon16_sculptmode_hlt.dat Binary files differindex ab8fbd88fe1..ac49226b300 100644 --- a/release/datafiles/blender_icons16/icon16_sculptmode_hlt.dat +++ b/release/datafiles/blender_icons16/icon16_sculptmode_hlt.dat diff --git a/release/datafiles/blender_icons16/icon16_tpaint_hlt.dat b/release/datafiles/blender_icons16/icon16_tpaint_hlt.dat Binary files differindex 9a56ff6177f..3537aa62099 100644 --- a/release/datafiles/blender_icons16/icon16_tpaint_hlt.dat +++ b/release/datafiles/blender_icons16/icon16_tpaint_hlt.dat diff --git a/release/datafiles/blender_icons16/icon16_uv_data.dat b/release/datafiles/blender_icons16/icon16_uv_data.dat Binary files differindex bea802a3bcb..b843c28ee26 100644 --- a/release/datafiles/blender_icons16/icon16_uv_data.dat +++ b/release/datafiles/blender_icons16/icon16_uv_data.dat diff --git a/release/datafiles/blender_icons16/icon16_vpaint_hlt.dat b/release/datafiles/blender_icons16/icon16_vpaint_hlt.dat Binary files differindex 0ad483ac862..7b4b42af987 100644 --- a/release/datafiles/blender_icons16/icon16_vpaint_hlt.dat +++ b/release/datafiles/blender_icons16/icon16_vpaint_hlt.dat diff --git a/release/datafiles/blender_icons16/icon16_wpaint_hlt.dat b/release/datafiles/blender_icons16/icon16_wpaint_hlt.dat Binary files differindex 199a859bb5d..f5eaf8ff566 100644 --- a/release/datafiles/blender_icons16/icon16_wpaint_hlt.dat +++ b/release/datafiles/blender_icons16/icon16_wpaint_hlt.dat diff --git a/release/datafiles/blender_icons32/icon32_editmode_hlt.dat b/release/datafiles/blender_icons32/icon32_editmode_hlt.dat Binary files differindex 6bfcaafe875..1a2f4ad096a 100644 --- a/release/datafiles/blender_icons32/icon32_editmode_hlt.dat +++ b/release/datafiles/blender_icons32/icon32_editmode_hlt.dat diff --git a/release/datafiles/blender_icons32/icon32_fake_user_off.dat b/release/datafiles/blender_icons32/icon32_fake_user_off.dat Binary files differindex 2e111fa7ba6..53a555f8ac5 100644 --- a/release/datafiles/blender_icons32/icon32_fake_user_off.dat +++ b/release/datafiles/blender_icons32/icon32_fake_user_off.dat diff --git a/release/datafiles/blender_icons32/icon32_fake_user_on.dat b/release/datafiles/blender_icons32/icon32_fake_user_on.dat Binary files differindex ce276de53d6..81ad3792699 100644 --- a/release/datafiles/blender_icons32/icon32_fake_user_on.dat +++ b/release/datafiles/blender_icons32/icon32_fake_user_on.dat diff --git a/release/datafiles/blender_icons32/icon32_force_boid.dat b/release/datafiles/blender_icons32/icon32_force_boid.dat Binary files differindex 9043989024b..7fc7cb5ee8c 100644 --- a/release/datafiles/blender_icons32/icon32_force_boid.dat +++ b/release/datafiles/blender_icons32/icon32_force_boid.dat diff --git a/release/datafiles/blender_icons32/icon32_hide_off.dat b/release/datafiles/blender_icons32/icon32_hide_off.dat Binary files differindex 3194af95943..17469a6095c 100644 --- a/release/datafiles/blender_icons32/icon32_hide_off.dat +++ b/release/datafiles/blender_icons32/icon32_hide_off.dat diff --git a/release/datafiles/blender_icons32/icon32_hide_on.dat b/release/datafiles/blender_icons32/icon32_hide_on.dat Binary files differindex 50de267bc78..722c25943d5 100644 --- a/release/datafiles/blender_icons32/icon32_hide_on.dat +++ b/release/datafiles/blender_icons32/icon32_hide_on.dat diff --git a/release/datafiles/blender_icons32/icon32_indirect_only_off.dat b/release/datafiles/blender_icons32/icon32_indirect_only_off.dat Binary files differindex a30545787fc..5dc49925a5a 100644 --- a/release/datafiles/blender_icons32/icon32_indirect_only_off.dat +++ b/release/datafiles/blender_icons32/icon32_indirect_only_off.dat diff --git a/release/datafiles/blender_icons32/icon32_indirect_only_on.dat b/release/datafiles/blender_icons32/icon32_indirect_only_on.dat Binary files differindex d2b9e894aca..31b4d64986b 100644 --- a/release/datafiles/blender_icons32/icon32_indirect_only_on.dat +++ b/release/datafiles/blender_icons32/icon32_indirect_only_on.dat diff --git a/release/datafiles/blender_icons32/icon32_library_data_indirect.dat b/release/datafiles/blender_icons32/icon32_library_data_indirect.dat Binary files differdeleted file mode 100644 index bc8198d8a5b..00000000000 --- a/release/datafiles/blender_icons32/icon32_library_data_indirect.dat +++ /dev/null diff --git a/release/datafiles/blender_icons32/icon32_object_datamode.dat b/release/datafiles/blender_icons32/icon32_object_datamode.dat Binary files differindex d4086196780..32173788c7e 100644 --- a/release/datafiles/blender_icons32/icon32_object_datamode.dat +++ b/release/datafiles/blender_icons32/icon32_object_datamode.dat diff --git a/release/datafiles/blender_icons32/icon32_particlemode.dat b/release/datafiles/blender_icons32/icon32_particlemode.dat Binary files differindex 343c568ec73..64edd74f980 100644 --- a/release/datafiles/blender_icons32/icon32_particlemode.dat +++ b/release/datafiles/blender_icons32/icon32_particlemode.dat diff --git a/release/datafiles/blender_icons32/icon32_pose_hlt.dat b/release/datafiles/blender_icons32/icon32_pose_hlt.dat Binary files differindex af5b10ad63a..d5f05a2e730 100644 --- a/release/datafiles/blender_icons32/icon32_pose_hlt.dat +++ b/release/datafiles/blender_icons32/icon32_pose_hlt.dat diff --git a/release/datafiles/blender_icons32/icon32_restrict_render_off.dat b/release/datafiles/blender_icons32/icon32_restrict_render_off.dat Binary files differindex 7f6cf73fea0..d1cc5a755c4 100644 --- a/release/datafiles/blender_icons32/icon32_restrict_render_off.dat +++ b/release/datafiles/blender_icons32/icon32_restrict_render_off.dat diff --git a/release/datafiles/blender_icons32/icon32_restrict_render_on.dat b/release/datafiles/blender_icons32/icon32_restrict_render_on.dat Binary files differindex 18184f7fe5f..0d80bea7add 100644 --- a/release/datafiles/blender_icons32/icon32_restrict_render_on.dat +++ b/release/datafiles/blender_icons32/icon32_restrict_render_on.dat diff --git a/release/datafiles/blender_icons32/icon32_restrict_select_off.dat b/release/datafiles/blender_icons32/icon32_restrict_select_off.dat Binary files differindex b7163da17a0..3e009393eac 100644 --- a/release/datafiles/blender_icons32/icon32_restrict_select_off.dat +++ b/release/datafiles/blender_icons32/icon32_restrict_select_off.dat diff --git a/release/datafiles/blender_icons32/icon32_restrict_select_on.dat b/release/datafiles/blender_icons32/icon32_restrict_select_on.dat Binary files differindex a4149dc650d..fd8b8c29064 100644 --- a/release/datafiles/blender_icons32/icon32_restrict_select_on.dat +++ b/release/datafiles/blender_icons32/icon32_restrict_select_on.dat diff --git a/release/datafiles/blender_icons32/icon32_restrict_view_off.dat b/release/datafiles/blender_icons32/icon32_restrict_view_off.dat Binary files differindex df30b2e873f..3737dd34d39 100644 --- a/release/datafiles/blender_icons32/icon32_restrict_view_off.dat +++ b/release/datafiles/blender_icons32/icon32_restrict_view_off.dat diff --git a/release/datafiles/blender_icons32/icon32_restrict_view_on.dat b/release/datafiles/blender_icons32/icon32_restrict_view_on.dat Binary files differindex 02c08a102d2..d85859c3aed 100644 --- a/release/datafiles/blender_icons32/icon32_restrict_view_on.dat +++ b/release/datafiles/blender_icons32/icon32_restrict_view_on.dat diff --git a/release/datafiles/blender_icons32/icon32_sculptmode_hlt.dat b/release/datafiles/blender_icons32/icon32_sculptmode_hlt.dat Binary files differindex 8590aa141c5..e5dfa527311 100644 --- a/release/datafiles/blender_icons32/icon32_sculptmode_hlt.dat +++ b/release/datafiles/blender_icons32/icon32_sculptmode_hlt.dat diff --git a/release/datafiles/blender_icons32/icon32_tpaint_hlt.dat b/release/datafiles/blender_icons32/icon32_tpaint_hlt.dat Binary files differindex b92dec6ef42..cd21f05419c 100644 --- a/release/datafiles/blender_icons32/icon32_tpaint_hlt.dat +++ b/release/datafiles/blender_icons32/icon32_tpaint_hlt.dat diff --git a/release/datafiles/blender_icons32/icon32_uv_data.dat b/release/datafiles/blender_icons32/icon32_uv_data.dat Binary files differindex d7bf1314c0c..9ef062e760e 100644 --- a/release/datafiles/blender_icons32/icon32_uv_data.dat +++ b/release/datafiles/blender_icons32/icon32_uv_data.dat diff --git a/release/datafiles/blender_icons32/icon32_vpaint_hlt.dat b/release/datafiles/blender_icons32/icon32_vpaint_hlt.dat Binary files differindex 71d263c5bc9..cee921a6ba8 100644 --- a/release/datafiles/blender_icons32/icon32_vpaint_hlt.dat +++ b/release/datafiles/blender_icons32/icon32_vpaint_hlt.dat diff --git a/release/datafiles/blender_icons32/icon32_wpaint_hlt.dat b/release/datafiles/blender_icons32/icon32_wpaint_hlt.dat Binary files differindex 9f3bb8421af..0d12a956ef7 100644 --- a/release/datafiles/blender_icons32/icon32_wpaint_hlt.dat +++ b/release/datafiles/blender_icons32/icon32_wpaint_hlt.dat diff --git a/release/datafiles/userdef/userdef_default_theme.c b/release/datafiles/userdef/userdef_default_theme.c index 292080ef629..08f91781aa0 100644 --- a/release/datafiles/userdef/userdef_default_theme.c +++ b/release/datafiles/userdef/userdef_default_theme.c @@ -833,7 +833,7 @@ const bTheme U_theme_default = { .outline_width = 1, .facedot_size = 4, .noodle_curving = 4, - .grid_levels = 7, + .grid_levels = 3, .dash_alpha = 0.5f, .syntaxl = RGBA(0x303030ff), .syntaxs = RGBA(0x973c3cff), diff --git a/release/license/THIRD-PARTY-LICENSES.txt b/release/license/THIRD-PARTY-LICENSES.txt index 933f03b5564..59f53832c9b 100644 --- a/release/license/THIRD-PARTY-LICENSES.txt +++ b/release/license/THIRD-PARTY-LICENSES.txt @@ -2961,6 +2961,8 @@ Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. ** Expat; version 2.2.10 -- https://github.com/libexpat/libexpat/ Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper Copyright (c) 2001-2019 Expat maintainers +** {fmt}; version 8.1.1 -- https://github.com/fmtlib/fmt +Copyright (c) 2012 - present, Victor Zverovich ** JSON for Modern C++; version 3.10.2 -- https://github.com/nlohmann/json/ Copyright (c) 2013-2021 Niels Lohmann ** Libxml2; version 2.9.10 -- http://xmlsoft.org/ diff --git a/release/scripts/modules/bl_i18n_utils/settings.py b/release/scripts/modules/bl_i18n_utils/settings.py index f8975d91f86..ef481a3eb19 100644 --- a/release/scripts/modules/bl_i18n_utils/settings.py +++ b/release/scripts/modules/bl_i18n_utils/settings.py @@ -340,7 +340,10 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = { "y", "y = (Ax + B)", # Sub-strings. + "all", + "all and invert unselected", "and AMD Radeon Pro 21.Q4 driver or newer", + "and NVIDIA driver version 470 or newer", "available with", "brown fox", "can't save image while rendering", @@ -358,6 +361,7 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = { "face data", "gimbal", "global", + "glTF Settings", "image file not found", "image format is read-only", "image path can't be written to", @@ -370,8 +374,12 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = { "multi-res modifier", "non-triangle face", "normal", + "or AMD with macOS 12.3 or newer", "performance impact!", "right", + "selected", + "selected and lock unselected", + "selected and unlock unselected", "the lazy dog", "to the top level of the tree", "unable to load movie clip", @@ -380,6 +388,7 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = { "unknown error reading file", "unknown error stating file", "unknown error writing file", + "unselected", "unsupported font format", "unsupported format", "unsupported image format", diff --git a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py index 144b7d09422..c0e065bf050 100644 --- a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py +++ b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py @@ -104,6 +104,7 @@ class SpellChecker: "builtin", "builtins", "bytecode", "chunksize", + "codebase", "customdata", "dataset", "datasets", "de", @@ -123,6 +124,7 @@ class SpellChecker: "filepath", "filepaths", "forcefield", "forcefields", "framerange", + "frontmost", "fulldome", "fulldomes", "fullscreen", "gamepad", diff --git a/release/scripts/presets/interface_theme/Blender_Light.xml b/release/scripts/presets/interface_theme/Blender_Light.xml index 9a315763c8b..49955bc3ff9 100644 --- a/release/scripts/presets/interface_theme/Blender_Light.xml +++ b/release/scripts/presets/interface_theme/Blender_Light.xml @@ -955,7 +955,7 @@ matte_node="#977474" distor_node="#749797" noodle_curving="4" - grid_levels="7" + grid_levels="3" dash_alpha="0.5" input_node="#cb3d4a" output_node="#cb3d4a" diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index d307c3d0f0a..b626f6a237a 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -4690,7 +4690,7 @@ def _template_paint_radial_control(paint, rotation=False, secondary_rotation=Fal def _template_view3d_select(*, type, value, legacy, select_passthrough, exclude_mod=None): # NOTE: `exclude_mod` is needed since we don't want this tool to exclude Control-RMB actions when this is used # as a tool key-map with RMB-select and `use_fallback_tool_rmb` is enabled. See T92467. - return [( + items = [( "view3d.select", {"type": type, "value": value, **{m: True for m in mods}}, {"properties": [(c, True) for c in props]}, @@ -4706,6 +4706,17 @@ def _template_view3d_select(*, type, value, legacy, select_passthrough, exclude_ (("toggle", "center", "enumerate"), ("shift", "ctrl", "alt")), ) if exclude_mod is None or exclude_mod not in mods] + if select_passthrough and (value == 'PRESS'): + # Add an additional click item to de-select all other items, + # needed so pass-through is able to de-select other items. + items.append(( + "view3d.select", + {"type": type, "value": 'CLICK'}, + {"properties": [("deselect_all", True)]}, + )) + + return items + def _template_view3d_gpencil_select(*, type, value, legacy, use_select_mouse=True): return [ @@ -4723,7 +4734,7 @@ def _template_view3d_gpencil_select(*, type, value, legacy, use_select_mouse=Tru def _template_uv_select(*, type, value, select_passthrough, legacy): - return [ + items = [ ("uv.select", {"type": type, "value": value}, {"properties": [ *((("deselect_all", True),) if not legacy else ()), @@ -4733,6 +4744,17 @@ def _template_uv_select(*, type, value, select_passthrough, legacy): {"properties": [("toggle", True)]}), ] + if select_passthrough and (value == 'PRESS'): + # Add an additional click item to de-select all other items, + # needed so pass-through is able to de-select other items. + items.append(( + "uv.select", + {"type": type, "value": 'CLICK'}, + {"properties": [("deselect_all", True)]}, + )) + + return items + def _template_sequencer_generic_select(*, type, value, legacy): return [( diff --git a/release/scripts/startup/bl_operators/geometry_nodes.py b/release/scripts/startup/bl_operators/geometry_nodes.py index 3616bf52540..c3892e988c5 100644 --- a/release/scripts/startup/bl_operators/geometry_nodes.py +++ b/release/scripts/startup/bl_operators/geometry_nodes.py @@ -26,7 +26,7 @@ def geometry_node_group_empty_new(): def geometry_modifier_poll(context): ob = context.object - # Test object support for geometry node modifier (No hair object support yet) + # Test object support for geometry node modifier (No curves object support yet) if not ob or ob.type not in {'MESH', 'POINTCLOUD', 'VOLUME', 'CURVE', 'FONT'}: return False @@ -50,6 +50,9 @@ class NewGeometryNodesModifier(Operator): if not modifier: return {'CANCELLED'} + group = geometry_node_group_empty_new() + modifier.node_group = group + return {'FINISHED'} diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py index 947a7e5c7a7..481753d5e79 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -361,6 +361,10 @@ class GPENCIL_UL_annotation_layer(UIList): split.prop(gpl, "info", text="", emboss=False) row = layout.row(align=True) + + icon_xray = 'XRAY' if gpl.show_in_front else 'FACESEL' + row.prop(gpl, "show_in_front", text="", icon=icon_xray, emboss=False) + row.prop(gpl, "annotation_hide", text="", emboss=False) elif self.layout_type == 'GRID': layout.alignment = 'CENTER' diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py index 89f840306e1..44c30cf4372 100644 --- a/release/scripts/startup/bl_ui/properties_object.py +++ b/release/scripts/startup/bl_ui/properties_object.py @@ -246,7 +246,7 @@ class OBJECT_PT_instancing(ObjectButtonsPanel, Panel): def poll(cls, context): ob = context.object # FONT objects need (vertex) instancing for the 'Object Font' feature - return (ob.type in {'MESH', 'EMPTY', 'POINTCLOUD', 'FONT'}) + return (ob.type in {'MESH', 'EMPTY', 'FONT'}) def draw(self, context): layout = self.layout diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py index 0e8e452c717..f8dea120db3 100644 --- a/release/scripts/startup/bl_ui/properties_physics_fluid.py +++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py @@ -55,7 +55,7 @@ class PhysicButtonsPanel: md = context.fluid if md and (md.fluid_type == 'DOMAIN'): domain = md.domain_settings - return domain.domain_type in {'GAS'} + return domain.domain_type == 'GAS' return False @staticmethod @@ -66,7 +66,7 @@ class PhysicButtonsPanel: md = context.fluid if md and (md.fluid_type == 'DOMAIN'): domain = md.domain_settings - return domain.domain_type in {'LIQUID'} + return domain.domain_type == 'LIQUID' return False @staticmethod @@ -812,7 +812,7 @@ class PHYSICS_PT_mesh(PhysicButtonsPanel, Panel): col.separator() col.prop(domain, "mesh_generator", text="Mesh Generator") - if domain.mesh_generator in {'IMPROVED'}: + if domain.mesh_generator == 'IMPROVED': col = flow.column(align=True) col.prop(domain, "mesh_smoothen_pos", text="Smoothing Positive") col.prop(domain, "mesh_smoothen_neg", text="Negative") @@ -1227,7 +1227,7 @@ class PHYSICS_PT_cache(PhysicButtonsPanel, Panel): row.enabled = not is_baking_any and not has_baked_data row.prop(domain, "cache_data_format", text="Format Volumes") - if md.domain_settings.domain_type in {'LIQUID'} and domain.use_mesh: + if md.domain_settings.domain_type == 'LIQUID' and domain.use_mesh: row = col.row() row.enabled = not is_baking_any and not has_baked_mesh row.prop(domain, "cache_mesh_format", text="Meshes") diff --git a/release/scripts/startup/bl_ui/properties_view_layer.py b/release/scripts/startup/bl_ui/properties_view_layer.py index 4dee7b73faf..83e797583ad 100644 --- a/release/scripts/startup/bl_ui/properties_view_layer.py +++ b/release/scripts/startup/bl_ui/properties_view_layer.py @@ -187,6 +187,33 @@ class VIEWLAYER_PT_layer_passes_cryptomatte(ViewLayerCryptomattePanel, Panel): COMPAT_ENGINES = {'BLENDER_EEVEE'} +class ViewLayerLightgroupsPanel(ViewLayerButtonsPanel, Panel): + bl_label = "Light Groups" + + def draw(self, context): + layout = self.layout + + layout.use_property_split = True + layout.use_property_decorate = False + + view_layer = context.view_layer + + row = layout.row() + col = row.column() + col.template_list("UI_UL_list", "lightgroups", view_layer, + "lightgroups", view_layer, "active_lightgroup_index", rows=2) + + col = row.column() + sub = col.column(align=True) + sub.operator("scene.view_layer_add_lightgroup", icon='ADD', text="") + sub.operator("scene.view_layer_remove_lightgroup", icon='REMOVE', text="") + + +class VIEWLAYER_PT_layer_passes_lightgroups(ViewLayerLightgroupsPanel): + bl_parent_id = "VIEWLAYER_PT_layer_passes" + COMPAT_ENGINES = {'CYCLES'} + + classes = ( VIEWLAYER_PT_layer, VIEWLAYER_PT_layer_passes, @@ -195,6 +222,7 @@ classes = ( VIEWLAYER_PT_eevee_layer_passes_effects, VIEWLAYER_PT_layer_passes_cryptomatte, VIEWLAYER_PT_layer_passes_aov, + VIEWLAYER_PT_layer_passes_lightgroups, VIEWLAYER_UL_aov, ) diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py index bbe165b9286..eff8ad8e8b3 100644 --- a/release/scripts/startup/bl_ui/space_outliner.py +++ b/release/scripts/startup/bl_ui/space_outliner.py @@ -22,6 +22,8 @@ class OUTLINER_HT_header(Header): if display_mode == 'DATA_API': OUTLINER_MT_editor_menus.draw_collapsible(context, layout) + if display_mode == 'LIBRARY_OVERRIDES': + layout.prop(space, "lib_override_view_mode", text="") layout.separator_spacer() @@ -41,7 +43,11 @@ class OUTLINER_HT_header(Header): text="", icon='FILTER', ) - if display_mode in {'LIBRARIES', 'LIBRARY_OVERRIDES', 'ORPHAN_DATA'}: + if display_mode == 'LIBRARY_OVERRIDES' and space.lib_override_view_mode == 'HIERARCHIES': + # Don't add ID type filter for library overrides hierarchies mode. Point of it is to see a hierarchy that is + # usually constructed out of different ID types. + pass + elif display_mode in {'LIBRARIES', 'LIBRARY_OVERRIDES', 'ORPHAN_DATA'}: row.prop(space, "use_filter_id_type", text="", icon='FILTER') sub = row.row(align=True) sub.active = space.use_filter_id_type @@ -351,7 +357,7 @@ class OUTLINER_PT_filter(Panel): col = layout.column(align=True) col.prop(space, "use_sort_alpha") - if display_mode not in {'LIBRARY_OVERRIDES'}: + if display_mode != 'LIBRARY_OVERRIDES': row = layout.row(align=True) row.prop(space, "use_sync_select", text="Sync Selection") @@ -364,13 +370,13 @@ class OUTLINER_PT_filter(Panel): col.prop(space, "use_filter_complete", text="Exact Match") col.prop(space, "use_filter_case_sensitive", text="Case Sensitive") - if display_mode in {'LIBRARY_OVERRIDES'} and bpy.data.libraries: + if display_mode == 'LIBRARY_OVERRIDES' and space.lib_override_view_mode == 'PROPERTIES' and bpy.data.libraries: col.separator() row = col.row() row.label(icon='LIBRARY_DATA_OVERRIDE') row.prop(space, "use_filter_lib_override_system", text="System Overrides") - if display_mode not in {'VIEW_LAYER'}: + if display_mode != 'VIEW_LAYER': return layout.separator() diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py index 3355b30dd61..0a428b4ea3f 100644 --- a/release/scripts/startup/bl_ui/space_topbar.py +++ b/release/scripts/startup/bl_ui/space_topbar.py @@ -464,7 +464,6 @@ class TOPBAR_MT_file_export(Menu): bl_owner_use_filter = False def draw(self, _context): - self.layout.operator("wm.obj_export", text="Wavefront OBJ (.obj)") if bpy.app.build_options.collada: self.layout.operator("wm.collada_export", text="Collada (.dae)") if bpy.app.build_options.alembic: @@ -480,6 +479,8 @@ class TOPBAR_MT_file_export(Menu): if bpy.app.build_options.haru: self.layout.operator("wm.gpencil_export_pdf", text="Grease Pencil as PDF") + self.layout.operator("wm.obj_export", text="Wavefront (.obj) (experimental)") + class TOPBAR_MT_file_external_data(Menu): bl_label = "External Data" diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index f40d96e30a0..a0336f7e7bf 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -514,6 +514,10 @@ class _draw_tool_settings_context_mode: layout.prop(tool_settings.curves_sculpt, "interpolate_length") layout.prop(tool_settings.curves_sculpt, "interpolate_shape") + if brush.curves_sculpt_tool == 'SNAKE_HOOK': + layout.prop(brush, "falloff_shape", expand=True) + layout.prop(brush, "curve_preset") + if brush.curves_sculpt_tool == 'TEST1': layout.prop(tool_settings.curves_sculpt, "distance") @@ -2636,6 +2640,8 @@ class VIEW3D_MT_object_apply(Menu): def draw(self, _context): layout = self.layout + # Need invoke for the popup confirming the multi-user data operation + layout.operator_context = 'INVOKE_DEFAULT' props = layout.operator("object.transform_apply", text="Location", text_ctxt=i18n_contexts.default) props.location, props.rotation, props.scale = True, False, False @@ -2859,6 +2865,9 @@ class VIEW3D_MT_object_convert(Menu): if bpy.app.build_options.potrace: layout.operator("gpencil.trace_image", icon='OUTLINER_OB_GREASEPENCIL') + if ob and ob.type == 'CURVES': + layout.operator("curves.convert_to_particle_system", text="Particle System") + class VIEW3D_MT_make_links(Menu): bl_label = "Link/Transfer Data" @@ -5297,7 +5306,7 @@ class VIEW3D_MT_pivot_pie(Menu): pie.prop_enum(context.scene.tool_settings, "transform_pivot_point", value='ACTIVE_ELEMENT') if (obj is None) or (mode in {'OBJECT', 'POSE', 'WEIGHT_PAINT'}): pie.prop(context.scene.tool_settings, "use_transform_pivot_point_align") - if mode in {'EDIT_GPENCIL'}: + if mode == 'EDIT_GPENCIL': pie.prop(context.scene.tool_settings.gpencil_sculpt, "use_scale_thickness") diff --git a/release/scripts/templates_py/ui_list.py b/release/scripts/templates_py/ui_list.py index f6b82356a78..9727a1b3678 100644 --- a/release/scripts/templates_py/ui_list.py +++ b/release/scripts/templates_py/ui_list.py @@ -18,7 +18,7 @@ class MESH_UL_mylist(bpy.types.UIList): if self.layout_type in {'DEFAULT', 'COMPACT'}: pass # 'GRID' layout type should be as compact as possible (typically a single icon!). - elif self.layout_type in {'GRID'}: + elif self.layout_type == 'GRID': pass # Called once to draw filtering/reordering options. diff --git a/release/scripts/templates_py/ui_list_simple.py b/release/scripts/templates_py/ui_list_simple.py index ac3f2b984de..c3efe16058a 100644 --- a/release/scripts/templates_py/ui_list_simple.py +++ b/release/scripts/templates_py/ui_list_simple.py @@ -29,7 +29,7 @@ class MATERIAL_UL_matslots_example(bpy.types.UIList): else: layout.label(text="", translate=False, icon_value=icon) # 'GRID' layout type should be as compact as possible (typically a single icon!). - elif self.layout_type in {'GRID'}: + elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.label(text="", icon_value=icon) diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 1639a564508..604c8cb7a06 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -25,7 +25,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 6 +#define BLENDER_FILE_SUBVERSION 8 /* 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/BKE_cachefile.h b/source/blender/blenkernel/BKE_cachefile.h index 425207398a0..41a0ad3f763 100644 --- a/source/blender/blenkernel/BKE_cachefile.h +++ b/source/blender/blenkernel/BKE_cachefile.h @@ -51,8 +51,7 @@ void BKE_cachefile_reader_free(struct CacheFile *cache_file, struct CacheReader * load the data directly if they support it. */ bool BKE_cache_file_uses_render_procedural(const struct CacheFile *cache_file, - struct Scene *scene, - int dag_eval_mode); + struct Scene *scene); /* Add a layer to the cache_file. Return NULL if the filename is already that of an existing layer * or if the number of layers exceeds the maximum allowed layer count. */ diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h index 7f4360d2e9c..a3bbcc8687a 100644 --- a/source/blender/blenkernel/BKE_collection.h +++ b/source/blender/blenkernel/BKE_collection.h @@ -346,6 +346,20 @@ void BKE_scene_objects_iterator_begin(struct BLI_Iterator *iter, void *data_in); void BKE_scene_objects_iterator_next(struct BLI_Iterator *iter); void BKE_scene_objects_iterator_end(struct BLI_Iterator *iter); +/** Iterate over objects in the scene based on a flag. + * + * \note The object->flag is tested against flag. + * */ +typedef struct SceneObjectsIteratorExData { + struct Scene *scene; + int flag; + void *iter_data; +} SceneObjectsIteratorExData; + +void BKE_scene_objects_iterator_begin_ex(struct BLI_Iterator *iter, void *data_in); +void BKE_scene_objects_iterator_next_ex(struct BLI_Iterator *iter); +void BKE_scene_objects_iterator_end_ex(struct BLI_Iterator *iter); + /** * Generate a new #GSet (or extend given `objects_gset` if not NULL) with all objects referenced by * all collections of given `scene`. diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh index 82f77d83bec..f097acc497f 100644 --- a/source/blender/blenkernel/BKE_curves.hh +++ b/source/blender/blenkernel/BKE_curves.hh @@ -77,6 +77,15 @@ class CurvesGeometryRuntime { mutable std::mutex position_cache_mutex; mutable bool position_cache_dirty = true; + /** + * Cache of lengths along each evaluated curve for for each evaluated point. If a curve is + * cyclic, it needs one more length value to correspond to the last segment, so in order to + * make slicing this array for a curve fast, an extra float is stored for every curve. + */ + mutable Vector<float> evaluated_length_cache; + mutable std::mutex length_cache_mutex; + mutable bool length_cache_dirty = true; + /** Direction of the spline at each evaluated point. */ mutable Vector<float3> evaluated_tangents_cache; mutable std::mutex tangent_cache_mutex; @@ -264,9 +273,30 @@ class CurvesGeometry : public ::CurvesGeometry { /** Makes sure the data described by #evaluated_offsets if necessary. */ void ensure_evaluated_offsets() const; + /** + * Retrieve offsets into a Bezier curve's evaluated points for each control point. + * Call #ensure_evaluated_offsets() first to ensure that the evaluated offsets cache is current. + */ + Span<int> bezier_evaluated_offsets_for_curve(int curve_index) const; + Span<float3> evaluated_positions() const; /** + * Return a cache of accumulated lengths along the curve. Each item is the length of the + * subsequent segment (the first value is the length of the first segment rather than 0). + * This calculation is rather trivial, and only depends on the evaluated positions, but + * the results are used often, and it is necessarily single threaded per curve, so it is cached. + * + * \param cyclic: This argument is redundant with the data stored for the curve, + * but is passed for performance reasons to avoid looking up the attribute. + */ + Span<float> evaluated_lengths_for_curve(int curve_index, bool cyclic) const; + float evaluated_length_total_for_curve(int curve_index, bool cyclic) const; + + /** Calculates the data described by #evaluated_lengths_for_curve if necessary. */ + void ensure_evaluated_lengths() const; + + /** * Evaluate a generic data to the standard evaluated points of a specific curve, * defined by the resolution attribute or other factors, depending on the curve type. * @@ -281,6 +311,9 @@ class CurvesGeometry : public ::CurvesGeometry { */ void ensure_nurbs_basis_cache() const; + /** Return the slice of #evaluated_length_cache that corresponds to this curve index. */ + IndexRange lengths_range_for_curve(int curve_index, bool cyclic) const; + /* -------------------------------------------------------------------- * Operations. */ @@ -305,6 +338,8 @@ class CurvesGeometry : public ::CurvesGeometry { void translate(const float3 &translation); void transform(const float4x4 &matrix); + void calculate_bezier_auto_handles(); + void update_customdata_pointers(); void remove_curves(IndexMask curves_to_delete); @@ -325,13 +360,12 @@ class CurvesGeometry : public ::CurvesGeometry { namespace curves { /** - * The number of segments between control points, accounting for the last segment of cyclic curves, - * and the fact that curves with two points cannot be cyclic. The logic is simple, but this - * function should be used to make intentions clearer. + * The number of segments between control points, accounting for the last segment of cyclic + * curves. The logic is simple, but this function should be used to make intentions clearer. */ inline int curve_segment_size(const int points_num, const bool cyclic) { - return (cyclic && points_num > 2) ? points_num : points_num - 1; + return cyclic ? points_num : points_num - 1; } namespace bezier { @@ -365,9 +399,37 @@ void calculate_evaluated_offsets(Span<int8_t> handle_types_left, MutableSpan<int> evaluated_offsets); /** + * Recalculate all auto (#BEZIER_HANDLE_AUTO) and vector (#BEZIER_HANDLE_VECTOR) handles with + * positions automatically derived from the neighboring control points, and update aligned + * (#BEZIER_HANDLE_ALIGN) handles to line up with neighboring non-aligned handles. The choices + * made here are relatively arbitrary, but having standardized behavior is essential. + */ +void calculate_auto_handles(bool cyclic, + Span<int8_t> types_left, + Span<int8_t> types_right, + Span<float3> positions, + MutableSpan<float3> positions_left, + MutableSpan<float3> positions_right); + +/** + * Change the handles of a single control point, aligning any aligned (#BEZIER_HANDLE_ALIGN) + * handles on the other side of the control point. + * + * \note This ignores the inputs if the handle types are automatically calculated, + * so the types should be updated before-hand to be editable. + */ +void set_handle_position(const float3 &position, + HandleType type, + HandleType type_other, + const float3 &new_handle, + float3 &handle, + float3 &handle_other); + +/** * Evaluate a cubic Bezier segment, using the "forward differencing" method. - * A generic Bezier curve is made up by four points, but in many cases the first and last points - * are referred to as the control points, and the middle points are the corresponding handles. + * A generic Bezier curve is made up by four points, but in many cases the first and last + * points are referred to as the control points, and the middle points are the corresponding + * handles. */ void evaluate_segment(const float3 &point_0, const float3 &point_1, diff --git a/source/blender/blenkernel/BKE_geometry_fields.hh b/source/blender/blenkernel/BKE_geometry_fields.hh new file mode 100644 index 00000000000..36b382feb5f --- /dev/null +++ b/source/blender/blenkernel/BKE_geometry_fields.hh @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +/** \file + * \ingroup bke + * + * Common field utilities and field definitions for geometry components. + */ + +#include "BKE_geometry_set.hh" + +#include "FN_field.hh" + +namespace blender::bke { + +class GeometryComponentFieldContext : public fn::FieldContext { + private: + const GeometryComponent &component_; + const AttributeDomain domain_; + + public: + GeometryComponentFieldContext(const GeometryComponent &component, const AttributeDomain domain) + : component_(component), domain_(domain) + { + } + + const GeometryComponent &geometry_component() const + { + return component_; + } + + AttributeDomain domain() const + { + return domain_; + } +}; + +class GeometryFieldInput : public fn::FieldInput { + public: + using fn::FieldInput::FieldInput; + + GVArray get_varray_for_context(const fn::FieldContext &context, + IndexMask mask, + ResourceScope &scope) const override; + + virtual GVArray get_varray_for_context(const GeometryComponent &component, + AttributeDomain domain, + IndexMask mask) const = 0; +}; + +class AttributeFieldInput : public GeometryFieldInput { + private: + std::string name_; + + public: + AttributeFieldInput(std::string name, const CPPType &type) + : GeometryFieldInput(type, name), name_(std::move(name)) + { + category_ = Category::NamedAttribute; + } + + template<typename T> static fn::Field<T> Create(std::string name) + { + const CPPType &type = CPPType::get<T>(); + auto field_input = std::make_shared<AttributeFieldInput>(std::move(name), type); + return fn::Field<T>{field_input}; + } + + StringRefNull attribute_name() const + { + return name_; + } + + GVArray get_varray_for_context(const GeometryComponent &component, + AttributeDomain domain, + IndexMask mask) const override; + + std::string socket_inspection_name() const override; + + uint64_t hash() const override; + bool is_equal_to(const fn::FieldNode &other) const override; +}; + +class IDAttributeFieldInput : public GeometryFieldInput { + public: + IDAttributeFieldInput() : GeometryFieldInput(CPPType::get<int>()) + { + category_ = Category::Generated; + } + + GVArray get_varray_for_context(const GeometryComponent &component, + AttributeDomain domain, + IndexMask mask) const override; + + std::string socket_inspection_name() const override; + + uint64_t hash() const override; + bool is_equal_to(const fn::FieldNode &other) const override; +}; + +VArray<float3> curve_normals_varray(const CurveComponent &component, const AttributeDomain domain); + +VArray<float3> mesh_normals_varray(const MeshComponent &mesh_component, + const Mesh &mesh, + const IndexMask mask, + const AttributeDomain domain); + +class NormalFieldInput : public GeometryFieldInput { + public: + NormalFieldInput() : GeometryFieldInput(CPPType::get<float3>()) + { + category_ = Category::Generated; + } + + GVArray get_varray_for_context(const GeometryComponent &component, + const AttributeDomain domain, + IndexMask mask) const override; + + std::string socket_inspection_name() const override; + + uint64_t hash() const override; + bool is_equal_to(const fn::FieldNode &other) const override; +}; + +class AnonymousAttributeFieldInput : public GeometryFieldInput { + private: + /** + * A strong reference is required to make sure that the referenced attribute is not removed + * automatically. + */ + StrongAnonymousAttributeID anonymous_id_; + std::string producer_name_; + + public: + AnonymousAttributeFieldInput(StrongAnonymousAttributeID anonymous_id, + const CPPType &type, + std::string producer_name) + : GeometryFieldInput(type, anonymous_id.debug_name()), + anonymous_id_(std::move(anonymous_id)), + producer_name_(producer_name) + { + category_ = Category::AnonymousAttribute; + } + + template<typename T> + static fn::Field<T> Create(StrongAnonymousAttributeID anonymous_id, std::string producer_name) + { + const CPPType &type = CPPType::get<T>(); + auto field_input = std::make_shared<AnonymousAttributeFieldInput>( + std::move(anonymous_id), type, std::move(producer_name)); + return fn::Field<T>{field_input}; + } + + GVArray get_varray_for_context(const GeometryComponent &component, + AttributeDomain domain, + IndexMask mask) const override; + + std::string socket_inspection_name() const override; + + uint64_t hash() const override; + bool is_equal_to(const fn::FieldNode &other) const override; +}; + +} // namespace blender::bke diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh index bd392057436..559007d1aee 100644 --- a/source/blender/blenkernel/BKE_geometry_set.hh +++ b/source/blender/blenkernel/BKE_geometry_set.hh @@ -22,8 +22,6 @@ #include "BKE_attribute_access.hh" #include "BKE_geometry_set.h" -#include "FN_field.hh" - struct Curves; struct Collection; struct Curve; @@ -1019,155 +1017,3 @@ class VolumeComponent : public GeometryComponent { static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_VOLUME; }; - -namespace blender::bke { - -class GeometryComponentFieldContext : public fn::FieldContext { - private: - const GeometryComponent &component_; - const AttributeDomain domain_; - - public: - GeometryComponentFieldContext(const GeometryComponent &component, const AttributeDomain domain) - : component_(component), domain_(domain) - { - } - - const GeometryComponent &geometry_component() const - { - return component_; - } - - AttributeDomain domain() const - { - return domain_; - } -}; - -class GeometryFieldInput : public fn::FieldInput { - public: - using fn::FieldInput::FieldInput; - - GVArray get_varray_for_context(const fn::FieldContext &context, - IndexMask mask, - ResourceScope &scope) const override; - - virtual GVArray get_varray_for_context(const GeometryComponent &component, - AttributeDomain domain, - IndexMask mask) const = 0; -}; - -class AttributeFieldInput : public GeometryFieldInput { - private: - std::string name_; - - public: - AttributeFieldInput(std::string name, const CPPType &type) - : GeometryFieldInput(type, name), name_(std::move(name)) - { - category_ = Category::NamedAttribute; - } - - template<typename T> static fn::Field<T> Create(std::string name) - { - const CPPType &type = CPPType::get<T>(); - auto field_input = std::make_shared<AttributeFieldInput>(std::move(name), type); - return fn::Field<T>{field_input}; - } - - StringRefNull attribute_name() const - { - return name_; - } - - GVArray get_varray_for_context(const GeometryComponent &component, - AttributeDomain domain, - IndexMask mask) const override; - - std::string socket_inspection_name() const override; - - uint64_t hash() const override; - bool is_equal_to(const fn::FieldNode &other) const override; -}; - -class IDAttributeFieldInput : public GeometryFieldInput { - public: - IDAttributeFieldInput() : GeometryFieldInput(CPPType::get<int>()) - { - category_ = Category::Generated; - } - - GVArray get_varray_for_context(const GeometryComponent &component, - AttributeDomain domain, - IndexMask mask) const override; - - std::string socket_inspection_name() const override; - - uint64_t hash() const override; - bool is_equal_to(const fn::FieldNode &other) const override; -}; - -VArray<float3> curve_normals_varray(const CurveComponent &component, const AttributeDomain domain); - -VArray<float3> mesh_normals_varray(const MeshComponent &mesh_component, - const Mesh &mesh, - const IndexMask mask, - const AttributeDomain domain); - -class NormalFieldInput : public GeometryFieldInput { - public: - NormalFieldInput() : GeometryFieldInput(CPPType::get<float3>()) - { - category_ = Category::Generated; - } - - GVArray get_varray_for_context(const GeometryComponent &component, - const AttributeDomain domain, - IndexMask mask) const override; - - std::string socket_inspection_name() const override; - - uint64_t hash() const override; - bool is_equal_to(const fn::FieldNode &other) const override; -}; - -class AnonymousAttributeFieldInput : public GeometryFieldInput { - private: - /** - * A strong reference is required to make sure that the referenced attribute is not removed - * automatically. - */ - StrongAnonymousAttributeID anonymous_id_; - std::string producer_name_; - - public: - AnonymousAttributeFieldInput(StrongAnonymousAttributeID anonymous_id, - const CPPType &type, - std::string producer_name) - : GeometryFieldInput(type, anonymous_id.debug_name()), - anonymous_id_(std::move(anonymous_id)), - producer_name_(producer_name) - { - category_ = Category::AnonymousAttribute; - } - - template<typename T> - static fn::Field<T> Create(StrongAnonymousAttributeID anonymous_id, std::string producer_name) - { - const CPPType &type = CPPType::get<T>(); - auto field_input = std::make_shared<AnonymousAttributeFieldInput>( - std::move(anonymous_id), type, std::move(producer_name)); - return fn::Field<T>{field_input}; - } - - GVArray get_varray_for_context(const GeometryComponent &component, - AttributeDomain domain, - IndexMask mask) const override; - - std::string socket_inspection_name() const override; - - uint64_t hash() const override; - bool is_equal_to(const fn::FieldNode &other) const override; -}; - -} // namespace blender::bke diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h index 77a3223c064..4a3917dafee 100644 --- a/source/blender/blenkernel/BKE_layer.h +++ b/source/blender/blenkernel/BKE_layer.h @@ -8,6 +8,7 @@ #include "BKE_collection.h" +#include "DNA_layer_types.h" #include "DNA_listBase.h" #ifdef __cplusplus @@ -436,15 +437,26 @@ void BKE_view_layer_visible_bases_iterator_end(BLI_Iterator *iter); IteratorBeginCb func_begin; \ IteratorCb func_next, func_end; \ void *data_in; \ - struct ObjectsVisibleIteratorData data_ = {NULL}; \ - data_.view_layer = _view_layer; \ - data_.v3d = _v3d; \ +\ + struct ObjectsVisibleIteratorData data_select_ = {NULL}; \ + data_select_.view_layer = _view_layer; \ + data_select_.v3d = _v3d; \ +\ + struct SceneObjectsIteratorExData data_flag_ = {NULL}; \ + data_flag_.scene = scene; \ + data_flag_.flag = flag; \ \ if (flag == SELECT) { \ func_begin = &BKE_view_layer_selected_objects_iterator_begin; \ func_next = &BKE_view_layer_selected_objects_iterator_next; \ func_end = &BKE_view_layer_selected_objects_iterator_end; \ - data_in = &data_; \ + data_in = &data_select_; \ + } \ + else if (flag != 0) { \ + func_begin = BKE_scene_objects_iterator_begin_ex; \ + func_next = BKE_scene_objects_iterator_next_ex; \ + func_end = BKE_scene_objects_iterator_end_ex; \ + data_in = &data_flag_; \ } \ else { \ func_begin = BKE_scene_objects_iterator_begin; \ @@ -570,6 +582,21 @@ bool BKE_view_layer_has_valid_aov(struct ViewLayer *view_layer); struct ViewLayer *BKE_view_layer_find_with_aov(struct Scene *scene, struct ViewLayerAOV *view_layer_aov); +struct ViewLayerLightgroup *BKE_view_layer_add_lightgroup(struct ViewLayer *view_layer); +void BKE_view_layer_remove_lightgroup(struct ViewLayer *view_layer, + struct ViewLayerLightgroup *lightgroup); +void BKE_view_layer_set_active_lightgroup(struct ViewLayer *view_layer, + struct ViewLayerLightgroup *lightgroup); +struct ViewLayer *BKE_view_layer_find_with_lightgroup( + struct Scene *scene, struct ViewLayerLightgroup *view_layer_lightgroup); +void BKE_view_layer_rename_lightgroup(ViewLayer *view_layer, + ViewLayerLightgroup *lightgroup, + const char *name); + +void BKE_lightgroup_membership_get(struct LightgroupMembership *lgm, char *value); +int BKE_lightgroup_membership_length(struct LightgroupMembership *lgm); +void BKE_lightgroup_membership_set(struct LightgroupMembership **lgm, const char *value); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h index 040be8d1280..504ab47c1c5 100644 --- a/source/blender/blenkernel/BKE_lib_id.h +++ b/source/blender/blenkernel/BKE_lib_id.h @@ -515,7 +515,7 @@ void BKE_main_id_flag_listbase(struct ListBase *lb, int flag, bool value); void BKE_main_id_flag_all(struct Main *bmain, int flag, bool value); /** - * Next to indirect usage in `readfile.c/writefile.c` also in `editobject.c`, `scene.c`. + * Next to indirect usage in `readfile.c/writefile.c` also in `editobject.c`, `scene.cc`. */ void BKE_main_id_newptr_and_tag_clear(struct Main *bmain); @@ -594,6 +594,17 @@ bool BKE_id_is_in_global_main(struct ID *id); bool BKE_id_can_be_asset(const struct ID *id); +/** Check if that ID can be considered as editable from a high-level (editor) perspective. + * + * NOTE: This used to be done with a check on whether ID was linked or not, but now with system + * overrides this is not enough anymore. + * + * NOTE: Execution of this function can be somewhat expensive currently. If this becomes an issue, + * we should either cache that status info also in virtual override IDs, or address the + * long-standing TODO of getting an efficient 'owner_id' access for all embedded ID types. + */ +bool BKE_id_is_editable(struct Main *bmain, struct ID *id); + /** * Returns ordered list of data-blocks for display in the UI. * Result is list of #LinkData of IDs that must be freed. diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h index 98301ca7a70..dfb2b900b10 100644 --- a/source/blender/blenkernel/BKE_lib_override.h +++ b/source/blender/blenkernel/BKE_lib_override.h @@ -65,6 +65,19 @@ void BKE_lib_override_library_free(struct IDOverrideLibrary **override, bool do_ bool BKE_lib_override_library_is_user_edited(struct ID *id); /** + * Check if given ID is a system override. + */ +bool BKE_lib_override_library_is_system_defined(struct Main *bmain, struct ID *id); + +/** + * Check if given ID is a leaf in its liboverride hierarchy (i.e. if it does not use any other + * override ID). + * + * NOTE: Embedded IDs of override IDs are not considered as leaves. + */ +bool BKE_lib_override_library_is_hierarchy_leaf(struct Main *bmain, struct ID *id); + +/** * Create an overridden local copy of linked reference. * * \note This function is very basic, low-level. It does not consider any hierarchical dependency, @@ -369,12 +382,22 @@ bool BKE_lib_override_library_main_operations_create(struct Main *bmain, bool fo /** * Reset all overrides in given \a id_root, while preserving ID relations. + * + * \param do_reset_system_override: If \a true, reset the given ID as a system override one (i.e. + * non-editable). */ -void BKE_lib_override_library_id_reset(struct Main *bmain, struct ID *id_root); +void BKE_lib_override_library_id_reset(struct Main *bmain, + struct ID *id_root, + bool do_reset_system_override); /** * Reset all overrides in given \a id_root and its dependencies, while preserving ID relations. + * + * \param do_reset_system_override: If \a true, reset the given ID and all of its descendants in + * the override hierarchy as system override ones (i.e. non-editable). */ -void BKE_lib_override_library_id_hierarchy_reset(struct Main *bmain, struct ID *id_root); +void BKE_lib_override_library_id_hierarchy_reset(struct Main *bmain, + struct ID *id_root, + bool do_reset_system_override); /** * Set or clear given tag in all operations in that override property data. diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 0ba9713b96d..1ad20c52a4b 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -571,7 +571,7 @@ typedef struct MLoopNorSpaceArray { struct LinkNode *loops_pool; /* Allocated once, avoids to call BLI_linklist_prepend_arena() for each loop! */ char data_type; /* Whether we store loop indices, or pointers to BMLoop. */ - int num_spaces; /* Number of clnors spaces defined in this array. */ + int spaces_num; /* Number of clnors spaces defined in this array. */ struct MemArena *mem; } MLoopNorSpaceArray; /** diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index acdca23b21c..41a02545591 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -301,10 +301,8 @@ typedef struct ModifierTypeInfo { * changes. * * This function is optional (assumes false if not present). - * - * The dag_eval_mode should be of type eEvaluationMode. */ - bool (*dependsOnTime)(struct Scene *scene, struct ModifierData *md, int dag_eval_mode); + bool (*dependsOnTime)(struct Scene *scene, struct ModifierData *md); /** * True when a deform modifier uses normals, the requiredDataMask @@ -421,7 +419,7 @@ void BKE_modifier_copydata(const struct ModifierData *md, struct ModifierData *t void BKE_modifier_copydata_ex(const struct ModifierData *md, struct ModifierData *target, int flag); -bool BKE_modifier_depends_ontime(struct Scene *scene, struct ModifierData *md, int dag_eval_mode); +bool BKE_modifier_depends_ontime(struct Scene *scene, struct ModifierData *md); bool BKE_modifier_supports_mapping(struct ModifierData *md); bool BKE_modifier_supports_cage(struct Scene *scene, struct ModifierData *md); bool BKE_modifier_couldbe_cage(struct Scene *scene, struct ModifierData *md); diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 17d90e64459..a90b9b12030 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -163,9 +163,12 @@ int BKE_object_visibility(const struct Object *ob, int dag_eval_mode); /** * More general add: creates minimum required data, but without vertices etc. + * + * \param bmain: The main to add the object to. May be null for #LIB_ID_CREATE_NO_MAIN behavior. */ -struct Object *BKE_object_add_only_object(struct Main *bmain, int type, const char *name) - ATTR_NONNULL(1) ATTR_RETURNS_NONNULL; +struct Object *BKE_object_add_only_object(struct Main *bmain, + int type, + const char *name) ATTR_RETURNS_NONNULL; /** * General add: to scene, with layer from area and default name. * @@ -334,7 +337,7 @@ void BKE_boundbox_minmax(const struct BoundBox *bb, float r_min[3], float r_max[3]); -struct BoundBox *BKE_object_boundbox_get(struct Object *ob); +const struct BoundBox *BKE_object_boundbox_get(struct Object *ob); void BKE_object_dimensions_get(struct Object *ob, float r_vec[3]); /** * The original scale and object matrix can be passed in so any difference @@ -352,10 +355,7 @@ void BKE_object_dimensions_set_ex(struct Object *ob, void BKE_object_dimensions_set(struct Object *ob, const float value[3], int axis_mask); void BKE_object_empty_draw_type_set(struct Object *ob, int value); -/** - * Use this to temporally disable/enable bound-box. - */ -void BKE_object_boundbox_flag(struct Object *ob, int flag, bool set); + void BKE_object_boundbox_calc_from_mesh(struct Object *ob, const struct Mesh *me_eval); bool BKE_object_boundbox_calc_from_evaluated_geometry(struct Object *ob); void BKE_object_minmax(struct Object *ob, float r_min[3], float r_max[3], bool use_hidden); @@ -618,10 +618,7 @@ void BKE_object_groups_clear(struct Main *bmain, struct Scene *scene, struct Obj */ struct KDTree_3d *BKE_object_as_kdtree(struct Object *ob, int *r_tot); -bool BKE_object_modifier_use_time(struct Scene *scene, - struct Object *ob, - struct ModifierData *md, - int dag_eval_mode); +bool BKE_object_modifier_use_time(struct Scene *scene, struct Object *ob, struct ModifierData *md); /** * \note this function should eventually be replaced by depsgraph functionality. diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 8f7ef035557..3be1c4b1278 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -247,7 +247,7 @@ set(SRC intern/preferences.c intern/report.c intern/rigidbody.c - intern/scene.c + intern/scene.cc intern/screen.c intern/shader_fx.c intern/shrinkwrap.c @@ -370,6 +370,7 @@ set(SRC BKE_fcurve_driver.h BKE_fluid.h BKE_freestyle.h + BKE_geometry_fields.hh BKE_geometry_set.h BKE_geometry_set.hh BKE_geometry_set_instances.hh @@ -599,10 +600,6 @@ if(WITH_IMAGE_CINEON) add_definitions(-DWITH_CINEON) endif() -if(WITH_IMAGE_FRAMESERVER) - add_definitions(-DWITH_FRAMESERVER) -endif() - if(WITH_IMAGE_HDR) add_definitions(-DWITH_HDR) endif() diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index 8fbab8dde25..d0420b4170a 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -6,6 +6,7 @@ #include "BKE_attribute_math.hh" #include "BKE_customdata.h" #include "BKE_deform.h" +#include "BKE_geometry_fields.hh" #include "BKE_geometry_set.hh" #include "BKE_mesh.h" #include "BKE_pointcloud.h" diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index c32081b5d1c..70c3dc2de39 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -352,7 +352,7 @@ static void setup_app_data(bContext *C, do_versions_ipos_to_animato(bmain); } - /* NOTE: readfile's `do_version` does not allow to create new IDs, and only operates on a single + /* NOTE: readfile's `do_versions` does not allow to create new IDs, and only operates on a single * library at a time. This code needs to operate on the whole Main at once. */ /* NOTE: Check bmain version (i.e. current blend file version), AND the versions of all the * linked libraries. */ diff --git a/source/blender/blenkernel/intern/blendfile_link_append.c b/source/blender/blenkernel/intern/blendfile_link_append.c index 294fe57c923..be2abdbfb69 100644 --- a/source/blender/blenkernel/intern/blendfile_link_append.c +++ b/source/blender/blenkernel/intern/blendfile_link_append.c @@ -999,7 +999,7 @@ static void blendfile_link_append_proxies_convert(Main *bmain, ReportList *repor RPT_WARNING, "Proxies have been removed from Blender (%d proxies were automatically converted " "to library overrides, %d proxies could not be converted and were cleared). " - "Please consider re-saving any library .blend file with the newest Blender version.", + "Please consider re-saving any library .blend file with the newest Blender version", bf_reports.count.proxies_to_lib_overrides_success, bf_reports.count.proxies_to_lib_overrides_failures); } diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c index 16fc05266e2..338c74d550c 100644 --- a/source/blender/blenkernel/intern/cachefile.c +++ b/source/blender/blenkernel/intern/cachefile.c @@ -417,9 +417,7 @@ float BKE_cachefile_time_offset(const CacheFile *cache_file, const float time, c return cache_file->is_sequence ? frame : frame / fps - time_offset; } -bool BKE_cache_file_uses_render_procedural(const CacheFile *cache_file, - Scene *scene, - const int dag_eval_mode) +bool BKE_cache_file_uses_render_procedural(const CacheFile *cache_file, Scene *scene) { RenderEngineType *render_engine_type = RE_engines_find(scene->r.engine); @@ -428,9 +426,7 @@ bool BKE_cache_file_uses_render_procedural(const CacheFile *cache_file, return false; } - /* The render time procedural is only enabled during viewport rendering. */ - const bool is_final_render = (eEvaluationMode)dag_eval_mode == DAG_EVAL_RENDER; - return cache_file->use_render_procedural && !is_final_render; + return cache_file->use_render_procedural; } CacheFileLayer *BKE_cachefile_add_layer(CacheFile *cache_file, const char filename[1024]) diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index bdaea487cfb..c215321bc30 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -1929,6 +1929,48 @@ void BKE_scene_objects_iterator_begin(BLI_Iterator *iter, void *data_in) scene_objects_iterator_begin(iter, scene, NULL); } +void BKE_scene_objects_iterator_begin_ex(BLI_Iterator *iter, void *data_in) +{ + SceneObjectsIteratorExData *data = data_in; + + BKE_scene_objects_iterator_begin(iter, data->scene); + + /* Pack the data. */ + data->iter_data = iter->data; + iter->data = data_in; +} + +void BKE_scene_objects_iterator_next_ex(struct BLI_Iterator *iter) +{ + /* Unpack the data. */ + SceneObjectsIteratorExData *data = iter->data; + iter->data = data->iter_data; + + BKE_scene_objects_iterator_next(iter); + + Object *ob = iter->current; + if (ob && (ob->flag & data->flag) == 0) { + iter->skip = true; + } + + /* Pack the data. */ + data->iter_data = iter->data; + iter->data = data; +} + +void BKE_scene_objects_iterator_end_ex(struct BLI_Iterator *iter) +{ + /* Unpack the data. */ + SceneObjectsIteratorExData *data = iter->data; + iter->data = data->iter_data; + + BKE_scene_objects_iterator_end(iter); + + /* Pack the data. */ + data->iter_data = iter->data; + iter->data = data; +} + /** * Ensures we only get each object once, even when included in several collections. */ diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 7a97139748f..fc3f84778f8 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -5412,7 +5412,7 @@ static void transformcache_evaluate(bConstraint *con, bConstraintOb *cob, ListBa } /* Do not process data if using a render time procedural. */ - if (BKE_cache_file_uses_render_procedural(cache_file, scene, DEG_get_mode(cob->depsgraph))) { + if (BKE_cache_file_uses_render_procedural(cache_file, scene)) { return; } diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c index 9d13bf3ac11..96389c44839 100644 --- a/source/blender/blenkernel/intern/crazyspace.c +++ b/source/blender/blenkernel/intern/crazyspace.c @@ -236,7 +236,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra ModifierData *md; Mesh *me_input = ob->data; Mesh *me = NULL; - int i, a, numleft = 0, numVerts = 0; + int i, a, modifiers_left_num = 0, verts_num = 0; int cageIndex = BKE_modifiers_get_cage_index(scene, ob, NULL, 1); float(*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL; VirtualModifierData virtualModifierData; @@ -266,14 +266,14 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra BLI_linklist_free((LinkNode *)datamasks, NULL); me = BKE_mesh_wrapper_from_editmesh_with_coords(em, &cd_mask_extra, NULL, me_input); - deformedVerts = editbmesh_vert_coords_alloc(em, &numVerts); - defmats = MEM_mallocN(sizeof(*defmats) * numVerts, "defmats"); + deformedVerts = editbmesh_vert_coords_alloc(em, &verts_num); + defmats = MEM_mallocN(sizeof(*defmats) * verts_num, "defmats"); - for (a = 0; a < numVerts; a++) { + for (a = 0; a < verts_num; a++) { unit_m3(defmats[a]); } } - mti->deformMatricesEM(md, &mectx, em, me, deformedVerts, defmats, numVerts); + mti->deformMatricesEM(md, &mectx, em, me, deformedVerts, defmats, verts_num); } else { break; @@ -283,7 +283,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra for (; md && i <= cageIndex; md = md->next, i++) { if (editbmesh_modifier_is_enabled(scene, ob, md, me != NULL) && BKE_modifier_is_correctable_deformed(md)) { - numleft++; + modifiers_left_num++; } } @@ -294,7 +294,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra *deformmats = defmats; *deformcos = deformedVerts; - return numleft; + return modifiers_left_num; } /** @@ -319,13 +319,13 @@ static void crazyspace_init_verts_and_matrices(const Mesh *mesh, float (**deformmats)[3][3], float (**deformcos)[3]) { - int num_verts; - *deformcos = BKE_mesh_vert_coords_alloc(mesh, &num_verts); - *deformmats = MEM_callocN(sizeof(**deformmats) * num_verts, "defmats"); - for (int a = 0; a < num_verts; a++) { + int verts_num; + *deformcos = BKE_mesh_vert_coords_alloc(mesh, &verts_num); + *deformmats = MEM_callocN(sizeof(**deformmats) * verts_num, "defmats"); + for (int a = 0; a < verts_num; a++) { unit_m3((*deformmats)[a]); } - BLI_assert(num_verts == mesh->totvert); + BLI_assert(verts_num == mesh->totvert); } static bool crazyspace_modifier_supports_deform_matrices(ModifierData *md) @@ -352,7 +352,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph, ModifierData *md; Mesh *me_eval = NULL; float(*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL; - int numleft = 0; + int modifiers_left_num = 0; VirtualModifierData virtualModifierData; Object object_eval; crazyspace_init_object_for_eval(depsgraph, object, &object_eval); @@ -364,7 +364,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph, if (is_sculpt_mode && has_multires) { *deformmats = NULL; *deformcos = NULL; - return numleft; + return modifiers_left_num; } md = BKE_modifiers_get_virtual_modifierlist(&object_eval, &virtualModifierData); @@ -401,7 +401,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph, } if (crazyspace_modifier_supports_deform(md)) { - numleft++; + modifiers_left_num++; } } @@ -412,7 +412,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph, *deformmats = defmats; *deformcos = deformedVerts; - return numleft; + return modifiers_left_num; } void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph, @@ -489,13 +489,13 @@ void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph, } if (*deformmats == NULL) { - int a, numVerts; + int a, verts_num; Mesh *mesh = (Mesh *)object->data; - *deformcos = BKE_mesh_vert_coords_alloc(mesh, &numVerts); - *deformmats = MEM_callocN(sizeof(*(*deformmats)) * numVerts, "defmats"); + *deformcos = BKE_mesh_vert_coords_alloc(mesh, &verts_num); + *deformmats = MEM_callocN(sizeof(*(*deformmats)) * verts_num, "defmats"); - for (a = 0; a < numVerts; a++) { + for (a = 0; a < verts_num; a++) { unit_m3((*deformmats)[a]); } } @@ -523,7 +523,7 @@ void BKE_crazyspace_api_eval(Depsgraph *depsgraph, } const Mesh *mesh = (const Mesh *)object->data; - object->runtime.crazyspace_num_verts = mesh->totvert; + object->runtime.crazyspace_verts_num = mesh->totvert; BKE_crazyspace_build_sculpt(depsgraph, scene, object, @@ -537,12 +537,12 @@ void BKE_crazyspace_api_displacement_to_deformed(struct Object *object, float displacement[3], float r_displacement_deformed[3]) { - if (vertex_index < 0 || vertex_index >= object->runtime.crazyspace_num_verts) { + if (vertex_index < 0 || vertex_index >= object->runtime.crazyspace_verts_num) { BKE_reportf(reports, RPT_ERROR, "Invalid vertex index %d (expected to be within 0 to %d range)", vertex_index, - object->runtime.crazyspace_num_verts); + object->runtime.crazyspace_verts_num); return; } @@ -557,12 +557,12 @@ void BKE_crazyspace_api_displacement_to_original(struct Object *object, float displacement_deformed[3], float r_displacement[3]) { - if (vertex_index < 0 || vertex_index >= object->runtime.crazyspace_num_verts) { + if (vertex_index < 0 || vertex_index >= object->runtime.crazyspace_verts_num) { BKE_reportf(reports, RPT_ERROR, "Invalid vertex index %d (expected to be within 0 to %d range))", vertex_index, - object->runtime.crazyspace_num_verts); + object->runtime.crazyspace_verts_num); return; } diff --git a/source/blender/blenkernel/intern/curve.cc b/source/blender/blenkernel/intern/curve.cc index 02710982564..26f5d7e9cb4 100644 --- a/source/blender/blenkernel/intern/curve.cc +++ b/source/blender/blenkernel/intern/curve.cc @@ -3184,7 +3184,7 @@ static void calchandleNurb_intern(BezTriple *bezt, len *= 2.5614f; if (len != 0.0f) { - /* only for fcurves */ + /* Only for F-curves. */ bool leftviolate = false, rightviolate = false; if (!is_fcurve || fcurve_smoothing == FCURVE_SMOOTH_NONE) { @@ -4765,7 +4765,7 @@ bool BKE_nurb_valid_message(const int pnts, message_dst[0] = 0; return false; } - msg_template = TIP_("At least two points required."); + msg_template = TIP_("At least two points required"); break; case NURBSValidationStatus::MorePointsThanOrderRequired: msg_template = TIP_("Must have more control points than Order"); diff --git a/source/blender/blenkernel/intern/curve_bezier.cc b/source/blender/blenkernel/intern/curve_bezier.cc index b11216983b2..30a5869c976 100644 --- a/source/blender/blenkernel/intern/curve_bezier.cc +++ b/source/blender/blenkernel/intern/curve_bezier.cc @@ -58,6 +58,131 @@ void calculate_evaluated_offsets(const Span<int8_t> handle_types_left, evaluated_offsets.last() = offset; } +static float3 calculate_aligned_handle(const float3 &position, + const float3 &other_handle, + const float3 &aligned_handle) +{ + /* Keep track of the old length of the opposite handle. */ + const float length = math::distance(aligned_handle, position); + /* Set the other handle to directly opposite from the current handle. */ + const float3 dir = math::normalize(other_handle - position); + return position - dir * length; +} + +static void calculate_point_handles(const HandleType type_left, + const HandleType type_right, + const float3 position, + const float3 prev_position, + const float3 next_position, + float3 &left, + float3 &right) +{ + if (ELEM(BEZIER_HANDLE_AUTO, type_left, type_right)) { + const float3 prev_diff = position - prev_position; + const float3 next_diff = next_position - position; + float prev_len = math::length(prev_diff); + float next_len = math::length(next_diff); + if (prev_len == 0.0f) { + prev_len = 1.0f; + } + if (next_len == 0.0f) { + next_len = 1.0f; + } + const float3 dir = next_diff / next_len + prev_diff / prev_len; + + /* This magic number is unfortunate, but comes from elsewhere in Blender. */ + const float len = math::length(dir) * 2.5614f; + if (len != 0.0f) { + if (type_left == BEZIER_HANDLE_AUTO) { + const float prev_len_clamped = std::min(prev_len, next_len * 5.0f); + left = position + dir * -(prev_len_clamped / len); + } + if (type_right == BEZIER_HANDLE_AUTO) { + const float next_len_clamped = std::min(next_len, prev_len * 5.0f); + right = position + dir * (next_len_clamped / len); + } + } + } + + if (type_left == BEZIER_HANDLE_VECTOR) { + left = math::interpolate(position, prev_position, 1.0f / 3.0f); + } + + if (type_right == BEZIER_HANDLE_VECTOR) { + right = math::interpolate(position, next_position, 1.0f / 3.0f); + } + + /* When one of the handles is "aligned" handle, it must be aligned with the other, i.e. point in + * the opposite direction. Don't handle the case of two aligned handles, because code elsewhere + * should keep the pair consistent, and the relative locations aren't affected by other points + * anyway. */ + if (type_left == BEZIER_HANDLE_ALIGN && type_right != BEZIER_HANDLE_ALIGN) { + left = calculate_aligned_handle(position, right, left); + } + else if (type_left != BEZIER_HANDLE_ALIGN && type_right == BEZIER_HANDLE_ALIGN) { + right = calculate_aligned_handle(position, left, right); + } +} + +void set_handle_position(const float3 &position, + const HandleType type, + const HandleType type_other, + const float3 &new_handle, + float3 &handle, + float3 &handle_other) +{ + /* Don't bother when the handle positions are calculated automatically anyway. */ + if (ELEM(type, BEZIER_HANDLE_AUTO, BEZIER_HANDLE_VECTOR)) { + return; + } + + handle = new_handle; + if (type_other == BEZIER_HANDLE_ALIGN) { + handle_other = calculate_aligned_handle(position, handle, handle_other); + } +} + +void calculate_auto_handles(const bool cyclic, + const Span<int8_t> types_left, + const Span<int8_t> types_right, + const Span<float3> positions, + MutableSpan<float3> positions_left, + MutableSpan<float3> positions_right) +{ + const int points_num = positions.size(); + if (points_num == 1) { + return; + } + + calculate_point_handles(HandleType(types_left.first()), + HandleType(types_right.first()), + positions.first(), + cyclic ? positions.last() : 2.0f * positions.first() - positions[1], + positions[1], + positions_left.first(), + positions_right.first()); + + threading::parallel_for(IndexRange(1, points_num - 2), 1024, [&](IndexRange range) { + for (const int i : range) { + calculate_point_handles(HandleType(types_left[i]), + HandleType(types_right[i]), + positions[i], + positions[i - 1], + positions[i + 1], + positions_left[i], + positions_right[i]); + } + }); + + calculate_point_handles(HandleType(types_left.last()), + HandleType(types_right.last()), + positions.last(), + positions.last(1), + cyclic ? positions.first() : 2.0f * positions.last() - positions.last(1), + positions_left.last(), + positions_right.last()); +} + void evaluate_segment(const float3 &point_0, const float3 &point_1, const float3 &point_2, @@ -150,7 +275,7 @@ static void interpolate_to_evaluated(const Span<T> src, MutableSpan<T> dst) { BLI_assert(!src.is_empty()); - BLI_assert(dst.size() == src.size()); + BLI_assert(evaluated_offsets.size() == src.size()); BLI_assert(evaluated_offsets.last() == dst.size()); linear_interpolation(src.first(), src[1], dst.take_front(evaluated_offsets.first())); @@ -178,6 +303,4 @@ void interpolate_to_evaluated(const GSpan src, const Span<int> evaluated_offsets }); } -/** \} */ - } // namespace blender::bke::curves::bezier diff --git a/source/blender/blenkernel/intern/curve_catmull_rom.cc b/source/blender/blenkernel/intern/curve_catmull_rom.cc index ea3672dd56b..2db183eea3e 100644 --- a/source/blender/blenkernel/intern/curve_catmull_rom.cc +++ b/source/blender/blenkernel/intern/curve_catmull_rom.cc @@ -13,7 +13,7 @@ int calculate_evaluated_size(const int points_num, const bool cyclic, const int { const int eval_size = resolution * curve_segment_size(points_num, cyclic); /* If the curve isn't cyclic, one last point is added to the final point. */ - return (cyclic && points_num > 2) ? eval_size : eval_size + 1; + return cyclic ? eval_size : eval_size + 1; } /* Adapted from Cycles #catmull_rom_basis_eval function. */ @@ -58,8 +58,14 @@ static void interpolate_to_evaluated(const Span<T> src, return; } if (src.size() == 2) { - evaluate_segment(src.first(), src.first(), src.last(), src.last(), dst); - dst.last() = src.last(); + evaluate_segment(src.first(), src.first(), src.last(), src.last(), dst.take_front(resolution)); + if (cyclic) { + evaluate_segment( + src.last(), src.last(), src.first(), src.first(), dst.take_back(resolution)); + } + else { + dst.last() = src.last(); + } return; } diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc index 7ceaa8f0f37..66088714e63 100644 --- a/source/blender/blenkernel/intern/curves_geometry.cc +++ b/source/blender/blenkernel/intern/curves_geometry.cc @@ -11,6 +11,7 @@ #include "BLI_bounds.hh" #include "BLI_index_mask_ops.hh" +#include "BLI_length_parameterize.hh" #include "DNA_curves_types.h" @@ -547,6 +548,12 @@ Span<int> CurvesGeometry::evaluated_offsets() const return this->runtime->evaluated_offsets_cache; } +Span<int> CurvesGeometry::bezier_evaluated_offsets_for_curve(const int curve_index) const +{ + const IndexRange points = this->points_for_curve(curve_index); + return this->runtime->bezier_evaluated_offsets.as_span().slice(points); +} + IndexMask CurvesGeometry::indices_for_curve_type(const CurveType type, Vector<int64_t> &r_indices) const { @@ -721,6 +728,69 @@ void CurvesGeometry::interpolate_to_evaluated(const int curve_index, BLI_assert_unreachable(); } +IndexRange CurvesGeometry::lengths_range_for_curve(const int curve_index, const bool cyclic) const +{ + BLI_assert(cyclic == this->cyclic()[curve_index]); + const IndexRange points = this->evaluated_points_for_curve(curve_index); + const int start = points.start() + curve_index; + const int size = curves::curve_segment_size(points.size(), cyclic); + return {start, size}; +} + +void CurvesGeometry::ensure_evaluated_lengths() const +{ + if (!this->runtime->length_cache_dirty) { + return; + } + + /* A double checked lock. */ + std::scoped_lock lock{this->runtime->length_cache_mutex}; + if (!this->runtime->length_cache_dirty) { + return; + } + + threading::isolate_task([&]() { + /* Use an extra length value for the final cyclic segment for a consistent size + * (see comment on #evaluated_length_cache). */ + const int total_size = this->evaluated_points_num() + this->curves_num(); + this->runtime->evaluated_length_cache.resize(total_size); + MutableSpan<float> evaluated_lengths = this->runtime->evaluated_length_cache; + + Span<float3> evaluated_positions = this->evaluated_positions(); + VArray<bool> curves_cyclic = this->cyclic(); + + threading::parallel_for(this->curves_range(), 128, [&](IndexRange curves_range) { + for (const int curve_index : curves_range) { + const bool cyclic = curves_cyclic[curve_index]; + const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index); + if (UNLIKELY(evaluated_points.is_empty())) { + continue; + } + const IndexRange lengths_range = this->lengths_range_for_curve(curve_index, cyclic); + length_parameterize::accumulate_lengths(evaluated_positions.slice(evaluated_points), + cyclic, + evaluated_lengths.slice(lengths_range)); + } + }); + }); + + this->runtime->length_cache_dirty = false; +} + +Span<float> CurvesGeometry::evaluated_lengths_for_curve(const int curve_index, + const bool cyclic) const +{ + BLI_assert(!this->runtime->length_cache_dirty); + const IndexRange range = this->lengths_range_for_curve(curve_index, cyclic); + return this->runtime->evaluated_length_cache.as_span().slice(range); +} + +float CurvesGeometry::evaluated_length_total_for_curve(const int curve_index, + const bool cyclic) const +{ + return this->evaluated_lengths_for_curve(curve_index, cyclic).last(); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -747,6 +817,7 @@ void CurvesGeometry::tag_positions_changed() this->runtime->position_cache_dirty = true; this->runtime->tangent_cache_dirty = true; this->runtime->normal_cache_dirty = true; + this->runtime->length_cache_dirty = true; } void CurvesGeometry::tag_topology_changed() { @@ -755,6 +826,7 @@ void CurvesGeometry::tag_topology_changed() this->runtime->normal_cache_dirty = true; this->runtime->offsets_cache_dirty = true; this->runtime->nurbs_basis_cache_dirty = true; + this->runtime->length_cache_dirty = true; } void CurvesGeometry::tag_normals_changed() { @@ -779,6 +851,34 @@ static void transform_positions(MutableSpan<float3> positions, const float4x4 &m }); } +void CurvesGeometry::calculate_bezier_auto_handles() +{ + const VArray<int8_t> types = std::as_const(*this).curve_types(); + if (types.is_single() && types.get_internal_single() != CURVE_TYPE_BEZIER) { + return; + } + const VArray<bool> cyclic = std::as_const(*this).cyclic(); + const Span<int8_t> types_left = this->handle_types_left(); + const Span<int8_t> types_right = this->handle_types_right(); + const Span<float3> positions = this->positions(); + MutableSpan<float3> positions_left = this->handle_positions_left(); + MutableSpan<float3> positions_right = this->handle_positions_right(); + + threading::parallel_for(this->curves_range(), 128, [&](IndexRange range) { + for (const int i_curve : range) { + if (types[i_curve] == CURVE_TYPE_BEZIER) { + const IndexRange points = this->points_for_curve(i_curve); + curves::bezier::calculate_auto_handles(cyclic[i_curve], + types_left.slice(points), + types_right.slice(points), + positions.slice(points), + positions_left.slice(points), + positions_right.slice(points)); + } + } + }); +} + void CurvesGeometry::translate(const float3 &translation) { /* Use `as_const` because the non-const functions can add the handle attributes. */ diff --git a/source/blender/blenkernel/intern/curves_geometry_test.cc b/source/blender/blenkernel/intern/curves_geometry_test.cc index e4dc9eead60..baa47bb7cf6 100644 --- a/source/blender/blenkernel/intern/curves_geometry_test.cc +++ b/source/blender/blenkernel/intern/curves_geometry_test.cc @@ -226,9 +226,8 @@ TEST(curves_geometry, CatmullRomTwoPointCyclic) curves.offsets().last() = 2; curves.cyclic().fill(true); - /* The cyclic value should be ignored when there are only two control points. There should - * be 12 evaluated points for the single segment and an extra for the last point. */ - EXPECT_EQ(curves.evaluated_points_num(), 13); + /* The curve should still be cyclic when there are only two control points. */ + EXPECT_EQ(curves.evaluated_points_num(), 24); } TEST(curves_geometry, BezierPositionEvaluation) diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index bf6f05300f8..9258c1ffb66 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -5379,8 +5379,6 @@ void CustomData_debug_info_from_layers(const CustomData *data, const char *inden namespace blender::bke { -/** \} */ - /* -------------------------------------------------------------------- */ /** \name Custom Data C++ API * \{ */ diff --git a/source/blender/blenkernel/intern/geometry_component_curves.cc b/source/blender/blenkernel/intern/geometry_component_curves.cc index 27689d70c77..b5771cc063f 100644 --- a/source/blender/blenkernel/intern/geometry_component_curves.cc +++ b/source/blender/blenkernel/intern/geometry_component_curves.cc @@ -9,6 +9,7 @@ #include "BKE_attribute_math.hh" #include "BKE_curve.h" #include "BKE_curves.hh" +#include "BKE_geometry_fields.hh" #include "BKE_geometry_set.hh" #include "BKE_lib_id.h" #include "BKE_spline.hh" diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc index 2bfe984462c..f5ed21af19a 100644 --- a/source/blender/blenkernel/intern/geometry_component_mesh.cc +++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc @@ -10,6 +10,7 @@ #include "BKE_attribute_access.hh" #include "BKE_attribute_math.hh" #include "BKE_deform.h" +#include "BKE_geometry_fields.hh" #include "BKE_geometry_set.hh" #include "BKE_lib_id.h" #include "BKE_mesh.h" diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc index 0eece6e9ad0..0b08acf92a3 100644 --- a/source/blender/blenkernel/intern/geometry_set.cc +++ b/source/blender/blenkernel/intern/geometry_set.cc @@ -8,6 +8,7 @@ #include "BKE_attribute.h" #include "BKE_attribute_access.hh" #include "BKE_curves.hh" +#include "BKE_geometry_fields.hh" #include "BKE_geometry_set.hh" #include "BKE_lib_id.h" #include "BKE_mesh.h" diff --git a/source/blender/blenkernel/intern/gpencil_geom.cc b/source/blender/blenkernel/intern/gpencil_geom.cc index a0b6ab2d654..76f21e369aa 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.cc +++ b/source/blender/blenkernel/intern/gpencil_geom.cc @@ -572,11 +572,11 @@ static bool BKE_gpencil_stroke_extra_points(bGPDstroke *gps, bGPDspoint *new_pts = (bGPDspoint *)MEM_mallocN(sizeof(bGPDspoint) * new_count, __func__); for (int i = 0; i < count_before; i++) { - memcpy(&new_pts[i], &pts[0], sizeof(bGPDspoint)); + new_pts[i] = blender::dna::shallow_copy(pts[0]); } - memcpy(&new_pts[count_before], pts, sizeof(bGPDspoint) * gps->totpoints); + memcpy(static_cast<void *>(&new_pts[count_before]), pts, sizeof(bGPDspoint) * gps->totpoints); for (int i = new_count - count_after; i < new_count; i++) { - memcpy(&new_pts[i], &pts[gps->totpoints - 1], sizeof(bGPDspoint)); + new_pts[i] = blender::dna::shallow_copy(pts[gps->totpoints - 1]); } if (gps->dvert) { @@ -809,7 +809,7 @@ bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, const int index_from, const } new_pt = (bGPDspoint *)MEM_mallocN(sizeof(bGPDspoint) * new_count, "gp_stroke_points_trimmed"); - memcpy(new_pt, &pt[index_from], sizeof(bGPDspoint) * new_count); + memcpy(static_cast<void *>(new_pt), &pt[index_from], sizeof(bGPDspoint) * new_count); if (gps->dvert) { new_dv = (MDeformVert *)MEM_mallocN(sizeof(MDeformVert) * new_count, @@ -866,7 +866,7 @@ bool BKE_gpencil_stroke_split(bGPdata *gpd, gpf, gps, gps->mat_nr, new_count, gps->thickness); new_pt = new_gps->points; /* Allocated from above. */ - memcpy(new_pt, &pt[before_index], sizeof(bGPDspoint) * new_count); + memcpy(static_cast<void *>(new_pt), &pt[before_index], sizeof(bGPDspoint) * new_count); if (gps->dvert) { new_dv = (MDeformVert *)MEM_mallocN(sizeof(MDeformVert) * new_count, @@ -1027,11 +1027,11 @@ bool BKE_gpencil_stroke_smooth_point(bGPDstroke *gps, * smooth. To solve that problem, choose a different n/2, which does not match the range and * normalize the weights on finish. This may cause some artifacts at low values. * - * keep_shape is a new option to stop the stroke from severly deforming. + * keep_shape is a new option to stop the stroke from severely deforming. * It uses different partially negative weights. * w = 2 * (nCr(n, j + n/2) / 2^n) - (nCr(3*n, j + n) / 2^(3*n)) * ~ 2 * sqrt(2/(pi*n)) * exp(-2*j*j/n) - sqrt(2/(pi*3*n)) * exp(-2*j*j/(3*n)) - * All weigths still sum up to 1. + * All weights still sum up to 1. * Note these weights only work because the averaging is done in relative coordinates. */ float sco[3] = {0.0f, 0.0f, 0.0f}; @@ -1302,7 +1302,7 @@ void BKE_gpencil_stroke_smooth(bGPDstroke *gps, } /* Make a copy of the point data to avoid directionality of the smooth operation. */ - bGPDstroke gps_old = *gps; + bGPDstroke gps_old = blender::dna::shallow_copy(*gps); gps_old.points = (bGPDspoint *)MEM_dupallocN(gps->points); /* Smooth stroke. */ @@ -1765,7 +1765,7 @@ bool BKE_gpencil_stroke_trim(bGPdata *gpd, bGPDstroke *gps) int idx = start + i; bGPDspoint *pt_src = &old_points[idx]; bGPDspoint *pt_new = &gps->points[i]; - memcpy(pt_new, pt_src, sizeof(bGPDspoint)); + *pt_new = blender::dna::shallow_copy(*pt_src); if (gps->dvert != nullptr) { dvert_src = &old_dvert[idx]; MDeformVert *dvert = &gps->dvert[i]; @@ -1930,7 +1930,7 @@ void BKE_gpencil_dissolve_points(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps, (gps->dvert != nullptr) ? dvert = gps->dvert : nullptr; for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { if ((pt->flag & tag) == 0) { - *npt = *pt; + *npt = blender::dna::shallow_copy(*pt); npt++; if (gps->dvert != nullptr) { @@ -2080,7 +2080,7 @@ void BKE_gpencil_stroke_simplify_adaptive(bGPdata *gpd, bGPDstroke *gps, float e bGPDspoint *pt = &gps->points[j]; if ((marked[i]) || (i == 0) || (i == totpoints - 1)) { - memcpy(pt, pt_src, sizeof(bGPDspoint)); + *pt = blender::dna::shallow_copy(*pt_src); if (gps->dvert != nullptr) { dvert_src = &old_dvert[i]; MDeformVert *dvert = &gps->dvert[j]; @@ -2142,7 +2142,7 @@ void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps) bGPDspoint *pt = &gps->points[j]; if ((i == 0) || (i == gps->totpoints - 1) || ((i % 2) > 0.0)) { - memcpy(pt, pt_src, sizeof(bGPDspoint)); + *pt = blender::dna::shallow_copy(*pt_src); if (gps->dvert != nullptr) { dvert_src = &old_dvert[i]; MDeformVert *dvert = &gps->dvert[j]; @@ -3158,7 +3158,7 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd, /* Copy over the relevant point data */ new_stroke->points = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * new_stroke->totpoints, "gp delete stroke fragment"); - memcpy(new_stroke->points, + memcpy(static_cast<void *>(new_stroke->points), gps->points + island->start_idx, sizeof(bGPDspoint) * new_stroke->totpoints); @@ -3471,13 +3471,13 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a, /* don't visibly link the first and last points? */ if (leave_gaps) { /* 1st: add one tail point to start invisible area */ - point = gps_a->points[gps_a->totpoints - 1]; + point = blender::dna::shallow_copy(gps_a->points[gps_a->totpoints - 1]); deltatime = point.time; gpencil_stroke_copy_point(gps_a, nullptr, &point, delta, 0.0f, 0.0f, 0.0f); /* 2nd: add one head point to finish invisible area */ - point = gps_b->points[0]; + point = blender::dna::shallow_copy(gps_b->points[0]); gpencil_stroke_copy_point(gps_a, nullptr, &point, delta, 0.0f, 0.0f, deltatime); } diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index 33410b4521e..faafd1e1040 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -743,7 +743,7 @@ void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *o } BLI_assert(ob->data != NULL); - /* Only copy strokes from visible frames to evaluated data.*/ + /* Only copy strokes from visible frames to evaluated data. */ gpencil_copy_visible_frames_to_eval(depsgraph, scene, ob); } diff --git a/source/blender/blenkernel/intern/gpencil_update_cache.c b/source/blender/blenkernel/intern/gpencil_update_cache.c index bbe576eb847..9113f2e2ab9 100644 --- a/source/blender/blenkernel/intern/gpencil_update_cache.c +++ b/source/blender/blenkernel/intern/gpencil_update_cache.c @@ -51,10 +51,8 @@ static void cache_node_free(void *node); static void update_cache_free(GPencilUpdateCache *cache) { - if (cache->children != NULL) { - BLI_dlrbTree_free(cache->children, cache_node_free); - MEM_freeN(cache->children); - } + BLI_dlrbTree_free(cache->children, cache_node_free); + MEM_SAFE_FREE(cache->children); MEM_freeN(cache); } @@ -83,9 +81,8 @@ static void cache_node_update(void *node, void *data) /* In case the new cache does a full update, remove its children since they will be all * updated by this cache. */ - if (new_update_cache->flag == GP_UPDATE_NODE_FULL_COPY && update_cache->children != NULL) { + if (new_update_cache->flag == GP_UPDATE_NODE_FULL_COPY) { BLI_dlrbTree_free(update_cache->children, cache_node_free); - MEM_freeN(update_cache->children); } update_cache_free(new_update_cache); diff --git a/source/blender/blenkernel/intern/icons.cc b/source/blender/blenkernel/intern/icons.cc index 8883613786b..2ba6510ee71 100644 --- a/source/blender/blenkernel/intern/icons.cc +++ b/source/blender/blenkernel/intern/icons.cc @@ -416,7 +416,7 @@ void BKE_previewimg_id_custom_set(ID *id, const char *path) bool BKE_previewimg_id_supports_jobs(const ID *id) { - return ELEM(GS(id->name), ID_OB, ID_MA, ID_TE, ID_LA, ID_WO, ID_IM, ID_BR); + return ELEM(GS(id->name), ID_OB, ID_MA, ID_TE, ID_LA, ID_WO, ID_IM, ID_BR, ID_GR); } void BKE_previewimg_deferred_release(PreviewImage *prv) diff --git a/source/blender/blenkernel/intern/image.cc b/source/blender/blenkernel/intern/image.cc index b65f3416f0f..3eade265bf2 100644 --- a/source/blender/blenkernel/intern/image.cc +++ b/source/blender/blenkernel/intern/image.cc @@ -468,7 +468,9 @@ constexpr IDTypeInfo get_type_info() IDTypeInfo IDType_ID_IM = get_type_info(); /* prototypes */ -static int image_num_files(struct Image *ima); +static int image_num_viewfiles(Image *ima); +static ImBuf *image_load_image_file( + Image *ima, ImageUser *iuser, int entry, int cfra, bool is_sequence); static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock); static void image_update_views_format(Image *ima, ImageUser *iuser); static void image_add_view(Image *ima, const char *viewname, const char *filepath); @@ -1277,9 +1279,9 @@ bool BKE_image_memorypack(Image *ima) void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath) { - const int totfiles = image_num_files(ima); + const int tot_viewfiles = image_num_viewfiles(ima); - if (totfiles == 1) { + if (tot_viewfiles == 1) { ImagePackedFile *imapf = static_cast<ImagePackedFile *>( MEM_mallocN(sizeof(ImagePackedFile), "Image packed file")); BLI_addtail(&ima->packedfiles, imapf); @@ -1313,9 +1315,9 @@ void BKE_image_packfiles_from_mem(ReportList *reports, char *data, const size_t data_len) { - const int totfiles = image_num_files(ima); + const int tot_viewfiles = image_num_viewfiles(ima); - if (totfiles != 1) { + if (tot_viewfiles != 1) { BKE_report(reports, RPT_ERROR, "Cannot pack multiview images from raw data currently..."); } else { @@ -2944,9 +2946,9 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal) case IMA_SIGNAL_RELOAD: /* try to repack file */ if (BKE_image_has_packedfile(ima)) { - const int totfiles = image_num_files(ima); + const int tot_viewfiles = image_num_viewfiles(ima); - if (totfiles != BLI_listbase_count_at_most(&ima->packedfiles, totfiles + 1)) { + if (tot_viewfiles != BLI_listbase_count_at_most(&ima->packedfiles, tot_viewfiles + 1)) { /* in case there are new available files to be loaded */ image_free_packedfiles(ima); BKE_image_packfiles(nullptr, ima, ID_BLEND_PATH(bmain, &ima->id)); @@ -3739,7 +3741,7 @@ static int imbuf_alpha_flags_for_image(Image *ima) /** * \return the number of files will vary according to the stereo format. */ -static int image_num_files(Image *ima) +static int image_num_viewfiles(Image *ima) { const bool is_multiview = BKE_image_is_multiview(ima); @@ -3754,117 +3756,6 @@ static int image_num_files(Image *ima) return BLI_listbase_count(&ima->views); } -static ImBuf *load_sequence_single( - Image *ima, ImageUser *iuser, int frame, const int view_id, bool *r_cache_ibuf) -{ - struct ImBuf *ibuf; - char name[FILE_MAX]; - int flag; - ImageUser iuser_t{}; - - *r_cache_ibuf = true; - - ima->lastframe = frame; - - if (iuser) { - iuser_t = *iuser; - } - else { - /* BKE_image_user_file_path() uses this value for file name for sequences. */ - iuser_t.framenr = frame; - /* TODO(sergey): Do we need to initialize something else here? */ - } - - iuser_t.view = view_id; - BKE_image_user_file_path(&iuser_t, ima, name); - - flag = IB_rect | IB_multilayer | IB_metadata; - flag |= imbuf_alpha_flags_for_image(ima); - - /* read ibuf */ - ibuf = IMB_loadiffname(name, flag, ima->colorspace_settings.name); - -#if 0 - if (ibuf) { - printf(AT " loaded %s\n", name); - } - else { - printf(AT " missed %s\n", name); - } -#endif - - if (ibuf) { -#ifdef WITH_OPENEXR - if (ibuf->ftype == IMB_FTYPE_OPENEXR && ibuf->userdata) { - /* Handle multilayer and multiview cases, don't assign ibuf here. - * will be set layer in BKE_image_acquire_ibuf from ima->rr. */ - if (IMB_exr_has_multilayer(ibuf->userdata)) { - image_create_multilayer(ima, ibuf, frame); - ima->type = IMA_TYPE_MULTILAYER; - IMB_freeImBuf(ibuf); - ibuf = nullptr; - /* Null ibuf in the cache means the image failed to load. However for multilayer we load - * pixels into RenderResult instead and intentionally leave ibuf null. */ - *r_cache_ibuf = false; - } - } - else { - image_init_after_load(ima, iuser, ibuf); - } -#else - image_init_after_load(ima, iuser, ibuf); -#endif - } - - return ibuf; -} - -static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int entry, int frame) -{ - struct ImBuf *ibuf = nullptr; - const bool is_multiview = BKE_image_is_multiview(ima); - const int totfiles = image_num_files(ima); - - if (!is_multiview) { - bool put_in_cache; - ibuf = load_sequence_single(ima, iuser, frame, 0, &put_in_cache); - if (put_in_cache) { - image_assign_ibuf(ima, ibuf, 0, entry); - } - } - else { - const int totviews = BLI_listbase_count(&ima->views); - Array<ImBuf *> ibuf_arr(totviews); - Array<bool> cache_ibuf_arr(totviews); - - for (int i = 0; i < totfiles; i++) { - ibuf_arr[i] = load_sequence_single(ima, iuser, frame, i, &cache_ibuf_arr[i]); - } - - if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D) { - IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]); - } - - /* return the original requested ImBuf */ - ibuf = ibuf_arr[(iuser ? iuser->multi_index : 0)]; - - for (int i = 0; i < totviews; i++) { - if (cache_ibuf_arr[i]) { - image_assign_ibuf(ima, ibuf_arr[i], i, entry); - } - } - - /* "remove" the others (decrease their refcount) */ - for (int i = 0; i < totviews; i++) { - if (ibuf_arr[i] != ibuf) { - IMB_freeImBuf(ibuf_arr[i]); - } - } - } - - return ibuf; -} - static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int entry, int frame) { struct ImBuf *ibuf = nullptr; @@ -3883,7 +3774,7 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int e ima->rr = nullptr; } - ibuf = image_load_sequence_file(ima, iuser, entry, frame); + ibuf = image_load_image_file(ima, iuser, entry, frame, true); if (ibuf) { /* actually an error */ ima->type = IMA_TYPE_IMAGE; @@ -3970,12 +3861,12 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) { struct ImBuf *ibuf = nullptr; const bool is_multiview = BKE_image_is_multiview(ima); - const int totfiles = image_num_files(ima); + const int tot_viewfiles = image_num_viewfiles(ima); - if (totfiles != BLI_listbase_count_at_most(&ima->anims, totfiles + 1)) { + if (tot_viewfiles != BLI_listbase_count_at_most(&ima->anims, tot_viewfiles + 1)) { image_free_anims(ima); - for (int i = 0; i < totfiles; i++) { + for (int i = 0; i < tot_viewfiles; i++) { /* allocate the ImageAnim */ ImageAnim *ia = MEM_cnew<ImageAnim>("Image Anim"); BLI_addtail(&ima->anims, ia); @@ -3990,7 +3881,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) const int totviews = BLI_listbase_count(&ima->views); Array<ImBuf *> ibuf_arr(totviews); - for (int i = 0; i < totfiles; i++) { + for (int i = 0; i < tot_viewfiles; i++) { ibuf_arr[i] = load_movie_single(ima, iuser, frame, i); } @@ -4021,23 +3912,21 @@ static ImBuf *load_image_single(Image *ima, int cfra, const int view_id, const bool has_packed, + const bool is_sequence, bool *r_cache_ibuf) { char filepath[FILE_MAX]; struct ImBuf *ibuf = nullptr; - int flag; + int flag = IB_rect | IB_multilayer; *r_cache_ibuf = true; /* is there a PackedFile with this image ? */ - if (has_packed) { - ImagePackedFile *imapf; - - flag = IB_rect | IB_multilayer; - flag |= imbuf_alpha_flags_for_image(ima); - - imapf = static_cast<ImagePackedFile *>(BLI_findlink(&ima->packedfiles, view_id)); + if (has_packed && !is_sequence) { + ImagePackedFile *imapf = static_cast<ImagePackedFile *>( + BLI_findlink(&ima->packedfiles, view_id)); if (imapf->packedfile) { + flag |= imbuf_alpha_flags_for_image(ima); ibuf = IMB_ibImageFromMemory((unsigned char *)imapf->packedfile->data, imapf->packedfile->size, flag, @@ -4046,14 +3935,17 @@ static ImBuf *load_image_single(Image *ima, } } else { - ImageUser iuser_t{}; - - flag = IB_rect | IB_multilayer | IB_metadata; - flag |= imbuf_alpha_flags_for_image(ima); + if (is_sequence) { + ima->lastframe = cfra; + } /* get the correct filepath */ - BKE_image_user_frame_calc(ima, iuser, cfra); + const bool is_tiled = (ima->source == IMA_SRC_TILED); + if (!(is_sequence || is_tiled)) { + BKE_image_user_frame_calc(ima, iuser, cfra); + } + ImageUser iuser_t{}; if (iuser) { iuser_t = *iuser; } @@ -4066,6 +3958,8 @@ static ImBuf *load_image_single(Image *ima, BKE_image_user_file_path(&iuser_t, ima, filepath); /* read ibuf */ + flag |= IB_metadata; + flag |= imbuf_alpha_flags_for_image(ima); ibuf = IMB_loadiffname(filepath, flag, ima->colorspace_settings.name); } @@ -4090,7 +3984,7 @@ static ImBuf *load_image_single(Image *ima, image_init_after_load(ima, iuser, ibuf); /* Make packed file for auto-pack. */ - if ((has_packed == false) && (G.fileflags & G_FILE_AUTOPACK)) { + if (!is_sequence && (has_packed == false) && (G.fileflags & G_FILE_AUTOPACK)) { ImagePackedFile *imapf = static_cast<ImagePackedFile *>( MEM_mallocN(sizeof(ImagePackedFile), "Image Pack-file")); BLI_addtail(&ima->packedfiles, imapf); @@ -4108,18 +4002,23 @@ static ImBuf *load_image_single(Image *ima, /* warning, 'iuser' can be null * NOTE: Image->views was already populated (in image_update_views_format) */ -static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) +static ImBuf *image_load_image_file( + Image *ima, ImageUser *iuser, int entry, int cfra, bool is_sequence) { struct ImBuf *ibuf = nullptr; const bool is_multiview = BKE_image_is_multiview(ima); - const int totfiles = image_num_files(ima); + const bool is_tiled = (ima->source == IMA_SRC_TILED); + const int tot_viewfiles = image_num_viewfiles(ima); bool has_packed = BKE_image_has_packedfile(ima); - /* always ensure clean ima */ - BKE_image_free_buffers(ima); + if (!(is_sequence || is_tiled)) { + /* ensure clean ima */ + BKE_image_free_buffers(ima); + } /* this should never happen, but just playing safe */ - if (has_packed) { + if (!is_sequence && has_packed) { + const int totfiles = tot_viewfiles * BLI_listbase_count(&ima->tiles); if (totfiles != BLI_listbase_count_at_most(&ima->packedfiles, totfiles + 1)) { image_free_packedfiles(ima); has_packed = false; @@ -4128,9 +4027,10 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) if (!is_multiview) { bool put_in_cache; - ibuf = load_image_single(ima, iuser, cfra, 0, has_packed, &put_in_cache); + ibuf = load_image_single(ima, iuser, cfra, 0, has_packed, is_sequence, &put_in_cache); if (put_in_cache) { - image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + const int index = (is_sequence || is_tiled) ? 0 : IMA_NO_INDEX; + image_assign_ibuf(ima, ibuf, index, entry); } } else { @@ -4140,28 +4040,29 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) Array<ImBuf *> ibuf_arr(totviews); Array<bool> cache_ibuf_arr(totviews); - for (int i = 0; i < totfiles; i++) { - ibuf_arr[i] = load_image_single(ima, iuser, cfra, i, has_packed, &cache_ibuf_arr[i]); + for (int i = 0; i < tot_viewfiles; i++) { + ibuf_arr[i] = load_image_single( + ima, iuser, cfra, i, has_packed, is_sequence, &cache_ibuf_arr[i]); } /* multi-views/multi-layers OpenEXR files directly populate ima, and return null ibuf... */ if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D && ibuf_arr[0] && - totfiles == 1 && totviews >= 2) { + tot_viewfiles == 1 && totviews >= 2) { IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]); } /* return the original requested ImBuf */ - int i = (iuser && iuser->multi_index < totviews) ? iuser->multi_index : 0; - ibuf = ibuf_arr[i]; + const int ibuf_index = (iuser && iuser->multi_index < totviews) ? iuser->multi_index : 0; + ibuf = ibuf_arr[ibuf_index]; - for (i = 0; i < totviews; i++) { + for (int i = 0; i < totviews; i++) { if (cache_ibuf_arr[i]) { - image_assign_ibuf(ima, ibuf_arr[i], i, 0); + image_assign_ibuf(ima, ibuf_arr[i], i, entry); } } /* "remove" the others (decrease their refcount) */ - for (i = 0; i < totviews; i++) { + for (int i = 0; i < totviews; i++) { if (ibuf_arr[i] != ibuf) { IMB_freeImBuf(ibuf_arr[i]); } @@ -4176,7 +4077,7 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser) ImBuf *ibuf = nullptr; if (ima->rr == nullptr) { - ibuf = image_load_image_file(ima, iuser, 0); + ibuf = image_load_image_file(ima, iuser, 0, 0, false); if (ibuf) { /* actually an error */ ima->type = IMA_TYPE_IMAGE; return ibuf; @@ -4553,7 +4454,7 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock) else if (ima->source == IMA_SRC_SEQUENCE) { if (ima->type == IMA_TYPE_IMAGE) { /* Regular files, ibufs in flip-book, allows saving. */ - ibuf = image_load_sequence_file(ima, iuser, entry, entry); + ibuf = image_load_image_file(ima, iuser, entry, entry, true); } /* no else; on load the ima type can change */ if (ima->type == IMA_TYPE_MULTILAYER) { @@ -4564,7 +4465,7 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock) else if (ima->source == IMA_SRC_TILED) { if (ima->type == IMA_TYPE_IMAGE) { /* Regular files, ibufs in flip-book, allows saving */ - ibuf = image_load_sequence_file(ima, iuser, entry, 0); + ibuf = image_load_image_file(ima, iuser, entry, 0, false); } /* no else; on load the ima type can change */ if (ima->type == IMA_TYPE_MULTILAYER) { @@ -4575,7 +4476,8 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock) else if (ima->source == IMA_SRC_FILE) { if (ima->type == IMA_TYPE_IMAGE) { - ibuf = image_load_image_file(ima, iuser, entry); /* cfra only for '#', this global is OK */ + ibuf = image_load_image_file( + ima, iuser, 0, entry, false); /* cfra only for '#', this global is OK */ } /* no else; on load the ima type can change */ if (ima->type == IMA_TYPE_MULTILAYER) { diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index ccff4dbed03..c99bf885074 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -266,6 +266,8 @@ void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user) BLI_freelistN(&view_layer->drawdata); BLI_freelistN(&view_layer->aovs); view_layer->active_aov = NULL; + BLI_freelistN(&view_layer->lightgroups); + view_layer->active_lightgroup = NULL; MEM_SAFE_FREE(view_layer->stats); @@ -428,6 +430,29 @@ static void layer_aov_copy_data(ViewLayer *view_layer_dst, } } +static void layer_lightgroup_copy_data(ViewLayer *view_layer_dst, + const ViewLayer *view_layer_src, + ListBase *lightgroups_dst, + const ListBase *lightgroups_src) +{ + if (lightgroups_src != NULL) { + BLI_duplicatelist(lightgroups_dst, lightgroups_src); + } + + ViewLayerLightgroup *lightgroup_dst = lightgroups_dst->first; + const ViewLayerLightgroup *lightgroup_src = lightgroups_src->first; + + while (lightgroup_dst != NULL) { + BLI_assert(lightgroup_src); + if (lightgroup_src == view_layer_src->active_lightgroup) { + view_layer_dst->active_lightgroup = lightgroup_dst; + } + + lightgroup_dst = lightgroup_dst->next; + lightgroup_src = lightgroup_src->next; + } +} + static void layer_collections_copy_data(ViewLayer *view_layer_dst, const ViewLayer *view_layer_src, ListBase *layer_collections_dst, @@ -496,6 +521,10 @@ void BKE_view_layer_copy_data(Scene *scene_dst, layer_aov_copy_data( view_layer_dst, view_layer_src, &view_layer_dst->aovs, &view_layer_src->aovs); + BLI_listbase_clear(&view_layer_dst->lightgroups); + layer_lightgroup_copy_data( + view_layer_dst, view_layer_src, &view_layer_dst->lightgroups, &view_layer_src->lightgroups); + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { id_us_plus((ID *)view_layer_dst->mat_override); } @@ -2256,6 +2285,9 @@ void BKE_view_layer_blend_write(BlendWriter *writer, ViewLayer *view_layer) LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) { BLO_write_struct(writer, ViewLayerAOV, aov); } + LISTBASE_FOREACH (ViewLayerLightgroup *, lightgroup, &view_layer->lightgroups) { + BLO_write_struct(writer, ViewLayerLightgroup, lightgroup); + } write_layer_collections(writer, &view_layer->layer_collections); } @@ -2294,6 +2326,9 @@ void BKE_view_layer_blend_read_data(BlendDataReader *reader, ViewLayer *view_lay BLO_read_list(reader, &view_layer->aovs); BLO_read_data_address(reader, &view_layer->active_aov); + BLO_read_list(reader, &view_layer->lightgroups); + BLO_read_data_address(reader, &view_layer->active_lightgroup); + BLI_listbase_clear(&view_layer->drawdata); view_layer->object_bases_array = NULL; view_layer->object_bases_hash = NULL; @@ -2471,4 +2506,117 @@ ViewLayer *BKE_view_layer_find_with_aov(struct Scene *scene, struct ViewLayerAOV return NULL; } +/* -------------------------------------------------------------------- */ +/** \name Light Groups + * \{ */ + +static void viewlayer_lightgroup_make_name_unique(ViewLayer *view_layer, + ViewLayerLightgroup *lightgroup) +{ + /* Don't allow dots, it's incompatible with OpenEXR convention to store channels + * as "layer.pass.channel". */ + BLI_str_replace_char(lightgroup->name, '.', '_'); + BLI_uniquename(&view_layer->lightgroups, + lightgroup, + DATA_("Lightgroup"), + '_', + offsetof(ViewLayerLightgroup, name), + sizeof(lightgroup->name)); +} + +static void viewlayer_lightgroup_active_set(ViewLayer *view_layer, ViewLayerLightgroup *lightgroup) +{ + if (lightgroup != NULL) { + BLI_assert(BLI_findindex(&view_layer->lightgroups, lightgroup) != -1); + view_layer->active_lightgroup = lightgroup; + } + else { + view_layer->active_lightgroup = NULL; + } +} + +struct ViewLayerLightgroup *BKE_view_layer_add_lightgroup(struct ViewLayer *view_layer) +{ + ViewLayerLightgroup *lightgroup; + lightgroup = MEM_callocN(sizeof(ViewLayerLightgroup), __func__); + BLI_strncpy(lightgroup->name, DATA_("Lightgroup"), sizeof(lightgroup->name)); + BLI_addtail(&view_layer->lightgroups, lightgroup); + viewlayer_lightgroup_active_set(view_layer, lightgroup); + viewlayer_lightgroup_make_name_unique(view_layer, lightgroup); + return lightgroup; +} + +void BKE_view_layer_remove_lightgroup(ViewLayer *view_layer, ViewLayerLightgroup *lightgroup) +{ + BLI_assert(BLI_findindex(&view_layer->lightgroups, lightgroup) != -1); + BLI_assert(lightgroup != NULL); + if (view_layer->active_lightgroup == lightgroup) { + if (lightgroup->next) { + viewlayer_lightgroup_active_set(view_layer, lightgroup->next); + } + else { + viewlayer_lightgroup_active_set(view_layer, lightgroup->prev); + } + } + BLI_freelinkN(&view_layer->lightgroups, lightgroup); +} + +void BKE_view_layer_set_active_lightgroup(ViewLayer *view_layer, ViewLayerLightgroup *lightgroup) +{ + viewlayer_lightgroup_active_set(view_layer, lightgroup); +} + +ViewLayer *BKE_view_layer_find_with_lightgroup(struct Scene *scene, + struct ViewLayerLightgroup *lightgroup) +{ + LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { + if (BLI_findindex(&view_layer->lightgroups, lightgroup) != -1) { + return view_layer; + } + } + return NULL; +} + +void BKE_view_layer_rename_lightgroup(ViewLayer *view_layer, + ViewLayerLightgroup *lightgroup, + const char *name) +{ + BLI_strncpy_utf8(lightgroup->name, name, sizeof(lightgroup->name)); + viewlayer_lightgroup_make_name_unique(view_layer, lightgroup); +} + +void BKE_lightgroup_membership_get(struct LightgroupMembership *lgm, char *name) +{ + if (lgm != NULL) { + BLI_strncpy(name, lgm->name, sizeof(lgm->name)); + } + else { + name[0] = '\0'; + } +} + +int BKE_lightgroup_membership_length(struct LightgroupMembership *lgm) +{ + if (lgm != NULL) { + return strlen(lgm->name); + } + return 0; +} + +void BKE_lightgroup_membership_set(struct LightgroupMembership **lgm, const char *name) +{ + if (name[0] != '\0') { + if (*lgm == NULL) { + *lgm = MEM_callocN(sizeof(LightgroupMembership), __func__); + } + BLI_strncpy((*lgm)->name, name, sizeof((*lgm)->name)); + } + else { + if (*lgm != NULL) { + MEM_freeN(*lgm); + *lgm = NULL; + } + } +} + /** \} */ diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 28745f1d2c7..27427b1fb44 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -2165,6 +2165,11 @@ bool BKE_id_can_be_asset(const ID *id) BKE_idtype_idcode_is_linkable(GS(id->name)); } +bool BKE_id_is_editable(Main *bmain, ID *id) +{ + return !(ID_IS_LINKED(id) || BKE_lib_override_library_is_system_defined(bmain, id)); +} + /************************* Datablock order in UI **************************/ static int *id_order_get(ID *id) diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 64ebb08f5d0..a2338eb9b39 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -122,6 +122,9 @@ IDOverrideLibrary *BKE_lib_override_library_init(ID *local_id, ID *reference_id) local_id->override_library->reference = reference_id; id_us_plus(local_id->override_library->reference); local_id->tag &= ~LIB_TAG_OVERRIDE_LIBRARY_REFOK; + /* By default initialized liboverrides are 'system overrides', higher-level code is responsible + * to unset this flag for specific IDs. */ + local_id->override_library->flag |= IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED; /* TODO: do we want to add tag or flag to referee to mark it as such? */ return local_id->override_library; } @@ -276,6 +279,44 @@ bool BKE_lib_override_library_is_user_edited(struct ID *id) return false; } +bool BKE_lib_override_library_is_system_defined(Main *bmain, ID *id) +{ + + if (ID_IS_OVERRIDE_LIBRARY(id)) { + ID *override_owner_id; + lib_override_get(bmain, id, &override_owner_id); + return (override_owner_id->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED) != + 0; + } + return false; +} + +static int foreachid_is_hierarchy_leaf_fn(LibraryIDLinkCallbackData *cb_data) +{ + ID *id_owner = cb_data->id_owner; + ID *id = *cb_data->id_pointer; + bool *is_leaf = cb_data->user_data; + + if (id != NULL && ID_IS_OVERRIDE_LIBRARY_REAL(id) && + id->override_library->hierarchy_root == id_owner->override_library->hierarchy_root) { + *is_leaf = false; + return IDWALK_RET_STOP_ITER; + } + return IDWALK_RET_NOP; +} + +bool BKE_lib_override_library_is_hierarchy_leaf(Main *bmain, ID *id) +{ + if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + bool is_leaf = true; + BKE_library_foreach_ID_link( + bmain, id, foreachid_is_hierarchy_leaf_fn, &is_leaf, IDWALK_READONLY); + return is_leaf; + } + + return false; +} + ID *BKE_lib_override_library_create_from_id(Main *bmain, ID *reference_id, const bool do_tagged_remap) @@ -288,6 +329,7 @@ ID *BKE_lib_override_library_create_from_id(Main *bmain, * mess in case there are a lot of hidden, non-instantiated, non-properly organized dependencies. * Ref T94650. */ local_id->override_library->flag |= IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY; + local_id->override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED; local_id->override_library->hierarchy_root = local_id; if (do_tagged_remap) { @@ -322,6 +364,18 @@ ID *BKE_lib_override_library_create_from_id(Main *bmain, return local_id; } +static void lib_override_prefill_newid_from_existing_overrides(Main *bmain, ID *id_hierarchy_root) +{ + ID *id_iter; + FOREACH_MAIN_ID_BEGIN (bmain, id_iter) { + if (ID_IS_OVERRIDE_LIBRARY_REAL(id_iter) && + id_iter->override_library->hierarchy_root == id_hierarchy_root) { + id_iter->override_library->reference->newid = id_iter; + } + } + FOREACH_MAIN_ID_END; +} + /* TODO: Make this static local function instead? API is becoming complex, and it's not used * outside of this file anyway. */ bool BKE_lib_override_library_create_from_tag(Main *bmain, @@ -345,6 +399,13 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain, * resync process mainly). */ BLI_assert((ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root) && id_hierarchy_root->override_library->reference->lib == id_root_reference->lib)); + + if (!do_no_main) { + /* When processing within Main, set existing overrides in given hierarchy as 'newid' of their + * linked reference. This allows to re-use existing overrides instead of creating new ones in + * partial override cases. */ + lib_override_prefill_newid_from_existing_overrides(bmain, id_hierarchy_root); + } } if (!ELEM(id_hierarchy_root_reference, NULL, id_root_reference)) { /* If the reference hierarchy root is given, it must be from the same library as the reference @@ -1616,6 +1677,8 @@ static bool lib_override_library_resync(Main *bmain, if (ID_IS_OVERRIDE_LIBRARY_REAL(id_override_new)) { BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_override_old)); + id_override_new->override_library->flag = id_override_old->override_library->flag; + /* Copy over overrides rules from old override ID to new one. */ BLI_duplicatelist(&id_override_new->override_library->properties, &id_override_old->override_library->properties); @@ -3021,10 +3084,16 @@ bool BKE_lib_override_library_main_operations_create(Main *bmain, const bool for return create_pool_data.changed; } -static bool lib_override_library_id_reset_do(Main *bmain, ID *id_root) +static bool lib_override_library_id_reset_do(Main *bmain, + ID *id_root, + const bool do_reset_system_override) { bool was_op_deleted = false; + if (do_reset_system_override) { + id_root->override_library->flag |= IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED; + } + LISTBASE_FOREACH_MUTABLE ( IDOverrideLibraryProperty *, op, &id_root->override_library->properties) { bool do_op_delete = true; @@ -3080,13 +3149,15 @@ static bool lib_override_library_id_reset_do(Main *bmain, ID *id_root) return was_op_deleted; } -void BKE_lib_override_library_id_reset(Main *bmain, ID *id_root) +void BKE_lib_override_library_id_reset(Main *bmain, + ID *id_root, + const bool do_reset_system_override) { if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) { return; } - if (lib_override_library_id_reset_do(bmain, id_root)) { + if (lib_override_library_id_reset_do(bmain, id_root, do_reset_system_override)) { if (id_root->override_library->runtime != NULL && (id_root->override_library->runtime->tag & IDOVERRIDE_LIBRARY_RUNTIME_TAG_NEEDS_RELOAD) != 0) { @@ -3096,7 +3167,9 @@ void BKE_lib_override_library_id_reset(Main *bmain, ID *id_root) } } -static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain, ID *id_root) +static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain, + ID *id_root, + const bool do_reset_system_override) { if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) { return; @@ -3105,7 +3178,7 @@ static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain, ID *i void **entry_vp = BLI_ghash_lookup_p(bmain->relations->relations_from_pointers, id_root); if (entry_vp == NULL) { /* This ID is not used by nor using any other ID. */ - lib_override_library_id_reset_do(bmain, id_root); + lib_override_library_id_reset_do(bmain, id_root, do_reset_system_override); return; } @@ -3115,7 +3188,7 @@ static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain, ID *i return; } - lib_override_library_id_reset_do(bmain, id_root); + lib_override_library_id_reset_do(bmain, id_root, do_reset_system_override); /* This way we won't process again that ID, should we encounter it again through another * relationship hierarchy. */ @@ -3132,17 +3205,19 @@ static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain, ID *i if (*to_id_entry->id_pointer.to != NULL) { ID *to_id = *to_id_entry->id_pointer.to; if (to_id->override_library != NULL) { - lib_override_library_id_hierarchy_recursive_reset(bmain, to_id); + lib_override_library_id_hierarchy_recursive_reset(bmain, to_id, do_reset_system_override); } } } } -void BKE_lib_override_library_id_hierarchy_reset(Main *bmain, ID *id_root) +void BKE_lib_override_library_id_hierarchy_reset(Main *bmain, + ID *id_root, + const bool do_reset_system_override) { BKE_main_relations_create(bmain, 0); - lib_override_library_id_hierarchy_recursive_reset(bmain, id_root); + lib_override_library_id_hierarchy_recursive_reset(bmain, id_root, do_reset_system_override); BKE_main_relations_free(bmain); diff --git a/source/blender/blenkernel/intern/lib_override_proxy_conversion.c b/source/blender/blenkernel/intern/lib_override_proxy_conversion.c index dc164313788..5e9d8e8c4d0 100644 --- a/source/blender/blenkernel/intern/lib_override_proxy_conversion.c +++ b/source/blender/blenkernel/intern/lib_override_proxy_conversion.c @@ -62,6 +62,7 @@ bool BKE_lib_override_library_proxy_convert(Main *bmain, ob_proxy->proxy->id.tag |= LIB_TAG_DOIT; ob_proxy->proxy->id.newid = &ob_proxy->id; BKE_lib_override_library_init(&ob_proxy->id, &ob_proxy->proxy->id); + ob_proxy->id.override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED; ob_proxy->proxy->proxy_from = NULL; ob_proxy->proxy = ob_proxy->proxy_group = NULL; diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc index fc484e73967..bf9525d5c90 100644 --- a/source/blender/blenkernel/intern/mesh_convert.cc +++ b/source/blender/blenkernel/intern/mesh_convert.cc @@ -910,20 +910,18 @@ static void curve_to_mesh_eval_ensure(Object &object) * * So we create temporary copy of the object which will use same data as the original bevel, but * will have no modifiers. */ - Object bevel_object; - blender::dna::zero_memory(bevel_object); + Object bevel_object = blender::dna::shallow_zero_initialize<Object>(); if (curve.bevobj != nullptr) { - blender::dna::copy_memory(bevel_object, *curve.bevobj); + bevel_object = blender::dna::shallow_copy(*curve.bevobj); BLI_listbase_clear(&bevel_object.modifiers); BKE_object_runtime_reset(&bevel_object); curve.bevobj = &bevel_object; } /* Same thing for taper. */ - Object taper_object; - blender::dna::zero_memory(taper_object); + Object taper_object = blender::dna::shallow_zero_initialize<Object>(); if (curve.taperobj != nullptr) { - blender::dna::copy_memory(taper_object, *curve.taperobj); + taper_object = blender::dna::shallow_copy(*curve.taperobj); BLI_listbase_clear(&taper_object.modifiers); BKE_object_runtime_reset(&taper_object); curve.taperobj = &taper_object; @@ -1067,8 +1065,7 @@ static Mesh *mesh_new_from_mesh_object_with_layers(Depsgraph *depsgraph, return nullptr; } - Object object_for_eval; - blender::dna::zero_memory(object_for_eval); + Object object_for_eval = blender::dna::shallow_copy(*object); if (object_for_eval.runtime.data_orig != nullptr) { object_for_eval.data = object_for_eval.runtime.data_orig; } diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index 4448bedb57a..ba1004e8371 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -532,7 +532,7 @@ void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, lnors_spacearr->loops_pool = (LinkNode *)BLI_memarena_alloc( mem, sizeof(LinkNode) * (size_t)numLoops); - lnors_spacearr->num_spaces = 0; + lnors_spacearr->spaces_num = 0; } BLI_assert(ELEM(data_type, MLNOR_SPACEARR_BMLOOP_PTR, MLNOR_SPACEARR_LOOP_INDEX)); lnors_spacearr->data_type = data_type; @@ -550,7 +550,7 @@ void BKE_lnor_spacearr_tls_join(MLoopNorSpaceArray *lnors_spacearr, { BLI_assert(lnors_spacearr->data_type == lnors_spacearr_tls->data_type); BLI_assert(lnors_spacearr->mem != lnors_spacearr_tls->mem); - lnors_spacearr->num_spaces += lnors_spacearr_tls->num_spaces; + lnors_spacearr->spaces_num += lnors_spacearr_tls->spaces_num; BLI_memarena_merge(lnors_spacearr->mem, lnors_spacearr_tls->mem); BLI_memarena_free(lnors_spacearr_tls->mem); lnors_spacearr_tls->mem = nullptr; @@ -559,7 +559,7 @@ void BKE_lnor_spacearr_tls_join(MLoopNorSpaceArray *lnors_spacearr, void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr) { - lnors_spacearr->num_spaces = 0; + lnors_spacearr->spaces_num = 0; lnors_spacearr->lspacearr = nullptr; lnors_spacearr->loops_pool = nullptr; if (lnors_spacearr->mem != nullptr) { @@ -569,7 +569,7 @@ void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr) void BKE_lnor_spacearr_free(MLoopNorSpaceArray *lnors_spacearr) { - lnors_spacearr->num_spaces = 0; + lnors_spacearr->spaces_num = 0; lnors_spacearr->lspacearr = nullptr; lnors_spacearr->loops_pool = nullptr; BLI_memarena_free(lnors_spacearr->mem); @@ -578,7 +578,7 @@ void BKE_lnor_spacearr_free(MLoopNorSpaceArray *lnors_spacearr) MLoopNorSpace *BKE_lnor_space_create(MLoopNorSpaceArray *lnors_spacearr) { - lnors_spacearr->num_spaces++; + lnors_spacearr->spaces_num++; return (MLoopNorSpace *)BLI_memarena_calloc(lnors_spacearr->mem, sizeof(MLoopNorSpace)); } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 5af8dfc2b72..395deeda4ad 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -233,11 +233,11 @@ bool BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md) return false; } -bool BKE_modifier_depends_ontime(Scene *scene, ModifierData *md, const int dag_eval_mode) +bool BKE_modifier_depends_ontime(Scene *scene, ModifierData *md) { const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - return mti->dependsOnTime && mti->dependsOnTime(scene, md, dag_eval_mode); + return mti->dependsOnTime && mti->dependsOnTime(scene, md); } bool BKE_modifier_supports_mapping(ModifierData *md) diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc index 098b7c52664..833e6f882f1 100644 --- a/source/blender/blenkernel/intern/object.cc +++ b/source/blender/blenkernel/intern/object.cc @@ -54,6 +54,7 @@ #include "BLI_linklist.h" #include "BLI_listbase.h" #include "BLI_math.h" +#include "BLI_math_vec_types.hh" #include "BLI_threads.h" #include "BLI_utildefines.h" @@ -143,6 +144,8 @@ #include "CCGSubSurf.h" #include "atomic_ops.h" +using blender::float3; + static CLG_LogRef LOG = {"bke.object"}; /** @@ -257,6 +260,10 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in else { ob_dst->preview = nullptr; } + + if (ob_src->lightgroup) { + ob_dst->lightgroup = (LightgroupMembership *)MEM_dupallocN(ob_src->lightgroup); + } } static void object_free_data(ID *id) @@ -307,6 +314,8 @@ static void object_free_data(ID *id) } BKE_previewimg_free(&ob->preview); + + MEM_SAFE_FREE(ob->lightgroup); } static void library_foreach_modifiersForeachIDLink(void *user_data, @@ -581,6 +590,10 @@ static void object_blend_write(BlendWriter *writer, ID *id, const void *id_addre BLO_write_struct_list(writer, LinkData, &ob->pc_ids); BKE_previewimg_blend_write(writer, ob->preview); + + if (ob->lightgroup) { + BLO_write_struct(writer, LightgroupMembership, ob->lightgroup); + } } /* XXX deprecated - old animation system */ @@ -766,7 +779,7 @@ static void object_blend_read_data(BlendDataReader *reader, ID *id) hmd->indexar = hook->indexar; hmd->object = hook->parent; memcpy(hmd->parentinv, hook->parentinv, sizeof(hmd->parentinv)); - hmd->totindex = hook->totindex; + hmd->indexar_num = hook->totindex; BLI_addhead(&ob->modifiers, hmd); BLI_remlink(&ob->hooks, hook); @@ -797,6 +810,8 @@ static void object_blend_read_data(BlendDataReader *reader, ID *id) BLO_read_data_address(reader, &ob->preview); BKE_previewimg_blend_read(reader, ob->preview); + + BLO_read_data_address(reader, &ob->lightgroup); } /* XXX deprecated - old animation system */ @@ -1172,7 +1187,7 @@ static void object_lib_override_apply_post(ID *id_dst, ID *id_src) static IDProperty *object_asset_dimensions_property(Object *ob) { - float dimensions[3]; + float3 dimensions; BKE_object_dimensions_get(ob, dimensions); if (is_zero_v3(dimensions)) { return nullptr; @@ -1236,7 +1251,7 @@ IDTypeInfo IDType_ID_OB = { void BKE_object_workob_clear(Object *workob) { - blender::dna::zero_memory(*workob); + *workob = blender::dna::shallow_zero_initialize<Object>(); workob->scale[0] = workob->scale[1] = workob->scale[2] = 1.0f; workob->dscale[0] = workob->dscale[1] = workob->dscale[2] = 1.0f; @@ -2217,7 +2232,7 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name) } /* We cannot use #BKE_id_new here as we need some custom initialization code. */ - Object *ob = (Object *)BKE_libblock_alloc(bmain, ID_OB, name, 0); + Object *ob = (Object *)BKE_libblock_alloc(bmain, ID_OB, name, bmain ? 0 : LIB_ID_CREATE_NO_MAIN); /* We increase object user count when linking to Collections. */ id_us_min(&ob->id); @@ -2837,7 +2852,7 @@ void BKE_object_obdata_size_init(struct Object *ob, const float size) void BKE_object_scale_to_mat3(Object *ob, float mat[3][3]) { - float vec[3]; + float3 vec; mul_v3_v3v3(vec, ob->scale, ob->dscale); size_to_mat3(mat, vec); } @@ -3119,7 +3134,7 @@ static bool ob_parcurve(Object *ob, Object *par, float r_mat[4][4]) static void ob_parbone(Object *ob, Object *par, float r_mat[4][4]) { - float vec[3]; + float3 vec; if (par->type != OB_ARMATURE) { unit_m4(r_mat); @@ -3540,11 +3555,8 @@ void BKE_object_apply_mat4(Object *ob, BoundBox *BKE_boundbox_alloc_unit() { - const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {1.0f, 1.0f, 1.0f}; - - BoundBox *bb = MEM_cnew<BoundBox>("OB-BoundBox"); - BKE_boundbox_init_from_minmax(bb, min, max); - + BoundBox *bb = MEM_cnew<BoundBox>(__func__); + BKE_boundbox_init_from_minmax(bb, float3(-1), float3(1)); return bb; } @@ -3587,7 +3599,7 @@ void BKE_boundbox_minmax(const BoundBox *bb, } } -BoundBox *BKE_object_boundbox_get(Object *ob) +const BoundBox *BKE_object_boundbox_get(Object *ob) { BoundBox *bb = nullptr; @@ -3627,28 +3639,14 @@ BoundBox *BKE_object_boundbox_get(Object *ob) return bb; } -void BKE_object_boundbox_flag(Object *ob, int flag, const bool set) -{ - BoundBox *bb = BKE_object_boundbox_get(ob); - if (bb) { - if (set) { - bb->flag |= flag; - } - else { - bb->flag &= ~flag; - } - } -} - void BKE_object_boundbox_calc_from_mesh(Object *ob, const Mesh *me_eval) { - float min[3], max[3]; - - INIT_MINMAX(min, max); + float3 min(FLT_MAX); + float3 max(-FLT_MAX); if (!BKE_mesh_wrapper_minmax(me_eval, min, max)) { - zero_v3(min); - zero_v3(max); + min = float3(0); + max = float3(0); } if (ob->runtime.bb == nullptr) { @@ -3662,19 +3660,19 @@ void BKE_object_boundbox_calc_from_mesh(Object *ob, const Mesh *me_eval) bool BKE_object_boundbox_calc_from_evaluated_geometry(Object *ob) { - blender::float3 min, max; - INIT_MINMAX(min, max); + float3 min(FLT_MAX); + float3 max(-FLT_MAX); if (ob->runtime.geometry_set_eval) { if (!ob->runtime.geometry_set_eval->compute_boundbox_without_instances(&min, &max)) { - zero_v3(min); - zero_v3(max); + min = float3(0); + max = float3(0); } } else if (const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob)) { if (!BKE_mesh_wrapper_minmax(mesh_eval, min, max)) { - zero_v3(min); - zero_v3(max); + min = float3(0); + max = float3(0); } } else if (ob->runtime.curve_cache) { @@ -3705,10 +3703,9 @@ bool BKE_object_boundbox_calc_from_evaluated_geometry(Object *ob) void BKE_object_dimensions_get(Object *ob, float r_vec[3]) { - BoundBox *bb = BKE_object_boundbox_get(ob); + const BoundBox *bb = BKE_object_boundbox_get(ob); if (bb) { - float scale[3]; - + float3 scale; mat4_to_size(scale, ob->obmat); r_vec[0] = fabsf(scale[0]) * (bb->vec[4][0] - bb->vec[0][0]); @@ -3726,13 +3723,12 @@ void BKE_object_dimensions_set_ex(Object *ob, const float ob_scale_orig[3], const float ob_obmat_orig[4][4]) { - BoundBox *bb = BKE_object_boundbox_get(ob); + const BoundBox *bb = BKE_object_boundbox_get(ob); if (bb) { - float len[3]; - - len[0] = bb->vec[4][0] - bb->vec[0][0]; - len[1] = bb->vec[2][1] - bb->vec[0][1]; - len[2] = bb->vec[1][2] - bb->vec[0][2]; + float3 len; + len.x = bb->vec[4][0] - bb->vec[0][0]; + len.y = bb->vec[2][1] - bb->vec[0][1]; + len.z = bb->vec[1][2] - bb->vec[0][2]; for (int i = 0; i < 3; i++) { if (((1 << i) & axis_mask) == 0) { @@ -3760,26 +3756,25 @@ void BKE_object_dimensions_set(Object *ob, const float value[3], int axis_mask) void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool use_hidden) { - float vec[3]; bool changed = false; switch (ob->type) { case OB_CURVES_LEGACY: case OB_FONT: case OB_SURF: { - BoundBox bb = *BKE_curve_boundbox_get(ob); + const BoundBox bb = *BKE_curve_boundbox_get(ob); BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max); changed = true; break; } case OB_MESH: { - BoundBox bb = *BKE_mesh_boundbox_get(ob); + const BoundBox bb = *BKE_mesh_boundbox_get(ob); BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max); changed = true; break; } case OB_GPENCIL: { - BoundBox bb = *BKE_gpencil_boundbox_get(ob); + const BoundBox bb = *BKE_gpencil_boundbox_get(ob); BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max); changed = true; break; @@ -3792,6 +3787,7 @@ void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool us for (w = 0; w < lt->pntsw; w++) { for (v = 0; v < lt->pntsv; v++) { for (u = 0; u < lt->pntsu; u++, bp++) { + float3 vec; mul_v3_m4v3(vec, ob->obmat, bp->vec); minmax_v3v3_v3(r_min, r_max, vec); } @@ -3815,20 +3811,20 @@ void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool us break; } case OB_CURVES: { - BoundBox bb = *BKE_curves_boundbox_get(ob); + const BoundBox bb = *BKE_curves_boundbox_get(ob); BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max); changed = true; break; } case OB_POINTCLOUD: { - BoundBox bb = *BKE_pointcloud_boundbox_get(ob); + const BoundBox bb = *BKE_pointcloud_boundbox_get(ob); BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max); changed = true; break; } case OB_VOLUME: { - BoundBox bb = *BKE_volume_boundbox_get(ob); + const BoundBox bb = *BKE_volume_boundbox_get(ob); BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max); changed = true; break; @@ -3836,15 +3832,16 @@ void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool us } if (changed == false) { - float size[3]; + float3 size = ob->scale; copy_v3_v3(size, ob->scale); if (ob->type == OB_EMPTY) { - mul_v3_fl(size, ob->empty_drawsize); + size *= ob->empty_drawsize; } minmax_v3v3_v3(r_min, r_max, ob->obmat[3]); + float3 vec; copy_v3_v3(vec, ob->obmat[3]); add_v3_v3(vec, size); minmax_v3v3_v3(r_min, r_max, vec); @@ -3895,7 +3892,7 @@ bool BKE_object_empty_image_data_is_visible_in_view3d(const Object *ob, const Re /* NOTE: we could normalize the 'view_dir' then use 'eps' * however the issue with empty objects being visible when viewed from the side * is only noticeable in orthographic views. */ - float view_dir[3]; + float3 view_dir; sub_v3_v3v3(view_dir, rv3d->viewinv[3], ob->obmat[3]); dot = dot_v3v3(ob->obmat[2], view_dir); eps = 0.0f; @@ -3917,7 +3914,7 @@ bool BKE_object_empty_image_data_is_visible_in_view3d(const Object *ob, const Re } if (visibility_flag & OB_EMPTY_IMAGE_HIDE_NON_AXIS_ALIGNED) { - float proj[3]; + float3 proj; project_plane_v3_v3v3(proj, ob->obmat[2], rv3d->viewinv[2]); const float proj_length_sq = len_squared_v3(proj); if (proj_length_sq > 1e-5f) { @@ -3950,12 +3947,12 @@ bool BKE_object_minmax_dupli(Depsgraph *depsgraph, /* Do not modify the original boundbox. */ temp_ob.runtime.bb = nullptr; BKE_object_replace_data_on_shallow_copy(&temp_ob, dob->ob_data); - BoundBox *bb = BKE_object_boundbox_get(&temp_ob); + const BoundBox *bb = BKE_object_boundbox_get(&temp_ob); if (bb) { int i; for (i = 0; i < 8; i++) { - float vec[3]; + float3 vec; mul_v3_m4v3(vec, dob->mat, bb->vec[i]); minmax_v3v3_v3(r_min, r_max, vec); } @@ -3988,7 +3985,7 @@ static void foreach_display_point_gpencil_stroke_fn(bGPDlayer *UNUSED(layer), bGPDspoint *pt; int i; for (i = 0, pt = stroke->points; i < stroke->totpoints; i++, pt++) { - float co[3]; + float3 co; mul_v3_m4v3(co, iter_data->obmat, &pt->x); iter_data->point_func_cb(co, iter_data->user_data); } @@ -4000,9 +3997,9 @@ void BKE_object_foreach_display_point(Object *ob, void (*func_cb)(const float[3], void *), void *user_data) { - /* TODO: pointcloud and hair objects support */ + /* TODO: pointcloud and curves object support */ const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); - float co[3]; + float3 co; if (mesh_eval != nullptr) { const MVert *mv = mesh_eval->mvert; @@ -5236,12 +5233,9 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot) /** \name Object Modifier Utilities * \{ */ -bool BKE_object_modifier_use_time(Scene *scene, - Object *ob, - ModifierData *md, - const int dag_eval_mode) +bool BKE_object_modifier_use_time(Scene *scene, Object *ob, ModifierData *md) { - if (BKE_modifier_depends_ontime(scene, md, dag_eval_mode)) { + if (BKE_modifier_depends_ontime(scene, md)) { return true; } diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc index 009a7bd70be..327035971d5 100644 --- a/source/blender/blenkernel/intern/object_dupli.cc +++ b/source/blender/blenkernel/intern/object_dupli.cc @@ -766,68 +766,6 @@ static const DupliGenerator gen_dupli_verts_font = { /** \} */ /* -------------------------------------------------------------------- */ -/** \name Dupli-Vertices Implementation (#OB_DUPLIVERTS for #PointCloud) - * \{ */ - -static void make_child_duplis_pointcloud(const DupliContext *ctx, - void *UNUSED(userdata), - Object *child) -{ - const Object *parent = ctx->object; - const PointCloud *pointcloud = (PointCloud *)parent->data; - const float(*co)[3] = pointcloud->co; - const float *radius = pointcloud->radius; - const float(*rotation)[4] = nullptr; /* TODO: add optional rotation attribute. */ - const float(*orco)[3] = nullptr; /* TODO: add optional texture coordinate attribute. */ - - /* Relative transform from parent to child space. */ - float child_imat[4][4]; - mul_m4_m4m4(child_imat, child->imat, parent->obmat); - - for (int i = 0; i < pointcloud->totpoint; i++) { - /* Transform matrix from point position, radius and rotation. */ - float quat[4] = {1.0f, 0.0f, 0.0f, 0.0f}; - float size[3] = {1.0f, 1.0f, 1.0f}; - if (radius) { - copy_v3_fl(size, radius[i]); - } - if (rotation) { - copy_v4_v4(quat, rotation[i]); - } - - float space_mat[4][4]; - loc_quat_size_to_mat4(space_mat, co[i], quat, size); - - /* Make offset relative to child object using relative child transform, - * and apply object matrix after local vertex transform. */ - mul_mat3_m4_v3(child_imat, space_mat[3]); - - /* Create dupli object. */ - float obmat[4][4]; - mul_m4_m4m4(obmat, child->obmat, space_mat); - DupliObject *dob = make_dupli(ctx, child, obmat, i); - if (orco) { - copy_v3_v3(dob->orco, orco[i]); - } - - /* Recursion. */ - make_recursive_duplis(ctx, child, space_mat, i); - } -} - -static void make_duplis_pointcloud(const DupliContext *ctx) -{ - make_child_duplis(ctx, nullptr, make_child_duplis_pointcloud); -} - -static const DupliGenerator gen_dupli_verts_pointcloud = { - OB_DUPLIVERTS, /* type */ - make_duplis_pointcloud /* make_duplis */ -}; - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Instances Geometry Component Implementation * \{ */ @@ -1654,9 +1592,6 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx) if (ctx->object->type == OB_MESH) { return &gen_dupli_verts; } - if (ctx->object->type == OB_POINTCLOUD) { - return &gen_dupli_verts_pointcloud; - } } else if (transflag & OB_DUPLIFACES) { if (ctx->object->type == OB_MESH) { diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 3bc2139ca0c..fbbd429f58a 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -243,7 +243,7 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o /** Bounding box from evaluated geometry. */ static void object_sync_boundbox_to_original(Object *object_orig, Object *object_eval) { - BoundBox *bb = object_eval->runtime.bb; + const BoundBox *bb = object_eval->runtime.bb; if (!bb || (bb->flag & BOUNDBOX_DIRTY)) { BKE_object_boundbox_calc_from_evaluated_geometry(object_eval); } diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index c21b525f628..60cc4ce83af 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -473,7 +473,6 @@ static rbCollisionShape *rigidbody_validate_sim_shape_helper(RigidBodyWorld *rbw { RigidBodyOb *rbo = ob->rigidbody_object; rbCollisionShape *new_shape = NULL; - BoundBox *bb = NULL; float size[3] = {1.0f, 1.0f, 1.0f}; float radius = 1.0f; float height = 1.0f; @@ -494,7 +493,7 @@ static rbCollisionShape *rigidbody_validate_sim_shape_helper(RigidBodyWorld *rbw */ /* XXX: all dimensions are auto-determined now... later can add stored settings for this */ /* get object dimensions without scaling */ - bb = BKE_object_boundbox_get(ob); + const BoundBox *bb = BKE_object_boundbox_get(ob); if (bb) { size[0] = (bb->vec[4][0] - bb->vec[0][0]); size[1] = (bb->vec[2][1] - bb->vec[0][1]); @@ -1678,7 +1677,7 @@ static void rigidbody_update_sim_ob( if (mesh) { MVert *mvert = mesh->mvert; int totvert = mesh->totvert; - BoundBox *bb = BKE_object_boundbox_get(ob); + const BoundBox *bb = BKE_object_boundbox_get(ob); RB_shape_trimesh_update(rbo->shared->physics_shape, (float *)mvert, diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.cc index b98c82e365e..685d24cee38 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.cc @@ -8,9 +8,9 @@ /* Allow using deprecated functionality for .blend file I/O. */ #define DNA_DEPRECATED_ALLOW -#include <stddef.h> -#include <stdio.h> -#include <string.h> +#include <cstddef> +#include <cstdio> +#include <cstring> #include "MEM_guardedalloc.h" @@ -139,7 +139,7 @@ static void scene_init_data(ID *id) scene->toolsettings->autokey_mode = (uchar)U.autokey_mode; - /* grease pencil multiframe falloff curve */ + /* Grease pencil multi-frame falloff curve. */ scene->toolsettings->gp_sculpt.cur_falloff = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); CurveMapping *gp_falloff_curve = scene->toolsettings->gp_sculpt.cur_falloff; BKE_curvemapping_init(gp_falloff_curve); @@ -183,11 +183,11 @@ static void scene_init_data(ID *id) /* multiview - stereo */ BKE_scene_add_render_view(scene, STEREO_LEFT_NAME); - srv = scene->r.views.first; + srv = static_cast<SceneRenderView *>(scene->r.views.first); BLI_strncpy(srv->suffix, STEREO_LEFT_SUFFIX, sizeof(srv->suffix)); BKE_scene_add_render_view(scene, STEREO_RIGHT_NAME); - srv = scene->r.views.last; + srv = static_cast<SceneRenderView *>(scene->r.views.last); BLI_strncpy(srv->suffix, STEREO_RIGHT_SUFFIX, sizeof(srv->suffix)); BKE_sound_reset_scene_runtime(scene); @@ -218,14 +218,14 @@ static void scene_init_data(ID *id) /* Master Collection */ scene->master_collection = BKE_collection_master_add(); - BKE_view_layer_add(scene, "ViewLayer", NULL, VIEWLAYER_ADD_NEW); + BKE_view_layer_add(scene, "ViewLayer", nullptr, VIEWLAYER_ADD_NEW); } static void scene_copy_markers(Scene *scene_dst, const Scene *scene_src, const int flag) { BLI_duplicatelist(&scene_dst->markers, &scene_src->markers); LISTBASE_FOREACH (TimeMarker *, marker, &scene_dst->markers) { - if (marker->prop != NULL) { + if (marker->prop != nullptr) { marker->prop = IDP_CopyProperty_ex(marker->prop, flag); } } @@ -240,9 +240,9 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int /* We always need allocation of our private ID data. */ const int flag_private_id_data = flag & ~LIB_ID_CREATE_NO_ALLOCATE; - scene_dst->ed = NULL; - scene_dst->depsgraph_hash = NULL; - scene_dst->fps_info = NULL; + scene_dst->ed = nullptr; + scene_dst->depsgraph_hash = nullptr; + scene_dst->fps_info = nullptr; /* Master Collection */ if (scene_src->master_collection) { @@ -254,8 +254,8 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int /* View Layers */ BLI_duplicatelist(&scene_dst->view_layers, &scene_src->view_layers); - for (ViewLayer *view_layer_src = scene_src->view_layers.first, - *view_layer_dst = scene_dst->view_layers.first; + for (ViewLayer *view_layer_src = static_cast<ViewLayer *>(scene_src->view_layers.first), + *view_layer_dst = static_cast<ViewLayer *>(scene_dst->view_layers.first); view_layer_src; view_layer_src = view_layer_src->next, view_layer_dst = view_layer_dst->next) { BKE_view_layer_copy_data(scene_dst, scene_src, view_layer_dst, view_layer_src, flag_subdata); @@ -299,7 +299,8 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int /* make a private copy of the avicodecdata */ if (scene_src->r.avicodecdata) { - scene_dst->r.avicodecdata = MEM_dupallocN(scene_src->r.avicodecdata); + scene_dst->r.avicodecdata = static_cast<AviCodecData *>( + MEM_dupallocN(scene_src->r.avicodecdata)); scene_dst->r.avicodecdata->lpFormat = MEM_dupallocN(scene_dst->r.avicodecdata->lpFormat); scene_dst->r.avicodecdata->lpParms = MEM_dupallocN(scene_dst->r.avicodecdata->lpParms); } @@ -312,7 +313,7 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int /* Copy sequencer, this is local data! */ if (scene_src->ed) { - scene_dst->ed = MEM_callocN(sizeof(*scene_dst->ed), __func__); + scene_dst->ed = MEM_cnew<Editing>(__func__); scene_dst->ed->seqbasep = &scene_dst->ed->seqbase; SEQ_sequence_base_dupli_recursive(scene_src, scene_dst, @@ -326,7 +327,7 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int BKE_previewimg_id_copy(&scene_dst->id, &scene_src->id); } else { - scene_dst->preview = NULL; + scene_dst->preview = nullptr; } BKE_scene_copy_data_eevee(scene_dst, scene_src); @@ -335,7 +336,7 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int static void scene_free_markers(Scene *scene, bool do_id_user) { LISTBASE_FOREACH_MUTABLE (TimeMarker *, marker, &scene->markers) { - if (marker->prop != NULL) { + if (marker->prop != nullptr) { IDP_FreePropertyContent_ex(marker->prop, do_id_user); MEM_freeN(marker->prop); } @@ -357,22 +358,22 @@ static void scene_free_data(ID *id) if (scene->nodetree) { ntreeFreeEmbeddedTree(scene->nodetree); MEM_freeN(scene->nodetree); - scene->nodetree = NULL; + scene->nodetree = nullptr; } if (scene->rigidbody_world) { /* Prevent rigidbody freeing code to follow other IDs pointers, this should never be allowed * nor necessary from here, and with new undo code, those pointers may be fully invalid or * worse, pointing to data actually belonging to new BMain! */ - scene->rigidbody_world->constraints = NULL; - scene->rigidbody_world->group = NULL; + scene->rigidbody_world->constraints = nullptr; + scene->rigidbody_world->group = nullptr; BKE_rigidbody_free_world(scene); } if (scene->r.avicodecdata) { free_avicodecdata(scene->r.avicodecdata); MEM_freeN(scene->r.avicodecdata); - scene->r.avicodecdata = NULL; + scene->r.avicodecdata = nullptr; } scene_free_markers(scene, do_id_user); @@ -380,7 +381,7 @@ static void scene_free_data(ID *id) BLI_freelistN(&scene->r.views); BKE_toolsettings_free(scene->toolsettings); - scene->toolsettings = NULL; + scene->toolsettings = nullptr; BKE_scene_free_depsgraph_hash(scene); @@ -395,10 +396,7 @@ static void scene_free_data(ID *id) BKE_previewimg_free(&scene->preview); BKE_curvemapping_free_data(&scene->r.mblur_shutter_curve); - for (ViewLayer *view_layer = scene->view_layers.first, *view_layer_next; view_layer; - view_layer = view_layer_next) { - view_layer_next = view_layer->next; - + LISTBASE_FOREACH_MUTABLE (ViewLayer *, view_layer, &scene->view_layers) { BLI_remlink(&scene->view_layers, view_layer); BKE_view_layer_free_ex(view_layer, do_id_user); } @@ -412,21 +410,21 @@ static void scene_free_data(ID *id) BKE_collection_free_data(scene->master_collection); BKE_libblock_free_data_py(&scene->master_collection->id); MEM_freeN(scene->master_collection); - scene->master_collection = NULL; + scene->master_collection = nullptr; } if (scene->eevee.light_cache_data) { EEVEE_lightcache_free(scene->eevee.light_cache_data); - scene->eevee.light_cache_data = NULL; + scene->eevee.light_cache_data = nullptr; } if (scene->display.shading.prop) { IDP_FreeProperty(scene->display.shading.prop); - scene->display.shading.prop = NULL; + scene->display.shading.prop = nullptr; } - /* These are freed on doversion. */ - BLI_assert(scene->layer_properties == NULL); + /* These are freed on `do_versions`. */ + BLI_assert(scene->layer_properties == nullptr); } static void scene_foreach_rigidbodyworldSceneLooper(struct RigidBodyWorld *UNUSED(rbw), @@ -443,14 +441,14 @@ static void scene_foreach_rigidbodyworldSceneLooper(struct RigidBodyWorld *UNUSE * This code is shared by both the regular `foreach_id` looper, and the code trying to restore or * preserve ID pointers like brushes across undo-steps. */ -typedef enum eSceneForeachUndoPreserveProcess { +enum eSceneForeachUndoPreserveProcess { /* Undo when preserving tool-settings from old scene, we also want to try to preserve that ID * pointer from its old scene's value. */ SCENE_FOREACH_UNDO_RESTORE, /* Undo when preserving tool-settings from old scene, we want to keep the new value of that ID * pointer. */ SCENE_FOREACH_UNDO_NO_RESTORE, -} eSceneForeachUndoPreserveProcess; +}; static void scene_foreach_toolsettings_id_pointer_process( ID **id_p, @@ -464,9 +462,10 @@ static void scene_foreach_toolsettings_id_pointer_process( ID *id_old = *id_old_p; /* Old data has not been remapped to new values of the pointers, if we want to keep the old * pointer here we need its new address. */ - ID *id_old_new = id_old != NULL ? BLO_read_get_new_id_address(reader, id_old->lib, id_old) : - NULL; - if (id_old_new != NULL) { + ID *id_old_new = id_old != nullptr ? + BLO_read_get_new_id_address(reader, id_old->lib, id_old) : + nullptr; + if (id_old_new != nullptr) { BLI_assert(ELEM(id_old, id_old_new, id_old_new->orig_id)); *id_old_p = id_old_new; if (cb_flag & IDWALK_CB_USER) { @@ -489,7 +488,7 @@ static void scene_foreach_toolsettings_id_pointer_process( /* Special handling is needed here, as `scene_foreach_toolsettings` (and its dependency * `scene_foreach_paint`) are also used by `scene_undo_preserve`, where `LibraryForeachIDData - * *data` is NULL. */ + * *data` is nullptr. */ #define BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER( \ __data, __id, __do_undo_restore, __action, __reader, __id_old, __cb_flag) \ { \ @@ -498,7 +497,7 @@ static void scene_foreach_toolsettings_id_pointer_process( (ID **)&(__id), __action, __reader, (ID **)&(__id_old), __cb_flag); \ } \ else { \ - BLI_assert((__data) != NULL); \ + BLI_assert((__data) != nullptr); \ BKE_LIB_FOREACHID_PROCESS_IDSUPER(__data, __id, __cb_flag); \ } \ } \ @@ -511,7 +510,7 @@ static void scene_foreach_toolsettings_id_pointer_process( __func_call; \ } \ else { \ - BLI_assert((__data) != NULL); \ + BLI_assert((__data) != nullptr); \ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(__data, __func_call); \ } \ } \ @@ -536,10 +535,10 @@ static void scene_foreach_paint(LibraryForeachIDData *data, * this is equivalent to simply looping over slots from `paint`. * - In case we do `undo_restore`, we only want to consider the slots from the old one, since * those are the one we keep in the end. - * + In case the new data has less valid slots, we feed in a dummy NULL pointer. + * + In case the new data has less valid slots, we feed in a dummy null pointer. * + In case the new data has more valid slots, the extra ones are ignored. */ - Brush *brush_tmp = NULL; + Brush *brush_tmp = nullptr; Brush **brush_p = i < paint->tool_slots_len ? &paint->tool_slots[i].brush : &brush_tmp; BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data, *brush_p, @@ -725,7 +724,7 @@ static void scene_foreach_layer_collection(LibraryForeachIDData *data, ListBase LISTBASE_FOREACH (LayerCollection *, lc, lb) { /* XXX This is very weak. The whole idea of keeping pointers to private IDs is very bad * anyway... */ - const int cb_flag = (lc->collection != NULL && + const int cb_flag = (lc->collection != nullptr && (lc->collection->id.flag & LIB_EMBEDDED_DATA) != 0) ? IDWALK_CB_EMBEDDED : IDWALK_CB_NOP; @@ -760,7 +759,7 @@ static bool seq_foreach_member_id_cb(Sequence *seq, void *user_data) } if (seq->type == SEQ_TYPE_TEXT && seq->effectdata) { - TextVars *text_data = seq->effectdata; + TextVars *text_data = static_cast<TextVars *>(seq->effectdata); FOREACHID_PROCESS_IDSUPER(data, text_data->text_font, IDWALK_CB_USER); } @@ -792,8 +791,8 @@ static void scene_foreach_id(ID *id, LibraryForeachIDData *data) BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, BKE_keyingsets_foreach_id(data, &scene->keyingsets)); - /* This pointer can be NULL during old files reading, better be safe than sorry. */ - if (scene->master_collection != NULL) { + /* This pointer can be nullptr during old files reading, better be safe than sorry. */ + if (scene->master_collection != nullptr) { BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( data, BKE_library_foreach_ID_embedded(data, (ID **)&scene->master_collection)); } @@ -839,7 +838,7 @@ static void scene_foreach_id(ID *id, LibraryForeachIDData *data) ToolSettings *toolsett = scene->toolsettings; if (toolsett) { BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( - data, scene_foreach_toolsettings(data, toolsett, false, NULL, toolsett)); + data, scene_foreach_toolsettings(data, toolsett, false, nullptr, toolsett)); } if (scene->rigidbody_world) { @@ -855,11 +854,10 @@ static void scene_foreach_cache(ID *id, void *user_data) { Scene *scene = (Scene *)id; - IDCacheKey key = { - .id_session_uuid = id->session_uuid, - .offset_in_ID = offsetof(Scene, eevee.light_cache_data), - .cache_v = scene->eevee.light_cache_data, - }; + IDCacheKey key{}; + key.id_session_uuid = id->session_uuid; + key.offset_in_ID = offsetof(Scene, eevee.light_cache_data); + key.cache_v = scene->eevee.light_cache_data; function_callback(id, &key, @@ -902,7 +900,7 @@ static bool seq_foreach_path_callback(Sequence *seq, void *user_data) static void scene_foreach_path(ID *id, BPathForeachPathData *bpath_data) { Scene *scene = (Scene *)id; - if (scene->ed != NULL) { + if (scene->ed != nullptr) { SEQ_for_each_callback(&scene->ed->seqbase, seq_foreach_path_callback, bpath_data); } } @@ -969,7 +967,7 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres if (tos->gp_interpolate.custom_ipo) { BKE_curvemapping_blend_write(writer, tos->gp_interpolate.custom_ipo); } - /* write grease-pencil multiframe falloff curve to file */ + /* write grease-pencil multi-frame falloff curve to file */ if (tos->gp_sculpt.cur_falloff) { BKE_curvemapping_blend_write(writer, tos->gp_sculpt.cur_falloff); } @@ -1012,7 +1010,7 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres LISTBASE_FOREACH (TimeMarker *, marker, &sce->markers) { BLO_write_struct(writer, TimeMarker, marker); - if (marker->prop != NULL) { + if (marker->prop != nullptr) { IDP_BlendWrite(writer, marker->prop); } } @@ -1060,7 +1058,7 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres BKE_collection_blend_write_nolib(writer, sce->master_collection); } - /* Eevee Lightcache */ + /* Eevee Light-cache */ if (sce->eevee.light_cache_data && !BLO_write_is_undo(writer)) { BLO_write_struct(writer, LightCache, sce->eevee.light_cache_data); EEVEE_lightcache_blend_write(writer, sce->eevee.light_cache_data); @@ -1068,8 +1066,8 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres BKE_screen_view3d_shading_blend_write(writer, &sce->display.shading); - /* Freed on doversion. */ - BLI_assert(sce->layer_properties == NULL); + /* Freed on `do_versions()`. */ + BLI_assert(sce->layer_properties == nullptr); } static void direct_link_paint_helper(BlendDataReader *reader, const Scene *scene, Paint **paint) @@ -1102,8 +1100,8 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id) { Scene *sce = (Scene *)id; - sce->depsgraph_hash = NULL; - sce->fps_info = NULL; + sce->depsgraph_hash = nullptr; + sce->fps_info = nullptr; memset(&sce->customdata_mask, 0, sizeof(sce->customdata_mask)); memset(&sce->customdata_mask_modal, 0, sizeof(sce->customdata_mask_modal)); @@ -1144,28 +1142,28 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id) BKE_paint_blend_read_data(reader, sce, &sce->toolsettings->imapaint.paint); - sce->toolsettings->particle.paintcursor = NULL; - sce->toolsettings->particle.scene = NULL; - sce->toolsettings->particle.object = NULL; - sce->toolsettings->gp_sculpt.paintcursor = NULL; + sce->toolsettings->particle.paintcursor = nullptr; + sce->toolsettings->particle.scene = nullptr; + sce->toolsettings->particle.object = nullptr; + sce->toolsettings->gp_sculpt.paintcursor = nullptr; - /* relink grease pencil interpolation curves */ + /* Relink grease pencil interpolation curves. */ BLO_read_data_address(reader, &sce->toolsettings->gp_interpolate.custom_ipo); if (sce->toolsettings->gp_interpolate.custom_ipo) { BKE_curvemapping_blend_read(reader, sce->toolsettings->gp_interpolate.custom_ipo); } - /* relink grease pencil multiframe falloff curve */ + /* Relink grease pencil multi-frame falloff curve. */ BLO_read_data_address(reader, &sce->toolsettings->gp_sculpt.cur_falloff); if (sce->toolsettings->gp_sculpt.cur_falloff) { BKE_curvemapping_blend_read(reader, sce->toolsettings->gp_sculpt.cur_falloff); } - /* relink grease pencil primitive curve */ + /* Relink grease pencil primitive curve. */ BLO_read_data_address(reader, &sce->toolsettings->gp_sculpt.cur_primitive); if (sce->toolsettings->gp_sculpt.cur_primitive) { BKE_curvemapping_blend_read(reader, sce->toolsettings->gp_sculpt.cur_primitive); } - /* Relink toolsettings curve profile */ + /* Relink toolsettings curve profile. */ BLO_read_data_address(reader, &sce->toolsettings->custom_bevel_profile_preset); if (sce->toolsettings->custom_bevel_profile_preset) { BKE_curveprofile_blend_read(reader, sce->toolsettings->custom_bevel_profile_preset); @@ -1181,9 +1179,9 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id) Editing *ed = sce->ed; BLO_read_data_address(reader, &ed->act_seq); - ed->cache = NULL; - ed->prefetch_job = NULL; - ed->runtime.sequence_lookup = NULL; + ed->cache = nullptr; + ed->prefetch_job = nullptr; + ed->runtime.sequence_lookup = nullptr; /* recursive link sequences, lb will be correctly initialized */ link_recurs_seq(reader, &ed->seqbase); @@ -1275,9 +1273,9 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id) if (rbw) { BLO_read_data_address(reader, &rbw->shared); - if (rbw->shared == NULL) { + if (rbw->shared == nullptr) { /* Link deprecated caches if they exist, so we can use them for versioning. - * We should only do this when rbw->shared == NULL, because those pointers + * We should only do this when rbw->shared == nullptr, because those pointers * are always set (for compatibility with older Blenders). We mustn't link * the same pointcache twice. */ BKE_ptcache_blend_read_data(reader, &rbw->ptcaches, &rbw->pointcache, false); @@ -1291,7 +1289,7 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id) /* must nullify the reference to physics sim object, since it no-longer exist * (and will need to be recalculated) */ - rbw->shared->physics_world = NULL; + rbw->shared->physics_world = nullptr; /* link caches */ BKE_ptcache_blend_read_data(reader, &rbw->shared->ptcaches, &rbw->shared->pointcache, false); @@ -1301,13 +1299,13 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id) rbw->ltime = (float)rbw->shared->pointcache->startframe; } } - rbw->objects = NULL; + rbw->objects = nullptr; rbw->numbodies = 0; /* set effector weights */ BLO_read_data_address(reader, &rbw->effector_weights); if (!rbw->effector_weights) { - rbw->effector_weights = BKE_effector_add_weights(NULL); + rbw->effector_weights = BKE_effector_add_weights(nullptr); } } @@ -1352,7 +1350,7 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id) static void composite_patch(bNodeTree *ntree, Scene *scene) { LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - if (node->id == NULL && + if (node->id == nullptr && ((node->type == CMP_NODE_R_LAYERS) || (node->type == CMP_NODE_CRYPTOMATTE && node->custom1 == CMP_CRYPTOMATTE_SRC_RENDER))) { node->id = &scene->id; @@ -1423,14 +1421,14 @@ static void scene_blend_read_lib(BlendLibReader *reader, ID *id) LISTBASE_FOREACH_MUTABLE (Base *, base_legacy, &sce->base) { BLO_read_id_address(reader, sce->id.lib, &base_legacy->object); - if (base_legacy->object == NULL) { + if (base_legacy->object == nullptr) { BLO_reportf_wrap(BLO_read_lib_reports(reader), RPT_WARNING, TIP_("LIB: object lost from scene: '%s'"), sce->id.name + 2); BLI_remlink(&sce->base, base_legacy); if (base_legacy == sce->basact) { - sce->basact = NULL; + sce->basact = nullptr; } MEM_freeN(base_legacy); } @@ -1494,7 +1492,7 @@ static void scene_blend_read_lib(BlendLibReader *reader, ID *id) } #ifdef USE_SETSCENE_CHECK - if (sce->set != NULL) { + if (sce->set != nullptr) { sce->flag |= SCE_READFILE_LIBLINK_NEED_SETSCENE_CHECK; } #endif @@ -1588,12 +1586,12 @@ static void scene_undo_preserve(BlendLibReader *reader, ID *id_new, ID *id_old) Scene *scene_old = (Scene *)id_old; SWAP(View3DCursor, scene_old->cursor, scene_new->cursor); - if (scene_new->toolsettings != NULL && scene_old->toolsettings != NULL) { + if (scene_new->toolsettings != nullptr && scene_old->toolsettings != nullptr) { /* First try to restore ID pointers that can be and should be preserved (like brushes or * palettes), and counteract the swap of the whole ToolSettings structs below for the others * (like object ones). */ scene_foreach_toolsettings( - NULL, scene_new->toolsettings, true, reader, scene_old->toolsettings); + nullptr, scene_new->toolsettings, true, reader, scene_old->toolsettings); SWAP(ToolSettings, *scene_old->toolsettings, *scene_new->toolsettings); } } @@ -1602,46 +1600,50 @@ static void scene_lib_override_apply_post(ID *id_dst, ID *UNUSED(id_src)) { Scene *scene = (Scene *)id_dst; - if (scene->rigidbody_world != NULL) { + if (scene->rigidbody_world != nullptr) { PTCacheID pid; - BKE_ptcache_id_from_rigidbody(&pid, NULL, scene->rigidbody_world); + BKE_ptcache_id_from_rigidbody(&pid, nullptr, scene->rigidbody_world); LISTBASE_FOREACH (PointCache *, point_cache, pid.ptcaches) { point_cache->flag |= PTCACHE_FLAG_INFO_DIRTY; } } } -IDTypeInfo IDType_ID_SCE = { - .id_code = ID_SCE, - .id_filter = FILTER_ID_SCE, - .main_listbase_index = INDEX_ID_SCE, - .struct_size = sizeof(Scene), - .name = "Scene", - .name_plural = "scenes", - .translation_context = BLT_I18NCONTEXT_ID_SCENE, - .flags = 0, - .asset_type_info = NULL, +constexpr IDTypeInfo get_type_info() +{ + IDTypeInfo info{}; + info.id_code = ID_SCE; + info.id_filter = FILTER_ID_SCE; + info.main_listbase_index = INDEX_ID_SCE; + info.struct_size = sizeof(Scene); + info.name = "Scene"; + info.name_plural = "scenes"; + info.translation_context = BLT_I18NCONTEXT_ID_SCENE; + info.flags = 0; + info.asset_type_info = nullptr; - .init_data = scene_init_data, - .copy_data = scene_copy_data, - .free_data = scene_free_data, - /* For now default `BKE_lib_id_make_local_generic()` should work, may need more work though to - * support all possible corner cases. */ - .make_local = NULL, - .foreach_id = scene_foreach_id, - .foreach_cache = scene_foreach_cache, - .foreach_path = scene_foreach_path, - .owner_get = NULL, + info.init_data = scene_init_data; + info.copy_data = scene_copy_data; + info.free_data = scene_free_data; + /* For now default `BKE_lib_id_make_local_generic()` should work, may need more work though to + * support all possible corner cases. */ + info.make_local = nullptr; + info.foreach_id = scene_foreach_id; + info.foreach_cache = scene_foreach_cache; + info.foreach_path = scene_foreach_path; + info.owner_get = nullptr; - .blend_write = scene_blend_write, - .blend_read_data = scene_blend_read_data, - .blend_read_lib = scene_blend_read_lib, - .blend_read_expand = scene_blend_read_expand, + info.blend_write = scene_blend_write; + info.blend_read_data = scene_blend_read_data; + info.blend_read_lib = scene_blend_read_lib; + info.blend_read_expand = scene_blend_read_expand; - .blend_read_undo_preserve = scene_undo_preserve, + info.blend_read_undo_preserve = scene_undo_preserve; - .lib_override_apply_post = scene_lib_override_apply_post, -}; + info.lib_override_apply_post = scene_lib_override_apply_post; + return info; +} +IDTypeInfo IDType_ID_SCE = get_type_info(); const char *RE_engine_id_BLENDER_EEVEE = "BLENDER_EEVEE"; const char *RE_engine_id_BLENDER_WORKBENCH = "BLENDER_WORKBENCH"; @@ -1652,12 +1654,12 @@ void free_avicodecdata(AviCodecData *acd) if (acd) { if (acd->lpFormat) { MEM_freeN(acd->lpFormat); - acd->lpFormat = NULL; + acd->lpFormat = nullptr; acd->cbFormat = 0; } if (acd->lpParms) { MEM_freeN(acd->lpParms); - acd->lpParms = NULL; + acd->lpParms = nullptr; acd->cbParms = 0; } } @@ -1668,11 +1670,7 @@ static void remove_sequencer_fcurves(Scene *sce) AnimData *adt = BKE_animdata_from_id(&sce->id); if (adt && adt->action) { - FCurve *fcu, *nextfcu; - - for (fcu = adt->action->curves.first; fcu; fcu = nextfcu) { - nextfcu = fcu->next; - + LISTBASE_FOREACH_MUTABLE (FCurve *, fcu, &adt->action->curves) { if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) { action_groups_remove_channel(adt->action, fcu); BKE_fcurve_free(fcu); @@ -1683,55 +1681,55 @@ static void remove_sequencer_fcurves(Scene *sce) ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag) { - if (toolsettings == NULL) { - return NULL; + if (toolsettings == nullptr) { + return nullptr; } - ToolSettings *ts = MEM_dupallocN(toolsettings); + ToolSettings *ts = static_cast<ToolSettings *>(MEM_dupallocN(toolsettings)); if (ts->vpaint) { - ts->vpaint = MEM_dupallocN(ts->vpaint); + ts->vpaint = static_cast<VPaint *>(MEM_dupallocN(ts->vpaint)); BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint, flag); } if (ts->wpaint) { - ts->wpaint = MEM_dupallocN(ts->wpaint); + ts->wpaint = static_cast<VPaint *>(MEM_dupallocN(ts->wpaint)); BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint, flag); } if (ts->sculpt) { - ts->sculpt = MEM_dupallocN(ts->sculpt); + ts->sculpt = static_cast<Sculpt *>(MEM_dupallocN(ts->sculpt)); BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint, flag); } if (ts->uvsculpt) { - ts->uvsculpt = MEM_dupallocN(ts->uvsculpt); + ts->uvsculpt = static_cast<UvSculpt *>(MEM_dupallocN(ts->uvsculpt)); BKE_paint_copy(&ts->uvsculpt->paint, &ts->uvsculpt->paint, flag); } if (ts->gp_paint) { - ts->gp_paint = MEM_dupallocN(ts->gp_paint); + ts->gp_paint = static_cast<GpPaint *>(MEM_dupallocN(ts->gp_paint)); BKE_paint_copy(&ts->gp_paint->paint, &ts->gp_paint->paint, flag); } if (ts->gp_vertexpaint) { - ts->gp_vertexpaint = MEM_dupallocN(ts->gp_vertexpaint); + ts->gp_vertexpaint = static_cast<GpVertexPaint *>(MEM_dupallocN(ts->gp_vertexpaint)); BKE_paint_copy(&ts->gp_vertexpaint->paint, &ts->gp_vertexpaint->paint, flag); } if (ts->gp_sculptpaint) { - ts->gp_sculptpaint = MEM_dupallocN(ts->gp_sculptpaint); + ts->gp_sculptpaint = static_cast<GpSculptPaint *>(MEM_dupallocN(ts->gp_sculptpaint)); BKE_paint_copy(&ts->gp_sculptpaint->paint, &ts->gp_sculptpaint->paint, flag); } if (ts->gp_weightpaint) { - ts->gp_weightpaint = MEM_dupallocN(ts->gp_weightpaint); + ts->gp_weightpaint = static_cast<GpWeightPaint *>(MEM_dupallocN(ts->gp_weightpaint)); BKE_paint_copy(&ts->gp_weightpaint->paint, &ts->gp_weightpaint->paint, flag); } if (ts->curves_sculpt) { - ts->curves_sculpt = MEM_dupallocN(ts->curves_sculpt); + ts->curves_sculpt = static_cast<CurvesSculpt *>(MEM_dupallocN(ts->curves_sculpt)); BKE_paint_copy(&ts->curves_sculpt->paint, &ts->curves_sculpt->paint, flag); } BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, flag); - ts->particle.paintcursor = NULL; - ts->particle.scene = NULL; - ts->particle.object = NULL; + ts->particle.paintcursor = nullptr; + ts->particle.scene = nullptr; + ts->particle.object = nullptr; /* duplicate Grease Pencil interpolation curve */ ts->gp_interpolate.custom_ipo = BKE_curvemapping_copy(ts->gp_interpolate.custom_ipo); - /* Duplicate Grease Pencil multiframe falloff. */ + /* Duplicate Grease Pencil multi-frame falloff. */ ts->gp_sculpt.cur_falloff = BKE_curvemapping_copy(ts->gp_sculpt.cur_falloff); ts->gp_sculpt.cur_primitive = BKE_curvemapping_copy(ts->gp_sculpt.cur_primitive); @@ -1743,7 +1741,7 @@ ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag) void BKE_toolsettings_free(ToolSettings *toolsettings) { - if (toolsettings == NULL) { + if (toolsettings == nullptr) { return; } if (toolsettings->vpaint) { @@ -1788,7 +1786,7 @@ void BKE_toolsettings_free(ToolSettings *toolsettings) if (toolsettings->gp_interpolate.custom_ipo) { BKE_curvemapping_free(toolsettings->gp_interpolate.custom_ipo); } - /* free Grease Pencil multiframe falloff curve */ + /* free Grease Pencil multi-frame falloff curve */ if (toolsettings->gp_sculpt.cur_falloff) { BKE_curvemapping_free(toolsettings->gp_sculpt.cur_falloff); } @@ -1811,7 +1809,7 @@ void BKE_scene_copy_data_eevee(Scene *sce_dst, const Scene *sce_src) { /* Copy eevee data between scenes. */ sce_dst->eevee = sce_src->eevee; - sce_dst->eevee.light_cache_data = NULL; + sce_dst->eevee.light_cache_data = nullptr; sce_dst->eevee.light_cache_info[0] = '\0'; /* TODO: Copy the cache. */ } @@ -1862,7 +1860,7 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type) /* make a private copy of the avicodecdata */ if (sce->r.avicodecdata) { - sce_copy->r.avicodecdata = MEM_dupallocN(sce->r.avicodecdata); + sce_copy->r.avicodecdata = static_cast<AviCodecData *>(MEM_dupallocN(sce->r.avicodecdata)); sce_copy->r.avicodecdata->lpFormat = MEM_dupallocN(sce_copy->r.avicodecdata->lpFormat); sce_copy->r.avicodecdata->lpParms = MEM_dupallocN(sce_copy->r.avicodecdata->lpParms); } @@ -1870,14 +1868,14 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type) BKE_sound_reset_scene_runtime(sce_copy); /* grease pencil */ - sce_copy->gpd = NULL; + sce_copy->gpd = nullptr; - sce_copy->preview = NULL; + sce_copy->preview = nullptr; return sce_copy; } - eDupli_ID_Flags duplicate_flags = U.dupflag | USER_DUP_OBJECT; + eDupli_ID_Flags duplicate_flags = (eDupli_ID_Flags)(U.dupflag | USER_DUP_OBJECT); sce_copy = (Scene *)BKE_id_copy(bmain, (ID *)sce); id_us_min(&sce_copy->id); @@ -1900,7 +1898,7 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type) /* In case root duplicated ID is linked, assume we want to get a local copy of it and * duplicate all expected linked data. */ if (ID_IS_LINKED(sce)) { - duplicate_flags |= USER_DUP_LINKED_ID; + duplicate_flags = (eDupli_ID_Flags)(duplicate_flags | USER_DUP_LINKED_ID); } } @@ -1919,22 +1917,25 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type) /* Deep-duplicate collections and objects (using preferences' settings for which sub-data to * duplicate along the object itself). */ - BKE_collection_duplicate( - bmain, NULL, sce_copy->master_collection, duplicate_flags, LIB_ID_DUPLICATE_IS_SUBPROCESS); + BKE_collection_duplicate(bmain, + nullptr, + sce_copy->master_collection, + duplicate_flags, + LIB_ID_DUPLICATE_IS_SUBPROCESS); /* Rigid body world collections may not be instantiated as scene's collections, ensure they * also get properly duplicated. */ - if (sce_copy->rigidbody_world != NULL) { - if (sce_copy->rigidbody_world->group != NULL) { + if (sce_copy->rigidbody_world != nullptr) { + if (sce_copy->rigidbody_world->group != nullptr) { BKE_collection_duplicate(bmain, - NULL, + nullptr, sce_copy->rigidbody_world->group, duplicate_flags, LIB_ID_DUPLICATE_IS_SUBPROCESS); } - if (sce_copy->rigidbody_world->constraints != NULL) { + if (sce_copy->rigidbody_world->constraints != nullptr) { BKE_collection_duplicate(bmain, - NULL, + nullptr, sce_copy->rigidbody_world->constraints, duplicate_flags, LIB_ID_DUPLICATE_IS_SUBPROCESS); @@ -1995,9 +1996,7 @@ bool BKE_scene_can_be_removed(const Main *bmain, const Scene *scene) Scene *BKE_scene_add(Main *bmain, const char *name) { - Scene *sce; - - sce = BKE_id_new(bmain, ID_SCE, name); + Scene *sce = static_cast<Scene *>(BKE_id_new(bmain, ID_SCE, name)); id_us_min(&sce->id); id_us_ensure_real(&sce->id); @@ -2023,25 +2022,22 @@ Object *BKE_scene_object_find_by_name(const Scene *scene, const char *name) } } } - return NULL; + return nullptr; } void BKE_scene_set_background(Main *bmain, Scene *scene) { - Object *ob; - /* check for cyclic sets, for reading old files but also for definite security (py?) */ BKE_scene_validate_setscene(bmain, scene); - /* deselect objects (for dataselect) */ - for (ob = bmain->objects.first; ob; ob = ob->id.next) { + /* Deselect objects (for data select). */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { ob->flag &= ~SELECT; } /* copy layers and flags from bases to objects */ LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { - ob = base->object; /* collection patch... */ BKE_scene_object_base_flag_sync_from_base(base); } @@ -2060,7 +2056,7 @@ Scene *BKE_scene_set_name(Main *bmain, const char *name) } printf("Can't find scene: '%s' in file: '%s'\n", name, BKE_main_blendfile_path(bmain)); - return NULL; + return nullptr; } int BKE_scene_base_iter_next( @@ -2071,9 +2067,9 @@ int BKE_scene_base_iter_next( /* init */ if (val == 0) { iter->phase = F_START; - iter->dupob = NULL; - iter->duplilist = NULL; - iter->dupli_refob = NULL; + iter->dupob = nullptr; + iter->duplilist = nullptr; + iter->dupli_refob = nullptr; } else { /* run_again is set when a duplilist has been ended */ @@ -2084,7 +2080,7 @@ int BKE_scene_base_iter_next( if (iter->phase == F_START) { ViewLayer *view_layer = (depsgraph) ? DEG_get_evaluated_view_layer(depsgraph) : BKE_view_layer_context_active_PLACEHOLDER(*scene); - *base = view_layer->object_bases.first; + *base = static_cast<Base *>(view_layer->object_bases.first); if (*base) { *ob = (*base)->object; iter->phase = F_SCENE; @@ -2095,7 +2091,7 @@ int BKE_scene_base_iter_next( (*scene) = (*scene)->set; ViewLayer *view_layer_set = BKE_view_layer_default_render(*scene); if (view_layer_set->object_bases.first) { - *base = view_layer_set->object_bases.first; + *base = static_cast<Base *>(view_layer_set->object_bases.first); *ob = (*base)->object; iter->phase = F_SCENE; break; @@ -2116,7 +2112,7 @@ int BKE_scene_base_iter_next( (*scene) = (*scene)->set; ViewLayer *view_layer_set = BKE_view_layer_default_render(*scene); if (view_layer_set->object_bases.first) { - *base = view_layer_set->object_bases.first; + *base = static_cast<Base *>(view_layer_set->object_bases.first); *ob = (*base)->object; break; } @@ -2126,7 +2122,7 @@ int BKE_scene_base_iter_next( } } - if (*base == NULL) { + if (*base == nullptr) { iter->phase = F_START; } else { @@ -2135,16 +2131,16 @@ int BKE_scene_base_iter_next( /* Collections cannot be duplicated for meta-balls yet, * this enters eternal loop because of * makeDispListMBall getting called inside of collection_duplilist */ - if ((*base)->object->instance_collection == NULL) { + if ((*base)->object->instance_collection == nullptr) { iter->duplilist = object_duplilist(depsgraph, (*scene), (*base)->object); - iter->dupob = iter->duplilist->first; + iter->dupob = static_cast<DupliObject *>(iter->duplilist->first); if (!iter->dupob) { free_object_duplilist(iter->duplilist); - iter->duplilist = NULL; + iter->duplilist = nullptr; } - iter->dupli_refob = NULL; + iter->dupli_refob = nullptr; } } } @@ -2174,11 +2170,11 @@ int BKE_scene_base_iter_next( if (iter->dupli_refob) { /* Restore last object's real matrix. */ copy_m4_m4(iter->dupli_refob->obmat, iter->omat); - iter->dupli_refob = NULL; + iter->dupli_refob = nullptr; } free_object_duplilist(iter->duplilist); - iter->duplilist = NULL; + iter->duplilist = nullptr; run_again = true; } } @@ -2195,7 +2191,7 @@ bool BKE_scene_has_view_layer(const Scene *scene, const ViewLayer *layer) Scene *BKE_scene_find_from_collection(const Main *bmain, const Collection *collection) { - for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { LISTBASE_FOREACH (ViewLayer *, layer, &scene->view_layers) { if (BKE_view_layer_has_collection(layer, collection)) { return scene; @@ -2203,21 +2199,21 @@ Scene *BKE_scene_find_from_collection(const Main *bmain, const Collection *colle } } - return NULL; + return nullptr; } #ifdef DURIAN_CAMERA_SWITCH Object *BKE_scene_camera_switch_find(Scene *scene) { if (scene->r.mode & R_NO_CAMERA_SWITCH) { - return NULL; + return nullptr; } const int ctime = (int)BKE_scene_ctime_get(scene); int frame = -(MAXFRAME + 1); int min_frame = MAXFRAME + 1; - Object *camera = NULL; - Object *first_camera = NULL; + Object *camera = nullptr; + Object *first_camera = nullptr; LISTBASE_FOREACH (TimeMarker *, m, &scene->markers) { if (m->camera && (m->camera->visibility_flag & OB_HIDE_RENDER) == 0) { @@ -2237,7 +2233,7 @@ Object *BKE_scene_camera_switch_find(Scene *scene) } } - if (camera == NULL) { + if (camera == nullptr) { /* If there's no marker to the left of current frame, * use camera from left-most marker to solve all sort * of Schrodinger uncertainties. @@ -2270,7 +2266,10 @@ const char *BKE_scene_find_marker_name(const Scene *scene, int frame) const TimeMarker *m1, *m2; /* search through markers for match */ - for (m1 = markers->first, m2 = markers->last; m1 && m2; m1 = m1->next, m2 = m2->prev) { + for (m1 = static_cast<const TimeMarker *>(markers->first), + m2 = static_cast<const TimeMarker *>(markers->last); + m1 && m2; + m1 = m1->next, m2 = m2->prev) { if (m1->frame == frame) { return m1->name; } @@ -2284,14 +2283,14 @@ const char *BKE_scene_find_marker_name(const Scene *scene, int frame) } } - return NULL; + return nullptr; } const char *BKE_scene_find_last_marker_name(const Scene *scene, int frame) { - const TimeMarker *marker, *best_marker = NULL; + const TimeMarker *best_marker = nullptr; int best_frame = -MAXFRAME * 2; - for (marker = scene->markers.first; marker; marker = marker->next) { + LISTBASE_FOREACH (const TimeMarker *, marker, &scene->markers) { if (marker->frame == frame) { return marker->name; } @@ -2302,7 +2301,7 @@ const char *BKE_scene_find_last_marker_name(const Scene *scene, int frame) } } - return best_marker ? best_marker->name : NULL; + return best_marker ? best_marker->name : nullptr; } int BKE_scene_frame_snap_by_seconds(Scene *scene, double interval_in_seconds, int frame) @@ -2335,7 +2334,7 @@ bool BKE_scene_validate_setscene(Main *bmain, Scene *sce) Scene *sce_iter; int a, totscene; - if (sce->set == NULL) { + if (sce->set == nullptr) { return true; } totscene = BLI_listbase_count(&bmain->scenes); @@ -2344,7 +2343,7 @@ bool BKE_scene_validate_setscene(Main *bmain, Scene *sce) /* more iterations than scenes means we have a cycle */ if (a > totscene) { /* the tested scene gets zero'ed, that's typically current scene */ - sce->set = NULL; + sce->set = nullptr; return false; } } @@ -2437,9 +2436,8 @@ int BKE_scene_orientation_get_index_from_flag(Scene *scene, int flag) static bool check_rendered_viewport_visible(Main *bmain) { - wmWindowManager *wm = bmain->wm.first; - wmWindow *window; - for (window = wm->windows.first; window != NULL; window = window->next) { + wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first); + LISTBASE_FOREACH (const wmWindow *, window, &wm->windows) { const bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook); Scene *scene = window->scene; RenderEngineType *type = RE_engines_find(scene->r.engine); @@ -2448,8 +2446,8 @@ static bool check_rendered_viewport_visible(Main *bmain) continue; } - for (ScrArea *area = screen->areabase.first; area != NULL; area = area->next) { - View3D *v3d = area->spacedata.first; + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + View3D *v3d = static_cast<View3D *>(area->spacedata.first); if (area->spacetype != SPACE_VIEW3D) { continue; } @@ -2462,7 +2460,7 @@ static bool check_rendered_viewport_visible(Main *bmain) } /* TODO(campbell): shouldn't we be able to use 'DEG_get_view_layer' here? - * Currently this is NULL on load, so don't. */ + * Currently this is nullptr on load, so don't. */ static void prepare_mesh_for_viewport_render(Main *bmain, const ViewLayer *view_layer) { /* This is needed to prepare mesh to be used by the render @@ -2476,18 +2474,15 @@ static void prepare_mesh_for_viewport_render(Main *bmain, const ViewLayer *view_ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); if (obedit) { - Mesh *mesh = obedit->data; + Mesh *mesh = static_cast<Mesh *>(obedit->data); if ((obedit->type == OB_MESH) && ((obedit->id.recalc & ID_RECALC_ALL) || (mesh->id.recalc & ID_RECALC_ALL))) { if (check_rendered_viewport_visible(bmain)) { BMesh *bm = mesh->edit_mesh->bm; - BM_mesh_bm_to_me(bmain, - bm, - mesh, - (&(struct BMeshToMeshParams){ - .calc_object_remap = true, - .update_shapekey_indices = true, - })); + BMeshToMeshParams params{}; + params.calc_object_remap = true; + params.update_shapekey_indices = true; + BM_mesh_bm_to_me(bmain, bm, mesh, ¶ms); DEG_id_tag_update(&mesh->id, 0); } } @@ -2630,7 +2625,7 @@ void BKE_scene_graph_update_for_newframe_ex(Depsgraph *depsgraph, const bool cle BKE_sound_set_cfra(scene->r.cfra); DEG_graph_relations_update(depsgraph); /* Update all objects: drivers, matrices, #DispList, etc. flags set - * by depgraph or manual, no layer check here, gets correct flushed. + * by depsgraph or manual, no layer check here, gets correct flushed. * * NOTE: Only update for new frame on first iteration. Second iteration is for ensuring user * edits from callback are properly taken into account. Doing a time update on those would @@ -2697,13 +2692,11 @@ void BKE_scene_view_layer_graph_evaluated_ensure(Main *bmain, Scene *scene, View SceneRenderView *BKE_scene_add_render_view(Scene *sce, const char *name) { - SceneRenderView *srv; - if (!name) { name = DATA_("RenderView"); } - srv = MEM_callocN(sizeof(SceneRenderView), "new render view"); + SceneRenderView *srv = MEM_cnew<SceneRenderView>(__func__); BLI_strncpy(srv->name, name, sizeof(srv->name)); BLI_uniquename(&sce->r.views, srv, @@ -2770,7 +2763,7 @@ Base *_setlooper_base_step(Scene **sce_iter, ViewLayer *view_layer, Base *base) /* Common case, step to the next. */ return base->next; } - if ((base == NULL) && (view_layer != NULL)) { + if ((base == nullptr) && (view_layer != nullptr)) { /* First time looping, return the scenes first base. */ /* For the first loop we should get the layer from workspace when available. */ if (view_layer->object_bases.first) { @@ -2792,7 +2785,7 @@ Base *_setlooper_base_step(Scene **sce_iter, ViewLayer *view_layer, Base *base) } } - return NULL; + return nullptr; } bool BKE_scene_use_shading_nodes_custom(Scene *scene) @@ -2823,10 +2816,10 @@ bool BKE_scene_uses_cycles(const Scene *scene) } /* This enumeration has to match the one defined in the Cycles addon. */ -typedef enum eCyclesFeatureSet { +enum eCyclesFeatureSet { CYCLES_FEATURES_SUPPORTED = 0, CYCLES_FEATURES_EXPERIMENTAL = 1, -} eCyclesFeatureSet; +}; bool BKE_scene_uses_cycles_experimental_features(Scene *scene) { @@ -2845,7 +2838,7 @@ bool BKE_scene_uses_cycles_experimental_features(Scene *scene) void BKE_scene_base_flag_to_objects(ViewLayer *view_layer) { - Base *base = view_layer->object_bases.first; + Base *base = static_cast<Base *>(view_layer->object_bases.first); while (base) { BKE_scene_object_base_flag_sync_from_base(base); @@ -2954,7 +2947,6 @@ double BKE_scene_unit_scale(const UnitSettings *unit, const int unit_type, doubl int BKE_scene_multiview_num_views_get(const RenderData *rd) { - SceneRenderView *srv; int totviews = 0; if ((rd->scemode & R_MULTIVIEW) == 0) { @@ -2962,18 +2954,20 @@ int BKE_scene_multiview_num_views_get(const RenderData *rd) } if (rd->views_format == SCE_VIEWS_FORMAT_STEREO_3D) { - srv = BLI_findstring(&rd->views, STEREO_LEFT_NAME, offsetof(SceneRenderView, name)); + SceneRenderView *srv = static_cast<SceneRenderView *>( + BLI_findstring(&rd->views, STEREO_LEFT_NAME, offsetof(SceneRenderView, name))); if ((srv && srv->viewflag & SCE_VIEW_DISABLE) == 0) { totviews++; } - srv = BLI_findstring(&rd->views, STEREO_RIGHT_NAME, offsetof(SceneRenderView, name)); + srv = static_cast<SceneRenderView *>( + BLI_findstring(&rd->views, STEREO_RIGHT_NAME, offsetof(SceneRenderView, name))); if ((srv && srv->viewflag & SCE_VIEW_DISABLE) == 0) { totviews++; } } else { - for (srv = rd->views.first; srv; srv = srv->next) { + LISTBASE_FOREACH (SceneRenderView *, srv, &rd->views) { if ((srv->viewflag & SCE_VIEW_DISABLE) == 0) { totviews++; } @@ -3001,7 +2995,7 @@ bool BKE_scene_multiview_is_stereo3d(const RenderData *rd) bool BKE_scene_multiview_is_render_view_active(const RenderData *rd, const SceneRenderView *srv) { - if (srv == NULL) { + if (srv == nullptr) { return false; } @@ -3027,8 +3021,6 @@ bool BKE_scene_multiview_is_render_view_active(const RenderData *rd, const Scene bool BKE_scene_multiview_is_render_view_first(const RenderData *rd, const char *viewname) { - SceneRenderView *srv; - if ((rd->scemode & R_MULTIVIEW) == 0) { return true; } @@ -3037,7 +3029,7 @@ bool BKE_scene_multiview_is_render_view_first(const RenderData *rd, const char * return true; } - for (srv = rd->views.first; srv; srv = srv->next) { + LISTBASE_FOREACH (const SceneRenderView *, srv, &rd->views) { if (BKE_scene_multiview_is_render_view_active(rd, srv)) { return STREQ(viewname, srv->name); } @@ -3048,8 +3040,6 @@ bool BKE_scene_multiview_is_render_view_first(const RenderData *rd, const char * bool BKE_scene_multiview_is_render_view_last(const RenderData *rd, const char *viewname) { - SceneRenderView *srv; - if ((rd->scemode & R_MULTIVIEW) == 0) { return true; } @@ -3058,7 +3048,7 @@ bool BKE_scene_multiview_is_render_view_last(const RenderData *rd, const char *v return true; } - for (srv = rd->views.last; srv; srv = srv->prev) { + LISTBASE_FOREACH_BACKWARD (const SceneRenderView *, srv, &rd->views) { if (BKE_scene_multiview_is_render_view_active(rd, srv)) { return STREQ(viewname, srv->name); } @@ -3073,10 +3063,10 @@ SceneRenderView *BKE_scene_multiview_render_view_findindex(const RenderData *rd, size_t nr; if ((rd->scemode & R_MULTIVIEW) == 0) { - return NULL; + return nullptr; } - for (srv = rd->views.first, nr = 0; srv; srv = srv->next) { + for (srv = static_cast<SceneRenderView *>(rd->views.first), nr = 0; srv; srv = srv->next) { if (BKE_scene_multiview_is_render_view_active(rd, srv)) { if (nr++ == view_id) { return srv; @@ -3110,7 +3100,7 @@ int BKE_scene_multiview_view_id_get(const RenderData *rd, const char *viewname) return 0; } - for (srv = rd->views.first, nr = 0; srv; srv = srv->next) { + for (srv = static_cast<SceneRenderView *>(rd->views.first), nr = 0; srv; srv = srv->next) { if (BKE_scene_multiview_is_render_view_active(rd, srv)) { if (STREQ(viewname, srv->name)) { return nr; @@ -3139,7 +3129,8 @@ void BKE_scene_multiview_view_filepath_get(const RenderData *rd, SceneRenderView *srv; char suffix[FILE_MAX]; - srv = BLI_findstring(&rd->views, viewname, offsetof(SceneRenderView, name)); + srv = static_cast<SceneRenderView *>( + BLI_findstring(&rd->views, viewname, offsetof(SceneRenderView, name))); if (srv) { BLI_strncpy(suffix, srv->suffix, sizeof(suffix)); } @@ -3155,11 +3146,12 @@ const char *BKE_scene_multiview_view_suffix_get(const RenderData *rd, const char { SceneRenderView *srv; - if ((viewname == NULL) || (viewname[0] == '\0')) { + if ((viewname == nullptr) || (viewname[0] == '\0')) { return viewname; } - srv = BLI_findstring(&rd->views, viewname, offsetof(SceneRenderView, name)); + srv = static_cast<SceneRenderView *>( + BLI_findstring(&rd->views, viewname, offsetof(SceneRenderView, name))); if (srv) { return srv->suffix; } @@ -3182,7 +3174,6 @@ void BKE_scene_multiview_view_prefix_get(Scene *scene, char *r_prefix, const char **r_ext) { - SceneRenderView *srv; size_t index_act; const char *suf_act; const char delims[] = {'.', '\0'}; @@ -3191,13 +3182,13 @@ void BKE_scene_multiview_view_prefix_get(Scene *scene, /* begin of extension */ index_act = BLI_str_rpartition(name, delims, r_ext, &suf_act); - if (*r_ext == NULL) { + if (*r_ext == nullptr) { return; } BLI_assert(index_act > 0); UNUSED_VARS_NDEBUG(index_act); - for (srv = scene->r.views.first; srv; srv = srv->next) { + LISTBASE_FOREACH (SceneRenderView *, srv, &scene->r.views) { if (BKE_scene_multiview_is_render_view_active(&scene->r, srv)) { const size_t len = strlen(srv->suffix); const size_t ext_len = strlen(*r_ext); @@ -3250,16 +3241,16 @@ int BKE_scene_multiview_num_videos_get(const RenderData *rd) /* Manipulation of depsgraph storage. */ /* This is a key which identifies depsgraph. */ -typedef struct DepsgraphKey { +struct DepsgraphKey { const ViewLayer *view_layer; /* TODO(sergey): Need to include window somehow (same layer might be in a * different states in different windows). */ -} DepsgraphKey; +}; static unsigned int depsgraph_key_hash(const void *key_v) { - const DepsgraphKey *key = key_v; + const DepsgraphKey *key = static_cast<const DepsgraphKey *>(key_v); unsigned int hash = BLI_ghashutil_ptrhash(key->view_layer); /* TODO(sergey): Include hash from other fields in the key. */ return hash; @@ -3267,21 +3258,21 @@ static unsigned int depsgraph_key_hash(const void *key_v) static bool depsgraph_key_compare(const void *key_a_v, const void *key_b_v) { - const DepsgraphKey *key_a = key_a_v; - const DepsgraphKey *key_b = key_b_v; + const DepsgraphKey *key_a = static_cast<const DepsgraphKey *>(key_a_v); + const DepsgraphKey *key_b = static_cast<const DepsgraphKey *>(key_b_v); /* TODO(sergey): Compare rest of. */ return !(key_a->view_layer == key_b->view_layer); } static void depsgraph_key_free(void *key_v) { - DepsgraphKey *key = key_v; + DepsgraphKey *key = static_cast<DepsgraphKey *>(key_v); MEM_freeN(key); } static void depsgraph_key_value_free(void *value) { - Depsgraph *depsgraph = value; + Depsgraph *depsgraph = static_cast<Depsgraph *>(value); DEG_graph_free(depsgraph); } @@ -3293,23 +3284,23 @@ void BKE_scene_allocate_depsgraph_hash(Scene *scene) void BKE_scene_ensure_depsgraph_hash(Scene *scene) { - if (scene->depsgraph_hash == NULL) { + if (scene->depsgraph_hash == nullptr) { BKE_scene_allocate_depsgraph_hash(scene); } } void BKE_scene_free_depsgraph_hash(Scene *scene) { - if (scene->depsgraph_hash == NULL) { + if (scene->depsgraph_hash == nullptr) { return; } BLI_ghash_free(scene->depsgraph_hash, depsgraph_key_free, depsgraph_key_value_free); - scene->depsgraph_hash = NULL; + scene->depsgraph_hash = nullptr; } void BKE_scene_free_view_layer_depsgraph(Scene *scene, ViewLayer *view_layer) { - if (scene->depsgraph_hash != NULL) { + if (scene->depsgraph_hash != nullptr) { DepsgraphKey key = {view_layer}; BLI_ghash_remove(scene->depsgraph_hash, &key, depsgraph_key_free, depsgraph_key_value_free); } @@ -3321,17 +3312,17 @@ static Depsgraph **scene_get_depsgraph_p(Scene *scene, ViewLayer *view_layer, const bool allocate_ghash_entry) { - /* bmain may be NULL here! */ - BLI_assert(scene != NULL); - BLI_assert(view_layer != NULL); + /* bmain may be nullptr here! */ + BLI_assert(scene != nullptr); + BLI_assert(view_layer != nullptr); BLI_assert(BKE_scene_has_view_layer(scene, view_layer)); /* Make sure hash itself exists. */ if (allocate_ghash_entry) { BKE_scene_ensure_depsgraph_hash(scene); } - if (scene->depsgraph_hash == NULL) { - return NULL; + if (scene->depsgraph_hash == nullptr) { + return nullptr; } DepsgraphKey key; @@ -3350,23 +3341,23 @@ static Depsgraph **scene_get_depsgraph_p(Scene *scene, } /* Depsgraph was not found in the ghash, but the key still needs allocating. */ - *key_ptr = MEM_mallocN(sizeof(DepsgraphKey), __func__); + *key_ptr = MEM_new<DepsgraphKey>(__func__); **key_ptr = key; - *depsgraph_ptr = NULL; + *depsgraph_ptr = nullptr; return depsgraph_ptr; } static Depsgraph **scene_ensure_depsgraph_p(Main *bmain, Scene *scene, ViewLayer *view_layer) { - BLI_assert(bmain != NULL); + BLI_assert(bmain != nullptr); Depsgraph **depsgraph_ptr = scene_get_depsgraph_p(scene, view_layer, true); - if (depsgraph_ptr == NULL) { + if (depsgraph_ptr == nullptr) { /* The scene has no depsgraph hash. */ - return NULL; + return nullptr; } - if (*depsgraph_ptr != NULL) { + if (*depsgraph_ptr != nullptr) { /* The depsgraph was found, no need to allocate. */ return depsgraph_ptr; } @@ -3393,25 +3384,25 @@ Depsgraph *BKE_scene_get_depsgraph(const Scene *scene, const ViewLayer *view_lay { BLI_assert(BKE_scene_has_view_layer(scene, view_layer)); - if (scene->depsgraph_hash == NULL) { - return NULL; + if (scene->depsgraph_hash == nullptr) { + return nullptr; } DepsgraphKey key; key.view_layer = view_layer; - return BLI_ghash_lookup(scene->depsgraph_hash, &key); + return static_cast<Depsgraph *>(BLI_ghash_lookup(scene->depsgraph_hash, &key)); } Depsgraph *BKE_scene_ensure_depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer) { Depsgraph **depsgraph_ptr = scene_ensure_depsgraph_p(bmain, scene, view_layer); - return (depsgraph_ptr != NULL) ? *depsgraph_ptr : NULL; + return (depsgraph_ptr != nullptr) ? *depsgraph_ptr : nullptr; } static char *scene_undo_depsgraph_gen_key(Scene *scene, ViewLayer *view_layer, char *key_full) { - if (key_full == NULL) { - key_full = MEM_callocN(MAX_ID_NAME + FILE_MAX + MAX_NAME, __func__); + if (key_full == nullptr) { + key_full = static_cast<char *>(MEM_callocN(MAX_ID_NAME + FILE_MAX + MAX_NAME, __func__)); } size_t key_full_offset = BLI_strncpy_rlen(key_full, scene->id.name, MAX_ID_NAME); @@ -3430,24 +3421,23 @@ GHash *BKE_scene_undo_depsgraphs_extract(Main *bmain) GHash *depsgraph_extract = BLI_ghash_new( BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, __func__); - for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) { - if (scene->depsgraph_hash == NULL) { + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + if (scene->depsgraph_hash == nullptr) { /* In some cases, e.g. when undo has to perform multiple steps at once, no depsgraph will - * be built so this pointer may be NULL. */ + * be built so this pointer may be nullptr. */ continue; } - for (ViewLayer *view_layer = scene->view_layers.first; view_layer != NULL; - view_layer = view_layer->next) { + LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { DepsgraphKey key; key.view_layer = view_layer; Depsgraph **depsgraph = (Depsgraph **)BLI_ghash_lookup_p(scene->depsgraph_hash, &key); - if (depsgraph != NULL && *depsgraph != NULL) { - char *key_full = scene_undo_depsgraph_gen_key(scene, view_layer, NULL); + if (depsgraph != nullptr && *depsgraph != nullptr) { + char *key_full = scene_undo_depsgraph_gen_key(scene, view_layer, nullptr); /* We steal the depsgraph from the scene. */ BLI_ghash_insert(depsgraph_extract, key_full, *depsgraph); - *depsgraph = NULL; + *depsgraph = nullptr; } } } @@ -3457,22 +3447,21 @@ GHash *BKE_scene_undo_depsgraphs_extract(Main *bmain) void BKE_scene_undo_depsgraphs_restore(Main *bmain, GHash *depsgraph_extract) { - for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) { - for (ViewLayer *view_layer = scene->view_layers.first; view_layer != NULL; - view_layer = view_layer->next) { + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { char key_full[MAX_ID_NAME + FILE_MAX + MAX_NAME] = {0}; scene_undo_depsgraph_gen_key(scene, view_layer, key_full); Depsgraph **depsgraph_extract_ptr = (Depsgraph **)BLI_ghash_lookup_p(depsgraph_extract, key_full); - if (depsgraph_extract_ptr == NULL) { + if (depsgraph_extract_ptr == nullptr) { continue; } - BLI_assert(*depsgraph_extract_ptr != NULL); + BLI_assert(*depsgraph_extract_ptr != nullptr); Depsgraph **depsgraph_scene_ptr = scene_get_depsgraph_p(scene, view_layer, true); - BLI_assert(depsgraph_scene_ptr != NULL); - BLI_assert(*depsgraph_scene_ptr == NULL); + BLI_assert(depsgraph_scene_ptr != nullptr); + BLI_assert(*depsgraph_scene_ptr == nullptr); /* We steal the depsgraph back from our 'extract' storage to the scene. */ Depsgraph *depsgraph = *depsgraph_extract_ptr; @@ -3482,7 +3471,7 @@ void BKE_scene_undo_depsgraphs_restore(Main *bmain, GHash *depsgraph_extract) DEG_graph_tag_relations_update(depsgraph); *depsgraph_scene_ptr = depsgraph; - *depsgraph_extract_ptr = NULL; + *depsgraph_extract_ptr = nullptr; } } @@ -3515,7 +3504,7 @@ void BKE_scene_transform_orientation_remove(Scene *scene, TransformOrientation * TransformOrientation *BKE_scene_transform_orientation_find(const Scene *scene, const int index) { - return BLI_findlink(&scene->transform_spaces, index); + return static_cast<TransformOrientation *>(BLI_findlink(&scene->transform_spaces, index)); } int BKE_scene_transform_orientation_get_index(const Scene *scene, diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 61ed4233474..91deeda8381 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1469,7 +1469,7 @@ static void ccgdm_create_grids(DerivedMesh *dm) DMFlagMat *gridFlagMats; CCGFace **gridFaces; int *gridOffset; - int index, numFaces, numGrids, S, gIndex /*, gridSize*/; + int index, numFaces, numGrids, S, gIndex /*, gridSize */; if (ccgdm->gridData) { return; diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index ac8b18f3395..cc3ee06f539 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -59,6 +59,8 @@ static void world_free_data(ID *id) BKE_icon_id_delete((struct ID *)wrld); BKE_previewimg_free(&wrld->preview); + + MEM_SAFE_FREE(wrld->lightgroup); } static void world_init_data(ID *id) @@ -107,6 +109,10 @@ static void world_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int else { wrld_dst->preview = NULL; } + + if (wrld_src->lightgroup) { + wrld_dst->lightgroup = (LightgroupMembership *)MEM_dupallocN(wrld_src->lightgroup); + } } static void world_foreach_id(ID *id, LibraryForeachIDData *data) @@ -142,6 +148,10 @@ static void world_blend_write(BlendWriter *writer, ID *id, const void *id_addres } BKE_previewimg_blend_write(writer, wrld->preview); + + if (wrld->lightgroup) { + BLO_write_struct(writer, LightgroupMembership, wrld->lightgroup); + } } static void world_blend_read_data(BlendDataReader *reader, ID *id) @@ -153,6 +163,8 @@ static void world_blend_read_data(BlendDataReader *reader, ID *id) BLO_read_data_address(reader, &wrld->preview); BKE_previewimg_blend_read(reader, wrld->preview); BLI_listbase_clear(&wrld->gpumaterial); + + BLO_read_data_address(reader, &wrld->lightgroup); } static void world_blend_read_lib(BlendLibReader *reader, ID *id) diff --git a/source/blender/blenlib/BLI_bitmap.h b/source/blender/blenlib/BLI_bitmap.h index 38c44193ab3..ca11cd6574e 100644 --- a/source/blender/blenlib/BLI_bitmap.h +++ b/source/blender/blenlib/BLI_bitmap.h @@ -25,33 +25,33 @@ typedef unsigned int BLI_bitmap; #define _BITMAP_MASK 31 /** - * Number of blocks needed to hold '_tot' bits. + * Number of blocks needed to hold '_num' bits. */ -#define _BITMAP_NUM_BLOCKS(_tot) (((_tot) >> _BITMAP_POWER) + 1) +#define _BITMAP_NUM_BLOCKS(_num) (((_num) >> _BITMAP_POWER) + 1) /** - * Size (in bytes) used to hold '_tot' bits. + * Size (in bytes) used to hold '_num' bits. */ -#define BLI_BITMAP_SIZE(_tot) ((size_t)(_BITMAP_NUM_BLOCKS(_tot)) * sizeof(BLI_bitmap)) +#define BLI_BITMAP_SIZE(_num) ((size_t)(_BITMAP_NUM_BLOCKS(_num)) * sizeof(BLI_bitmap)) /** - * Allocate memory for a bitmap with '_tot' bits; free with MEM_freeN(). + * Allocate memory for a bitmap with '_num' bits; free with MEM_freeN(). */ -#define BLI_BITMAP_NEW(_tot, _alloc_string) \ - ((BLI_bitmap *)MEM_callocN(BLI_BITMAP_SIZE(_tot), _alloc_string)) +#define BLI_BITMAP_NEW(_num, _alloc_string) \ + ((BLI_bitmap *)MEM_callocN(BLI_BITMAP_SIZE(_num), _alloc_string)) /** * Allocate a bitmap on the stack. */ -#define BLI_BITMAP_NEW_ALLOCA(_tot) \ - ((BLI_bitmap *)memset(alloca(BLI_BITMAP_SIZE(_tot)), 0, BLI_BITMAP_SIZE(_tot))) +#define BLI_BITMAP_NEW_ALLOCA(_num) \ + ((BLI_bitmap *)memset(alloca(BLI_BITMAP_SIZE(_num)), 0, BLI_BITMAP_SIZE(_num))) /** * Allocate using given MemArena. */ -#define BLI_BITMAP_NEW_MEMARENA(_mem, _tot) \ +#define BLI_BITMAP_NEW_MEMARENA(_mem, _num) \ (CHECK_TYPE_INLINE(_mem, MemArena *), \ - ((BLI_bitmap *)BLI_memarena_calloc(_mem, BLI_BITMAP_SIZE(_tot)))) + ((BLI_bitmap *)BLI_memarena_calloc(_mem, BLI_BITMAP_SIZE(_num)))) /** * Get the value of a single bit at '_index'. @@ -107,12 +107,12 @@ typedef unsigned int BLI_bitmap; (void)0 /** - * Resize bitmap to have space for '_tot' bits. + * Resize bitmap to have space for '_num' bits. */ -#define BLI_BITMAP_RESIZE(_bitmap, _tot) \ +#define BLI_BITMAP_RESIZE(_bitmap, _num) \ { \ CHECK_TYPE(_bitmap, BLI_bitmap *); \ - (_bitmap) = MEM_recallocN(_bitmap, BLI_BITMAP_SIZE(_tot)); \ + (_bitmap) = MEM_recallocN(_bitmap, BLI_BITMAP_SIZE(_num)); \ } \ (void)0 diff --git a/source/blender/blenlib/BLI_cpp_type.hh b/source/blender/blenlib/BLI_cpp_type.hh index 881408f460b..9453eb89a2e 100644 --- a/source/blender/blenlib/BLI_cpp_type.hh +++ b/source/blender/blenlib/BLI_cpp_type.hh @@ -110,6 +110,9 @@ class CPPType : NonCopyable, NonMovable { void (*default_construct_)(void *ptr) = nullptr; void (*default_construct_indices_)(void *ptr, IndexMask mask) = nullptr; + void (*value_initialize_)(void *ptr) = nullptr; + void (*value_initialize_indices_)(void *ptr, IndexMask mask) = nullptr; + void (*destruct_)(void *ptr) = nullptr; void (*destruct_indices_)(void *ptr, IndexMask mask) = nullptr; @@ -326,6 +329,31 @@ class CPPType : NonCopyable, NonMovable { } /** + * Same as #default_construct, but does zero initialization for trivial types. + * + * C++ equivalent: + * new (ptr) T(); + */ + void value_initialize(void *ptr) const + { + BLI_assert(this->pointer_can_point_to_instance(ptr)); + + value_initialize_(ptr); + } + + void value_initialize_n(void *ptr, int64_t n) const + { + this->value_initialize_indices(ptr, IndexMask(n)); + } + + void value_initialize_indices(void *ptr, IndexMask mask) const + { + BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(ptr)); + + value_initialize_indices_(ptr, mask); + } + + /** * Call the destructor on the given instance of this type. The pointer must not be nullptr. * * For some trivial types, this does nothing. @@ -651,9 +679,9 @@ class CPPType : NonCopyable, NonMovable { * compile-time. This allows the compiler to optimize a function for specific types, while all * other types can still use a generic fallback function. * - * \param Types The types that code should be generated for. - * \param fn The function object to call. This is expected to have a templated `operator()` and a - * non-templated `operator()`. The templated version will be called if the current #CPPType + * \param Types: The types that code should be generated for. + * \param fn: The function object to call. This is expected to have a templated `operator()` and + * a non-templated `operator()`. The templated version will be called if the current #CPPType * matches any of the given types. Otherwise, the non-templated function is called. */ template<typename... Types, typename Fn> void to_static_type(const Fn &fn) const diff --git a/source/blender/blenlib/BLI_cpp_type_make.hh b/source/blender/blenlib/BLI_cpp_type_make.hh index 9100b2b9a0f..2612348075b 100644 --- a/source/blender/blenlib/BLI_cpp_type_make.hh +++ b/source/blender/blenlib/BLI_cpp_type_make.hh @@ -20,6 +20,16 @@ template<typename T> void default_construct_indices_cb(void *ptr, IndexMask mask mask.foreach_index([&](int64_t i) { new (static_cast<T *>(ptr) + i) T; }); } +template<typename T> void value_initialize_cb(void *ptr) +{ + new (ptr) T(); +} + +template<typename T> void value_initialize_indices_cb(void *ptr, IndexMask mask) +{ + mask.foreach_index([&](int64_t i) { new (static_cast<T *>(ptr) + i) T(); }); +} + template<typename T> void destruct_cb(void *ptr) { (static_cast<T *>(ptr))->~T(); @@ -186,6 +196,8 @@ CPPType::CPPType(CPPTypeParam<T, Flags> /* unused */, StringRef debug_name) if constexpr (std::is_default_constructible_v<T>) { default_construct_ = default_construct_cb<T>; default_construct_indices_ = default_construct_indices_cb<T>; + value_initialize_ = value_initialize_cb<T>; + value_initialize_indices_ = value_initialize_indices_cb<T>; static T default_value; default_value_ = (void *)&default_value; } diff --git a/source/blender/blenlib/BLI_enumerable_thread_specific.hh b/source/blender/blenlib/BLI_enumerable_thread_specific.hh index 51bf8d06cf1..a5bd79d5826 100644 --- a/source/blender/blenlib/BLI_enumerable_thread_specific.hh +++ b/source/blender/blenlib/BLI_enumerable_thread_specific.hh @@ -3,23 +3,20 @@ #pragma once #ifdef WITH_TBB - -# ifdef WITH_TBB /* Quiet top level deprecation message, unrelated to API usage here. */ -# if defined(WIN32) && !defined(NOMINMAX) +# if defined(WIN32) && !defined(NOMINMAX) /* TBB includes Windows.h which will define min/max macros causing issues * when we try to use std::min and std::max later on. */ -# define NOMINMAX -# define TBB_MIN_MAX_CLEANUP -# endif -# include <tbb/enumerable_thread_specific.h> -# ifdef WIN32 +# define NOMINMAX +# define TBB_MIN_MAX_CLEANUP +# endif +# include <tbb/enumerable_thread_specific.h> +# ifdef WIN32 /* We cannot keep this defined, since other parts of the code deal with this on their own, leading * to multiple define warnings unless we un-define this, however we can only undefine this if we * were the ones that made the definition earlier. */ -# ifdef TBB_MIN_MAX_CLEANUP -# undef NOMINMAX -# endif +# ifdef TBB_MIN_MAX_CLEANUP +# undef NOMINMAX # endif # endif #endif diff --git a/source/blender/blenlib/BLI_generic_span.hh b/source/blender/blenlib/BLI_generic_span.hh index f4f93735e06..4c0bfc83ba8 100644 --- a/source/blender/blenlib/BLI_generic_span.hh +++ b/source/blender/blenlib/BLI_generic_span.hh @@ -164,6 +164,18 @@ class GMutableSpan { { return this->slice(range.start(), range.size()); } + + /** + * Copy all values from another span into this span. This invokes undefined behavior when the + * destination contains uninitialized data and T is not trivially copy constructible. + * The size of both spans is expected to be the same. + */ + void copy_from(GSpan values) + { + BLI_assert(type_ == &values.type()); + BLI_assert(size_ == values.size()); + type_->copy_assign_n(values.data(), data_, size_); + } }; } // namespace blender diff --git a/source/blender/blenlib/BLI_heap.h b/source/blender/blenlib/BLI_heap.h index e8aa95f6aa7..882f40c1850 100644 --- a/source/blender/blenlib/BLI_heap.h +++ b/source/blender/blenlib/BLI_heap.h @@ -25,7 +25,7 @@ typedef void (*HeapFreeFP)(void *ptr); * * \note Use when the size of the heap is known in advance. */ -Heap *BLI_heap_new_ex(unsigned int tot_reserve) ATTR_WARN_UNUSED_RESULT; +Heap *BLI_heap_new_ex(unsigned int reserve_num) ATTR_WARN_UNUSED_RESULT; Heap *BLI_heap_new(void) ATTR_WARN_UNUSED_RESULT; void BLI_heap_clear(Heap *heap, HeapFreeFP ptrfreefp) ATTR_NONNULL(1); void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp) ATTR_NONNULL(1); diff --git a/source/blender/blenlib/BLI_heap_simple.h b/source/blender/blenlib/BLI_heap_simple.h index 79504096d67..4a63a6d624c 100644 --- a/source/blender/blenlib/BLI_heap_simple.h +++ b/source/blender/blenlib/BLI_heap_simple.h @@ -21,7 +21,7 @@ typedef void (*HeapSimpleFreeFP)(void *ptr); * * \note Use when the size of the heap is known in advance. */ -HeapSimple *BLI_heapsimple_new_ex(unsigned int tot_reserve) ATTR_WARN_UNUSED_RESULT; +HeapSimple *BLI_heapsimple_new_ex(unsigned int reserve_num) ATTR_WARN_UNUSED_RESULT; HeapSimple *BLI_heapsimple_new(void) ATTR_WARN_UNUSED_RESULT; void BLI_heapsimple_clear(HeapSimple *heap, HeapSimpleFreeFP ptrfreefp) ATTR_NONNULL(1); void BLI_heapsimple_free(HeapSimple *heap, HeapSimpleFreeFP ptrfreefp) ATTR_NONNULL(1); diff --git a/source/blender/blenlib/BLI_index_mask.hh b/source/blender/blenlib/BLI_index_mask.hh index 3decd8b9441..b87ab0afc98 100644 --- a/source/blender/blenlib/BLI_index_mask.hh +++ b/source/blender/blenlib/BLI_index_mask.hh @@ -163,16 +163,30 @@ class IndexMask { */ template<typename CallbackT> void foreach_index(const CallbackT &callback) const { - if (this->is_range()) { - IndexRange range = this->as_range(); - for (int64_t i : range) { + this->to_best_mask_type([&](const auto &mask) { + for (const int64_t i : mask) { callback(i); } + }); + } + + /** + * Often an #IndexMask wraps a range of indices without any gaps. In this case, it is more + * efficient to compute the indices in a loop on-the-fly instead of reading them from memory. + * This method makes it easy to generate code for both cases. + * + * The given function is expected to take one parameter that can either be of type #IndexRange or + * #Span<int64_t>. + */ + template<typename Fn> void to_best_mask_type(const Fn &fn) const + { + if (this->is_range()) { + const IndexRange masked_range = this->as_range(); + fn(masked_range); } else { - for (int64_t i : indices_) { - callback(i); - } + const Span<int64_t> masked_indices = indices_; + fn(masked_indices); } } diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index 38f3e1ee290..8642d728909 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -181,18 +181,18 @@ int BLI_bvhtree_overlap_thread_num(const BVHTree *tree); */ BVHTreeOverlap *BLI_bvhtree_overlap_ex(const BVHTree *tree1, const BVHTree *tree2, - uint *r_overlap_tot, + uint *r_overlap_num, BVHTree_OverlapCallback callback, void *userdata, uint max_interactions, int flag); BVHTreeOverlap *BLI_bvhtree_overlap(const BVHTree *tree1, const BVHTree *tree2, - unsigned int *r_overlap_tot, + unsigned int *r_overlap_num, BVHTree_OverlapCallback callback, void *userdata); -int *BLI_bvhtree_intersect_plane(BVHTree *tree, float plane[4], uint *r_intersect_tot); +int *BLI_bvhtree_intersect_plane(BVHTree *tree, float plane[4], uint *r_intersect_num); /** * Number of times #BLI_bvhtree_insert has been called. diff --git a/source/blender/blenlib/BLI_length_parameterize.hh b/source/blender/blenlib/BLI_length_parameterize.hh new file mode 100644 index 00000000000..e4a4e9cbb9c --- /dev/null +++ b/source/blender/blenlib/BLI_length_parameterize.hh @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +/** \file + * \ingroup bli + */ + +#include "BLI_math_base.hh" +#include "BLI_math_color.hh" +#include "BLI_math_vector.hh" +#include "BLI_vector.hh" + +namespace blender::length_parameterize { + +/** + * Return the size of the necessary lengths array for a group of points, taking into account the + * possible last cyclic segment. + * + * \note This is the same as #bke::curves::curve_segment_size. + */ +inline int lengths_num(const int points_num, const bool cyclic) +{ + return cyclic ? points_num : points_num - 1; +} + +/** + * Accumulate the length of the next segment into each point. + */ +template<typename T> +void accumulate_lengths(const Span<T> values, const bool cyclic, MutableSpan<float> lengths) +{ + BLI_assert(lengths.size() == lengths_num(values.size(), cyclic)); + float length = 0.0f; + for (const int i : IndexRange(values.size() - 1)) { + length += math::distance(values[i], values[i + 1]); + lengths[i] = length; + } + if (cyclic) { + lengths.last() = length + math::distance(values.last(), values.first()); + } +} + +template<typename T> +void linear_interpolation(const Span<T> src, + const Span<int> indices, + const Span<float> factors, + MutableSpan<T> dst) +{ + BLI_assert(indices.size() == factors.size()); + BLI_assert(indices.size() == dst.size()); + const int last_src_index = src.index_range().last(); + + int cyclic_sample_count = 0; + for (int i = indices.index_range().last(); i > 0; i--) { + if (indices[i] != last_src_index) { + break; + } + dst[i] = math::interpolate(src.last(), src.first(), factors[i]); + cyclic_sample_count++; + } + + for (const int i : dst.index_range().drop_back(cyclic_sample_count)) { + dst[i] = math::interpolate(src[indices[i]], src[indices[i] + 1], factors[i]); + } +} + +/** + * Find the given number of points, evenly spaced along the provided length. For non-cyclic + * sequences, the first point will always be included, and last point will always be included if + * the #count is greater than zero. For cyclic sequences, the first point will always be included. + * + * \warning The #count argument must be greater than zero. + */ +void create_uniform_samples(Span<float> lengths, + bool cyclic, + MutableSpan<int> indices, + MutableSpan<float> factors); + +} // namespace blender::length_parameterize diff --git a/source/blender/blenlib/BLI_map.hh b/source/blender/blenlib/BLI_map.hh index 3cbb81b5c7d..d76aa46502d 100644 --- a/source/blender/blenlib/BLI_map.hh +++ b/source/blender/blenlib/BLI_map.hh @@ -962,7 +962,13 @@ class Map { */ void clear() { - this->noexcept_reset(); + for (Slot &slot : slots_) { + slot.~Slot(); + new (&slot) Slot(); + } + + removed_slots_ = 0; + occupied_and_removed_slots_ = 0; } /** diff --git a/source/blender/blenlib/BLI_math_color.hh b/source/blender/blenlib/BLI_math_color.hh new file mode 100644 index 00000000000..5195cfb6238 --- /dev/null +++ b/source/blender/blenlib/BLI_math_color.hh @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. */ + +#pragma once + +/** \file + * \ingroup bli + */ + +#include <cmath> +#include <type_traits> + +#include "BLI_color.hh" +#include "BLI_math_base.hh" + +namespace blender::math { + +inline ColorGeometry4f interpolate(const ColorGeometry4f &a, + const ColorGeometry4f &b, + const float t) +{ + return {math::interpolate(a.r, b.r, t), + math::interpolate(a.g, b.g, t), + math::interpolate(a.b, b.b, t), + math::interpolate(a.a, b.a, t)}; +} + +} // namespace blender::math diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index c31e3045c97..9e65093a05f 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -890,7 +890,7 @@ bool clip_segment_v3_plane( bool clip_segment_v3_plane_n(const float p1[3], const float p2[3], const float plane_array[][4], - int plane_tot, + int plane_num, float r_p1[3], float r_p2[3]); diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h index 740cf4dedb9..0313b743401 100644 --- a/source/blender/blenlib/BLI_mempool.h +++ b/source/blender/blenlib/BLI_mempool.h @@ -20,7 +20,7 @@ struct BLI_mempool_chunk; typedef struct BLI_mempool BLI_mempool; BLI_mempool *BLI_mempool_create(unsigned int esize, - unsigned int totelem, + unsigned int elem_num, unsigned int pchunk, unsigned int flag) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL; diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 7b3e3e983f0..06dd9ab0db9 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -204,12 +204,12 @@ bool BLI_path_filename_ensure(char *filepath, size_t maxlen, const char *filenam * or before dot if no digits. * \param tail: Optional area to return copy of part of string following digits, * or from dot if no digits. - * \param r_num_len: Optional to return number of digits found. + * \param r_digits_len: Optional to return number of digits found. */ int BLI_path_sequence_decode(const char *string, char *head, char *tail, - unsigned short *r_num_len); + unsigned short *r_digits_len); /** * Returns in area pointed to by string a string of the form `<head><pic><tail>`, * where pic is formatted as `numlen` digits with leading zeroes. @@ -310,7 +310,7 @@ bool BLI_path_frame_range(char *path, int sta, int end, int digits) ATTR_NONNULL /** * Get the frame from a filename formatted by blender's frame scheme */ -bool BLI_path_frame_get(char *path, int *r_frame, int *numdigits) ATTR_NONNULL(); +bool BLI_path_frame_get(char *path, int *r_frame, int *r_digits_len) ATTR_NONNULL(); /** * Given a `path` with digits representing frame numbers, replace the digits with the '#' * character and extract the extension. diff --git a/source/blender/blenlib/BLI_polyfill_2d.h b/source/blender/blenlib/BLI_polyfill_2d.h index a551188737f..ccb4c856de3 100644 --- a/source/blender/blenlib/BLI_polyfill_2d.h +++ b/source/blender/blenlib/BLI_polyfill_2d.h @@ -16,7 +16,7 @@ struct MemArena; * A version of #BLI_polyfill_calc that uses a memory arena to avoid re-allocations. */ void BLI_polyfill_calc_arena(const float (*coords)[2], - unsigned int coords_tot, + unsigned int coords_num, int coords_sign, unsigned int (*r_tris)[3], @@ -27,16 +27,16 @@ void BLI_polyfill_calc_arena(const float (*coords)[2], * * \param coords: 2D coordinates describing vertices of the polygon, * in either clockwise or counterclockwise order. - * \param coords_tot: Total points in the array. + * \param coords_num: Total points in the array. * \param coords_sign: Pass this when we know the sign in advance to avoid extra calculations. * * \param r_tris: This array is filled in with triangle indices in clockwise order. - * The length of the array must be `coords_tot - 2`. + * The length of the array must be `coords_num - 2`. * Indices are guaranteed to be assigned to unique triangles, with valid indices, * even in the case of degenerate input (self intersecting polygons, zero area ears... etc). */ void BLI_polyfill_calc(const float (*coords)[2], - unsigned int coords_tot, + unsigned int coords_num, int coords_sign, unsigned int (*r_tris)[3]); diff --git a/source/blender/blenlib/BLI_polyfill_2d_beautify.h b/source/blender/blenlib/BLI_polyfill_2d_beautify.h index c5a7cb80ff2..8e14bd5c641 100644 --- a/source/blender/blenlib/BLI_polyfill_2d_beautify.h +++ b/source/blender/blenlib/BLI_polyfill_2d_beautify.h @@ -20,7 +20,7 @@ struct MemArena; * are ignored since the edges won't share 2 faces. */ void BLI_polyfill_beautify(const float (*coords)[2], - unsigned int coords_tot, + unsigned int coords_num, unsigned int (*tris)[3], /* structs for reuse */ diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h index 2cfd868e943..6382c73d3cb 100644 --- a/source/blender/blenlib/BLI_rand.h +++ b/source/blender/blenlib/BLI_rand.h @@ -69,9 +69,9 @@ void BLI_rng_get_tri_sample_float_v3(RNG *rng, void BLI_rng_shuffle_array(struct RNG *rng, void *data, unsigned int elem_size_i, - unsigned int elem_tot) ATTR_NONNULL(1, 2); + unsigned int elem_num) ATTR_NONNULL(1, 2); -void BLI_rng_shuffle_bitmap(struct RNG *rng, unsigned int *bitmap, unsigned int bits_tot) +void BLI_rng_shuffle_bitmap(struct RNG *rng, unsigned int *bitmap, unsigned int bits_num) ATTR_NONNULL(1, 2); /** Note that skipping is as slow as generating n numbers! */ @@ -96,10 +96,10 @@ float BLI_hash_frand(unsigned int seed) ATTR_WARN_UNUSED_RESULT; */ void BLI_array_randomize(void *data, unsigned int elem_size, - unsigned int elem_tot, + unsigned int elem_num, unsigned int seed); -void BLI_bitmap_randomize(unsigned int *bitmap, unsigned int bits_tot, unsigned int seed) +void BLI_bitmap_randomize(unsigned int *bitmap, unsigned int bits_num, unsigned int seed) ATTR_NONNULL(1); /** Better seed for the random number generator, using noise.c hash[] */ diff --git a/source/blender/blenlib/BLI_scanfill.h b/source/blender/blenlib/BLI_scanfill.h index 8e43a3c5a8f..04ac7cb05e4 100644 --- a/source/blender/blenlib/BLI_scanfill.h +++ b/source/blender/blenlib/BLI_scanfill.h @@ -51,7 +51,7 @@ typedef struct ScanFillVert { unsigned int keyindex; unsigned short poly_nr; /** number of edges using this vertex */ - unsigned char edge_tot; + unsigned char edge_count; /** vert status */ unsigned int f : 4; /** flag callers can use as they like */ diff --git a/source/blender/blenlib/BLI_set.hh b/source/blender/blenlib/BLI_set.hh index bf177802c97..391d31c2228 100644 --- a/source/blender/blenlib/BLI_set.hh +++ b/source/blender/blenlib/BLI_set.hh @@ -515,8 +515,13 @@ class Set { */ void clear() { - this->~Set(); - new (this) Set(); + for (Slot &slot : slots_) { + slot.~Slot(); + new (&slot) Slot(); + } + + removed_slots_ = 0; + occupied_and_removed_slots_ = 0; } /** diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h index 1bd49165048..3be492009b0 100644 --- a/source/blender/blenlib/BLI_task.h +++ b/source/blender/blenlib/BLI_task.h @@ -238,18 +238,18 @@ typedef void (*TaskParallelIteratorFunc)(void *__restrict userdata, * \param iter_func: Callback function used to generate chunks of items. * \param init_item: The initial item, if necessary (may be NULL if unused). * \param init_index: The initial index. - * \param tot_items: The total amount of items to iterate over + * \param items_num: The total amount of items to iterate over * (if unknown, set it to a negative number). * \param func: Callback function. * \param settings: See public API doc of TaskParallelSettings for description of all settings. * - * \note Static scheduling is only available when \a tot_items is >= 0. + * \note Static scheduling is only available when \a items_num is >= 0. */ void BLI_task_parallel_iterator(void *userdata, TaskParallelIteratorIterFunc iter_func, void *init_item, int init_index, - int tot_items, + int items_num, TaskParallelIteratorFunc func, const TaskParallelSettings *settings); diff --git a/source/blender/blenlib/BLI_utildefines_stack.h b/source/blender/blenlib/BLI_utildefines_stack.h index fd5c3c72161..caf1726bbcf 100644 --- a/source/blender/blenlib/BLI_utildefines_stack.h +++ b/source/blender/blenlib/BLI_utildefines_stack.h @@ -11,17 +11,17 @@ /* only validate array-bounds in debug mode */ #ifdef DEBUG -# define STACK_DECLARE(stack) unsigned int _##stack##_index, _##stack##_totalloc -# define STACK_INIT(stack, tot) \ - ((void)stack, (void)((_##stack##_index) = 0), (void)((_##stack##_totalloc) = (tot))) +# define STACK_DECLARE(stack) unsigned int _##stack##_index, _##stack##_num_alloc +# define STACK_INIT(stack, stack_num) \ + ((void)stack, (void)((_##stack##_index) = 0), (void)((_##stack##_num_alloc) = (stack_num))) # define _STACK_SIZETEST(stack, off) \ - (BLI_assert((_##stack##_index) + (off) <= _##stack##_totalloc)) + (BLI_assert((_##stack##_index) + (off) <= _##stack##_num_alloc)) # define _STACK_SWAP_TOTALLOC(stack_a, stack_b) \ - SWAP(unsigned int, _##stack_a##_totalloc, _##stack_b##_totalloc) + SWAP(unsigned int, _##stack_a##_num_alloc, _##stack_b##_num_alloc) #else # define STACK_DECLARE(stack) unsigned int _##stack##_index -# define STACK_INIT(stack, tot) \ - ((void)stack, (void)((_##stack##_index) = 0), (void)(0 ? (tot) : 0)) +# define STACK_INIT(stack, stack_num) \ + ((void)stack, (void)((_##stack##_index) = 0), (void)(0 ? (stack_num) : 0)) # define _STACK_SIZETEST(stack, off) (void)(stack), (void)(off) # define _STACK_SWAP_TOTALLOC(stack_a, stack_b) (void)(stack_a), (void)(stack_b) #endif diff --git a/source/blender/blenlib/BLI_vector_set.hh b/source/blender/blenlib/BLI_vector_set.hh index 23284fd94bc..4ae1bf9000d 100644 --- a/source/blender/blenlib/BLI_vector_set.hh +++ b/source/blender/blenlib/BLI_vector_set.hh @@ -531,7 +531,14 @@ class VectorSet { */ void clear() { - this->noexcept_reset(); + destruct_n(keys_, this->size()); + for (Slot &slot : slots_) { + slot.~Slot(); + new (&slot) Slot(); + } + + removed_slots_ = 0; + occupied_and_removed_slots_ = 0; } /** diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 647726722b1..99e07264276 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -80,6 +80,7 @@ set(SRC intern/kdtree_4d.c intern/lasso_2d.c intern/listbase.c + intern/length_parameterize.cc intern/math_base.c intern/math_base_inline.c intern/math_base_safe_inline.c @@ -225,6 +226,7 @@ set(SRC BLI_kdtree.h BLI_kdtree_impl.h BLI_lasso_2d.h + BLI_length_parameterize.hh BLI_linear_allocator.hh BLI_link_utils.h BLI_linklist.h @@ -241,6 +243,7 @@ set(SRC BLI_math_bits.h BLI_math_boolean.hh BLI_math_color.h + BLI_math_color.hh BLI_math_color_blend.h BLI_math_geom.h BLI_math_inline.h @@ -435,6 +438,7 @@ if(WITH_GTESTS) tests/BLI_index_range_test.cc tests/BLI_inplace_priority_queue_test.cc tests/BLI_kdopbvh_test.cc + tests/BLI_length_parameterize_test.cc tests/BLI_linear_allocator_test.cc tests/BLI_linklist_lockfree_test.cc tests/BLI_listbase_test.cc diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c index cf8073d4ba4..0bc50f62232 100644 --- a/source/blender/blenlib/intern/BLI_heap.c +++ b/source/blender/blenlib/intern/BLI_heap.c @@ -35,7 +35,7 @@ struct HeapNode_Chunk { * or we allocate past the reserved number. * * \note Optimize number for 64kb allocs. - * \note keep type in sync with tot_nodes in heap_node_alloc_chunk. + * \note keep type in sync with nodes_num in heap_node_alloc_chunk. */ #define HEAP_CHUNK_DEFAULT_NUM \ ((uint)((MEM_SIZE_OPTIMAL((1 << 16) - sizeof(struct HeapNode_Chunk))) / sizeof(HeapNode))) @@ -137,13 +137,13 @@ static void heap_up(Heap *heap, uint i) /** \name Internal Memory Management * \{ */ -static struct HeapNode_Chunk *heap_node_alloc_chunk(uint tot_nodes, +static struct HeapNode_Chunk *heap_node_alloc_chunk(uint nodes_num, struct HeapNode_Chunk *chunk_prev) { struct HeapNode_Chunk *chunk = MEM_mallocN( - sizeof(struct HeapNode_Chunk) + (sizeof(HeapNode) * tot_nodes), __func__); + sizeof(struct HeapNode_Chunk) + (sizeof(HeapNode) * nodes_num), __func__); chunk->prev = chunk_prev; - chunk->bufsize = tot_nodes; + chunk->bufsize = nodes_num; chunk->size = 0; return chunk; } @@ -179,16 +179,16 @@ static void heap_node_free(Heap *heap, HeapNode *node) /** \name Public Heap API * \{ */ -Heap *BLI_heap_new_ex(uint tot_reserve) +Heap *BLI_heap_new_ex(uint reserve_num) { Heap *heap = MEM_mallocN(sizeof(Heap), __func__); /* ensure we have at least one so we can keep doubling it */ heap->size = 0; - heap->bufsize = MAX2(1u, tot_reserve); + heap->bufsize = MAX2(1u, reserve_num); heap->tree = MEM_mallocN(heap->bufsize * sizeof(HeapNode *), "BLIHeapTree"); heap->nodes.chunk = heap_node_alloc_chunk( - (tot_reserve > 1) ? tot_reserve : HEAP_CHUNK_DEFAULT_NUM, NULL); + (reserve_num > 1) ? reserve_num : HEAP_CHUNK_DEFAULT_NUM, NULL); heap->nodes.free = NULL; return heap; diff --git a/source/blender/blenlib/intern/BLI_heap_simple.c b/source/blender/blenlib/intern/BLI_heap_simple.c index 0876888bcc5..b6c045cbefa 100644 --- a/source/blender/blenlib/intern/BLI_heap_simple.c +++ b/source/blender/blenlib/intern/BLI_heap_simple.c @@ -133,12 +133,12 @@ static void heapsimple_up(HeapSimple *heap, uint i, float active_val, void *acti /** \name Public HeapSimple API * \{ */ -HeapSimple *BLI_heapsimple_new_ex(uint tot_reserve) +HeapSimple *BLI_heapsimple_new_ex(uint reserve_num) { HeapSimple *heap = MEM_mallocN(sizeof(HeapSimple), __func__); /* ensure we have at least one so we can keep doubling it */ heap->size = 0; - heap->bufsize = MAX2(1u, tot_reserve); + heap->bufsize = MAX2(1u, reserve_num); heap->tree = MEM_mallocN(heap->bufsize * sizeof(HeapSimpleNode), "BLIHeapSimpleTree"); return heap; } diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 0c3497d3edf..0f52c84c45e 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -68,7 +68,7 @@ typedef struct BVHNode { #endif float *bv; /* Bounding volume of all nodes, max 13 axis */ int index; /* face, edge, vertex index */ - char totnode; /* how many nodes are used, used for speedup */ + char node_num; /* how many nodes are used, used for speedup */ char main_axis; /* Axis used to split this node */ } BVHNode; @@ -79,8 +79,8 @@ struct BVHTree { BVHNode **nodechild; /* pre-alloc children for nodes */ float *nodebv; /* pre-alloc bounding-volumes for nodes */ float epsilon; /* Epsilon is used for inflation of the K-DOP. */ - int totleaf; /* leafs */ - int totbranch; + int leaf_num; /* leafs */ + int branch_num; axis_t start_axis, stop_axis; /* bvhtree_kdop_axes array indices according to axis */ axis_t axis; /* KDOP type (6 => OBB, 7 => AABB, ...) */ char tree_type; /* type of tree (4 => quad-tree). */ @@ -325,8 +325,8 @@ static void build_skip_links(BVHTree *tree, BVHNode *node, BVHNode *left, BVHNod node->skip[0] = left; node->skip[1] = right; - for (i = 0; i < node->totnode; i++) { - if (i + 1 < node->totnode) { + for (i = 0; i < node->node_num; i++) { + if (i + 1 < node->node_num) { build_skip_links(tree, node->children[i], left, node->children[i + 1]); } else { @@ -485,9 +485,9 @@ static void bvhtree_info(BVHTree *tree) tree->axis, tree->epsilon); printf("nodes = %d, branches = %d, leafs = %d\n", - tree->totbranch + tree->totleaf, - tree->totbranch, - tree->totleaf); + tree->branch_num + tree->leaf_num, + tree->branch_num, + tree->leaf_num); printf( "Memory per node = %ubytes\n", (uint)(sizeof(BVHNode) + sizeof(BVHNode *) * tree->tree_type + sizeof(float) * tree->axis)); @@ -497,7 +497,7 @@ static void bvhtree_info(BVHTree *tree) (uint)(sizeof(BVHTree) + MEM_allocN_len(tree->nodes) + MEM_allocN_len(tree->nodearray) + MEM_allocN_len(tree->nodechild) + MEM_allocN_len(tree->nodebv))); - bvhtree_print_tree(tree, tree->nodes[tree->totleaf], 0); + bvhtree_print_tree(tree, tree->nodes[tree->leaf_num], 0); } #endif /* USE_PRINT_TREE */ @@ -508,7 +508,7 @@ static void bvhtree_verify(BVHTree *tree) int i, j, check = 0; /* check the pointer list */ - for (i = 0; i < tree->totleaf; i++) { + for (i = 0; i < tree->leaf_num; i++) { if (tree->nodes[i]->parent == NULL) { printf("Leaf has no parent: %d\n", i); } @@ -526,7 +526,7 @@ static void bvhtree_verify(BVHTree *tree) } /* check the leaf list */ - for (i = 0; i < tree->totleaf; i++) { + for (i = 0; i < tree->leaf_num; i++) { if (tree->nodearray[i].parent == NULL) { printf("Leaf has no parent: %d\n", i); } @@ -544,9 +544,9 @@ static void bvhtree_verify(BVHTree *tree) } printf("branches: %d, leafs: %d, total: %d\n", - tree->totbranch, - tree->totleaf, - tree->totbranch + tree->totleaf); + tree->branch_num, + tree->leaf_num, + tree->branch_num + tree->leaf_num); } #endif /* USE_VERIFY_TREE */ @@ -555,7 +555,7 @@ static void bvhtree_verify(BVHTree *tree) * (basically this is only method to calculate pow(k, n) in O(1).. and stuff like that) */ typedef struct BVHBuildHelper { int tree_type; - int totleafs; + int leafs_num; /** Min number of leafs that are achievable from a node at depth `N`. */ int leafs_per_child[32]; @@ -573,11 +573,11 @@ static void build_implicit_tree_helper(const BVHTree *tree, BVHBuildHelper *data int remain; int nnodes; - data->totleafs = tree->totleaf; + data->leafs_num = tree->leaf_num; data->tree_type = tree->tree_type; - /* Calculate the smallest tree_type^n such that tree_type^n >= num_leafs */ - for (data->leafs_per_child[0] = 1; data->leafs_per_child[0] < data->totleafs; + /* Calculate the smallest tree_type^n such that tree_type^n >= leafs_num */ + for (data->leafs_per_child[0] = 1; data->leafs_per_child[0] < data->leafs_num; data->leafs_per_child[0] *= data->tree_type) { /* pass */ } @@ -589,7 +589,7 @@ static void build_implicit_tree_helper(const BVHTree *tree, BVHBuildHelper *data data->leafs_per_child[depth] = data->leafs_per_child[depth - 1] / data->tree_type; } - remain = data->totleafs - data->leafs_per_child[1]; + remain = data->leafs_num - data->leafs_per_child[1]; nnodes = (remain + data->tree_type - 2) / (data->tree_type - 1); data->remain_leafs = remain + nnodes; } @@ -604,7 +604,7 @@ static int implicit_leafs_index(const BVHBuildHelper *data, const int depth, con return min_leaf_index; } if (data->leafs_per_child[depth]) { - return data->totleafs - + return data->leafs_num - (data->branches_on_level[depth - 1] - child_index) * data->leafs_per_child[depth]; } return data->remain_leafs; @@ -725,7 +725,7 @@ static void non_recursive_bvh_div_nodes_task_cb(void *__restrict userdata, split_leafs(data->leafs_array, nth_positions, data->tree_type, split_axis); - /* Setup children and totnode counters + /* Setup `children` and `node_num` counters * Not really needed but currently most of BVH code * relies on having an explicit children structure */ for (k = 0; k < data->tree_type; k++) { @@ -750,7 +750,7 @@ static void non_recursive_bvh_div_nodes_task_cb(void *__restrict userdata, break; } } - parent->totnode = (char)k; + parent->node_num = (char)k; } /** @@ -774,7 +774,7 @@ static void non_recursive_bvh_div_nodes_task_cb(void *__restrict userdata, static void non_recursive_bvh_div_nodes(const BVHTree *tree, BVHNode *branches_array, BVHNode **leafs_array, - int num_leafs) + int leafs_num) { int i; @@ -782,7 +782,7 @@ static void non_recursive_bvh_div_nodes(const BVHTree *tree, /* this value is 0 (on binary trees) and negative on the others */ const int tree_offset = 2 - tree->tree_type; - const int num_branches = implicit_needed_branches(tree_type, num_leafs); + const int branches_num = implicit_needed_branches(tree_type, leafs_num); BVHBuildHelper data; int depth; @@ -794,10 +794,10 @@ static void non_recursive_bvh_div_nodes(const BVHTree *tree, /* Most of bvhtree code relies on 1-leaf trees having at least one branch * We handle that special case here */ - if (num_leafs == 1) { - refit_kdop_hull(tree, root, 0, num_leafs); + if (leafs_num == 1) { + refit_kdop_hull(tree, root, 0, leafs_num); root->main_axis = get_largest_axis(root->bv) / 2; - root->totnode = 1; + root->node_num = 1; root->children[0] = leafs_array[0]; root->children[0]->parent = root; return; @@ -819,10 +819,10 @@ static void non_recursive_bvh_div_nodes(const BVHTree *tree, }; /* Loop tree levels (log N) loops */ - for (i = 1, depth = 1; i <= num_branches; i = i * tree_type + tree_offset, depth++) { + for (i = 1, depth = 1; i <= branches_num; i = i * tree_type + tree_offset, depth++) { const int first_of_next_level = i * tree_type + tree_offset; /* index of last branch on this level */ - const int i_stop = min_ii(first_of_next_level, num_branches + 1); + const int i_stop = min_ii(first_of_next_level, branches_num + 1); /* Loop all branches on this level */ cb_data.first_of_next_level = first_of_next_level; @@ -832,7 +832,7 @@ static void non_recursive_bvh_div_nodes(const BVHTree *tree, if (true) { TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.use_threading = (num_leafs > KDOPBVH_THREAD_LEAF_THRESHOLD); + settings.use_threading = (leafs_num > KDOPBVH_THREAD_LEAF_THRESHOLD); BLI_task_parallel_range(i, i_stop, &cb_data, non_recursive_bvh_div_nodes_task_cb, &settings); } else { @@ -940,21 +940,21 @@ void BLI_bvhtree_balance(BVHTree *tree) /* This function should only be called once * (some big bug goes here if its being called more than once per tree) */ - BLI_assert(tree->totbranch == 0); + BLI_assert(tree->branch_num == 0); /* Build the implicit tree */ non_recursive_bvh_div_nodes( - tree, tree->nodearray + (tree->totleaf - 1), leafs_array, tree->totleaf); + tree, tree->nodearray + (tree->leaf_num - 1), leafs_array, tree->leaf_num); /* current code expects the branches to be linked to the nodes array * we perform that linkage here */ - tree->totbranch = implicit_needed_branches(tree->tree_type, tree->totleaf); - for (int i = 0; i < tree->totbranch; i++) { - tree->nodes[tree->totleaf + i] = &tree->nodearray[tree->totleaf + i]; + tree->branch_num = implicit_needed_branches(tree->tree_type, tree->leaf_num); + for (int i = 0; i < tree->branch_num; i++) { + tree->nodes[tree->leaf_num + i] = &tree->nodearray[tree->leaf_num + i]; } #ifdef USE_SKIP_LINKS - build_skip_links(tree, tree->nodes[tree->totleaf], NULL, NULL); + build_skip_links(tree, tree->nodes[tree->leaf_num], NULL, NULL); #endif #ifdef USE_VERIFY_TREE @@ -980,12 +980,12 @@ void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoin { BVHNode *node = NULL; - /* insert should only possible as long as tree->totbranch is 0 */ - BLI_assert(tree->totbranch <= 0); - BLI_assert((size_t)tree->totleaf < MEM_allocN_len(tree->nodes) / sizeof(*(tree->nodes))); + /* insert should only possible as long as tree->branch_num is 0 */ + BLI_assert(tree->branch_num <= 0); + BLI_assert((size_t)tree->leaf_num < MEM_allocN_len(tree->nodes) / sizeof(*(tree->nodes))); - node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]); - tree->totleaf++; + node = tree->nodes[tree->leaf_num] = &(tree->nodearray[tree->leaf_num]); + tree->leaf_num++; create_kdop_hull(tree, node, co, numpoints, 0); node->index = index; @@ -1000,7 +1000,7 @@ bool BLI_bvhtree_update_node( BVHNode *node = NULL; /* check if index exists */ - if (index > tree->totleaf) { + if (index > tree->leaf_num) { return false; } @@ -1024,8 +1024,8 @@ void BLI_bvhtree_update_tree(BVHTree *tree) * TRICKY: the way we build the tree all the children have an index greater than the parent * This allows us todo a bottom up update by starting on the bigger numbered branch. */ - BVHNode **root = tree->nodes + tree->totleaf; - BVHNode **index = tree->nodes + tree->totleaf + tree->totbranch - 1; + BVHNode **root = tree->nodes + tree->leaf_num; + BVHNode **index = tree->nodes + tree->leaf_num + tree->branch_num - 1; for (; index >= root; index--) { node_join(tree, *index); @@ -1033,7 +1033,7 @@ void BLI_bvhtree_update_tree(BVHTree *tree) } int BLI_bvhtree_get_len(const BVHTree *tree) { - return tree->totleaf; + return tree->leaf_num; } int BLI_bvhtree_get_tree_type(const BVHTree *tree) @@ -1048,7 +1048,7 @@ float BLI_bvhtree_get_epsilon(const BVHTree *tree) void BLI_bvhtree_get_bounding_box(BVHTree *tree, float r_bb_min[3], float r_bb_max[3]) { - BVHNode *root = tree->nodes[tree->totleaf]; + BVHNode *root = tree->nodes[tree->leaf_num]; if (root != NULL) { const float bb_min[3] = {root->bv[0], root->bv[2], root->bv[4]}; const float bb_max[3] = {root->bv[1], root->bv[3], root->bv[5]}; @@ -1099,9 +1099,9 @@ static void tree_overlap_traverse(BVHOverlapData_Thread *data_thread, if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) { /* check if node1 is a leaf */ - if (!node1->totnode) { + if (!node1->node_num) { /* check if node2 is a leaf */ - if (!node2->totnode) { + if (!node2->node_num) { BVHTreeOverlap *overlap; if (UNLIKELY(node1 == node2)) { @@ -1143,9 +1143,9 @@ static void tree_overlap_traverse_cb(BVHOverlapData_Thread *data_thread, if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) { /* check if node1 is a leaf */ - if (!node1->totnode) { + if (!node1->node_num) { /* check if node2 is a leaf */ - if (!node2->totnode) { + if (!node2->node_num) { BVHTreeOverlap *overlap; if (UNLIKELY(node1 == node2)) { @@ -1190,9 +1190,9 @@ static bool tree_overlap_traverse_num(BVHOverlapData_Thread *data_thread, if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) { /* check if node1 is a leaf */ - if (!node1->totnode) { + if (!node1->node_num) { /* check if node2 is a leaf */ - if (!node2->totnode) { + if (!node2->node_num) { BVHTreeOverlap *overlap; if (UNLIKELY(node1 == node2)) { @@ -1212,7 +1212,7 @@ static bool tree_overlap_traverse_num(BVHOverlapData_Thread *data_thread, } } else { - for (j = 0; j < node2->totnode; j++) { + for (j = 0; j < node2->node_num; j++) { if (tree_overlap_traverse_num(data_thread, node1, node2->children[j])) { return true; } @@ -1221,7 +1221,7 @@ static bool tree_overlap_traverse_num(BVHOverlapData_Thread *data_thread, } else { const uint max_interactions = data_thread->max_interactions; - for (j = 0; j < node1->totnode; j++) { + for (j = 0; j < node1->node_num; j++) { if (tree_overlap_traverse_num(data_thread, node1->children[j], node2)) { data_thread->max_interactions = max_interactions; } @@ -1233,7 +1233,7 @@ static bool tree_overlap_traverse_num(BVHOverlapData_Thread *data_thread, int BLI_bvhtree_overlap_thread_num(const BVHTree *tree) { - return (int)MIN2(tree->tree_type, tree->nodes[tree->totleaf]->totnode); + return (int)MIN2(tree->tree_type, tree->nodes[tree->leaf_num]->node_num); } static void bvhtree_overlap_task_cb(void *__restrict userdata, @@ -1245,25 +1245,25 @@ static void bvhtree_overlap_task_cb(void *__restrict userdata, if (data->max_interactions) { tree_overlap_traverse_num(data, - data_shared->tree1->nodes[data_shared->tree1->totleaf]->children[j], - data_shared->tree2->nodes[data_shared->tree2->totleaf]); + data_shared->tree1->nodes[data_shared->tree1->leaf_num]->children[j], + data_shared->tree2->nodes[data_shared->tree2->leaf_num]); } else if (data_shared->callback) { tree_overlap_traverse_cb(data, - data_shared->tree1->nodes[data_shared->tree1->totleaf]->children[j], - data_shared->tree2->nodes[data_shared->tree2->totleaf]); + data_shared->tree1->nodes[data_shared->tree1->leaf_num]->children[j], + data_shared->tree2->nodes[data_shared->tree2->leaf_num]); } else { tree_overlap_traverse(data, - data_shared->tree1->nodes[data_shared->tree1->totleaf]->children[j], - data_shared->tree2->nodes[data_shared->tree2->totleaf]); + data_shared->tree1->nodes[data_shared->tree1->leaf_num]->children[j], + data_shared->tree2->nodes[data_shared->tree2->leaf_num]); } } BVHTreeOverlap *BLI_bvhtree_overlap_ex( const BVHTree *tree1, const BVHTree *tree2, - uint *r_overlap_tot, + uint *r_overlap_num, /* optional callback to test the overlap before adding (must be thread-safe!) */ BVHTree_OverlapCallback callback, void *userdata, @@ -1272,7 +1272,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap_ex( { bool overlap_pairs = (flag & BVH_OVERLAP_RETURN_PAIRS) != 0; bool use_threading = (flag & BVH_OVERLAP_USE_THREADING) != 0 && - (tree1->totleaf > KDOPBVH_THREAD_LEAF_THRESHOLD); + (tree1->leaf_num > KDOPBVH_THREAD_LEAF_THRESHOLD); /* 'RETURN_PAIRS' was not implemented without 'max_interactions'. */ BLI_assert(overlap_pairs || max_interactions); @@ -1293,8 +1293,8 @@ BVHTreeOverlap *BLI_bvhtree_overlap_ex( return NULL; } - const BVHNode *root1 = tree1->nodes[tree1->totleaf]; - const BVHNode *root2 = tree2->nodes[tree2->totleaf]; + const BVHNode *root1 = tree1->nodes[tree1->leaf_num]; + const BVHNode *root2 = tree2->nodes[tree2->leaf_num]; start_axis = min_axis(tree1->start_axis, tree2->start_axis); stop_axis = min_axis(tree1->stop_axis, tree2->stop_axis); @@ -1354,7 +1354,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap_ex( BLI_stack_free(data[j].overlap); to += count; } - *r_overlap_tot = (uint)total; + *r_overlap_num = (uint)total; } return overlap; @@ -1363,14 +1363,14 @@ BVHTreeOverlap *BLI_bvhtree_overlap_ex( BVHTreeOverlap *BLI_bvhtree_overlap( const BVHTree *tree1, const BVHTree *tree2, - uint *r_overlap_tot, + uint *r_overlap_num, /* optional callback to test the overlap before adding (must be thread-safe!) */ BVHTree_OverlapCallback callback, void *userdata) { return BLI_bvhtree_overlap_ex(tree1, tree2, - r_overlap_tot, + r_overlap_num, callback, userdata, 0, @@ -1403,7 +1403,7 @@ static void bvhtree_intersect_plane_dfs_recursive(BVHIntersectPlaneData *__restr { if (tree_intersect_plane_test(node->bv, data->plane)) { /* check if node is a leaf */ - if (!node->totnode) { + if (!node->node_num) { int *intersect = BLI_stack_push_r(data->intersect); *intersect = node->index; } @@ -1417,18 +1417,18 @@ static void bvhtree_intersect_plane_dfs_recursive(BVHIntersectPlaneData *__restr } } -int *BLI_bvhtree_intersect_plane(BVHTree *tree, float plane[4], uint *r_intersect_tot) +int *BLI_bvhtree_intersect_plane(BVHTree *tree, float plane[4], uint *r_intersect_num) { int *intersect = NULL; size_t total = 0; - if (tree->totleaf) { + if (tree->leaf_num) { BVHIntersectPlaneData data; data.tree = tree; copy_v4_v4(data.plane, plane); data.intersect = BLI_stack_new(sizeof(int), __func__); - BVHNode *root = tree->nodes[tree->totleaf]; + BVHNode *root = tree->nodes[tree->leaf_num]; bvhtree_intersect_plane_dfs_recursive(&data, root); total = BLI_stack_count(data.intersect); @@ -1438,7 +1438,7 @@ int *BLI_bvhtree_intersect_plane(BVHTree *tree, float plane[4], uint *r_intersec } BLI_stack_free(data.intersect); } - *r_intersect_tot = (uint)total; + *r_intersect_num = (uint)total; return intersect; } @@ -1473,7 +1473,7 @@ static float calc_nearest_point_squared(const float proj[3], BVHNode *node, floa /* Depth first search method */ static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node) { - if (node->totnode == 0) { + if (node->node_num == 0) { if (data->callback) { data->callback(data->userdata, node->index, data->co, &data->nearest); } @@ -1489,7 +1489,7 @@ static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node) if (data->proj[node->main_axis] <= node->children[0]->bv[node->main_axis * 2 + 1]) { - for (i = 0; i != node->totnode; i++) { + for (i = 0; i != node->node_num; i++) { if (calc_nearest_point_squared(data->proj, node->children[i], nearest) >= data->nearest.dist_sq) { continue; @@ -1498,7 +1498,7 @@ static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node) } } else { - for (i = node->totnode - 1; i >= 0; i--) { + for (i = node->node_num - 1; i >= 0; i--) { if (calc_nearest_point_squared(data->proj, node->children[i], nearest) >= data->nearest.dist_sq) { continue; @@ -1522,7 +1522,7 @@ static void dfs_find_nearest_begin(BVHNearestData *data, BVHNode *node) /* Priority queue method */ static void heap_find_nearest_inner(BVHNearestData *data, HeapSimple *heap, BVHNode *node) { - if (node->totnode == 0) { + if (node->node_num == 0) { if (data->callback) { data->callback(data->userdata, node->index, data->co, &data->nearest); } @@ -1534,7 +1534,7 @@ static void heap_find_nearest_inner(BVHNearestData *data, HeapSimple *heap, BVHN else { float nearest[3]; - for (int i = 0; i != node->totnode; i++) { + for (int i = 0; i != node->node_num; i++) { float dist_sq = calc_nearest_point_squared(data->proj, node->children[i], nearest); if (dist_sq < data->nearest.dist_sq) { @@ -1574,7 +1574,7 @@ int BLI_bvhtree_find_nearest_ex(BVHTree *tree, axis_t axis_iter; BVHNearestData data; - BVHNode *root = tree->nodes[tree->totleaf]; + BVHNode *root = tree->nodes[tree->leaf_num]; /* init data to search */ data.tree = tree; @@ -1642,7 +1642,7 @@ static bool isect_aabb_v3(BVHNode *node, const float co[3]) static bool dfs_find_duplicate_fast_dfs(BVHNearestData *data, BVHNode *node) { - if (node->totnode == 0) { + if (node->node_num == 0) { if (isect_aabb_v3(node, data->co)) { if (data->callback) { const float dist_sq = data->nearest.dist_sq; @@ -1658,7 +1658,7 @@ static bool dfs_find_duplicate_fast_dfs(BVHNearestData *data, BVHNode *node) int i; if (data->proj[node->main_axis] <= node->children[0]->bv[node->main_axis * 2 + 1]) { - for (i = 0; i != node->totnode; i++) { + for (i = 0; i != node->node_num; i++) { if (isect_aabb_v3(node->children[i], data->co)) { if (dfs_find_duplicate_fast_dfs(data, node->children[i])) { return true; @@ -1667,7 +1667,7 @@ static bool dfs_find_duplicate_fast_dfs(BVHNearestData *data, BVHNode *node) } } else { - for (i = node->totnode; i--;) { + for (i = node->node_num; i--;) { if (isect_aabb_v3(node->children[i], data->co)) { if (dfs_find_duplicate_fast_dfs(data, node->children[i])) { return true; @@ -1686,7 +1686,7 @@ int BLI_bvhtree_find_nearest_first(BVHTree *tree, void *userdata) { BVHNearestData data; - BVHNode *root = tree->nodes[tree->totleaf]; + BVHNode *root = tree->nodes[tree->leaf_num]; /* init data to search */ data.tree = tree; @@ -1796,7 +1796,7 @@ static void dfs_raycast(BVHRayCastData *data, BVHNode *node) return; } - if (node->totnode == 0) { + if (node->node_num == 0) { if (data->callback) { data->callback(data->userdata, node->index, &data->ray, &data->hit); } @@ -1809,12 +1809,12 @@ static void dfs_raycast(BVHRayCastData *data, BVHNode *node) else { /* pick loop direction to dive into the tree (based on ray direction and split axis) */ if (data->ray_dot_axis[node->main_axis] > 0.0f) { - for (i = 0; i != node->totnode; i++) { + for (i = 0; i != node->node_num; i++) { dfs_raycast(data, node->children[i]); } } else { - for (i = node->totnode - 1; i >= 0; i--) { + for (i = node->node_num - 1; i >= 0; i--) { dfs_raycast(data, node->children[i]); } } @@ -1837,7 +1837,7 @@ static void dfs_raycast_all(BVHRayCastData *data, BVHNode *node) return; } - if (node->totnode == 0) { + if (node->node_num == 0) { /* no need to check for 'data->callback' (using 'all' only makes sense with a callback). */ dist = data->hit.dist; data->callback(data->userdata, node->index, &data->ray, &data->hit); @@ -1847,12 +1847,12 @@ static void dfs_raycast_all(BVHRayCastData *data, BVHNode *node) else { /* pick loop direction to dive into the tree (based on ray direction and split axis) */ if (data->ray_dot_axis[node->main_axis] > 0.0f) { - for (i = 0; i != node->totnode; i++) { + for (i = 0; i != node->node_num; i++) { dfs_raycast_all(data, node->children[i]); } } else { - for (i = node->totnode - 1; i >= 0; i--) { + for (i = node->node_num - 1; i >= 0; i--) { dfs_raycast_all(data, node->children[i]); } } @@ -1904,7 +1904,7 @@ int BLI_bvhtree_ray_cast_ex(BVHTree *tree, int flag) { BVHRayCastData data; - BVHNode *root = tree->nodes[tree->totleaf]; + BVHNode *root = tree->nodes[tree->leaf_num]; BLI_ASSERT_UNIT_V3(dir); @@ -1988,7 +1988,7 @@ void BLI_bvhtree_ray_cast_all_ex(BVHTree *tree, int flag) { BVHRayCastData data; - BVHNode *root = tree->nodes[tree->totleaf]; + BVHNode *root = tree->nodes[tree->leaf_num]; BLI_ASSERT_UNIT_V3(dir); BLI_assert(callback != NULL); @@ -2048,7 +2048,7 @@ typedef struct RangeQueryData { static void dfs_range_query(RangeQueryData *data, BVHNode *node) { - if (node->totnode == 0) { + if (node->node_num == 0) { #if 0 /*UNUSED*/ /* Calculate the node min-coords * (if the node was a point then this is the point coordinates) */ @@ -2060,12 +2060,12 @@ static void dfs_range_query(RangeQueryData *data, BVHNode *node) } else { int i; - for (i = 0; i != node->totnode; i++) { + for (i = 0; i != node->node_num; i++) { float nearest[3]; float dist_sq = calc_nearest_point_squared(data->center, node->children[i], nearest); if (dist_sq < data->radius_sq) { /* Its a leaf.. call the callback */ - if (node->children[i]->totnode == 0) { + if (node->children[i]->node_num == 0) { data->hits++; data->callback(data->userdata, node->children[i]->index, data->center, dist_sq); } @@ -2080,7 +2080,7 @@ static void dfs_range_query(RangeQueryData *data, BVHNode *node) int BLI_bvhtree_range_query( BVHTree *tree, const float co[3], float radius, BVHTree_RangeQuery callback, void *userdata) { - BVHNode *root = tree->nodes[tree->totleaf]; + BVHNode *root = tree->nodes[tree->leaf_num]; RangeQueryData data; data.tree = tree; @@ -2096,7 +2096,7 @@ int BLI_bvhtree_range_query( float dist_sq = calc_nearest_point_squared(data.center, root, nearest); if (dist_sq < data.radius_sq) { /* Its a leaf.. call the callback */ - if (root->totnode == 0) { + if (root->node_num == 0) { data.hits++; data.callback(data.userdata, root->index, co, dist_sq); } @@ -2118,7 +2118,7 @@ int BLI_bvhtree_range_query( static void bvhtree_nearest_projected_dfs_recursive(BVHNearestProjectedData *__restrict data, const BVHNode *node) { - if (node->totnode == 0) { + if (node->node_num == 0) { if (data->callback) { data->callback(data->userdata, node->index, &data->precalc, NULL, 0, &data->nearest); } @@ -2134,7 +2134,7 @@ static void bvhtree_nearest_projected_dfs_recursive(BVHNearestProjectedData *__r else { /* First pick the closest node to recurse into */ if (data->closest_axis[node->main_axis]) { - for (int i = 0; i != node->totnode; i++) { + for (int i = 0; i != node->node_num; i++) { const float *bv = node->children[i]->bv; if (dist_squared_to_projected_aabb(&data->precalc, @@ -2146,7 +2146,7 @@ static void bvhtree_nearest_projected_dfs_recursive(BVHNearestProjectedData *__r } } else { - for (int i = node->totnode; i--;) { + for (int i = node->node_num; i--;) { const float *bv = node->children[i]->bv; if (dist_squared_to_projected_aabb(&data->precalc, @@ -2163,7 +2163,7 @@ static void bvhtree_nearest_projected_dfs_recursive(BVHNearestProjectedData *__r static void bvhtree_nearest_projected_with_clipplane_test_dfs_recursive( BVHNearestProjectedData *__restrict data, const BVHNode *node) { - if (node->totnode == 0) { + if (node->node_num == 0) { if (data->callback) { data->callback(data->userdata, node->index, @@ -2184,7 +2184,7 @@ static void bvhtree_nearest_projected_with_clipplane_test_dfs_recursive( else { /* First pick the closest node to recurse into */ if (data->closest_axis[node->main_axis]) { - for (int i = 0; i != node->totnode; i++) { + for (int i = 0; i != node->node_num; i++) { const float *bv = node->children[i]->bv; const float bb_min[3] = {bv[0], bv[2], bv[4]}; const float bb_max[3] = {bv[1], bv[3], bv[5]}; @@ -2206,7 +2206,7 @@ static void bvhtree_nearest_projected_with_clipplane_test_dfs_recursive( } } else { - for (int i = node->totnode; i--;) { + for (int i = node->node_num; i--;) { const float *bv = node->children[i]->bv; const float bb_min[3] = {bv[0], bv[2], bv[4]}; const float bb_max[3] = {bv[1], bv[3], bv[5]}; @@ -2240,7 +2240,7 @@ int BLI_bvhtree_find_nearest_projected(BVHTree *tree, BVHTree_NearestProjectedCallback callback, void *userdata) { - BVHNode *root = tree->nodes[tree->totleaf]; + BVHNode *root = tree->nodes[tree->leaf_num]; if (root != NULL) { BVHNearestProjectedData data; dist_squared_to_projected_aabb_precalc(&data.precalc, projmat, winsize, mval); @@ -2314,7 +2314,7 @@ typedef struct BVHTree_WalkData { */ static bool bvhtree_walk_dfs_recursive(BVHTree_WalkData *walk_data, const BVHNode *node) { - if (node->totnode == 0) { + if (node->node_num == 0) { return walk_data->walk_leaf_cb( (const BVHTreeAxisRange *)node->bv, node->index, walk_data->userdata); } @@ -2322,7 +2322,7 @@ static bool bvhtree_walk_dfs_recursive(BVHTree_WalkData *walk_data, const BVHNod /* First pick the closest node to recurse into */ if (walk_data->walk_order_cb( (const BVHTreeAxisRange *)node->bv, node->main_axis, walk_data->userdata)) { - for (int i = 0; i != node->totnode; i++) { + for (int i = 0; i != node->node_num; i++) { if (walk_data->walk_parent_cb((const BVHTreeAxisRange *)node->children[i]->bv, walk_data->userdata)) { if (!bvhtree_walk_dfs_recursive(walk_data, node->children[i])) { @@ -2332,7 +2332,7 @@ static bool bvhtree_walk_dfs_recursive(BVHTree_WalkData *walk_data, const BVHNod } } else { - for (int i = node->totnode - 1; i >= 0; i--) { + for (int i = node->node_num - 1; i >= 0; i--) { if (walk_data->walk_parent_cb((const BVHTreeAxisRange *)node->children[i]->bv, walk_data->userdata)) { if (!bvhtree_walk_dfs_recursive(walk_data, node->children[i])) { @@ -2350,7 +2350,7 @@ void BLI_bvhtree_walk_dfs(BVHTree *tree, BVHTree_WalkOrderCallback walk_order_cb, void *userdata) { - const BVHNode *root = tree->nodes[tree->totleaf]; + const BVHNode *root = tree->nodes[tree->leaf_num]; if (root != NULL) { BVHTree_WalkData walk_data = {walk_parent_cb, walk_leaf_cb, walk_order_cb, userdata}; /* first make sure the bv of root passes in the test too */ diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c index 76a82e505e3..f70b5ddd766 100644 --- a/source/blender/blenlib/intern/BLI_mempool.c +++ b/source/blender/blenlib/intern/BLI_mempool.c @@ -159,9 +159,9 @@ BLI_INLINE BLI_mempool_chunk *mempool_chunk_find(BLI_mempool_chunk *head, uint i * \note for small pools 1 is a good default, the elements need to be initialized, * adding overhead on creation which is redundant if they aren't used. */ -BLI_INLINE uint mempool_maxchunks(const uint totelem, const uint pchunk) +BLI_INLINE uint mempool_maxchunks(const uint elem_num, const uint pchunk) { - return (totelem <= pchunk) ? 1 : ((totelem / pchunk) + 1); + return (elem_num <= pchunk) ? 1 : ((elem_num / pchunk) + 1); } static BLI_mempool_chunk *mempool_chunk_alloc(BLI_mempool *pool) @@ -250,7 +250,7 @@ static void mempool_chunk_free_all(BLI_mempool_chunk *mpchunk) } } -BLI_mempool *BLI_mempool_create(uint esize, uint totelem, uint pchunk, uint flag) +BLI_mempool *BLI_mempool_create(uint esize, uint elem_num, uint pchunk, uint flag) { BLI_mempool *pool; BLI_freenode *last_tail = NULL; @@ -268,7 +268,7 @@ BLI_mempool *BLI_mempool_create(uint esize, uint totelem, uint pchunk, uint flag esize = MAX2(esize, (uint)sizeof(BLI_freenode)); } - maxchunks = mempool_maxchunks(totelem, pchunk); + maxchunks = mempool_maxchunks(elem_num, pchunk); pool->chunks = NULL; pool->chunk_tail = NULL; @@ -301,7 +301,7 @@ BLI_mempool *BLI_mempool_create(uint esize, uint totelem, uint pchunk, uint flag #endif pool->totused = 0; - if (totelem) { + if (elem_num) { /* Allocate the actual chunks. */ for (i = 0; i < maxchunks; i++) { BLI_mempool_chunk *mpchunk = mempool_chunk_alloc(pool); @@ -510,18 +510,18 @@ static void mempool_threadsafe_iternew(BLI_mempool *pool, BLI_mempool_threadsafe ts_iter->curchunk_threaded_shared = NULL; } -ParallelMempoolTaskData *mempool_iter_threadsafe_create(BLI_mempool *pool, const size_t num_iter) +ParallelMempoolTaskData *mempool_iter_threadsafe_create(BLI_mempool *pool, const size_t iter_num) { BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER); - ParallelMempoolTaskData *iter_arr = MEM_mallocN(sizeof(*iter_arr) * num_iter, __func__); + ParallelMempoolTaskData *iter_arr = MEM_mallocN(sizeof(*iter_arr) * iter_num, __func__); BLI_mempool_chunk **curchunk_threaded_shared = MEM_mallocN(sizeof(void *), __func__); mempool_threadsafe_iternew(pool, &iter_arr->ts_iter); *curchunk_threaded_shared = iter_arr->ts_iter.iter.curchunk; iter_arr->ts_iter.curchunk_threaded_shared = curchunk_threaded_shared; - for (size_t i = 1; i < num_iter; i++) { + for (size_t i = 1; i < iter_num; i++) { iter_arr[i].ts_iter = iter_arr[0].ts_iter; *curchunk_threaded_shared = iter_arr[i].ts_iter.iter.curchunk = ((*curchunk_threaded_shared) ? (*curchunk_threaded_shared)->next : NULL); diff --git a/source/blender/blenlib/intern/BLI_mempool_private.h b/source/blender/blenlib/intern/BLI_mempool_private.h index 5e17d4af05a..042b39c2e7f 100644 --- a/source/blender/blenlib/intern/BLI_mempool_private.h +++ b/source/blender/blenlib/intern/BLI_mempool_private.h @@ -39,7 +39,7 @@ typedef struct ParallelMempoolTaskData { * See #BLI_task_parallel_mempool implementation for detailed usage example. */ ParallelMempoolTaskData *mempool_iter_threadsafe_create(BLI_mempool *pool, - size_t num_iter) ATTR_WARN_UNUSED_RESULT + size_t iter_num) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); void mempool_iter_threadsafe_destroy(ParallelMempoolTaskData *iter_arr) ATTR_NONNULL(); diff --git a/source/blender/blenlib/intern/DLRB_tree.c b/source/blender/blenlib/intern/DLRB_tree.c index 0965d8ba05e..c672bb1f2ce 100644 --- a/source/blender/blenlib/intern/DLRB_tree.c +++ b/source/blender/blenlib/intern/DLRB_tree.c @@ -578,7 +578,7 @@ DLRBT_Node *BLI_dlrbTree_add(DLRBT_Tree *tree, } default: /* update the duplicate node as appropriate */ { - /* Return the updated node after calling the callback. */ + /* Return the updated node after calling the callback. */ node = parNode; if (update_cb) { update_cb(node, data); diff --git a/source/blender/blenlib/intern/bitmap.c b/source/blender/blenlib/intern/bitmap.c index dd022986e14..7fcbc31c066 100644 --- a/source/blender/blenlib/intern/bitmap.c +++ b/source/blender/blenlib/intern/bitmap.c @@ -20,8 +20,8 @@ void BLI_bitmap_set_all(BLI_bitmap *bitmap, bool set, size_t bits) void BLI_bitmap_flip_all(BLI_bitmap *bitmap, size_t bits) { - size_t num_blocks = _BITMAP_NUM_BLOCKS(bits); - for (size_t i = 0; i < num_blocks; i++) { + size_t blocks_num = _BITMAP_NUM_BLOCKS(bits); + for (size_t i = 0; i < blocks_num; i++) { bitmap[i] ^= ~(BLI_bitmap)0; } } @@ -33,16 +33,16 @@ void BLI_bitmap_copy_all(BLI_bitmap *dst, const BLI_bitmap *src, size_t bits) void BLI_bitmap_and_all(BLI_bitmap *dst, const BLI_bitmap *src, size_t bits) { - size_t num_blocks = _BITMAP_NUM_BLOCKS(bits); - for (size_t i = 0; i < num_blocks; i++) { + size_t blocks_num = _BITMAP_NUM_BLOCKS(bits); + for (size_t i = 0; i < blocks_num; i++) { dst[i] &= src[i]; } } void BLI_bitmap_or_all(BLI_bitmap *dst, const BLI_bitmap *src, size_t bits) { - size_t num_blocks = _BITMAP_NUM_BLOCKS(bits); - for (size_t i = 0; i < num_blocks; i++) { + size_t blocks_num = _BITMAP_NUM_BLOCKS(bits); + for (size_t i = 0; i < blocks_num; i++) { dst[i] |= src[i]; } } diff --git a/source/blender/blenlib/intern/convexhull_2d.c b/source/blender/blenlib/intern/convexhull_2d.c index d1daa511b1a..33d1a68a76e 100644 --- a/source/blender/blenlib/intern/convexhull_2d.c +++ b/source/blender/blenlib/intern/convexhull_2d.c @@ -165,7 +165,7 @@ int BLI_convexhull_2d(const float (*points)[2], const int n, int r_points[]) struct PointRef *points_ref = MEM_mallocN(sizeof(*points_ref) * (size_t)n, __func__); float(*points_sort)[2] = MEM_mallocN(sizeof(*points_sort) * (size_t)n, __func__); int *points_map; - int tot, i; + int points_hull_num, i; for (i = 0; i < n; i++) { points_ref[i].pt = points[i]; @@ -178,20 +178,20 @@ int BLI_convexhull_2d(const float (*points)[2], const int n, int r_points[]) memcpy(points_sort[i], points_ref[i].pt, sizeof(float[2])); } - tot = BLI_convexhull_2d_sorted(points_sort, n, r_points); + points_hull_num = BLI_convexhull_2d_sorted(points_sort, n, r_points); /* map back to the original index values */ points_map = (int *)points_sort; /* abuse float array for temp storage */ - for (i = 0; i < tot; i++) { + for (i = 0; i < points_hull_num; i++) { points_map[i] = (int)((const float(*)[2])points_ref[r_points[i]].pt - points); } - memcpy(r_points, points_map, (size_t)tot * sizeof(*points_map)); + memcpy(r_points, points_map, (size_t)points_hull_num * sizeof(*points_map)); MEM_freeN(points_ref); MEM_freeN(points_sort); - return tot; + return points_hull_num; } /** \} */ @@ -252,24 +252,24 @@ float BLI_convexhull_aabb_fit_hull_2d(const float (*points_hull)[2], unsigned in float BLI_convexhull_aabb_fit_points_2d(const float (*points)[2], unsigned int n) { int *index_map; - int tot; + int points_hull_num; float angle; index_map = MEM_mallocN(sizeof(*index_map) * n * 2, __func__); - tot = BLI_convexhull_2d(points, (int)n, index_map); + points_hull_num = BLI_convexhull_2d(points, (int)n, index_map); - if (tot) { + if (points_hull_num) { float(*points_hull)[2]; int j; - points_hull = MEM_mallocN(sizeof(*points_hull) * (size_t)tot, __func__); - for (j = 0; j < tot; j++) { + points_hull = MEM_mallocN(sizeof(*points_hull) * (size_t)points_hull_num, __func__); + for (j = 0; j < points_hull_num; j++) { copy_v2_v2(points_hull[j], points[index_map[j]]); } - angle = BLI_convexhull_aabb_fit_hull_2d(points_hull, (unsigned int)tot); + angle = BLI_convexhull_aabb_fit_hull_2d(points_hull, (unsigned int)points_hull_num); MEM_freeN(points_hull); } else { diff --git a/source/blender/blenlib/intern/delaunay_2d.cc b/source/blender/blenlib/intern/delaunay_2d.cc index e6164c98402..804ba5c3c80 100644 --- a/source/blender/blenlib/intern/delaunay_2d.cc +++ b/source/blender/blenlib/intern/delaunay_2d.cc @@ -245,7 +245,7 @@ template<typename Arith_t> struct CDTArrangement { /** Hint to how much space to reserve in the Vectors of the arrangement, * based on these counts of input elements. */ - void reserve(int num_verts, int num_edges, int num_faces); + void reserve(int verts_num, int edges_num, int faces_num); /** * Add a new vertex to the arrangement, with the given 2D coordinate. @@ -318,7 +318,7 @@ template<typename T> class CDT_state { public: CDTArrangement<T> cdt; /** How many verts were in input (will be first in vert_array). */ - int input_vert_tot; + int input_vert_num; /** Used for visiting things without having to initialized their visit fields. */ int visit_count; /** @@ -332,7 +332,7 @@ template<typename T> class CDT_state { bool need_ids; explicit CDT_state( - int num_input_verts, int num_input_edges, int num_input_faces, T epsilon, bool need_ids); + int input_verts_num, int input_edges_num, int input_faces_num, T epsilon, bool need_ids); }; template<typename T> CDTArrangement<T>::~CDTArrangement() @@ -859,20 +859,20 @@ template<typename T> CDTFace<T> *CDTArrangement<T>::add_face() return f; } -template<typename T> void CDTArrangement<T>::reserve(int num_verts, int num_edges, int num_faces) +template<typename T> void CDTArrangement<T>::reserve(int verts_num, int edges_num, int faces_num) { /* These reserves are just guesses; OK if they aren't exactly right since vectors will resize. */ - this->verts.reserve(2 * num_verts); - this->edges.reserve(3 * num_verts + 2 * num_edges + 3 * 2 * num_faces); - this->faces.reserve(2 * num_verts + 2 * num_edges + 2 * num_faces); + this->verts.reserve(2 * verts_num); + this->edges.reserve(3 * verts_num + 2 * edges_num + 3 * 2 * faces_num); + this->faces.reserve(2 * verts_num + 2 * edges_num + 2 * faces_num); } template<typename T> CDT_state<T>::CDT_state( - int num_input_verts, int num_input_edges, int num_input_faces, T epsilon, bool need_ids) + int input_verts_num, int input_edges_num, int input_faces_num, T epsilon, bool need_ids) { - this->input_vert_tot = num_input_verts; - this->cdt.reserve(num_input_verts, num_input_edges, num_input_faces); + this->input_vert_num = input_verts_num; + this->cdt.reserve(input_verts_num, input_edges_num, input_faces_num); this->cdt.outer_face = this->cdt.add_face(); this->epsilon = epsilon; this->need_ids = need_ids; @@ -919,7 +919,7 @@ template<typename T> inline bool is_deleted_edge(const CDTEdge<T> *e) template<typename T> inline bool is_original_vert(const CDTVert<T> *v, CDT_state<T> *cdt) { - return (v->index < cdt->input_vert_tot); + return (v->index < cdt->input_vert_num); } /** @@ -2188,17 +2188,19 @@ static int power_of_10_greater_equal_to(int x) } /** - Incrementally each edge of each input face as an edge constraint. + * Incrementally each edge of each input face as an edge constraint. * The code will ensure that the #CDTEdge's created will have ids that tie them * back to the original face edge (using a numbering system for those edges * that starts with cdt->face_edge_offset, and continues with the edges in * order around each face in turn. And then the next face starts at * cdt->face_edge_offset beyond the start for the previous face. + * Return the number of faces added, which may be less than input.face.size() + * in the case that some faces have less than 3 sides. */ template<typename T> -void add_face_constraints(CDT_state<T> *cdt_state, - const CDT_input<T> &input, - CDT_output_type output_type) +int add_face_constraints(CDT_state<T> *cdt_state, + const CDT_input<T> &input, + CDT_output_type output_type) { int nv = input.vert.size(); int nf = input.face.size(); @@ -2216,6 +2218,7 @@ void add_face_constraints(CDT_state<T> *cdt_state, * together the are >= INT_MAX, then the Delaunay calculation will take unreasonably long anyway. */ BLI_assert(INT_MAX / cdt_state->face_edge_offset > nf); + int faces_added = 0; for (int f = 0; f < nf; f++) { int flen = input.face[f].size(); if (flen <= 2) { @@ -2231,6 +2234,7 @@ void add_face_constraints(CDT_state<T> *cdt_state, /* Ignore face edges with invalid vertices. */ continue; } + ++faces_added; CDTVert<T> *v1 = cdt->get_vert_resolve_merge(iv1); CDTVert<T> *v2 = cdt->get_vert_resolve_merge(iv2); LinkNode *edge_list; @@ -2265,6 +2269,7 @@ void add_face_constraints(CDT_state<T> *cdt_state, } } } + return faces_added; } /* Delete_edge but try not to mess up outer face. @@ -2642,7 +2647,8 @@ CDT_result<T> get_cdt_output(CDT_state<T> *cdt_state, const CDT_input<T> UNUSED(input), CDT_output_type output_type) { - prepare_cdt_for_output(cdt_state, output_type); + CDT_output_type oty = output_type; + prepare_cdt_for_output(cdt_state, oty); CDT_result<T> result; CDTArrangement<T> *cdt = &cdt_state->cdt; result.face_edge_offset = cdt_state->face_edge_offset; @@ -2672,7 +2678,7 @@ CDT_result<T> get_cdt_output(CDT_state<T> *cdt_state, CDTVert<T> *v = cdt->verts[i]; if (v->merge_to_index != -1) { if (cdt_state->need_ids) { - if (i < cdt_state->input_vert_tot) { + if (i < cdt_state->input_vert_num) { add_to_input_ids(cdt->verts[v->merge_to_index]->input_ids, i); } } @@ -2690,7 +2696,7 @@ CDT_result<T> get_cdt_output(CDT_state<T> *cdt_state, if (v->merge_to_index == -1) { result.vert[i_out] = v->co.exact; if (cdt_state->need_ids) { - if (i < cdt_state->input_vert_tot) { + if (i < cdt_state->input_vert_num) { result.vert_orig[i_out].append(i); } for (int vert : v->input_ids) { @@ -2759,7 +2765,7 @@ CDT_result<T> get_cdt_output(CDT_state<T> *cdt_state, */ template<typename T> void add_input_verts(CDT_state<T> *cdt_state, const CDT_input<T> &input) { - for (int i = 0; i < cdt_state->input_vert_tot; ++i) { + for (int i = 0; i < cdt_state->input_vert_num; ++i) { cdt_state->cdt.add_vert(input.vert[i]); } } @@ -2774,7 +2780,11 @@ CDT_result<T> delaunay_calc(const CDT_input<T> &input, CDT_output_type output_ty add_input_verts(&cdt_state, input); initial_triangulation(&cdt_state.cdt); add_edge_constraints(&cdt_state, input); - add_face_constraints(&cdt_state, input, output_type); + int actual_nf = add_face_constraints(&cdt_state, input, output_type); + if (actual_nf == 0 && !ELEM(output_type, CDT_FULL, CDT_INSIDE, CDT_CONSTRAINTS)) { + /* Can't look for faces or holes if there were no valid input faces. */ + output_type = CDT_INSIDE; + } return get_cdt_output(&cdt_state, input, output_type); } diff --git a/source/blender/blenlib/intern/filereader_zstd.c b/source/blender/blenlib/intern/filereader_zstd.c index 0a04a443e76..5f114f24fb0 100644 --- a/source/blender/blenlib/intern/filereader_zstd.c +++ b/source/blender/blenlib/intern/filereader_zstd.c @@ -25,7 +25,7 @@ typedef struct { size_t in_buf_max_size; struct { - int num_frames; + int frames_num; size_t *compressed_ofs; size_t *uncompressed_ofs; @@ -69,21 +69,21 @@ static bool zstd_read_seek_table(ZstdReader *zstd) return false; } - uint32_t num_frames; - if (base->seek(base, -9, SEEK_END) < 0 || !zstd_read_u32(base, &num_frames)) { + uint32_t frames_num; + if (base->seek(base, -9, SEEK_END) < 0 || !zstd_read_u32(base, &frames_num)) { return false; } /* Each frame has either 2 or 3 uint32_t, and after that we have - * num_frames, flags and magic for another 9 bytes. */ - uint32_t expected_frame_length = num_frames * (has_checksums ? 12 : 8) + 9; + * frames_num, flags and magic for another 9 bytes. */ + uint32_t expected_frame_length = frames_num * (has_checksums ? 12 : 8) + 9; /* The frame starts with another magic number and its length, but these * two fields are not included when counting length. */ off64_t frame_start_ofs = 8 + expected_frame_length; /* Sanity check: Before the start of the seek table frame, - * there must be num_frames frames, each of which at least 8 bytes long. */ + * there must be frames_num frames, each of which at least 8 bytes long. */ off64_t seek_frame_start = base->seek(base, -frame_start_ofs, SEEK_END); - if (seek_frame_start < num_frames * 8) { + if (seek_frame_start < frames_num * 8) { return false; } @@ -96,13 +96,13 @@ static bool zstd_read_seek_table(ZstdReader *zstd) return false; } - zstd->seek.num_frames = num_frames; - zstd->seek.compressed_ofs = MEM_malloc_arrayN(num_frames + 1, sizeof(size_t), __func__); - zstd->seek.uncompressed_ofs = MEM_malloc_arrayN(num_frames + 1, sizeof(size_t), __func__); + zstd->seek.frames_num = frames_num; + zstd->seek.compressed_ofs = MEM_malloc_arrayN(frames_num + 1, sizeof(size_t), __func__); + zstd->seek.uncompressed_ofs = MEM_malloc_arrayN(frames_num + 1, sizeof(size_t), __func__); size_t compressed_ofs = 0; size_t uncompressed_ofs = 0; - for (int i = 0; i < num_frames; i++) { + for (int i = 0; i < frames_num; i++) { uint32_t compressed_size, uncompressed_size; if (!zstd_read_u32(base, &compressed_size) || !zstd_read_u32(base, &uncompressed_size)) { break; @@ -115,8 +115,8 @@ static bool zstd_read_seek_table(ZstdReader *zstd) compressed_ofs += compressed_size; uncompressed_ofs += uncompressed_size; } - zstd->seek.compressed_ofs[num_frames] = compressed_ofs; - zstd->seek.uncompressed_ofs[num_frames] = uncompressed_ofs; + zstd->seek.compressed_ofs[frames_num] = compressed_ofs; + zstd->seek.uncompressed_ofs[frames_num] = uncompressed_ofs; /* Seek to the end of the previous frame for the following #BHead frame detection. */ if (seek_frame_start != compressed_ofs || base->seek(base, seek_frame_start, SEEK_SET) < 0) { @@ -135,9 +135,9 @@ static bool zstd_read_seek_table(ZstdReader *zstd) * Basically just bisection. */ static int zstd_frame_from_pos(ZstdReader *zstd, size_t pos) { - int low = 0, high = zstd->seek.num_frames; + int low = 0, high = zstd->seek.frames_num; - if (pos >= zstd->seek.uncompressed_ofs[zstd->seek.num_frames]) { + if (pos >= zstd->seek.uncompressed_ofs[zstd->seek.frames_num]) { return -1; } @@ -229,13 +229,13 @@ static off64_t zstd_seek(FileReader *reader, off64_t offset, int whence) new_pos = offset; } else if (whence == SEEK_END) { - new_pos = zstd->seek.uncompressed_ofs[zstd->seek.num_frames] + offset; + new_pos = zstd->seek.uncompressed_ofs[zstd->seek.frames_num] + offset; } else { new_pos = zstd->reader.offset + offset; } - if (new_pos < 0 || new_pos > zstd->seek.uncompressed_ofs[zstd->seek.num_frames]) { + if (new_pos < 0 || new_pos > zstd->seek.uncompressed_ofs[zstd->seek.frames_num]) { return -1; } zstd->reader.offset = new_pos; diff --git a/source/blender/blenlib/intern/gsqueue.c b/source/blender/blenlib/intern/gsqueue.c index 4bf4e15d864..b09f5113be7 100644 --- a/source/blender/blenlib/intern/gsqueue.c +++ b/source/blender/blenlib/intern/gsqueue.c @@ -33,7 +33,7 @@ struct _GSQueue { size_t chunk_last_index; /* index into 'chunk_last' */ size_t chunk_elem_max; /* number of elements per chunk */ size_t elem_size; /* memory size of elements */ - size_t totelem; /* total number of elements */ + size_t elem_num; /* total number of elements */ }; static void *queue_get_first_elem(GSQueue *queue) @@ -97,7 +97,7 @@ void BLI_gsqueue_free(GSQueue *queue) void BLI_gsqueue_push(GSQueue *queue, const void *item) { queue->chunk_last_index++; - queue->totelem++; + queue->elem_num++; if (UNLIKELY(queue->chunk_last_index == queue->chunk_elem_max)) { struct QueueChunk *chunk; @@ -134,9 +134,9 @@ void BLI_gsqueue_pop(GSQueue *queue, void *r_item) memcpy(r_item, queue_get_first_elem(queue), queue->elem_size); queue->chunk_first_index++; - queue->totelem--; + queue->elem_num--; - if (UNLIKELY(queue->chunk_first_index == queue->chunk_elem_max || queue->totelem == 0)) { + if (UNLIKELY(queue->chunk_first_index == queue->chunk_elem_max || queue->elem_num == 0)) { struct QueueChunk *chunk_free = queue->chunk_first; queue->chunk_first = queue->chunk_first->next; @@ -153,7 +153,7 @@ void BLI_gsqueue_pop(GSQueue *queue, void *r_item) size_t BLI_gsqueue_len(const GSQueue *queue) { - return queue->totelem; + return queue->elem_num; } bool BLI_gsqueue_is_empty(const GSQueue *queue) diff --git a/source/blender/blenlib/intern/jitter_2d.c b/source/blender/blenlib/intern/jitter_2d.c index 5e840e8178e..8fa0f2c1e15 100644 --- a/source/blender/blenlib/intern/jitter_2d.c +++ b/source/blender/blenlib/intern/jitter_2d.c @@ -126,7 +126,7 @@ void BLI_jitterate2(float (*jit1)[2], float (*jit2)[2], int num, float radius2) void BLI_jitter_init(float (*jitarr)[2], int num) { float(*jit2)[2]; - float num_fl, num_fl_sqrt; + float number_fl, number_fl_sqrt; float x, rad1, rad2, rad3; RNG *rng; int i; @@ -135,20 +135,20 @@ void BLI_jitter_init(float (*jitarr)[2], int num) return; } - num_fl = (float)num; - num_fl_sqrt = sqrtf(num_fl); + number_fl = (float)num; + number_fl_sqrt = sqrtf(number_fl); jit2 = MEM_mallocN(12 + (unsigned int)num * sizeof(float[2]), "initjit"); - rad1 = 1.0f / num_fl_sqrt; - rad2 = 1.0f / num_fl; - rad3 = num_fl_sqrt / num_fl; + rad1 = 1.0f / number_fl_sqrt; + rad2 = 1.0f / number_fl; + rad3 = number_fl_sqrt / number_fl; rng = BLI_rng_new(31415926 + (unsigned int)num); x = 0; for (i = 0; i < num; i++) { jitarr[i][0] = x + rad1 * (float)(0.5 - BLI_rng_get_double(rng)); - jitarr[i][1] = (float)i / num_fl + rad1 * (float)(0.5 - BLI_rng_get_double(rng)); + jitarr[i][1] = (float)i / number_fl + rad1 * (float)(0.5 - BLI_rng_get_double(rng)); x += rad3; x -= floorf(x); } diff --git a/source/blender/blenlib/intern/length_parameterize.cc b/source/blender/blenlib/intern/length_parameterize.cc new file mode 100644 index 00000000000..d6862b96944 --- /dev/null +++ b/source/blender/blenlib/intern/length_parameterize.cc @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_length_parameterize.hh" + +namespace blender::length_parameterize { + +void create_uniform_samples(const Span<float> lengths, + const bool cyclic, + MutableSpan<int> indices, + MutableSpan<float> factors) +{ + const int count = indices.size(); + BLI_assert(count > 0); + BLI_assert(lengths.size() >= 1); + BLI_assert(std::is_sorted(lengths.begin(), lengths.end())); + const int segments_num = lengths.size(); + const int points_num = cyclic ? segments_num : segments_num + 1; + + indices.first() = 0; + factors.first() = 0.0f; + if (count == 1) { + return; + } + + const float total_length = lengths.last(); + if (total_length == 0.0f) { + indices.fill(0); + factors.fill(0.0f); + return; + } + + const float step_length = total_length / (count - (cyclic ? 0 : 1)); + const float step_length_inv = 1.0f / step_length; + + int i_dst = 1; + /* Store the length at the previous point in a variable so it can start out at zero + * (the lengths array doesn't contain 0 for the first point). */ + float prev_length = 0.0f; + for (const int i_src : IndexRange(points_num - 1)) { + const float next_length = lengths[i_src]; + const float segment_length = next_length - prev_length; + if (segment_length == 0.0f) { + continue; + } + /* Add every sample that fits in this segment. */ + const float segment_length_inv = 1.0f / segment_length; + const int segment_samples_num = std::ceil(next_length * step_length_inv - i_dst); + indices.slice(i_dst, segment_samples_num).fill(i_src); + + for (const int i : factors.index_range().slice(i_dst, segment_samples_num)) { + const float length_in_segment = step_length * i - prev_length; + factors[i] = length_in_segment * segment_length_inv; + } + + i_dst += segment_samples_num; + + prev_length = next_length; + } + + /* Add the samples on the last cyclic segment if necessary, and also the samples + * that weren't created in the previous loop due to floating point inaccuracy. */ + if (cyclic && lengths.size() > 1) { + indices.drop_front(i_dst).fill(points_num - 1); + const float segment_length = lengths.last() - lengths.last(1); + if (segment_length == 0.0f) { + return; + } + const float segment_length_inv = 1.0f / segment_length; + for (const int i : indices.index_range().drop_front(i_dst)) { + const float length_in_segment = step_length * i - prev_length; + factors[i] = length_in_segment * segment_length_inv; + } + } + else { + indices.drop_front(i_dst).fill(points_num - 2); + factors.drop_front(i_dst).fill(1.0f); + } +} + +} // namespace blender::length_parameterize diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index e1ec22063e0..1b13493e00c 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -3404,7 +3404,7 @@ bool clip_segment_v3_plane( bool clip_segment_v3_plane_n(const float p1[3], const float p2[3], const float plane_array[][4], - const int plane_tot, + const int plane_num, float r_p1[3], float r_p2[3]) { @@ -3414,7 +3414,7 @@ bool clip_segment_v3_plane_n(const float p1[3], float dp[3]; sub_v3_v3v3(dp, p2, p1); - for (int i = 0; i < plane_tot; i++) { + for (int i = 0; i < plane_num; i++) { const float *plane = plane_array[i]; const float div = dot_v3v3(dp, plane); diff --git a/source/blender/blenlib/intern/mesh_boolean.cc b/source/blender/blenlib/intern/mesh_boolean.cc index 70030fc2bdf..700c126ca4c 100644 --- a/source/blender/blenlib/intern/mesh_boolean.cc +++ b/source/blender/blenlib/intern/mesh_boolean.cc @@ -171,9 +171,9 @@ TriMeshTopology::TriMeshTopology(const IMesh &tm) /* If everything were manifold, `F+V-E=2` and `E=3F/2`. * So an likely overestimate, allowing for non-manifoldness, is `E=2F` and `V=F`. */ const int estimate_num_edges = 2 * tm.face_size(); - const int estimate_num_verts = tm.face_size(); + const int estimate_verts_num = tm.face_size(); edge_tri_.reserve(estimate_num_edges); - vert_edges_.reserve(estimate_num_verts); + vert_edges_.reserve(estimate_verts_num); for (int t : tm.face_index_range()) { const Face &tri = *tm.face(t); BLI_assert(tri.is_tri()); @@ -2607,18 +2607,18 @@ static void test_tri_inside_shapes(const IMesh &tm, * Perturb their directions slightly to make it less likely to hit a seam. * Ray-cast assumes they have unit length, so use r1 near 1 and * ra near 0.5, and rb near .01, but normalized so `sqrt(r1^2 + ra^2 + rb^2) == 1`. */ - constexpr int num_rays = 6; + constexpr int rays_num = 6; constexpr float r1 = 0.9987025295199663f; constexpr float ra = 0.04993512647599832f; constexpr float rb = 0.009987025295199663f; - const float test_rays[num_rays][3] = { + const float test_rays[rays_num][3] = { {r1, ra, rb}, {-r1, -ra, -rb}, {rb, r1, ra}, {-rb, -r1, -ra}, {ra, rb, r1}, {-ra, -rb, -r1}}; InsideShapeTestData data(tm, shape_fn, nshapes); data.hit_parity = Array<int>(nshapes, 0); Array<int> count_insides(nshapes, 0); const float co[3] = { float(offset_test_point[0]), float(offset_test_point[1]), float(offset_test_point[2])}; - for (int i = 0; i < num_rays; ++i) { + for (int i = 0; i < rays_num; ++i) { if (dbg_level > 0) { std::cout << "shoot ray " << i << "(" << test_rays[i][0] << "," << test_rays[i][1] << "," << test_rays[i][2] << ")\n"; @@ -2643,7 +2643,7 @@ static void test_tri_inside_shapes(const IMesh &tm, in_shape[j] = 1.0f; /* Let's say a shape is always inside itself. */ } else { - in_shape[j] = float(count_insides[j]) / float(num_rays); + in_shape[j] = float(count_insides[j]) / float(rays_num); } if (dbg_level > 0) { std::cout << "shape " << j << " inside = " << in_shape[j] << "\n"; @@ -3400,19 +3400,19 @@ static void dissolve_verts(IMesh *imesh, const Array<bool> dissolve, IMeshArena for (int f : imesh->face_index_range()) { const Face &face = *imesh->face(f); face_pos_erase.clear(); - int num_erase = 0; + int erase_num = 0; for (const Vert *v : face) { int v_index = imesh->lookup_vert(v); BLI_assert(v_index != NO_INDEX); if (dissolve[v_index]) { face_pos_erase.append(true); - ++num_erase; + ++erase_num; } else { face_pos_erase.append(false); } } - if (num_erase > 0) { + if (erase_num > 0) { any_faces_erased |= imesh->erase_face_positions(f, face_pos_erase, arena); } } @@ -3475,8 +3475,8 @@ static IMesh polymesh_from_trimesh_with_dissolve(const IMesh &tm_out, if (dbg_level > 1) { std::cout << "merge tris for face " << in_f << "\n"; } - int num_out_tris_for_face = face_output_tris.size(); - if (num_out_tris_for_face == 0) { + int out_tris_for_face_num = face_output_tris.size(); + if (out_tris_for_face_num == 0) { continue; } face_output_face[in_f] = merge_tris_for_face(face_output_tris[in_f], tm_out, imesh_in, arena); diff --git a/source/blender/blenlib/intern/mesh_intersect.cc b/source/blender/blenlib/intern/mesh_intersect.cc index 96ae0750899..d5585f953ec 100644 --- a/source/blender/blenlib/intern/mesh_intersect.cc +++ b/source/blender/blenlib/intern/mesh_intersect.cc @@ -635,8 +635,8 @@ void IMesh::populate_vert() /* This is likely an overestimate, since verts are shared between * faces. It is ok if estimate is over or even under. */ constexpr int ESTIMATE_VERTS_PER_FACE = 4; - int estimate_num_verts = ESTIMATE_VERTS_PER_FACE * face_.size(); - populate_vert(estimate_num_verts); + int estimate_verts_num = ESTIMATE_VERTS_PER_FACE * face_.size(); + populate_vert(estimate_verts_num); } void IMesh::populate_vert(int max_verts) @@ -693,16 +693,16 @@ bool IMesh::erase_face_positions(int f_index, Span<bool> face_pos_erase, IMeshAr { const Face *cur_f = this->face(f_index); int cur_len = cur_f->size(); - int num_to_erase = 0; + int to_erase_num = 0; for (int i : cur_f->index_range()) { if (face_pos_erase[i]) { - ++num_to_erase; + ++to_erase_num; } } - if (num_to_erase == 0) { + if (to_erase_num == 0) { return false; } - int new_len = cur_len - num_to_erase; + int new_len = cur_len - to_erase_num; if (new_len < 3) { /* This erase causes removal of whole face. * Because this may be called from a loop over the face array, @@ -2324,7 +2324,7 @@ class TriOverlaps { BVHTree *tree_b_{nullptr}; BVHTreeOverlap *overlap_{nullptr}; Array<int> first_overlap_; - uint overlap_tot_{0}; + uint overlap_num_{0}; struct CBData { const IMesh &tm; @@ -2386,16 +2386,16 @@ class TriOverlaps { if (two_trees_no_self) { BLI_bvhtree_balance(tree_b_); /* Don't expect a lot of trivial intersects in this case. */ - overlap_ = BLI_bvhtree_overlap(tree_, tree_b_, &overlap_tot_, nullptr, nullptr); + overlap_ = BLI_bvhtree_overlap(tree_, tree_b_, &overlap_num_, nullptr, nullptr); } else { CBData cbdata{tm, shape_fn, nshapes, use_self}; if (nshapes == 1) { - overlap_ = BLI_bvhtree_overlap(tree_, tree_, &overlap_tot_, nullptr, nullptr); + overlap_ = BLI_bvhtree_overlap(tree_, tree_, &overlap_num_, nullptr, nullptr); } else { overlap_ = BLI_bvhtree_overlap( - tree_, tree_, &overlap_tot_, only_different_shapes, &cbdata); + tree_, tree_, &overlap_num_, only_different_shapes, &cbdata); } } /* The rest of the code is simpler and easier to parallelize if, in the two-trees case, @@ -2403,23 +2403,23 @@ class TriOverlaps { * in the repeated part, sorting will then bring things with indexB together. */ if (two_trees_no_self) { overlap_ = static_cast<BVHTreeOverlap *>( - MEM_reallocN(overlap_, 2 * overlap_tot_ * sizeof(overlap_[0]))); - for (uint i = 0; i < overlap_tot_; ++i) { - overlap_[overlap_tot_ + i].indexA = overlap_[i].indexB; - overlap_[overlap_tot_ + i].indexB = overlap_[i].indexA; + MEM_reallocN(overlap_, 2 * overlap_num_ * sizeof(overlap_[0]))); + for (uint i = 0; i < overlap_num_; ++i) { + overlap_[overlap_num_ + i].indexA = overlap_[i].indexB; + overlap_[overlap_num_ + i].indexB = overlap_[i].indexA; } - overlap_tot_ += overlap_tot_; + overlap_num_ += overlap_num_; } /* Sort the overlaps to bring all the intersects with a given indexA together. */ - std::sort(overlap_, overlap_ + overlap_tot_, bvhtreeverlap_cmp); + std::sort(overlap_, overlap_ + overlap_num_, bvhtreeverlap_cmp); if (dbg_level > 0) { - std::cout << overlap_tot_ << " overlaps found:\n"; + std::cout << overlap_num_ << " overlaps found:\n"; for (BVHTreeOverlap ov : overlap()) { std::cout << "A: " << ov.indexA << ", B: " << ov.indexB << "\n"; } } first_overlap_ = Array<int>(tm.face_size(), -1); - for (int i = 0; i < static_cast<int>(overlap_tot_); ++i) { + for (int i = 0; i < static_cast<int>(overlap_num_); ++i) { int t = overlap_[i].indexA; if (first_overlap_[t] == -1) { first_overlap_[t] = i; @@ -2442,7 +2442,7 @@ class TriOverlaps { Span<BVHTreeOverlap> overlap() const { - return Span<BVHTreeOverlap>(overlap_, overlap_tot_); + return Span<BVHTreeOverlap>(overlap_, overlap_num_); } int first_overlap_index(int t) const @@ -2557,13 +2557,13 @@ static void calc_subdivided_non_cluster_tris(Array<IMesh> &r_tri_subdivided, int len; }; Vector<OverlapTriRange> overlap_tri_range; - int overlap_tot = overlap.size(); - overlap_tri_range.reserve(overlap_tot); + int overlap_num = overlap.size(); + overlap_tri_range.reserve(overlap_num); int overlap_index = 0; - while (overlap_index < overlap_tot) { + while (overlap_index < overlap_num) { int t = overlap[overlap_index].indexA; int i = overlap_index; - while (i + 1 < overlap_tot && overlap[i + 1].indexA == t) { + while (i + 1 < overlap_num && overlap[i + 1].indexA == t) { ++i; } /* Now overlap[overlap_index] to overlap[i] have indexA == t. @@ -2581,8 +2581,8 @@ static void calc_subdivided_non_cluster_tris(Array<IMesh> &r_tri_subdivided, } overlap_index = i + 1; } - int overlap_tri_range_tot = overlap_tri_range.size(); - Array<CDT_data> cd_data(overlap_tri_range_tot); + int overlap_tri_range_num = overlap_tri_range.size(); + Array<CDT_data> cd_data(overlap_tri_range_num); int grain_size = 64; threading::parallel_for(overlap_tri_range.index_range(), grain_size, [&](IndexRange range) { for (int otr_index : range) { diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 6c576627fa0..5a96221c8d1 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -53,7 +53,7 @@ static bool BLI_path_is_abs(const char *name); /* implementation */ -int BLI_path_sequence_decode(const char *string, char *head, char *tail, ushort *r_num_len) +int BLI_path_sequence_decode(const char *string, char *head, char *tail, ushort *r_digits_len) { uint nums = 0, nume = 0; int i; @@ -98,8 +98,8 @@ int BLI_path_sequence_decode(const char *string, char *head, char *tail, ushort strcpy(head, string); head[nums] = 0; } - if (r_num_len) { - *r_num_len = nume - nums + 1; + if (r_digits_len) { + *r_digits_len = nume - nums + 1; } return (int)ret; } @@ -114,8 +114,8 @@ int BLI_path_sequence_decode(const char *string, char *head, char *tail, ushort */ BLI_strncpy(head, string, name_end + 1); } - if (r_num_len) { - *r_num_len = 0; + if (r_digits_len) { + *r_digits_len = 0; } return 0; } @@ -750,14 +750,14 @@ bool BLI_path_frame_range(char *path, int sta, int end, int digits) return false; } -bool BLI_path_frame_get(char *path, int *r_frame, int *r_numdigits) +bool BLI_path_frame_get(char *path, int *r_frame, int *r_digits_len) { if (*path) { char *file = (char *)BLI_path_slash_rfind(path); char *c; - int len, numdigits; + int len, digits_len; - numdigits = *r_numdigits = 0; + digits_len = *r_digits_len = 0; if (file == NULL) { file = path; @@ -779,21 +779,21 @@ bool BLI_path_frame_get(char *path, int *r_frame, int *r_numdigits) /* find start of number */ while (c != (file - 1) && isdigit(*c)) { c--; - numdigits++; + digits_len++; } - if (numdigits) { + if (digits_len) { char prevchar; c++; - prevchar = c[numdigits]; - c[numdigits] = 0; + prevchar = c[digits_len]; + c[digits_len] = 0; /* was the number really an extension? */ *r_frame = atoi(c); - c[numdigits] = prevchar; + c[digits_len] = prevchar; - *r_numdigits = numdigits; + *r_digits_len = digits_len; return true; } @@ -812,7 +812,7 @@ void BLI_path_frame_strip(char *path, char *r_ext) char *file = (char *)BLI_path_slash_rfind(path); char *c, *suffix; int len; - int numdigits = 0; + int digits_len = 0; if (file == NULL) { file = path; @@ -836,7 +836,7 @@ void BLI_path_frame_strip(char *path, char *r_ext) /* find start of number */ while (c != (file - 1) && isdigit(*c)) { c--; - numdigits++; + digits_len++; } c++; @@ -845,7 +845,7 @@ void BLI_path_frame_strip(char *path, char *r_ext) BLI_strncpy(r_ext, suffix, suffix_length + 1); /* replace the number with the suffix and terminate the string */ - while (numdigits--) { + while (digits_len--) { *c++ = '#'; } *c = '\0'; diff --git a/source/blender/blenlib/intern/polyfill_2d.c b/source/blender/blenlib/intern/polyfill_2d.c index 76cf7880c7a..eed87eda436 100644 --- a/source/blender/blenlib/intern/polyfill_2d.c +++ b/source/blender/blenlib/intern/polyfill_2d.c @@ -100,7 +100,7 @@ struct KDTree2D { KDTreeNode2D *nodes; const float (*coords)[2]; uint root; - uint totnode; + uint node_num; uint *nodes_map; /* index -> node lookup */ }; @@ -119,14 +119,14 @@ typedef struct PolyFill { struct PolyIndex *indices; /* vertex aligned */ const float (*coords)[2]; - uint coords_tot; + uint coords_num; #ifdef USE_CONVEX_SKIP - uint coords_tot_concave; + uint coords_num_concave; #endif /* A polygon with n vertices has a triangulation of n-2 triangles. */ uint (*tris)[3]; - uint tris_tot; + uint tris_num; #ifdef USE_KDTREE struct KDTree2D kdtree; @@ -202,18 +202,18 @@ static void kdtree2d_new(struct KDTree2D *tree, uint tot, const float (*coords)[ // tree->nodes = nodes; tree->coords = coords; tree->root = KDNODE_UNSET; - tree->totnode = tot; + tree->node_num = tot; } /** * no need for kdtree2d_insert, since we know the coords array. */ -static void kdtree2d_init(struct KDTree2D *tree, const uint coords_tot, const PolyIndex *indices) +static void kdtree2d_init(struct KDTree2D *tree, const uint coords_num, const PolyIndex *indices) { KDTreeNode2D *node; uint i; - for (i = 0, node = tree->nodes; i < coords_tot; i++) { + for (i = 0, node = tree->nodes; i < coords_num; i++) { if (indices[i].sign != CONVEX) { node->neg = node->pos = KDNODE_UNSET; node->index = indices[i].index; @@ -223,26 +223,26 @@ static void kdtree2d_init(struct KDTree2D *tree, const uint coords_tot, const Po } } - BLI_assert(tree->totnode == (uint)(node - tree->nodes)); + BLI_assert(tree->node_num == (uint)(node - tree->nodes)); } static uint kdtree2d_balance_recursive( - KDTreeNode2D *nodes, uint totnode, axis_t axis, const float (*coords)[2], const uint ofs) + KDTreeNode2D *nodes, uint node_num, axis_t axis, const float (*coords)[2], const uint ofs) { KDTreeNode2D *node; uint neg, pos, median, i, j; - if (totnode <= 0) { + if (node_num <= 0) { return KDNODE_UNSET; } - if (totnode == 1) { + if (node_num == 1) { return 0 + ofs; } /* Quick-sort style sorting around median. */ neg = 0; - pos = totnode - 1; - median = totnode / 2; + pos = node_num - 1; + median = node_num / 2; while (pos > neg) { const float co = coords[nodes[pos].index][axis]; @@ -276,14 +276,14 @@ static uint kdtree2d_balance_recursive( axis = !axis; node->neg = kdtree2d_balance_recursive(nodes, median, axis, coords, ofs); node->pos = kdtree2d_balance_recursive( - &nodes[median + 1], (totnode - (median + 1)), axis, coords, (median + 1) + ofs); + &nodes[median + 1], (node_num - (median + 1)), axis, coords, (median + 1) + ofs); return median + ofs; } static void kdtree2d_balance(struct KDTree2D *tree) { - tree->root = kdtree2d_balance_recursive(tree->nodes, tree->totnode, 0, tree->coords, 0); + tree->root = kdtree2d_balance_recursive(tree->nodes, tree->node_num, 0, tree->coords, 0); } static void kdtree2d_init_mapping(struct KDTree2D *tree) @@ -291,7 +291,7 @@ static void kdtree2d_init_mapping(struct KDTree2D *tree) uint i; KDTreeNode2D *node; - for (i = 0, node = tree->nodes; i < tree->totnode; i++, node++) { + for (i = 0, node = tree->nodes; i < tree->node_num; i++, node++) { if (node->neg != KDNODE_UNSET) { tree->nodes[node->neg].parent = i; } @@ -319,7 +319,7 @@ static void kdtree2d_node_remove(struct KDTree2D *tree, uint index) tree->nodes_map[index] = KDNODE_UNSET; node = &tree->nodes[node_index]; - tree->totnode -= 1; + tree->node_num -= 1; BLI_assert((node->flag & KDNODE_FLAG_REMOVED) == 0); node->flag |= KDNODE_FLAG_REMOVED; @@ -435,14 +435,14 @@ static bool kdtree2d_isect_tri(struct KDTree2D *tree, const uint ind[3]) static uint *pf_tri_add(PolyFill *pf) { - return pf->tris[pf->tris_tot++]; + return pf->tris[pf->tris_num++]; } static void pf_coord_remove(PolyFill *pf, PolyIndex *pi) { #ifdef USE_KDTREE /* avoid double lookups, since convex coords are ignored when testing intersections */ - if (pf->kdtree.totnode) { + if (pf->kdtree.node_num) { kdtree2d_node_remove(&pf->kdtree, pi->index); } #endif @@ -458,7 +458,7 @@ static void pf_coord_remove(PolyFill *pf, PolyIndex *pi) pi->next = pi->prev = NULL; #endif - pf->coords_tot -= 1; + pf->coords_num -= 1; } static void pf_triangulate(PolyFill *pf) @@ -473,7 +473,7 @@ static void pf_triangulate(PolyFill *pf) bool reverse = false; #endif - while (pf->coords_tot > 3) { + while (pf->coords_num > 3) { PolyIndex *pi_prev, *pi_next; eSign sign_orig_prev, sign_orig_next; @@ -490,7 +490,7 @@ static void pf_triangulate(PolyFill *pf) #ifdef USE_CONVEX_SKIP if (pi_ear->sign != CONVEX) { - pf->coords_tot_concave -= 1; + pf->coords_num_concave -= 1; } #endif @@ -509,7 +509,7 @@ static void pf_triangulate(PolyFill *pf) pf_coord_sign_calc(pf, pi_prev); #ifdef USE_CONVEX_SKIP if (pi_prev->sign == CONVEX) { - pf->coords_tot_concave -= 1; + pf->coords_num_concave -= 1; # ifdef USE_KDTREE kdtree2d_node_remove(&pf->kdtree, pi_prev->index); # endif @@ -520,7 +520,7 @@ static void pf_triangulate(PolyFill *pf) pf_coord_sign_calc(pf, pi_next); #ifdef USE_CONVEX_SKIP if (pi_next->sign == CONVEX) { - pf->coords_tot_concave -= 1; + pf->coords_num_concave -= 1; # ifdef USE_KDTREE kdtree2d_node_remove(&pf->kdtree, pi_next->index); # endif @@ -551,7 +551,7 @@ static void pf_triangulate(PolyFill *pf) #endif } - if (pf->coords_tot == 3) { + if (pf->coords_num == 3) { uint *tri = pf_tri_add(pf); pi_ear = pf->indices; tri[0] = pi_ear->index; @@ -585,7 +585,7 @@ static PolyIndex *pf_ear_tip_find(PolyFill *pf ) { /* localize */ - const uint coords_tot = pf->coords_tot; + const uint coords_num = pf->coords_num; PolyIndex *pi_ear; uint i; @@ -596,7 +596,7 @@ static PolyIndex *pf_ear_tip_find(PolyFill *pf pi_ear = pf->indices; #endif - i = coords_tot; + i = coords_num; while (i--) { if (pf_ear_tip_check(pf, pi_ear)) { return pi_ear; @@ -626,7 +626,7 @@ static PolyIndex *pf_ear_tip_find(PolyFill *pf pi_ear = pf->indices; #endif - i = coords_tot; + i = coords_num; while (i--) { if (pi_ear->sign != CONCAVE) { return pi_ear; @@ -649,7 +649,7 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip) #endif #if defined(USE_CONVEX_SKIP) && !defined(USE_KDTREE) - uint coords_tot_concave_checked = 0; + uint coords_num_concave_checked = 0; #endif #ifdef USE_CONVEX_SKIP @@ -657,19 +657,19 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip) # ifdef USE_CONVEX_SKIP_TEST /* check if counting is wrong */ { - uint coords_tot_concave_test = 0; + uint coords_num_concave_test = 0; PolyIndex *pi_iter = pi_ear_tip; do { if (pi_iter->sign != CONVEX) { - coords_tot_concave_test += 1; + coords_num_concave_test += 1; } } while ((pi_iter = pi_iter->next) != pi_ear_tip); - BLI_assert(coords_tot_concave_test == pf->coords_tot_concave); + BLI_assert(coords_num_concave_test == pf->coords_num_concave); } # endif /* fast-path for circles */ - if (pf->coords_tot_concave == 0) { + if (pf->coords_num_concave == 0) { return true; } #endif @@ -715,8 +715,8 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip) } # ifdef USE_CONVEX_SKIP - coords_tot_concave_checked += 1; - if (coords_tot_concave_checked == pf->coords_tot_concave) { + coords_num_concave_checked += 1; + if (coords_num_concave_checked == pf->coords_num_concave) { break; } # endif @@ -743,7 +743,7 @@ static void pf_ear_tip_cut(PolyFill *pf, PolyIndex *pi_ear_tip) */ static void polyfill_prepare(PolyFill *pf, const float (*coords)[2], - const uint coords_tot, + const uint coords_num, int coords_sign, uint (*r_tris)[3], PolyIndex *r_indices) @@ -756,32 +756,32 @@ static void polyfill_prepare(PolyFill *pf, /* assign all polyfill members here */ pf->indices = r_indices; pf->coords = coords; - pf->coords_tot = coords_tot; + pf->coords_num = coords_num; #ifdef USE_CONVEX_SKIP - pf->coords_tot_concave = 0; + pf->coords_num_concave = 0; #endif pf->tris = r_tris; - pf->tris_tot = 0; + pf->tris_num = 0; if (coords_sign == 0) { - coords_sign = (cross_poly_v2(coords, coords_tot) >= 0.0f) ? 1 : -1; + coords_sign = (cross_poly_v2(coords, coords_num) >= 0.0f) ? 1 : -1; } else { /* check we're passing in correct args */ #ifdef USE_STRICT_ASSERT # ifndef NDEBUG if (coords_sign == 1) { - BLI_assert(cross_poly_v2(coords, coords_tot) >= 0.0f); + BLI_assert(cross_poly_v2(coords, coords_num) >= 0.0f); } else { - BLI_assert(cross_poly_v2(coords, coords_tot) <= 0.0f); + BLI_assert(cross_poly_v2(coords, coords_num) <= 0.0f); } # endif #endif } if (coords_sign == 1) { - for (i = 0; i < coords_tot; i++) { + for (i = 0; i < coords_num; i++) { indices[i].next = &indices[i + 1]; indices[i].prev = &indices[i - 1]; indices[i].index = i; @@ -789,22 +789,22 @@ static void polyfill_prepare(PolyFill *pf, } else { /* reversed */ - uint n = coords_tot - 1; - for (i = 0; i < coords_tot; i++) { + uint n = coords_num - 1; + for (i = 0; i < coords_num; i++) { indices[i].next = &indices[i + 1]; indices[i].prev = &indices[i - 1]; indices[i].index = (n - i); } } - indices[0].prev = &indices[coords_tot - 1]; - indices[coords_tot - 1].next = &indices[0]; + indices[0].prev = &indices[coords_num - 1]; + indices[coords_num - 1].next = &indices[0]; - for (i = 0; i < coords_tot; i++) { + for (i = 0; i < coords_num; i++) { PolyIndex *pi = &indices[i]; pf_coord_sign_calc(pf, pi); #ifdef USE_CONVEX_SKIP if (pi->sign != CONVEX) { - pf->coords_tot_concave += 1; + pf->coords_num_concave += 1; } #endif } @@ -814,11 +814,11 @@ static void polyfill_calc(PolyFill *pf) { #ifdef USE_KDTREE # ifdef USE_CONVEX_SKIP - if (pf->coords_tot_concave) + if (pf->coords_num_concave) # endif { - kdtree2d_new(&pf->kdtree, pf->coords_tot_concave, pf->coords); - kdtree2d_init(&pf->kdtree, pf->coords_tot, pf->indices); + kdtree2d_new(&pf->kdtree, pf->coords_num_concave, pf->coords); + kdtree2d_init(&pf->kdtree, pf->coords_num, pf->indices); kdtree2d_balance(&pf->kdtree); kdtree2d_init_mapping(&pf->kdtree); } @@ -828,14 +828,14 @@ static void polyfill_calc(PolyFill *pf) } void BLI_polyfill_calc_arena(const float (*coords)[2], - const uint coords_tot, + const uint coords_num, const int coords_sign, uint (*r_tris)[3], struct MemArena *arena) { PolyFill pf; - PolyIndex *indices = BLI_memarena_alloc(arena, sizeof(*indices) * coords_tot); + PolyIndex *indices = BLI_memarena_alloc(arena, sizeof(*indices) * coords_num); #ifdef DEBUG_TIME TIMEIT_START(polyfill2d); @@ -843,22 +843,22 @@ void BLI_polyfill_calc_arena(const float (*coords)[2], polyfill_prepare(&pf, coords, - coords_tot, + coords_num, coords_sign, r_tris, /* cache */ indices); #ifdef USE_KDTREE - if (pf.coords_tot_concave) { - pf.kdtree.nodes = BLI_memarena_alloc(arena, sizeof(*pf.kdtree.nodes) * pf.coords_tot_concave); + if (pf.coords_num_concave) { + pf.kdtree.nodes = BLI_memarena_alloc(arena, sizeof(*pf.kdtree.nodes) * pf.coords_num_concave); pf.kdtree.nodes_map = memset( - BLI_memarena_alloc(arena, sizeof(*pf.kdtree.nodes_map) * coords_tot), + BLI_memarena_alloc(arena, sizeof(*pf.kdtree.nodes_map) * coords_num), 0xff, - sizeof(*pf.kdtree.nodes_map) * coords_tot); + sizeof(*pf.kdtree.nodes_map) * coords_num); } else { - pf.kdtree.totnode = 0; + pf.kdtree.node_num = 0; } #endif @@ -873,25 +873,25 @@ void BLI_polyfill_calc_arena(const float (*coords)[2], } void BLI_polyfill_calc(const float (*coords)[2], - const uint coords_tot, + const uint coords_num, const int coords_sign, uint (*r_tris)[3]) { /* Fallback to heap memory for large allocations. * Avoid running out of stack memory on systems with 512kb stack (macOS). * This happens at around 13,000 points, use a much lower value to be safe. */ - if (UNLIKELY(coords_tot > 8192)) { + if (UNLIKELY(coords_num > 8192)) { /* The buffer size only accounts for the index allocation, * worst case we do two allocations when concave, while we should try to be efficient, * any caller that relies on this frequently should use #BLI_polyfill_calc_arena directly. */ - MemArena *arena = BLI_memarena_new(sizeof(PolyIndex) * coords_tot, __func__); - BLI_polyfill_calc_arena(coords, coords_tot, coords_sign, r_tris, arena); + MemArena *arena = BLI_memarena_new(sizeof(PolyIndex) * coords_num, __func__); + BLI_polyfill_calc_arena(coords, coords_num, coords_sign, r_tris, arena); BLI_memarena_free(arena); return; } PolyFill pf; - PolyIndex *indices = BLI_array_alloca(indices, coords_tot); + PolyIndex *indices = BLI_array_alloca(indices, coords_num); #ifdef DEBUG_TIME TIMEIT_START(polyfill2d); @@ -899,21 +899,21 @@ void BLI_polyfill_calc(const float (*coords)[2], polyfill_prepare(&pf, coords, - coords_tot, + coords_num, coords_sign, r_tris, /* cache */ indices); #ifdef USE_KDTREE - if (pf.coords_tot_concave) { - pf.kdtree.nodes = BLI_array_alloca(pf.kdtree.nodes, pf.coords_tot_concave); - pf.kdtree.nodes_map = memset(BLI_array_alloca(pf.kdtree.nodes_map, coords_tot), + if (pf.coords_num_concave) { + pf.kdtree.nodes = BLI_array_alloca(pf.kdtree.nodes, pf.coords_num_concave); + pf.kdtree.nodes_map = memset(BLI_array_alloca(pf.kdtree.nodes_map, coords_num), 0xff, - sizeof(*pf.kdtree.nodes_map) * coords_tot); + sizeof(*pf.kdtree.nodes_map) * coords_num); } else { - pf.kdtree.totnode = 0; + pf.kdtree.node_num = 0; } #endif diff --git a/source/blender/blenlib/intern/polyfill_2d_beautify.c b/source/blender/blenlib/intern/polyfill_2d_beautify.c index c527e88b440..38cf97d6a8f 100644 --- a/source/blender/blenlib/intern/polyfill_2d_beautify.c +++ b/source/blender/blenlib/intern/polyfill_2d_beautify.c @@ -288,15 +288,15 @@ static void polyedge_rotate(struct HalfEdge *edges, struct HalfEdge *e) } void BLI_polyfill_beautify(const float (*coords)[2], - const uint coords_tot, + const uint coords_num, uint (*tris)[3], /* structs for reuse */ MemArena *arena, Heap *eheap) { - const uint coord_last = coords_tot - 1; - const uint tris_len = coords_tot - 2; + const uint coord_last = coords_num - 1; + const uint tris_len = coords_num - 2; /* internal edges only (between 2 tris) */ const uint edges_len = tris_len - 1; diff --git a/source/blender/blenlib/intern/rand.cc b/source/blender/blenlib/intern/rand.cc index 17bf5585f3f..f6d91cdcc4f 100644 --- a/source/blender/blenlib/intern/rand.cc +++ b/source/blender/blenlib/intern/rand.cc @@ -117,18 +117,18 @@ void BLI_rng_get_tri_sample_float_v3( copy_v3_v3(r_pt, rng->rng.get_triangle_sample_3d(v1, v2, v3)); } -void BLI_rng_shuffle_array(RNG *rng, void *data, unsigned int elem_size_i, unsigned int elem_tot) +void BLI_rng_shuffle_array(RNG *rng, void *data, unsigned int elem_size_i, unsigned int elem_num) { - if (elem_tot <= 1) { + if (elem_num <= 1) { return; } const uint elem_size = elem_size_i; - unsigned int i = elem_tot; + unsigned int i = elem_num; void *temp = malloc(elem_size); while (i--) { - const unsigned int j = BLI_rng_get_uint(rng) % elem_tot; + const unsigned int j = BLI_rng_get_uint(rng) % elem_num; if (i != j) { void *iElem = (unsigned char *)data + i * elem_size_i; void *jElem = (unsigned char *)data + j * elem_size_i; @@ -141,15 +141,15 @@ void BLI_rng_shuffle_array(RNG *rng, void *data, unsigned int elem_size_i, unsig free(temp); } -void BLI_rng_shuffle_bitmap(struct RNG *rng, BLI_bitmap *bitmap, unsigned int bits_tot) +void BLI_rng_shuffle_bitmap(struct RNG *rng, BLI_bitmap *bitmap, unsigned int bits_num) { - if (bits_tot <= 1) { + if (bits_num <= 1) { return; } - unsigned int i = bits_tot; + unsigned int i = bits_num; while (i--) { - const unsigned int j = BLI_rng_get_uint(rng) % bits_tot; + const unsigned int j = BLI_rng_get_uint(rng) % bits_num; if (i != j) { const bool i_bit = BLI_BITMAP_TEST(bitmap, i); const bool j_bit = BLI_BITMAP_TEST(bitmap, j); @@ -187,21 +187,21 @@ float BLI_hash_frand(unsigned int seed) void BLI_array_randomize(void *data, unsigned int elem_size, - unsigned int elem_tot, + unsigned int elem_num, unsigned int seed) { RNG rng; BLI_rng_seed(&rng, seed); - BLI_rng_shuffle_array(&rng, data, elem_size, elem_tot); + BLI_rng_shuffle_array(&rng, data, elem_size, elem_num); } -void BLI_bitmap_randomize(BLI_bitmap *bitmap, unsigned int bits_tot, unsigned int seed) +void BLI_bitmap_randomize(BLI_bitmap *bitmap, unsigned int bits_num, unsigned int seed) { RNG rng; BLI_rng_seed(&rng, seed); - BLI_rng_shuffle_bitmap(&rng, bitmap, bits_tot); + BLI_rng_shuffle_bitmap(&rng, bitmap, bits_num); } /* ********* for threaded random ************** */ diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c index 7e9893925a4..32932c3dee1 100644 --- a/source/blender/blenlib/intern/scanfill.c +++ b/source/blender/blenlib/intern/scanfill.c @@ -124,7 +124,7 @@ ScanFillVert *BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3]) zero_v2(sf_v->xy); sf_v->keyindex = 0; sf_v->poly_nr = sf_ctx->poly_nr; - sf_v->edge_tot = 0; + sf_v->edge_count = 0; sf_v->f = SF_VERT_NEW; sf_v->user_flag = 0; @@ -373,14 +373,14 @@ static bool boundinsideEV(ScanFillEdge *eed, ScanFillVert *eve) static void testvertexnearedge(ScanFillContext *sf_ctx) { - /* only vertices with (->edge_tot == 1) are being tested for + /* only vertices with (->edge_count == 1) are being tested for * being close to an edge, if true insert */ ScanFillVert *eve; ScanFillEdge *eed, *ed1; for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { - if (eve->edge_tot == 1) { + if (eve->edge_count == 1) { /* find the edge which has vertex eve, * NOTE: we _know_ this will crash if 'ed1' becomes NULL * but this will never happen. */ @@ -398,14 +398,14 @@ static void testvertexnearedge(ScanFillContext *sf_ctx) if (eve != eed->v1 && eve != eed->v2 && eve->poly_nr == eed->poly_nr) { if (compare_v2v2(eve->xy, eed->v1->xy, SF_EPSILON)) { ed1->v2 = eed->v1; - eed->v1->edge_tot++; - eve->edge_tot = 0; + eed->v1->edge_count++; + eve->edge_count = 0; break; } if (compare_v2v2(eve->xy, eed->v2->xy, SF_EPSILON)) { ed1->v2 = eed->v2; - eed->v2->edge_tot++; - eve->edge_tot = 0; + eed->v2->edge_count++; + eve->edge_count = 0; break; } @@ -418,7 +418,7 @@ static void testvertexnearedge(ScanFillContext *sf_ctx) // printf("fill: vertex near edge %x\n", eve); ed1->poly_nr = eed->poly_nr; eed->v1 = eve; - eve->edge_tot = 3; + eve->edge_count = 3; break; } } @@ -597,14 +597,14 @@ static unsigned int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int fl /* Set connect-flags. */ for (ed1 = sc->edge_first; ed1; ed1 = eed_next) { eed_next = ed1->next; - if (ed1->v1->edge_tot == 1 || ed1->v2->edge_tot == 1) { + if (ed1->v1->edge_count == 1 || ed1->v2->edge_count == 1) { BLI_remlink((ListBase *)&(sc->edge_first), ed1); BLI_addtail(&sf_ctx->filledgebase, ed1); - if (ed1->v1->edge_tot > 1) { - ed1->v1->edge_tot--; + if (ed1->v1->edge_count > 1) { + ed1->v1->edge_count--; } - if (ed1->v2->edge_tot > 1) { - ed1->v2->edge_tot--; + if (ed1->v2->edge_count > 1) { + ed1->v2->edge_count--; } } else { @@ -628,8 +628,8 @@ static unsigned int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int fl // printf("just 1 edge to vert\n"); BLI_addtail(&sf_ctx->filledgebase, ed1); ed1->v2->f = SF_VERT_NEW; - ed1->v1->edge_tot--; - ed1->v2->edge_tot--; + ed1->v1->edge_count--; + ed1->v2->edge_count--; } else { /* test rest of vertices */ @@ -697,8 +697,8 @@ static unsigned int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int fl BLI_insertlinkbefore((ListBase *)&(sc->edge_first), ed2, ed3); ed3->v2->f = SF_VERT_AVAILABLE; ed3->f = SF_EDGE_INTERNAL; - ed3->v1->edge_tot++; - ed3->v2->edge_tot++; + ed3->v1->edge_count++; + ed3->v2->edge_count++; } else { /* new triangle */ @@ -708,39 +708,39 @@ static unsigned int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int fl BLI_remlink((ListBase *)&(sc->edge_first), ed1); BLI_addtail(&sf_ctx->filledgebase, ed1); ed1->v2->f = SF_VERT_NEW; - ed1->v1->edge_tot--; - ed1->v2->edge_tot--; + ed1->v1->edge_count--; + ed1->v2->edge_count--; /* ed2 can be removed when it's a boundary edge */ if (((ed2->f == SF_EDGE_NEW) && twoconnected) /* || (ed2->f == SF_EDGE_BOUNDARY) */) { BLI_remlink((ListBase *)&(sc->edge_first), ed2); BLI_addtail(&sf_ctx->filledgebase, ed2); ed2->v2->f = SF_VERT_NEW; - ed2->v1->edge_tot--; - ed2->v2->edge_tot--; + ed2->v1->edge_count--; + ed2->v2->edge_count--; } /* new edge */ ed3 = BLI_scanfill_edge_add(sf_ctx, v1, v3); BLI_remlink(&sf_ctx->filledgebase, ed3); ed3->f = SF_EDGE_INTERNAL; - ed3->v1->edge_tot++; - ed3->v2->edge_tot++; + ed3->v1->edge_count++; + ed3->v2->edge_count++; // printf("add new edge %x %x\n", v1, v3); sc1 = addedgetoscanlist(scdata, ed3, verts); if (sc1) { /* ed3 already exists: remove if a boundary */ // printf("Edge exists\n"); - ed3->v1->edge_tot--; - ed3->v2->edge_tot--; + ed3->v1->edge_count--; + ed3->v2->edge_count--; for (ed3 = sc1->edge_first; ed3; ed3 = ed3->next) { if ((ed3->v1 == v1 && ed3->v2 == v3) || (ed3->v1 == v3 && ed3->v2 == v1)) { if (twoconnected /* || (ed3->f == SF_EDGE_BOUNDARY) */) { BLI_remlink((ListBase *)&(sc1->edge_first), ed3); BLI_addtail(&sf_ctx->filledgebase, ed3); - ed3->v1->edge_tot--; - ed3->v2->edge_tot--; + ed3->v1->edge_count--; + ed3->v2->edge_count--; } break; } @@ -752,14 +752,14 @@ static unsigned int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int fl /* test for loose edges */ for (ed1 = sc->edge_first; ed1; ed1 = eed_next) { eed_next = ed1->next; - if (ed1->v1->edge_tot < 2 || ed1->v2->edge_tot < 2) { + if (ed1->v1->edge_count < 2 || ed1->v2->edge_count < 2) { BLI_remlink((ListBase *)&(sc->edge_first), ed1); BLI_addtail(&sf_ctx->filledgebase, ed1); - if (ed1->v1->edge_tot > 1) { - ed1->v1->edge_tot--; + if (ed1->v1->edge_count > 1) { + ed1->v1->edge_count--; } - if (ed1->v2->edge_tot > 1) { - ed1->v2->edge_tot--; + if (ed1->v2->edge_count > 1) { + ed1->v2->edge_count--; } } } @@ -838,7 +838,7 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const * however they should always be zero'd so check instead */ BLI_assert(eve->f == 0); BLI_assert(sf_ctx->poly_nr || eve->poly_nr == 0); - BLI_assert(eve->edge_tot == 0); + BLI_assert(eve->edge_count == 0); } #endif @@ -964,10 +964,10 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const if (flag & BLI_SCANFILL_CALC_LOOSE) { unsigned int toggle = 0; for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { - if (eed->v1->edge_tot++ > 250) { + if (eed->v1->edge_count++ > 250) { break; } - if (eed->v2->edge_tot++ > 250) { + if (eed->v2->edge_count++ > 250) { break; } } @@ -979,7 +979,7 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const return 0; } - /* does it only for vertices with (->edge_tot == 1) */ + /* does it only for vertices with (->edge_count == 1) */ testvertexnearedge(sf_ctx); ok = true; @@ -990,14 +990,14 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const for (eed = (toggle & 1) ? sf_ctx->filledgebase.first : sf_ctx->filledgebase.last; eed; eed = eed_next) { eed_next = (toggle & 1) ? eed->next : eed->prev; - if (eed->v1->edge_tot == 1) { - eed->v2->edge_tot--; + if (eed->v1->edge_count == 1) { + eed->v2->edge_count--; BLI_remlink(&sf_ctx->fillvertbase, eed->v1); BLI_remlink(&sf_ctx->filledgebase, eed); ok = true; } - else if (eed->v2->edge_tot == 1) { - eed->v1->edge_tot--; + else if (eed->v2->edge_count == 1) { + eed->v1->edge_count--; BLI_remlink(&sf_ctx->fillvertbase, eed->v2); BLI_remlink(&sf_ctx->filledgebase, eed); ok = true; @@ -1012,14 +1012,14 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const else { /* skip checks for loose edges */ for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { - eed->v1->edge_tot++; - eed->v2->edge_tot++; + eed->v1->edge_count++; + eed->v2->edge_count++; } #ifdef DEBUG /* ensure we're right! */ for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { - BLI_assert(eed->v1->edge_tot != 1); - BLI_assert(eed->v2->edge_tot != 1); + BLI_assert(eed->v1->edge_count != 1); + BLI_assert(eed->v2->edge_count != 1); } #endif } @@ -1027,7 +1027,7 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const /* CURRENT STATUS: * - `eve->f`: 1 = available in edges. * - `eve->poly_nr`: poly-number. - * - `eve->edge_tot`: amount of edges connected to vertex. + * - `eve->edge_count`: amount of edges connected to vertex. * - `eve->tmp.v`: store! original vertex number. * * - `eed->f`: 1 = boundary edge (optionally set by caller). @@ -1058,7 +1058,7 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const min_xy_p[1] = (min_xy_p[1]) < (eve->xy[1]) ? (min_xy_p[1]) : (eve->xy[1]); max_xy_p[0] = (max_xy_p[0]) > (eve->xy[0]) ? (max_xy_p[0]) : (eve->xy[0]); max_xy_p[1] = (max_xy_p[1]) > (eve->xy[1]) ? (max_xy_p[1]) : (eve->xy[1]); - if (eve->edge_tot > 2) { + if (eve->edge_count > 2) { pflist[eve->poly_nr].f = SF_POLY_VALID; } } diff --git a/source/blender/blenlib/intern/scanfill_utils.c b/source/blender/blenlib/intern/scanfill_utils.c index 149589fb933..1d2225a5b56 100644 --- a/source/blender/blenlib/intern/scanfill_utils.c +++ b/source/blender/blenlib/intern/scanfill_utils.c @@ -359,7 +359,7 @@ bool BLI_scanfill_calc_self_isect(ScanFillContext *sf_ctx, ListBase *remvertbase, ListBase *remedgebase) { - const unsigned int poly_tot = (unsigned int)sf_ctx->poly_nr + 1; + const unsigned int poly_num = (unsigned int)sf_ctx->poly_nr + 1; unsigned int eed_index = 0; int totvert_new = 0; bool changed = false; @@ -370,7 +370,7 @@ bool BLI_scanfill_calc_self_isect(ScanFillContext *sf_ctx, return false; } - poly_info = MEM_callocN(sizeof(*poly_info) * poly_tot, __func__); + poly_info = MEM_callocN(sizeof(*poly_info) * poly_num, __func__); /* get the polygon span */ if (sf_ctx->poly_nr == 0) { @@ -408,7 +408,7 @@ bool BLI_scanfill_calc_self_isect(ScanFillContext *sf_ctx, /* self-intersect each polygon */ { unsigned short poly_nr; - for (poly_nr = 0; poly_nr < poly_tot; poly_nr++) { + for (poly_nr = 0; poly_nr < poly_num; poly_nr++) { changed |= scanfill_preprocess_self_isect(sf_ctx, poly_info, poly_nr, remedgebase); } } diff --git a/source/blender/blenlib/intern/stack.c b/source/blender/blenlib/intern/stack.c index 61319613859..ff34cfe41cb 100644 --- a/source/blender/blenlib/intern/stack.c +++ b/source/blender/blenlib/intern/stack.c @@ -34,7 +34,7 @@ struct BLI_Stack { size_t chunk_elem_max; /* number of elements per chunk */ size_t elem_size; #ifdef USE_TOTELEM - size_t totelem; + size_t elem_num; #endif }; @@ -119,7 +119,7 @@ void *BLI_stack_push_r(BLI_Stack *stack) BLI_assert(stack->chunk_index < stack->chunk_elem_max); #ifdef USE_TOTELEM - stack->totelem++; + stack->elem_num++; #endif /* Return end of stack */ @@ -175,7 +175,7 @@ void BLI_stack_discard(BLI_Stack *stack) BLI_assert(BLI_stack_is_empty(stack) == false); #ifdef USE_TOTELEM - stack->totelem--; + stack->elem_num--; #endif if (UNLIKELY(--stack->chunk_index == CHUNK_EMPTY)) { struct StackChunk *chunk_free; @@ -193,10 +193,10 @@ void BLI_stack_discard(BLI_Stack *stack) void BLI_stack_clear(BLI_Stack *stack) { #ifdef USE_TOTELEM - if (UNLIKELY(stack->totelem == 0)) { + if (UNLIKELY(stack->elem_num == 0)) { return; } - stack->totelem = 0; + stack->elem_num = 0; #else if (UNLIKELY(stack->chunk_curr == NULL)) { return; @@ -225,29 +225,29 @@ void BLI_stack_clear(BLI_Stack *stack) size_t BLI_stack_count(const BLI_Stack *stack) { #ifdef USE_TOTELEM - return stack->totelem; + return stack->elem_num; #else struct StackChunk *data = stack->chunk_curr; - size_t totelem = stack->chunk_index + 1; + size_t elem_num = stack->chunk_index + 1; size_t i; - if (totelem != stack->chunk_elem_max) { + if (elem_num != stack->chunk_elem_max) { data = data->next; } else { - totelem = 0; + elem_num = 0; } for (i = 0; data; data = data->next) { i++; } - totelem += stack->chunk_elem_max * i; - return totelem; + elem_num += stack->chunk_elem_max * i; + return elem_num; #endif } bool BLI_stack_is_empty(const BLI_Stack *stack) { #ifdef USE_TOTELEM - BLI_assert((stack->chunk_curr == NULL) == (stack->totelem == 0)); + BLI_assert((stack->chunk_curr == NULL) == (stack->elem_num == 0)); #endif return (stack->chunk_curr == NULL); } diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index 75fa628e701..74559751d91 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -1131,11 +1131,11 @@ void BLI_str_format_byte_unit(char dst[15], long long int bytes, const bool base const int base = base_10 ? 1000 : 1024; const char *units_base_10[] = {"B", "KB", "MB", "GB", "TB", "PB"}; const char *units_base_2[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB"}; - const int tot_units = ARRAY_SIZE(units_base_2); + const int units_num = ARRAY_SIZE(units_base_2); BLI_STATIC_ASSERT(ARRAY_SIZE(units_base_2) == ARRAY_SIZE(units_base_10), "array size mismatch"); - while ((fabs(bytes_converted) >= base) && ((order + 1) < tot_units)) { + while ((fabs(bytes_converted) >= base) && ((order + 1) < units_num)) { bytes_converted /= base; order++; } @@ -1155,9 +1155,9 @@ void BLI_str_format_attribute_domain_size(char dst[7], int number_to_format) int order = 0; const float base = 1000; const char *units[] = {"", "K", "M", "B"}; - const int tot_units = ARRAY_SIZE(units); + const int units_num = ARRAY_SIZE(units); - while ((fabsf(number_to_format_converted) >= base) && ((order + 1) < tot_units)) { + while ((fabsf(number_to_format_converted) >= base) && ((order + 1) < units_num)) { number_to_format_converted /= base; order++; } diff --git a/source/blender/blenlib/intern/task_iterator.c b/source/blender/blenlib/intern/task_iterator.c index 4ee4e6c6ff2..d5afbb2b117 100644 --- a/source/blender/blenlib/intern/task_iterator.c +++ b/source/blender/blenlib/intern/task_iterator.c @@ -40,8 +40,8 @@ * \{ */ BLI_INLINE void task_parallel_calc_chunk_size(const TaskParallelSettings *settings, - const int tot_items, - int num_tasks, + const int items_num, + int tasks_num, int *r_chunk_size) { int chunk_size = 0; @@ -50,7 +50,7 @@ BLI_INLINE void task_parallel_calc_chunk_size(const TaskParallelSettings *settin /* Some users of this helper will still need a valid chunk size in case processing is not * threaded. We can use a bigger one than in default threaded case then. */ chunk_size = 1024; - num_tasks = 1; + tasks_num = 1; } else if (settings->min_iter_per_thread > 0) { /* Already set by user, no need to do anything here. */ @@ -61,24 +61,24 @@ BLI_INLINE void task_parallel_calc_chunk_size(const TaskParallelSettings *settin * The idea here is to increase the chunk size to compensate for a rather measurable threading * overhead caused by fetching tasks. With too many CPU threads we are starting * to spend too much time in those overheads. - * First values are: 1 if num_tasks < 16; - * else 2 if num_tasks < 32; - * else 3 if num_tasks < 48; - * else 4 if num_tasks < 64; + * First values are: 1 if tasks_num < 16; + * else 2 if tasks_num < 32; + * else 3 if tasks_num < 48; + * else 4 if tasks_num < 64; * etc. * NOTE: If we wanted to keep the 'power of two' multiplier, we'd need something like: - * 1 << max_ii(0, (int)(sizeof(int) * 8) - 1 - bitscan_reverse_i(num_tasks) - 3) + * 1 << max_ii(0, (int)(sizeof(int) * 8) - 1 - bitscan_reverse_i(tasks_num) - 3) */ - const int num_tasks_factor = max_ii(1, num_tasks >> 3); + const int tasks_num_factor = max_ii(1, tasks_num >> 3); /* We could make that 'base' 32 number configurable in TaskParallelSettings too, or maybe just * always use that heuristic using TaskParallelSettings.min_iter_per_thread as basis? */ - chunk_size = 32 * num_tasks_factor; + chunk_size = 32 * tasks_num_factor; /* Basic heuristic to avoid threading on low amount of items. * We could make that limit configurable in settings too. */ - if (tot_items > 0 && tot_items < max_ii(256, chunk_size * 2)) { - chunk_size = tot_items; + if (items_num > 0 && items_num < max_ii(256, chunk_size * 2)) { + chunk_size = items_num; } } @@ -95,7 +95,7 @@ typedef struct TaskParallelIteratorState { /* Common data also passed to the generator callback. */ TaskParallelIteratorStateShared iter_shared; /* Total number of items. If unknown, set it to a negative number. */ - int tot_items; + int items_num; } TaskParallelIteratorState; static void parallel_iterator_func_do(TaskParallelIteratorState *__restrict state, @@ -188,10 +188,10 @@ static void task_parallel_iterator_no_threads(const TaskParallelSettings *settin static void task_parallel_iterator_do(const TaskParallelSettings *settings, TaskParallelIteratorState *state) { - const int num_threads = BLI_task_scheduler_num_threads(); + const int threads_num = BLI_task_scheduler_num_threads(); task_parallel_calc_chunk_size( - settings, state->tot_items, num_threads, &state->iter_shared.chunk_size); + settings, state->items_num, threads_num, &state->iter_shared.chunk_size); if (!settings->use_threading) { task_parallel_iterator_no_threads(settings, state); @@ -199,13 +199,13 @@ static void task_parallel_iterator_do(const TaskParallelSettings *settings, } const int chunk_size = state->iter_shared.chunk_size; - const int tot_items = state->tot_items; - const size_t num_tasks = tot_items >= 0 ? - (size_t)min_ii(num_threads, state->tot_items / chunk_size) : - (size_t)num_threads; + const int items_num = state->items_num; + const size_t tasks_num = items_num >= 0 ? + (size_t)min_ii(threads_num, state->items_num / chunk_size) : + (size_t)threads_num; - BLI_assert(num_tasks > 0); - if (num_tasks == 1) { + BLI_assert(tasks_num > 0); + if (tasks_num == 1) { task_parallel_iterator_no_threads(settings, state); return; } @@ -223,10 +223,10 @@ static void task_parallel_iterator_do(const TaskParallelSettings *settings, TaskPool *task_pool = BLI_task_pool_create(state, TASK_PRIORITY_HIGH); if (use_userdata_chunk) { - userdata_chunk_array = MALLOCA(userdata_chunk_size * num_tasks); + userdata_chunk_array = MALLOCA(userdata_chunk_size * tasks_num); } - for (size_t i = 0; i < num_tasks; i++) { + for (size_t i = 0; i < tasks_num; i++) { if (use_userdata_chunk) { userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i); memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size); @@ -243,7 +243,7 @@ static void task_parallel_iterator_do(const TaskParallelSettings *settings, if (use_userdata_chunk) { if (settings->func_reduce != NULL || settings->func_free != NULL) { - for (size_t i = 0; i < num_tasks; i++) { + for (size_t i = 0; i < tasks_num; i++) { userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i); if (settings->func_reduce != NULL) { settings->func_reduce(state->userdata, userdata_chunk, userdata_chunk_local); @@ -253,7 +253,7 @@ static void task_parallel_iterator_do(const TaskParallelSettings *settings, } } } - MALLOCA_FREE(userdata_chunk_array, userdata_chunk_size * num_tasks); + MALLOCA_FREE(userdata_chunk_array, userdata_chunk_size * tasks_num); } BLI_spin_end(&spin_lock); @@ -264,13 +264,13 @@ void BLI_task_parallel_iterator(void *userdata, TaskParallelIteratorIterFunc iter_func, void *init_item, const int init_index, - const int tot_items, + const int items_num, TaskParallelIteratorFunc func, const TaskParallelSettings *settings) { TaskParallelIteratorState state = {0}; - state.tot_items = tot_items; + state.items_num = items_num; state.iter_shared.next_index = init_index; state.iter_shared.next_item = init_item; state.iter_shared.is_finished = false; @@ -314,7 +314,7 @@ void BLI_task_parallel_listbase(ListBase *listbase, TaskParallelIteratorState state = {0}; - state.tot_items = BLI_listbase_count(listbase); + state.items_num = BLI_listbase_count(listbase); state.iter_shared.next_index = 0; state.iter_shared.next_item = listbase->first; state.iter_shared.is_finished = false; @@ -391,25 +391,25 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, ParallelMempoolState state; TaskPool *task_pool = BLI_task_pool_create(&state, TASK_PRIORITY_HIGH); - const int num_threads = BLI_task_scheduler_num_threads(); + const int threads_num = BLI_task_scheduler_num_threads(); /* The idea here is to prevent creating task for each of the loop iterations * and instead have tasks which are evenly distributed across CPU cores and * pull next item to be crunched using the threaded-aware BLI_mempool_iter. */ - const int num_tasks = num_threads + 2; + const int tasks_num = threads_num + 2; state.userdata = userdata; state.func = func; if (use_userdata_chunk) { - userdata_chunk_array = MALLOCA(userdata_chunk_size * num_tasks); + userdata_chunk_array = MALLOCA(userdata_chunk_size * tasks_num); } ParallelMempoolTaskData *mempool_iterator_data = mempool_iter_threadsafe_create( - mempool, (size_t)num_tasks); + mempool, (size_t)tasks_num); - for (int i = 0; i < num_tasks; i++) { + for (int i = 0; i < tasks_num; i++) { void *userdata_chunk_local = NULL; if (use_userdata_chunk) { userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i); @@ -429,7 +429,7 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, if (use_userdata_chunk) { if ((settings->func_free != NULL) || (settings->func_reduce != NULL)) { - for (int i = 0; i < num_tasks; i++) { + for (int i = 0; i < tasks_num; i++) { if (settings->func_reduce) { settings->func_reduce( userdata, userdata_chunk, mempool_iterator_data[i].tls.userdata_chunk); @@ -439,7 +439,7 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, } } } - MALLOCA_FREE(userdata_chunk_array, userdata_chunk_size * num_tasks); + MALLOCA_FREE(userdata_chunk_array, userdata_chunk_size * tasks_num); } mempool_iter_threadsafe_destroy(mempool_iterator_data); diff --git a/source/blender/blenlib/intern/task_scheduler.cc b/source/blender/blenlib/intern/task_scheduler.cc index 32c833fae38..1f7747453c1 100644 --- a/source/blender/blenlib/intern/task_scheduler.cc +++ b/source/blender/blenlib/intern/task_scheduler.cc @@ -31,14 +31,14 @@ static tbb::global_control *task_scheduler_global_control = nullptr; void BLI_task_scheduler_init() { #ifdef WITH_TBB_GLOBAL_CONTROL - const int num_threads_override = BLI_system_num_threads_override_get(); + const int threads_override_num = BLI_system_num_threads_override_get(); - if (num_threads_override > 0) { + if (threads_override_num > 0) { /* Override number of threads. This settings is used within the lifetime * of tbb::global_control, so we allocate it on the heap. */ task_scheduler_global_control = MEM_new<tbb::global_control>( - __func__, tbb::global_control::max_allowed_parallelism, num_threads_override); - task_scheduler_num_threads = num_threads_override; + __func__, tbb::global_control::max_allowed_parallelism, threads_override_num); + task_scheduler_num_threads = threads_override_num; } else { /* Let TBB choose the number of threads. For (legacy) code that calls diff --git a/source/blender/blenlib/intern/threads.cc b/source/blender/blenlib/intern/threads.cc index ff67f821d1e..70c1e701348 100644 --- a/source/blender/blenlib/intern/threads.cc +++ b/source/blender/blenlib/intern/threads.cc @@ -109,7 +109,7 @@ static pthread_mutex_t _fftw_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _view3d_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_t mainid; static unsigned int thread_levels = 0; /* threads can be invoked inside threads */ -static int num_threads_override = 0; +static int threads_override_num = 0; /* just a max for security reasons */ #define RE_MAX_THREAD BLENDER_MAX_THREADS @@ -282,8 +282,8 @@ int BLI_system_thread_count() { static int t = -1; - if (num_threads_override != 0) { - return num_threads_override; + if (threads_override_num != 0) { + return threads_override_num; } if (LIKELY(t != -1)) { return t; @@ -316,12 +316,12 @@ int BLI_system_thread_count() void BLI_system_num_threads_override_set(int num) { - num_threads_override = num; + threads_override_num = num; } int BLI_system_num_threads_override_get() { - return num_threads_override; + return threads_override_num; } /* Global Mutex Locks */ diff --git a/source/blender/blenlib/intern/uuid.cc b/source/blender/blenlib/intern/uuid.cc index b175ed4a770..890a721a9d1 100644 --- a/source/blender/blenlib/intern/uuid.cc +++ b/source/blender/blenlib/intern/uuid.cc @@ -102,7 +102,7 @@ void BLI_uuid_format(char *buffer, const bUUID uuid) bool BLI_uuid_parse_string(bUUID *uuid, const char *buffer) { - const int num_fields_parsed = std::sscanf( + const int fields_parsed_num = std::sscanf( buffer, "%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", &uuid->time_low, @@ -116,7 +116,7 @@ bool BLI_uuid_parse_string(bUUID *uuid, const char *buffer) &uuid->node[3], &uuid->node[4], &uuid->node[5]); - return num_fields_parsed == 11; + return fields_parsed_num == 11; } std::ostream &operator<<(std::ostream &stream, bUUID uuid) diff --git a/source/blender/blenlib/tests/BLI_cpp_type_test.cc b/source/blender/blenlib/tests/BLI_cpp_type_test.cc index 94456e1ee28..f00767eda8c 100644 --- a/source/blender/blenlib/tests/BLI_cpp_type_test.cc +++ b/source/blender/blenlib/tests/BLI_cpp_type_test.cc @@ -118,6 +118,40 @@ TEST(cpp_type, DefaultConstruction) EXPECT_EQ(buffer[8], 0); } +TEST(cpp_type, DefaultConstructTrivial) +{ + int value = 5; + CPPType::get<int>().default_construct(&value); + EXPECT_EQ(value, 5); +} + +TEST(cpp_type, ValueInitialize) +{ + int buffer[10] = {0}; + CPPType_TestType.value_initialize((void *)buffer); + EXPECT_EQ(buffer[0], default_constructed_value); + EXPECT_EQ(buffer[1], 0); + CPPType_TestType.value_initialize_n((void *)buffer, 3); + EXPECT_EQ(buffer[0], default_constructed_value); + EXPECT_EQ(buffer[1], default_constructed_value); + EXPECT_EQ(buffer[2], default_constructed_value); + EXPECT_EQ(buffer[3], 0); + CPPType_TestType.value_initialize_indices((void *)buffer, {2, 5, 7}); + EXPECT_EQ(buffer[2], default_constructed_value); + EXPECT_EQ(buffer[4], 0); + EXPECT_EQ(buffer[5], default_constructed_value); + EXPECT_EQ(buffer[6], 0); + EXPECT_EQ(buffer[7], default_constructed_value); + EXPECT_EQ(buffer[8], 0); +} + +TEST(cpp_type, ValueInitializeTrivial) +{ + int value = 5; + CPPType::get<int>().value_initialize(&value); + EXPECT_EQ(value, 0); +} + TEST(cpp_type, Destruct) { int buffer[10] = {0}; diff --git a/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc b/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc index bdf263d982a..25ee523ebc0 100644 --- a/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc +++ b/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc @@ -1788,7 +1788,7 @@ TEST(delaunay_d, CintTwoFaceNoIds) #if DO_TEXT_TESTS template<typename T> void text_test( - int num_arc_points, int num_lets_per_line, int num_lines, CDT_output_type otype, bool need_ids) + int arc_points_num, int lets_per_line_num, int lines_num, CDT_output_type otype, bool need_ids) { constexpr bool print_timing = true; /* @@ -1810,7 +1810,7 @@ void text_test( * * Where the numbers are the first 13 vertices, and the rest of * the vertices are in arcs a0, a1, a2, a3, each of which have - * num_arc_points per arc in them. + * arc_points_num per arc in them. */ const char *b_before_arcs = R"(13 0 3 @@ -1834,13 +1834,13 @@ void text_test( CDT_input<T> b_before_arcs_in = fill_input_from_string<T>(b_before_arcs); constexpr int narcs = 4; - int b_npts = b_before_arcs_in.vert.size() + narcs * num_arc_points; + int b_npts = b_before_arcs_in.vert.size() + narcs * arc_points_num; constexpr int b_nfaces = 3; Array<vec2<T>> b_vert(b_npts); Array<Vector<int>> b_face(b_nfaces); std::copy(b_before_arcs_in.vert.begin(), b_before_arcs_in.vert.end(), b_vert.begin()); std::copy(b_before_arcs_in.face.begin(), b_before_arcs_in.face.end(), b_face.begin()); - if (num_arc_points > 0) { + if (arc_points_num > 0) { b_face[0].pop_last(); /* We'll add center point back between arcs for outer face. */ for (int arc = 0; arc < narcs; ++arc) { int arc_origin_vert; @@ -1875,10 +1875,10 @@ void text_test( vec2<T> center_co = 0.5 * (start_co + end_co); BLI_assert(start_co[0] == end_co[0]); double radius = abs(math_to_double<T>(end_co[1] - center_co[1])); - double angle_delta = M_PI / (num_arc_points + 1); - int start_vert = b_before_arcs_in.vert.size() + arc * num_arc_points; + double angle_delta = M_PI / (arc_points_num + 1); + int start_vert = b_before_arcs_in.vert.size() + arc * arc_points_num; Vector<int> &face = b_face[(arc <= 1) ? 0 : arc - 1]; - for (int i = 0; i < num_arc_points; ++i) { + for (int i = 0; i < arc_points_num; ++i) { vec2<T> delta; float ang = ccw ? (-M_PI_2 + (i + 1) * angle_delta) : (M_PI_2 - (i + 1) * angle_delta); delta[0] = T(radius * cos(ang)); @@ -1893,7 +1893,7 @@ void text_test( } CDT_input<T> in; - int tot_instances = num_lets_per_line * num_lines; + int tot_instances = lets_per_line_num * lines_num; if (tot_instances == 1) { in.vert = b_vert; in.face = b_face; @@ -1906,8 +1906,8 @@ void text_test( T delta_x = T(2); T delta_y = T(3.25); int instance = 0; - for (int line = 0; line < num_lines; ++line) { - for (int let = 0; let < num_lets_per_line; ++let) { + for (int line = 0; line < lines_num; ++line) { + for (int let = 0; let < lets_per_line_num; ++let) { vec2<T> co_offset(cur_x, cur_y); int in_v_offset = instance * b_vert.size(); for (int v = 0; v < b_vert.size(); ++v) { @@ -1940,12 +1940,12 @@ void text_test( EXPECT_EQ(out.face_orig.size(), 0); } if (DO_DRAW) { - std::string label = "Text arcpts=" + std::to_string(num_arc_points); - if (num_lets_per_line > 1) { - label += " linelen=" + std::to_string(num_lets_per_line); + std::string label = "Text arcpts=" + std::to_string(arc_points_num); + if (lets_per_line_num > 1) { + label += " linelen=" + std::to_string(lets_per_line_num); } - if (num_lines > 1) { - label += " lines=" + std::to_string(num_lines); + if (lines_num > 1) { + label += " lines=" + std::to_string(lines_num); } if (!need_ids) { label += " no_ids"; diff --git a/source/blender/blenlib/tests/BLI_length_parameterize_test.cc b/source/blender/blenlib/tests/BLI_length_parameterize_test.cc new file mode 100644 index 00000000000..4a8b7095888 --- /dev/null +++ b/source/blender/blenlib/tests/BLI_length_parameterize_test.cc @@ -0,0 +1,202 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "BLI_array.hh" +#include "BLI_length_parameterize.hh" +#include "BLI_vector.hh" + +#include "testing/testing.h" + +namespace blender::length_parameterize::tests { + +template<typename T> Array<float> calculate_lengths(const Span<T> values, const bool cyclic) +{ + Array<float> lengths(lengths_num(values.size(), cyclic)); + accumulate_lengths<T>(values, cyclic, lengths); + return lengths; +} + +template<typename T> void test_uniform_lengths(const Span<T> values) +{ + const float segment_length = math::distance(values.first(), values.last()) / (values.size() - 1); + for (const int i : values.index_range().drop_back(1)) { + EXPECT_NEAR(math::distance(values[i], values[i + 1]), segment_length, 1e-5); + } +} + +TEST(length_parameterize, FloatSimple) +{ + Array<float> values{{0, 1, 4}}; + Array<float> lengths = calculate_lengths(values.as_span(), false); + + Array<int> indices(4); + Array<float> factors(4); + create_uniform_samples(lengths, false, indices, factors); + Array<float> results(4); + linear_interpolation<float>(values, indices, factors, results); + Array<float> expected({ + 0.0f, + 1.33333f, + 2.66667f, + 4.0f, + }); + for (const int i : results.index_range()) { + EXPECT_NEAR(results[i], expected[i], 1e-5); + } + test_uniform_lengths(results.as_span()); +} + +TEST(length_parameterize, Float) +{ + Array<float> values{{1, 2, 3, 5, 10}}; + Array<float> lengths = calculate_lengths(values.as_span(), false); + + Array<int> indices(20); + Array<float> factors(20); + create_uniform_samples(lengths, false, indices, factors); + Array<float> results(20); + linear_interpolation<float>(values, indices, factors, results); + Array<float> expected({ + 1.0f, 1.47368f, 1.94737f, 2.42105f, 2.89474f, 3.36842f, 3.84211f, + 4.31579f, 4.78947f, 5.26316f, 5.73684f, 6.21053f, 6.68421f, 7.1579f, + 7.63158f, 8.10526f, 8.57895f, 9.05263f, 9.52632f, 10.0f, + }); + for (const int i : results.index_range()) { + EXPECT_NEAR(results[i], expected[i], 1e-5); + } + test_uniform_lengths(results.as_span()); +} + +TEST(length_parameterize, Float2) +{ + Array<float2> values{{{0, 0}, {1, 0}, {1, 1}, {0, 1}}}; + Array<float> lengths = calculate_lengths(values.as_span(), false); + + Array<int> indices(12); + Array<float> factors(12); + create_uniform_samples(lengths, false, indices, factors); + Array<float2> results(12); + linear_interpolation<float2>(values, indices, factors, results); + Array<float2> expected({ + {0.0f, 0.0f}, + {0.272727f, 0.0f}, + {0.545455f, 0.0f}, + {0.818182f, 0.0f}, + {1.0f, 0.0909091f}, + {1.0f, 0.363636f}, + {1.0f, 0.636364f}, + {1.0f, 0.909091f}, + {0.818182f, 1.0f}, + {0.545455f, 1.0f}, + {0.272727f, 1.0f}, + {0.0f, 1.0f}, + }); + for (const int i : results.index_range()) { + EXPECT_NEAR(results[i].x, expected[i].x, 1e-5); + EXPECT_NEAR(results[i].y, expected[i].y, 1e-5); + } +} + +TEST(length_parameterize, Float2Cyclic) +{ + Array<float2> values{{{0, 0}, {1, 0}, {1, 1}, {0, 1}}}; + Array<float> lengths = calculate_lengths(values.as_span(), true); + + Array<int> indices(12); + Array<float> factors(12); + create_uniform_samples(lengths, true, indices, factors); + Array<float2> results(12); + linear_interpolation<float2>(values, indices, factors, results); + Array<float2> expected({ + {0.0f, 0.0f}, + {0.333333f, 0.0f}, + {0.666667f, 0.0f}, + {1.0f, 0.0f}, + {1.0f, 0.333333f}, + {1.0f, 0.666667f}, + {1.0f, 1.0f}, + {0.666667f, 1.0f}, + {0.333333f, 1.0f}, + {0.0f, 1.0f}, + {0.0f, 0.666667f}, + {0.0f, 0.333333f}, + }); + for (const int i : results.index_range()) { + EXPECT_NEAR(results[i].x, expected[i].x, 1e-5); + EXPECT_NEAR(results[i].y, expected[i].y, 1e-5); + } +} + +TEST(length_parameterize, LineMany) +{ + Array<float> values{{1, 2}}; + Array<float> lengths = calculate_lengths(values.as_span(), false); + + Array<int> indices(5007); + Array<float> factors(5007); + create_uniform_samples(lengths, false, indices, factors); + Array<float> results(5007); + linear_interpolation<float>(values, indices, factors, results); + Array<float> expected({ + 1.9962f, 1.9964f, 1.9966f, 1.9968f, 1.997f, 1.9972f, 1.9974f, 1.9976f, 1.9978f, 1.998f, + 1.9982f, 1.9984f, 1.9986f, 1.9988f, 1.999f, 1.9992f, 1.9994f, 1.9996f, 1.9998f, 2.0f, + }); + for (const int i : expected.index_range()) { + EXPECT_NEAR(results.as_span().take_back(20)[i], expected[i], 1e-5); + } +} + +TEST(length_parameterize, CyclicMany) +{ + Array<float2> values{{{0, 0}, {1, 0}, {1, 1}, {0, 1}}}; + Array<float> lengths = calculate_lengths(values.as_span(), true); + + Array<int> indices(5007); + Array<float> factors(5007); + create_uniform_samples(lengths, true, indices, factors); + Array<float2> results(5007); + linear_interpolation<float2>(values, indices, factors, results); + Array<float2> expected({ + {0, 0.0159776}, {0, 0.0151787}, {0, 0.0143797}, {0, 0.013581}, {0, 0.0127821}, + {0, 0.0119832}, {0, 0.0111842}, {0, 0.0103855}, {0, 0.00958657}, {0, 0.00878763}, + {0, 0.00798869}, {0, 0.00718999}, {0, 0.00639105}, {0, 0.00559211}, {0, 0.00479317}, + {0, 0.00399446}, {0, 0.00319552}, {0, 0.00239658}, {0, 0.00159764}, {0, 0.000798941}, + }); + for (const int i : expected.index_range()) { + EXPECT_NEAR(results.as_span().take_back(20)[i].x, expected[i].x, 1e-5); + EXPECT_NEAR(results.as_span().take_back(20)[i].y, expected[i].y, 1e-5); + } +} + +TEST(length_parameterize, InterpolateColor) +{ + Array<float2> values{{{0, 0}, {1, 0}, {1, 1}, {0, 1}}}; + Array<float> lengths = calculate_lengths(values.as_span(), true); + + Array<ColorGeometry4f> colors{{{0, 0, 0, 1}, {1, 0, 0, 1}, {1, 1, 0, 1}, {0, 1, 0, 1}}}; + + Array<int> indices(10); + Array<float> factors(10); + create_uniform_samples(lengths, true, indices, factors); + Array<ColorGeometry4f> results(10); + linear_interpolation<ColorGeometry4f>(colors, indices, factors, results); + Array<ColorGeometry4f> expected({ + {0, 0, 0, 1}, + {0.4, 0, 0, 1}, + {0.8, 0, 0, 1}, + {1, 0.2, 0, 1}, + {1, 0.6, 0, 1}, + {1, 1, 0, 1}, + {0.6, 1, 0, 1}, + {0.2, 1, 0, 1}, + {0, 0.8, 0, 1}, + {0, 0.4, 0, 1}, + }); + for (const int i : results.index_range()) { + EXPECT_NEAR(results[i].r, expected[i].r, 1e-6); + EXPECT_NEAR(results[i].g, expected[i].g, 1e-6); + EXPECT_NEAR(results[i].b, expected[i].b, 1e-6); + EXPECT_NEAR(results[i].a, expected[i].a, 1e-6); + } +} + +} // namespace blender::length_parameterize::tests diff --git a/source/blender/blenlib/tests/BLI_linklist_lockfree_test.cc b/source/blender/blenlib/tests/BLI_linklist_lockfree_test.cc index 561ebefb8d2..0c2b4ee52cc 100644 --- a/source/blender/blenlib/tests/BLI_linklist_lockfree_test.cc +++ b/source/blender/blenlib/tests/BLI_linklist_lockfree_test.cc @@ -32,9 +32,9 @@ TEST(LockfreeLinkList, InsertSingle) TEST(LockfreeLinkList, InsertMultiple) { - static const int num_nodes = 128; + static const int nodes_num = 128; LockfreeLinkList list; - LockfreeLinkNode nodes[num_nodes]; + LockfreeLinkNode nodes[nodes_num]; BLI_linklist_lockfree_init(&list); /* Insert all the nodes. */ for (LockfreeLinkNode &node : nodes) { @@ -42,13 +42,13 @@ TEST(LockfreeLinkList, InsertMultiple) } /* Check head and tail. */ EXPECT_EQ(list.head, &list.dummy_node); - EXPECT_EQ(list.tail, &nodes[num_nodes - 1]); + EXPECT_EQ(list.tail, &nodes[nodes_num - 1]); /* Check rest of the nodes. */ int node_index = 0; for (LockfreeLinkNode *node = BLI_linklist_lockfree_begin(&list); node != nullptr; node = node->next, ++node_index) { EXPECT_EQ(node, &nodes[node_index]); - if (node_index != num_nodes - 1) { + if (node_index != nodes_num - 1) { EXPECT_EQ(node->next, &nodes[node_index + 1]); } } @@ -76,32 +76,32 @@ void concurrent_insert(TaskPool *__restrict pool, void *taskdata) TEST(LockfreeLinkList, InsertMultipleConcurrent) { - static const int num_nodes = 655360; + static const int nodes_num = 655360; /* Initialize list. */ LockfreeLinkList list; BLI_linklist_lockfree_init(&list); /* Initialize task scheduler and pool. */ TaskPool *pool = BLI_task_pool_create_suspended(&list, TASK_PRIORITY_HIGH); /* Push tasks to the pool. */ - for (int i = 0; i < num_nodes; ++i) { + for (int i = 0; i < nodes_num; ++i) { BLI_task_pool_push(pool, concurrent_insert, POINTER_FROM_INT(i), false, nullptr); } /* Run all the tasks. */ BLI_task_pool_work_and_wait(pool); /* Verify we've got all the data properly inserted. */ EXPECT_EQ(list.head, &list.dummy_node); - bool *visited_nodes = (bool *)MEM_callocN(sizeof(bool) * num_nodes, "visited nodes"); + bool *visited_nodes = (bool *)MEM_callocN(sizeof(bool) * nodes_num, "visited nodes"); /* First, we make sure that none of the nodes are added twice. */ for (LockfreeLinkNode *node_v = BLI_linklist_lockfree_begin(&list); node_v != nullptr; node_v = node_v->next) { IndexedNode *node = (IndexedNode *)node_v; EXPECT_GE(node->index, 0); - EXPECT_LT(node->index, num_nodes); + EXPECT_LT(node->index, nodes_num); EXPECT_FALSE(visited_nodes[node->index]); visited_nodes[node->index] = true; } /* Then we make sure node was added. */ - for (int node_index = 0; node_index < num_nodes; ++node_index) { + for (int node_index = 0; node_index < nodes_num; ++node_index) { EXPECT_TRUE(visited_nodes[node_index]); } MEM_freeN(visited_nodes); diff --git a/source/blender/blenlib/tests/BLI_listbase_test.cc b/source/blender/blenlib/tests/BLI_listbase_test.cc index f19b536a829..aa2f885e39d 100644 --- a/source/blender/blenlib/tests/BLI_listbase_test.cc +++ b/source/blender/blenlib/tests/BLI_listbase_test.cc @@ -215,13 +215,13 @@ static int testsort_listbase_str_cmp_reverse(const void *a, const void *b) } /* check array and listbase compare */ -static bool testsort_listbase_array_str_cmp(ListBase *lb, char **arr, int arr_tot) +static bool testsort_listbase_array_str_cmp(ListBase *lb, char **arr, int arr_num) { LinkData *link_step; int i; link_step = (LinkData *)lb->first; - for (i = 0; i < arr_tot; i++) { + for (i = 0; i < arr_num; i++) { if (strcmp(arr[i], (char *)link_step->data) != 0) { return false; } @@ -255,7 +255,7 @@ TEST(listbase, Sort) { const int words_len = sizeof(words10k) - 1; char *words = BLI_strdupn(words10k, words_len); - int words_tot; + int words_num; char **words_arr; /* qsort for comparison */ int i; char *w_step; @@ -263,15 +263,15 @@ TEST(listbase, Sort) LinkData *words_linkdata_arr; /* delimit words */ - words_tot = 1 + char_switch(words, ' ', '\0'); + words_num = 1 + char_switch(words, ' ', '\0'); - words_arr = (char **)MEM_mallocN(sizeof(*words_arr) * words_tot, __func__); + words_arr = (char **)MEM_mallocN(sizeof(*words_arr) * words_num, __func__); - words_linkdata_arr = (LinkData *)MEM_mallocN(sizeof(*words_linkdata_arr) * words_tot, __func__); + words_linkdata_arr = (LinkData *)MEM_mallocN(sizeof(*words_linkdata_arr) * words_num, __func__); /* create array */ w_step = words; - for (i = 0; i < words_tot; i++) { + for (i = 0; i < words_num; i++) { words_arr[i] = w_step; w_step += strlen(w_step) + 1; } @@ -296,7 +296,7 @@ TEST(listbase, Sort) /* create listbase */ BLI_listbase_clear(&words_lb); w_step = words; - for (i = 0; i < words_tot; i++) { + for (i = 0; i < words_num; i++) { LinkData *link = &words_linkdata_arr[i]; link->data = w_step; BLI_addtail(&words_lb, link); @@ -306,37 +306,37 @@ TEST(listbase, Sort) /* sort (forward) */ { - qsort(words_arr, words_tot, sizeof(*words_arr), testsort_array_str_cmp); + qsort(words_arr, words_num, sizeof(*words_arr), testsort_array_str_cmp); BLI_listbase_sort(&words_lb, testsort_listbase_str_cmp); EXPECT_TRUE(listbase_is_valid(&words_lb)); - EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_tot)); + EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_num)); EXPECT_TRUE(testsort_listbase_sort_is_stable(&words_lb, true)); } /* sort (reverse) */ { - qsort(words_arr, words_tot, sizeof(*words_arr), testsort_array_str_cmp_reverse); + qsort(words_arr, words_num, sizeof(*words_arr), testsort_array_str_cmp_reverse); BLI_listbase_sort(&words_lb, testsort_listbase_str_cmp_reverse); EXPECT_TRUE(listbase_is_valid(&words_lb)); - EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_tot)); + EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_num)); EXPECT_TRUE(testsort_listbase_sort_is_stable(&words_lb, true)); } /* sort (forward but after reversing, test stability in alternate direction) */ { - BLI_array_reverse(words_arr, words_tot); + BLI_array_reverse(words_arr, words_num); BLI_listbase_reverse(&words_lb); EXPECT_TRUE(listbase_is_valid(&words_lb)); - EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_tot)); + EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_num)); EXPECT_TRUE(testsort_listbase_sort_is_stable(&words_lb, false)); /* and again */ - BLI_array_reverse(words_arr, words_tot); + BLI_array_reverse(words_arr, words_num); BLI_listbase_sort(&words_lb, testsort_listbase_str_cmp_reverse); - EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_tot)); + EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_num)); EXPECT_TRUE(testsort_listbase_sort_is_stable(&words_lb, false)); } diff --git a/source/blender/blenlib/tests/BLI_memiter_test.cc b/source/blender/blenlib/tests/BLI_memiter_test.cc index 17b26d115c4..eb88a8615f8 100644 --- a/source/blender/blenlib/tests/BLI_memiter_test.cc +++ b/source/blender/blenlib/tests/BLI_memiter_test.cc @@ -16,11 +16,11 @@ TEST(memiter, Nop) BLI_memiter_destroy(mi); } -static void memiter_empty_test(int num_elems, const int chunk_size) +static void memiter_empty_test(int elems_num, const int chunk_size) { BLI_memiter *mi = BLI_memiter_create(chunk_size); void *data; - for (int index = 0; index < num_elems; index++) { + for (int index = 0; index < elems_num; index++) { data = BLI_memiter_alloc(mi, 0); } int index = 0, total_size = 0; @@ -32,17 +32,17 @@ static void memiter_empty_test(int num_elems, const int chunk_size) total_size += elem_size; } EXPECT_EQ(0, total_size); - EXPECT_EQ(num_elems, index); + EXPECT_EQ(elems_num, index); BLI_memiter_destroy(mi); } #define MEMITER_NUMBER_TEST_FN(fn, number_type) \ - static void fn(int num_elems, const int chunk_size) \ + static void fn(int elems_num, const int chunk_size) \ { \ BLI_memiter *mi = BLI_memiter_create(chunk_size); \ number_type *data; \ - for (int index = 0; index < num_elems; index++) { \ + for (int index = 0; index < elems_num; index++) { \ data = (number_type *)BLI_memiter_alloc(mi, sizeof(number_type)); \ *data = index; \ } \ diff --git a/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc b/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc index d6a7a338d13..c155068b94a 100644 --- a/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc +++ b/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc @@ -811,14 +811,14 @@ TEST(mesh_intersect, RectCross) # if DO_PERF_TESTS static void get_sphere_params( - int nrings, int nsegs, bool triangulate, int *r_num_verts, int *r_num_faces) + int nrings, int nsegs, bool triangulate, int *r_verts_num, int *r_faces_num) { - *r_num_verts = nsegs * (nrings - 1) + 2; + *r_verts_num = nsegs * (nrings - 1) + 2; if (triangulate) { - *r_num_faces = 2 * nsegs + 2 * nsegs * (nrings - 2); + *r_faces_num = 2 * nsegs + 2 * nsegs * (nrings - 2); } else { - *r_num_faces = nsegs * nrings; + *r_faces_num = nsegs * nrings; } } @@ -832,11 +832,11 @@ static void fill_sphere_data(int nrings, int fid_start, IMeshArena *arena) { - int num_verts; - int num_faces; - get_sphere_params(nrings, nsegs, triangulate, &num_verts, &num_faces); - BLI_assert(num_faces == face.size()); - Array<const Vert *> vert(num_verts); + int verts_num; + int faces_num; + get_sphere_params(nrings, nsegs, triangulate, &verts_num, &faces_num); + BLI_assert(faces_num == face.size()); + Array<const Vert *> vert(verts_num); const bool nrings_even = (nrings % 2 == 0); int half_nrings = nrings / 2; const bool nsegs_even = (nsegs % 2) == 0; @@ -847,12 +847,12 @@ static void fill_sphere_data(int nrings, double delta_theta = M_PI / nrings; int fid = fid_start; int vid = vid_start; - auto vert_index_fn = [nrings, num_verts](int seg, int ring) { + auto vert_index_fn = [nrings, verts_num](int seg, int ring) { if (ring == 0) { /* Top vert. */ - return num_verts - 2; + return verts_num - 2; } if (ring == nrings) { /* Bottom vert. */ - return num_verts - 1; + return verts_num - 1; } return seg * (nrings - 1) + (ring - 1); }; @@ -980,18 +980,18 @@ static void spheresphere_test(int nrings, double y_offset, bool use_self) double time_start = PIL_check_seconds_timer(); IMeshArena arena; int nsegs = 2 * nrings; - int num_sphere_verts; - int num_sphere_tris; - get_sphere_params(nrings, nsegs, true, &num_sphere_verts, &num_sphere_tris); - Array<Face *> tris(2 * num_sphere_tris); - arena.reserve(6 * num_sphere_verts / 2, 8 * num_sphere_tris); + int sphere_verts_num; + int sphere_tris_num; + get_sphere_params(nrings, nsegs, true, &sphere_verts_num, &sphere_tris_num); + Array<Face *> tris(2 * sphere_tris_num); + arena.reserve(6 * sphere_verts_num / 2, 8 * sphere_tris_num); double3 center1(0.0, 0.0, 0.0); fill_sphere_data(nrings, nsegs, center1, 1.0, true, - MutableSpan<Face *>(tris.begin(), num_sphere_tris), + MutableSpan<Face *>(tris.begin(), sphere_tris_num), 0, 0, &arena); @@ -1001,9 +1001,9 @@ static void spheresphere_test(int nrings, double y_offset, bool use_self) center2, 1.0, true, - MutableSpan<Face *>(tris.begin() + num_sphere_tris, num_sphere_tris), - num_sphere_verts, - num_sphere_verts, + MutableSpan<Face *>(tris.begin() + sphere_tris_num, sphere_tris_num), + sphere_verts_num, + sphere_verts_num, &arena); IMesh mesh(tris); double time_create = PIL_check_seconds_timer(); @@ -1013,7 +1013,7 @@ static void spheresphere_test(int nrings, double y_offset, bool use_self) out = trimesh_self_intersect(mesh, &arena); } else { - int nf = num_sphere_tris; + int nf = sphere_tris_num; out = trimesh_nary_intersect( mesh, 2, [nf](int t) { return t < nf ? 0 : 1; }, false, &arena); } @@ -1028,14 +1028,14 @@ static void spheresphere_test(int nrings, double y_offset, bool use_self) } static void get_grid_params( - int x_subdiv, int y_subdiv, bool triangulate, int *r_num_verts, int *r_num_faces) + int x_subdiv, int y_subdiv, bool triangulate, int *r_verts_num, int *r_faces_num) { - *r_num_verts = x_subdiv * y_subdiv; + *r_verts_num = x_subdiv * y_subdiv; if (triangulate) { - *r_num_faces = 2 * (x_subdiv - 1) * (y_subdiv - 1); + *r_faces_num = 2 * (x_subdiv - 1) * (y_subdiv - 1); } else { - *r_num_faces = (x_subdiv - 1) * (y_subdiv - 1); + *r_faces_num = (x_subdiv - 1) * (y_subdiv - 1); } } @@ -1053,11 +1053,11 @@ static void fill_grid_data(int x_subdiv, if (x_subdiv <= 1 || y_subdiv <= 1) { return; } - int num_verts; - int num_faces; - get_grid_params(x_subdiv, y_subdiv, triangulate, &num_verts, &num_faces); - BLI_assert(face.size() == num_faces); - Array<const Vert *> vert(num_verts); + int verts_num; + int faces_num; + get_grid_params(x_subdiv, y_subdiv, triangulate, &verts_num, &faces_num); + BLI_assert(face.size() == faces_num); + Array<const Vert *> vert(verts_num); auto vert_index_fn = [x_subdiv](int ix, int iy) { return iy * x_subdiv + ix; }; auto face_index_fn = [x_subdiv](int ix, int iy) { return iy * (x_subdiv - 1) + ix; }; auto tri_index_fn = [x_subdiv](int ix, int iy, int tri) { @@ -1119,24 +1119,24 @@ static void spheregrid_test(int nrings, int grid_level, double z_offset, bool us BLI_task_scheduler_init(); /* Without this, no parallelism. */ double time_start = PIL_check_seconds_timer(); IMeshArena arena; - int num_sphere_verts; - int num_sphere_tris; + int sphere_verts_num; + int sphere_tris_num; int nsegs = 2 * nrings; - int num_grid_verts; - int num_grid_tris; + int grid_verts_num; + int grid_tris_num; int subdivs = 1 << grid_level; - get_sphere_params(nrings, nsegs, true, &num_sphere_verts, &num_sphere_tris); - get_grid_params(subdivs, subdivs, true, &num_grid_verts, &num_grid_tris); - Array<Face *> tris(num_sphere_tris + num_grid_tris); - arena.reserve(3 * (num_sphere_verts + num_grid_verts) / 2, - 4 * (num_sphere_tris + num_grid_tris)); + get_sphere_params(nrings, nsegs, true, &sphere_verts_num, &sphere_tris_num); + get_grid_params(subdivs, subdivs, true, &grid_verts_num, &grid_tris_num); + Array<Face *> tris(sphere_tris_num + grid_tris_num); + arena.reserve(3 * (sphere_verts_num + grid_verts_num) / 2, + 4 * (sphere_tris_num + grid_tris_num)); double3 center(0.0, 0.0, z_offset); fill_sphere_data(nrings, nsegs, center, 1.0, true, - MutableSpan<Face *>(tris.begin(), num_sphere_tris), + MutableSpan<Face *>(tris.begin(), sphere_tris_num), 0, 0, &arena); @@ -1146,9 +1146,9 @@ static void spheregrid_test(int nrings, int grid_level, double z_offset, bool us 4.0, double3(0, 0, 0), 0.0, - MutableSpan<Face *>(tris.begin() + num_sphere_tris, num_grid_tris), - num_sphere_verts, - num_sphere_tris, + MutableSpan<Face *>(tris.begin() + sphere_tris_num, grid_tris_num), + sphere_verts_num, + sphere_tris_num, &arena); IMesh mesh(tris); double time_create = PIL_check_seconds_timer(); @@ -1158,7 +1158,7 @@ static void spheregrid_test(int nrings, int grid_level, double z_offset, bool us out = trimesh_self_intersect(mesh, &arena); } else { - int nf = num_sphere_tris; + int nf = sphere_tris_num; out = trimesh_nary_intersect( mesh, 2, [nf](int t) { return t < nf ? 0 : 1; }, false, &arena); } @@ -1190,22 +1190,22 @@ static void gridgrid_test(int x_level_1, int y_subdivs_1 = 1 << y_level_1; int x_subdivs_2 = 1 << x_level_2; int y_subdivs_2 = 1 << y_level_2; - int num_grid_verts_1; - int num_grid_verts_2; - int num_grid_tris_1; - int num_grid_tris_2; - get_grid_params(x_subdivs_1, y_subdivs_1, true, &num_grid_verts_1, &num_grid_tris_1); - get_grid_params(x_subdivs_2, y_subdivs_2, true, &num_grid_verts_2, &num_grid_tris_2); - Array<Face *> tris(num_grid_tris_1 + num_grid_tris_2); - arena.reserve(3 * (num_grid_verts_1 + num_grid_verts_2) / 2, - 4 * (num_grid_tris_1 + num_grid_tris_2)); + int grid_verts_1_num; + int grid_verts_2_num; + int grid_tris_1_num; + int grid_tris_2_num; + get_grid_params(x_subdivs_1, y_subdivs_1, true, &grid_verts_1_num, &grid_tris_1_num); + get_grid_params(x_subdivs_2, y_subdivs_2, true, &grid_verts_2_num, &grid_tris_2_num); + Array<Face *> tris(grid_tris_1_num + grid_tris_2_num); + arena.reserve(3 * (grid_verts_1_num + grid_verts_2_num) / 2, + 4 * (grid_tris_1_num + grid_tris_2_num)); fill_grid_data(x_subdivs_1, y_subdivs_1, true, 4.0, double3(0, 0, 0), 0.0, - MutableSpan<Face *>(tris.begin(), num_grid_tris_1), + MutableSpan<Face *>(tris.begin(), grid_tris_1_num), 0, 0, &arena); @@ -1215,9 +1215,9 @@ static void gridgrid_test(int x_level_1, 4.0, double3(x_off, y_off, 0), rot_deg, - MutableSpan<Face *>(tris.begin() + num_grid_tris_1, num_grid_tris_2), - num_grid_verts_1, - num_grid_tris_1, + MutableSpan<Face *>(tris.begin() + grid_tris_1_num, grid_tris_2_num), + grid_verts_1_num, + grid_tris_1_num, &arena); IMesh mesh(tris); double time_create = PIL_check_seconds_timer(); @@ -1227,7 +1227,7 @@ static void gridgrid_test(int x_level_1, out = trimesh_self_intersect(mesh, &arena); } else { - int nf = num_grid_tris_1; + int nf = grid_tris_1_num; out = trimesh_nary_intersect( mesh, 2, [nf](int t) { return t < nf ? 0 : 1; }, false, &arena); } diff --git a/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc b/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc index 3efa35a0048..db2fb1ba671 100644 --- a/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc +++ b/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc @@ -29,19 +29,19 @@ static void polyfill_to_obj(const char *id, const float poly[][2], - const unsigned int poly_tot, + const unsigned int poly_num, const unsigned int tris[][3], - const unsigned int tris_tot); + const unsigned int tris_num); /* -------------------------------------------------------------------- */ /* test utility functions */ #define TRI_ERROR_VALUE (unsigned int)-1 -static void test_valid_polyfill_prepare(unsigned int tris[][3], unsigned int tris_tot) +static void test_valid_polyfill_prepare(unsigned int tris[][3], unsigned int tris_num) { unsigned int i; - for (i = 0; i < tris_tot; i++) { + for (i = 0; i < tris_num; i++) { unsigned int j; for (j = 0; j < 3; j++) { tris[i][j] = TRI_ERROR_VALUE; @@ -57,37 +57,37 @@ static void test_valid_polyfill_prepare(unsigned int tris[][3], unsigned int tri * - all verts used at least once. */ static void test_polyfill_simple(const float /*poly*/[][2], - const unsigned int poly_tot, + const unsigned int poly_num, const unsigned int tris[][3], - const unsigned int tris_tot) + const unsigned int tris_num) { unsigned int i; - int *tot_used = (int *)MEM_callocN(poly_tot * sizeof(int), __func__); - for (i = 0; i < tris_tot; i++) { + int *used_num = (int *)MEM_callocN(poly_num * sizeof(int), __func__); + for (i = 0; i < tris_num; i++) { unsigned int j; for (j = 0; j < 3; j++) { EXPECT_NE(TRI_ERROR_VALUE, tris[i][j]); - tot_used[tris[i][j]] += 1; + used_num[tris[i][j]] += 1; } EXPECT_NE(tris[i][0], tris[i][1]); EXPECT_NE(tris[i][1], tris[i][2]); EXPECT_NE(tris[i][2], tris[i][0]); } - for (i = 0; i < poly_tot; i++) { - EXPECT_NE(0, tot_used[i]); + for (i = 0; i < poly_num; i++) { + EXPECT_NE(0, used_num[i]); } - MEM_freeN(tot_used); + MEM_freeN(used_num); } static void test_polyfill_topology(const float /*poly*/[][2], - const unsigned int poly_tot, + const unsigned int poly_num, const unsigned int tris[][3], - const unsigned int tris_tot) + const unsigned int tris_num) { EdgeHash *edgehash = BLI_edgehash_new(__func__); EdgeHashIterator *ehi; unsigned int i; - for (i = 0; i < tris_tot; i++) { + for (i = 0; i < tris_num; i++) { unsigned int j; for (j = 0; j < 3; j++) { const unsigned int v1 = tris[i][j]; @@ -101,11 +101,11 @@ static void test_polyfill_topology(const float /*poly*/[][2], } } } - EXPECT_EQ(BLI_edgehash_len(edgehash), poly_tot + (poly_tot - 3)); + EXPECT_EQ(BLI_edgehash_len(edgehash), poly_num + (poly_num - 3)); - for (i = 0; i < poly_tot; i++) { + for (i = 0; i < poly_num; i++) { const unsigned int v1 = i; - const unsigned int v2 = (i + 1) % poly_tot; + const unsigned int v2 = (i + 1) % poly_num; void **p = BLI_edgehash_lookup_p(edgehash, v1, v2); EXPECT_NE((void *)p, nullptr); EXPECT_EQ((intptr_t)*p, 1); @@ -125,13 +125,13 @@ static void test_polyfill_topology(const float /*poly*/[][2], * Check all faces are flipped the same way */ static void test_polyfill_winding(const float poly[][2], - const unsigned int /*poly_tot*/, + const unsigned int /*poly_num*/, const unsigned int tris[][3], - const unsigned int tris_tot) + const unsigned int tris_num) { unsigned int i; unsigned int count[2] = {0, 0}; - for (i = 0; i < tris_tot; i++) { + for (i = 0; i < tris_num; i++) { float winding_test = cross_tri_v2(poly[tris[i][0]], poly[tris[i][1]], poly[tris[i][2]]); if (fabsf(winding_test) > FLT_EPSILON) { count[winding_test < 0.0f] += 1; @@ -144,19 +144,19 @@ static void test_polyfill_winding(const float poly[][2], * Check the accumulated triangle area is close to the original area. */ static void test_polyfill_area(const float poly[][2], - const unsigned int poly_tot, + const unsigned int poly_num, const unsigned int tris[][3], - const unsigned int tris_tot) + const unsigned int tris_num) { unsigned int i; - const float area_tot = area_poly_v2(poly, poly_tot); - float area_tot_tris = 0.0f; + const float area_total = area_poly_v2(poly, poly_num); + float area_total_tris = 0.0f; const float eps_abs = 0.00001f; - const float eps = area_tot > 1.0f ? (area_tot * eps_abs) : eps_abs; - for (i = 0; i < tris_tot; i++) { - area_tot_tris += area_tri_v2(poly[tris[i][0]], poly[tris[i][1]], poly[tris[i][2]]); + const float eps = area_total > 1.0f ? (area_total * eps_abs) : eps_abs; + for (i = 0; i < tris_num; i++) { + area_total_tris += area_tri_v2(poly[tris[i][0]], poly[tris[i][1]], poly[tris[i][2]]); } - EXPECT_NEAR(area_tot, area_tot_tris, eps); + EXPECT_NEAR(area_total, area_total_tris, eps); } /* -------------------------------------------------------------------- */ @@ -167,32 +167,32 @@ static void test_polyfill_area(const float poly[][2], static void test_polyfill_template_check(const char *id, bool is_degenerate, const float poly[][2], - const unsigned int poly_tot, + const unsigned int poly_num, const unsigned int tris[][3], - const unsigned int tris_tot) + const unsigned int tris_num) { - test_polyfill_simple(poly, poly_tot, tris, tris_tot); - test_polyfill_topology(poly, poly_tot, tris, tris_tot); + test_polyfill_simple(poly, poly_num, tris, tris_num); + test_polyfill_topology(poly, poly_num, tris, tris_num); if (!is_degenerate) { - test_polyfill_winding(poly, poly_tot, tris, tris_tot); + test_polyfill_winding(poly, poly_num, tris, tris_num); - test_polyfill_area(poly, poly_tot, tris, tris_tot); + test_polyfill_area(poly, poly_num, tris, tris_num); } - polyfill_to_obj(id, poly, poly_tot, tris, tris_tot); + polyfill_to_obj(id, poly, poly_num, tris, tris_num); } static void test_polyfill_template(const char *id, bool is_degenerate, const float poly[][2], - const unsigned int poly_tot, + const unsigned int poly_num, unsigned int tris[][3], - const unsigned int tris_tot) + const unsigned int tris_num) { - test_valid_polyfill_prepare(tris, tris_tot); - BLI_polyfill_calc(poly, poly_tot, 0, tris); + test_valid_polyfill_prepare(tris, tris_num); + BLI_polyfill_calc(poly, poly_num, 0, tris); /* check all went well */ - test_polyfill_template_check(id, is_degenerate, poly, poly_tot, tris, tris_tot); + test_polyfill_template_check(id, is_degenerate, poly, poly_num, tris, tris_num); #ifdef USE_BEAUTIFY /* check beautify gives good results too */ @@ -200,9 +200,9 @@ static void test_polyfill_template(const char *id, MemArena *pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__); Heap *pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE); - BLI_polyfill_beautify(poly, poly_tot, tris, pf_arena, pf_heap); + BLI_polyfill_beautify(poly, poly_num, tris, pf_arena, pf_heap); - test_polyfill_template_check(id, is_degenerate, poly, poly_tot, tris, tris_tot); + test_polyfill_template_check(id, is_degenerate, poly, poly_num, tris, tris_num); BLI_memarena_free(pf_arena); BLI_heap_free(pf_heap, nullptr); @@ -213,20 +213,20 @@ static void test_polyfill_template(const char *id, static void test_polyfill_template_flip_sign(const char *id, bool is_degenerate, const float poly[][2], - const unsigned int poly_tot, + const unsigned int poly_num, unsigned int tris[][3], - const unsigned int tris_tot) + const unsigned int tris_num) { - float(*poly_copy)[2] = (float(*)[2])MEM_mallocN(sizeof(float[2]) * poly_tot, id); + float(*poly_copy)[2] = (float(*)[2])MEM_mallocN(sizeof(float[2]) * poly_num, id); for (int flip_x = 0; flip_x < 2; flip_x++) { for (int flip_y = 0; flip_y < 2; flip_y++) { float sign_x = flip_x ? -1.0f : 1.0f; float sign_y = flip_y ? -1.0f : 1.0f; - for (int i = 0; i < poly_tot; i++) { + for (int i = 0; i < poly_num; i++) { poly_copy[i][0] = poly[i][0] * sign_x; poly_copy[i][1] = poly[i][1] * sign_y; } - test_polyfill_template(id, is_degenerate, poly_copy, poly_tot, tris, tris_tot); + test_polyfill_template(id, is_degenerate, poly_copy, poly_num, tris, tris_num); } } MEM_freeN(poly_copy); @@ -236,32 +236,32 @@ static void test_polyfill_template_flip_sign(const char *id, static void test_polyfill_template_main(const char *id, bool is_degenerate, const float poly[][2], - const unsigned int poly_tot, + const unsigned int poly_num, unsigned int tris[][3], - const unsigned int tris_tot) + const unsigned int tris_num) { /* overkill? - try at _every_ offset & reverse */ unsigned int poly_reverse; - float(*poly_copy)[2] = (float(*)[2])MEM_mallocN(sizeof(float[2]) * poly_tot, id); + float(*poly_copy)[2] = (float(*)[2])MEM_mallocN(sizeof(float[2]) * poly_num, id); float tmp[2]; - memcpy(poly_copy, poly, sizeof(float[2]) * poly_tot); + memcpy(poly_copy, poly, sizeof(float[2]) * poly_num); for (poly_reverse = 0; poly_reverse < 2; poly_reverse++) { unsigned int poly_cycle; if (poly_reverse) { - BLI_array_reverse(poly_copy, poly_tot); + BLI_array_reverse(poly_copy, poly_num); } - for (poly_cycle = 0; poly_cycle < poly_tot; poly_cycle++) { + for (poly_cycle = 0; poly_cycle < poly_num; poly_cycle++) { // printf("polytest %s ofs=%d, reverse=%d\n", id, poly_cycle, poly_reverse); - test_polyfill_template_flip_sign(id, is_degenerate, poly, poly_tot, tris, tris_tot); + test_polyfill_template_flip_sign(id, is_degenerate, poly, poly_num, tris, tris_num); /* cycle */ copy_v2_v2(tmp, poly_copy[0]); - memmove(&poly_copy[0], &poly_copy[1], (poly_tot - 1) * sizeof(float[2])); - copy_v2_v2(poly_copy[poly_tot - 1], tmp); + memmove(&poly_copy[0], &poly_copy[1], (poly_num - 1) * sizeof(float[2])); + copy_v2_v2(poly_copy[poly_num - 1], tmp); } } @@ -271,22 +271,22 @@ static void test_polyfill_template_main(const char *id, static void test_polyfill_template_main(const char *id, bool is_degenerate, const float poly[][2], - const unsigned int poly_tot, + const unsigned int poly_num, unsigned int tris[][3], - const unsigned int tris_tot) + const unsigned int tris_num) { - test_polyfill_template_flip_sign(id, is_degenerate, poly, poly_tot, tris, tris_tot); + test_polyfill_template_flip_sign(id, is_degenerate, poly, poly_num, tris, tris_num); } #endif /* USE_COMBINATIONS_ALL */ #define TEST_POLYFILL_TEMPLATE_STATIC(poly, is_degenerate) \ { \ unsigned int tris[POLY_TRI_COUNT(ARRAY_SIZE(poly))][3]; \ - const unsigned int poly_tot = ARRAY_SIZE(poly); \ - const unsigned int tris_tot = ARRAY_SIZE(tris); \ + const unsigned int poly_num = ARRAY_SIZE(poly); \ + const unsigned int tris_num = ARRAY_SIZE(tris); \ const char *id = typeid(*this).name(); \ \ - test_polyfill_template_main(id, is_degenerate, poly, poly_tot, tris, tris_tot); \ + test_polyfill_template_main(id, is_degenerate, poly, poly_num, tris, tris_num); \ } \ (void)0 @@ -296,9 +296,9 @@ static void test_polyfill_template_main(const char *id, #ifdef USE_OBJ_PREVIEW static void polyfill_to_obj(const char *id, const float poly[][2], - const unsigned int poly_tot, + const unsigned int poly_num, const unsigned int tris[][3], - const unsigned int tris_tot) + const unsigned int tris_num) { char path[1024]; FILE *f; @@ -311,11 +311,11 @@ static void polyfill_to_obj(const char *id, return; } - for (i = 0; i < poly_tot; i++) { + for (i = 0; i < poly_num; i++) { fprintf(f, "v %f %f 0.0\n", UNPACK2(poly[i])); } - for (i = 0; i < tris_tot; i++) { + for (i = 0; i < tris_num; i++) { fprintf(f, "f %u %u %u\n", UNPACK3_EX(1 +, tris[i], )); } @@ -324,13 +324,13 @@ static void polyfill_to_obj(const char *id, #else static void polyfill_to_obj(const char *id, const float poly[][2], - const unsigned int poly_tot, + const unsigned int poly_num, const unsigned int tris[][3], - const unsigned int tris_tot) + const unsigned int tris_num) { (void)id; - (void)poly, (void)poly_tot; - (void)tris, (void)tris_tot; + (void)poly, (void)poly_num; + (void)tris, (void)tris_num; } #endif /* USE_OBJ_PREVIEW */ diff --git a/source/blender/blenlib/tests/BLI_string_test.cc b/source/blender/blenlib/tests/BLI_string_test.cc index 553bd8453e0..6c16af5767c 100644 --- a/source/blender/blenlib/tests/BLI_string_test.cc +++ b/source/blender/blenlib/tests/BLI_string_test.cc @@ -324,35 +324,35 @@ TEST(string, StrPartitionExUtf8) /* BLI_str_format_int_grouped */ TEST(string, StrFormatIntGrouped) { - char num_str[16]; - int num; + char number_str[16]; + int number; - BLI_str_format_int_grouped(num_str, num = 0); - EXPECT_STREQ("0", num_str); + BLI_str_format_int_grouped(number_str, number = 0); + EXPECT_STREQ("0", number_str); - BLI_str_format_int_grouped(num_str, num = 1); - EXPECT_STREQ("1", num_str); + BLI_str_format_int_grouped(number_str, number = 1); + EXPECT_STREQ("1", number_str); - BLI_str_format_int_grouped(num_str, num = -1); - EXPECT_STREQ("-1", num_str); + BLI_str_format_int_grouped(number_str, number = -1); + EXPECT_STREQ("-1", number_str); - BLI_str_format_int_grouped(num_str, num = -2147483648); - EXPECT_STREQ("-2,147,483,648", num_str); + BLI_str_format_int_grouped(number_str, number = -2147483648); + EXPECT_STREQ("-2,147,483,648", number_str); - BLI_str_format_int_grouped(num_str, num = 2147483647); - EXPECT_STREQ("2,147,483,647", num_str); + BLI_str_format_int_grouped(number_str, number = 2147483647); + EXPECT_STREQ("2,147,483,647", number_str); - BLI_str_format_int_grouped(num_str, num = 1000); - EXPECT_STREQ("1,000", num_str); + BLI_str_format_int_grouped(number_str, number = 1000); + EXPECT_STREQ("1,000", number_str); - BLI_str_format_int_grouped(num_str, num = -1000); - EXPECT_STREQ("-1,000", num_str); + BLI_str_format_int_grouped(number_str, number = -1000); + EXPECT_STREQ("-1,000", number_str); - BLI_str_format_int_grouped(num_str, num = 999); - EXPECT_STREQ("999", num_str); + BLI_str_format_int_grouped(number_str, number = 999); + EXPECT_STREQ("999", number_str); - BLI_str_format_int_grouped(num_str, num = -999); - EXPECT_STREQ("-999", num_str); + BLI_str_format_int_grouped(number_str, number = -999); + EXPECT_STREQ("-999", number_str); } /* BLI_str_format_byte_unit */ diff --git a/source/blender/blenlib/tests/BLI_string_utf8_test.cc b/source/blender/blenlib/tests/BLI_string_utf8_test.cc index a2b8e139510..2da439dad18 100644 --- a/source/blender/blenlib/tests/BLI_string_utf8_test.cc +++ b/source/blender/blenlib/tests/BLI_string_utf8_test.cc @@ -274,15 +274,15 @@ TEST(string, Utf8InvalidBytes) for (int i = 0; utf8_invalid_tests[i][0] != nullptr; i++) { const char *tst = utf8_invalid_tests[i][0]; const char *tst_stripped = utf8_invalid_tests[i][1]; - const int num_errors = (int)utf8_invalid_tests[i][2][0]; + const int errors_num = (int)utf8_invalid_tests[i][2][0]; char buff[80]; memcpy(buff, tst, sizeof(buff)); - const int num_errors_found = BLI_str_utf8_invalid_strip(buff, sizeof(buff) - 1); + const int errors_found_num = BLI_str_utf8_invalid_strip(buff, sizeof(buff) - 1); - printf("[%02d] -> [%02d] \"%s\" -> \"%s\"\n", num_errors, num_errors_found, tst, buff); - EXPECT_EQ(num_errors_found, num_errors); + printf("[%02d] -> [%02d] \"%s\" -> \"%s\"\n", errors_num, errors_found_num, tst, buff); + EXPECT_EQ(errors_found_num, errors_num); EXPECT_STREQ(buff, tst_stripped); } } diff --git a/source/blender/blenlib/tests/BLI_task_test.cc b/source/blender/blenlib/tests/BLI_task_test.cc index 52852873a06..a933d45e7cd 100644 --- a/source/blender/blenlib/tests/BLI_task_test.cc +++ b/source/blender/blenlib/tests/BLI_task_test.cc @@ -15,7 +15,7 @@ #include "BLI_task.h" #include "BLI_task.hh" -#define NUM_ITEMS 10000 +#define ITEMS_NUM 10000 /* *** Parallel iterations over range of integer values. *** */ @@ -34,12 +34,12 @@ static void task_range_iter_reduce_func(const void *__restrict UNUSED(userdata), int *join = (int *)join_v; int *chunk = (int *)userdata_chunk; *join += *chunk; - // printf("%d, %d\n", data[NUM_ITEMS], *((int *)userdata_chunk)); + // printf("%d, %d\n", data[ITEMS_NUM], *((int *)userdata_chunk)); } TEST(task, RangeIter) { - int data[NUM_ITEMS] = {0}; + int data[ITEMS_NUM] = {0}; int sum = 0; BLI_threadapi_init(); @@ -52,13 +52,13 @@ TEST(task, RangeIter) settings.userdata_chunk_size = sizeof(sum); settings.func_reduce = task_range_iter_reduce_func; - BLI_task_parallel_range(0, NUM_ITEMS, data, task_range_iter_func, &settings); + BLI_task_parallel_range(0, ITEMS_NUM, data, task_range_iter_func, &settings); /* Those checks should ensure us all items of the listbase were processed once, and only once * as expected. */ int expected_sum = 0; - for (int i = 0; i < NUM_ITEMS; i++) { + for (int i = 0; i < ITEMS_NUM; i++) { EXPECT_EQ(data[i], i); expected_sum += i; } @@ -84,41 +84,41 @@ static void task_mempool_iter_func(void *userdata, TEST(task, MempoolIter) { - int *data[NUM_ITEMS]; + int *data[ITEMS_NUM]; BLI_threadapi_init(); BLI_mempool *mempool = BLI_mempool_create( - sizeof(*data[0]), NUM_ITEMS, 32, BLI_MEMPOOL_ALLOW_ITER); + sizeof(*data[0]), ITEMS_NUM, 32, BLI_MEMPOOL_ALLOW_ITER); int i; /* 'Randomly' add and remove some items from mempool, to create a non-homogeneous one. */ - int num_items = 0; - for (i = 0; i < NUM_ITEMS; i++) { + int items_num = 0; + for (i = 0; i < ITEMS_NUM; i++) { data[i] = (int *)BLI_mempool_alloc(mempool); *data[i] = i - 1; - num_items++; + items_num++; } - for (i = 0; i < NUM_ITEMS; i += 3) { + for (i = 0; i < ITEMS_NUM; i += 3) { BLI_mempool_free(mempool, data[i]); data[i] = nullptr; - num_items--; + items_num--; } - for (i = 0; i < NUM_ITEMS; i += 7) { + for (i = 0; i < ITEMS_NUM; i += 7) { if (data[i] == nullptr) { data[i] = (int *)BLI_mempool_alloc(mempool); *data[i] = i - 1; - num_items++; + items_num++; } } - for (i = 0; i < NUM_ITEMS - 5; i += 23) { + for (i = 0; i < ITEMS_NUM - 5; i += 23) { for (int j = 0; j < 5; j++) { if (data[i + j] != nullptr) { BLI_mempool_free(mempool, data[i + j]); data[i + j] = nullptr; - num_items--; + items_num--; } } } @@ -126,12 +126,12 @@ TEST(task, MempoolIter) TaskParallelSettings settings; BLI_parallel_mempool_settings_defaults(&settings); - BLI_task_parallel_mempool(mempool, &num_items, task_mempool_iter_func, &settings); + BLI_task_parallel_mempool(mempool, &items_num, task_mempool_iter_func, &settings); /* Those checks should ensure us all items of the mempool were processed once, and only once - as * expected. */ - EXPECT_EQ(num_items, 0); - for (i = 0; i < NUM_ITEMS; i++) { + EXPECT_EQ(items_num, 0); + for (i = 0; i < ITEMS_NUM; i++) { if (data[i] != nullptr) { EXPECT_EQ(*data[i], i); } @@ -189,19 +189,19 @@ static void task_mempool_iter_tls_free(const void *UNUSED(userdata), TEST(task, MempoolIterTLS) { - int *data[NUM_ITEMS]; + int *data[ITEMS_NUM]; BLI_threadapi_init(); BLI_mempool *mempool = BLI_mempool_create( - sizeof(*data[0]), NUM_ITEMS, 32, BLI_MEMPOOL_ALLOW_ITER); + sizeof(*data[0]), ITEMS_NUM, 32, BLI_MEMPOOL_ALLOW_ITER); int i; - /* Add numbers negative `1..NUM_ITEMS` inclusive. */ - int num_items = 0; - for (i = 0; i < NUM_ITEMS; i++) { + /* Add numbers negative `1..ITEMS_NUM` inclusive. */ + int items_num = 0; + for (i = 0; i < ITEMS_NUM; i++) { data[i] = (int *)BLI_mempool_alloc(mempool); *data[i] = -(i + 1); - num_items++; + items_num++; } TaskParallelSettings settings; @@ -218,15 +218,15 @@ TEST(task, MempoolIterTLS) BLI_task_parallel_mempool(mempool, nullptr, task_mempool_iter_tls_func, &settings); - EXPECT_EQ(BLI_listbase_count(tls_data.accumulate_items), NUM_ITEMS); + EXPECT_EQ(BLI_listbase_count(tls_data.accumulate_items), ITEMS_NUM); /* Check that all elements are added into the list once. */ - int num_accum = 0; + int number_accum = 0; for (LinkData *link = (LinkData *)tls_data.accumulate_items->first; link; link = link->next) { int *data = (int *)link->data; - num_accum += *data; + number_accum += *data; } - EXPECT_EQ(num_accum, (NUM_ITEMS * (NUM_ITEMS + 1)) / 2); + EXPECT_EQ(number_accum, (ITEMS_NUM * (ITEMS_NUM + 1)) / 2); BLI_freelistN(tls_data.accumulate_items); MEM_freeN(tls_data.accumulate_items); @@ -253,31 +253,31 @@ TEST(task, ListBaseIter) { ListBase list = {nullptr, nullptr}; LinkData *items_buffer = (LinkData *)MEM_calloc_arrayN( - NUM_ITEMS, sizeof(*items_buffer), __func__); + ITEMS_NUM, sizeof(*items_buffer), __func__); BLI_threadapi_init(); int i; - int num_items = 0; - for (i = 0; i < NUM_ITEMS; i++) { + int items_num = 0; + for (i = 0; i < ITEMS_NUM; i++) { BLI_addtail(&list, &items_buffer[i]); - num_items++; + items_num++; } TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - BLI_task_parallel_listbase(&list, &num_items, task_listbase_iter_func, &settings); + BLI_task_parallel_listbase(&list, &items_num, task_listbase_iter_func, &settings); /* Those checks should ensure us all items of the listbase were processed once, and only once - * as expected. */ - EXPECT_EQ(num_items, 0); + EXPECT_EQ(items_num, 0); LinkData *item; - for (i = 0, item = (LinkData *)list.first; i < NUM_ITEMS && item != nullptr; + for (i = 0, item = (LinkData *)list.first; i < ITEMS_NUM && item != nullptr; i++, item = item->next) { EXPECT_EQ(POINTER_AS_INT(item->data), i); } - EXPECT_EQ(NUM_ITEMS, i); + EXPECT_EQ(ITEMS_NUM, i); MEM_freeN(items_buffer); BLI_threadapi_exit(); diff --git a/source/blender/blenlib/tests/performance/BLI_task_performance_test.cc b/source/blender/blenlib/tests/performance/BLI_task_performance_test.cc index 98fafe55d69..a86e9b0b86d 100644 --- a/source/blender/blenlib/tests/performance/BLI_task_performance_test.cc +++ b/source/blender/blenlib/tests/performance/BLI_task_performance_test.cc @@ -95,12 +95,12 @@ static void task_listbase_heavy_membarrier_iter_func(void *userdata, } static void task_listbase_test_do(ListBase *list, - const int num_items, - int *num_items_tmp, + const int items_num, + int *items_tmp_num, const char *id, TaskParallelIteratorFunc func, const bool use_threads, - const bool check_num_items_tmp) + const bool check_items_tmp_num) { TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); @@ -109,24 +109,24 @@ static void task_listbase_test_do(ListBase *list, double averaged_timing = 0.0; for (int i = 0; i < NUM_RUN_AVERAGED; i++) { const double init_time = PIL_check_seconds_timer(); - BLI_task_parallel_listbase(list, num_items_tmp, func, &settings); + BLI_task_parallel_listbase(list, items_tmp_num, func, &settings); averaged_timing += PIL_check_seconds_timer() - init_time; /* Those checks should ensure us all items of the listbase were processed once, and only once - * as expected. */ - if (check_num_items_tmp) { - EXPECT_EQ(*num_items_tmp, 0); + if (check_items_tmp_num) { + EXPECT_EQ(*items_tmp_num, 0); } LinkData *item; int j; - for (j = 0, item = (LinkData *)list->first; j < num_items && item != nullptr; + for (j = 0, item = (LinkData *)list->first; j < items_num && item != nullptr; j++, item = item->next) { EXPECT_EQ(POINTER_AS_INT(item->data), j); item->data = POINTER_FROM_INT(0); } - EXPECT_EQ(num_items, j); + EXPECT_EQ(items_num, j); - *num_items_tmp = num_items; + *items_tmp_num = items_num; } printf("\t%s: done in %fs on average over %d runs\n", @@ -144,40 +144,40 @@ static void task_listbase_test(const char *id, const int count, const bool use_t BLI_threadapi_init(); - int num_items = 0; + int items_num = 0; for (int i = 0; i < count; i++) { BLI_addtail(&list, &items_buffer[i]); - num_items++; + items_num++; } - int num_items_tmp = num_items; + int items_tmp_num = items_num; task_listbase_test_do(&list, - num_items, - &num_items_tmp, + items_num, + &items_tmp_num, "Light iter", task_listbase_light_iter_func, use_threads, false); task_listbase_test_do(&list, - num_items, - &num_items_tmp, + items_num, + &items_tmp_num, "Light iter with mem barrier", task_listbase_light_membarrier_iter_func, use_threads, true); task_listbase_test_do(&list, - num_items, - &num_items_tmp, + items_num, + &items_tmp_num, "Heavy iter", task_listbase_heavy_iter_func, use_threads, false); task_listbase_test_do(&list, - num_items, - &num_items_tmp, + items_num, + &items_tmp_num, "Heavy iter with mem barrier", task_listbase_heavy_membarrier_iter_func, use_threads, diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c index adc6b990869..eee0e7fbea8 100644 --- a/source/blender/blenloader/intern/versioning_300.c +++ b/source/blender/blenloader/intern/versioning_300.c @@ -1569,10 +1569,10 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) { if (md->type == eModifierType_SurfaceDeform) { SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; - if (smd->num_bind_verts && smd->verts) { - smd->num_mesh_verts = smd->num_bind_verts; + if (smd->bind_verts_num && smd->verts) { + smd->mesh_verts_num = smd->bind_verts_num; - for (unsigned int i = 0; i < smd->num_bind_verts; i++) { + for (unsigned int i = 0; i < smd->bind_verts_num; i++) { smd->verts[i].vertex_idx = i; } } @@ -2435,17 +2435,27 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) } } - /** - * 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, 302, 7)) { + /* Generate 'system' liboverrides IDs. + * NOTE: This is a fairly rough process, based on very basic heuristics. Should be enough for a + * do_version code though, this is a new optional feature, not a critical conversion. */ + ID *id; + FOREACH_MAIN_ID_BEGIN (bmain, id) { + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id) || ID_IS_LINKED(id)) { + /* Ignore non-real liboverrides, and linked ones. */ + continue; + } + if (GS(id->name) == ID_OB) { + /* Never 'lock' an object into a system override for now. */ + continue; + } + if (BKE_lib_override_library_is_user_edited(id)) { + /* Do not 'lock' an ID already edited by the user. */ + continue; + } + id->override_library->flag |= IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED; + } + FOREACH_MAIN_ID_END; /* Initialize brush curves sculpt settings. */ LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) { @@ -2476,4 +2486,17 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + + /** + * 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/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index 16297149cc3..4c27b8b9016 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -1254,7 +1254,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) } cam = cam->id.next; } - /* Force oops draw if depgraph was set. */ + /* Force oops draw if depsgraph was set. */ /* Set time line var. */ /* softbody init new vars */ diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index 3b966fe5358..ec76f516780 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -324,6 +324,10 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme) if (!USER_VERSION_ATLEAST(301, 2)) { FROM_DEFAULT_V4_UCHAR(space_sequencer.mask); } + + if (!USER_VERSION_ATLEAST(302, 8)) { + btheme->space_node.grid_levels = U_theme_default.space_node.grid_levels; + } /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.cc b/source/blender/bmesh/intern/bmesh_mesh_convert.cc index 118e7751cbc..40f1d7c496d 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_convert.cc +++ b/source/blender/bmesh/intern/bmesh_mesh_convert.cc @@ -1096,7 +1096,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh vertMap = bm_to_mesh_vertex_map(bm, ototvert); } - for (i = j = 0; i < hmd->totindex; i++) { + for (i = j = 0; i < hmd->indexar_num; i++) { if (hmd->indexar[i] < ototvert) { eve = vertMap[hmd->indexar[i]]; @@ -1109,7 +1109,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh } } - hmd->totindex = j; + hmd->indexar_num = j; } } } diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cc b/source/blender/compositor/operations/COM_OutputFileOperation.cc index cde1496546e..372e0736cd2 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.cc +++ b/source/blender/compositor/operations/COM_OutputFileOperation.cc @@ -225,6 +225,11 @@ OutputSingleLayerOperation::OutputSingleLayerOperation(const Scene *scene, save_as_render_ = save_as_render; } +OutputSingleLayerOperation::~OutputSingleLayerOperation() +{ + BKE_image_format_free(&format_); +} + void OutputSingleLayerOperation::init_execution() { image_input_ = get_input_socket_reader(0); diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.h b/source/blender/compositor/operations/COM_OutputFileOperation.h index 98b7e77cc21..875defe00e9 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.h +++ b/source/blender/compositor/operations/COM_OutputFileOperation.h @@ -39,6 +39,7 @@ class OutputSingleLayerOperation : public MultiThreadedOperation { const char *path, const char *view_name, bool save_as_render); + ~OutputSingleLayerOperation(); void execute_region(rcti *rect, unsigned int tile_number) override; bool is_output_operation(bool /*rendering*/) const override diff --git a/source/blender/compositor/operations/COM_ViewerOperation.cc b/source/blender/compositor/operations/COM_ViewerOperation.cc index bc7e08ee98a..58392b8a638 100644 --- a/source/blender/compositor/operations/COM_ViewerOperation.cc +++ b/source/blender/compositor/operations/COM_ViewerOperation.cc @@ -202,7 +202,7 @@ void ViewerOperation::update_image(const rcti *rect) rect->ymax); /* This could be improved to use partial updates. For now disabled as the full frame compositor - * would not use partial frames anymore and the image engine requires more testing.*/ + * would not use partial frames anymore and the image engine requires more testing. */ BKE_image_partial_update_mark_full_update(image_); this->update_draw(); } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 76bfd216c03..4782f1c4a5d 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -1085,7 +1085,7 @@ void DepsgraphNodeBuilder::build_animation_images(ID *id) * tree. */ const bool can_have_gpu_material = ELEM(GS(id->name), ID_MA, ID_WO); - if (BKE_image_user_id_has_animation(id) || can_have_gpu_material) { + if (can_have_gpu_material || BKE_image_user_id_has_animation(id)) { ID *id_cow = get_cow_id(id); add_operation_node( id, diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 163ed1607e9..b5945c06ad3 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -1423,7 +1423,7 @@ void DepsgraphRelationBuilder::build_animation_images(ID *id) const bool can_have_gpu_material = ELEM(GS(id->name), ID_MA, ID_WO); /* TODO: can we check for existence of node for performance? */ - if (BKE_image_user_id_has_animation(id) || can_have_gpu_material) { + if (can_have_gpu_material || BKE_image_user_id_has_animation(id)) { OperationKey image_animation_key( id, NodeType::IMAGE_ANIMATION, OperationCode::IMAGE_ANIMATION); TimeSourceKey time_src_key; @@ -1839,9 +1839,8 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) /* We do not have to update the objects final transform after the simulation if it is * passive or controlled by the animation system in blender. * (Bullet doesn't move the object at all in these cases). - * But we can't update the depgraph when the animated property in changed during playback. - * So always assume that active bodies needs updating. - */ + * But we can't update the depsgraph when the animated property in changed during playback. + * So always assume that active bodies needs updating. */ OperationKey rb_transform_copy_key( &object->id, NodeType::TRANSFORM, OperationCode::RIGIDBODY_TRANSFORM_COPY); /* Rigid body synchronization depends on the actual simulation. */ @@ -2089,7 +2088,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle); mti->updateDepsgraph(md, &ctx); } - if (BKE_object_modifier_use_time(scene_, object, md, graph_->mode)) { + if (BKE_object_modifier_use_time(scene_, object, md)) { TimeSourceKey time_src_key; add_relation(time_src_key, obdata_ubereval_key, "Time Source"); } diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc index d5566e4be98..bcde1839a0f 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc @@ -54,7 +54,7 @@ void deg_invalidate_iterator_work_data(DEGObjectIterData *data) { #ifdef INVALIDATE_WORK_DATA BLI_assert(data != nullptr); - memset(&data->temp_dupli_object, 0xff, sizeof(data->temp_dupli_object)); + memset((void *)&data->temp_dupli_object, 0xff, sizeof(data->temp_dupli_object)); #else (void)data; #endif diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc index 19022d534b2..91170abed0b 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc @@ -886,7 +886,7 @@ ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, const IDNode return id_cow; } /* In case we don't need to do a copy-on-write, we can use the update cache of the grease - * pencil data to do an update-on-write.*/ + * pencil data to do an update-on-write. */ if (id_type == ID_GD && BKE_gpencil_can_avoid_full_copy_on_write( (const ::Depsgraph *)depsgraph, (bGPdata *)id_orig)) { BKE_gpencil_update_on_write((bGPdata *)id_orig, (bGPdata *)id_cow); diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 38ae9e86585..be7d24fb007 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -190,6 +190,7 @@ set(SRC intern/draw_cache_inline.h intern/draw_color_management.h intern/draw_common.h + intern/draw_common_shader_shared.h intern/draw_debug.h intern/draw_hair_private.h intern/draw_instance_data.h @@ -392,6 +393,7 @@ set(GLSL_SRC intern/shaders/common_subdiv_vbo_sculpt_data_comp.glsl intern/draw_shader_shared.h + intern/draw_common_shader_shared.h engines/gpencil/shaders/gpencil_frag.glsl engines/gpencil/shaders/gpencil_vert.glsl diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index 78b9b68bb01..5fa719facf4 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -108,7 +108,7 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, * MinMax Pyramid */ - if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) { + if (GPU_type_matches_ex(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) { /* Intel gpu seems to have problem rendering to only depth hiz_format */ DRW_texture_ensure_2d(&txl->maxzbuffer, UNPACK2(effects->hiz_size), GPU_R32F, DRW_TEX_MIPMAP); GPU_framebuffer_ensure_config(&fbl->maxzbuffer_fb, @@ -230,7 +230,7 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) /* Intel gpu seems to have problem rendering to only depth format. * Use color texture instead. */ - if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) { + if (GPU_type_matches_ex(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) { downsample_write = DRW_STATE_WRITE_COLOR; } diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index 7029d015b22..219c44de9dc 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -204,7 +204,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1); DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_len, 1); - DRW_shgroup_uniform_float(grp, "roughness", &pinfo->roughness, 1); + DRW_shgroup_uniform_float(grp, "probe_roughness", &pinfo->roughness, 1); DRW_shgroup_uniform_float(grp, "lodFactor", &pinfo->lodfactor, 1); DRW_shgroup_uniform_float(grp, "lodMax", &pinfo->lod_rt_max, 1); DRW_shgroup_uniform_float(grp, "texelSize", &pinfo->texel_size, 1); diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c index e148ac53cd4..d896c4e9331 100644 --- a/source/blender/draw/engines/eevee/eevee_occlusion.c +++ b/source/blender/draw/engines/eevee/eevee_occlusion.c @@ -200,7 +200,8 @@ void EEVEE_occlusion_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) } if (GPU_mip_render_workaround() || - GPU_type_matches(GPU_DEVICE_INTEL_UHD, GPU_OS_WIN, GPU_DRIVER_ANY)) { + GPU_type_matches_ex( + GPU_DEVICE_INTEL_UHD, GPU_OS_WIN, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) { /* Fix dot corruption on intel HD5XX/HD6XX series. */ GPU_flush(); } diff --git a/source/blender/draw/engines/eevee/eevee_shadows.c b/source/blender/draw/engines/eevee/eevee_shadows.c index 29d98f6795d..9e571b1d15b 100644 --- a/source/blender/draw/engines/eevee/eevee_shadows.c +++ b/source/blender/draw/engines/eevee/eevee_shadows.c @@ -147,7 +147,7 @@ void EEVEE_shadows_caster_register(EEVEE_ViewLayerData *sldata, Object *ob) } /* Update World AABB in frontbuffer. */ - BoundBox *bb = BKE_object_boundbox_get(ob); + const BoundBox *bb = BKE_object_boundbox_get(ob); float min[3], max[3]; INIT_MINMAX(min, max); for (int i = 0; i < 8; i++) { diff --git a/source/blender/draw/engines/eevee/eevee_shadows_cascade.c b/source/blender/draw/engines/eevee/eevee_shadows_cascade.c index 25939926cfa..536242f67d8 100644 --- a/source/blender/draw/engines/eevee/eevee_shadows_cascade.c +++ b/source/blender/draw/engines/eevee/eevee_shadows_cascade.c @@ -311,7 +311,7 @@ static void eevee_shadow_cascade_setup(EEVEE_LightsInfo *linfo, if (c < 3) { dbg_col[c] = 1.0f; } - DRW_debug_bbox((BoundBox *)&corners, dbg_col); + DRW_debug_bbox((const BoundBox *)&corners, dbg_col); DRW_debug_sphere(center, csm_render->radius[c], dbg_col); #endif diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 6ef58c90e7a..7d210f15d8b 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -346,7 +346,7 @@ static bool eevee_volume_object_grids_init(Object *ob, ListBase *gpu_grids, DRWS if (multiple_transforms) { /* For multiple grids with different transform, we first transform from object space * to bounds, then for each individual grid from bounds to texture. */ - BoundBox *bb = BKE_volume_boundbox_get(ob); + const BoundBox *bb = BKE_volume_boundbox_get(ob); float bb_size[3]; sub_v3_v3v3(bb_size, bb->vec[6], bb->vec[0]); size_to_mat4(bounds_to_object, bb_size); diff --git a/source/blender/draw/engines/eevee/shaders/effect_mist_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_mist_frag.glsl index 7331f92ba6d..94b881b44f1 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_mist_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_mist_frag.glsl @@ -4,7 +4,7 @@ /* Convert depth to Mist factor */ uniform vec3 mistSettings; -uniform sampler2D depthBuffer; +uniform depth2D depthBuffer; #define mistStart mistSettings.x #define mistInvDistance mistSettings.y diff --git a/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl index 0aa54715460..4f87cdf05d2 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl @@ -11,7 +11,7 @@ * by Jorge Jimenez */ uniform sampler2D colorBuffer; -uniform sampler2D depthBuffer; +uniform depth2D depthBuffer; uniform sampler2D velocityBuffer; uniform sampler2D tileMaxBuffer; diff --git a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl index 58bbb825043..1aff93e01f8 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl @@ -9,7 +9,7 @@ #define MAX_SSS_SAMPLES 65 layout(std140) uniform sssProfile { - vec4 kernel[MAX_SSS_SAMPLES]; + vec4 sss_kernel[MAX_SSS_SAMPLES]; vec4 radii_max_radius; int sss_samples; }; @@ -48,11 +48,11 @@ void main(void) float sss_radius_inv = 1.0 / max(1e-8, sss_radius); /* Center sample */ - vec3 accum = sss_irradiance * kernel[0].rgb; + vec3 accum = sss_irradiance * sss_kernel[0].rgb; for (int i = 1; i < sss_samples && i < MAX_SSS_SAMPLES; i++) { - vec2 sample_uv = uvs + kernel[i].a * finalStep * - ((abs(kernel[i].a) > sssJitterThreshold) ? dir : dir_rand); + vec2 sample_uv = uvs + sss_kernel[i].a * finalStep * + ((abs(sss_kernel[i].a) > sssJitterThreshold) ? dir : dir_rand); vec3 color = texture(sssIrradiance, sample_uv).rgb; float sample_depth = texture(depthBuffer, sample_uv).r; sample_depth = get_view_z_from_depth(sample_depth); @@ -66,8 +66,8 @@ void main(void) if (any(lessThan(sample_uv, vec2(0.0))) || any(greaterThan(sample_uv, vec2(1.0)))) { s = 0.0; } - /* Mix with first sample in failure case and apply kernel color. */ - accum += kernel[i].rgb * mix(sss_irradiance, color, s); + /* Mix with first sample in failure case and apply sss_kernel color. */ + accum += sss_kernel[i].rgb * mix(sss_irradiance, color, s); } #if defined(FIRST_PASS) diff --git a/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl b/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl index c54621f123d..b4ae8bd4405 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl @@ -3,7 +3,7 @@ #pragma BLENDER_REQUIRE(common_view_lib.glsl) uniform sampler2D colorBuffer; -uniform sampler2D depthBuffer; +uniform depth2D depthBuffer; uniform sampler2D colorHistoryBuffer; uniform mat4 prevViewProjectionMatrix; diff --git a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl index 831ed0a119a..3cf21dc32d1 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl @@ -8,7 +8,7 @@ in vec4 uvcoordsvar; out vec4 FragColor; -uniform sampler2D depthBuffer; +uniform depth2D depthBuffer; uniform sampler1D sssTexProfile; uniform sampler2D sssRadius; uniform sampler2DArray sssShadowCubes; @@ -21,7 +21,7 @@ uniform sampler2DArray sssShadowCascades; layout(std140) uniform sssProfile { - vec4 kernel[MAX_SSS_SAMPLES]; + vec4 sss_kernel[MAX_SSS_SAMPLES]; vec4 radii_max_radius; int sss_samples; }; diff --git a/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl index 9182171bab4..87854dd3be2 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl @@ -1,7 +1,7 @@ #pragma BLENDER_REQUIRE(common_math_lib.glsl) -uniform sampler2D depthBuffer; +uniform depth2D depthBuffer; uniform mat4 prevViewProjMatrix; uniform mat4 currViewProjMatrixInv; diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl index a5d11f52a1d..af2982b30c0 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl @@ -4,7 +4,7 @@ #pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) uniform samplerCube probeHdr; -uniform float roughness; +uniform float probe_roughness; uniform float texelSize; uniform float lodFactor; uniform float lodMax; @@ -51,7 +51,7 @@ void main() float pdf; /* Microfacet normal */ - vec3 H = sample_ggx(Xi, roughness, V, N, T, B, pdf); + vec3 H = sample_ggx(Xi, probe_roughness, V, N, T, B, pdf); vec3 L = -reflect(V, H); float NL = dot(N, L); diff --git a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl index dc98a00a1cd..3d43ef9addd 100644 --- a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl @@ -89,8 +89,8 @@ layout(std140) uniform light_block LightData lights_data[MAX_LIGHT]; }; -uniform sampler2DArrayShadow shadowCubeTexture; -uniform sampler2DArrayShadow shadowCascadeTexture; +uniform depth2DArrayShadow shadowCubeTexture; +uniform depth2DArrayShadow shadowCascadeTexture; /** \} */ diff --git a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl index 363b5cb978a..64ba8d44d39 100644 --- a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl @@ -16,7 +16,7 @@ uniform int postProcessType; uniform int currentSample; -uniform sampler2D depthBuffer; +uniform depth2D depthBuffer; uniform sampler2D inputBuffer; uniform sampler2D inputSecondLightBuffer; uniform sampler2D inputColorBuffer; diff --git a/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl index ad0d682dcf4..2a7d7e38504 100644 --- a/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl @@ -3,7 +3,7 @@ #pragma BLENDER_REQUIRE(common_utiltex_lib.glsl) #pragma BLENDER_REQUIRE(lights_lib.glsl) -uniform sampler2D depthBuffer; +uniform depth2D depthBuffer; out vec4 fragColor; diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c index be35660a4d7..40ebd262df5 100644 --- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c @@ -60,7 +60,7 @@ GPENCIL_tObject *gpencil_object_cache_add(GPENCIL_PrivateData *pd, Object *ob) * strokes not aligned with the object axes. Maybe we could try to * compute the minimum axis of all strokes. But this would be more * computationally heavy and should go into the GPData evaluation. */ - BoundBox *bbox = BKE_object_boundbox_get(ob); + const BoundBox *bbox = BKE_object_boundbox_get(ob); /* Convert bbox to matrix */ float mat[4][4], size[3], center[3]; BKE_boundbox_calc_size_aabb(bbox, size); diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl index c0ff8d945f2..af8aec85598 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl @@ -61,7 +61,9 @@ void main() gp_interp.hardness); if (GPENCIL_IS_STROKE_VERTEX) { - gp_interp.uv.x *= gp_mat._stroke_u_scale; + if (!flag_test(gp_flag, GP_STROKE_ALIGNMENT)) { + gp_interp.uv.x *= gp_mat._stroke_u_scale; + } /* Special case: We don't use vertex color if material Holdout. */ if (flag_test(gp_flag, GP_STROKE_HOLDOUT)) { diff --git a/source/blender/draw/engines/image/image_drawing_mode.hh b/source/blender/draw/engines/image/image_drawing_mode.hh index f43bbadfa91..14529797405 100644 --- a/source/blender/draw/engines/image/image_drawing_mode.hh +++ b/source/blender/draw/engines/image/image_drawing_mode.hh @@ -58,7 +58,7 @@ struct OneTextureMethod { { /* Although this works, computing an inverted matrix adds some precision issues and leads to * tearing artifacts. This should be modified to use the scaling and transformation from the - * not inverted matrix.*/ + * not inverted matrix. */ float4x4 mat(instance_data->ss_to_texture); float4x4 mat_inv = mat.inverted(); float3 min_uv = mat_inv * float3(0.0f, 0.0f, 0.0f); @@ -420,7 +420,7 @@ template<typename TextureMethod> class ScreenSpaceDrawingMode : public AbstractD /* IMB_transform works in a non-consistent space. This should be documented or fixed!. * Construct a variant of the info_uv_to_texture that adds the texel space - * transformation.*/ + * transformation. */ float uv_to_texel[4][4]; copy_m4_m4(uv_to_texel, instance_data.ss_to_texture); float scale[3] = {static_cast<float>(texture_width) / static_cast<float>(tile_buffer.x), diff --git a/source/blender/draw/engines/image/image_usage.hh b/source/blender/draw/engines/image/image_usage.hh index bea5c3853b0..f4ba3f495ce 100644 --- a/source/blender/draw/engines/image/image_usage.hh +++ b/source/blender/draw/engines/image/image_usage.hh @@ -14,7 +14,7 @@ struct ImageUsage { /** Render pass of the image that is used. */ short pass = 0; - /** Layer of the image that is used.*/ + /** Layer of the image that is used. */ short layer = 0; /** View of the image that is used. */ short view = 0; diff --git a/source/blender/draw/engines/overlay/overlay_edit_mesh.c b/source/blender/draw/engines/overlay/overlay_edit_mesh.c index e605a3be375..e0671eac156 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_mesh.c +++ b/source/blender/draw/engines/overlay/overlay_edit_mesh.c @@ -138,6 +138,7 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata) GPUShader *edge_sh = OVERLAY_shader_edit_mesh_edge(!select_vert); GPUShader *face_sh = OVERLAY_shader_edit_mesh_face(); const bool do_zbufclip = (i == 0 && pd->edit_mesh.do_zbufclip); + const bool do_smooth_wire = (U.gpu_flag & USER_GPU_FLAG_NO_EDIT_MODE_SMOOTH_WIRE) == 0; DRWState state_common = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA; /* Faces */ @@ -173,17 +174,21 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata) DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity); DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex); DRW_shgroup_uniform_bool_copy(grp, "selectEdges", pd->edit_mesh.do_edges || select_edge); + DRW_shgroup_uniform_bool_copy(grp, "do_smooth_wire", do_smooth_wire); /* Verts */ state |= DRW_STATE_WRITE_DEPTH; DRW_PASS_CREATE(psl->edit_mesh_verts_ps[i], state | pd->clipping_state); if (select_vert) { + int vert_mask[4] = {0xFF, 0xFF, 0xFF, 0xFF}; + sh = OVERLAY_shader_edit_mesh_vert(); grp = pd->edit_mesh_verts_grp[i] = DRW_shgroup_create(sh, psl->edit_mesh_verts_ps[i]); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity); DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex); + DRW_shgroup_uniform_ivec4_copy(grp, "dataMask", vert_mask); sh = OVERLAY_shader_edit_mesh_skin_root(); grp = pd->edit_mesh_skin_roots_grp[i] = DRW_shgroup_create(sh, psl->edit_mesh_verts_ps[i]); diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c index aae12e5513e..4f0bf0b8048 100644 --- a/source/blender/draw/engines/overlay/overlay_extra.c +++ b/source/blender/draw/engines/overlay/overlay_extra.c @@ -345,18 +345,17 @@ static void OVERLAY_bounds(OVERLAY_ExtraCallBuffers *cb, bool around_origin) { float center[3], size[3], tmp[4][4], final_mat[4][4]; - BoundBox bb_local; if (ob->type == OB_MBALL && !BKE_mball_is_basis(ob)) { return; } - BoundBox *bb = BKE_object_boundbox_get(ob); - + const BoundBox *bb = BKE_object_boundbox_get(ob); + BoundBox bb_local; if (bb == NULL) { const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {1.0f, 1.0f, 1.0f}; + BKE_boundbox_init_from_minmax(&bb_local, min, max); bb = &bb_local; - BKE_boundbox_init_from_minmax(bb, min, max); } BKE_boundbox_calc_size_aabb(bb, size); @@ -756,7 +755,7 @@ void OVERLAY_lightprobe_cache_populate(OVERLAY_Data *vedata, Object *ob) uint cell_count = prb->grid_resolution_x * prb->grid_resolution_y * prb->grid_resolution_z; DRWShadingGroup *grp = DRW_shgroup_create_sub(vedata->stl->pd->extra_grid_grp); - DRW_shgroup_uniform_vec4_array_copy(grp, "gridModelMatrix", instdata.mat, 4); + DRW_shgroup_uniform_mat4_copy(grp, "gridModelMatrix", instdata.mat); DRW_shgroup_call_procedural_points(grp, NULL, cell_count); } break; diff --git a/source/blender/draw/engines/overlay/overlay_outline.c b/source/blender/draw/engines/overlay/overlay_outline.c index cb94008f53f..8010319e3fa 100644 --- a/source/blender/draw/engines/overlay/overlay_outline.c +++ b/source/blender/draw/engines/overlay/overlay_outline.c @@ -32,7 +32,7 @@ static void gpencil_depth_plane(Object *ob, float r_plane[4]) * strokes not aligned with the object axes. Maybe we could try to * compute the minimum axis of all strokes. But this would be more * computationally heavy and should go into the GPData evaluation. */ - BoundBox *bbox = BKE_object_boundbox_get(ob); + const BoundBox *bbox = BKE_object_boundbox_get(ob); /* Convert bbox to matrix */ float mat[4][4], size[3], center[3]; BKE_boundbox_calc_size_aabb(bbox, size); diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c index 639b20feae4..278aefb8fec 100644 --- a/source/blender/draw/engines/overlay/overlay_shader.c +++ b/source/blender/draw/engines/overlay/overlay_shader.c @@ -299,21 +299,10 @@ GPUShader *OVERLAY_shader_depth_only(void) GPUShader *OVERLAY_shader_edit_mesh_vert(void) { const DRWContextState *draw_ctx = DRW_context_state_get(); - const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; if (!sh_data->edit_mesh_vert) { - sh_data->edit_mesh_vert = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg->lib, - datatoc_common_globals_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_edit_mesh_common_lib_glsl, - datatoc_edit_mesh_vert_glsl, - NULL}, - .frag = (const char *[]){datatoc_common_globals_lib_glsl, - datatoc_gpu_shader_point_varying_color_frag_glsl, - NULL}, - .defs = (const char *[]){sh_cfg->def, "#define VERT\n", NULL}, - }); + sh_data->edit_mesh_vert = GPU_shader_create_from_info_name( + draw_ctx->sh_cfg ? "overlay_edit_mesh_vert_clipped" : "overlay_edit_mesh_vert"); } return sh_data->edit_mesh_vert; } @@ -321,47 +310,14 @@ GPUShader *OVERLAY_shader_edit_mesh_vert(void) GPUShader *OVERLAY_shader_edit_mesh_edge(bool use_flat_interp) { const DRWContextState *draw_ctx = DRW_context_state_get(); - const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; GPUShader **sh = use_flat_interp ? &sh_data->edit_mesh_edge_flat : &sh_data->edit_mesh_edge; if (*sh == NULL) { - /* Use geometry shader to draw edge wire-frame. This ensure us - * the same result across platforms and more flexibility. - * But we pay the cost of running a geometry shader. - * In the future we might consider using only the vertex shader - * and loading data manually with buffer textures. */ - const bool use_geom_shader = true; - const bool use_smooth_wires = (U.gpu_flag & USER_GPU_FLAG_NO_EDIT_MODE_SMOOTH_WIRE) == 0; - const char *geom_sh_code[] = {use_geom_shader ? sh_cfg->lib : NULL, - datatoc_common_globals_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_edit_mesh_geom_glsl, - NULL}; - const char *vert_sh_code[] = {sh_cfg->lib, - datatoc_common_globals_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_edit_mesh_common_lib_glsl, - datatoc_edit_mesh_vert_glsl, - NULL}; - const char *frag_sh_code[] = {sh_cfg->lib, - datatoc_common_globals_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_edit_mesh_common_lib_glsl, - datatoc_edit_mesh_frag_glsl, - NULL}; - const char *defs[] = {sh_cfg->def, - use_geom_shader ? "#define USE_GEOM_SHADER\n" : "", - use_smooth_wires ? "#define USE_SMOOTH_WIRE\n" : "", - use_flat_interp ? "#define FLAT\n" : "", - "#define EDGE\n", - NULL}; - - *sh = GPU_shader_create_from_arrays({ - .vert = vert_sh_code, - .frag = frag_sh_code, - .geom = geom_sh_code, - .defs = defs, - }); + *sh = GPU_shader_create_from_info_name( + draw_ctx->sh_cfg ? + (use_flat_interp ? "overlay_edit_mesh_edge_flat_clipped" : + "overlay_edit_mesh_edge_clipped") : + (use_flat_interp ? "overlay_edit_mesh_edge_flat" : "overlay_edit_mesh_edge")); } return *sh; } @@ -369,35 +325,16 @@ GPUShader *OVERLAY_shader_edit_mesh_edge(bool use_flat_interp) GPUShader *OVERLAY_shader_armature_sphere(bool use_outline) { const DRWContextState *draw_ctx = DRW_context_state_get(); - const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - const char extensions[] = ""; if (use_outline && !sh_data->armature_sphere_outline) { - sh_data->armature_sphere_outline = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg->lib, - datatoc_common_globals_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_armature_sphere_outline_vert_glsl, - NULL}, - .frag = (const char *[]){extensions, - datatoc_common_view_lib_glsl, - datatoc_armature_wire_frag_glsl, - NULL}, - .defs = (const char *[]){sh_cfg->def, NULL}, - }); + sh_data->armature_sphere_outline = GPU_shader_create_from_info_name( + draw_ctx->sh_cfg ? "overlay_armature_sphere_outline_clipped" : + "overlay_armature_sphere_outline"); } else if (!sh_data->armature_sphere_solid) { - sh_data->armature_sphere_solid = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg->lib, - datatoc_common_view_lib_glsl, - datatoc_armature_sphere_solid_vert_glsl, - NULL}, - .frag = (const char *[]){extensions, - datatoc_common_view_lib_glsl, - datatoc_armature_sphere_solid_frag_glsl, - NULL}, - .defs = (const char *[]){sh_cfg->def, NULL}, - }); + sh_data->armature_sphere_solid = GPU_shader_create_from_info_name( + draw_ctx->sh_cfg ? "overlay_armature_sphere_solid_clipped" : + "overlay_armature_sphere_solid"); } return use_outline ? sh_data->armature_sphere_outline : sh_data->armature_sphere_solid; } @@ -405,34 +342,16 @@ GPUShader *OVERLAY_shader_armature_sphere(bool use_outline) GPUShader *OVERLAY_shader_armature_shape(bool use_outline) { const DRWContextState *draw_ctx = DRW_context_state_get(); - const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; if (use_outline && !sh_data->armature_shape_outline) { - sh_data->armature_shape_outline = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg->lib, - datatoc_common_globals_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_armature_shape_outline_vert_glsl, - NULL}, - .geom = (const char *[]){sh_cfg->lib, - datatoc_common_globals_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_armature_shape_outline_geom_glsl, - NULL}, - .frag = - (const char *[]){datatoc_common_view_lib_glsl, datatoc_armature_wire_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg->def, NULL}, - }); + sh_data->armature_shape_outline = GPU_shader_create_from_info_name( + draw_ctx->sh_cfg ? "overlay_armature_shape_outline_clipped" : + "overlay_armature_shape_outline"); } else if (!sh_data->armature_shape_solid) { - sh_data->armature_shape_solid = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg->lib, - datatoc_common_view_lib_glsl, - datatoc_armature_shape_solid_vert_glsl, - NULL}, - .frag = (const char *[]){datatoc_armature_shape_solid_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg->def, NULL}, - }); + sh_data->armature_shape_solid = GPU_shader_create_from_info_name( + draw_ctx->sh_cfg ? "overlay_armature_shape_solid_clipped" : + "overlay_armature_shape_solid"); } return use_outline ? sh_data->armature_shape_outline : sh_data->armature_shape_solid; } @@ -440,19 +359,10 @@ GPUShader *OVERLAY_shader_armature_shape(bool use_outline) GPUShader *OVERLAY_shader_armature_shape_wire(void) { const DRWContextState *draw_ctx = DRW_context_state_get(); - const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; if (!sh_data->armature_shape_wire) { - sh_data->armature_shape_wire = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg->lib, - datatoc_common_globals_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_armature_shape_wire_vert_glsl, - NULL}, - .frag = - (const char *[]){datatoc_common_view_lib_glsl, datatoc_armature_wire_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg->def, NULL}, - }); + sh_data->armature_shape_wire = GPU_shader_create_from_info_name( + draw_ctx->sh_cfg ? "overlay_armature_shape_wire_clipped" : "overlay_armature_shape_wire"); } return sh_data->armature_shape_wire; } @@ -460,29 +370,16 @@ GPUShader *OVERLAY_shader_armature_shape_wire(void) GPUShader *OVERLAY_shader_armature_envelope(bool use_outline) { const DRWContextState *draw_ctx = DRW_context_state_get(); - const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; if (use_outline && !sh_data->armature_envelope_outline) { - sh_data->armature_envelope_outline = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg->lib, - datatoc_common_globals_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_armature_envelope_outline_vert_glsl, - NULL}, - .frag = - (const char *[]){datatoc_common_view_lib_glsl, datatoc_armature_wire_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg->def, NULL}, - }); + sh_data->armature_envelope_outline = GPU_shader_create_from_info_name( + draw_ctx->sh_cfg ? "overlay_armature_envelope_outline_clipped" : + "overlay_armature_envelope_outline"); } else if (!sh_data->armature_envelope_solid) { - sh_data->armature_envelope_solid = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg->lib, - datatoc_common_view_lib_glsl, - datatoc_armature_envelope_solid_vert_glsl, - NULL}, - .frag = (const char *[]){datatoc_armature_envelope_solid_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg->def, NULL}, - }); + sh_data->armature_envelope_solid = GPU_shader_create_from_info_name( + draw_ctx->sh_cfg ? "overlay_armature_envelope_solid_clipped" : + "overlay_armature_envelope_solid"); } return use_outline ? sh_data->armature_envelope_outline : sh_data->armature_envelope_solid; } @@ -490,18 +387,10 @@ GPUShader *OVERLAY_shader_armature_envelope(bool use_outline) GPUShader *OVERLAY_shader_armature_stick(void) { const DRWContextState *draw_ctx = DRW_context_state_get(); - const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; if (!sh_data->armature_stick) { - sh_data->armature_stick = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg->lib, - datatoc_common_globals_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_armature_stick_vert_glsl, - NULL}, - .frag = (const char *[]){datatoc_armature_stick_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg->def, NULL}, - }); + sh_data->armature_stick = GPU_shader_create_from_info_name( + draw_ctx->sh_cfg ? "overlay_armature_stick_clipped" : "overlay_armature_stick"); } return sh_data->armature_stick; } @@ -509,19 +398,10 @@ GPUShader *OVERLAY_shader_armature_stick(void) GPUShader *OVERLAY_shader_armature_degrees_of_freedom_wire(void) { const DRWContextState *draw_ctx = DRW_context_state_get(); - const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; if (!sh_data->armature_dof_wire) { - sh_data->armature_dof_wire = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg->lib, - datatoc_common_globals_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_armature_dof_vert_glsl, - NULL}, - .frag = - (const char *[]){datatoc_common_view_lib_glsl, datatoc_armature_wire_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg->def, "#define EDGE\n", NULL}, - }); + sh_data->armature_dof_wire = GPU_shader_create_from_info_name( + draw_ctx->sh_cfg ? "overlay_armature_dof_wire_clipped" : "overlay_armature_dof_wire"); } return sh_data->armature_dof_wire; } @@ -529,20 +409,10 @@ GPUShader *OVERLAY_shader_armature_degrees_of_freedom_wire(void) GPUShader *OVERLAY_shader_armature_degrees_of_freedom_solid(void) { const DRWContextState *draw_ctx = DRW_context_state_get(); - const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; if (!sh_data->armature_dof_solid) { - sh_data->armature_dof_solid = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg->lib, - datatoc_common_globals_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_armature_dof_vert_glsl, - NULL}, - .frag = (const char *[]){datatoc_common_view_lib_glsl, - datatoc_armature_dof_solid_frag_glsl, - NULL}, - .defs = (const char *[]){sh_cfg->def, NULL}, - }); + sh_data->armature_dof_solid = GPU_shader_create_from_info_name( + draw_ctx->sh_cfg ? "overlay_armature_dof_solid_clipped" : "overlay_armature_dof_solid"); } return sh_data->armature_dof_solid; } @@ -550,19 +420,10 @@ GPUShader *OVERLAY_shader_armature_degrees_of_freedom_solid(void) GPUShader *OVERLAY_shader_armature_wire(void) { const DRWContextState *draw_ctx = DRW_context_state_get(); - const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; if (!sh_data->armature_wire) { - sh_data->armature_wire = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg->lib, - datatoc_common_globals_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_armature_wire_vert_glsl, - NULL}, - .frag = - (const char *[]){datatoc_common_view_lib_glsl, datatoc_armature_wire_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg->def, NULL}, - }); + sh_data->armature_wire = GPU_shader_create_from_info_name( + draw_ctx->sh_cfg ? "overlay_armature_wire_clipped" : "overlay_armature_wire"); } return sh_data->armature_wire; } @@ -722,19 +583,10 @@ GPUShader *OVERLAY_shader_edit_lattice_wire(void) GPUShader *OVERLAY_shader_edit_mesh_face(void) { const DRWContextState *draw_ctx = DRW_context_state_get(); - const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; if (!sh_data->edit_mesh_face) { - sh_data->edit_mesh_face = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg->lib, - datatoc_common_globals_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_edit_mesh_common_lib_glsl, - datatoc_edit_mesh_vert_glsl, - NULL}, - .frag = (const char *[]){datatoc_gpu_shader_3D_smooth_color_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg->def, "#define FACE\n", NULL}, - }); + sh_data->edit_mesh_face = GPU_shader_create_from_info_name( + draw_ctx->sh_cfg ? "overlay_edit_mesh_face_clipped" : "overlay_edit_mesh_face"); } return sh_data->edit_mesh_face; } @@ -742,19 +594,10 @@ GPUShader *OVERLAY_shader_edit_mesh_face(void) GPUShader *OVERLAY_shader_edit_mesh_facedot(void) { const DRWContextState *draw_ctx = DRW_context_state_get(); - const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; if (!sh_data->edit_mesh_facedot) { - sh_data->edit_mesh_facedot = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg->lib, - datatoc_common_globals_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_edit_mesh_common_lib_glsl, - datatoc_edit_mesh_vert_glsl, - NULL}, - .frag = (const char *[]){datatoc_gpu_shader_point_varying_color_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg->def, "#define FACEDOT\n", NULL}, - }); + sh_data->edit_mesh_facedot = GPU_shader_create_from_info_name( + draw_ctx->sh_cfg ? "overlay_edit_mesh_facedot_clipped" : "overlay_edit_mesh_facedot"); } return sh_data->edit_mesh_facedot; } @@ -762,18 +605,10 @@ GPUShader *OVERLAY_shader_edit_mesh_facedot(void) GPUShader *OVERLAY_shader_edit_mesh_normal(void) { const DRWContextState *draw_ctx = DRW_context_state_get(); - const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; if (!sh_data->edit_mesh_normals) { - sh_data->edit_mesh_normals = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg->lib, - datatoc_common_globals_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_edit_mesh_normal_vert_glsl, - NULL}, - .frag = (const char *[]){datatoc_gpu_shader_flat_color_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg->def, "#define INSTANCED_ATTR\n", NULL}, - }); + sh_data->edit_mesh_normals = GPU_shader_create_from_info_name( + draw_ctx->sh_cfg ? "overlay_edit_mesh_normal_clipped" : "overlay_edit_mesh_normal"); } return sh_data->edit_mesh_normals; } @@ -781,17 +616,10 @@ GPUShader *OVERLAY_shader_edit_mesh_normal(void) GPUShader *OVERLAY_shader_edit_mesh_analysis(void) { const DRWContextState *draw_ctx = DRW_context_state_get(); - const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; if (!sh_data->edit_mesh_analysis) { - sh_data->edit_mesh_analysis = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg->lib, - datatoc_common_view_lib_glsl, - datatoc_edit_mesh_analysis_vert_glsl, - NULL}, - .frag = (const char *[]){datatoc_edit_mesh_analysis_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg->def, NULL}, - }); + sh_data->edit_mesh_analysis = GPU_shader_create_from_info_name( + draw_ctx->sh_cfg ? "overlay_edit_mesh_analysis_clipped" : "overlay_edit_mesh_analysis"); } return sh_data->edit_mesh_analysis; } @@ -799,18 +627,10 @@ GPUShader *OVERLAY_shader_edit_mesh_analysis(void) GPUShader *OVERLAY_shader_edit_mesh_skin_root(void) { const DRWContextState *draw_ctx = DRW_context_state_get(); - const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; if (!sh_data->edit_mesh_skin_root) { - sh_data->edit_mesh_skin_root = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg->lib, - datatoc_common_globals_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_edit_mesh_skin_root_vert_glsl, - NULL}, - .frag = (const char *[]){datatoc_gpu_shader_flat_color_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg->def, "#define INSTANCED_ATTR\n", NULL}, - }); + sh_data->edit_mesh_skin_root = GPU_shader_create_from_info_name( + draw_ctx->sh_cfg ? "overlay_edit_mesh_skin_root_clipped" : "overlay_edit_mesh_skin_root"); } return sh_data->edit_mesh_skin_root; } diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c index b3c0c5da9b5..a5628559cfd 100644 --- a/source/blender/draw/engines/overlay/overlay_wireframe.c +++ b/source/blender/draw/engines/overlay/overlay_wireframe.c @@ -148,7 +148,7 @@ static void wireframe_hair_cache_populate(OVERLAY_Data *vedata, Object *ob, Part const bool use_coloring = true; DRWShadingGroup *shgrp = DRW_shgroup_create_sub(pd->wires_hair_grp[is_xray][use_coloring]); - DRW_shgroup_uniform_vec4_array_copy(shgrp, "hairDupliMatrix", dupli_mat, 4); + DRW_shgroup_uniform_mat4_copy(shgrp, "hairDupliMatrix", dupli_mat); DRW_shgroup_call_no_cull(shgrp, hairs, ob); } diff --git a/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl b/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl index 67d172fbd01..2f4542343f7 100644 --- a/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl @@ -2,7 +2,7 @@ #pragma BLENDER_REQUIRE(common_math_lib.glsl) uniform sampler2D colorTex; -uniform sampler2D depthTex; +uniform depth2D depthTex; uniform sampler2D lineTex; uniform bool doSmoothLines; diff --git a/source/blender/draw/engines/overlay/shaders/armature_dof_solid_frag.glsl b/source/blender/draw/engines/overlay/shaders/armature_dof_solid_frag.glsl index aedc9bcda61..d46abbf79ee 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_dof_solid_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_dof_solid_frag.glsl @@ -1,11 +1,4 @@ -uniform float alpha = 1.0; - -flat in vec4 finalColor; - -layout(location = 0) out vec4 fragColor; -layout(location = 1) out vec4 lineOutput; - void main() { fragColor = vec4(finalColor.rgb, finalColor.a * alpha); diff --git a/source/blender/draw/engines/overlay/shaders/armature_dof_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_dof_vert.glsl index 18a80fc1fb4..b3c9ce5dfd2 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_dof_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_dof_vert.glsl @@ -1,17 +1,6 @@ -/* ---- Instantiated Attrs ---- */ -in vec2 pos; - -/* ---- Per instance Attrs ---- */ -/* Assumed to be in world coordinate already. */ -in vec4 color; -in mat4 inst_obmat; - -flat out vec4 finalColor; -#ifdef EDGE -flat out vec2 edgeStart; -noperspective out vec2 edgePos; -#endif +#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) vec3 sphere_project(float ax, float az) { @@ -37,11 +26,7 @@ void main() gl_Position = point_world_to_ndc(world_pos); finalColor = color; -#ifdef EDGE - edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy; -#endif + edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport; -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(world_pos); -#endif + view_clipping_distances(world_pos); } diff --git a/source/blender/draw/engines/overlay/shaders/armature_envelope_outline_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_envelope_outline_vert.glsl index 2260b2d3fa6..0a8e279e9b0 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_envelope_outline_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_envelope_outline_vert.glsl @@ -1,19 +1,6 @@ -/* ---- Instantiated Attrs ---- */ -in vec2 pos0; -in vec2 pos1; -in vec2 pos2; - -/* ---- Per instance Attrs ---- */ -/* Assumed to be in world coordinate already. */ -in vec4 headSphere; -in vec4 tailSphere; -in vec4 outlineColorSize; -in vec3 xAxis; - -flat out vec4 finalColor; -flat out vec2 edgeStart; -noperspective out vec2 edgePos; +#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) /* project to screen space */ vec2 proj(vec4 pos) @@ -134,9 +121,7 @@ void main() vec3 wpos2 = get_outline_point( pos2, sph_near, sph_far, mat_near, mat_far, z_ofs_near, z_ofs_far, b); -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(wpos1); -#endif + view_clipping_distances(wpos1); vec4 p0 = point_world_to_ndc(wpos0); vec4 p1 = point_world_to_ndc(wpos1); @@ -152,7 +137,7 @@ void main() vec2 ofs_dir = compute_dir(ss0, ss1, ss2); /* Offset away from the center to avoid overlap with solid shape. */ - gl_Position.xy += ofs_dir * sizeViewportInv.xy * gl_Position.w; + gl_Position.xy += ofs_dir * drw_view.viewport_size_inverse * gl_Position.w; edgeStart = edgePos = proj(gl_Position); diff --git a/source/blender/draw/engines/overlay/shaders/armature_envelope_solid_frag.glsl b/source/blender/draw/engines/overlay/shaders/armature_envelope_solid_frag.glsl index 51cfe6250be..a90d2e3e406 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_envelope_solid_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_envelope_solid_frag.glsl @@ -1,14 +1,4 @@ -uniform float alpha = 0.6; -uniform bool isDistance; - -flat in vec3 finalStateColor; -flat in vec3 finalBoneColor; -in vec3 normalView; - -layout(location = 0) out vec4 fragColor; -layout(location = 1) out vec4 lineOutput; - void main() { float n = normalize(normalView).z; diff --git a/source/blender/draw/engines/overlay/shaders/armature_envelope_solid_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_envelope_solid_vert.glsl index 620b3f2527c..2dd86a57dfd 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_envelope_solid_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_envelope_solid_vert.glsl @@ -1,18 +1,6 @@ -/* ---- Instantiated Attrs ---- */ -in vec3 pos; - -/* ---- Per instance Attrs ---- */ -/* Assumed to be in world coordinate already. */ -in vec4 headSphere; -in vec4 tailSphere; -in vec3 xAxis; -in vec3 stateColor; -in vec3 boneColor; - -flat out vec3 finalStateColor; -flat out vec3 finalBoneColor; -out vec3 normalView; +#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) void main() { @@ -47,9 +35,8 @@ void main() finalStateColor = stateColor; finalBoneColor = boneColor; + view_clipping_distances(sp); + vec4 pos_4d = vec4(sp, 1.0); gl_Position = ViewProjectionMatrix * pos_4d; -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(pos_4d.xyz); -#endif } diff --git a/source/blender/draw/engines/overlay/shaders/armature_shape_outline_geom.glsl b/source/blender/draw/engines/overlay/shaders/armature_shape_outline_geom.glsl index a2a478f400b..47c5dada708 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_shape_outline_geom.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_shape_outline_geom.glsl @@ -1,28 +1,16 @@ -layout(lines_adjacency) in; -layout(line_strip, max_vertices = 2) out; - -in vec4 pPos[]; -in vec3 vPos[]; -in vec2 ssPos[]; -in vec2 ssNor[]; -in vec4 vColSize[]; -in int inverted[]; - -flat out vec4 finalColor; -flat out vec2 edgeStart; -noperspective out vec2 edgePos; +#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl) void main(void) { - finalColor = vec4(vColSize[0].rgb, 1.0); + finalColor = vec4(geom_in[0].vColSize.rgb, 1.0); bool is_persp = (ProjectionMatrix[3][3] == 0.0); - vec3 view_vec = (is_persp) ? normalize(vPos[1]) : vec3(0.0, 0.0, -1.0); - vec3 v10 = vPos[0] - vPos[1]; - vec3 v12 = vPos[2] - vPos[1]; - vec3 v13 = vPos[3] - vPos[1]; + vec3 view_vec = (is_persp) ? normalize(geom_in[1].vPos) : vec3(0.0, 0.0, -1.0); + vec3 v10 = geom_in[0].vPos - geom_in[1].vPos; + vec3 v12 = geom_in[2].vPos - geom_in[1].vPos; + vec3 v13 = geom_in[3].vPos - geom_in[1].vPos; vec3 n0 = cross(v12, v10); vec3 n3 = cross(v13, v12); @@ -40,13 +28,13 @@ void main(void) } } - n0 = (inverted[0] == 1) ? -n0 : n0; + n0 = (geom_in[0].inverted == 1) ? -n0 : n0; /* Don't outline if concave edge. */ if (dot(n0, v13) > 0.0001) { return; } - vec2 perp = normalize(ssPos[2] - ssPos[1]); + vec2 perp = normalize(geom_in[2].ssPos - geom_in[1].ssPos); vec2 edge_dir = vec2(-perp.y, perp.x); vec2 hidden_point; @@ -55,37 +43,33 @@ void main(void) * If the chosen point is parallel to the edge in screen space, * choose the other point anyway. * This fixes some issue with cubes in orthographic views. */ - if (vPos[0].z < vPos[3].z) { - hidden_point = (abs(fac0) > 1e-5) ? ssPos[0] : ssPos[3]; + if (geom_in[0].vPos.z < geom_in[3].vPos.z) { + hidden_point = (abs(fac0) > 1e-5) ? geom_in[0].ssPos : geom_in[3].ssPos; } else { - hidden_point = (abs(fac3) > 1e-5) ? ssPos[3] : ssPos[0]; + hidden_point = (abs(fac3) > 1e-5) ? geom_in[3].ssPos : geom_in[0].ssPos; } - vec2 hidden_dir = normalize(hidden_point - ssPos[1]); + vec2 hidden_dir = normalize(hidden_point - geom_in[1].ssPos); float fac = dot(-hidden_dir, edge_dir); edge_dir *= (fac < 0.0) ? -1.0 : 1.0; - gl_Position = pPos[1]; + gl_Position = geom_in[1].pPos; /* Offset away from the center to avoid overlap with solid shape. */ - gl_Position.xy += (edge_dir - perp) * sizeViewportInv.xy * gl_Position.w; + gl_Position.xy += (edge_dir - perp) * drw_view.viewport_size_inverse * gl_Position.w; /* Improve AA bleeding inside bone silhouette. */ gl_Position.z -= (is_persp) ? 1e-4 : 1e-6; - edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy; -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance); -#endif + edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport; + view_clipping_distances_set(gl_in[1]); EmitVertex(); - gl_Position = pPos[2]; + gl_Position = geom_in[2].pPos; /* Offset away from the center to avoid overlap with solid shape. */ - gl_Position.xy += (edge_dir + perp) * sizeViewportInv.xy * gl_Position.w; + gl_Position.xy += (edge_dir + perp) * drw_view.viewport_size_inverse * gl_Position.w; /* Improve AA bleeding inside bone silhouette. */ gl_Position.z -= (is_persp) ? 1e-4 : 1e-6; edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy; -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[2].gl_ClipDistance); -#endif + view_clipping_distances_set(gl_in[2]); EmitVertex(); EndPrimitive(); diff --git a/source/blender/draw/engines/overlay/shaders/armature_shape_outline_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_shape_outline_vert.glsl index ddc6328e6a2..29319b3f7ac 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_shape_outline_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_shape_outline_vert.glsl @@ -1,18 +1,6 @@ -/* ---- Instantiated Attrs ---- */ -in vec3 pos; -in vec3 snor; - -/* ---- Per instance Attrs ---- */ -in vec4 color; -in mat4 inst_obmat; - -out vec4 pPos; -out vec3 vPos; -out vec2 ssPos; -out vec2 ssNor; -out vec4 vColSize; -out int inverted; +#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) /* project to screen space */ vec2 proj(vec4 pos) @@ -25,13 +13,13 @@ void main() vec4 bone_color, state_color; mat4 model_mat = extract_matrix_packed_data(inst_obmat, state_color, bone_color); - vec4 worldPosition = model_mat * vec4(pos, 1.0); - vec4 viewpos = ViewMatrix * worldPosition; + vec4 world_pos = model_mat * vec4(pos, 1.0); + vec4 view_pos = ViewMatrix * world_pos; - vPos = viewpos.xyz; - pPos = ProjectionMatrix * viewpos; + geom_in.vPos = view_pos.xyz; + geom_in.pPos = ProjectionMatrix * view_pos; - inverted = int(dot(cross(model_mat[0].xyz, model_mat[1].xyz), model_mat[2].xyz) < 0.0); + geom_in.inverted = int(dot(cross(model_mat[0].xyz, model_mat[1].xyz), model_mat[2].xyz) < 0.0); /* This is slow and run per vertex, but it's still faster than * doing it per instance on CPU and sending it on via instance attribute. */ @@ -39,13 +27,11 @@ void main() /* TODO: FIX: there is still a problem with this vector * when the bone is scaled or in persp mode. But it's * barely visible at the outline corners. */ - ssNor = normalize(normal_world_to_view(normal_mat * snor).xy); + geom_in.ssNor = normalize(normal_world_to_view(normal_mat * snor).xy); - ssPos = proj(pPos); + geom_in.ssPos = proj(geom_in.pPos); - vColSize = bone_color; + geom_in.vColSize = bone_color; -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(worldPosition.xyz); -#endif + view_clipping_distances(world_pos.xyz); } diff --git a/source/blender/draw/engines/overlay/shaders/armature_shape_solid_frag.glsl b/source/blender/draw/engines/overlay/shaders/armature_shape_solid_frag.glsl index 26796c82f66..8e1768846dc 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_shape_solid_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_shape_solid_frag.glsl @@ -1,12 +1,4 @@ -uniform float alpha = 0.6; - -in vec4 finalColor; -flat in int inverted; - -layout(location = 0) out vec4 fragColor; -layout(location = 1) out vec4 lineOutput; - void main() { /* Manual back-face culling. Not ideal for performance diff --git a/source/blender/draw/engines/overlay/shaders/armature_shape_solid_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_shape_solid_vert.glsl index 5979a877681..cdbe8c3d7df 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_shape_solid_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_shape_solid_vert.glsl @@ -1,13 +1,6 @@ -/* ---- Instantiated Attrs ---- */ -in vec3 pos; -in vec3 nor; - -/* ---- Per instance Attrs ---- */ -in mat4 inst_obmat; - -out vec4 finalColor; -flat out int inverted; +#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) void main() { @@ -31,10 +24,8 @@ void main() finalColor.rgb = mix(state_color.rgb, bone_color.rgb, fac * fac); finalColor.a = 1.0; - vec4 worldPosition = model_mat * vec4(pos, 1.0); - gl_Position = ViewProjectionMatrix * worldPosition; + vec4 world_pos = model_mat * vec4(pos, 1.0); + gl_Position = ViewProjectionMatrix * world_pos; -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(worldPosition.xyz); -#endif + view_clipping_distances(world_pos.xyz); } diff --git a/source/blender/draw/engines/overlay/shaders/armature_shape_wire_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_shape_wire_vert.glsl index 0bf21cbaaac..cee86956c43 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_shape_wire_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_shape_wire_vert.glsl @@ -1,14 +1,6 @@ -/* ---- Instantiated Attrs ---- */ -in vec3 pos; -in vec3 nor; - -/* ---- Per instance Attrs ---- */ -in mat4 inst_obmat; - -flat out vec4 finalColor; -flat out vec2 edgeStart; -noperspective out vec2 edgePos; +#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) void main() { @@ -23,7 +15,5 @@ void main() edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy; -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(world_pos); -#endif + view_clipping_distances(world_pos); } diff --git a/source/blender/draw/engines/overlay/shaders/armature_sphere_outline_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_sphere_outline_vert.glsl index 934485359b3..31369e0c3df 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_sphere_outline_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_sphere_outline_vert.glsl @@ -1,13 +1,6 @@ -/* ---- Instantiated Attrs ---- */ -in vec2 pos; - -/* ---- Per instance Attrs ---- */ -in mat4 inst_obmat; - -flat out vec4 finalColor; -flat out vec2 edgeStart; -noperspective out vec2 edgePos; +#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) /* project to screen space */ vec2 proj(vec4 pos) @@ -70,14 +63,12 @@ void main() /* Offset away from the center to avoid overlap with solid shape. */ vec2 ofs_dir = normalize(proj(gl_Position) - proj(center)); - gl_Position.xy += ofs_dir * sizeViewportInv.xy * gl_Position.w; + gl_Position.xy += ofs_dir * drw_view.viewport_size_inverse * gl_Position.w; edgeStart = edgePos = proj(gl_Position); finalColor = vec4(bone_color.rgb, 1.0); -#ifdef USE_WORLD_CLIP_PLANES - vec4 worldPosition = model_mat * vec4(cam_pos0, 1.0); - world_clip_planes_calc_clip_distance(worldPosition.xyz); -#endif + vec4 world_pos = model_mat * vec4(cam_pos0, 1.0); + view_clipping_distances(world_pos.xyz); } diff --git a/source/blender/draw/engines/overlay/shaders/armature_sphere_solid_frag.glsl b/source/blender/draw/engines/overlay/shaders/armature_sphere_solid_frag.glsl index 0925901a9c9..e60b6e94492 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_sphere_solid_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_sphere_solid_frag.glsl @@ -1,18 +1,5 @@ -uniform float alpha = 0.4; - -flat in vec3 finalStateColor; -flat in vec3 finalBoneColor; -flat in mat4 sphereMatrix; -in vec3 viewPosition; - -#ifdef GL_ARB_conservative_depth -/* Saves a lot of overdraw! */ -layout(depth_greater) out float gl_FragDepth; -#endif - -layout(location = 0) out vec4 fragColor; -layout(location = 1) out vec4 lineOutput; +#pragma BLENDER_REQUIRE(common_view_lib.glsl) void main() { diff --git a/source/blender/draw/engines/overlay/shaders/armature_sphere_solid_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_sphere_solid_vert.glsl index e6fa29ce851..abbaad8cd10 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_sphere_solid_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_sphere_solid_vert.glsl @@ -1,15 +1,6 @@ -/* ---- Instantiated Attrs ---- */ -in vec2 pos; - -/* ---- Per instance Attrs ---- */ -in vec4 color; -in mat4 inst_obmat; - -flat out vec3 finalStateColor; -flat out vec3 finalBoneColor; -flat out mat4 sphereMatrix; -out vec3 viewPosition; +#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) /* Sphere radius */ const float rad = 0.05; @@ -80,8 +71,6 @@ void main() finalStateColor = state_color.xyz; finalBoneColor = bone_color.xyz; -#ifdef USE_WORLD_CLIP_PLANES - vec4 worldPosition = model_mat * pos_4d; - world_clip_planes_calc_clip_distance(worldPosition.xyz); -#endif + vec4 world_pos = model_mat * pos_4d; + view_clipping_distances(world_pos.xyz); } diff --git a/source/blender/draw/engines/overlay/shaders/armature_stick_frag.glsl b/source/blender/draw/engines/overlay/shaders/armature_stick_frag.glsl index 85136672180..2e42cdf0517 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_stick_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_stick_frag.glsl @@ -1,13 +1,4 @@ -uniform float alpha = 1.0; - -noperspective in float colorFac; -flat in vec4 finalWireColor; -flat in vec4 finalInnerColor; - -layout(location = 0) out vec4 fragColor; -layout(location = 1) out vec4 lineOutput; - void main() { float fac = smoothstep(1.0, 0.2, colorFac); diff --git a/source/blender/draw/engines/overlay/shaders/armature_stick_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_stick_vert.glsl index 0a2598fb6b7..b5edcd2858b 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_stick_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_stick_vert.glsl @@ -1,8 +1,8 @@ -/* ---- Instantiated Attrs ---- */ -in vec2 pos; /* bone aligned screen space */ -in uint flag; +#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +/* TODO(@fclem): Share definition with C code. */ #define COL_WIRE 1u /* (1 << 0) */ #define COL_HEAD 2u /* (1 << 1) */ #define COL_TAIL 4u /* (1 << 2) */ @@ -12,22 +12,9 @@ in uint flag; #define POS_TAIL 32u /* (1 << 5) */ /* UNUSED */ #define POS_BONE 64u /* (1 << 6) */ -/* ---- Per instance Attrs ---- */ -in vec3 boneStart; -in vec3 boneEnd; -in vec4 wireColor; /* alpha encode if we do wire. If 0.0 we don't. */ -in vec4 boneColor; /* alpha encode if we do bone. If 0.0 we don't. */ -in vec4 headColor; /* alpha encode if we do head. If 0.0 we don't. */ -in vec4 tailColor; /* alpha encode if we do tail. If 0.0 we don't. */ - -#define do_wire (wireColor.a > 0.0) #define is_head bool(flag & POS_HEAD) #define is_bone bool(flag & POS_BONE) -noperspective out float colorFac; -flat out vec4 finalWireColor; -flat out vec4 finalInnerColor; - /* project to screen space */ vec2 proj(vec4 pos) { @@ -77,12 +64,9 @@ void main() if (finalInnerColor.a > 0.0) { float stick_size = sizePixel * 5.0; gl_Position = (is_head) ? p0 : p1; - gl_Position.xy += stick_size * (vpos * sizeViewportInv.xy); + gl_Position.xy += stick_size * (vpos * drw_view.viewport_size_inverse); gl_Position.z += (is_bone) ? 0.0 : 1e-6; /* Avoid Z fighting of head/tails. */ - -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((is_head ? boneStart_4d : boneEnd_4d).xyz); -#endif + view_clipping_distances((is_head ? boneStart_4d : boneEnd_4d).xyz); } else { gl_Position = vec4(0.0); diff --git a/source/blender/draw/engines/overlay/shaders/armature_wire_frag.glsl b/source/blender/draw/engines/overlay/shaders/armature_wire_frag.glsl index 55278515f74..2c454a8becd 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_wire_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_wire_frag.glsl @@ -1,12 +1,5 @@ -uniform float alpha = 1.0; - -flat in vec4 finalColor; -flat in vec2 edgeStart; -noperspective in vec2 edgePos; - -layout(location = 0) out vec4 fragColor; -layout(location = 1) out vec4 lineOutput; +#pragma BLENDER_REQUIRE(common_view_lib.glsl) void main() { diff --git a/source/blender/draw/engines/overlay/shaders/armature_wire_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_wire_vert.glsl index d6d6cb6e024..c89d0249e4f 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_wire_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_wire_vert.glsl @@ -1,22 +1,16 @@ -in vec3 color; -in vec3 pos; - -flat out vec4 finalColor; -flat out vec2 edgeStart; -noperspective out vec2 edgePos; +#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) void main() { - finalColor.rgb = color; + finalColor.rgb = color.rgb; finalColor.a = 1.0; - vec3 worldPosition = point_object_to_world(pos); - gl_Position = point_world_to_ndc(worldPosition); + vec3 world_pos = point_object_to_world(pos); + gl_Position = point_world_to_ndc(world_pos); edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy; -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(worldPosition); -#endif + view_clipping_distances(world_pos); } diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_analysis_frag.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_analysis_frag.glsl index 8d96c0e418f..430ace8726a 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_mesh_analysis_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_analysis_frag.glsl @@ -1,6 +1,3 @@ -out vec4 fragColor; - -in vec4 weightColor; void main() { diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_analysis_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_analysis_vert.glsl index b89a3f407f9..1e163dc9a9a 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_mesh_analysis_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_analysis_vert.glsl @@ -1,10 +1,6 @@ -in vec3 pos; -in float weight; - -uniform sampler1D weightTex; - -out vec4 weightColor; +#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) vec3 weight_to_rgb(float t) { @@ -29,7 +25,5 @@ void main() gl_Position = point_world_to_ndc(world_pos); weightColor = vec4(weight_to_rgb(weight), 1.0); -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(world_pos); -#endif + view_clipping_distances(world_pos); } diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_common_lib.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_common_lib.glsl index 418c7bceb63..72b0a43cdb4 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_mesh_common_lib.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_common_lib.glsl @@ -1,7 +1,4 @@ -uniform bool selectFaces = true; -uniform bool selectEdges = true; - vec4 EDIT_MESH_edge_color_outer(int edge_flag, int face_flag, float crease, float bweight) { vec4 color = vec4(0.0); diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_frag.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_frag.glsl index 1fe20d1cb1f..2fd155f715c 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_mesh_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_frag.glsl @@ -12,35 +12,33 @@ #define GRID_LINE_SMOOTH_START (0.5 - DISC_RADIUS) #define GRID_LINE_SMOOTH_END (0.5 + DISC_RADIUS) -uniform sampler2D depthTex; -uniform float alpha = 1.0; - -flat in vec4 finalColorOuter_f; -in vec4 finalColor_f; -noperspective in float edgeCoord_f; - -out vec4 FragColor; - bool test_occlusion() { return gl_FragCoord.z > texelFetch(depthTex, ivec2(gl_FragCoord.xy), 0).r; } +float edge_step(float dist) +{ + if (do_smooth_wire) { + return smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, dist); + } + else { + return step(0.5, dist); + } +} + void main() { - float dist = abs(edgeCoord_f) - max(sizeEdge - 0.5, 0.0); + float dist = abs(geometry_out.edgeCoord) - max(sizeEdge - 0.5, 0.0); float dist_outer = dist - max(sizeEdge, 1.0); -#ifdef USE_SMOOTH_WIRE - float mix_w = smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, dist); - float mix_w_outer = smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, dist_outer); -#else - float mix_w = step(0.5, dist); - float mix_w_outer = step(0.5, dist_outer); -#endif + float mix_w = edge_step(dist); + float mix_w_outer = edge_step(dist_outer); /* Line color & alpha. */ - FragColor = mix(finalColorOuter_f, finalColor_f, 1.0 - mix_w * finalColorOuter_f.a); + fragColor = mix(geometry_out.finalColorOuter, + geometry_out.finalColor, + 1.0 - mix_w * geometry_out.finalColorOuter.a); /* Line edges shape. */ - FragColor.a *= 1.0 - (finalColorOuter_f.a > 0.0 ? mix_w_outer : mix_w); + fragColor.a *= 1.0 - (geometry_out.finalColorOuter.a > 0.0 ? mix_w_outer : mix_w); - FragColor.a *= test_occlusion() ? alpha : 1.0; + fragColor.a *= test_occlusion() ? alpha : 1.0; } diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_geom.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_geom.glsl index 66fa85685e2..65615524927 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_mesh_geom.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_geom.glsl @@ -1,26 +1,18 @@ -layout(lines) in; -layout(triangle_strip, max_vertices = 4) out; - -in vec4 finalColor[2]; -in vec4 finalColorOuter[2]; -in int selectOverride[2]; - -flat out vec4 finalColorOuter_f; -out vec4 finalColor_f; -noperspective out float edgeCoord_f; +#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) void do_vertex(vec4 color, vec4 pos, float coord, vec2 offset) { - finalColor_f = color; - edgeCoord_f = coord; + geometry_out.finalColor = color; + geometry_out.edgeCoord = coord; gl_Position = pos; /* Multiply offset by 2 because gl_Position range is [-1..1]. */ gl_Position.xy += offset * 2.0 * pos.w; /* Correct but fails due to an AMD compiler bug, see: T62792. * Do inline instead. */ #if 0 - world_clip_planes_set_clip_distance(gl_in[i].gl_ClipDistance); + view_clipping_distances_set(gl_in[i]); #endif EmitVertex(); } @@ -54,33 +46,30 @@ void main() vec2 line = ss_pos[0] - ss_pos[1]; line = abs(line) * sizeViewport.xy; - finalColorOuter_f = finalColorOuter[0]; + geometry_out.finalColorOuter = geometry_in[0].finalColorOuter; float half_size = sizeEdge; /* Enlarge edge for flag display. */ - half_size += (finalColorOuter_f.a > 0.0) ? max(sizeEdge, 1.0) : 0.0; + half_size += (geometry_out.finalColorOuter.a > 0.0) ? max(sizeEdge, 1.0) : 0.0; -#ifdef USE_SMOOTH_WIRE - /* Add 1 px for AA */ - half_size += 0.5; -#endif + if (do_smooth_wire) { + /* Add 1 px for AA */ + half_size += 0.5; + } - vec3 edge_ofs = vec3(half_size * sizeViewportInv.xy, 0.0); + vec3 edge_ofs = vec3(half_size * drw_view.viewport_size_inverse, 0.0); bool horizontal = line.x > line.y; edge_ofs = (horizontal) ? edge_ofs.zyz : edge_ofs.xzz; -#ifdef USE_WORLD_CLIP_PLANES /* Due to an AMD glitch, this line was moved out of the `do_vertex` * function (see T62792). */ - world_clip_planes_set_clip_distance(gl_in[0].gl_ClipDistance); -#endif - do_vertex(finalColor[0], pos0, half_size, edge_ofs.xy); - do_vertex(finalColor[0], pos0, -half_size, -edge_ofs.xy); + view_clipping_distances_set(gl_in[0]); + do_vertex(geometry_in[0].finalColor, pos0, half_size, edge_ofs.xy); + do_vertex(geometry_in[0].finalColor, pos0, -half_size, -edge_ofs.xy); -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance); -#endif - vec4 final_color = (selectOverride[0] == 0) ? finalColor[1] : finalColor[0]; + view_clipping_distances_set(gl_in[1]); + vec4 final_color = (geometry_in[0].selectOverride == 0) ? geometry_in[1].finalColor : + geometry_in[0].finalColor; do_vertex(final_color, pos1, half_size, edge_ofs.xy); do_vertex(final_color, pos1, -half_size, -edge_ofs.xy); 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 d370943db03..6ff8d0665d1 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,16 +1,6 @@ -uniform float normalSize; -uniform float normalScreenSize; -uniform bool isConstantScreenSizeNormals; -uniform sampler2D depthTex; -uniform float alpha = 1.0; - -in vec3 pos; -in vec4 lnor; -in vec4 vnor; -in vec4 norAndFlag; - -flat out vec4 finalColor; +#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) bool test_occlusion() { @@ -75,7 +65,5 @@ void main() finalColor.a *= (test_occlusion()) ? alpha : 1.0; -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(world_pos); -#endif + view_clipping_distances(world_pos); } diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_skin_root_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_skin_root_vert.glsl index 944eb41058e..f1fbdac7847 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_mesh_skin_root_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_skin_root_vert.glsl @@ -1,12 +1,6 @@ -/* ---- Instantiated Attrs ---- */ -in vec3 pos; - -/* ---- Per instance Attrs ---- */ -in float size; -in vec3 local_pos; - -flat out vec4 finalColor; +#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) void main() { @@ -19,7 +13,5 @@ void main() /* Manual stipple: one segment out of 2 is transparent. */ finalColor = ((gl_VertexID & 1) == 0) ? colorSkinRoot : vec4(0.0); -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(pos_4d.xyz); -#endif + view_clipping_distances(pos_4d.xyz); } diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl index 5cee976f9a8..77826e26c8a 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl @@ -1,26 +1,13 @@ -uniform sampler2D depthTex; -uniform float alpha = 1.0; -uniform ivec4 dataMask = ivec4(0xFF); - -in ivec4 data; -in vec3 pos; -#ifndef FACEDOT -in vec3 vnor; -#else -in vec4 norAndFlag; -# define vnor norAndFlag.xyz -#endif +#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(edit_mesh_common_lib.glsl) -out vec4 finalColor; -#ifdef VERT -out float vertexCrease; -#endif #ifdef EDGE -out vec4 finalColorOuter; -#endif -#ifdef USE_GEOM_SHADER -out int selectOverride; +/* Ugly but needed to keep the same vertex shader code for other passes. */ +# define finalColor geometry_in.finalColor +# define finalColorOuter geometry_in.finalColorOuter +# define selectOverride geometry_in.selectOverride #endif bool test_occlusion() @@ -108,7 +95,5 @@ void main() finalColor.rgb = non_linear_blend_color(colorEditMeshMiddle.rgb, finalColor.rgb, facing); #endif -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(world_pos); -#endif + view_clipping_distances(world_pos); } diff --git a/source/blender/draw/engines/overlay/shaders/extra_lightprobe_grid_vert.glsl b/source/blender/draw/engines/overlay/shaders/extra_lightprobe_grid_vert.glsl index 1f3a23324bb..8006c51a946 100644 --- a/source/blender/draw/engines/overlay/shaders/extra_lightprobe_grid_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/extra_lightprobe_grid_vert.glsl @@ -1,6 +1,6 @@ -uniform sampler2D depthBuffer; -uniform vec4 gridModelMatrix[4]; +uniform depth2D depthBuffer; +uniform mat4 gridModelMatrix; uniform bool isTransform; out vec4 finalColor; @@ -27,8 +27,7 @@ vec4 color_from_id(float color_id) void main() { - mat4 model_mat = mat4( - gridModelMatrix[0], gridModelMatrix[1], gridModelMatrix[2], gridModelMatrix[3]); + mat4 model_mat = gridModelMatrix; model_mat[0][3] = model_mat[1][3] = model_mat[2][3] = 0.0; model_mat[3][3] = 1.0; float color_id = gridModelMatrix[3].w; diff --git a/source/blender/draw/engines/overlay/shaders/grid_frag.glsl b/source/blender/draw/engines/overlay/shaders/grid_frag.glsl index 9feca644bd3..4a9b8d15528 100644 --- a/source/blender/draw/engines/overlay/shaders/grid_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/grid_frag.glsl @@ -12,7 +12,7 @@ uniform vec3 planeAxes; uniform float gridDistance; uniform vec3 gridSize; uniform float lineKernel = 0.0; -uniform sampler2D depthBuffer; +uniform depth2D depthBuffer; uniform int gridFlag; uniform float zoomFactor; @@ -49,7 +49,7 @@ float get_grid(vec2 co, vec2 fwidthCos, float grid_size) { float half_size = grid_size / 2.0; /* triangular wave pattern, amplitude is [0, half_size] */ - vec2 grid_domain = abs(mod(co + half_size, grid_size) - half_size); + vec2 grid_domain = abs(mod(co + half_size, vec2(grid_size)) - half_size); /* modulate by the absolute rate of change of the coordinates * (make lines have the same width under perspective) */ grid_domain /= fwidthCos; diff --git a/source/blender/draw/engines/overlay/shaders/infos/armature_info.hh b/source/blender/draw/engines/overlay/shaders/infos/armature_info.hh new file mode 100644 index 00000000000..f417fbe1fd4 --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/infos/armature_info.hh @@ -0,0 +1,262 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(overlay_frag_output) + .fragment_out(0, Type::VEC4, "fragColor") + .fragment_out(1, Type::VEC4, "lineOutput"); + +GPU_SHADER_INTERFACE_INFO(overlay_armature_wire_iface, "") + .flat(Type::VEC4, "finalColor") + .flat(Type::VEC2, "edgeStart") + .no_perspective(Type::VEC2, "edgePos"); + +GPU_SHADER_CREATE_INFO(overlay_armature_common) + .push_constant(Type::FLOAT, "alpha") + .additional_info("draw_view"); + +/* -------------------------------------------------------------------- */ +/** \name Armature Sphere + * \{ */ + +GPU_SHADER_CREATE_INFO(overlay_armature_sphere_outline) + .do_static_compilation(true) + .vertex_in(0, Type::VEC2, "pos") + /* Per instance. */ + .vertex_in(1, Type::MAT4, "inst_obmat") + .vertex_out(overlay_armature_wire_iface) + .vertex_source("armature_sphere_outline_vert.glsl") + .fragment_source("armature_wire_frag.glsl") + .additional_info("overlay_frag_output", "overlay_armature_common", "draw_globals"); + +GPU_SHADER_CREATE_INFO(overlay_armature_sphere_outline_clipped) + .do_static_compilation(true) + .additional_info("overlay_armature_sphere_outline", "drw_clipped"); + +GPU_SHADER_INTERFACE_INFO(overlay_armature_sphere_solid_iface, "") + .flat(Type::VEC3, "finalStateColor") + .flat(Type::VEC3, "finalBoneColor") + .flat(Type::MAT4, "sphereMatrix") + .smooth(Type::VEC3, "viewPosition"); + +GPU_SHADER_CREATE_INFO(overlay_armature_sphere_solid) + .do_static_compilation(true) + .vertex_in(0, Type::VEC2, "pos") + /* Per instance. */ + .vertex_in(1, Type::MAT4, "inst_obmat") + .vertex_in(2, Type::VEC4, "color") + // .depth_layout(DepthLayout::GREATER) /* TODO */ + .vertex_out(overlay_armature_sphere_solid_iface) + .vertex_source("armature_sphere_solid_vert.glsl") + .fragment_source("armature_sphere_solid_frag.glsl") + .additional_info("overlay_frag_output", "overlay_armature_common", "draw_globals"); + +GPU_SHADER_CREATE_INFO(overlay_armature_sphere_solid_clipped) + .do_static_compilation(true) + .additional_info("overlay_armature_sphere_solid", "drw_clipped"); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Armature Shapes + * \{ */ + +GPU_SHADER_INTERFACE_INFO(overlay_armature_shape_outline_iface, "geom_in") + .smooth(Type::VEC4, "pPos") + .smooth(Type::VEC3, "vPos") + .smooth(Type::VEC2, "ssPos") + .smooth(Type::VEC2, "ssNor") + .smooth(Type::VEC4, "vColSize") + .flat(Type::INT, "inverted"); + +GPU_SHADER_CREATE_INFO(overlay_armature_shape_outline) + .do_static_compilation(true) + .vertex_in(0, Type::VEC3, "pos") + .vertex_in(1, Type::VEC3, "snor") + /* Per instance. */ + .vertex_in(2, Type::VEC4, "color") + .vertex_in(3, Type::MAT4, "inst_obmat") + .vertex_out(overlay_armature_shape_outline_iface) + .geometry_layout(PrimitiveIn::LINES_ADJACENCY, PrimitiveOut::LINE_STRIP, 2) + .geometry_out(overlay_armature_wire_iface) + .vertex_source("armature_shape_outline_vert.glsl") + .geometry_source("armature_shape_outline_geom.glsl") + .fragment_source("armature_wire_frag.glsl") + .additional_info("overlay_frag_output", "overlay_armature_common", "draw_globals"); + +GPU_SHADER_CREATE_INFO(overlay_armature_shape_outline_clipped) + .do_static_compilation(true) + .additional_info("overlay_armature_shape_outline", "drw_clipped"); + +GPU_SHADER_INTERFACE_INFO(overlay_armature_shape_solid_iface, "") + .smooth(Type::VEC4, "finalColor") + .flat(Type::INT, "inverted"); + +GPU_SHADER_CREATE_INFO(overlay_armature_shape_solid) + .do_static_compilation(true) + .vertex_in(0, Type::VEC3, "pos") + .vertex_in(1, Type::VEC3, "nor") + /* Per instance. */ + .vertex_in(2, Type::MAT4, "inst_obmat") + .depth_write(DepthWrite::GREATER) + .vertex_out(overlay_armature_shape_solid_iface) + .vertex_source("armature_shape_solid_vert.glsl") + .fragment_source("armature_shape_solid_frag.glsl") + .additional_info("overlay_frag_output", "overlay_armature_common", "draw_globals"); + +GPU_SHADER_CREATE_INFO(overlay_armature_shape_solid_clipped) + .do_static_compilation(true) + .additional_info("overlay_armature_shape_solid", "drw_clipped"); + +GPU_SHADER_CREATE_INFO(overlay_armature_shape_wire) + .do_static_compilation(true) + .vertex_in(0, Type::VEC3, "pos") + .vertex_in(1, Type::VEC3, "nor") + /* Per instance. */ + .vertex_in(2, Type::MAT4, "inst_obmat") + .vertex_out(overlay_armature_wire_iface) + .vertex_source("armature_shape_wire_vert.glsl") + .fragment_source("armature_wire_frag.glsl") + .additional_info("overlay_frag_output", "overlay_armature_common", "draw_globals"); + +GPU_SHADER_CREATE_INFO(overlay_armature_shape_wire_clipped) + .do_static_compilation(true) + .additional_info("overlay_armature_shape_wire", "drw_clipped"); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Armature Envelope + * \{ */ + +GPU_SHADER_CREATE_INFO(overlay_armature_envelope_outline) + .do_static_compilation(true) + .vertex_in(0, Type::VEC2, "pos0") + .vertex_in(1, Type::VEC2, "pos1") + .vertex_in(2, Type::VEC2, "pos2") + /* Per instance. */ + .vertex_in(3, Type::VEC4, "headSphere") + .vertex_in(4, Type::VEC4, "tailSphere") + .vertex_in(5, Type::VEC4, "outlineColorSize") + .vertex_in(6, Type::VEC3, "xAxis") + .vertex_out(overlay_armature_wire_iface) + .vertex_source("armature_envelope_outline_vert.glsl") + .fragment_source("armature_wire_frag.glsl") + .additional_info("overlay_frag_output", "overlay_armature_common", "draw_globals"); + +GPU_SHADER_CREATE_INFO(overlay_armature_envelope_outline_clipped) + .do_static_compilation(true) + .additional_info("overlay_armature_envelope_outline", "drw_clipped"); + +GPU_SHADER_INTERFACE_INFO(overlay_armature_envelope_solid_iface, "") + .flat(Type::VEC3, "finalStateColor") + .flat(Type::VEC3, "finalBoneColor") + .smooth(Type::VEC3, "normalView"); + +GPU_SHADER_CREATE_INFO(overlay_armature_envelope_solid) + .do_static_compilation(true) + .vertex_in(0, Type::VEC3, "pos") + /* Per instance. Assumed to be in world coordinate already. */ + .vertex_in(1, Type::VEC4, "headSphere") + .vertex_in(2, Type::VEC4, "tailSphere") + .vertex_in(3, Type::VEC3, "xAxis") + .vertex_in(4, Type::VEC3, "stateColor") + .vertex_in(5, Type::VEC3, "boneColor") + .vertex_out(overlay_armature_envelope_solid_iface) + .push_constant(Type::BOOL, "isDistance") + .vertex_source("armature_envelope_solid_vert.glsl") + .fragment_source("armature_envelope_solid_frag.glsl") + .additional_info("overlay_frag_output", "overlay_armature_common"); + +GPU_SHADER_CREATE_INFO(overlay_armature_envelope_solid_clipped) + .do_static_compilation(true) + .additional_info("overlay_armature_envelope_solid", "drw_clipped"); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Armature Stick + * \{ */ + +GPU_SHADER_INTERFACE_INFO(overlay_armature_stick_iface, "") + .no_perspective(Type::FLOAT, "colorFac") + .flat(Type::VEC4, "finalWireColor") + .flat(Type::VEC4, "finalInnerColor"); + +GPU_SHADER_CREATE_INFO(overlay_armature_stick) + .do_static_compilation(true) + /* Bone aligned screen space. */ + .vertex_in(0, Type::VEC2, "pos") + .vertex_in(1, Type::UINT, "flag") + /* Per instance. Assumed to be in world coordinate already. */ + .vertex_in(2, Type::VEC3, "boneStart") + .vertex_in(3, Type::VEC3, "boneEnd") + /* alpha encode if we do wire. If 0.0 we don't. */ + .vertex_in(4, Type::VEC4, "wireColor") + .vertex_in(5, Type::VEC4, "boneColor") + .vertex_in(6, Type::VEC4, "headColor") + .vertex_in(7, Type::VEC4, "tailColor") + .define("do_wire", "(wireColor.a > 0.0)") + .vertex_out(overlay_armature_stick_iface) + .vertex_source("armature_stick_vert.glsl") + .fragment_source("armature_stick_frag.glsl") + .additional_info("overlay_frag_output", "overlay_armature_common", "draw_globals"); + +GPU_SHADER_CREATE_INFO(overlay_armature_stick_clipped) + .do_static_compilation(true) + .additional_info("overlay_armature_stick", "drw_clipped"); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Armature Degrees of Freedom + * \{ */ + +GPU_SHADER_CREATE_INFO(overlay_armature_dof) + .vertex_in(0, Type::VEC2, "pos") + /* Per instance. Assumed to be in world coordinate already. */ + .vertex_in(1, Type::VEC4, "color") + .vertex_in(2, Type::MAT4, "inst_obmat") + .vertex_out(overlay_armature_wire_iface) + .vertex_source("armature_dof_vert.glsl") + .additional_info("overlay_frag_output", "overlay_armature_common", "draw_globals"); + +GPU_SHADER_CREATE_INFO(overlay_armature_dof_wire) + .do_static_compilation(true) + .fragment_source("armature_dof_solid_frag.glsl") + .additional_info("overlay_armature_dof"); + +GPU_SHADER_CREATE_INFO(overlay_armature_dof_wire_clipped) + .do_static_compilation(true) + .additional_info("overlay_armature_dof_wire", "drw_clipped"); + +GPU_SHADER_CREATE_INFO(overlay_armature_dof_solid) + .do_static_compilation(true) + .fragment_source("armature_dof_solid_frag.glsl") + .additional_info("overlay_armature_dof"); + +GPU_SHADER_CREATE_INFO(overlay_armature_dof_solid_clipped) + .do_static_compilation(true) + .additional_info("overlay_armature_dof_solid", "drw_clipped"); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Armature Wire + * \{ */ + +GPU_SHADER_CREATE_INFO(overlay_armature_wire) + .do_static_compilation(true) + .vertex_in(0, Type::VEC3, "pos") + .vertex_in(1, Type::VEC4, "color") + .push_constant(Type::FLOAT, "alpha") + .vertex_out(overlay_armature_wire_iface) + .vertex_source("armature_wire_vert.glsl") + .fragment_source("armature_wire_frag.glsl") + .additional_info("overlay_frag_output", "draw_mesh", "draw_globals"); + +GPU_SHADER_CREATE_INFO(overlay_armature_wire_clipped) + .do_static_compilation(true) + .additional_info("overlay_armature_wire", "drw_clipped"); + +/** \} */ diff --git a/source/blender/draw/engines/overlay/shaders/infos/edit_mode_info.hh b/source/blender/draw/engines/overlay/shaders/infos/edit_mode_info.hh new file mode 100644 index 00000000000..c756b9473a3 --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/infos/edit_mode_info.hh @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +/* -------------------------------------------------------------------- */ +/** \name Edit Mesh + * \{ */ + +GPU_SHADER_INTERFACE_INFO(overlay_edit_mesh_color_iface, "").flat(Type::VEC4, "finalColor"); + +GPU_SHADER_CREATE_INFO(overlay_edit_mesh_common) + .define("blender_srgb_to_framebuffer_space(a)", "a") + .sampler(0, ImageType::DEPTH_2D, "depthTex") + .fragment_out(0, Type::VEC4, "fragColor") + .push_constant(Type::BOOL, "selectFaces") + .push_constant(Type::BOOL, "selectEdges") + .push_constant(Type::FLOAT, "alpha") + .push_constant(Type::IVEC4, "dataMask") + .vertex_source("edit_mesh_vert.glsl") + .additional_info("draw_modelmat", "draw_globals"); + +GPU_SHADER_INTERFACE_INFO(overlay_edit_mesh_vert_iface, "") + .smooth(Type::VEC4, "finalColor") + .smooth(Type::FLOAT, "vertexCrease"); + +GPU_SHADER_CREATE_INFO(overlay_edit_mesh_vert) + .do_static_compilation(true) + .builtins(BuiltinBits::POINT_SIZE) + .define("srgbTarget", "false") /* Colors are already in linear space. */ + .define("VERT") + .vertex_in(0, Type::VEC3, "pos") + .vertex_in(1, Type::IVEC4, "data") + .vertex_in(2, Type::VEC3, "vnor") + .vertex_out(overlay_edit_mesh_vert_iface) + .fragment_source("gpu_shader_point_varying_color_frag.glsl") + .additional_info("overlay_edit_mesh_common"); + +GPU_SHADER_INTERFACE_INFO(overlay_edit_mesh_edge_iface, "geometry_in") + .smooth(Type::VEC4, "finalColor") + .smooth(Type::VEC4, "finalColorOuter") + .smooth(Type::INT, "selectOverride"); + +GPU_SHADER_INTERFACE_INFO(overlay_edit_mesh_edge_geom_iface, "geometry_out") + .smooth(Type::VEC4, "finalColor") + .flat(Type::VEC4, "finalColorOuter") + .no_perspective(Type::FLOAT, "edgeCoord"); + +GPU_SHADER_CREATE_INFO(overlay_edit_mesh_edge) + .do_static_compilation(true) + .define("EDGE") + .vertex_in(0, Type::VEC3, "pos") + .vertex_in(1, Type::IVEC4, "data") + .vertex_in(2, Type::VEC3, "vnor") + .push_constant(Type::BOOL, "do_smooth_wire") + .vertex_out(overlay_edit_mesh_edge_iface) + .geometry_out(overlay_edit_mesh_edge_geom_iface) + .geometry_layout(PrimitiveIn::LINES, PrimitiveOut::TRIANGLE_STRIP, 4) + .geometry_source("edit_mesh_geom.glsl") + .fragment_source("edit_mesh_frag.glsl") + .additional_info("overlay_edit_mesh_common"); + +GPU_SHADER_CREATE_INFO(overlay_edit_mesh_edge_flat) + .do_static_compilation(true) + .define("FLAT") + .additional_info("overlay_edit_mesh_edge"); + +GPU_SHADER_CREATE_INFO(overlay_edit_mesh_face) + .do_static_compilation(true) + .define("srgbTarget", "false") /* Colors are already in linear space. */ + .define("FACE") + .vertex_in(0, Type::VEC3, "pos") + .vertex_in(1, Type::IVEC4, "data") + .vertex_in(2, Type::VEC3, "vnor") + .vertex_out(overlay_edit_mesh_color_iface) + .fragment_source("gpu_shader_3D_smooth_color_frag.glsl") + .additional_info("overlay_edit_mesh_common"); + +GPU_SHADER_CREATE_INFO(overlay_edit_mesh_facedot) + .do_static_compilation(true) + .define("FACEDOT") + .vertex_in(0, Type::VEC3, "pos") + .vertex_in(1, Type::IVEC4, "data") + .vertex_in(2, Type::VEC4, "norAndFlag") + .define("vnor", "norAndFlag.xyz") + .vertex_out(overlay_edit_mesh_color_iface) + .fragment_source("gpu_shader_point_varying_color_frag.glsl") + .additional_info("overlay_edit_mesh_common"); + +GPU_SHADER_CREATE_INFO(overlay_edit_mesh_normal) + .do_static_compilation(true) + .define("srgbTarget", "false") /* Colors are already in linear space. */ + .vertex_in(0, Type::VEC3, "pos") + .vertex_in(1, Type::VEC4, "lnor") + .vertex_in(2, Type::VEC4, "vnor") + .vertex_in(3, Type::VEC4, "norAndFlag") + .sampler(0, ImageType::DEPTH_2D, "depthTex") + .push_constant(Type::FLOAT, "normalSize") + .push_constant(Type::FLOAT, "normalScreenSize") + .push_constant(Type::FLOAT, "alpha") + .push_constant(Type::BOOL, "isConstantScreenSizeNormals") + .vertex_out(overlay_edit_mesh_color_iface) + .fragment_out(0, Type::VEC4, "fragColor") + .vertex_source("edit_mesh_normal_vert.glsl") + .fragment_source("gpu_shader_flat_color_frag.glsl") + .additional_info("draw_modelmat_instanced_attr", "draw_globals"); + +GPU_SHADER_INTERFACE_INFO(overlay_edit_mesh_analysis_iface, "").smooth(Type::VEC4, "weightColor"); + +GPU_SHADER_CREATE_INFO(overlay_edit_mesh_analysis) + .do_static_compilation(true) + .vertex_in(0, Type::VEC3, "pos") + .vertex_in(1, Type::FLOAT, "weight") + .sampler(0, ImageType::FLOAT_1D, "weightTex") + .fragment_out(0, Type::VEC4, "fragColor") + .vertex_out(overlay_edit_mesh_analysis_iface) + .vertex_source("edit_mesh_analysis_vert.glsl") + .fragment_source("edit_mesh_analysis_frag.glsl") + .additional_info("draw_modelmat"); + +GPU_SHADER_CREATE_INFO(overlay_edit_mesh_skin_root) + .do_static_compilation(true) + .define("srgbTarget", "false") /* Colors are already in linear space. */ + .vertex_in(0, Type::VEC3, "pos") + .vertex_in(1, Type::FLOAT, "size") + .vertex_in(2, Type::VEC3, "local_pos") + .vertex_out(overlay_edit_mesh_color_iface) + .fragment_out(0, Type::VEC4, "fragColor") + .vertex_source("edit_mesh_skin_root_vert.glsl") + .fragment_source("gpu_shader_flat_color_frag.glsl") + .additional_info("draw_modelmat_instanced_attr", "draw_globals"); + +GPU_SHADER_CREATE_INFO(overlay_edit_mesh_vert_clipped) + .do_static_compilation(true) + .additional_info("overlay_edit_mesh_vert", "drw_clipped"); + +GPU_SHADER_CREATE_INFO(overlay_edit_mesh_edge_clipped) + .do_static_compilation(true) + .additional_info("overlay_edit_mesh_edge", "drw_clipped"); + +GPU_SHADER_CREATE_INFO(overlay_edit_mesh_edge_flat_clipped) + .do_static_compilation(true) + .additional_info("overlay_edit_mesh_edge_flat", "drw_clipped"); + +GPU_SHADER_CREATE_INFO(overlay_edit_mesh_face_clipped) + .do_static_compilation(true) + .additional_info("overlay_edit_mesh_face", "drw_clipped"); + +GPU_SHADER_CREATE_INFO(overlay_edit_mesh_facedot_clipped) + .do_static_compilation(true) + .additional_info("overlay_edit_mesh_facedot", "drw_clipped"); + +GPU_SHADER_CREATE_INFO(overlay_edit_mesh_normal_clipped) + .do_static_compilation(true) + .additional_info("overlay_edit_mesh_normal", "drw_clipped"); + +GPU_SHADER_CREATE_INFO(overlay_edit_mesh_analysis_clipped) + .do_static_compilation(true) + .additional_info("overlay_edit_mesh_analysis", "drw_clipped"); + +GPU_SHADER_CREATE_INFO(overlay_edit_mesh_skin_root_clipped) + .do_static_compilation(true) + .additional_info("overlay_edit_mesh_skin_root", "drw_clipped"); + +/** \} */ diff --git a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl index 060b7a957c1..8d26aa89f13 100644 --- a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl @@ -6,7 +6,7 @@ uniform bool isTransform; uniform bool isObjectColor; uniform bool isRandomColor; uniform bool isHair; -uniform vec4 hairDupliMatrix[4]; +uniform mat4 hairDupliMatrix; in vec3 pos; in vec3 nor; @@ -94,9 +94,7 @@ void main() vec3 wpos = point_object_to_world(pos); if (isHair) { - mat4 obmat = mat4( - hairDupliMatrix[0], hairDupliMatrix[1], hairDupliMatrix[2], hairDupliMatrix[3]); - + mat4 obmat = hairDupliMatrix; wpos = (obmat * vec4(pos, 1.0)).xyz; wnor = -normalize(mat3(obmat) * nor); } diff --git a/source/blender/draw/engines/select/select_draw_utils.c b/source/blender/draw/engines/select/select_draw_utils.c index 7615b5bb39c..613b60f8829 100644 --- a/source/blender/draw/engines/select/select_draw_utils.c +++ b/source/blender/draw/engines/select/select_draw_utils.c @@ -31,7 +31,7 @@ void select_id_object_min_max(Object *obj, float r_min[3], float r_max[3]) { - BoundBox *bb; + const BoundBox *bb; BMEditMesh *em = BKE_editmesh_from_object(obj); if (em) { bb = BKE_editmesh_cage_boundbox_get(obj, em); diff --git a/source/blender/draw/engines/workbench/shaders/infos/workbench_prepass_info.hh b/source/blender/draw/engines/workbench/shaders/infos/workbench_prepass_info.hh index 6e1da090f9f..d3766da23cf 100644 --- a/source/blender/draw/engines/workbench/shaders/infos/workbench_prepass_info.hh +++ b/source/blender/draw/engines/workbench/shaders/infos/workbench_prepass_info.hh @@ -74,7 +74,7 @@ GPU_SHADER_INTERFACE_INFO(workbench_material_iface, "") .smooth(Type::FLOAT, "alpha_interp") .smooth(Type::VEC2, "uv_interp") .flat(Type::INT, "object_id") - .flat(Type::FLOAT, "roughness") + .flat(Type::FLOAT, "_roughness") .flat(Type::FLOAT, "metallic"); GPU_SHADER_CREATE_INFO(workbench_material) diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl index 1b20171b3ff..82fa65449eb 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl @@ -7,7 +7,7 @@ void main() { normalData = workbench_normal_encode(gl_FrontFacing, normal_interp); - materialData = vec4(color_interp, workbench_float_pair_encode(roughness, metallic)); + materialData = vec4(color_interp, workbench_float_pair_encode(_roughness, metallic)); objectId = uint(object_id); diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl index 65b9f4de4b6..71cf08b7e8c 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl @@ -66,7 +66,7 @@ void main() normal_interp = normalize(normal_world_to_view(nor)); - workbench_material_data_get(resource_handle, color_interp, alpha_interp, roughness, metallic); + workbench_material_data_get(resource_handle, color_interp, alpha_interp, _roughness, metallic); if (materialIndex == 0) { color_interp = hair_get_customdata_vec3(ac); @@ -76,7 +76,7 @@ void main() * So we lower their alpha artificially. */ alpha_interp *= 0.3; - workbench_hair_random_material(hair_rand, color_interp, roughness, metallic); + workbench_hair_random_material(hair_rand, color_interp, _roughness, metallic); object_id = int(uint(resource_handle) & 0xFFFFu) + 1; } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl index 911d6f5b036..366bc2f9105 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl @@ -19,7 +19,7 @@ void main() uv_interp = vec2(0.0); - workbench_material_data_get(resource_handle, color_interp, alpha_interp, roughness, metallic); + workbench_material_data_get(resource_handle, color_interp, alpha_interp, _roughness, metallic); if (materialIndex == 0) { color_interp = vec3(1.0); diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl index 3a63b141c5f..0637f669961 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl @@ -16,7 +16,7 @@ void main() normal_interp = normalize(normal_object_to_view(nor)); - workbench_material_data_get(resource_handle, color_interp, alpha_interp, roughness, metallic); + workbench_material_data_get(resource_handle, color_interp, alpha_interp, _roughness, metallic); if (materialIndex == 0) { color_interp = ac.rgb; diff --git a/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl index 9c0f93c67d9..d8f1b83d747 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl @@ -62,7 +62,7 @@ void main() #endif #ifdef V3D_LIGHTING_STUDIO - vec3 shaded_color = get_world_lighting(color, roughness, metallic, N, I); + vec3 shaded_color = get_world_lighting(color, _roughness, metallic, N, I); #endif #ifdef V3D_LIGHTING_FLAT diff --git a/source/blender/draw/engines/workbench/workbench_shadow.c b/source/blender/draw/engines/workbench/workbench_shadow.c index 432e571d74b..588c7240ab2 100644 --- a/source/blender/draw/engines/workbench/workbench_shadow.c +++ b/source/blender/draw/engines/workbench/workbench_shadow.c @@ -166,7 +166,7 @@ void workbench_shadow_cache_init(WORKBENCH_Data *data) } } -static BoundBox *workbench_shadow_object_shadow_bbox_get(WORKBENCH_PrivateData *wpd, +static const BoundBox *workbench_shadow_object_shadow_bbox_get(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed) { @@ -178,7 +178,7 @@ static BoundBox *workbench_shadow_object_shadow_bbox_get(WORKBENCH_PrivateData * INIT_MINMAX(oed->shadow_min, oed->shadow_max); /* From object space to shadow space */ - BoundBox *bbox = BKE_object_boundbox_get(ob); + const BoundBox *bbox = BKE_object_boundbox_get(ob); for (int i = 0; i < 8; i++) { float corner[3]; mul_v3_m4v3(corner, tmp_mat, bbox->vec[i]); @@ -203,7 +203,7 @@ static bool workbench_shadow_object_cast_visible_shadow(WORKBENCH_PrivateData *w Object *ob, WORKBENCH_ObjectData *oed) { - BoundBox *shadow_bbox = workbench_shadow_object_shadow_bbox_get(wpd, ob, oed); + const BoundBox *shadow_bbox = workbench_shadow_object_shadow_bbox_get(wpd, ob, oed); const DRWView *default_view = DRW_view_default_get(); return DRW_culling_box_test(default_view, shadow_bbox); } @@ -212,7 +212,7 @@ static float workbench_shadow_object_shadow_distance(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed) { - BoundBox *shadow_bbox = workbench_shadow_object_shadow_bbox_get(wpd, ob, oed); + const BoundBox *shadow_bbox = workbench_shadow_object_shadow_bbox_get(wpd, ob, oed); const int corners[4] = {0, 3, 4, 7}; float dist = 1e4f, dist_isect; diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 8dbf5483d47..d3b1d2e74a2 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -634,10 +634,9 @@ void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, void DRW_shgroup_uniform_vec2_copy(DRWShadingGroup *shgroup, const char *name, const float *value); void DRW_shgroup_uniform_vec3_copy(DRWShadingGroup *shgroup, const char *name, const float *value); void DRW_shgroup_uniform_vec4_copy(DRWShadingGroup *shgroup, const char *name, const float *value); -void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup, - const char *name, - const float (*value)[4], - int arraysize); +void DRW_shgroup_uniform_mat4_copy(DRWShadingGroup *shgroup, + const char *name, + const float (*value)[4]); void DRW_shgroup_vertex_buffer_ex(DRWShadingGroup *shgroup, const char *name, struct GPUVertBuf *vertex_buffer DRW_DEBUG_FILE_LINE_ARGS); diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 8fc97ddcfc2..1c2a580e26d 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -26,6 +26,7 @@ #include "GPU_batch.h" #include "GPU_batch_utils.h" +#include "GPU_capabilities.h" #include "MEM_guardedalloc.h" @@ -395,12 +396,12 @@ GPUBatch *DRW_cache_quad_get(void) int v = 0; int flag = VCLASS_EMPTY_SCALED; - const float p[4][2] = {{-1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, -1.0f}}; + const float p[4][2] = {{-1.0f, 1.0f}, {1.0f, 1.0f}, {-1.0f, -1.0f}, {1.0f, -1.0f}}; for (int a = 0; a < 4; a++) { GPU_vertbuf_vert_set(vbo, v++, &(Vert){{p[a][0], p[a][1], 0.0f}, flag}); } - SHC.drw_quad = GPU_batch_create_ex(GPU_PRIM_TRI_FAN, vbo, NULL, GPU_BATCH_OWNS_VBO); + SHC.drw_quad = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO); } return SHC.drw_quad; } diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc index e84f2c7a327..717ea00fc0c 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc @@ -842,6 +842,7 @@ static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache, EXTRACT_ADD_REQUESTED(vbo, tan); EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_area); EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_angle); + EXTRACT_ADD_REQUESTED(ibo, lines_paint_mask); EXTRACT_ADD_REQUESTED(ibo, lines_adjacency); EXTRACT_ADD_REQUESTED(vbo, vcol); EXTRACT_ADD_REQUESTED(vbo, weights); diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c index a2995d6cd3f..0a93f346b37 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c @@ -461,7 +461,14 @@ MeshRenderData *mesh_render_data_create(Object *object, mr->bm_poly_centers = mr->edit_data->polyCos; } - bool has_mdata = is_mode_active && (mr->me->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA); + /* A subdivision wrapper may be created in edit mode when X-ray is turned on to ensure that the + * topology seen by the user matches the one used for the selection routines. This wrapper + * seemingly takes precedence over the MDATA one, however the mesh we use for rendering is not + * the subdivided one, but the one where the MDATA wrapper would have been added. So consider + * the subdivision wrapper as well for the `has_mdata` case. */ + bool has_mdata = is_mode_active && ELEM(mr->me->runtime.wrapper_type, + ME_WRAPPER_TYPE_MDATA, + ME_WRAPPER_TYPE_SUBD); bool use_mapped = is_mode_active && (has_mdata && !do_uvedit && mr->me && !mr->me->runtime.is_original); diff --git a/source/blender/draw/intern/draw_cache_impl_curves.cc b/source/blender/draw/intern/draw_cache_impl_curves.cc index a21a6409ca5..0b8913402e6 100644 --- a/source/blender/draw/intern/draw_cache_impl_curves.cc +++ b/source/blender/draw/intern/draw_cache_impl_curves.cc @@ -4,7 +4,7 @@ /** \file * \ingroup draw * - * \brief Hair API for render engines + * \brief Curves API for render engines */ #include <cstring> @@ -35,33 +35,29 @@ using blender::float3; using blender::IndexRange; using blender::Span; -static void curves_batch_cache_clear(Curves *curves); - /* ---------------------------------------------------------------------- */ -/* Hair GPUBatch Cache */ +/* Curves GPUBatch Cache */ -struct HairBatchCache { +struct CurvesBatchCache { ParticleHairCache hair; - /* settings to determine if cache is invalid */ + /* To determine if cache is invalid. */ bool is_dirty; }; -/* GPUBatch cache management. */ - -static bool curves_batch_cache_valid(Curves *curves) +static bool curves_batch_cache_valid(const Curves &curves) { - HairBatchCache *cache = static_cast<HairBatchCache *>(curves->batch_cache); + const CurvesBatchCache *cache = static_cast<CurvesBatchCache *>(curves.batch_cache); return (cache && cache->is_dirty == false); } -static void curves_batch_cache_init(Curves *curves) +static void curves_batch_cache_init(Curves &curves) { - HairBatchCache *cache = static_cast<HairBatchCache *>(curves->batch_cache); + CurvesBatchCache *cache = static_cast<CurvesBatchCache *>(curves.batch_cache); if (!cache) { - cache = MEM_cnew<HairBatchCache>(__func__); - curves->batch_cache = cache; + cache = MEM_cnew<CurvesBatchCache>(__func__); + curves.batch_cache = cache; } else { memset(cache, 0, sizeof(*cache)); @@ -70,23 +66,33 @@ static void curves_batch_cache_init(Curves *curves) cache->is_dirty = false; } +static void curves_batch_cache_clear(Curves &curves) +{ + CurvesBatchCache *cache = static_cast<CurvesBatchCache *>(curves.batch_cache); + if (!cache) { + return; + } + + particle_batch_cache_clear_hair(&cache->hair); +} + void DRW_curves_batch_cache_validate(Curves *curves) { - if (!curves_batch_cache_valid(curves)) { - curves_batch_cache_clear(curves); - curves_batch_cache_init(curves); + if (!curves_batch_cache_valid(*curves)) { + curves_batch_cache_clear(*curves); + curves_batch_cache_init(*curves); } } -static HairBatchCache *curves_batch_cache_get(Curves *curves) +static CurvesBatchCache &curves_batch_cache_get(Curves &curves) { - DRW_curves_batch_cache_validate(curves); - return static_cast<HairBatchCache *>(curves->batch_cache); + DRW_curves_batch_cache_validate(&curves); + return *static_cast<CurvesBatchCache *>(curves.batch_cache); } void DRW_curves_batch_cache_dirty_tag(Curves *curves, int mode) { - HairBatchCache *cache = static_cast<HairBatchCache *>(curves->batch_cache); + CurvesBatchCache *cache = static_cast<CurvesBatchCache *>(curves->batch_cache); if (cache == nullptr) { return; } @@ -99,52 +105,42 @@ void DRW_curves_batch_cache_dirty_tag(Curves *curves, int mode) } } -static void curves_batch_cache_clear(Curves *curves) -{ - HairBatchCache *cache = static_cast<HairBatchCache *>(curves->batch_cache); - if (!cache) { - return; - } - - particle_batch_cache_clear_hair(&cache->hair); -} - void DRW_curves_batch_cache_free(Curves *curves) { - curves_batch_cache_clear(curves); + curves_batch_cache_clear(*curves); MEM_SAFE_FREE(curves->batch_cache); } -static void ensure_seg_pt_count(Curves *curves, ParticleHairCache *curves_cache) +static void ensure_seg_pt_count(const Curves &curves, ParticleHairCache &curves_cache) { - if ((curves_cache->pos != nullptr && curves_cache->indices != nullptr) || - (curves_cache->proc_point_buf != nullptr)) { + if ((curves_cache.pos != nullptr && curves_cache.indices != nullptr) || + (curves_cache.proc_point_buf != nullptr)) { return; } - curves_cache->strands_len = curves->geometry.curve_size; - curves_cache->elems_len = curves->geometry.point_size + curves->geometry.curve_size; - curves_cache->point_len = curves->geometry.point_size; + curves_cache.strands_len = curves.geometry.curve_size; + curves_cache.elems_len = curves.geometry.point_size + curves.geometry.curve_size; + curves_cache.point_len = curves.geometry.point_size; } -static void curves_batch_cache_fill_segments_proc_pos(Curves *curves, - GPUVertBufRaw *attr_step, - GPUVertBufRaw *length_step) +static void curves_batch_cache_fill_segments_proc_pos(const Curves &curves_id, + GPUVertBufRaw &attr_step, + GPUVertBufRaw &length_step) { /* TODO: use hair radius layer if available. */ - const int curve_size = curves->geometry.curve_size; - const blender::bke::CurvesGeometry &geometry = blender::bke::CurvesGeometry::wrap( - curves->geometry); - Span<float3> positions = geometry.positions(); + const int curve_size = curves_id.geometry.curve_size; + const blender::bke::CurvesGeometry &curves = blender::bke::CurvesGeometry::wrap( + curves_id.geometry); + Span<float3> positions = curves.positions(); for (const int i : IndexRange(curve_size)) { - const IndexRange curve_range = geometry.points_for_curve(i); + const IndexRange curve_range = curves.points_for_curve(i); Span<float3> curve_positions = positions.slice(curve_range); float total_len = 0.0f; float *seg_data_first; for (const int i_curve : curve_positions.index_range()) { - float *seg_data = (float *)GPU_vertbuf_raw_step(attr_step); + float *seg_data = (float *)GPU_vertbuf_raw_step(&attr_step); copy_v3_v3(seg_data, curve_positions[i_curve]); if (i_curve == 0) { seg_data_first = seg_data; @@ -156,7 +152,7 @@ static void curves_batch_cache_fill_segments_proc_pos(Curves *curves, seg_data[3] = total_len; } /* Assign length value. */ - *(float *)GPU_vertbuf_raw_step(length_step) = total_len; + *(float *)GPU_vertbuf_raw_step(&length_step) = total_len; if (total_len > 0.0f) { /* Divide by total length to have a [0-1] number. */ for ([[maybe_unused]] const int i_curve : curve_positions.index_range()) { @@ -167,67 +163,67 @@ static void curves_batch_cache_fill_segments_proc_pos(Curves *curves, } } -static void curves_batch_cache_ensure_procedural_pos(Curves *curves, - ParticleHairCache *cache, +static void curves_batch_cache_ensure_procedural_pos(Curves &curves, + ParticleHairCache &cache, GPUMaterial *gpu_material) { - if (cache->proc_point_buf == nullptr) { - /* initialize vertex format */ + if (cache.proc_point_buf == nullptr) { + /* Initialize vertex format. */ GPUVertFormat format = {0}; uint pos_id = GPU_vertformat_attr_add(&format, "posTime", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - cache->proc_point_buf = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(cache->proc_point_buf, cache->point_len); + cache.proc_point_buf = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(cache.proc_point_buf, cache.point_len); GPUVertBufRaw point_step; - GPU_vertbuf_attr_get_raw_data(cache->proc_point_buf, pos_id, &point_step); + GPU_vertbuf_attr_get_raw_data(cache.proc_point_buf, pos_id, &point_step); GPUVertFormat length_format = {0}; uint length_id = GPU_vertformat_attr_add( &length_format, "hairLength", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - cache->proc_length_buf = GPU_vertbuf_create_with_format(&length_format); - GPU_vertbuf_data_alloc(cache->proc_length_buf, cache->strands_len); + cache.proc_length_buf = GPU_vertbuf_create_with_format(&length_format); + GPU_vertbuf_data_alloc(cache.proc_length_buf, cache.strands_len); GPUVertBufRaw length_step; - GPU_vertbuf_attr_get_raw_data(cache->proc_length_buf, length_id, &length_step); + GPU_vertbuf_attr_get_raw_data(cache.proc_length_buf, length_id, &length_step); - curves_batch_cache_fill_segments_proc_pos(curves, &point_step, &length_step); + curves_batch_cache_fill_segments_proc_pos(curves, point_step, length_step); /* Create vbo immediately to bind to texture buffer. */ - GPU_vertbuf_use(cache->proc_point_buf); - cache->point_tex = GPU_texture_create_from_vertbuf("hair_point", cache->proc_point_buf); + GPU_vertbuf_use(cache.proc_point_buf); + cache.point_tex = GPU_texture_create_from_vertbuf("hair_point", cache.proc_point_buf); } - if (gpu_material && cache->proc_length_buf != nullptr && cache->length_tex) { + if (gpu_material && cache.proc_length_buf != nullptr && cache.length_tex) { ListBase gpu_attrs = GPU_material_attributes(gpu_material); LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &gpu_attrs) { if (attr->type == CD_HAIRLENGTH) { - GPU_vertbuf_use(cache->proc_length_buf); - cache->length_tex = GPU_texture_create_from_vertbuf("hair_length", cache->proc_length_buf); + GPU_vertbuf_use(cache.proc_length_buf); + cache.length_tex = GPU_texture_create_from_vertbuf("hair_length", cache.proc_length_buf); break; } } } } -static void curves_batch_cache_fill_strands_data(Curves *curves, - GPUVertBufRaw *data_step, - GPUVertBufRaw *seg_step) +static void curves_batch_cache_fill_strands_data(const Curves &curves_id, + GPUVertBufRaw &data_step, + GPUVertBufRaw &seg_step) { - const blender::bke::CurvesGeometry &geometry = blender::bke::CurvesGeometry::wrap( - curves->geometry); + const blender::bke::CurvesGeometry &curves = blender::bke::CurvesGeometry::wrap( + curves_id.geometry); - for (const int i : IndexRange(geometry.curves_num())) { - const IndexRange curve_range = geometry.points_for_curve(i); + for (const int i : IndexRange(curves.curves_num())) { + const IndexRange curve_range = curves.points_for_curve(i); - *(uint *)GPU_vertbuf_raw_step(data_step) = curve_range.start(); - *(ushort *)GPU_vertbuf_raw_step(seg_step) = curve_range.size() - 1; + *(uint *)GPU_vertbuf_raw_step(&data_step) = curve_range.start(); + *(ushort *)GPU_vertbuf_raw_step(&seg_step) = curve_range.size() - 1; } } -static void curves_batch_cache_ensure_procedural_strand_data(Curves *curves, - ParticleHairCache *cache) +static void curves_batch_cache_ensure_procedural_strand_data(Curves &curves, + ParticleHairCache &cache) { GPUVertBufRaw data_step, seg_step; @@ -237,77 +233,76 @@ static void curves_batch_cache_ensure_procedural_strand_data(Curves *curves, GPUVertFormat format_seg = {0}; uint seg_id = GPU_vertformat_attr_add(&format_seg, "data", GPU_COMP_U16, 1, GPU_FETCH_INT); - /* Strand Data */ - cache->proc_strand_buf = GPU_vertbuf_create_with_format(&format_data); - GPU_vertbuf_data_alloc(cache->proc_strand_buf, cache->strands_len); - GPU_vertbuf_attr_get_raw_data(cache->proc_strand_buf, data_id, &data_step); + /* Curve Data. */ + cache.proc_strand_buf = GPU_vertbuf_create_with_format(&format_data); + GPU_vertbuf_data_alloc(cache.proc_strand_buf, cache.strands_len); + GPU_vertbuf_attr_get_raw_data(cache.proc_strand_buf, data_id, &data_step); - cache->proc_strand_seg_buf = GPU_vertbuf_create_with_format(&format_seg); - GPU_vertbuf_data_alloc(cache->proc_strand_seg_buf, cache->strands_len); - GPU_vertbuf_attr_get_raw_data(cache->proc_strand_seg_buf, seg_id, &seg_step); + cache.proc_strand_seg_buf = GPU_vertbuf_create_with_format(&format_seg); + GPU_vertbuf_data_alloc(cache.proc_strand_seg_buf, cache.strands_len); + GPU_vertbuf_attr_get_raw_data(cache.proc_strand_seg_buf, seg_id, &seg_step); - curves_batch_cache_fill_strands_data(curves, &data_step, &seg_step); + curves_batch_cache_fill_strands_data(curves, data_step, seg_step); /* Create vbo immediately to bind to texture buffer. */ - GPU_vertbuf_use(cache->proc_strand_buf); - cache->strand_tex = GPU_texture_create_from_vertbuf("curves_strand", cache->proc_strand_buf); + GPU_vertbuf_use(cache.proc_strand_buf); + cache.strand_tex = GPU_texture_create_from_vertbuf("curves_strand", cache.proc_strand_buf); - GPU_vertbuf_use(cache->proc_strand_seg_buf); - cache->strand_seg_tex = GPU_texture_create_from_vertbuf("curves_strand_seg", - cache->proc_strand_seg_buf); + GPU_vertbuf_use(cache.proc_strand_seg_buf); + cache.strand_seg_tex = GPU_texture_create_from_vertbuf("curves_strand_seg", + cache.proc_strand_seg_buf); } -static void curves_batch_cache_ensure_procedural_final_points(ParticleHairCache *cache, int subdiv) +static void curves_batch_cache_ensure_procedural_final_points(ParticleHairCache &cache, int subdiv) { /* Same format as point_tex. */ GPUVertFormat format = {0}; GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - cache->final[subdiv].proc_buf = GPU_vertbuf_create_with_format_ex(&format, - GPU_USAGE_DEVICE_ONLY); + cache.final[subdiv].proc_buf = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_DEVICE_ONLY); /* Create a destination buffer for the transform feedback. Sized appropriately */ /* Those are points! not line segments. */ - GPU_vertbuf_data_alloc(cache->final[subdiv].proc_buf, - cache->final[subdiv].strands_res * cache->strands_len); + GPU_vertbuf_data_alloc(cache.final[subdiv].proc_buf, + cache.final[subdiv].strands_res * cache.strands_len); /* Create vbo immediately to bind to texture buffer. */ - GPU_vertbuf_use(cache->final[subdiv].proc_buf); + GPU_vertbuf_use(cache.final[subdiv].proc_buf); - cache->final[subdiv].proc_tex = GPU_texture_create_from_vertbuf("hair_proc", - cache->final[subdiv].proc_buf); + cache.final[subdiv].proc_tex = GPU_texture_create_from_vertbuf("hair_proc", + cache.final[subdiv].proc_buf); } -static void curves_batch_cache_fill_segments_indices(Curves *curves, +static void curves_batch_cache_fill_segments_indices(const Curves &curves, const int res, - GPUIndexBufBuilder *elb) + GPUIndexBufBuilder &elb) { - const int curve_size = curves->geometry.curve_size; + const int curves_num = curves.geometry.curve_size; uint curr_point = 0; - for ([[maybe_unused]] const int i : IndexRange(curve_size)) { + for ([[maybe_unused]] const int i : IndexRange(curves_num)) { for (int k = 0; k < res; k++) { - GPU_indexbuf_add_generic_vert(elb, curr_point++); + GPU_indexbuf_add_generic_vert(&elb, curr_point++); } - GPU_indexbuf_add_primitive_restart(elb); + GPU_indexbuf_add_primitive_restart(&elb); } } -static void curves_batch_cache_ensure_procedural_indices(Curves *curves, - ParticleHairCache *cache, - int thickness_res, - int subdiv) +static void curves_batch_cache_ensure_procedural_indices(Curves &curves, + ParticleHairCache &cache, + const int thickness_res, + const int subdiv) { BLI_assert(thickness_res <= MAX_THICKRES); /* Cylinder strip not currently supported. */ - if (cache->final[subdiv].proc_hairs[thickness_res - 1] != nullptr) { + if (cache.final[subdiv].proc_hairs[thickness_res - 1] != nullptr) { return; } - int verts_per_hair = cache->final[subdiv].strands_res * thickness_res; + int verts_per_curve = cache.final[subdiv].strands_res * thickness_res; /* +1 for primitive restart */ - int element_count = (verts_per_hair + 1) * cache->strands_len; + int element_count = (verts_per_curve + 1) * cache.strands_len; GPUPrimType prim_type = (thickness_res == 1) ? GPU_PRIM_LINE_STRIP : GPU_PRIM_TRI_STRIP; static GPUVertFormat format = {0}; @@ -322,46 +317,46 @@ static void curves_batch_cache_ensure_procedural_indices(Curves *curves, GPUIndexBufBuilder elb; GPU_indexbuf_init_ex(&elb, prim_type, element_count, element_count); - curves_batch_cache_fill_segments_indices(curves, verts_per_hair, &elb); + curves_batch_cache_fill_segments_indices(curves, verts_per_curve, elb); - cache->final[subdiv].proc_hairs[thickness_res - 1] = GPU_batch_create_ex( + cache.final[subdiv].proc_hairs[thickness_res - 1] = GPU_batch_create_ex( prim_type, vbo, GPU_indexbuf_build(&elb), GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX); } -bool hair_ensure_procedural_data(Object *object, - ParticleHairCache **r_hair_cache, - GPUMaterial *gpu_material, - int subdiv, - int thickness_res) +bool curves_ensure_procedural_data(Object *object, + ParticleHairCache **r_hair_cache, + GPUMaterial *gpu_material, + const int subdiv, + const int thickness_res) { bool need_ft_update = false; - Curves *curves = static_cast<Curves *>(object->data); + Curves &curves = *static_cast<Curves *>(object->data); - HairBatchCache *cache = curves_batch_cache_get(curves); - *r_hair_cache = &cache->hair; + CurvesBatchCache &cache = curves_batch_cache_get(curves); + *r_hair_cache = &cache.hair; const int steps = 3; /* TODO: don't hard-code? */ (*r_hair_cache)->final[subdiv].strands_res = 1 << (steps + subdiv); /* Refreshed on combing and simulation. */ if ((*r_hair_cache)->proc_point_buf == nullptr) { - ensure_seg_pt_count(curves, &cache->hair); - curves_batch_cache_ensure_procedural_pos(curves, &cache->hair, gpu_material); + ensure_seg_pt_count(curves, cache.hair); + curves_batch_cache_ensure_procedural_pos(curves, cache.hair, gpu_material); need_ft_update = true; } /* Refreshed if active layer or custom data changes. */ if ((*r_hair_cache)->strand_tex == nullptr) { - curves_batch_cache_ensure_procedural_strand_data(curves, &cache->hair); + curves_batch_cache_ensure_procedural_strand_data(curves, cache.hair); } /* Refreshed only on subdiv count change. */ if ((*r_hair_cache)->final[subdiv].proc_buf == nullptr) { - curves_batch_cache_ensure_procedural_final_points(&cache->hair, subdiv); + curves_batch_cache_ensure_procedural_final_points(cache.hair, subdiv); need_ft_update = true; } if ((*r_hair_cache)->final[subdiv].proc_hairs[thickness_res - 1] == nullptr) { - curves_batch_cache_ensure_procedural_indices(curves, &cache->hair, thickness_res, subdiv); + curves_batch_cache_ensure_procedural_indices(curves, cache.hair, thickness_res, subdiv); } return need_ft_update; diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index 8aa7ff66d65..2653035a39f 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -544,6 +544,7 @@ void draw_subdiv_cache_free(DRWSubdivCache *cache) GPU_VERTBUF_DISCARD_SAFE(cache->subdiv_polygon_offset_buffer); GPU_VERTBUF_DISCARD_SAFE(cache->extra_coarse_face_data); MEM_SAFE_FREE(cache->subdiv_loop_subdiv_vert_index); + MEM_SAFE_FREE(cache->subdiv_loop_subdiv_edge_index); MEM_SAFE_FREE(cache->subdiv_loop_poly_index); MEM_SAFE_FREE(cache->subdiv_polygon_offset); GPU_VERTBUF_DISCARD_SAFE(cache->subdiv_vertex_face_adjacency_offsets); @@ -630,7 +631,10 @@ static void draw_subdiv_cache_extra_coarse_face_data_mesh(Mesh *mesh, uint32_t * for (int i = 0; i < mesh->totpoly; i++) { uint32_t flag = 0; if ((mesh->mpoly[i].flag & ME_SMOOTH) != 0) { - flag = SUBDIV_COARSE_FACE_FLAG_SMOOTH; + flag |= SUBDIV_COARSE_FACE_FLAG_SMOOTH; + } + if ((mesh->mpoly[i].flag & ME_FACE_SEL) != 0) { + flag |= SUBDIV_COARSE_FACE_FLAG_SELECT; } flags_data[i] = (uint)(mesh->mpoly[i].loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET); } @@ -720,6 +724,7 @@ struct DRWCacheBuildingContext { int *subdiv_loop_vert_index; int *subdiv_loop_subdiv_vert_index; int *subdiv_loop_edge_index; + int *subdiv_loop_subdiv_edge_index; int *subdiv_loop_poly_index; /* Temporary buffers used during traversal. */ @@ -781,6 +786,9 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con cache->subdiv_loop_subdiv_vert_index = static_cast<int *>( MEM_mallocN(cache->num_subdiv_loops * sizeof(int), "subdiv_loop_subdiv_vert_index")); + cache->subdiv_loop_subdiv_edge_index = static_cast<int *>( + MEM_mallocN(cache->num_subdiv_loops * sizeof(int), "subdiv_loop_subdiv_edge_index")); + cache->subdiv_loop_poly_index = static_cast<int *>( MEM_mallocN(cache->num_subdiv_loops * sizeof(int), "subdiv_loop_poly_index")); @@ -789,6 +797,7 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con ctx->subdiv_loop_vert_index = (int *)GPU_vertbuf_get_data(cache->verts_orig_index); ctx->subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(cache->edges_orig_index); ctx->subdiv_loop_subdiv_vert_index = cache->subdiv_loop_subdiv_vert_index; + ctx->subdiv_loop_subdiv_edge_index = cache->subdiv_loop_subdiv_edge_index; ctx->subdiv_loop_poly_index = cache->subdiv_loop_poly_index; ctx->v_origindex = static_cast<int *>( @@ -887,9 +896,7 @@ static void draw_subdiv_loop_cb(const SubdivForeachContext *foreach_context, int coarse_vertex_index = ctx->vert_origindex_map[subdiv_vertex_index]; ctx->subdiv_loop_subdiv_vert_index[subdiv_loop_index] = subdiv_vertex_index; - /* For now index the subdiv_edge_index, it will be replaced by the actual coarse edge index - * at the end of the traversal as some edges are only then traversed. */ - ctx->subdiv_loop_edge_index[subdiv_loop_index] = subdiv_edge_index; + ctx->subdiv_loop_subdiv_edge_index[subdiv_loop_index] = subdiv_edge_index; ctx->subdiv_loop_poly_index[subdiv_loop_index] = coarse_poly_index; ctx->subdiv_loop_vert_index[subdiv_loop_index] = coarse_vertex_index; } @@ -915,12 +922,13 @@ static void do_subdiv_traversal(DRWCacheBuildingContext *cache_building_context, cache_building_context->settings, cache_building_context->coarse_mesh); - /* Now that traversal is done, we can set up the right original indices for the loop-to-edge map. + /* Now that traversal is done, we can set up the right original indices for the + * subdiv-loop-to-coarse-edge map. */ for (int i = 0; i < cache_building_context->cache->num_subdiv_loops; i++) { cache_building_context->subdiv_loop_edge_index[i] = cache_building_context - ->edge_origindex_map[cache_building_context->subdiv_loop_edge_index[i]]; + ->edge_origindex_map[cache_building_context->subdiv_loop_subdiv_edge_index[i]]; } } diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index c7edf003346..462ae6f7cf1 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -184,9 +184,10 @@ void DRW_globals_update(void) gb->pixelFac = *DRW_viewport_pixelsize_get(); - copy_v2_v2(gb->sizeViewport, DRW_viewport_size_get()); - copy_v2_v2(gb->sizeViewportInv, gb->sizeViewport); - invert_v2(gb->sizeViewportInv); + /* Deprecated, use drw_view.viewport_size instead */ + copy_v2_v2(&gb->sizeViewport[0], DRW_viewport_size_get()); + copy_v2_v2(&gb->sizeViewport[2], &gb->sizeViewport[0]); + invert_v2(&gb->sizeViewport[2]); /* Color management. */ { diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index 53946c0cec5..e2dc91f64be 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -7,6 +7,8 @@ #pragma once +#include "draw_common_shader_shared.h" + struct DRWShadingGroup; struct FluidModifierData; struct GPUMaterial; @@ -16,126 +18,6 @@ struct ParticleSystem; struct RegionView3D; struct ViewLayer; -#define UBO_FIRST_COLOR colorWire -#define UBO_LAST_COLOR colorUVShadow - -/* Used as ubo but colors can be directly referenced as well */ -/* Keep in sync with: common_globals_lib.glsl (globalsBlock) */ -/* NOTE: Also keep all color as vec4 and between #UBO_FIRST_COLOR and #UBO_LAST_COLOR. */ -typedef struct GlobalsUboStorage { - /* UBOs data needs to be 16 byte aligned (size of vec4) */ - float colorWire[4]; - float colorWireEdit[4]; - float colorActive[4]; - float colorSelect[4]; - float colorLibrarySelect[4]; - float colorLibrary[4]; - float colorTransform[4]; - float colorLight[4]; - float colorSpeaker[4]; - float colorCamera[4]; - float colorCameraPath[4]; - float colorEmpty[4]; - float colorVertex[4]; - float colorVertexSelect[4]; - float colorVertexUnreferenced[4]; - float colorVertexMissingData[4]; - float colorEditMeshActive[4]; - float colorEdgeSelect[4]; - float colorEdgeSeam[4]; - float colorEdgeSharp[4]; - float colorEdgeCrease[4]; - float colorEdgeBWeight[4]; - float colorEdgeFaceSelect[4]; - float colorEdgeFreestyle[4]; - float colorFace[4]; - float colorFaceSelect[4]; - float colorFaceFreestyle[4]; - float colorGpencilVertex[4]; - float colorGpencilVertexSelect[4]; - float colorNormal[4]; - float colorVNormal[4]; - float colorLNormal[4]; - float colorFaceDot[4]; - float colorSkinRoot[4]; - - float colorDeselect[4]; - float colorOutline[4]; - float colorLightNoAlpha[4]; - - float colorBackground[4]; - float colorBackgroundGradient[4]; - float colorCheckerPrimary[4]; - float colorCheckerSecondary[4]; - float colorClippingBorder[4]; - float colorEditMeshMiddle[4]; - - float colorHandleFree[4]; - float colorHandleAuto[4]; - float colorHandleVect[4]; - float colorHandleAlign[4]; - float colorHandleAutoclamp[4]; - float colorHandleSelFree[4]; - float colorHandleSelAuto[4]; - float colorHandleSelVect[4]; - float colorHandleSelAlign[4]; - float colorHandleSelAutoclamp[4]; - float colorNurbUline[4]; - float colorNurbVline[4]; - float colorNurbSelUline[4]; - float colorNurbSelVline[4]; - float colorActiveSpline[4]; - - float colorBonePose[4]; - float colorBonePoseActive[4]; - float colorBonePoseActiveUnsel[4]; - float colorBonePoseConstraint[4]; - float colorBonePoseIK[4]; - float colorBonePoseSplineIK[4]; - float colorBonePoseTarget[4]; - float colorBoneSolid[4]; - float colorBoneLocked[4]; - float colorBoneActive[4]; - float colorBoneActiveUnsel[4]; - float colorBoneSelect[4]; - float colorBoneIKLine[4]; - float colorBoneIKLineNoTarget[4]; - float colorBoneIKLineSpline[4]; - - float colorText[4]; - float colorTextHi[4]; - - float colorBundleSolid[4]; - - float colorMballRadius[4]; - float colorMballRadiusSelect[4]; - float colorMballStiffness[4]; - float colorMballStiffnessSelect[4]; - - float colorCurrentFrame[4]; - - float colorGrid[4]; - float colorGridEmphasis[4]; - float colorGridAxisX[4]; - float colorGridAxisY[4]; - float colorGridAxisZ[4]; - - float colorFaceBack[4]; - float colorFaceFront[4]; - - float colorUVShadow[4]; - - /* NOTE: Put all color before #UBO_LAST_COLOR. */ - float screenVecs[2][4]; /* Padded as vec4. */ - float sizeViewport[2], sizeViewportInv[2]; /* Packed as vec4 in GLSL. */ - - /* Pack individual float at the end of the buffer to avoid alignment errors */ - float sizePixel, pixelFac; - float sizeObjectCenter, sizeLightCenter, sizeLightCircle, sizeLightCircleShadow; - float sizeVertex, sizeEdge, sizeEdgeFix, sizeFaceDot; - float sizeChecker; - float sizeVertexGpencil; -} GlobalsUboStorage; /* Keep in sync with globalsBlock in shaders */ BLI_STATIC_ASSERT_ALIGN(GlobalsUboStorage, 16) diff --git a/source/blender/draw/intern/draw_common_shader_shared.h b/source/blender/draw/intern/draw_common_shader_shared.h new file mode 100644 index 00000000000..ecddddded78 --- /dev/null +++ b/source/blender/draw/intern/draw_common_shader_shared.h @@ -0,0 +1,268 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. */ + +/** \file + * \ingroup draw + */ + +#ifndef GPU_SHADER +# include "GPU_shader_shared_utils.h" + +typedef struct GlobalsUboStorage GlobalsUboStorage; +#endif + +/* Future Plan: These globals were once shared between multiple overlay engines. But now that they + * have been merged into one engine, there is no reasons to keep these globals out of the overlay + * engine. */ + +#define UBO_FIRST_COLOR colorWire +#define UBO_LAST_COLOR colorUVShadow + +/* Used as ubo but colors can be directly referenced as well */ +/* NOTE: Also keep all color as vec4 and between #UBO_FIRST_COLOR and #UBO_LAST_COLOR. */ +struct GlobalsUboStorage { + /* UBOs data needs to be 16 byte aligned (size of vec4) */ + float4 colorWire; + float4 colorWireEdit; + float4 colorActive; + float4 colorSelect; + float4 colorLibrarySelect; + float4 colorLibrary; + float4 colorTransform; + float4 colorLight; + float4 colorSpeaker; + float4 colorCamera; + float4 colorCameraPath; + float4 colorEmpty; + float4 colorVertex; + float4 colorVertexSelect; + float4 colorVertexUnreferenced; + float4 colorVertexMissingData; + float4 colorEditMeshActive; + float4 colorEdgeSelect; + float4 colorEdgeSeam; + float4 colorEdgeSharp; + float4 colorEdgeCrease; + float4 colorEdgeBWeight; + float4 colorEdgeFaceSelect; + float4 colorEdgeFreestyle; + float4 colorFace; + float4 colorFaceSelect; + float4 colorFaceFreestyle; + float4 colorGpencilVertex; + float4 colorGpencilVertexSelect; + float4 colorNormal; + float4 colorVNormal; + float4 colorLNormal; + float4 colorFaceDot; + float4 colorSkinRoot; + + float4 colorDeselect; + float4 colorOutline; + float4 colorLightNoAlpha; + + float4 colorBackground; + float4 colorBackgroundGradient; + float4 colorCheckerPrimary; + float4 colorCheckerSecondary; + float4 colorClippingBorder; + float4 colorEditMeshMiddle; + + float4 colorHandleFree; + float4 colorHandleAuto; + float4 colorHandleVect; + float4 colorHandleAlign; + float4 colorHandleAutoclamp; + float4 colorHandleSelFree; + float4 colorHandleSelAuto; + float4 colorHandleSelVect; + float4 colorHandleSelAlign; + float4 colorHandleSelAutoclamp; + float4 colorNurbUline; + float4 colorNurbVline; + float4 colorNurbSelUline; + float4 colorNurbSelVline; + float4 colorActiveSpline; + + float4 colorBonePose; + float4 colorBonePoseActive; + float4 colorBonePoseActiveUnsel; + float4 colorBonePoseConstraint; + float4 colorBonePoseIK; + float4 colorBonePoseSplineIK; + float4 colorBonePoseTarget; + float4 colorBoneSolid; + float4 colorBoneLocked; + float4 colorBoneActive; + float4 colorBoneActiveUnsel; + float4 colorBoneSelect; + float4 colorBoneIKLine; + float4 colorBoneIKLineNoTarget; + float4 colorBoneIKLineSpline; + + float4 colorText; + float4 colorTextHi; + + float4 colorBundleSolid; + + float4 colorMballRadius; + float4 colorMballRadiusSelect; + float4 colorMballStiffness; + float4 colorMballStiffnessSelect; + + float4 colorCurrentFrame; + + float4 colorGrid; + float4 colorGridEmphasis; + float4 colorGridAxisX; + float4 colorGridAxisY; + float4 colorGridAxisZ; + + float4 colorFaceBack; + float4 colorFaceFront; + + float4 colorUVShadow; + + /* NOTE: Put all color before #UBO_LAST_COLOR. */ + float4 screenVecs[2]; /* Padded as vec4. */ + float4 sizeViewport; /* Packed as vec4. */ + + /* Pack individual float at the end of the buffer to avoid alignment errors */ + float sizePixel, pixelFac; + float sizeObjectCenter, sizeLightCenter, sizeLightCircle, sizeLightCircleShadow; + float sizeVertex, sizeEdge, sizeEdgeFix, sizeFaceDot; + float sizeChecker; + float sizeVertexGpencil; +}; +BLI_STATIC_ASSERT_ALIGN(GlobalsUboStorage, 16) + +#ifdef GPU_SHADER +/* Keep compatibility_with old global scope syntax. */ +/* TODO(@fclem) Mass rename and remove the camel case. */ +# define colorWire globalsBlock.colorWire +# define colorWireEdit globalsBlock.colorWireEdit +# define colorActive globalsBlock.colorActive +# define colorSelect globalsBlock.colorSelect +# define colorLibrarySelect globalsBlock.colorLibrarySelect +# define colorLibrary globalsBlock.colorLibrary +# define colorTransform globalsBlock.colorTransform +# define colorLight globalsBlock.colorLight +# define colorSpeaker globalsBlock.colorSpeaker +# define colorCamera globalsBlock.colorCamera +# define colorCameraPath globalsBlock.colorCameraPath +# define colorEmpty globalsBlock.colorEmpty +# define colorVertex globalsBlock.colorVertex +# define colorVertexSelect globalsBlock.colorVertexSelect +# define colorVertexUnreferenced globalsBlock.colorVertexUnreferenced +# define colorVertexMissingData globalsBlock.colorVertexMissingData +# define colorEditMeshActive globalsBlock.colorEditMeshActive +# define colorEdgeSelect globalsBlock.colorEdgeSelect +# define colorEdgeSeam globalsBlock.colorEdgeSeam +# define colorEdgeSharp globalsBlock.colorEdgeSharp +# define colorEdgeCrease globalsBlock.colorEdgeCrease +# define colorEdgeBWeight globalsBlock.colorEdgeBWeight +# define colorEdgeFaceSelect globalsBlock.colorEdgeFaceSelect +# define colorEdgeFreestyle globalsBlock.colorEdgeFreestyle +# define colorFace globalsBlock.colorFace +# define colorFaceSelect globalsBlock.colorFaceSelect +# define colorFaceFreestyle globalsBlock.colorFaceFreestyle +# define colorGpencilVertex globalsBlock.colorGpencilVertex +# define colorGpencilVertexSelect globalsBlock.colorGpencilVertexSelect +# define colorNormal globalsBlock.colorNormal +# define colorVNormal globalsBlock.colorVNormal +# define colorLNormal globalsBlock.colorLNormal +# define colorFaceDot globalsBlock.colorFaceDot +# define colorSkinRoot globalsBlock.colorSkinRoot +# define colorDeselect globalsBlock.colorDeselect +# define colorOutline globalsBlock.colorOutline +# define colorLightNoAlpha globalsBlock.colorLightNoAlpha +# define colorBackground globalsBlock.colorBackground +# define colorBackgroundGradient globalsBlock.colorBackgroundGradient +# define colorCheckerPrimary globalsBlock.colorCheckerPrimary +# define colorCheckerSecondary globalsBlock.colorCheckerSecondary +# define colorClippingBorder globalsBlock.colorClippingBorder +# define colorEditMeshMiddle globalsBlock.colorEditMeshMiddle +# define colorHandleFree globalsBlock.colorHandleFree +# define colorHandleAuto globalsBlock.colorHandleAuto +# define colorHandleVect globalsBlock.colorHandleVect +# define colorHandleAlign globalsBlock.colorHandleAlign +# define colorHandleAutoclamp globalsBlock.colorHandleAutoclamp +# define colorHandleSelFree globalsBlock.colorHandleSelFree +# define colorHandleSelAuto globalsBlock.colorHandleSelAuto +# define colorHandleSelVect globalsBlock.colorHandleSelVect +# define colorHandleSelAlign globalsBlock.colorHandleSelAlign +# define colorHandleSelAutoclamp globalsBlock.colorHandleSelAutoclamp +# define colorNurbUline globalsBlock.colorNurbUline +# define colorNurbVline globalsBlock.colorNurbVline +# define colorNurbSelUline globalsBlock.colorNurbSelUline +# define colorNurbSelVline globalsBlock.colorNurbSelVline +# define colorActiveSpline globalsBlock.colorActiveSpline +# define colorBonePose globalsBlock.colorBonePose +# define colorBonePoseActive globalsBlock.colorBonePoseActive +# define colorBonePoseActiveUnsel globalsBlock.colorBonePoseActiveUnsel +# define colorBonePoseConstraint globalsBlock.colorBonePoseConstraint +# define colorBonePoseIK globalsBlock.colorBonePoseIK +# define colorBonePoseSplineIK globalsBlock.colorBonePoseSplineIK +# define colorBonePoseTarget globalsBlock.colorBonePoseTarget +# define colorBoneSolid globalsBlock.colorBoneSolid +# define colorBoneLocked globalsBlock.colorBoneLocked +# define colorBoneActive globalsBlock.colorBoneActive +# define colorBoneActiveUnsel globalsBlock.colorBoneActiveUnsel +# define colorBoneSelect globalsBlock.colorBoneSelect +# define colorBoneIKLine globalsBlock.colorBoneIKLine +# define colorBoneIKLineNoTarget globalsBlock.colorBoneIKLineNoTarget +# define colorBoneIKLineSpline globalsBlock.colorBoneIKLineSpline +# define colorText globalsBlock.colorText +# define colorTextHi globalsBlock.colorTextHi +# define colorBundleSolid globalsBlock.colorBundleSolid +# define colorMballRadius globalsBlock.colorMballRadius +# define colorMballRadiusSelect globalsBlock.colorMballRadiusSelect +# define colorMballStiffness globalsBlock.colorMballStiffness +# define colorMballStiffnessSelect globalsBlock.colorMballStiffnessSelect +# define colorCurrentFrame globalsBlock.colorCurrentFrame +# define colorGrid globalsBlock.colorGrid +# define colorGridEmphasis globalsBlock.colorGridEmphasis +# define colorGridAxisX globalsBlock.colorGridAxisX +# define colorGridAxisY globalsBlock.colorGridAxisY +# define colorGridAxisZ globalsBlock.colorGridAxisZ +# define colorFaceBack globalsBlock.colorFaceBack +# define colorFaceFront globalsBlock.colorFaceFront +# define colorUVShadow globalsBlock.colorUVShadow +# define screenVecs globalsBlock.screenVecs +# define sizeViewport globalsBlock.sizeViewport.xy +# define sizePixel globalsBlock.sizePixel +# define pixelFac globalsBlock.pixelFac +# define sizeObjectCenter globalsBlock.sizeObjectCenter +# define sizeLightCenter globalsBlock.sizeLightCenter +# define sizeLightCircle globalsBlock.sizeLightCircle +# define sizeLightCircleShadow globalsBlock.sizeLightCircleShadow +# define sizeVertex globalsBlock.sizeVertex +# define sizeEdge globalsBlock.sizeEdge +# define sizeEdgeFix globalsBlock.sizeEdgeFix +# define sizeFaceDot globalsBlock.sizeFaceDot +# define sizeChecker globalsBlock.sizeChecker +# define sizeVertexGpencil globalsBlock.sizeVertexGpencil +#endif + +/* See: 'draw_cache_impl.h' for matching includes. */ +#define VERT_GPENCIL_BEZT_HANDLE (1 << 30) +/* data[0] (1st byte flags) */ +#define FACE_ACTIVE (1 << 0) +#define FACE_SELECTED (1 << 1) +#define FACE_FREESTYLE (1 << 2) +#define VERT_UV_SELECT (1 << 3) +#define VERT_UV_PINNED (1 << 4) +#define EDGE_UV_SELECT (1 << 5) +#define FACE_UV_ACTIVE (1 << 6) +#define FACE_UV_SELECT (1 << 7) +/* data[1] (2st byte flags) */ +#define VERT_ACTIVE (1 << 0) +#define VERT_SELECTED (1 << 1) +#define VERT_SELECTED_BEZT_HANDLE (1 << 2) +#define EDGE_ACTIVE (1 << 3) +#define EDGE_SELECTED (1 << 4) +#define EDGE_SEAM (1 << 5) +#define EDGE_SHARP (1 << 6) +#define EDGE_FREESTYLE (1 << 7) + +#define COMMON_GLOBALS_LIB diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c index 7e2ab2c6193..e06df334d23 100644 --- a/source/blender/draw/intern/draw_hair.c +++ b/source/blender/draw/intern/draw_hair.c @@ -172,8 +172,8 @@ static ParticleHairCache *drw_hair_particle_cache_get(Object *object, object, psys, md, &cache, gpu_material, subdiv, thickness_res); } else { - /* New hair object. */ - update = hair_ensure_procedural_data(object, &cache, gpu_material, subdiv, thickness_res); + /* New curves object. */ + update = curves_ensure_procedural_data(object, &cache, gpu_material, subdiv, thickness_res); } if (update) { @@ -230,7 +230,7 @@ void DRW_hair_duplimat_get(Object *object, } } else { - /* New hair object. */ + /* New curves object. */ copy_m4_m4(dupli_mat, object->obmat); } } @@ -291,7 +291,7 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object, hair_close_tip = (part->shape_flag & PART_SHAPE_CLOSE_TIP) != 0; } else { - /* TODO: implement for new hair object. */ + /* TODO: implement for new curves object. */ hair_rad_shape = 1.0f; hair_rad_root = 0.005f; hair_rad_tip = 0.0f; @@ -305,7 +305,7 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object, DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1); DRW_shgroup_uniform_int_copy(shgrp, "hairThicknessRes", thickness_res); DRW_shgroup_uniform_float_copy(shgrp, "hairRadShape", hair_rad_shape); - DRW_shgroup_uniform_vec4_array_copy(shgrp, "hairDupliMatrix", dupli_mat, 4); + DRW_shgroup_uniform_mat4_copy(shgrp, "hairDupliMatrix", dupli_mat); DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", hair_rad_root); DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", hair_rad_tip); DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", hair_close_tip); diff --git a/source/blender/draw/intern/draw_hair_private.h b/source/blender/draw/intern/draw_hair_private.h index 98a55d76373..58e8609106b 100644 --- a/source/blender/draw/intern/draw_hair_private.h +++ b/source/blender/draw/intern/draw_hair_private.h @@ -91,11 +91,11 @@ bool particles_ensure_procedural_data(struct Object *object, /** * Ensure all textures and buffers needed for GPU accelerated drawing. */ -bool hair_ensure_procedural_data(struct Object *object, - struct ParticleHairCache **r_hair_cache, - struct GPUMaterial *gpu_material, - int subdiv, - int thickness_res); +bool curves_ensure_procedural_data(struct Object *object, + struct ParticleHairCache **r_hair_cache, + struct GPUMaterial *gpu_material, + int subdiv, + int thickness_res); #ifdef __cplusplus } diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 39ae01697a1..75c27937f25 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -55,6 +55,7 @@ #include "GPU_framebuffer.h" #include "GPU_immediate.h" #include "GPU_matrix.h" +#include "GPU_platform.h" #include "GPU_shader_shared.h" #include "GPU_state.h" #include "GPU_uniform_buffer.h" @@ -1706,7 +1707,9 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, drw_engines_draw_scene(); /* Fix 3D view "lagging" on APPLE and WIN32+NVIDIA. (See T56996, T61474) */ - GPU_flush(); + if (GPU_type_matches_ex(GPU_DEVICE_ANY, GPU_OS_ANY, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) { + GPU_flush(); + } DRW_stats_reset(); @@ -1938,6 +1941,9 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) }; drw_context_state_init(); + /* Begin GPU workload Boundary */ + GPU_render_begin(); + const int size[2] = {engine->resolution_x, engine->resolution_y}; drw_manager_init(&DST, NULL, size); @@ -1993,6 +1999,9 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) /* Reset state after drawing */ DRW_state_reset(); + + /* End GPU workload Boundary */ + GPU_render_end(); } void DRW_render_object_iter( @@ -2072,7 +2081,10 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type, * resources as the main thread (viewport) may lead to data * races and undefined behavior on certain drivers. Using * GPU_finish to sync seems to fix the issue. (see T62997) */ - GPU_finish(); + eGPUBackendType type = GPU_backend_get_type(); + if (type == GPU_BACKEND_OPENGL) { + GPU_finish(); + } drw_manager_exit(&DST); } @@ -2173,7 +2185,9 @@ void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph, drw_engines_draw_scene(); /* Fix 3D view being "laggy" on macos and win+nvidia. (See T56996, T61474) */ - GPU_flush(); + if (GPU_type_matches_ex(GPU_DEVICE_ANY, GPU_OS_ANY, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) { + GPU_flush(); + } if (DST.draw_ctx.evil_C) { DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); @@ -3094,6 +3108,7 @@ void DRW_opengl_context_enable_ex(bool UNUSED(restore)) * This shall remain in effect until immediate mode supports * multiple threads. */ BLI_ticket_mutex_lock(DST.gl_context_mutex); + GPU_render_begin(); WM_opengl_context_activate(DST.gl_context); GPU_context_active_set(DST.gpu_context); } @@ -3105,7 +3120,9 @@ void DRW_opengl_context_disable_ex(bool restore) #ifdef __APPLE__ /* Need to flush before disabling draw context, otherwise it does not * always finish drawing and viewport can be empty or partially drawn */ - GPU_flush(); + if (GPU_type_matches_ex(GPU_DEVICE_ANY, GPU_OS_MAC, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) { + GPU_flush(); + } #endif if (BLI_thread_is_main() && restore) { @@ -3116,6 +3133,10 @@ void DRW_opengl_context_disable_ex(bool restore) GPU_context_active_set(NULL); } + /* Render boundaries are opened and closed here as this may be + * called outside of an existing render loop. */ + GPU_render_end(); + BLI_ticket_mutex_unlock(DST.gl_context_mutex); } } diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index b01c901c77f..8c7cd6d1648 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -485,10 +485,9 @@ void DRW_shgroup_uniform_vec4_copy(DRWShadingGroup *shgroup, const char *name, c drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT_COPY, value, 4, 1); } -void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup, - const char *name, - const float (*value)[4], - int arraysize) +void DRW_shgroup_uniform_mat4_copy(DRWShadingGroup *shgroup, + const char *name, + const float (*value)[4]) { int location = GPU_shader_get_uniform(shgroup->shader, name); @@ -498,9 +497,12 @@ void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup, return; } - for (int i = 0; i < arraysize; i++) { - drw_shgroup_uniform_create_ex( - shgroup, location + i, DRW_UNIFORM_FLOAT_COPY, &value[i], 0, 4, 1); + /* Each array element stored as an individual entry in the uniform list. + * All entries from the same array share the same base location, + * and array-size used to determine the number of elements + * copied in draw_update_uniforms. */ + for (int i = 0; i < 4; i++) { + drw_shgroup_uniform_create_ex(shgroup, location, DRW_UNIFORM_FLOAT_COPY, &value[i], 0, 4, 4); } } @@ -612,7 +614,7 @@ static void drw_call_obinfos_init(DRWObjectInfos *ob_infos, Object *ob) drw_call_calc_orco(ob, ob_infos->orcotexfac); /* Random float value. */ uint random = (DST.dupli_source) ? - DST.dupli_source->random_id : + DST.dupli_source->random_id : /* TODO(fclem): this is rather costly to do at runtime. Maybe we can * put it in ob->runtime and make depsgraph ensure it is up to date. */ BLI_hash_int_2d(BLI_hash_string(ob->id.name + 2), 0); @@ -636,7 +638,7 @@ static void drw_call_obinfos_init(DRWObjectInfos *ob_infos, Object *ob) static void drw_call_culling_init(DRWCullingState *cull, Object *ob) { - BoundBox *bbox; + const BoundBox *bbox; if (ob != NULL && (bbox = BKE_object_boundbox_get(ob))) { float corner[3]; /* Get BoundSphere center and radius from the BoundBox. */ diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 7d6ce51ff35..2c5b02f88a9 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -584,21 +584,60 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup, DRWCommandsState *state, bool *use_tfeedback) { +#define MAX_UNIFORM_STACK_SIZE 64 + + /* Uniform array elements stored as separate entries. We need to batch these together */ + int array_uniform_loc = -1; + int array_index = 0; + float mat4_stack[4 * 4]; + + /* Loop through uniforms in reverse order. */ for (DRWUniformChunk *unichunk = shgroup->uniforms; unichunk; unichunk = unichunk->next) { - DRWUniform *uni = unichunk->uniforms; - for (int i = 0; i < unichunk->uniform_used; i++, uni++) { + DRWUniform *uni = unichunk->uniforms + unichunk->uniform_used - 1; + + for (int i = 0; i < unichunk->uniform_used; i++, uni--) { + /* For uniform array copies, copy per-array-element data into local buffer before upload. */ + if (uni->arraysize > 1 && uni->type == DRW_UNIFORM_FLOAT_COPY) { + /* Only written for mat4 copy for now and is not meant to become generalized. */ + /* TODO(@fclem): Use UBOs/SSBOs instead of inline mat4 copies. */ + BLI_assert(uni->arraysize == 4 && uni->length == 4); + /* Begin copying uniform array. */ + if (array_uniform_loc == -1) { + array_uniform_loc = uni->location; + array_index = uni->arraysize * uni->length; + } + /* Debug check same array loc. */ + BLI_assert(array_uniform_loc > -1 && array_uniform_loc == uni->location); + /* Copy array element data to local buffer. */ + array_index -= uni->length; + memcpy(&mat4_stack[array_index], uni->fvalue, sizeof(float) * uni->length); + /* Flush array data to shader. */ + if (array_index <= 0) { + GPU_shader_uniform_vector(shgroup->shader, uni->location, 16, 1, mat4_stack); + array_uniform_loc = -1; + } + continue; + } + + /* Handle standard cases. */ switch (uni->type) { case DRW_UNIFORM_INT_COPY: - GPU_shader_uniform_vector_int( - shgroup->shader, uni->location, uni->length, uni->arraysize, uni->ivalue); + BLI_assert(uni->arraysize == 1); + if (uni->arraysize == 1) { + GPU_shader_uniform_vector_int( + shgroup->shader, uni->location, uni->length, uni->arraysize, uni->ivalue); + } break; case DRW_UNIFORM_INT: GPU_shader_uniform_vector_int( shgroup->shader, uni->location, uni->length, uni->arraysize, uni->pvalue); break; case DRW_UNIFORM_FLOAT_COPY: - GPU_shader_uniform_vector( - shgroup->shader, uni->location, uni->length, uni->arraysize, uni->fvalue); + BLI_assert(uni->arraysize == 1); + if (uni->arraysize == 1) { + GPU_shader_uniform_vector( + shgroup->shader, uni->location, uni->length, uni->arraysize, uni->fvalue); + } break; case DRW_UNIFORM_FLOAT: GPU_shader_uniform_vector( @@ -673,6 +712,10 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup, } } } + /* Ensure uniform arrays copied. */ + BLI_assert(array_index == 0); + BLI_assert(array_uniform_loc == -1); + UNUSED_VARS_NDEBUG(array_uniform_loc); } BLI_INLINE void draw_select_buffer(DRWShadingGroup *shgroup, diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c index 618d2f46e91..1936aa599ff 100644 --- a/source/blender/draw/intern/draw_manager_shader.c +++ b/source/blender/draw/intern/draw_manager_shader.c @@ -91,6 +91,7 @@ static void drw_deferred_shader_compilation_exec( short *do_update, float *progress) { + GPU_render_begin(); DRWShaderCompiler *comp = (DRWShaderCompiler *)custom_data; void *gl_context = comp->gl_context; GPUContext *gpu_context = comp->gpu_context; @@ -138,7 +139,9 @@ static void drw_deferred_shader_compilation_exec( *progress = (float)comp->shaders_done / (float)total; *do_update = true; - GPU_flush(); + if (GPU_type_matches_ex(GPU_DEVICE_ANY, GPU_OS_ANY, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) { + GPU_flush(); + } BLI_mutex_unlock(&comp->compilation_lock); BLI_spin_lock(&comp->list_lock); @@ -157,6 +160,7 @@ static void drw_deferred_shader_compilation_exec( if (use_main_context_workaround) { GPU_context_main_unlock(); } + GPU_render_end(); } static void drw_deferred_shader_compilation_free(void *custom_data) diff --git a/source/blender/draw/intern/draw_subdivision.h b/source/blender/draw/intern/draw_subdivision.h index 41d177a644a..8d7bc3dc495 100644 --- a/source/blender/draw/intern/draw_subdivision.h +++ b/source/blender/draw/intern/draw_subdivision.h @@ -130,6 +130,8 @@ typedef struct DRWSubdivCache { /* Maps subdivision loop to subdivided vertex index. */ int *subdiv_loop_subdiv_vert_index; + /* Maps subdivision loop to subdivided edge index. */ + int *subdiv_loop_subdiv_edge_index; /* Maps subdivision loop to original coarse poly index. */ int *subdiv_loop_poly_index; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc index 9d799feabc6..286c7ea9c43 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc @@ -11,6 +11,7 @@ #include "MEM_guardedalloc.h" +#include "draw_subdivision.h" #include "extract_mesh.h" namespace blender::draw { @@ -87,12 +88,88 @@ static void extract_lines_paint_mask_finish(const MeshRenderData *UNUSED(mr), MEM_freeN(data->select_map); } +static void extract_lines_paint_mask_init_subdiv(const DRWSubdivCache *subdiv_cache, + const MeshRenderData *mr, + MeshBatchCache *UNUSED(cache), + void *UNUSED(buf), + void *tls_data) +{ + MeshExtract_LinePaintMask_Data *data = static_cast<MeshExtract_LinePaintMask_Data *>(tls_data); + data->select_map = BLI_BITMAP_NEW(mr->edge_len, __func__); + GPU_indexbuf_init(&data->elb, + GPU_PRIM_LINES, + subdiv_cache->num_subdiv_edges, + subdiv_cache->num_subdiv_loops * 2); +} + +static void extract_lines_paint_mask_iter_subdiv_mesh(const DRWSubdivCache *subdiv_cache, + const MeshRenderData *mr, + void *_data, + uint subdiv_quad_index, + const MPoly *coarse_quad) +{ + MeshExtract_LinePaintMask_Data *data = static_cast<MeshExtract_LinePaintMask_Data *>(_data); + int *subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(subdiv_cache->edges_orig_index); + int *subdiv_loop_subdiv_edge_index = subdiv_cache->subdiv_loop_subdiv_edge_index; + + uint start_loop_idx = subdiv_quad_index * 4; + uint end_loop_idx = (subdiv_quad_index + 1) * 4; + for (uint loop_idx = start_loop_idx; loop_idx < end_loop_idx; loop_idx++) { + const uint coarse_edge_index = (uint)subdiv_loop_edge_index[loop_idx]; + const uint subdiv_edge_index = (uint)subdiv_loop_subdiv_edge_index[loop_idx]; + + if (coarse_edge_index == -1u) { + GPU_indexbuf_set_line_restart(&data->elb, subdiv_edge_index); + } + else { + const MEdge *me = &mr->medge[coarse_edge_index]; + if (!((mr->use_hide && (me->flag & ME_HIDE)) || + ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) && + (mr->e_origindex[coarse_edge_index] == ORIGINDEX_NONE)))) { + const uint ml_index_other = (loop_idx == end_loop_idx) ? start_loop_idx : loop_idx + 1; + if (coarse_quad->flag & ME_FACE_SEL) { + if (BLI_BITMAP_TEST_AND_SET_ATOMIC(data->select_map, coarse_edge_index)) { + /* Hide edge as it has more than 2 selected loop. */ + GPU_indexbuf_set_line_restart(&data->elb, subdiv_edge_index); + } + else { + /* First selected loop. Set edge visible, overwriting any unselected loop. */ + GPU_indexbuf_set_line_verts(&data->elb, subdiv_edge_index, loop_idx, ml_index_other); + } + } + else { + /* Set these unselected loop only if this edge has no other selected loop. */ + if (!BLI_BITMAP_TEST(data->select_map, coarse_edge_index)) { + GPU_indexbuf_set_line_verts(&data->elb, subdiv_edge_index, loop_idx, ml_index_other); + } + } + } + else { + GPU_indexbuf_set_line_restart(&data->elb, subdiv_edge_index); + } + } + } +} + +static void extract_lines_paint_mask_finish_subdiv( + const struct DRWSubdivCache *UNUSED(subdiv_cache), + const MeshRenderData *mr, + struct MeshBatchCache *cache, + void *buf, + void *_data) +{ + extract_lines_paint_mask_finish(mr, cache, buf, _data); +} + constexpr MeshExtract create_extractor_lines_paint_mask() { MeshExtract extractor = {nullptr}; extractor.init = extract_lines_paint_mask_init; extractor.iter_poly_mesh = extract_lines_paint_mask_iter_poly_mesh; extractor.finish = extract_lines_paint_mask_finish; + extractor.init_subdiv = extract_lines_paint_mask_init_subdiv; + extractor.iter_subdiv_mesh = extract_lines_paint_mask_iter_subdiv_mesh; + extractor.finish_subdiv = extract_lines_paint_mask_finish_subdiv; extractor.data_type = MR_DATA_NONE; extractor.data_size = sizeof(MeshExtract_LinePaintMask_Data); extractor.use_threading = false; diff --git a/source/blender/draw/intern/shaders/common_colormanagement_lib.glsl b/source/blender/draw/intern/shaders/common_colormanagement_lib.glsl index 45f711296f3..92d13c6d48b 100644 --- a/source/blender/draw/intern/shaders/common_colormanagement_lib.glsl +++ b/source/blender/draw/intern/shaders/common_colormanagement_lib.glsl @@ -12,19 +12,19 @@ vec4 texture_read_as_linearrgb(sampler2D tex, bool premultiplied, vec2 co) { /* By convention image textures return scene linear colors, but * overlays still assume srgb. */ - vec4 color = texture(tex, co); + vec4 col = texture(tex, co); /* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */ - if (premultiplied && !(color.a == 0.0 || color.a == 1.0)) { - color.rgb = color.rgb / color.a; + if (premultiplied && !(col.a == 0.0 || col.a == 1.0)) { + col.rgb = col.rgb / col.a; } - return color; + return col; } vec4 texture_read_as_srgb(sampler2D tex, bool premultiplied, vec2 co) { - vec4 color = texture_read_as_linearrgb(tex, premultiplied, co); - color.r = linearrgb_to_srgb(color.r); - color.g = linearrgb_to_srgb(color.g); - color.b = linearrgb_to_srgb(color.b); - return color; + vec4 col = texture_read_as_linearrgb(tex, premultiplied, co); + col.r = linearrgb_to_srgb(col.r); + col.g = linearrgb_to_srgb(col.g); + col.b = linearrgb_to_srgb(col.b); + return col; } diff --git a/source/blender/draw/intern/shaders/common_gpencil_lib.glsl b/source/blender/draw/intern/shaders/common_gpencil_lib.glsl index 9e3c219a30b..0610bc4e57d 100644 --- a/source/blender/draw/intern/shaders/common_gpencil_lib.glsl +++ b/source/blender/draw/intern/shaders/common_gpencil_lib.glsl @@ -81,7 +81,7 @@ float gpencil_stroke_thickness_modulate(float thickness, vec4 ndc_pos, vec4 view float gpencil_clamp_small_stroke_thickness(float thickness, vec4 ndc_pos) { /* To avoid aliasing artifacts, we clamp the line thickness and - * reduce its opacity in the fragment shader.*/ + * reduce its opacity in the fragment shader. */ float min_thickness = ndc_pos.w * 1.3; thickness = max(min_thickness, thickness); @@ -169,7 +169,7 @@ vec4 gpencil_vertex(ivec4 ma, if (GPENCIL_IS_STROKE_VERTEX) { bool is_dot = flag_test(material_flags, GP_STROKE_ALIGNMENT); - bool is_squares = !flag_test(material_flags, GP_STROKE_ALIGNMENT); + bool is_squares = !flag_test(material_flags, GP_STROKE_DOTS); /* Special Case. Stroke with single vert are rendered as dots. Do not discard them. */ if (!is_dot && ma.x == -1 && ma2.x == -1) { diff --git a/source/blender/draw/intern/shaders/common_hair_lib.glsl b/source/blender/draw/intern/shaders/common_hair_lib.glsl index 7f94b7ea1c1..6a8f1132e1b 100644 --- a/source/blender/draw/intern/shaders/common_hair_lib.glsl +++ b/source/blender/draw/intern/shaders/common_hair_lib.glsl @@ -29,7 +29,7 @@ uniform float hairRadTip = 0.0; uniform float hairRadShape = 0.5; uniform bool hairCloseTip = true; -uniform vec4 hairDupliMatrix[4]; +uniform mat4 hairDupliMatrix; /* Strand batch offset when used in compute shaders. */ uniform int hairStrandOffset = 0; @@ -192,9 +192,7 @@ void hair_get_pos_tan_binor_time(bool is_persp, wtan = wpos - texelFetch(hairPointBuffer, id - 1).point_position; } - mat4 obmat = mat4( - hairDupliMatrix[0], hairDupliMatrix[1], hairDupliMatrix[2], hairDupliMatrix[3]); - + mat4 obmat = hairDupliMatrix; wpos = (obmat * vec4(wpos, 1.0)).xyz; wtan = -normalize(mat3(obmat) * wtan); diff --git a/source/blender/draw/intern/shaders/common_subdiv_lib.glsl b/source/blender/draw/intern/shaders/common_subdiv_lib.glsl index 5d71c5e4bb8..ce324249446 100644 --- a/source/blender/draw/intern/shaders/common_subdiv_lib.glsl +++ b/source/blender/draw/intern/shaders/common_subdiv_lib.glsl @@ -107,6 +107,10 @@ struct PosNorLoop { float flag; }; +struct LoopNormal { + float nx, ny, nz, flag; +}; + vec3 get_vertex_pos(PosNorLoop vertex_data) { return vec3(vertex_data.x, vertex_data.y, vertex_data.z); @@ -117,6 +121,16 @@ vec3 get_vertex_nor(PosNorLoop vertex_data) return vec3(vertex_data.nx, vertex_data.ny, vertex_data.nz); } +LoopNormal get_normal_and_flag(PosNorLoop vertex_data) +{ + LoopNormal loop_nor; + loop_nor.nx = vertex_data.nx; + loop_nor.ny = vertex_data.ny; + loop_nor.nz = vertex_data.nz; + loop_nor.flag = vertex_data.flag; + return loop_nor; +} + void set_vertex_pos(inout PosNorLoop vertex_data, vec3 pos) { vertex_data.x = pos.x; diff --git a/source/blender/draw/intern/shaders/common_subdiv_vbo_lnor_comp.glsl b/source/blender/draw/intern/shaders/common_subdiv_vbo_lnor_comp.glsl index b7e04e240fb..b7bcfd2d369 100644 --- a/source/blender/draw/intern/shaders/common_subdiv_vbo_lnor_comp.glsl +++ b/source/blender/draw/intern/shaders/common_subdiv_vbo_lnor_comp.glsl @@ -13,9 +13,14 @@ layout(std430, binding = 2) readonly buffer extraCoarseFaceData layout(std430, binding = 3) writeonly buffer outputLoopNormals { - vec3 output_lnor[]; + LoopNormal output_lnor[]; }; +bool is_face_selected(uint coarse_quad_index) +{ + return (extra_coarse_face_data[coarse_quad_index] & coarse_face_select_mask) != 0; +} + void main() { /* We execute for each quad. */ @@ -34,7 +39,7 @@ void main() /* Face is smooth, use vertex normals. */ for (int i = 0; i < 4; i++) { PosNorLoop pos_nor_loop = pos_nor[start_loop_index + i]; - output_lnor[start_loop_index + i] = get_vertex_nor(pos_nor_loop); + output_lnor[start_loop_index + i] = get_normal_and_flag(pos_nor_loop); } } else { @@ -50,8 +55,19 @@ void main() add_newell_cross_v3_v3v3(face_normal, v3, v0); face_normal = normalize(face_normal); + + LoopNormal loop_normal; + loop_normal.nx = face_normal.x; + loop_normal.ny = face_normal.y; + loop_normal.nz = face_normal.z; + loop_normal.flag = 0.0; + + if (is_face_selected(coarse_quad_index)) { + loop_normal.flag = 1.0; + } + for (int i = 0; i < 4; i++) { - output_lnor[start_loop_index + i] = face_normal; + output_lnor[start_loop_index + i] = loop_normal; } } } diff --git a/source/blender/draw/intern/shaders/common_view_clipping_lib.glsl b/source/blender/draw/intern/shaders/common_view_clipping_lib.glsl index d55808c42d2..bae818cf9f3 100644 --- a/source/blender/draw/intern/shaders/common_view_clipping_lib.glsl +++ b/source/blender/draw/intern/shaders/common_view_clipping_lib.glsl @@ -6,13 +6,13 @@ void view_clipping_distances(vec3 wpos) { # ifdef USE_WORLD_CLIP_PLANES - vec4 pos = vec4(wpos, 1.0); - gl_ClipDistance[0] = dot(drw_view.clip_planes[0], pos); - gl_ClipDistance[1] = dot(drw_view.clip_planes[1], pos); - gl_ClipDistance[2] = dot(drw_view.clip_planes[2], pos); - gl_ClipDistance[3] = dot(drw_view.clip_planes[3], pos); - gl_ClipDistance[4] = dot(drw_view.clip_planes[4], pos); - gl_ClipDistance[5] = dot(drw_view.clip_planes[5], pos); + vec4 pos_4d = vec4(wpos, 1.0); + gl_ClipDistance[0] = dot(drw_view.clip_planes[0], pos_4d); + gl_ClipDistance[1] = dot(drw_view.clip_planes[1], pos_4d); + gl_ClipDistance[2] = dot(drw_view.clip_planes[2], pos_4d); + gl_ClipDistance[3] = dot(drw_view.clip_planes[3], pos_4d); + gl_ClipDistance[4] = dot(drw_view.clip_planes[4], pos_4d); + gl_ClipDistance[5] = dot(drw_view.clip_planes[5], pos_4d); # endif } diff --git a/source/blender/draw/intern/shaders/common_view_lib.glsl b/source/blender/draw/intern/shaders/common_view_lib.glsl index 6c58752c8bb..a2b8cb4bbd6 100644 --- a/source/blender/draw/intern/shaders/common_view_lib.glsl +++ b/source/blender/draw/intern/shaders/common_view_lib.glsl @@ -47,6 +47,7 @@ layout(std140) uniform viewBlock #endif #ifdef COMMON_GLOBALS_LIB +/* TODO move to overlay engine. */ float mul_project_m4_v3_zfac(in vec3 co) { return pixelFac * ((ViewProjectionMatrix[0][3] * co.x) + (ViewProjectionMatrix[1][3] * co.y) + diff --git a/source/blender/draw/intern/shaders/draw_hair_refine_info.hh b/source/blender/draw/intern/shaders/draw_hair_refine_info.hh index 16766ffee18..b80537f9deb 100644 --- a/source/blender/draw/intern/shaders/draw_hair_refine_info.hh +++ b/source/blender/draw/intern/shaders/draw_hair_refine_info.hh @@ -13,7 +13,7 @@ GPU_SHADER_CREATE_INFO(draw_hair_refine_compute) .sampler(0, ImageType::FLOAT_BUFFER, "hairPointBuffer") .sampler(1, ImageType::UINT_BUFFER, "hairStrandBuffer") .sampler(2, ImageType::UINT_BUFFER, "hairStrandSegBuffer") - .push_constant(Type::VEC4, "hairDupliMatrix", 4) + .push_constant(Type::MAT4, "hairDupliMatrix") .push_constant(Type::BOOL, "hairCloseTip") .push_constant(Type::FLOAT, "hairRadShape") .push_constant(Type::FLOAT, "hairRadTip") diff --git a/source/blender/draw/intern/shaders/draw_view_info.hh b/source/blender/draw/intern/shaders/draw_view_info.hh index a699b9013ef..7329f2ed677 100644 --- a/source/blender/draw/intern/shaders/draw_view_info.hh +++ b/source/blender/draw/intern/shaders/draw_view_info.hh @@ -75,6 +75,16 @@ GPU_SHADER_CREATE_INFO(drw_clipped).define("USE_WORLD_CLIP_PLANES"); /** \} */ /* -------------------------------------------------------------------- */ +/** \name Draw Globals + * \{ */ + +GPU_SHADER_CREATE_INFO(draw_globals) + .typedef_source("draw_common_shader_shared.h") + .uniform_buf(1, "GlobalsUboStorage", "globalsBlock", Frequency::PASS); + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Geometry Type * \{ */ @@ -92,7 +102,7 @@ GPU_SHADER_CREATE_INFO(draw_hair) .push_constant(Type::FLOAT, "hairRadShape") .push_constant(Type::BOOL, "hairCloseTip") .push_constant(Type::INT, "hairStrandOffset") - .push_constant(Type::VEC4, "hairDupliMatrix", 4) + .push_constant(Type::MAT4, "hairDupliMatrix") .additional_info("draw_modelmat", "draw_resource_id"); GPU_SHADER_CREATE_INFO(draw_pointcloud) diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 5169d6904f5..ed0befbcc24 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -5117,8 +5117,9 @@ static void draw_setting_widget(bAnimContext *ac, break; } - if ((ale->fcurve_owner_id != NULL && ID_IS_LINKED(ale->fcurve_owner_id)) || - (ale->id != NULL && ID_IS_LINKED(ale->id))) { + if ((ale->fcurve_owner_id != NULL && + (ID_IS_LINKED(ale->fcurve_owner_id) || ID_IS_OVERRIDE_LIBRARY(ale->fcurve_owner_id))) || + (ale->id != NULL && (ID_IS_LINKED(ale->id) || ID_IS_OVERRIDE_LIBRARY(ale->id)))) { if (setting != ACHANNEL_SETTING_EXPAND) { UI_but_flag_enable(but, UI_BUT_DISABLED); } diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 08379be36fa..31d90c8bfec 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -2789,8 +2789,9 @@ static bool rename_anim_channels(bAnimContext *ac, int channel_index) } /* don't allow renaming linked channels */ - if ((ale->fcurve_owner_id != NULL && ID_IS_LINKED(ale->fcurve_owner_id)) || - (ale->id != NULL && ID_IS_LINKED(ale->id))) { + if ((ale->fcurve_owner_id != NULL && + (ID_IS_LINKED(ale->fcurve_owner_id) || ID_IS_OVERRIDE_LIBRARY(ale->fcurve_owner_id))) || + (ale->id != NULL && (ID_IS_LINKED(ale->id) || ID_IS_OVERRIDE_LIBRARY(ale->id)))) { ANIM_animdata_freelist(&anim_data); return false; } diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 0389e57627a..a75944fa2f2 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -1462,7 +1462,7 @@ static size_t animfilter_action(bAnimContext *ac, /* don't include anything from this action if it is linked in from another file, * and we're getting stuff for editing... */ - if ((filter_mode & ANIMFILTER_FOREDIT) && ID_IS_LINKED(act)) { + if ((filter_mode & ANIMFILTER_FOREDIT) && (ID_IS_LINKED(act) || ID_IS_OVERRIDE_LIBRARY(act))) { return 0; } diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index f40c1b983d7..58d093c678d 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -659,7 +659,8 @@ void draw_fcurve_channel(AnimKeylistDrawList *draw_list, { const bool locked = (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) || - ((adt && adt->action) && ID_IS_LINKED(adt->action)); + ((adt && adt->action) && + (ID_IS_LINKED(adt->action) || ID_IS_OVERRIDE_LIBRARY(adt->action))); AnimKeylistDrawListElem *draw_elem = ed_keylist_draw_list_add_elem( draw_list, ANIM_KEYLIST_FCURVE, ypos, yscale_fac, saction_flag); @@ -676,7 +677,8 @@ void draw_agroup_channel(AnimKeylistDrawList *draw_list, int saction_flag) { bool locked = (agrp->flag & AGRP_PROTECTED) || - ((adt && adt->action) && ID_IS_LINKED(adt->action)); + ((adt && adt->action) && + (ID_IS_LINKED(adt->action) || ID_IS_OVERRIDE_LIBRARY(adt->action))); AnimKeylistDrawListElem *draw_elem = ed_keylist_draw_list_add_elem( draw_list, ANIM_KEYLIST_AGROUP, ypos, yscale_fac, saction_flag); @@ -692,7 +694,7 @@ void draw_action_channel(AnimKeylistDrawList *draw_list, float yscale_fac, int saction_flag) { - const bool locked = (act && ID_IS_LINKED(act)); + const bool locked = (act && (ID_IS_LINKED(act) || ID_IS_OVERRIDE_LIBRARY(act))); saction_flag &= ~SACTION_SHOW_EXTREMES; AnimKeylistDrawListElem *draw_elem = ed_keylist_draw_list_add_elem( diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index 31caa29a02a..7016511111e 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -59,7 +59,7 @@ static void error(const char *str) struct LaplacianSystem { LinearSolver *context; /* linear solver */ - int totvert, totface; + int verts_num, faces_num; float **verts; /* vertex coordinates */ float *varea; /* vertex weights for laplacian computation */ @@ -76,8 +76,8 @@ struct LaplacianSystem { struct HeatWeighting { const MLoopTri *mlooptri; const MLoop *mloop; /* needed to find vertices by index */ - int totvert; - int tottri; + int verts_num; + int tris_num; float (*verts)[3]; /* vertex coordinates */ float (*vnors)[3]; /* vertex normals */ @@ -202,28 +202,28 @@ static void laplacian_triangle_weights(LaplacianSystem *sys, int f, int i1, int } } -static LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface, int lsq) +static LaplacianSystem *laplacian_system_construct_begin(int verts_num, int faces_num, int lsq) { LaplacianSystem *sys; sys = MEM_callocN(sizeof(LaplacianSystem), "LaplacianSystem"); - sys->verts = MEM_callocN(sizeof(float *) * totvert, "LaplacianSystemVerts"); - sys->vpinned = MEM_callocN(sizeof(char) * totvert, "LaplacianSystemVpinned"); - sys->faces = MEM_callocN(sizeof(int[3]) * totface, "LaplacianSystemFaces"); + sys->verts = MEM_callocN(sizeof(float *) * verts_num, "LaplacianSystemVerts"); + sys->vpinned = MEM_callocN(sizeof(char) * verts_num, "LaplacianSystemVpinned"); + sys->faces = MEM_callocN(sizeof(int[3]) * faces_num, "LaplacianSystemFaces"); - sys->totvert = 0; - sys->totface = 0; + sys->verts_num = 0; + sys->faces_num = 0; sys->areaweights = 1; sys->storeweights = 0; /* create linear solver */ if (lsq) { - sys->context = EIG_linear_least_squares_solver_new(0, totvert, 1); + sys->context = EIG_linear_least_squares_solver_new(0, verts_num, 1); } else { - sys->context = EIG_linear_solver_new(0, totvert, 1); + sys->context = EIG_linear_solver_new(0, verts_num, 1); } return sys; @@ -231,42 +231,43 @@ static LaplacianSystem *laplacian_system_construct_begin(int totvert, int totfac void laplacian_add_vertex(LaplacianSystem *sys, float *co, int pinned) { - sys->verts[sys->totvert] = co; - sys->vpinned[sys->totvert] = pinned; - sys->totvert++; + sys->verts[sys->verts_num] = co; + sys->vpinned[sys->verts_num] = pinned; + sys->verts_num++; } void laplacian_add_triangle(LaplacianSystem *sys, int v1, int v2, int v3) { - sys->faces[sys->totface][0] = v1; - sys->faces[sys->totface][1] = v2; - sys->faces[sys->totface][2] = v3; - sys->totface++; + sys->faces[sys->faces_num][0] = v1; + sys->faces[sys->faces_num][1] = v2; + sys->faces[sys->faces_num][2] = v3; + sys->faces_num++; } static void laplacian_system_construct_end(LaplacianSystem *sys) { int(*face)[3]; - int a, totvert = sys->totvert, totface = sys->totface; + int a, verts_num = sys->verts_num, faces_num = sys->faces_num; laplacian_begin_solve(sys, 0); - sys->varea = MEM_callocN(sizeof(float) * totvert, "LaplacianSystemVarea"); + sys->varea = MEM_callocN(sizeof(float) * verts_num, "LaplacianSystemVarea"); - sys->edgehash = BLI_edgehash_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(sys->totface)); - for (a = 0, face = sys->faces; a < sys->totface; a++, face++) { + sys->edgehash = BLI_edgehash_new_ex(__func__, + BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(sys->faces_num)); + for (a = 0, face = sys->faces; a < sys->faces_num; a++, face++) { laplacian_increase_edge_count(sys->edgehash, (*face)[0], (*face)[1]); laplacian_increase_edge_count(sys->edgehash, (*face)[1], (*face)[2]); laplacian_increase_edge_count(sys->edgehash, (*face)[2], (*face)[0]); } if (sys->areaweights) { - for (a = 0, face = sys->faces; a < sys->totface; a++, face++) { + for (a = 0, face = sys->faces; a < sys->faces_num; a++, face++) { laplacian_triangle_area(sys, (*face)[0], (*face)[1], (*face)[2]); } } - for (a = 0; a < totvert; a++) { + for (a = 0; a < verts_num; a++) { if (sys->areaweights) { if (sys->varea[a] != 0.0f) { sys->varea[a] = 0.5f / sys->varea[a]; @@ -283,10 +284,10 @@ static void laplacian_system_construct_end(LaplacianSystem *sys) } if (sys->storeweights) { - sys->fweights = MEM_callocN(sizeof(float[3]) * totface, "LaplacianFWeight"); + sys->fweights = MEM_callocN(sizeof(float[3]) * faces_num, "LaplacianFWeight"); } - for (a = 0, face = sys->faces; a < totface; a++, face++) { + for (a = 0, face = sys->faces; a < faces_num; a++, face++) { laplacian_triangle_weights(sys, a, (*face)[0], (*face)[1], (*face)[2]); } @@ -327,7 +328,7 @@ void laplacian_begin_solve(LaplacianSystem *sys, int index) if (!sys->variablesdone) { if (index >= 0) { - for (a = 0; a < sys->totvert; a++) { + for (a = 0; a < sys->verts_num; a++) { if (sys->vpinned[a]) { EIG_linear_solver_variable_set(sys->context, 0, a, sys->verts[a][index]); EIG_linear_solver_variable_lock(sys->context, a); @@ -411,14 +412,14 @@ static void heat_ray_tree_create(LaplacianSystem *sys) const MLoopTri *looptri = sys->heat.mlooptri; const MLoop *mloop = sys->heat.mloop; float(*verts)[3] = sys->heat.verts; - int tottri = sys->heat.tottri; - int totvert = sys->heat.totvert; + int tris_num = sys->heat.tris_num; + int verts_num = sys->heat.verts_num; int a; - sys->heat.bvhtree = BLI_bvhtree_new(tottri, 0.0f, 4, 6); - sys->heat.vltree = MEM_callocN(sizeof(MLoopTri *) * totvert, "HeatVFaces"); + sys->heat.bvhtree = BLI_bvhtree_new(tris_num, 0.0f, 4, 6); + sys->heat.vltree = MEM_callocN(sizeof(MLoopTri *) * verts_num, "HeatVFaces"); - for (a = 0; a < tottri; a++) { + for (a = 0; a < tris_num; a++) { const MLoopTri *lt = &looptri[a]; float bb[6]; int vtri[3]; @@ -552,9 +553,9 @@ static void heat_calc_vnormals(LaplacianSystem *sys) float fnor[3]; int a, v1, v2, v3, (*face)[3]; - sys->heat.vnors = MEM_callocN(sizeof(float[3]) * sys->totvert, "HeatVNors"); + sys->heat.vnors = MEM_callocN(sizeof(float[3]) * sys->verts_num, "HeatVNors"); - for (a = 0, face = sys->faces; a < sys->totface; a++, face++) { + for (a = 0, face = sys->faces; a < sys->faces_num; a++, face++) { v1 = (*face)[0]; v2 = (*face)[1]; v3 = (*face)[2]; @@ -566,7 +567,7 @@ static void heat_calc_vnormals(LaplacianSystem *sys) add_v3_v3(sys->heat.vnors[v3], fnor); } - for (a = 0; a < sys->totvert; a++) { + for (a = 0; a < sys->verts_num; a++) { normalize_v3(sys->heat.vnors[a]); } } @@ -575,21 +576,21 @@ static void heat_laplacian_create(LaplacianSystem *sys) { const MLoopTri *mlooptri = sys->heat.mlooptri, *lt; const MLoop *mloop = sys->heat.mloop; - int tottri = sys->heat.tottri; - int totvert = sys->heat.totvert; + int tris_num = sys->heat.tris_num; + int verts_num = sys->heat.verts_num; int a; /* heat specific definitions */ - sys->heat.mindist = MEM_callocN(sizeof(float) * totvert, "HeatMinDist"); - sys->heat.H = MEM_callocN(sizeof(float) * totvert, "HeatH"); - sys->heat.p = MEM_callocN(sizeof(float) * totvert, "HeatP"); + sys->heat.mindist = MEM_callocN(sizeof(float) * verts_num, "HeatMinDist"); + sys->heat.H = MEM_callocN(sizeof(float) * verts_num, "HeatH"); + sys->heat.p = MEM_callocN(sizeof(float) * verts_num, "HeatP"); /* add verts and faces to laplacian */ - for (a = 0; a < totvert; a++) { + for (a = 0; a < verts_num; a++) { laplacian_add_vertex(sys, sys->heat.verts[a], 0); } - for (a = 0, lt = mlooptri; a < tottri; a++, lt++) { + for (a = 0, lt = mlooptri; a < tris_num; a++, lt++) { int vtri[3]; vtri[0] = mloop[lt->tri[0]].v; vtri[1] = mloop[lt->tri[1]].v; @@ -600,7 +601,7 @@ static void heat_laplacian_create(LaplacianSystem *sys) /* for distance computation in set_H */ heat_calc_vnormals(sys); - for (a = 0; a < totvert; a++) { + for (a = 0; a < verts_num; a++) { heat_set_H(sys, a); } } @@ -648,7 +649,7 @@ void heat_bone_weighting(Object *ob, MLoop *ml; float solution, weight; int *vertsflipped = NULL, *mask = NULL; - int a, tottri, j, bbone, firstsegment, lastsegment; + int a, tris_num, j, bbone, firstsegment, lastsegment; bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; MVert *mvert = me->mvert; @@ -658,7 +659,7 @@ void heat_bone_weighting(Object *ob, *error_str = NULL; /* bone heat needs triangulated faces */ - tottri = poly_to_tri_count(me->totpoly, me->totloop); + tris_num = poly_to_tri_count(me->totpoly, me->totloop); /* count triangles and create mask */ if (ob->mode & OB_MODE_WEIGHT_PAINT && (use_face_sel || use_vert_sel)) { @@ -684,16 +685,16 @@ void heat_bone_weighting(Object *ob, } /* create laplacian */ - sys = laplacian_system_construct_begin(me->totvert, tottri, 1); + sys = laplacian_system_construct_begin(me->totvert, tris_num, 1); - sys->heat.tottri = poly_to_tri_count(me->totpoly, me->totloop); - mlooptri = MEM_mallocN(sizeof(*sys->heat.mlooptri) * sys->heat.tottri, __func__); + sys->heat.tris_num = poly_to_tri_count(me->totpoly, me->totloop); + mlooptri = MEM_mallocN(sizeof(*sys->heat.mlooptri) * sys->heat.tris_num, __func__); BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, mlooptri); sys->heat.mlooptri = mlooptri; sys->heat.mloop = me->mloop; - sys->heat.totvert = me->totvert; + sys->heat.verts_num = me->totvert; sys->heat.verts = verts; sys->heat.root = root; sys->heat.tip = tip; @@ -886,7 +887,7 @@ typedef struct MeshDeformBind { Mesh *cagemesh; float (*cagecos)[3]; float (*vertexcos)[3]; - int totvert, totcagevert; + int verts_num, cage_verts_num; /* grids */ MemArena *memarena; @@ -1467,7 +1468,7 @@ static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind } /* solve for each cage vert */ - for (a = 0; a < mdb->totcagevert; a++) { + for (a = 0; a < mdb->cage_verts_num; a++) { /* fill in right hand side and solve */ for (z = 0; z < mdb->size; z++) { for (y = 0; y < mdb->size; y++) { @@ -1503,14 +1504,14 @@ static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind if (mdb->weights) { /* static bind : compute weights for each vertex */ - for (b = 0; b < mdb->totvert; b++) { + for (b = 0; b < mdb->verts_num; b++) { if (mdb->inside[b]) { copy_v3_v3(vec, mdb->vertexcos[b]); gridvec[0] = (vec[0] - mdb->min[0] - mdb->halfwidth[0]) / mdb->width[0]; gridvec[1] = (vec[1] - mdb->min[1] - mdb->halfwidth[1]) / mdb->width[1]; gridvec[2] = (vec[2] - mdb->min[2] - mdb->halfwidth[2]) / mdb->width[2]; - mdb->weights[b * mdb->totcagevert + a] = meshdeform_interp_w(mdb, gridvec, vec, a); + mdb->weights[b * mdb->cage_verts_num + a] = meshdeform_interp_w(mdb, gridvec, vec, a); } } } @@ -1536,9 +1537,12 @@ static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind break; } - BLI_snprintf( - message, sizeof(message), "Mesh deform solve %d / %d |||", a + 1, mdb->totcagevert); - progress_bar((float)(a + 1) / (float)(mdb->totcagevert), message); + BLI_snprintf(message, + sizeof(message), + "Mesh deform solve %d / %d |||", + a + 1, + mdb->cage_verts_num); + progress_bar((float)(a + 1) / (float)(mdb->cage_verts_num), message); } #if 0 @@ -1573,7 +1577,7 @@ static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBin /* compute bounding box of the cage mesh */ INIT_MINMAX(mdb->min, mdb->max); - for (a = 0; a < mdb->totcagevert; a++) { + for (a = 0; a < mdb->cage_verts_num; a++) { minmax_v3v3_v3(mdb->min, mdb->max, mdb->cagecos[a]); } @@ -1586,13 +1590,14 @@ static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBin mdb->boundisect = MEM_callocN(sizeof(*mdb->boundisect) * mdb->size3, "MDefBoundIsect"); mdb->semibound = MEM_callocN(sizeof(int) * mdb->size3, "MDefSemiBound"); mdb->bvhtree = BKE_bvhtree_from_mesh_get(&mdb->bvhdata, mdb->cagemesh, BVHTREE_FROM_LOOPTRI, 4); - mdb->inside = MEM_callocN(sizeof(int) * mdb->totvert, "MDefInside"); + mdb->inside = MEM_callocN(sizeof(int) * mdb->verts_num, "MDefInside"); if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) { mdb->dyngrid = MEM_callocN(sizeof(MDefBindInfluence *) * mdb->size3, "MDefDynGrid"); } else { - mdb->weights = MEM_callocN(sizeof(float) * mdb->totvert * mdb->totcagevert, "MDefWeights"); + mdb->weights = MEM_callocN(sizeof(float) * mdb->verts_num * mdb->cage_verts_num, + "MDefWeights"); } mdb->memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "harmonic coords arena"); @@ -1632,7 +1637,7 @@ static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBin progress_bar(0, "Setting up mesh deform system"); totinside = 0; - for (a = 0; a < mdb->totvert; a++) { + for (a = 0; a < mdb->verts_num; a++) { copy_v3_v3(vec, mdb->vertexcos[a]); mdb->inside[a] = meshdeform_inside_cage(mdb, vec); if (mdb->inside[a]) { @@ -1674,16 +1679,16 @@ static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBin /* assign results */ if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) { - mmd->totinfluence = 0; + mmd->influences_num = 0; for (a = 0; a < mdb->size3; a++) { for (inf = mdb->dyngrid[a]; inf; inf = inf->next) { - mmd->totinfluence++; + mmd->influences_num++; } } /* convert MDefBindInfluences to smaller MDefInfluences */ mmd->dyngrid = MEM_callocN(sizeof(MDefCell) * mdb->size3, "MDefDynGrid"); - mmd->dyninfluences = MEM_callocN(sizeof(MDefInfluence) * mmd->totinfluence, "MDefInfluence"); + mmd->dyninfluences = MEM_callocN(sizeof(MDefInfluence) * mmd->influences_num, "MDefInfluence"); offset = 0; for (a = 0; a < mdb->size3; a++) { cell = &mmd->dyngrid[a]; @@ -1695,17 +1700,17 @@ static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBin mdinf->weight = inf->weight; mdinf->vertex = inf->vertex; totweight += mdinf->weight; - cell->totinfluence++; + cell->influences_num++; } if (totweight > 0.0f) { mdinf = mmd->dyninfluences + cell->offset; - for (b = 0; b < cell->totinfluence; b++, mdinf++) { + for (b = 0; b < cell->influences_num; b++, mdinf++) { mdinf->weight /= totweight; } } - offset += cell->totinfluence; + offset += cell->influences_num; } mmd->dynverts = mdb->inside; @@ -1732,7 +1737,7 @@ void ED_mesh_deform_bind_callback(Object *object, MeshDeformModifierData *mmd, Mesh *cagemesh, float *vertexcos, - int totvert, + int verts_num, float cagemat[4][4]) { MeshDeformModifierData *mmd_orig = (MeshDeformModifierData *)BKE_modifier_get_original( @@ -1750,19 +1755,19 @@ void ED_mesh_deform_bind_callback(Object *object, BKE_mesh_wrapper_ensure_mdata(cagemesh); /* get mesh and cage mesh */ - mdb.vertexcos = MEM_callocN(sizeof(float[3]) * totvert, "MeshDeformCos"); - mdb.totvert = totvert; + mdb.vertexcos = MEM_callocN(sizeof(float[3]) * verts_num, "MeshDeformCos"); + mdb.verts_num = verts_num; mdb.cagemesh = cagemesh; - mdb.totcagevert = mdb.cagemesh->totvert; - mdb.cagecos = MEM_callocN(sizeof(*mdb.cagecos) * mdb.totcagevert, "MeshDeformBindCos"); + mdb.cage_verts_num = mdb.cagemesh->totvert; + mdb.cagecos = MEM_callocN(sizeof(*mdb.cagecos) * mdb.cage_verts_num, "MeshDeformBindCos"); copy_m4_m4(mdb.cagemat, cagemat); mvert = mdb.cagemesh->mvert; - for (a = 0; a < mdb.totcagevert; a++) { + for (a = 0; a < mdb.cage_verts_num; a++) { copy_v3_v3(mdb.cagecos[a], mvert[a].co); } - for (a = 0; a < mdb.totvert; a++) { + for (a = 0; a < mdb.verts_num; a++) { mul_v3_m4v3(mdb.vertexcos[a], mdb.cagemat, vertexcos + a * 3); } @@ -1771,12 +1776,12 @@ void ED_mesh_deform_bind_callback(Object *object, /* assign bind variables */ mmd_orig->bindcagecos = (float *)mdb.cagecos; - mmd_orig->totvert = mdb.totvert; - mmd_orig->totcagevert = mdb.totcagevert; + mmd_orig->verts_num = mdb.verts_num; + mmd_orig->cage_verts_num = mdb.cage_verts_num; copy_m4_m4(mmd_orig->bindmat, mmd_orig->object->obmat); /* transform bindcagecos to world space */ - for (a = 0; a < mdb.totcagevert; a++) { + for (a = 0; a < mdb.cage_verts_num; a++) { mul_m4_v3(mmd_orig->object->obmat, mmd_orig->bindcagecos + a * 3); } diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c index 90ee7c83436..2ad7a373012 100644 --- a/source/blender/editors/armature/pose_edit.c +++ b/source/blender/editors/armature/pose_edit.c @@ -23,6 +23,7 @@ #include "BKE_deform.h" #include "BKE_global.h" #include "BKE_layer.h" +#include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_object.h" #include "BKE_report.h" @@ -78,7 +79,7 @@ Object *ED_pose_object_from_context(bContext *C) bool ED_object_posemode_enter_ex(struct Main *bmain, Object *ob) { - BLI_assert(!ID_IS_LINKED(ob)); + BLI_assert(BKE_id_is_editable(bmain, &ob->id)); bool ok = false; switch (ob->type) { @@ -99,11 +100,11 @@ bool ED_object_posemode_enter_ex(struct Main *bmain, Object *ob) bool ED_object_posemode_enter(bContext *C, Object *ob) { ReportList *reports = CTX_wm_reports(C); - if (ID_IS_LINKED(ob)) { + struct Main *bmain = CTX_data_main(C); + if (!BKE_id_is_editable(bmain, &ob->id)) { BKE_report(reports, RPT_WARNING, "Cannot pose libdata"); return false; } - struct Main *bmain = CTX_data_main(C); bool ok = ED_object_posemode_enter_ex(bmain, ob); if (ok) { WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_POSE, NULL); diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c index 9796f6771d2..4b3ece64bf9 100644 --- a/source/blender/editors/armature/pose_lib.c +++ b/source/blender/editors/armature/pose_lib.c @@ -170,7 +170,7 @@ static bool has_poselib_pose_data_poll(bContext *C) static bool has_poselib_pose_data_for_editing_poll(bContext *C) { Object *ob = get_poselib_object(C); - return (ob && ob->poselib && !ID_IS_LINKED(ob->poselib)); + return (ob && ob->poselib && BKE_id_is_editable(CTX_data_main(C), &ob->poselib->id)); } /* ----------------------------------- */ @@ -377,7 +377,7 @@ static bool poselib_add_poll(bContext *C) if (ED_operator_posemode(C)) { Object *ob = get_poselib_object(C); if (ob) { - if ((ob->poselib == NULL) || !ID_IS_LINKED(ob->poselib)) { + if ((ob->poselib == NULL) || BKE_id_is_editable(CTX_data_main(C), &ob->poselib->id)) { return true; } } diff --git a/source/blender/editors/armature/pose_lib_2.c b/source/blender/editors/armature/pose_lib_2.c index ced99f16794..9ee289145c4 100644 --- a/source/blender/editors/armature/pose_lib_2.c +++ b/source/blender/editors/armature/pose_lib_2.c @@ -103,7 +103,8 @@ static void poselib_keytag_pose(bContext *C, Scene *scene, PoseBlendData *pbd) } AnimData *adt = BKE_animdata_from_id(&pbd->ob->id); - if (adt != NULL && adt->action != NULL && ID_IS_LINKED(&adt->action->id)) { + if (adt != NULL && adt->action != NULL && + !BKE_id_is_editable(CTX_data_main(C), &adt->action->id)) { /* Changes to linked-in Actions are not allowed. */ return; } diff --git a/source/blender/editors/asset/ED_asset_type.h b/source/blender/editors/asset/ED_asset_type.h index 88511490b5c..f0cddbdf070 100644 --- a/source/blender/editors/asset/ED_asset_type.h +++ b/source/blender/editors/asset/ED_asset_type.h @@ -16,7 +16,7 @@ struct ID; bool ED_asset_type_id_is_non_experimental(const struct ID *id); #define ED_ASSET_TYPE_IDS_NON_EXPERIMENTAL_FLAGS \ - (FILTER_ID_MA | FILTER_ID_OB | FILTER_ID_AC | FILTER_ID_WO | FILTER_ID_NT) + (FILTER_ID_MA | FILTER_ID_GR | FILTER_ID_OB | FILTER_ID_AC | FILTER_ID_WO | FILTER_ID_NT) /** * Check if the asset type for \a id (which doesn't need to be an asset right now) can be an asset, @@ -39,7 +39,7 @@ int64_t ED_asset_types_supported_as_filter_flags(void); * Should start with a consonant, so usages can prefix it with "a" (not "an"). */ #define ED_ASSET_TYPE_IDS_NON_EXPERIMENTAL_UI_STRING \ - "Material, Object, Pose Action, Node Group or World" + "Material, Collection, Object, Pose Action, Node Group or World" #ifdef __cplusplus } diff --git a/source/blender/editors/asset/intern/asset_type.cc b/source/blender/editors/asset/intern/asset_type.cc index 2c219f3dce2..3ecf7df068f 100644 --- a/source/blender/editors/asset/intern/asset_type.cc +++ b/source/blender/editors/asset/intern/asset_type.cc @@ -16,7 +16,7 @@ bool ED_asset_type_id_is_non_experimental(const ID *id) { /* Remember to update #ED_ASSET_TYPE_IDS_NON_EXPERIMENTAL_UI_STRING and * #ED_ASSET_TYPE_IDS_NON_EXPERIMENTAL_FLAGS() with this! */ - return ELEM(GS(id->name), ID_MA, ID_OB, ID_AC, ID_WO, ID_NT); + return ELEM(GS(id->name), ID_MA, ID_GR, ID_OB, ID_AC, ID_WO, ID_NT); } bool ED_asset_type_is_supported(const ID *id) diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 5ff63e767f6..38c14391273 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -1209,7 +1209,7 @@ static void remap_hooks_and_vertex_parents(Main *bmain, Object *obedit) old_to_new_map = init_index_map(obedit, &old_totvert); } - for (i = j = 0; i < hmd->totindex; i++) { + for (i = j = 0; i < hmd->indexar_num; i++) { if (hmd->indexar[i] < old_totvert) { index = old_to_new_map[hmd->indexar[i]]; if (index != -1) { @@ -1221,7 +1221,7 @@ static void remap_hooks_and_vertex_parents(Main *bmain, Object *obedit) } } - hmd->totindex = j; + hmd->indexar_num = j; } } } diff --git a/source/blender/editors/curves/intern/curves_ops.cc b/source/blender/editors/curves/intern/curves_ops.cc index 52a55ae1760..bbd48ccd89a 100644 --- a/source/blender/editors/curves/intern/curves_ops.cc +++ b/source/blender/editors/curves/intern/curves_ops.cc @@ -4,8 +4,289 @@ * \ingroup edcurves */ +#include "BLI_utildefines.h" + #include "ED_curves.h" +#include "ED_object.h" + +#include "WM_api.h" + +#include "BKE_context.h" +#include "BKE_curves.hh" +#include "BKE_layer.h" +#include "BKE_mesh.h" +#include "BKE_mesh_runtime.h" +#include "BKE_paint.h" +#include "BKE_particle.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_particle_types.h" +#include "DNA_scene_types.h" + +#include "DEG_depsgraph.h" + +/** + * The code below uses a suffix naming convention to indicate the coordinate space: + * `cu`: Local space of the curves object that is being edited. + * `su`: Local space of the surface object. + * `wo`: World space. + * `ha`: Local space of an individual hair in the legacy hair system. + */ + +namespace blender::ed::curves { + +using bke::CurvesGeometry; + +namespace convert_to_particle_system { + +static int find_mface_for_root_position(const Mesh &mesh, + const Span<int> possible_mface_indices, + const float3 &root_pos) +{ + BLI_assert(possible_mface_indices.size() >= 1); + if (possible_mface_indices.size() == 1) { + return possible_mface_indices.first(); + } + /* Find the closest #MFace to #root_pos. */ + int mface_i; + float best_distance_sq = FLT_MAX; + for (const int possible_mface_i : possible_mface_indices) { + const MFace &possible_mface = mesh.mface[possible_mface_i]; + { + float3 point_in_triangle; + closest_on_tri_to_point_v3(point_in_triangle, + root_pos, + mesh.mvert[possible_mface.v1].co, + mesh.mvert[possible_mface.v2].co, + mesh.mvert[possible_mface.v3].co); + const float distance_sq = len_squared_v3v3(root_pos, point_in_triangle); + if (distance_sq < best_distance_sq) { + best_distance_sq = distance_sq; + mface_i = possible_mface_i; + } + } + /* Optionally check the second triangle if the #MFace is a quad. */ + if (possible_mface.v4) { + float3 point_in_triangle; + closest_on_tri_to_point_v3(point_in_triangle, + root_pos, + mesh.mvert[possible_mface.v1].co, + mesh.mvert[possible_mface.v3].co, + mesh.mvert[possible_mface.v4].co); + const float distance_sq = len_squared_v3v3(root_pos, point_in_triangle); + if (distance_sq < best_distance_sq) { + best_distance_sq = distance_sq; + mface_i = possible_mface_i; + } + } + } + return mface_i; +} + +/** + * \return Barycentric coordinates in the #MFace. + */ +static float4 compute_mface_weights_for_position(const Mesh &mesh, + const MFace &mface, + const float3 &position) +{ + float4 mface_weights; + if (mface.v4) { + float mface_verts_su[4][3]; + copy_v3_v3(mface_verts_su[0], mesh.mvert[mface.v1].co); + copy_v3_v3(mface_verts_su[1], mesh.mvert[mface.v2].co); + copy_v3_v3(mface_verts_su[2], mesh.mvert[mface.v3].co); + copy_v3_v3(mface_verts_su[3], mesh.mvert[mface.v4].co); + interp_weights_poly_v3(mface_weights, mface_verts_su, 4, position); + } + else { + interp_weights_tri_v3(mface_weights, + mesh.mvert[mface.v1].co, + mesh.mvert[mface.v2].co, + mesh.mvert[mface.v3].co, + position); + mface_weights[3] = 0.0f; + } + return mface_weights; +} + +static int curves_convert_to_particle_system_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + + CTX_DATA_BEGIN (C, Object *, curves_ob, selected_objects) { + if (curves_ob->type != OB_CURVES) { + continue; + } + Curves &curves_id = *static_cast<Curves *>(curves_ob->data); + CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry); + if (curves_id.surface == nullptr) { + continue; + } + Object &surface_ob = *curves_id.surface; + if (surface_ob.type != OB_MESH) { + continue; + } + Mesh &surface_me = *static_cast<Mesh *>(surface_ob.data); + + const Span<float3> positions_cu = curves.positions(); + const VArray<int> looptri_indices = std::as_const(curves).surface_triangle_indices(); + const Span<MLoopTri> looptris{BKE_mesh_runtime_looptri_ensure(&surface_me), + BKE_mesh_runtime_looptri_len(&surface_me)}; + + /* Find indices of curves that can be transferred to the old hair system. */ + Vector<int> curves_indices_to_transfer; + for (const int curve_i : curves.curves_range()) { + const int looptri_i = looptri_indices[curve_i]; + if (looptri_i >= 0 && looptri_i < looptris.size()) { + curves_indices_to_transfer.append(curve_i); + } + } + + const int hairs_num = curves_indices_to_transfer.size(); + if (hairs_num == 0) { + continue; + } + + ParticleSystem *particle_system = nullptr; + LISTBASE_FOREACH (ParticleSystem *, psys, &surface_ob.particlesystem) { + if (STREQ(psys->name, curves_ob->id.name + 2)) { + particle_system = psys; + break; + } + } + if (particle_system == nullptr) { + ParticleSystemModifierData &psmd = *reinterpret_cast<ParticleSystemModifierData *>( + object_add_particle_system(bmain, scene, &surface_ob, curves_ob->id.name + 2)); + particle_system = psmd.psys; + } + + ParticleSettings &settings = *particle_system->part; + + psys_free_particles(particle_system); + settings.type = PART_HAIR; + settings.totpart = 0; + psys_changed_type(&surface_ob, particle_system); + + MutableSpan<ParticleData> particles{ + static_cast<ParticleData *>(MEM_calloc_arrayN(hairs_num, sizeof(ParticleData), __func__)), + hairs_num}; + + /* The old hair system still uses #MFace, so make sure those are available on the mesh. */ + BKE_mesh_tessface_calc(&surface_me); + + /* Prepare utility data structure to map hair roots to mfaces. */ + const Span<int> mface_to_poly_map{ + static_cast<int *>(CustomData_get_layer(&surface_me.fdata, CD_ORIGINDEX)), + surface_me.totface}; + Array<Vector<int>> poly_to_mface_map(surface_me.totpoly); + for (const int mface_i : mface_to_poly_map.index_range()) { + const int poly_i = mface_to_poly_map[mface_i]; + poly_to_mface_map[poly_i].append(mface_i); + } + + /* Prepare transformation matrices. */ + const float4x4 curves_to_world_mat = curves_ob->obmat; + const float4x4 surface_to_world_mat = surface_ob.obmat; + const float4x4 world_to_surface_mat = surface_to_world_mat.inverted(); + const float4x4 curves_to_surface_mat = world_to_surface_mat * curves_to_world_mat; + + for (const int new_hair_i : curves_indices_to_transfer.index_range()) { + const int curve_i = curves_indices_to_transfer[new_hair_i]; + const IndexRange points = curves.points_for_curve(curve_i); + + const int looptri_i = looptri_indices[curve_i]; + const MLoopTri &looptri = looptris[looptri_i]; + const int poly_i = looptri.poly; + + const float3 &root_pos_cu = positions_cu[points.first()]; + const float3 root_pos_su = curves_to_surface_mat * root_pos_cu; + + const int mface_i = find_mface_for_root_position( + surface_me, poly_to_mface_map[poly_i], root_pos_su); + const MFace &mface = surface_me.mface[mface_i]; + + const float4 mface_weights = compute_mface_weights_for_position( + surface_me, mface, root_pos_su); + + ParticleData &particle = particles[new_hair_i]; + const int num_keys = points.size(); + MutableSpan<HairKey> hair_keys{ + static_cast<HairKey *>(MEM_calloc_arrayN(num_keys, sizeof(HairKey), __func__)), + num_keys}; + + particle.hair = hair_keys.data(); + particle.totkey = hair_keys.size(); + copy_v4_v4(particle.fuv, mface_weights); + particle.num = mface_i; + /* Not sure if there is a better way to initialize this. */ + particle.num_dmcache = DMCACHE_NOTFOUND; + + float4x4 hair_to_surface_mat; + psys_mat_hair_to_object( + &surface_ob, &surface_me, PART_FROM_FACE, &particle, hair_to_surface_mat.values); + /* In theory, #psys_mat_hair_to_object should handle this, but it doesn't right now. */ + copy_v3_v3(hair_to_surface_mat.values[3], root_pos_su); + const float4x4 surface_to_hair_mat = hair_to_surface_mat.inverted(); + + for (const int key_i : hair_keys.index_range()) { + const float3 &key_pos_cu = positions_cu[points[key_i]]; + const float3 key_pos_su = curves_to_surface_mat * key_pos_cu; + const float3 key_pos_ha = surface_to_hair_mat * key_pos_su; + + HairKey &key = hair_keys[key_i]; + copy_v3_v3(key.co, key_pos_ha); + key.time = 100.0f * key_i / (float)(hair_keys.size() - 1); + } + } + + particle_system->particles = particles.data(); + particle_system->totpart = particles.size(); + particle_system->flag |= PSYS_EDITED; + particle_system->recalc |= ID_RECALC_PSYS_RESET; + + DEG_id_tag_update(&surface_ob.id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&settings.id, ID_RECALC_COPY_ON_WRITE); + } + CTX_DATA_END; + + WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +static bool curves_convert_to_particle_system_poll(bContext *C) +{ + Object *ob = CTX_data_active_object(C); + if (ob == nullptr || ob->type != OB_CURVES) { + return false; + } + Curves &curves = *static_cast<Curves *>(ob->data); + return curves.surface != nullptr; +} + +} // namespace convert_to_particle_system + +static void CURVES_OT_convert_to_particle_system(wmOperatorType *ot) +{ + ot->name = "Convert Curves to Particle System"; + ot->idname = "CURVES_OT_convert_to_particle_system"; + ot->description = "Add a new or update an existing hair particle system on the surface object"; + + ot->poll = convert_to_particle_system::curves_convert_to_particle_system_poll; + ot->exec = convert_to_particle_system::curves_convert_to_particle_system_exec; + + ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER; +} + +} // namespace blender::ed::curves void ED_operatortypes_curves() { + using namespace blender::ed::curves; + WM_operatortype_append(CURVES_OT_convert_to_particle_system); } diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index d58bbec01cd..e820423cdff 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -191,7 +191,6 @@ set(ICON_NAMES library_data_broken boids strands - library_data_indirect greasepencil line_data library_data_override diff --git a/source/blender/editors/geometry/geometry_attributes.cc b/source/blender/editors/geometry/geometry_attributes.cc index 6225a68f53c..5d9d02db660 100644 --- a/source/blender/editors/geometry/geometry_attributes.cc +++ b/source/blender/editors/geometry/geometry_attributes.cc @@ -15,6 +15,7 @@ #include "BKE_context.h" #include "BKE_deform.h" #include "BKE_geometry_set.hh" +#include "BKE_lib_id.h" #include "BKE_object_deform.h" #include "BKE_report.h" @@ -41,8 +42,9 @@ namespace blender::ed::geometry { static bool geometry_attributes_poll(bContext *C) { Object *ob = ED_object_context(C); + Main *bmain = CTX_data_main(C); ID *data = (ob) ? static_cast<ID *>(ob->data) : nullptr; - return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data)) && + return (ob && BKE_id_is_editable(bmain, &ob->id) && data && BKE_id_is_editable(bmain, data)) && BKE_id_attributes_supported(data); } diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt index f8fa23a54d1..09a3cac0d48 100644 --- a/source/blender/editors/gpencil/CMakeLists.txt +++ b/source/blender/editors/gpencil/CMakeLists.txt @@ -28,7 +28,7 @@ set(SRC gpencil_add_monkey.c gpencil_add_stroke.c gpencil_armature.c - gpencil_bake_animation.c + gpencil_bake_animation.cc gpencil_convert.c gpencil_data.c gpencil_edit.c @@ -36,7 +36,7 @@ set(SRC gpencil_fill.c gpencil_interpolate.c gpencil_merge.c - gpencil_mesh.c + gpencil_mesh.cc gpencil_ops.c gpencil_ops_versioning.c gpencil_paint.c diff --git a/source/blender/editors/gpencil/gpencil_bake_animation.c b/source/blender/editors/gpencil/gpencil_bake_animation.cc index 5d33377900f..0667da46e25 100644 --- a/source/blender/editors/gpencil/gpencil_bake_animation.c +++ b/source/blender/editors/gpencil/gpencil_bake_animation.cc @@ -61,7 +61,7 @@ const EnumPropertyItem rna_gpencil_reproject_type_items[] = { 0, "Cursor", "Reproject the strokes using the orientation of 3D cursor"}, - {0, NULL, 0, NULL, NULL}, + {0, nullptr, 0, nullptr, nullptr}, }; /* Check frame_end is always > start frame! */ @@ -86,7 +86,7 @@ static bool gpencil_bake_grease_pencil_animation_poll(bContext *C) } /* Check if grease pencil or empty for dupli groups. */ - if ((obact == NULL) || (!ELEM(obact->type, OB_GPENCIL, OB_EMPTY))) { + if ((obact == nullptr) || (!ELEM(obact->type, OB_GPENCIL, OB_EMPTY))) { return false; } @@ -95,10 +95,10 @@ static bool gpencil_bake_grease_pencil_animation_poll(bContext *C) return (area && area->spacetype); } -typedef struct GpBakeOb { +struct GpBakeOb { struct GpBakeOb *next, *prev; Object *ob; -} GpBakeOb; +}; /* Get list of keyframes used by selected objects. */ static void animdata_keyframe_list_get(ListBase *ob_list, @@ -109,7 +109,7 @@ static void animdata_keyframe_list_get(ListBase *ob_list, LISTBASE_FOREACH (GpBakeOb *, elem, ob_list) { Object *ob = elem->ob; AnimData *adt = BKE_animdata_from_id(&ob->id); - if ((adt == NULL) || (adt->action == NULL)) { + if ((adt == nullptr) || (adt->action == nullptr)) { continue; } LISTBASE_FOREACH (FCurve *, fcurve, &adt->action->curves) { @@ -131,16 +131,15 @@ static void animdata_keyframe_list_get(ListBase *ob_list, static void gpencil_bake_duplilist(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *list) { - GpBakeOb *elem = NULL; + GpBakeOb *elem = nullptr; ListBase *lb; - DupliObject *dob; lb = object_duplilist(depsgraph, scene, ob); - for (dob = lb->first; dob; dob = dob->next) { + LISTBASE_FOREACH (DupliObject *, dob, lb) { if (dob->ob->type != OB_GPENCIL) { continue; } - elem = MEM_callocN(sizeof(GpBakeOb), __func__); + elem = MEM_cnew<GpBakeOb>(__func__); elem->ob = dob->ob; BLI_addtail(list, elem); } @@ -150,13 +149,13 @@ static void gpencil_bake_duplilist(Depsgraph *depsgraph, Scene *scene, Object *o static void gpencil_bake_ob_list(bContext *C, Depsgraph *depsgraph, Scene *scene, ListBase *list) { - GpBakeOb *elem = NULL; + GpBakeOb *elem = nullptr; /* Add active object. In some files this could not be in selected array. */ Object *obact = CTX_data_active_object(C); if (obact->type == OB_GPENCIL) { - elem = MEM_callocN(sizeof(GpBakeOb), __func__); + elem = MEM_cnew<GpBakeOb>(__func__); elem->ob = obact; BLI_addtail(list, elem); } @@ -172,7 +171,7 @@ static void gpencil_bake_ob_list(bContext *C, Depsgraph *depsgraph, Scene *scene } /* Add selected objects. */ if (ob->type == OB_GPENCIL) { - elem = MEM_callocN(sizeof(GpBakeOb), __func__); + elem = MEM_cnew<GpBakeOb>(__func__); elem->ob = ob; BLI_addtail(list, elem); } @@ -199,7 +198,7 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); - ListBase ob_selected_list = {NULL, NULL}; + ListBase ob_selected_list = {nullptr, nullptr}; gpencil_bake_ob_list(C, depsgraph, scene, &ob_selected_list); /* Grab all relevant settings. */ @@ -215,10 +214,11 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op const bool only_selected = RNA_boolean_get(op->ptr, "only_selected"); const int frame_offset = RNA_int_get(op->ptr, "frame_target") - frame_start; - const int project_type = RNA_enum_get(op->ptr, "project_type"); + const eGP_ReprojectModes project_type = (eGP_ReprojectModes)RNA_enum_get(op->ptr, + "project_type"); /* Create a new grease pencil object. */ - Object *ob_gpencil = NULL; + Object *ob_gpencil = nullptr; ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0; ob_gpencil = ED_gpencil_add_object(C, scene->cursor.location, local_view_bits); float invmat[4][4]; @@ -230,8 +230,8 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op /* Set cursor to indicate working. */ WM_cursor_wait(true); - GP_SpaceConversion gsc = {NULL}; - SnapObjectContext *sctx = NULL; + GP_SpaceConversion gsc = {nullptr}; + SnapObjectContext *sctx = nullptr; if (project_type != GP_REPROJECT_KEEP) { /* Init space conversion stuff. */ gpencil_point_conversion_init(C, &gsc); @@ -271,14 +271,14 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op /* Loop all objects in the list. */ LISTBASE_FOREACH (GpBakeOb *, elem, &ob_selected_list) { Object *ob_eval = (Object *)DEG_get_evaluated_object(depsgraph, elem->ob); - bGPdata *gpd_src = ob_eval->data; + bGPdata *gpd_src = static_cast<bGPdata *>(ob_eval->data); LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd_src->layers) { /* Create destination layer. */ char *layer_name; layer_name = BLI_sprintfN("%s_%s", elem->ob->id.name + 2, gpl_src->info); bGPDlayer *gpl_dst = BKE_gpencil_layer_named_get(gpd_dst, layer_name); - if (gpl_dst == NULL) { + if (gpl_dst == nullptr) { gpl_dst = BKE_gpencil_layer_addnew(gpd_dst, layer_name, true, false); } MEM_freeN(layer_name); @@ -293,7 +293,7 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op /* Duplicate frame. */ bGPDframe *gpf_src = BKE_gpencil_layer_frame_get( gpl_src, remap_cfra, GP_GETFRAME_USE_PREV); - if (gpf_src == NULL) { + if (gpf_src == nullptr) { continue; } bGPDframe *gpf_dst = BKE_gpencil_frame_duplicate(gpf_src, true); @@ -346,19 +346,19 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op /* Free memory. */ gpencil_bake_free_ob_list(&ob_selected_list); - if (sctx != NULL) { + if (sctx != nullptr) { ED_transform_snap_object_context_destroy(sctx); } /* Free temp hash table. */ - if (keyframe_list != NULL) { - BLI_ghash_free(keyframe_list, NULL, NULL); + if (keyframe_list != nullptr) { + BLI_ghash_free(keyframe_list, nullptr, nullptr); } /* Notifiers. */ DEG_relations_tag_update(bmain); DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); DEG_id_tag_update(&gpd_dst->id, ID_RECALC_COPY_ON_WRITE); - WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL); + WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, nullptr); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); /* Reset cursor. */ @@ -418,12 +418,15 @@ void GPENCIL_OT_bake_grease_pencil_animation(wmOperatorType *ot) prop = RNA_def_int( ot->srna, "frame_end", 250, 1, 100000, "End Frame", "The end frame of animation", 1, 100000); - RNA_def_property_update_runtime(prop, gpencil_bake_set_frame_end); + RNA_def_property_update_runtime(prop, (void *)gpencil_bake_set_frame_end); prop = RNA_def_int(ot->srna, "step", 1, 1, 100, "Step", "Step between generated frames", 1, 100); - RNA_def_boolean( - ot->srna, "only_selected", 0, "Only Selected Keyframes", "Convert only selected keyframes"); + RNA_def_boolean(ot->srna, + "only_selected", + false, + "Only Selected Keyframes", + "Convert only selected keyframes"); RNA_def_int( ot->srna, "frame_target", 1, 1, 100000, "Target Frame", "Destination frame", 1, 100000); diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index 338a7c8a51d..6843c42d2d0 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -2195,8 +2195,9 @@ static bool gpencil_vertex_group_poll(bContext *C) Object *ob = CTX_data_active_object(C); if ((ob) && (ob->type == OB_GPENCIL)) { + Main *bmain = CTX_data_main(C); const bGPdata *gpd = (const bGPdata *)ob->data; - if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) && + if (BKE_id_is_editable(bmain, &ob->id) && BKE_id_is_editable(bmain, ob->data) && !BLI_listbase_is_empty(&gpd->vertex_group_names)) { if (ELEM(ob->mode, OB_MODE_EDIT_GPENCIL, OB_MODE_SCULPT_GPENCIL)) { return true; @@ -2212,8 +2213,9 @@ static bool gpencil_vertex_group_weight_poll(bContext *C) Object *ob = CTX_data_active_object(C); if ((ob) && (ob->type == OB_GPENCIL)) { + Main *bmain = CTX_data_main(C); const bGPdata *gpd = (const bGPdata *)ob->data; - if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) && + if (BKE_id_is_editable(bmain, &ob->id) && BKE_id_is_editable(bmain, ob->data) && !BLI_listbase_is_empty(&gpd->vertex_group_names)) { if (ob->mode == OB_MODE_WEIGHT_GPENCIL) { return true; diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index 8fc300412d9..3f06dbfdbb3 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -2108,18 +2108,18 @@ static bool gpencil_do_frame_fill(tGPDfill *tgpf, const bool is_inverted) int totpoints_prv = 0; int loop_limit = 0; while (totpoints > 0) { - /* analyze outline */ + /* Analyze outline. */ gpencil_get_outline_points(tgpf, (totpoints == 1) ? true : false); - /* create array of points from stack */ + /* Create array of points from stack. */ totpoints = gpencil_points_from_stack(tgpf); + if (totpoints > 0) { + /* Create z-depth array for reproject. */ + gpencil_get_depth_array(tgpf); - /* create z-depth array for reproject */ - gpencil_get_depth_array(tgpf); - - /* create stroke and reproject */ - gpencil_stroke_from_buffer(tgpf); - + /* Create stroke and reproject. */ + gpencil_stroke_from_buffer(tgpf); + } if (is_inverted) { gpencil_erase_processed_area(tgpf); } @@ -2222,7 +2222,7 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) /* Hash of selected frames. */ GHash *frame_list = BLI_ghash_int_new_ex(__func__, 64); - /* If not multiframe and there is no frame in CFRA for the active layer, create + /* If not multi-frame and there is no frame in CFRA for the active layer, create * a new frame. */ if (!is_multiedit) { tgpf->gpf = BKE_gpencil_layer_frame_get( diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index 1bb98ce51c7..56c94e4494d 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -13,6 +13,10 @@ #define DEPTH_INVALID 1.0f +#ifdef __cplusplus +extern "C" { +#endif + /* internal exports only */ struct Material; struct bGPDspoint; @@ -826,3 +830,7 @@ struct GP_EditableStrokes_Iter { extern const EnumPropertyItem rna_gpencil_reproject_type_items[]; /* ****************************************************** */ + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/editors/gpencil/gpencil_mesh.c b/source/blender/editors/gpencil/gpencil_mesh.cc index 7db55796053..aee00d4ede3 100644 --- a/source/blender/editors/gpencil/gpencil_mesh.c +++ b/source/blender/editors/gpencil/gpencil_mesh.cc @@ -67,10 +67,10 @@ static bool gpencil_bake_mesh_animation_poll(bContext *C) return (area && area->spacetype); } -typedef struct GpBakeOb { +struct GpBakeOb { struct GpBakeOb *next, *prev; Object *ob; -} GpBakeOb; +}; /* Get list of keyframes used by selected objects. */ static void animdata_keyframe_list_get(ListBase *ob_list, @@ -81,7 +81,7 @@ static void animdata_keyframe_list_get(ListBase *ob_list, LISTBASE_FOREACH (GpBakeOb *, elem, ob_list) { Object *ob = elem->ob; AnimData *adt = BKE_animdata_from_id(&ob->id); - if ((adt == NULL) || (adt->action == NULL)) { + if ((adt == nullptr) || (adt->action == nullptr)) { continue; } LISTBASE_FOREACH (FCurve *, fcurve, &adt->action->curves) { @@ -103,15 +103,14 @@ static void animdata_keyframe_list_get(ListBase *ob_list, static void gpencil_bake_duplilist(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *list) { - GpBakeOb *elem = NULL; + GpBakeOb *elem = nullptr; ListBase *lb; - DupliObject *dob; lb = object_duplilist(depsgraph, scene, ob); - for (dob = lb->first; dob; dob = dob->next) { + LISTBASE_FOREACH (DupliObject *, dob, lb) { if (dob->ob->type != OB_MESH) { continue; } - elem = MEM_callocN(sizeof(GpBakeOb), __func__); + elem = MEM_cnew<GpBakeOb>(__func__); elem->ob = dob->ob; BLI_addtail(list, elem); } @@ -121,17 +120,17 @@ static void gpencil_bake_duplilist(Depsgraph *depsgraph, Scene *scene, Object *o static bool gpencil_bake_ob_list(bContext *C, Depsgraph *depsgraph, Scene *scene, ListBase *list) { - GpBakeOb *elem = NULL; + GpBakeOb *elem = nullptr; bool simple_material = false; /* Add active object. In some files this could not be in selected array. */ Object *obact = CTX_data_active_object(C); - if (obact == NULL) { + if (obact == nullptr) { return false; } if (obact->type == OB_MESH) { - elem = MEM_callocN(sizeof(GpBakeOb), __func__); + elem = MEM_cnew<GpBakeOb>(__func__); elem->ob = obact; BLI_addtail(list, elem); } @@ -148,7 +147,7 @@ static bool gpencil_bake_ob_list(bContext *C, Depsgraph *depsgraph, Scene *scene } /* Add selected meshes. */ if (ob->type == OB_MESH) { - elem = MEM_callocN(sizeof(GpBakeOb), __func__); + elem = MEM_cnew<GpBakeOb>(__func__); elem->ob = ob; BLI_addtail(list, elem); } @@ -177,11 +176,11 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); - ListBase ob_selected_list = {NULL, NULL}; + ListBase ob_selected_list = {nullptr, nullptr}; gpencil_bake_ob_list(C, depsgraph, scene, &ob_selected_list); /* Cannot check this in poll because the active object changes. */ - if (ob_selected_list.first == NULL) { + if (ob_selected_list.first == nullptr) { BKE_report(op->reports, RPT_INFO, "No valid object selected"); gpencil_bake_free_ob_list(&ob_selected_list); return OPERATOR_CANCELLED; @@ -205,28 +204,29 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) const bool only_selected = RNA_boolean_get(op->ptr, "only_selected"); const float offset = RNA_float_get(op->ptr, "offset"); const int frame_offset = RNA_int_get(op->ptr, "frame_target") - frame_start; - const int project_type = RNA_enum_get(op->ptr, "project_type"); - eGP_TargetObjectMode target = RNA_enum_get(op->ptr, "target"); + const eGP_ReprojectModes project_type = (eGP_ReprojectModes)RNA_enum_get(op->ptr, + "project_type"); + const eGP_TargetObjectMode target = (eGP_TargetObjectMode)RNA_enum_get(op->ptr, "target"); /* Create a new grease pencil object in origin or reuse selected. */ - Object *ob_gpencil = NULL; + Object *ob_gpencil = nullptr; bool newob = false; if (target == GP_TARGET_OB_SELECTED) { ob_gpencil = BKE_view_layer_non_active_selected_object(CTX_data_view_layer(C), v3d); - if (ob_gpencil != NULL) { + if (ob_gpencil != nullptr) { if (ob_gpencil->type != OB_GPENCIL) { BKE_report(op->reports, RPT_WARNING, "Target object not a grease pencil, ignoring!"); - ob_gpencil = NULL; + ob_gpencil = nullptr; } else if (BKE_object_obdata_is_libdata(ob_gpencil)) { BKE_report(op->reports, RPT_WARNING, "Target object library-data, ignoring!"); - ob_gpencil = NULL; + ob_gpencil = nullptr; } } } - if (ob_gpencil == NULL) { + if (ob_gpencil == nullptr) { ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0; const float loc[3] = {0.0f, 0.0f, 0.0f}; ob_gpencil = ED_gpencil_add_object(C, loc, local_view_bits); @@ -239,8 +239,8 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) /* Set cursor to indicate working. */ WM_cursor_wait(true); - GP_SpaceConversion gsc = {NULL}; - SnapObjectContext *sctx = NULL; + GP_SpaceConversion gsc = {nullptr}; + SnapObjectContext *sctx = nullptr; if (project_type != GP_REPROJECT_KEEP) { /* Init space conversion stuff. */ gpencil_point_conversion_init(C, &gsc); @@ -309,7 +309,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) if (project_type != GP_REPROJECT_KEEP) { LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { bGPDframe *gpf = gpl->actframe; - if (gpf == NULL) { + if (gpf == nullptr) { continue; } LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { @@ -355,12 +355,12 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) /* Free memory. */ gpencil_bake_free_ob_list(&ob_selected_list); - if (sctx != NULL) { + if (sctx != nullptr) { ED_transform_snap_object_context_destroy(sctx); } /* Free temp hash table. */ - if (keyframe_list != NULL) { - BLI_ghash_free(keyframe_list, NULL, NULL); + if (keyframe_list != nullptr) { + BLI_ghash_free(keyframe_list, nullptr, nullptr); } /* notifiers */ @@ -368,7 +368,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) DEG_relations_tag_update(bmain); } DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL); + WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, nullptr); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); /* Reset cursor. */ @@ -392,7 +392,7 @@ void GPENCIL_OT_bake_mesh_animation(wmOperatorType *ot) static const EnumPropertyItem target_object_modes[] = { {GP_TARGET_OB_NEW, "NEW", 0, "New Object", ""}, {GP_TARGET_OB_SELECTED, "SELECTED", 0, "Selected Object", ""}, - {0, NULL, 0, NULL, NULL}, + {0, nullptr, 0, nullptr, nullptr}, }; PropertyRNA *prop; @@ -424,7 +424,7 @@ void GPENCIL_OT_bake_mesh_animation(wmOperatorType *ot) prop = RNA_def_int( ot->srna, "frame_end", 250, 1, 100000, "End Frame", "The end frame of animation", 1, 100000); - RNA_def_property_update_runtime(prop, gpencil_bake_set_frame_end); + RNA_def_property_update_runtime(prop, (void *)gpencil_bake_set_frame_end); prop = RNA_def_int(ot->srna, "step", 1, 1, 100, "Step", "Step between generated frames", 1, 100); @@ -433,7 +433,7 @@ void GPENCIL_OT_bake_mesh_animation(wmOperatorType *ot) prop = RNA_def_float_rotation(ot->srna, "angle", 0, - NULL, + nullptr, DEG2RADF(0.0f), DEG2RADF(180.0f), "Threshold Angle", @@ -452,10 +452,13 @@ void GPENCIL_OT_bake_mesh_animation(wmOperatorType *ot) 0.0, 100.00); - RNA_def_boolean(ot->srna, "seams", 0, "Only Seam Edges", "Convert only seam edges"); - RNA_def_boolean(ot->srna, "faces", 1, "Export Faces", "Export faces as filled strokes"); - RNA_def_boolean( - ot->srna, "only_selected", 0, "Only Selected Keyframes", "Convert only selected keyframes"); + RNA_def_boolean(ot->srna, "seams", false, "Only Seam Edges", "Convert only seam edges"); + RNA_def_boolean(ot->srna, "faces", true, "Export Faces", "Export faces as filled strokes"); + RNA_def_boolean(ot->srna, + "only_selected", + false, + "Only Selected Keyframes", + "Convert only selected keyframes"); RNA_def_int( ot->srna, "frame_target", 1, 1, 100000, "Target Frame", "Destination frame", 1, 100000); diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index 57a184b0e8d..b57b8145749 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -1401,7 +1401,7 @@ static void gpencil_primitive_interaction_end(bContext *C, BKE_gpencil_stroke_geometry_update(tgpi->gpd, gps); } - /* In Multiframe mode, duplicate the stroke in other frames. */ + /* In Multi-frame mode, duplicate the stroke in other frames. */ if (GPENCIL_MULTIEDIT_SESSIONS_ON(tgpi->gpd)) { const bool tail = (ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK); BKE_gpencil_stroke_copy_to_keyframes(tgpi->gpd, tgpi->gpl, gpf, gps, tail); @@ -1481,7 +1481,7 @@ static void gpencil_primitive_edit_event_handling( break; } case MOUSEMOVE: { - if ((event->val == KM_PRESS) && tgpi->sel_cp != SELECT_NONE) { + if (tgpi->sel_cp != SELECT_NONE) { if (tgpi->sel_cp == SELECT_START && tgpi->tot_stored_edges == 0) { copy_v2_v2(tgpi->start, tgpi->mval); } diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c index 1e7159392e2..7de579993c1 100644 --- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c +++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c @@ -1442,20 +1442,22 @@ static bool gpencil_sculpt_brush_do_stroke(tGP_BrushEditData *gso, if (gps->totpoints == 1) { bGPDspoint pt_temp; pt = &gps->points[0]; - gpencil_point_to_parent_space(gps->points, diff_mat, &pt_temp); - gpencil_point_to_xy(gsc, gps, &pt_temp, &pc1[0], &pc1[1]); - - pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; - /* Do bound-box check first. */ - if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) { - /* only check if point is inside */ - int mval_i[2]; - round_v2i_v2fl(mval_i, gso->mval); - if (len_v2v2_int(mval_i, pc1) <= radius) { - /* apply operation to this point */ - if (pt_active != NULL) { - rot_eval = gpencil_sculpt_rotation_eval_get(gso, gps, pt, 0); - changed = apply(gso, gps_active, rot_eval, 0, radius, pc1); + if (GPENCIL_ANY_SCULPT_MASK(gso->mask) && (pt->flag & GP_SPOINT_SELECT) != 0) { + gpencil_point_to_parent_space(gps->points, diff_mat, &pt_temp); + gpencil_point_to_xy(gsc, gps, &pt_temp, &pc1[0], &pc1[1]); + + pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; + /* Do bound-box check first. */ + if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) { + /* only check if point is inside */ + int mval_i[2]; + round_v2i_v2fl(mval_i, gso->mval); + if (len_v2v2_int(mval_i, pc1) <= radius) { + /* apply operation to this point */ + if (pt_active != NULL) { + rot_eval = gpencil_sculpt_rotation_eval_get(gso, gps, pt, 0); + changed = apply(gso, gps_active, rot_eval, 0, radius, pc1); + } } } } diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index fca4ff84dc5..d962dcdfa10 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -2651,7 +2651,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL); } - return OPERATOR_FINISHED; + return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED; } static int gpencil_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) @@ -2662,7 +2662,9 @@ static int gpencil_select_invoke(bContext *C, wmOperator *op, const wmEvent *eve RNA_boolean_set(op->ptr, "use_shift_extend", event->modifier & KM_SHIFT); } - return gpencil_select_exec(C, op); + const int retval = gpencil_select_exec(C, op); + + return WM_operator_flag_only_pass_through_on_press(retval, event); } void GPENCIL_OT_select(wmOperatorType *ot) diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 69ea58eee02..2dc12125f40 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -1423,7 +1423,7 @@ void ED_gpencil_add_defaults(bContext *C, Object *ob) /* ensure a color exists and is assigned to object */ BKE_gpencil_object_material_ensure_from_active_input_toolsettings(bmain, ob, ts); - /* ensure multiframe falloff curve */ + /* Ensure multi-frame falloff curve. */ if (ts->gp_sculpt.cur_falloff == NULL) { ts->gp_sculpt.cur_falloff = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); CurveMapping *gp_falloff_curve = ts->gp_sculpt.cur_falloff; diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c index b4cfc7f3a08..c221d8e25e4 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_paint.c +++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c @@ -738,7 +738,7 @@ static bool gpencil_vertexpaint_brush_init(bContext *C, wmOperator *op) /* Save mask. */ gso->mask = ts->gpencil_selectmode_vertex; - /* Multiframe settings. */ + /* Multi-frame settings. */ gso->is_multiframe = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd); gso->use_multiframe_falloff = (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_FRAME_FALLOFF) != 0; diff --git a/source/blender/editors/gpencil/gpencil_weight_paint.c b/source/blender/editors/gpencil/gpencil_weight_paint.c index bceec7a638e..22fbf0021fc 100644 --- a/source/blender/editors/gpencil/gpencil_weight_paint.c +++ b/source/blender/editors/gpencil/gpencil_weight_paint.c @@ -322,7 +322,7 @@ static bool gpencil_weightpaint_brush_init(bContext *C, wmOperator *op) gso->region = CTX_wm_region(C); - /* Multiframe settings. */ + /* Multi-frame settings. */ gso->is_multiframe = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd); gso->use_multiframe_falloff = (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_FRAME_FALLOFF) != 0; diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h index 6a207a6e453..c367072e6e7 100644 --- a/source/blender/editors/include/ED_fileselect.h +++ b/source/blender/editors/include/ED_fileselect.h @@ -216,6 +216,8 @@ typedef enum FSMenuInsert { FS_INSERT_FIRST = (1 << 2), /** just append to preserve delivered order */ FS_INSERT_LAST = (1 << 3), + /** Do not validate the link when inserted. */ + FS_INSERT_NO_VALIDATE = (1 << 4), } FSMenuInsert; struct FSMenu; diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index 8c9fa7e4494..c30b8c5ec6a 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -33,7 +33,7 @@ typedef enum { NODE_RIGHT = 8, } NodeBorder; -#define NODE_GRID_STEP_SIZE 10 +#define NODE_GRID_STEP_SIZE U.widget_unit /* Based on the grid nodes snap to. */ #define NODE_EDGE_PAN_INSIDE_PAD 2 #define NODE_EDGE_PAN_OUTSIDE_PAD 0 /* Disable clamping for node panning, use whole screen. */ #define NODE_EDGE_PAN_SPEED_RAMP 1 diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index abadbe5a5c6..54e434e0db5 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -381,6 +381,8 @@ struct Object *ED_object_add_type(struct bContext *C, */ void ED_object_single_user(struct Main *bmain, struct Scene *scene, struct Object *ob); +void ED_object_single_obdata_user(struct Main *bmain, struct Scene *scene, struct Object *ob); + /* object motion paths */ /** diff --git a/source/blender/editors/include/ED_select_utils.h b/source/blender/editors/include/ED_select_utils.h index b9ef5c283aa..dbe1b582132 100644 --- a/source/blender/editors/include/ED_select_utils.h +++ b/source/blender/editors/include/ED_select_utils.h @@ -6,11 +6,14 @@ #pragma once +#include "BLI_compiler_attrs.h" + #ifdef __cplusplus extern "C" { #endif struct KDTree_1d; +struct wmOperator; enum { SEL_TOGGLE = 0, @@ -93,7 +96,15 @@ struct SelectPick_Params { /** * Utility to get #eSelectPickMode from booleans for convenience. */ -eSelectOp ED_select_op_from_booleans(bool extend, bool deselect, bool toggle); +eSelectOp ED_select_op_from_operator(struct wmOperator *op) + ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT; + +/** + * Initialize `params` from `op`, + * these properties are defined by #WM_operator_properties_mouse_select. + */ +void ED_select_pick_params_from_operator(struct wmOperator *op, struct SelectPick_Params *params) + ATTR_NONNULL(1, 2); #ifdef __cplusplus } diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h index fa53e7a76e4..2919001c5ce 100644 --- a/source/blender/editors/include/ED_transform_snap_object_context.h +++ b/source/blender/editors/include/ED_transform_snap_object_context.h @@ -21,19 +21,19 @@ struct Object; struct Scene; struct View3D; -/* transform_snap_object.c */ +/* transform_snap_object.cc */ /* ED_transform_snap_object_*** API */ -typedef enum { +typedef enum eSnapSelect { SNAP_ALL = 0, SNAP_NOT_SELECTED = 1, SNAP_NOT_ACTIVE = 2, - SNAP_ONLY_ACTIVE = 3, + SNAP_NOT_EDITED = 3, SNAP_SELECTABLE = 4, } eSnapSelect; -typedef enum { +typedef enum eSnapEditType { SNAP_GEOM_FINAL = 0, SNAP_GEOM_CAGE = 1, SNAP_GEOM_EDIT = 2, /* Bmesh for mesh-type. */ @@ -59,13 +59,13 @@ struct SnapObjectHitDepth { /** parameters that define which objects will be used to snap. */ struct SnapObjectParams { /* Special context sensitive handling for the active or selected object. */ - char snap_select; + eSnapSelect snap_select; /* Geometry for snapping in edit mode. */ - char edit_mode_type; + eSnapEditType edit_mode_type; /* snap to the closest element, use when using more than one snap type */ - unsigned int use_occlusion_test : 1; + bool use_occlusion_test : true; /* exclude back facing geometry from snapping */ - unsigned int use_backface_culling : 1; + bool use_backface_culling : true; }; typedef struct SnapObjectContext SnapObjectContext; diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 14cb02121bf..b10dbf3084a 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -273,9 +273,8 @@ typedef enum { V3D_SNAPCURSOR_TOGGLE_ALWAYS_TRUE = 1 << 0, V3D_SNAPCURSOR_OCCLUSION_ALWAYS_TRUE = 1 << 1, V3D_SNAPCURSOR_OCCLUSION_ALWAYS_FALSE = 1 << 2, /* TODO. */ - V3D_SNAPCURSOR_SNAP_ONLY_ACTIVE = 1 << 3, - V3D_SNAPCURSOR_SNAP_EDIT_GEOM_FINAL = 1 << 4, - V3D_SNAPCURSOR_SNAP_EDIT_GEOM_CAGE = 1 << 5, + V3D_SNAPCURSOR_SNAP_EDIT_GEOM_FINAL = 1 << 3, + V3D_SNAPCURSOR_SNAP_EDIT_GEOM_CAGE = 1 << 4, } eV3DSnapCursor; typedef enum { diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index a560208ac1e..94232a5108d 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -246,7 +246,7 @@ DEF_ICON(RENDER_STILL) DEF_ICON(LIBRARY_DATA_BROKEN) DEF_ICON(BOIDS) DEF_ICON(STRANDS) -DEF_ICON(LIBRARY_DATA_INDIRECT) +DEF_ICON_BLANK(263) DEF_ICON(GREASEPENCIL) DEF_ICON_SHADING(LINE_DATA) DEF_ICON(LIBRARY_DATA_OVERRIDE) @@ -981,6 +981,9 @@ DEF_ICON_VECTOR(SEQUENCE_COLOR_07) DEF_ICON_VECTOR(SEQUENCE_COLOR_08) DEF_ICON_VECTOR(SEQUENCE_COLOR_09) +DEF_ICON_VECTOR(LIBRARY_DATA_INDIRECT) +DEF_ICON_VECTOR(LIBRARY_DATA_OVERRIDE_NONEDITABLE) + /* Events. */ DEF_ICON_COLOR(EVENT_A) DEF_ICON_COLOR(EVENT_B) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index d8415064d2f..ce86cdfc226 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -634,7 +634,7 @@ uiPopupMenu *UI_popup_menu_begin_ex(struct bContext *C, * Set the whole structure to work. */ void UI_popup_menu_end(struct bContext *C, struct uiPopupMenu *pup); -bool UI_popup_menu_end_or_cancel(struct bContext *C, struct uiPopupMenu *head); +bool UI_popup_menu_end_or_cancel(struct bContext *C, struct uiPopupMenu *pup); struct uiLayout *UI_popup_menu_layout(uiPopupMenu *pup); void UI_popup_menu_reports(struct bContext *C, struct ReportList *reports) ATTR_NONNULL(); @@ -1595,13 +1595,15 @@ typedef enum { } eButLabelAlign; /* Return info for uiDefAutoButsRNA */ -typedef enum { +typedef enum eAutoPropButsReturn { /* Returns when no buttons were added */ UI_PROP_BUTS_NONE_ADDED = 1 << 0, /* Returned when any property failed the custom check callback (check_prop) */ UI_PROP_BUTS_ANY_FAILED_CHECK = 1 << 1, } eAutoPropButsReturn; +ENUM_OPERATORS(eAutoPropButsReturn, UI_PROP_BUTS_ANY_FAILED_CHECK); + uiBut *uiDefAutoButR(uiBlock *block, struct PointerRNA *ptr, struct PropertyRNA *prop, diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index b69d3008f1d..4282465c0ca 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -178,12 +178,12 @@ void UI_view2d_multi_grid_draw( * \param grid_color_id: The theme color used for the points. Faded dynamically based on zoom. * \param min_step: The base size of the grid. At different zoom levels, the visible grid may have * a larger step size. - * \param grid_levels: The maximum grid depth. Larger grid levels will subdivide the grid more. + * \param grid_subdivisions: The maximum number of sub-levels drawn at once. */ void UI_view2d_dot_grid_draw(const struct View2D *v2d, int grid_color_id, float min_step, - int grid_levels); + int grid_subdivisions); void UI_view2d_draw_lines_y__values(const struct View2D *v2d); void UI_view2d_draw_lines_x__values(const struct View2D *v2d); diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt index 14d8e136061..8a45768f3dc 100644 --- a/source/blender/editors/interface/CMakeLists.txt +++ b/source/blender/editors/interface/CMakeLists.txt @@ -46,17 +46,17 @@ set(SRC interface_layout.c interface_ops.c interface_panel.c - interface_query.c - interface_region_color_picker.c - interface_region_hud.c - interface_region_menu_pie.c - interface_region_menu_popup.c - interface_region_popover.c - interface_region_popup.c + interface_query.cc + interface_region_color_picker.cc + interface_region_hud.cc + interface_region_menu_pie.cc + interface_region_menu_popup.cc + interface_region_popover.cc + interface_region_popup.cc interface_region_search.cc interface_region_tooltip.c - interface_regions.c - interface_style.c + interface_regions.cc + interface_style.cc interface_template_asset_view.cc interface_template_attribute_search.cc interface_template_list.cc @@ -64,7 +64,7 @@ set(SRC interface_template_search_operator.c interface_templates.c interface_undo.c - interface_utils.c + interface_utils.cc interface_view.cc interface_widgets.c resources.c diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index c02024bc82d..695f34a448f 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -38,6 +38,7 @@ #include "GPU_batch.h" #include "GPU_batch_presets.h" +#include "GPU_context.h" #include "GPU_immediate.h" #include "GPU_immediate_util.h" #include "GPU_matrix.h" @@ -1084,12 +1085,23 @@ static void ui_draw_colorband_handle_tri( static void ui_draw_colorband_handle_box( uint pos, float x1, float y1, float x2, float y2, bool fill) { - immBegin(fill ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, 4); - immVertex2f(pos, x1, y1); - immVertex2f(pos, x1, y2); - immVertex2f(pos, x2, y2); - immVertex2f(pos, x2, y1); - immEnd(); + if (fill) { + immBegin(GPU_PRIM_TRI_STRIP, 4); + immVertex2f(pos, x2, y1); + immVertex2f(pos, x1, y1); + immVertex2f(pos, x2, y2); + immVertex2f(pos, x1, y2); + immEnd(); + } + else { + immBegin(GPU_PRIM_LINE_STRIP, 5); + immVertex2f(pos, x1, y1); + immVertex2f(pos, x1, y2); + immVertex2f(pos, x2, y2); + immVertex2f(pos, x2, y1); + immVertex2f(pos, x1, y1); + immEnd(); + } } static void ui_draw_colorband_handle(uint shdr_pos, diff --git a/source/blender/editors/interface/interface_eyedropper_depth.c b/source/blender/editors/interface/interface_eyedropper_depth.c index 4710bada8e0..56bc1a6d956 100644 --- a/source/blender/editors/interface/interface_eyedropper_depth.c +++ b/source/blender/editors/interface/interface_eyedropper_depth.c @@ -22,6 +22,7 @@ #include "BLI_string.h" #include "BKE_context.h" +#include "BKE_lib_id.h" #include "BKE_screen.h" #include "BKE_unit.h" @@ -88,7 +89,8 @@ static int depthdropper_init(bContext *C, wmOperator *op) RegionView3D *rv3d = CTX_wm_region_view3d(C); if (rv3d && rv3d->persp == RV3D_CAMOB) { View3D *v3d = CTX_wm_view3d(C); - if (v3d->camera && v3d->camera->data && !ID_IS_LINKED(v3d->camera->data)) { + if (v3d->camera && v3d->camera->data && + BKE_id_is_editable(CTX_data_main(C), v3d->camera->data)) { Camera *camera = (Camera *)v3d->camera->data; RNA_pointer_create(&camera->id, &RNA_CameraDOFSettings, &camera->dof, &ddr->ptr); ddr->prop = RNA_struct_find_property(&ddr->ptr, "focus_distance"); @@ -348,7 +350,8 @@ static bool depthdropper_poll(bContext *C) RegionView3D *rv3d = CTX_wm_region_view3d(C); if (rv3d && rv3d->persp == RV3D_CAMOB) { View3D *v3d = CTX_wm_view3d(C); - if (v3d->camera && v3d->camera->data && !ID_IS_LINKED(v3d->camera->data)) { + if (v3d->camera && v3d->camera->data && + BKE_id_is_editable(CTX_data_main(C), v3d->camera->data)) { return true; } } diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 07e4f6c2a24..e3bf1a48907 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -465,6 +465,32 @@ DEF_ICON_STRIP_COLOR_DRAW(09, SEQUENCE_COLOR_09); # undef DEF_ICON_STRIP_COLOR_DRAW +# define ICON_INDIRECT_DATA_ALPHA 0.6f + +static void vicon_strip_color_draw_library_data_indirect( + int x, int y, int w, int UNUSED(h), float alpha) +{ + const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w; + + UI_icon_draw_ex( + x, y, ICON_LIBRARY_DATA_DIRECT, aspect, ICON_INDIRECT_DATA_ALPHA * alpha, 0.0f, NULL, false); +} + +static void vicon_strip_color_draw_library_data_override_noneditable( + int x, int y, int w, int UNUSED(h), float alpha) +{ + const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w; + + UI_icon_draw_ex(x, + y, + ICON_LIBRARY_DATA_OVERRIDE, + aspect, + ICON_INDIRECT_DATA_ALPHA * alpha * 0.75f, + 0.0f, + NULL, + false); +} + /* Dynamically render icon instead of rendering a plain color to a texture/buffer * This is not strictly a "vicon", as it needs access to icon->obj to get the color info, * but it works in a very similar way. @@ -974,6 +1000,10 @@ static void init_internal_icons(void) def_internal_vicon(ICON_SEQUENCE_COLOR_07, vicon_strip_color_draw_07); def_internal_vicon(ICON_SEQUENCE_COLOR_08, vicon_strip_color_draw_08); def_internal_vicon(ICON_SEQUENCE_COLOR_09, vicon_strip_color_draw_09); + + def_internal_vicon(ICON_LIBRARY_DATA_INDIRECT, vicon_strip_color_draw_library_data_indirect); + def_internal_vicon(ICON_LIBRARY_DATA_OVERRIDE_NONEDITABLE, + vicon_strip_color_draw_library_data_override_noneditable); } static void init_iconfile_list(struct ListBase *list) @@ -2179,6 +2209,10 @@ int UI_icon_from_library(const ID *id) return ICON_LIBRARY_DATA_DIRECT; } if (ID_IS_OVERRIDE_LIBRARY(id)) { + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id) || + (id->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED) != 0) { + return ICON_LIBRARY_DATA_OVERRIDE_NONEDITABLE; + } return ICON_LIBRARY_DATA_OVERRIDE; } if (ID_IS_ASSET(id)) { diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index a7a2409ef17..e619b14fb69 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -214,8 +214,8 @@ struct uiBut { BIFIconID icon; /** Copied from the #uiBlock.emboss */ eUIEmbossType emboss; - /** direction in a pie menu, used for collision detection (RadialDirection) */ - signed char pie_dir; + /** direction in a pie menu, used for collision detection. */ + RadialDirection pie_dir; /** could be made into a single flag */ bool changed; /** so buttons can support unit systems which are not RNA */ @@ -954,7 +954,7 @@ void ui_pie_menu_level_create(uiBlock *block, const EnumPropertyItem *items, int totitem, wmOperatorCallContext context, - int flag); + wmOperatorCallContext flag); /* interface_region_popup.c */ diff --git a/source/blender/editors/interface/interface_query.c b/source/blender/editors/interface/interface_query.cc index 4703367671d..2767a184619 100644 --- a/source/blender/editors/interface/interface_query.c +++ b/source/blender/editors/interface/interface_query.cc @@ -61,7 +61,7 @@ bool ui_but_is_toggle(const uiBut *but) bool ui_but_is_interactive(const uiBut *but, const bool labeledit) { /* NOTE: #UI_BTYPE_LABEL is included for highlights, this allows drags. */ - if ((but->type == UI_BTYPE_LABEL) && but->dragpoin == NULL) { + if ((but->type == UI_BTYPE_LABEL) && but->dragpoin == nullptr) { return false; } if (ELEM(but->type, UI_BTYPE_ROUNDBOX, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_LISTBOX)) { @@ -119,12 +119,12 @@ bool ui_but_has_array_value(const uiBut *but) PROP_COORDS)); } -static wmOperatorType *g_ot_tool_set_by_id = NULL; +static wmOperatorType *g_ot_tool_set_by_id = nullptr; bool UI_but_is_tool(const uiBut *but) { /* very evil! */ - if (but->optype != NULL) { - if (g_ot_tool_set_by_id == NULL) { + if (but->optype != nullptr) { + if (g_ot_tool_set_by_id == nullptr) { g_ot_tool_set_by_id = WM_operatortype_find("WM_OT_tool_set_by_id", false); } if (but->optype == g_ot_tool_set_by_id) { @@ -198,7 +198,7 @@ bool ui_but_contains_pt(const uiBut *but, float mx, float my) bool ui_but_contains_rect(const uiBut *but, const rctf *rect) { - return BLI_rctf_isect(&but->rect, rect, NULL); + return BLI_rctf_isect(&but->rect, rect, nullptr); } bool ui_but_contains_point_px(const uiBut *but, const ARegion *region, const int xy[2]) @@ -260,7 +260,7 @@ static uiBut *ui_but_find(const ARegion *region, } } - return NULL; + return nullptr; } uiBut *ui_but_find_mouse_over_ex(const ARegion *region, @@ -269,10 +269,10 @@ uiBut *ui_but_find_mouse_over_ex(const ARegion *region, const uiButFindPollFn find_poll, const void *find_custom_data) { - uiBut *butover = NULL; + uiBut *butover = nullptr; if (!ui_region_contains_point_px(region, xy)) { - return NULL; + return nullptr; } LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { float mx = xy[0], my = xy[1]; @@ -310,20 +310,20 @@ uiBut *ui_but_find_mouse_over_ex(const ARegion *region, uiBut *ui_but_find_mouse_over(const ARegion *region, const wmEvent *event) { - return ui_but_find_mouse_over_ex(region, event->xy, event->modifier & KM_CTRL, NULL, NULL); + return ui_but_find_mouse_over_ex(region, event->xy, event->modifier & KM_CTRL, nullptr, nullptr); } uiBut *ui_but_find_rect_over(const struct ARegion *region, const rcti *rect_px) { if (!ui_region_contains_rect_px(region, rect_px)) { - return NULL; + return nullptr; } /* Currently no need to expose this at the moment. */ const bool labeledit = true; rctf rect_px_fl; BLI_rctf_rcti_copy(&rect_px_fl, rect_px); - uiBut *butover = NULL; + uiBut *butover = nullptr; LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { rctf rect_block; @@ -343,7 +343,7 @@ uiBut *ui_but_find_rect_over(const struct ARegion *region, const rcti *rect_px) /* CLIP_EVENTS prevents the event from reaching other blocks */ if (block->flag & UI_BLOCK_CLIP_EVENTS) { /* check if mouse is inside block */ - if (BLI_rctf_isect(&block->rect, &rect_block, NULL)) { + if (BLI_rctf_isect(&block->rect, &rect_block, nullptr)) { break; } } @@ -354,7 +354,7 @@ uiBut *ui_but_find_rect_over(const struct ARegion *region, const rcti *rect_px) uiBut *ui_list_find_mouse_over_ex(const ARegion *region, const int xy[2]) { if (!ui_region_contains_point_px(region, xy)) { - return NULL; + return nullptr; } LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { float mx = xy[0], my = xy[1]; @@ -366,14 +366,14 @@ uiBut *ui_list_find_mouse_over_ex(const ARegion *region, const int xy[2]) } } - return NULL; + return nullptr; } uiBut *ui_list_find_mouse_over(const ARegion *region, const wmEvent *event) { - if (event == NULL) { + if (event == nullptr) { /* If there is no info about the mouse, just act as if there is nothing underneath it. */ - return NULL; + return nullptr; } return ui_list_find_mouse_over_ex(region, event->xy); } @@ -382,10 +382,10 @@ uiList *UI_list_find_mouse_over(const ARegion *region, const wmEvent *event) { uiBut *list_but = ui_list_find_mouse_over(region, event); if (!list_but) { - return NULL; + return nullptr; } - return list_but->custom_data; + return static_cast<uiList *>(list_but->custom_data); } static bool ui_list_contains_row(const uiBut *listbox_but, const uiBut *listrow_but) @@ -398,7 +398,7 @@ static bool ui_list_contains_row(const uiBut *listbox_but, const uiBut *listrow_ static bool ui_but_is_listbox_with_row(const uiBut *but, const void *customdata) { - const uiBut *row_but = customdata; + const uiBut *row_but = static_cast<const uiBut *>(customdata); return (but->type == UI_BTYPE_LISTBOX) && ui_list_contains_row(but, row_but); } @@ -414,7 +414,7 @@ static bool ui_but_is_listrow(const uiBut *but, const void *UNUSED(customdata)) uiBut *ui_list_row_find_mouse_over(const ARegion *region, const int xy[2]) { - return ui_but_find_mouse_over_ex(region, xy, false, ui_but_is_listrow, NULL); + return ui_but_find_mouse_over_ex(region, xy, false, ui_but_is_listrow, nullptr); } struct ListRowFindIndexData { @@ -424,19 +424,18 @@ struct ListRowFindIndexData { static bool ui_but_is_listrow_at_index(const uiBut *but, const void *customdata) { - const struct ListRowFindIndexData *find_data = customdata; + const ListRowFindIndexData *find_data = static_cast<const ListRowFindIndexData *>(customdata); - return ui_but_is_listrow(but, NULL) && ui_list_contains_row(find_data->listbox, but) && + return ui_but_is_listrow(but, nullptr) && ui_list_contains_row(find_data->listbox, but) && (but->hardmax == find_data->index); } uiBut *ui_list_row_find_from_index(const ARegion *region, const int index, uiBut *listbox) { BLI_assert(listbox->type == UI_BTYPE_LISTBOX); - struct ListRowFindIndexData data = { - .index = index, - .listbox = listbox, - }; + ListRowFindIndexData data = {}; + data.index = index; + data.listbox = listbox; return ui_but_find(region, ui_but_is_listrow_at_index, &data); } @@ -447,7 +446,7 @@ static bool ui_but_is_treerow(const uiBut *but, const void *UNUSED(customdata)) uiBut *ui_tree_row_find_mouse_over(const ARegion *region, const int xy[2]) { - return ui_but_find_mouse_over_ex(region, xy, false, ui_but_is_treerow, NULL); + return ui_but_find_mouse_over_ex(region, xy, false, ui_but_is_treerow, nullptr); } static bool ui_but_is_active_treerow(const uiBut *but, const void *customdata) @@ -462,7 +461,7 @@ static bool ui_but_is_active_treerow(const uiBut *but, const void *customdata) uiBut *ui_tree_row_find_active(const ARegion *region) { - return ui_but_find(region, ui_but_is_active_treerow, NULL); + return ui_but_find(region, ui_but_is_active_treerow, nullptr); } /** \} */ @@ -479,7 +478,7 @@ uiBut *ui_but_prev(uiBut *but) return but; } } - return NULL; + return nullptr; } uiBut *ui_but_next(uiBut *but) @@ -490,7 +489,7 @@ uiBut *ui_but_next(uiBut *but) return but; } } - return NULL; + return nullptr; } uiBut *ui_but_first(uiBlock *block) @@ -500,21 +499,19 @@ uiBut *ui_but_first(uiBlock *block) return but; } } - return NULL; + return nullptr; } uiBut *ui_but_last(uiBlock *block) { - uiBut *but; - - but = block->buttons.last; + uiBut *but = static_cast<uiBut *>(block->buttons.last); while (but) { if (ui_but_is_editable(but)) { return but; } but = but->prev; } - return NULL; + return nullptr; } bool ui_but_is_cursor_warp(const uiBut *but) @@ -550,7 +547,7 @@ size_t ui_but_drawstr_len_without_sep_char(const uiBut *but) { if (but->flag & UI_BUT_HAS_SEP_CHAR) { const char *str_sep = strrchr(but->drawstr, UI_SEP_CHAR); - if (str_sep != NULL) { + if (str_sep != nullptr) { return (str_sep - but->drawstr); } } @@ -565,12 +562,12 @@ size_t ui_but_drawstr_without_sep_char(const uiBut *but, char *str, size_t str_m size_t ui_but_tip_len_only_first_line(const uiBut *but) { - if (but->tip == NULL) { + if (but->tip == nullptr) { return 0; } const char *str_sep = strchr(but->tip, '\n'); - if (str_sep != NULL) { + if (str_sep != nullptr) { return (str_sep - but->tip); } return strlen(but->tip); @@ -590,7 +587,7 @@ uiBut *ui_block_active_but_get(const uiBlock *block) } } - return NULL; + return nullptr; } bool ui_block_is_menu(const uiBlock *block) @@ -622,12 +619,12 @@ static const uiBut *ui_but_next_non_separator(const uiBut *but) return but; } } - return NULL; + return nullptr; } bool UI_block_is_empty_ex(const uiBlock *block, const bool skip_title) { - const uiBut *but = block->buttons.first; + const uiBut *but = static_cast<const uiBut *>(block->buttons.first); if (skip_title) { /* Skip the first label, since popups often have a title, * we may want to consider the block empty in this case. */ @@ -636,7 +633,7 @@ bool UI_block_is_empty_ex(const uiBlock *block, const bool skip_title) but = but->next; } } - return (ui_but_next_non_separator(but) == NULL); + return (ui_but_next_non_separator(but) == nullptr); } bool UI_block_is_empty(const uiBlock *block) @@ -647,7 +644,7 @@ bool UI_block_is_empty(const uiBlock *block) bool UI_block_can_add_separator(const uiBlock *block) { if (ui_block_is_menu(block) && !ui_block_is_pie_menu(block)) { - const uiBut *but = block->buttons.last; + const uiBut *but = static_cast<const uiBut *>(block->buttons.last); return (but && !ELEM(but->type, UI_BTYPE_SEPR_LINE, UI_BTYPE_SEPR)); } return true; @@ -662,7 +659,7 @@ bool UI_block_can_add_separator(const uiBlock *block) uiBlock *ui_block_find_mouse_over_ex(const ARegion *region, const int xy[2], bool only_clip) { if (!ui_region_contains_point_px(region, xy)) { - return NULL; + return nullptr; } LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { if (only_clip) { @@ -676,7 +673,7 @@ uiBlock *ui_block_find_mouse_over_ex(const ARegion *region, const int xy[2], boo return block; } } - return NULL; + return nullptr; } uiBlock *ui_block_find_mouse_over(const ARegion *region, const wmEvent *event, bool only_clip) @@ -699,7 +696,7 @@ uiBut *ui_region_find_active_but(ARegion *region) } } - return NULL; + return nullptr; } uiBut *ui_region_find_first_but_test_flag(ARegion *region, int flag_include, int flag_exclude) @@ -712,7 +709,7 @@ uiBut *ui_region_find_first_but_test_flag(ARegion *region, int flag_include, int } } - return NULL; + return nullptr; } /** \} */ @@ -752,7 +749,7 @@ bool ui_region_contains_rect_px(const ARegion *region, const rcti *rect_px) { rcti winrct; ui_region_winrct_get_no_margin(region, &winrct); - if (!BLI_rcti_isect(&winrct, rect_px, NULL)) { + if (!BLI_rcti_isect(&winrct, rect_px, nullptr)) { return false; } @@ -761,7 +758,7 @@ bool ui_region_contains_rect_px(const ARegion *region, const rcti *rect_px) const View2D *v2d = ®ion->v2d; rcti rect_region; ui_window_to_region_rcti(region, &rect_region, rect_px); - if (!BLI_rcti_isect(&v2d->mask, &rect_region, NULL) || + if (!BLI_rcti_isect(&v2d->mask, &rect_region, nullptr) || UI_view2d_rect_in_scrollers(region, ®ion->v2d, rect_px)) { return false; } @@ -787,7 +784,7 @@ ARegion *ui_screen_region_find_mouse_over_ex(bScreen *screen, const int xy[2]) return region; } } - return NULL; + return nullptr; } ARegion *ui_screen_region_find_mouse_over(bScreen *screen, const wmEvent *event) @@ -803,7 +800,7 @@ ARegion *ui_screen_region_find_mouse_over(bScreen *screen, const wmEvent *event) void ui_interface_tag_script_reload_queries(void) { - g_ot_tool_set_by_id = NULL; + g_ot_tool_set_by_id = nullptr; } /** \} */ diff --git a/source/blender/editors/interface/interface_region_color_picker.c b/source/blender/editors/interface/interface_region_color_picker.cc index 9fb6f538191..ab0a6039cdc 100644 --- a/source/blender/editors/interface/interface_region_color_picker.c +++ b/source/blender/editors/interface/interface_region_color_picker.cc @@ -7,9 +7,9 @@ * Color Picker Region & Color Utils */ -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> +#include <cstdarg> +#include <cstdlib> +#include <cstring> #include "MEM_guardedalloc.h" @@ -168,7 +168,7 @@ static void ui_color_picker_update_hsv(ColorPicker *cpicker, void ui_but_hsv_set(uiBut *but) { float rgb_perceptual[3]; - ColorPicker *cpicker = but->custom_data; + ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data); float *hsv_perceptual = cpicker->hsv_perceptual; ui_color_picker_hsv_to_rgb(hsv_perceptual, rgb_perceptual); @@ -255,7 +255,8 @@ static void ui_colorpicker_rgba_update_cb(bContext *UNUSED(C), void *bt1, void * if (prop) { RNA_property_float_get_array(&ptr, prop, rgb_scene_linear); - ui_update_color_picker_buts_rgb(but, but->block, but->custom_data, rgb_scene_linear); + ui_update_color_picker_buts_rgb( + but, but->block, static_cast<ColorPicker *>(but->custom_data), rgb_scene_linear); } if (popup) { @@ -268,7 +269,7 @@ static void ui_colorpicker_hsv_update_cb(bContext *UNUSED(C), void *bt1, void *U uiBut *but = (uiBut *)bt1; uiPopupBlockHandle *popup = but->block->handle; float rgb_scene_linear[3]; - ColorPicker *cpicker = but->custom_data; + ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data); ui_color_picker_hsv_to_rgb(cpicker->hsv_scene_linear, rgb_scene_linear); ui_update_color_picker_buts_rgb(but, but->block, cpicker, rgb_scene_linear); @@ -282,7 +283,7 @@ static void ui_colorpicker_hex_rna_cb(bContext *UNUSED(C), void *bt1, void *hexc { uiBut *but = (uiBut *)bt1; uiPopupBlockHandle *popup = but->block->handle; - ColorPicker *cpicker = but->custom_data; + ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data); char *hexcol = (char *)hexcl; float rgb[3]; @@ -307,7 +308,7 @@ static void ui_popup_close_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg)) uiPopupBlockHandle *popup = but->block->handle; if (popup) { - ColorPicker *cpicker = but->custom_data; + ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data); BLI_assert(cpicker->is_init); popup->menuretval = (equals_v3v3(cpicker->hsv_perceptual, cpicker->hsv_perceptual_init) ? UI_RETURN_CANCEL : @@ -315,7 +316,7 @@ static void ui_popup_close_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg)) } } -static void ui_colorpicker_hide_reveal(uiBlock *block, enum ePickerType colormode) +static void ui_colorpicker_hide_reveal(uiBlock *block, ePickerType colormode) { /* tag buttons */ LISTBASE_FOREACH (uiBut *, bt, &block->buttons) { @@ -337,9 +338,9 @@ static void ui_colorpicker_hide_reveal(uiBlock *block, enum ePickerType colormod static void ui_colorpicker_create_mode_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg)) { - uiBut *bt = bt1; + uiBut *bt = static_cast<uiBut *>(bt1); const short colormode = ui_but_value_get(bt); - ui_colorpicker_hide_reveal(bt->block, colormode); + ui_colorpicker_hide_reveal(bt->block, (ePickerType)colormode); } #define PICKER_H (7.5f * U.widget_unit) @@ -374,7 +375,7 @@ static void ui_colorpicker_circle(uiBlock *block, 0.0, 0, TIP_("Color")); - UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, NULL); + UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, nullptr); bt->custom_data = cpicker; /* value */ @@ -396,7 +397,7 @@ static void ui_colorpicker_circle(uiBlock *block, 0, "Lightness"); hsv_but->gradient_type = UI_GRAD_L_ALT; - UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, NULL); + UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, nullptr); } else { hsv_but = (uiButHSVCube *)uiDefButR_prop(block, @@ -416,7 +417,7 @@ static void ui_colorpicker_circle(uiBlock *block, 0, TIP_("Value")); hsv_but->gradient_type = UI_GRAD_V_ALT; - UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, NULL); + UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, nullptr); } hsv_but->but.custom_data = cpicker; } @@ -449,7 +450,7 @@ static void ui_colorpicker_square(uiBlock *block, 0, TIP_("Color")); hsv_but->gradient_type = type; - UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, NULL); + UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, nullptr); hsv_but->but.custom_data = cpicker; /* value */ @@ -469,8 +470,8 @@ static void ui_colorpicker_square(uiBlock *block, 0, 0, TIP_("Value")); - hsv_but->gradient_type = type + 3; - UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, NULL); + hsv_but->gradient_type = (eButGradientType)(type + 3); + UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, nullptr); hsv_but->but.custom_data = cpicker; } @@ -547,7 +548,7 @@ static void ui_block_colorpicker(uiBlock *block, ""); UI_but_flag_disable(bt, UI_BUT_UNDO); UI_but_drawflag_disable(bt, UI_BUT_TEXT_LEFT); - UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, NULL); + UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, nullptr); bt->custom_data = cpicker; bt = uiDefButC(block, UI_BTYPE_ROW, @@ -565,7 +566,7 @@ static void ui_block_colorpicker(uiBlock *block, ""); UI_but_flag_disable(bt, UI_BUT_UNDO); UI_but_drawflag_disable(bt, UI_BUT_TEXT_LEFT); - UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, NULL); + UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, nullptr); bt->custom_data = cpicker; bt = uiDefButC(block, UI_BTYPE_ROW, @@ -583,7 +584,7 @@ static void ui_block_colorpicker(uiBlock *block, ""); UI_but_flag_disable(bt, UI_BUT_UNDO); UI_but_drawflag_disable(bt, UI_BUT_TEXT_LEFT); - UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, NULL); + UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, nullptr); bt->custom_data = cpicker; UI_block_align_end(block); @@ -598,10 +599,10 @@ static void ui_block_colorpicker(uiBlock *block, yco, UI_UNIT_X, UI_UNIT_Y, - NULL); + nullptr); UI_but_flag_disable(bt, UI_BUT_UNDO); UI_but_drawflag_disable(bt, UI_BUT_ICON_LEFT); - UI_but_func_set(bt, ui_popup_close_cb, bt, NULL); + UI_but_func_set(bt, ui_popup_close_cb, bt, nullptr); bt->custom_data = cpicker; } @@ -625,7 +626,7 @@ static void ui_block_colorpicker(uiBlock *block, 0, 3, TIP_("Red")); - UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, NULL); + UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, nullptr); bt->custom_data = cpicker; bt = uiDefButR_prop(block, UI_BTYPE_NUM_SLIDER, @@ -643,7 +644,7 @@ static void ui_block_colorpicker(uiBlock *block, 0, 3, TIP_("Green")); - UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, NULL); + UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, nullptr); bt->custom_data = cpicker; bt = uiDefButR_prop(block, UI_BTYPE_NUM_SLIDER, @@ -661,7 +662,7 @@ static void ui_block_colorpicker(uiBlock *block, 0, 3, TIP_("Blue")); - UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, NULL); + UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, nullptr); bt->custom_data = cpicker; /* Could use: @@ -686,7 +687,7 @@ static void ui_block_colorpicker(uiBlock *block, 3, TIP_("Hue")); UI_but_flag_disable(bt, UI_BUT_UNDO); - UI_but_func_set(bt, ui_colorpicker_hsv_update_cb, bt, NULL); + UI_but_func_set(bt, ui_colorpicker_hsv_update_cb, bt, nullptr); bt->custom_data = cpicker; bt = uiDefButF(block, UI_BTYPE_NUM_SLIDER, @@ -703,7 +704,7 @@ static void ui_block_colorpicker(uiBlock *block, 3, TIP_("Saturation")); UI_but_flag_disable(bt, UI_BUT_UNDO); - UI_but_func_set(bt, ui_colorpicker_hsv_update_cb, bt, NULL); + UI_but_func_set(bt, ui_colorpicker_hsv_update_cb, bt, nullptr); bt->custom_data = cpicker; if (U.color_picker_type == USER_CP_CIRCLE_HSL) { bt = uiDefButF(block, @@ -740,7 +741,7 @@ static void ui_block_colorpicker(uiBlock *block, UI_but_flag_disable(bt, UI_BUT_UNDO); bt->hardmax = hardmax; /* not common but rgb may be over 1.0 */ - UI_but_func_set(bt, ui_colorpicker_hsv_update_cb, bt, NULL); + UI_but_func_set(bt, ui_colorpicker_hsv_update_cb, bt, nullptr); bt->custom_data = cpicker; UI_block_align_end(block); @@ -762,7 +763,7 @@ static void ui_block_colorpicker(uiBlock *block, 0, 3, TIP_("Alpha")); - UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, NULL); + UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, nullptr); bt->custom_data = cpicker; } else { @@ -809,14 +810,14 @@ static void ui_block_colorpicker(uiBlock *block, yco - UI_UNIT_Y, butwidth, UI_UNIT_Y, - NULL, + nullptr, 0.0, 0.0, 0, 0, ""); - ui_colorpicker_hide_reveal(block, colormode); + ui_colorpicker_hide_reveal(block, (ePickerType)colormode); } static int ui_colorpicker_small_wheel_cb(const bContext *UNUSED(C), @@ -834,9 +835,9 @@ static int ui_colorpicker_small_wheel_cb(const bContext *UNUSED(C), if (add != 0.0f) { LISTBASE_FOREACH (uiBut *, but, &block->buttons) { - if (but->type == UI_BTYPE_HSVCUBE && but->active == NULL) { + if (but->type == UI_BTYPE_HSVCUBE && but->active == nullptr) { uiPopupBlockHandle *popup = block->handle; - ColorPicker *cpicker = but->custom_data; + ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data); float *hsv_perceptual = cpicker->hsv_perceptual; float rgb_perceptual[3]; @@ -865,7 +866,7 @@ static int ui_colorpicker_small_wheel_cb(const bContext *UNUSED(C), uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_but) { - uiBut *but = arg_but; + uiBut *but = static_cast<uiBut *>(arg_but); uiBlock *block; bool show_picker = true; @@ -901,7 +902,7 @@ uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_ ColorPicker *ui_block_colorpicker_create(struct uiBlock *block) { - ColorPicker *cpicker = MEM_callocN(sizeof(ColorPicker), "color_picker"); + ColorPicker *cpicker = MEM_cnew<ColorPicker>(__func__); BLI_addhead(&block->color_pickers.list, cpicker); return cpicker; diff --git a/source/blender/editors/interface/interface_region_hud.c b/source/blender/editors/interface/interface_region_hud.cc index 4d72cd5382c..d6166694a4a 100644 --- a/source/blender/editors/interface/interface_region_hud.c +++ b/source/blender/editors/interface/interface_region_hud.cc @@ -7,7 +7,7 @@ * Floating Persistent Region */ -#include <string.h> +#include <cstring> #include "MEM_guardedalloc.h" @@ -49,7 +49,7 @@ struct HudRegionData { static bool last_redo_poll(const bContext *C, short region_type) { wmOperator *op = WM_operator_last_redo(C); - if (op == NULL) { + if (op == nullptr) { return false; } @@ -60,7 +60,8 @@ static bool last_redo_poll(const bContext *C, short region_type) * wrong context. */ ScrArea *area = CTX_wm_area(C); - ARegion *region_op = (region_type != -1) ? BKE_area_find_region_type(area, region_type) : NULL; + ARegion *region_op = (region_type != -1) ? BKE_area_find_region_type(area, region_type) : + nullptr; ARegion *region_prev = CTX_wm_region(C); CTX_wm_region_set((bContext *)C, region_op); @@ -90,9 +91,9 @@ static bool hud_panel_operator_redo_poll(const bContext *C, PanelType *UNUSED(pt { ScrArea *area = CTX_wm_area(C); ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_HUD); - if (region != NULL) { - struct HudRegionData *hrd = region->regiondata; - if (hrd != NULL) { + if (region != nullptr) { + HudRegionData *hrd = static_cast<HudRegionData *>(region->regiondata); + if (hrd != nullptr) { return last_redo_poll(C, hrd->regionid); } } @@ -108,7 +109,7 @@ static void hud_panel_operator_redo_draw_header(const bContext *C, Panel *panel) static void hud_panel_operator_redo_draw(const bContext *C, Panel *panel) { wmOperator *op = WM_operator_last_redo(C); - if (op == NULL) { + if (op == nullptr) { return; } if (!WM_operator_check_ui_enabled(C, op->type->name)) { @@ -120,9 +121,7 @@ static void hud_panel_operator_redo_draw(const bContext *C, Panel *panel) static void hud_panels_register(ARegionType *art, int space_type, int region_type) { - PanelType *pt; - - pt = MEM_callocN(sizeof(PanelType), __func__); + PanelType *pt = MEM_cnew<PanelType>(__func__); strcpy(pt->idname, "OPERATOR_PT_redo"); strcpy(pt->label, N_("Redo")); strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); @@ -155,8 +154,8 @@ static void hud_region_free(ARegion *region) static void hud_region_layout(const bContext *C, ARegion *region) { - struct HudRegionData *hrd = region->regiondata; - if (hrd == NULL || !last_redo_poll(C, hrd->regionid)) { + HudRegionData *hrd = static_cast<HudRegionData *>(region->regiondata); + if (hrd == nullptr || !last_redo_poll(C, hrd->regionid)) { ED_region_tag_redraw(region); hud_region_hide(region); return; @@ -205,19 +204,17 @@ static void hud_region_draw(const bContext *C, ARegion *region) GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f); if ((region->flag & RGN_FLAG_HIDDEN) == 0) { - ui_draw_menu_back(NULL, - NULL, - &(rcti){ - .xmax = region->winx, - .ymax = region->winy, - }); + rcti reset_rect = {}; + reset_rect.xmax = region->winx; + reset_rect.ymax = region->winy; + ui_draw_menu_back(nullptr, nullptr, &reset_rect); ED_region_panels_draw(C, region); } } ARegionType *ED_area_type_hud(int space_type) { - ARegionType *art = MEM_callocN(sizeof(ARegionType), __func__); + ARegionType *art = MEM_cnew<ARegionType>(__func__); art->regionid = RGN_TYPE_HUD; art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D; art->layout = hud_region_layout; @@ -238,7 +235,7 @@ ARegionType *ED_area_type_hud(int space_type) static ARegion *hud_region_add(ScrArea *area) { - ARegion *region = MEM_callocN(sizeof(ARegion), "area region"); + ARegion *region = MEM_cnew<ARegion>(__func__); ARegion *region_win = BKE_area_find_region_type(area, RGN_TYPE_WINDOW); if (region_win) { BLI_insertlinkbefore(&area->regionbase, region_win, region); @@ -288,7 +285,7 @@ void ED_area_type_hud_ensure(bContext *C, ScrArea *area) ED_area_type_hud_clear(wm, area); ARegionType *art = BKE_regiontype_from_id(area->type, RGN_TYPE_HUD); - if (art == NULL) { + if (art == nullptr) { return; } @@ -301,9 +298,9 @@ void ED_area_type_hud_ensure(bContext *C, ScrArea *area) } bool init = false; - const bool was_hidden = region == NULL || region->visible == false; + const bool was_hidden = region == nullptr || region->visible == false; ARegion *region_op = CTX_wm_region(C); - BLI_assert((region_op == NULL) || (region_op->regiontype != RGN_TYPE_HUD)); + BLI_assert((region_op == nullptr) || (region_op->regiontype != RGN_TYPE_HUD)); if (!last_redo_poll(C, region_op ? region_op->regiontype : -1)) { if (region) { ED_region_tag_redraw(region); @@ -312,7 +309,7 @@ void ED_area_type_hud_ensure(bContext *C, ScrArea *area) return; } - if (region == NULL) { + if (region == nullptr) { init = true; region = hud_region_add(area); region->type = art; @@ -332,9 +329,9 @@ void ED_area_type_hud_ensure(bContext *C, ScrArea *area) } { - struct HudRegionData *hrd = region->regiondata; - if (hrd == NULL) { - hrd = MEM_callocN(sizeof(*hrd), __func__); + HudRegionData *hrd = static_cast<HudRegionData *>(region->regiondata); + if (hrd == nullptr) { + hrd = MEM_cnew<HudRegionData>(__func__); region->regiondata = hrd; } if (region_op) { @@ -355,10 +352,10 @@ void ED_area_type_hud_ensure(bContext *C, ScrArea *area) ED_region_tag_redraw(region); /* Reset zoom level (not well supported). */ - region->v2d.cur = region->v2d.tot = (rctf){ - .xmax = region->winx, - .ymax = region->winy, - }; + rctf reset_rect = {}; + reset_rect.xmax = region->winx; + reset_rect.ymax = region->winy; + region->v2d.cur = region->v2d.tot = reset_rect; region->v2d.minzoom = 1.0f; region->v2d.maxzoom = 1.0f; @@ -373,10 +370,7 @@ void ED_area_type_hud_ensure(bContext *C, ScrArea *area) if (was_hidden) { region->winx = region->v2d.winx; region->winy = region->v2d.winy; - region->v2d.cur = region->v2d.tot = (rctf){ - .xmax = region->winx, - .ymax = region->winy, - }; + region->v2d.cur = region->v2d.tot = reset_rect; } CTX_wm_region_set((bContext *)C, region_prev); } diff --git a/source/blender/editors/interface/interface_region_menu_pie.c b/source/blender/editors/interface/interface_region_menu_pie.cc index 74e128f3098..586aeef44fd 100644 --- a/source/blender/editors/interface/interface_region_menu_pie.c +++ b/source/blender/editors/interface/interface_region_menu_pie.cc @@ -7,9 +7,9 @@ * Pie Menu Region */ -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> +#include <cstdarg> +#include <cstdlib> +#include <cstring> #include "MEM_guardedalloc.h" @@ -51,7 +51,7 @@ struct uiPieMenu { static uiBlock *ui_block_func_PIE(bContext *UNUSED(C), uiPopupBlockHandle *handle, void *arg_pie) { uiBlock *block; - uiPieMenu *pie = arg_pie; + uiPieMenu *pie = static_cast<uiPieMenu *>(arg_pie); int minwidth, width, height; minwidth = UI_MENU_WIDTH_MIN; @@ -89,14 +89,13 @@ static float ui_pie_menu_title_width(const char *name, int icon) uiPieMenu *UI_pie_menu_begin(struct bContext *C, const char *title, int icon, const wmEvent *event) { const uiStyle *style = UI_style_get_dpi(); - uiPieMenu *pie; short event_type; wmWindow *win = CTX_wm_window(C); - pie = MEM_callocN(sizeof(*pie), "pie menu"); + uiPieMenu *pie = MEM_cnew<uiPieMenu>(__func__); - pie->block_radial = UI_block_begin(C, NULL, __func__, UI_EMBOSS); + pie->block_radial = UI_block_begin(C, nullptr, __func__, UI_EMBOSS); /* may be useful later to allow spawning pies * from old positions */ /* pie->block_radial->flag |= UI_BLOCK_POPUP_MEMORY; */ @@ -153,7 +152,7 @@ uiPieMenu *UI_pie_menu_begin(struct bContext *C, const char *title, int icon, co 0, w, UI_UNIT_Y, - NULL, + nullptr, 0.0, 0.0, 0, @@ -170,7 +169,7 @@ uiPieMenu *UI_pie_menu_begin(struct bContext *C, const char *title, int icon, co 0, w, UI_UNIT_Y, - NULL, + nullptr, 0.0, 0.0, 0, @@ -191,7 +190,7 @@ void UI_pie_menu_end(bContext *C, uiPieMenu *pie) wmWindow *window = CTX_wm_window(C); uiPopupBlockHandle *menu; - menu = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_PIE, pie, NULL); + menu = ui_popup_block_create(C, nullptr, nullptr, nullptr, ui_block_func_PIE, pie, nullptr); menu->popup = true; menu->towardstime = PIL_check_seconds_timer(); @@ -212,7 +211,7 @@ int UI_pie_menu_invoke(struct bContext *C, const char *idname, const wmEvent *ev uiLayout *layout; MenuType *mt = WM_menutype_find(idname, true); - if (mt == NULL) { + if (mt == nullptr) { printf("%s: named menu \"%s\" not found\n", __func__, idname); return OPERATOR_CANCELLED; } @@ -263,7 +262,7 @@ int UI_pie_menu_invoke_from_rna_enum(struct bContext *C, uiPieMenu *pie; uiLayout *layout; - RNA_pointer_create(NULL, &RNA_Context, C, &ctx_ptr); + RNA_pointer_create(nullptr, &RNA_Context, C, &ctx_ptr); if (!RNA_path_resolve(&ctx_ptr, path, &r_ptr, &r_prop)) { return OPERATOR_CANCELLED; @@ -280,7 +279,7 @@ int UI_pie_menu_invoke_from_rna_enum(struct bContext *C, layout = UI_pie_menu_layout(pie); layout = uiLayoutRadial(layout); - uiItemFullR(layout, &r_ptr, r_prop, RNA_NO_INDEX, 0, UI_ITEM_R_EXPAND, NULL, 0); + uiItemFullR(layout, &r_ptr, r_prop, RNA_NO_INDEX, 0, UI_ITEM_R_EXPAND, nullptr, 0); UI_pie_menu_end(C, pie); @@ -304,7 +303,7 @@ int UI_pie_menu_invoke_from_rna_enum(struct bContext *C, * - Julian (Feb 2016) * \{ */ -typedef struct PieMenuLevelData { + struct PieMenuLevelData { char title[UI_MAX_NAME_STR]; /* parent pie title, copied for level */ int icon; /* parent pie icon, copied for level */ int totitem; /* total count of *remaining* items */ @@ -314,7 +313,7 @@ typedef struct PieMenuLevelData { const char *propname; IDProperty *properties; wmOperatorCallContext context, flag; -} PieMenuLevelData; +} ; /** * Invokes a new pie menu for a new level. @@ -362,17 +361,17 @@ void ui_pie_menu_level_create(uiBlock *block, const EnumPropertyItem *items, int totitem, wmOperatorCallContext context, - int flag) + wmOperatorCallContext flag) { const int totitem_parent = PIE_MAX_ITEMS - 1; const int totitem_remain = totitem - totitem_parent; const size_t array_size = sizeof(EnumPropertyItem) * totitem_remain; /* used as but->func_argN so freeing is handled elsewhere */ - EnumPropertyItem *remaining = MEM_mallocN(array_size + sizeof(EnumPropertyItem), - "pie_level_item_array"); + EnumPropertyItem *remaining = static_cast<EnumPropertyItem *>( + MEM_mallocN(array_size + sizeof(EnumPropertyItem), "pie_level_item_array")); memcpy(remaining, items + totitem_parent, array_size); - /* A NULL terminating sentinel element is required. */ + /* A nullptr terminating sentinel element is required. */ memset(&remaining[totitem_remain], 0, sizeof(EnumPropertyItem)); /* yuk, static... issue is we can't reliably free this without doing dangerous changes */ @@ -395,7 +394,7 @@ void ui_pie_menu_level_create(uiBlock *block, 0, UI_UNIT_X * 3, UI_UNIT_Y, - NULL, + nullptr, 0.0f, 0.0f, 0.0f, diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.cc index 7d8f4315710..e843a275d08 100644 --- a/source/blender/editors/interface/interface_region_menu_popup.c +++ b/source/blender/editors/interface/interface_region_menu_popup.cc @@ -7,9 +7,9 @@ * PopUp Menu Region */ -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> +#include <cstdarg> +#include <cstdlib> +#include <cstring> #include "MEM_guardedalloc.h" @@ -50,7 +50,7 @@ bool ui_but_menu_step_poll(const uiBut *but) BLI_assert(but->type == UI_BTYPE_MENU); /* currently only RNA buttons */ - return ((but->menu_step_func != NULL) || + return ((but->menu_step_func != nullptr) || (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM)); } @@ -58,12 +58,16 @@ int ui_but_menu_step(uiBut *but, int direction) { if (ui_but_menu_step_poll(but)) { if (but->menu_step_func) { - return but->menu_step_func(but->block->evil_C, direction, but->poin); + return but->menu_step_func( + static_cast<bContext *>(but->block->evil_C), direction, but->poin); } const int curval = RNA_property_enum_get(&but->rnapoin, but->rnaprop); - return RNA_property_enum_step( - but->block->evil_C, &but->rnapoin, but->rnaprop, curval, direction); + return RNA_property_enum_step(static_cast<bContext *>(but->block->evil_C), + &but->rnapoin, + but->rnaprop, + curval, + direction); } printf("%s: cannot cycle button '%s'\n", __func__, but->str); @@ -85,7 +89,7 @@ static uint ui_popup_string_hash(const char *str, const bool use_sep) { /* sometimes button contains hotkey, sometimes not, strip for proper compare */ int hash; - const char *delimit = use_sep ? strrchr(str, UI_SEP_CHAR) : NULL; + const char *delimit = use_sep ? strrchr(str, UI_SEP_CHAR) : nullptr; if (delimit) { hash = BLI_ghashutil_strhash_n(str, delimit - str); @@ -102,7 +106,7 @@ uint ui_popup_menu_hash(const char *str) return BLI_ghashutil_strhash(str); } -/* but == NULL read, otherwise set */ +/* but == nullptr read, otherwise set */ static uiBut *ui_popup_menu_memory__internal(uiBlock *block, uiBut *but) { static uint mem[256]; @@ -114,13 +118,13 @@ static uiBut *ui_popup_menu_memory__internal(uiBlock *block, uiBut *but) if (first) { /* init */ memset(mem, -1, sizeof(mem)); - first = 0; + first = false; } if (but) { /* set */ mem[hash_mod] = ui_popup_string_hash(but->str, but->flag & UI_BUT_HAS_SEP_CHAR); - return NULL; + return nullptr; } /* get */ @@ -131,12 +135,12 @@ static uiBut *ui_popup_menu_memory__internal(uiBlock *block, uiBut *but) } } - return NULL; + return nullptr; } uiBut *ui_popup_menu_memory_get(uiBlock *block) { - return ui_popup_menu_memory__internal(block, NULL); + return ui_popup_menu_memory__internal(block, nullptr); } void ui_popup_menu_memory_set(uiBlock *block, uiBut *but) @@ -166,7 +170,7 @@ struct uiPopupMenu { static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, void *arg_pup) { uiBlock *block; - uiPopupMenu *pup = arg_pup; + uiPopupMenu *pup = static_cast<uiPopupMenu *>(arg_pup); int minwidth, width, height; char direction; bool flip; @@ -174,7 +178,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi if (pup->menu_func) { pup->block->handle = handle; pup->menu_func(C, pup->layout, pup->menu_arg); - pup->block->handle = NULL; + pup->block->handle = nullptr; } /* Find block minimum width. */ @@ -229,7 +233,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi if (pup->popup) { int offset[2]; - uiBut *but_activate = NULL; + uiBut *but_activate = nullptr; UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_NUMSELECT); UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); UI_block_direction_set(block, direction); @@ -309,10 +313,9 @@ uiPopupBlockHandle *ui_popup_menu_create( wmWindow *window = CTX_wm_window(C); const uiStyle *style = UI_style_get_dpi(); uiPopupBlockHandle *handle; - uiPopupMenu *pup; - pup = MEM_callocN(sizeof(uiPopupMenu), __func__); - pup->block = UI_block_begin(C, NULL, __func__, UI_EMBOSS_PULLDOWN); + uiPopupMenu *pup = MEM_cnew<uiPopupMenu>(__func__); + pup->block = UI_block_begin(C, nullptr, __func__, UI_EMBOSS_PULLDOWN); pup->block->flag |= UI_BLOCK_NUMSELECT; /* default menus to numselect */ pup->layout = UI_block_layout( pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); @@ -348,7 +351,7 @@ uiPopupBlockHandle *ui_popup_menu_create( pup->menu_func = menu_func; pup->menu_arg = arg; - handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup, NULL); + handle = ui_popup_block_create(C, butregion, but, nullptr, ui_block_func_POPUP, pup, nullptr); if (!but) { handle->popup = true; @@ -374,10 +377,10 @@ uiPopupMenu *UI_popup_menu_begin_ex(bContext *C, int icon) { const uiStyle *style = UI_style_get_dpi(); - uiPopupMenu *pup = MEM_callocN(sizeof(uiPopupMenu), "popup menu"); + uiPopupMenu *pup = MEM_cnew<uiPopupMenu>(__func__); uiBut *but; - pup->block = UI_block_begin(C, NULL, block_name, UI_EMBOSS_PULLDOWN); + pup->block = UI_block_begin(C, nullptr, block_name, UI_EMBOSS_PULLDOWN); pup->block->flag |= UI_BLOCK_POPUP_MEMORY | UI_BLOCK_IS_FLIP; pup->block->puphash = ui_popup_menu_hash(title); pup->layout = UI_block_layout( @@ -389,7 +392,7 @@ uiPopupMenu *UI_popup_menu_begin_ex(bContext *C, uiLayoutSetOperatorContext(pup->layout, WM_OP_EXEC_REGION_WIN); /* create in advance so we can let buttons point to retval already */ - pup->block->handle = MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle"); + pup->block->handle = MEM_cnew<uiPopupBlockHandle>(__func__); /* create title button */ if (title[0]) { @@ -406,7 +409,7 @@ uiPopupMenu *UI_popup_menu_begin_ex(bContext *C, 0, 200, UI_UNIT_Y, - NULL, + nullptr, 0.0, 0.0, 0, @@ -415,7 +418,7 @@ uiPopupMenu *UI_popup_menu_begin_ex(bContext *C, } else { but = uiDefBut( - pup->block, UI_BTYPE_LABEL, 0, title, 0, 0, 200, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); + pup->block, UI_BTYPE_LABEL, 0, title, 0, 0, 200, UI_UNIT_Y, nullptr, 0.0, 0.0, 0, 0, ""); but->drawflag = UI_BUT_TEXT_LEFT; } @@ -440,8 +443,8 @@ void UI_popup_menu_end(bContext *C, uiPopupMenu *pup) { wmWindow *window = CTX_wm_window(C); uiPopupBlockHandle *menu; - uiBut *but = NULL; - ARegion *butregion = NULL; + uiBut *but = nullptr; + ARegion *butregion = nullptr; pup->popup = true; pup->mx = window->eventstate->xy[0]; @@ -452,7 +455,7 @@ void UI_popup_menu_end(bContext *C, uiPopupMenu *pup) butregion = pup->butregion; } - menu = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup, NULL); + menu = ui_popup_block_create(C, butregion, but, nullptr, ui_block_func_POPUP, pup, nullptr); menu->popup = true; UI_popup_handlers_add(C, &window->modalhandlers, menu, 0); @@ -467,7 +470,7 @@ bool UI_popup_menu_end_or_cancel(bContext *C, uiPopupMenu *pup) UI_popup_menu_end(C, pup); return true; } - UI_block_layout_resolve(pup->block, NULL, NULL); + UI_block_layout_resolve(pup->block, nullptr, nullptr); MEM_freeN(pup->block->handle); UI_block_free(C, pup->block); MEM_freeN(pup); @@ -487,7 +490,7 @@ uiLayout *UI_popup_menu_layout(uiPopupMenu *pup) void UI_popup_menu_reports(bContext *C, ReportList *reports) { - uiPopupMenu *pup = NULL; + uiPopupMenu *pup = nullptr; uiLayout *layout; if (!CTX_wm_window(C)) { @@ -502,7 +505,7 @@ void UI_popup_menu_reports(bContext *C, ReportList *reports) continue; } - if (pup == NULL) { + if (pup == nullptr) { char title[UI_MAX_DRAW_STR]; BLI_snprintf(title, sizeof(title), "%s: %s", IFACE_("Report"), report->typestr); /* popup_menu stuff does just what we need (but pass meaningful block name) */ @@ -540,7 +543,7 @@ int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports) uiLayout *layout; MenuType *mt = WM_menutype_find(idname, true); - if (mt == NULL) { + if (mt == nullptr) { BKE_reportf(reports, RPT_ERROR, "Menu \"%s\" not found", idname); return OPERATOR_CANCELLED; } @@ -572,7 +575,7 @@ void UI_popup_block_invoke_ex( wmWindow *window = CTX_wm_window(C); uiPopupBlockHandle *handle; - handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg, arg_free); + handle = ui_popup_block_create(C, nullptr, nullptr, func, nullptr, arg, arg_free); handle->popup = true; /* It can be useful to disable refresh (even though it will work) @@ -580,7 +583,8 @@ void UI_popup_block_invoke_ex( handle->can_refresh = can_refresh; UI_popup_handlers_add(C, &window->modalhandlers, handle, 0); - UI_block_active_only_flagged_buttons(C, handle->region, handle->region->uiblocks.first); + UI_block_active_only_flagged_buttons( + C, handle->region, static_cast<uiBlock *>(handle->region->uiblocks.first)); WM_event_add_mousemove(window); } @@ -599,7 +603,7 @@ void UI_popup_block_ex(bContext *C, wmWindow *window = CTX_wm_window(C); uiPopupBlockHandle *handle; - handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg, NULL); + handle = ui_popup_block_create(C, nullptr, nullptr, func, nullptr, arg, nullptr); handle->popup = true; handle->retvalue = 1; handle->can_refresh = true; @@ -611,7 +615,8 @@ void UI_popup_block_ex(bContext *C, // handle->opcontext = opcontext; UI_popup_handlers_add(C, &window->modalhandlers, handle, 0); - UI_block_active_only_flagged_buttons(C, handle->region, handle->region->uiblocks.first); + UI_block_active_only_flagged_buttons( + C, handle->region, static_cast<uiBlock *>(handle->region->uiblocks.first)); WM_event_add_mousemove(window); } @@ -621,7 +626,7 @@ void uiPupBlockOperator(bContext *C, uiBlockCreateFunc func, wmOperator *op, wmO wmWindow *window = CTX_wm_window(C); uiPopupBlockHandle *handle; - handle = ui_popup_block_create(C, NULL, NULL, func, NULL, op, NULL); + handle = ui_popup_block_create(C, nullptr, nullptr, func, nullptr, op, nullptr); handle->popup = 1; handle->retvalue = 1; handle->can_refresh = true; @@ -638,7 +643,7 @@ void uiPupBlockOperator(bContext *C, uiBlockCreateFunc func, wmOperator *op, wmO void UI_popup_block_close(bContext *C, wmWindow *win, uiBlock *block) { - /* if loading new .blend while popup is open, window will be NULL */ + /* if loading new .blend while popup is open, window will be nullptr */ if (block->handle) { if (win) { const bScreen *screen = WM_window_get_active_screen(win); diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.cc index 7c7c9e887dd..2e10261a4f7 100644 --- a/source/blender/editors/interface/interface_region_popover.c +++ b/source/blender/editors/interface/interface_region_popover.cc @@ -80,7 +80,7 @@ static void ui_popover_create_block(bContext *C, uiPopover *pup, wmOperatorCallC const uiStyle *style = UI_style_get_dpi(); - pup->block = UI_block_begin(C, NULL, __func__, UI_EMBOSS); + pup->block = UI_block_begin(C, nullptr, __func__, UI_EMBOSS); UI_block_flag_enable(pup->block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_POPOVER); #ifdef USE_UI_POPOVER_ONCE if (pup->is_once) { @@ -104,7 +104,7 @@ static void ui_popover_create_block(bContext *C, uiPopover *pup, wmOperatorCallC static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, void *arg_pup) { - uiPopover *pup = arg_pup; + uiPopover *pup = static_cast<uiPopover *>(arg_pup); /* Create UI block and layout now if it wasn't done between begin/end. */ if (!pup->layout) { @@ -113,10 +113,10 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v if (pup->menu_func) { pup->block->handle = handle; pup->menu_func(C, pup->layout, pup->menu_arg); - pup->block->handle = NULL; + pup->block->handle = nullptr; } - pup->layout = NULL; + pup->layout = nullptr; } /* Setup and resolve UI layout for block. */ @@ -185,10 +185,10 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v block->minbounds = UI_MENU_WIDTH_MIN; if (!handle->refresh) { - uiBut *but = NULL; - uiBut *but_first = NULL; + uiBut *but = nullptr; + uiBut *but_first = nullptr; LISTBASE_FOREACH (uiBut *, but_iter, &block->buttons) { - if ((but_first == NULL) && ui_but_is_editable(but_iter)) { + if ((but_first == nullptr) && ui_but_is_editable(but_iter)) { but_first = but_iter; } if (but_iter->flag & (UI_SELECT | UI_SELECT_DRAW)) { @@ -219,8 +219,8 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v static void ui_block_free_func_POPOVER(void *arg_pup) { - uiPopover *pup = arg_pup; - if (pup->keymap != NULL) { + uiPopover *pup = static_cast<uiPopover *>(arg_pup); + if (pup->keymap != nullptr) { wmWindow *window = pup->window; WM_event_remove_keymap_handler(&window->modalhandlers, pup->keymap); } @@ -235,7 +235,7 @@ uiPopupBlockHandle *ui_popover_panel_create( const PanelType *panel_type = (PanelType *)arg; /* Create popover, buttons are created from callback. */ - uiPopover *pup = MEM_callocN(sizeof(uiPopover), __func__); + uiPopover *pup = MEM_cnew<uiPopover>(__func__); pup->but = but; /* FIXME: maybe one day we want non panel popovers? */ @@ -262,7 +262,7 @@ uiPopupBlockHandle *ui_popover_panel_create( /* Create popup block. */ uiPopupBlockHandle *handle; handle = ui_popup_block_create( - C, butregion, but, NULL, ui_block_func_POPOVER, pup, ui_block_free_func_POPOVER); + C, butregion, but, nullptr, ui_block_func_POPOVER, pup, ui_block_free_func_POPOVER); handle->can_refresh = true; /* Add handlers. If attached to a button, the button will already @@ -286,7 +286,7 @@ int UI_popover_panel_invoke(bContext *C, const char *idname, bool keep_open, Rep { uiLayout *layout; PanelType *pt = WM_paneltype_find(idname, true); - if (pt == NULL) { + if (pt == nullptr) { BKE_reportf(reports, RPT_ERROR, "Panel \"%s\" not found", idname); return OPERATOR_CANCELLED; } @@ -296,23 +296,23 @@ int UI_popover_panel_invoke(bContext *C, const char *idname, bool keep_open, Rep return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH); } - uiBlock *block = NULL; + uiBlock *block = nullptr; if (keep_open) { uiPopupBlockHandle *handle = ui_popover_panel_create( - C, NULL, NULL, ui_item_paneltype_func, pt); - uiPopover *pup = handle->popup_create_vars.arg; + C, nullptr, nullptr, ui_item_paneltype_func, pt); + uiPopover *pup = static_cast<uiPopover *>(handle->popup_create_vars.arg); block = pup->block; } else { uiPopover *pup = UI_popover_begin(C, U.widget_unit * pt->ui_units_x, false); layout = UI_popover_layout(pup); UI_paneltype_draw(C, pt, layout); - UI_popover_end(C, pup, NULL); + UI_popover_end(C, pup, nullptr); block = pup->block; } if (block) { - uiPopupBlockHandle *handle = block->handle; + uiPopupBlockHandle *handle = static_cast<uiPopupBlockHandle *>(block->handle); UI_block_active_only_flagged_buttons(C, handle->region, block); } return OPERATOR_INTERFACE; @@ -326,20 +326,20 @@ int UI_popover_panel_invoke(bContext *C, const char *idname, bool keep_open, Rep uiPopover *UI_popover_begin(bContext *C, int ui_menu_width, bool from_active_button) { - uiPopover *pup = MEM_callocN(sizeof(uiPopover), "popover menu"); + uiPopover *pup = MEM_cnew<uiPopover>(__func__); if (ui_menu_width == 0) { ui_menu_width = U.widget_unit * UI_POPOVER_WIDTH_UNITS; } pup->ui_size_x = ui_menu_width; - ARegion *butregion = NULL; - uiBut *but = NULL; + ARegion *butregion = nullptr; + uiBut *but = nullptr; if (from_active_button) { butregion = CTX_wm_region(C); but = UI_region_active_but_get(butregion); - if (but == NULL) { - butregion = NULL; + if (but == nullptr) { + butregion = nullptr; } } @@ -350,14 +350,14 @@ uiPopover *UI_popover_begin(bContext *C, int ui_menu_width, bool from_active_but ui_popover_create_block(C, pup, WM_OP_EXEC_REGION_WIN); /* create in advance so we can let buttons point to retval already */ - pup->block->handle = MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle"); + pup->block->handle = MEM_cnew<uiPopupBlockHandle>(__func__); return pup; } static void popover_keymap_fn(wmKeyMap *UNUSED(keymap), wmKeyMapItem *UNUSED(kmi), void *user_data) { - uiPopover *pup = user_data; + uiPopover *pup = static_cast<uiPopover *>(user_data); pup->block->handle->menuretval = UI_RETURN_OK; } @@ -376,8 +376,13 @@ void UI_popover_end(bContext *C, uiPopover *pup, wmKeyMap *keymap) WM_event_set_keymap_handler_post_callback(pup->keymap_handler, popover_keymap_fn, pup); } - handle = ui_popup_block_create( - C, pup->butregion, pup->but, NULL, ui_block_func_POPOVER, pup, ui_block_free_func_POPOVER); + handle = ui_popup_block_create(C, + pup->butregion, + pup->but, + nullptr, + ui_block_func_POPOVER, + pup, + ui_block_free_func_POPOVER); /* Add handlers. */ UI_popup_handlers_add(C, &window->modalhandlers, handle, 0); diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.cc index 2f2556225b5..74c228e3338 100644 --- a/source/blender/editors/interface/interface_region_popup.c +++ b/source/blender/editors/interface/interface_region_popup.cc @@ -7,9 +7,9 @@ * PopUp Region (Generic) */ -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> +#include <cstdarg> +#include <cstdlib> +#include <cstring> #include "MEM_guardedalloc.h" @@ -120,7 +120,7 @@ static void ui_popup_block_position(wmWindow *window, short dir1 = 0, dir2 = 0; if (!handle->refresh) { - bool left = 0, right = 0, top = 0, down = 0; + bool left = false, right = false, top = false, down = false; const int win_x = WM_window_pixels_x(window); const int win_y = WM_window_pixels_y(window); @@ -131,24 +131,24 @@ static void ui_popup_block_position(wmWindow *window, /* check if there's space at all */ if (butrct.xmin - max_size_x + center_x > 0.0f) { - left = 1; + left = true; } if (butrct.xmax + max_size_x - center_x < win_x) { - right = 1; + right = true; } if (butrct.ymin - max_size_y + center_y > 0.0f) { - down = 1; + down = true; } if (butrct.ymax + max_size_y - center_y < win_y) { - top = 1; + top = true; } if (top == 0 && down == 0) { if (butrct.ymin - max_size_y < win_y - butrct.ymax - max_size_y) { - top = 1; + top = true; } else { - down = 1; + down = true; } } @@ -335,7 +335,7 @@ static void ui_popup_block_position(wmWindow *window, } /* Keep a list of these, needed for pull-down menus. */ - uiSafetyRct *saferct = MEM_callocN(sizeof(uiSafetyRct), "uiSafetyRct"); + uiSafetyRct *saferct = MEM_cnew<uiSafetyRct>(__func__); saferct->parent = butrct; saferct->safety = block->safety; BLI_freelistN(&block->saferct); @@ -520,7 +520,7 @@ static void ui_popup_block_remove(bContext *C, uiPopupBlockHandle *handle) CTX_wm_window_set(C, win); ui_region_temp_remove(C, screen, handle->region); - /* Reset context (area and region were NULL'ed when changing context window). */ + /* Reset context (area and region were nullptr'ed when changing context window). */ CTX_wm_window_set(C, ctx_win); CTX_wm_area_set(C, ctx_area); CTX_wm_region_set(C, ctx_region); @@ -548,10 +548,10 @@ uiBlock *ui_popup_block_refresh(bContext *C, const uiBlockHandleCreateFunc handle_create_func = handle->popup_create_vars.handle_create_func; void *arg = handle->popup_create_vars.arg; - uiBlock *block_old = region->uiblocks.first; + uiBlock *block_old = static_cast<uiBlock *>(region->uiblocks.first); uiBlock *block; - handle->refresh = (block_old != NULL); + handle->refresh = (block_old != nullptr); BLI_assert(!handle->refresh || handle->can_refresh); @@ -573,7 +573,7 @@ uiBlock *ui_popup_block_refresh(bContext *C, /* ensure we don't use mouse coords here! */ #ifdef DEBUG - window->eventstate = NULL; + window->eventstate = nullptr; #endif if (block->handle) { @@ -588,7 +588,7 @@ uiBlock *ui_popup_block_refresh(bContext *C, region->regiondata = handle; /* set UI_BLOCK_NUMSELECT before UI_block_end() so we get alphanumeric keys assigned */ - if (but == NULL) { + if (but == nullptr) { block->flag |= UI_BLOCK_POPUP; } @@ -596,7 +596,7 @@ uiBlock *ui_popup_block_refresh(bContext *C, UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); /* defer this until blocks are translated (below) */ - block->oldblock = NULL; + block->oldblock = nullptr; if (!block->endblock) { UI_block_end_ex( @@ -610,9 +610,8 @@ uiBlock *ui_popup_block_refresh(bContext *C, handle->direction = block->direction; } else { - uiSafetyRct *saferct; /* Keep a list of these, needed for pull-down menus. */ - saferct = MEM_callocN(sizeof(uiSafetyRct), "uiSafetyRct"); + uiSafetyRct *saferct = MEM_cnew<uiSafetyRct>(__func__); saferct->safety = block->safety; BLI_addhead(&block->saferct, saferct); } @@ -760,7 +759,6 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, static ARegionType type; ARegion *region; uiBlock *block; - uiPopupBlockHandle *handle; /* disable tooltips from buttons below */ if (activebut) { @@ -770,7 +768,7 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, WM_cursor_set(window, WM_CURSOR_DEFAULT); /* create handle */ - handle = MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle"); + uiPopupBlockHandle *handle = MEM_cnew<uiPopupBlockHandle>(__func__); /* store context for operator */ handle->ctx_area = CTX_wm_area(C); @@ -782,7 +780,7 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, handle->popup_create_vars.arg = arg; handle->popup_create_vars.arg_free = arg_free; handle->popup_create_vars.but = but; - handle->popup_create_vars.butregion = but ? butregion : NULL; + handle->popup_create_vars.butregion = but ? butregion : nullptr; copy_v2_v2_int(handle->popup_create_vars.event_xy, window->eventstate->xy); /* don't allow by default, only if popup type explicitly supports it */ @@ -816,7 +814,7 @@ void ui_popup_block_free(bContext *C, uiPopupBlockHandle *handle) /* If this popup is created from a popover which does NOT have keep-open flag set, * then close the popover too. We could extend this to other popup types too. */ ARegion *region = handle->popup_create_vars.butregion; - if (region != NULL) { + if (region != nullptr) { LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { if (block->handle && (block->flag & UI_BLOCK_POPOVER) && (block->flag & UI_BLOCK_KEEP_OPEN) == 0) { diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.cc index ea6d293e52f..1a2c1f7919c 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.cc @@ -25,7 +25,7 @@ ARegion *ui_region_temp_add(bScreen *screen) { - ARegion *region = MEM_callocN(sizeof(ARegion), __func__); + ARegion *region = MEM_cnew<ARegion>(__func__); BLI_addtail(&screen->regionbase, region); region->regiontype = RGN_TYPE_TEMPORARY; @@ -45,6 +45,6 @@ void ui_region_temp_remove(bContext *C, bScreen *screen, ARegion *region) } ED_region_exit(C, region); - BKE_area_region_free(NULL, region); /* NULL: no spacetype */ + BKE_area_region_free(nullptr, region); /* nullptr: no spacetype */ BLI_freelinkN(&screen->regionbase, region); } diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.cc index 76023f3033f..b4e97f8a396 100644 --- a/source/blender/editors/interface/interface_style.c +++ b/source/blender/editors/interface/interface_style.cc @@ -5,11 +5,11 @@ * \ingroup edinterface */ -#include <limits.h> -#include <math.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> +#include <climits> +#include <cmath> +#include <cstdio> +#include <cstdlib> +#include <cstring> #include "MEM_guardedalloc.h" @@ -57,7 +57,7 @@ static uiStyle *ui_style_new(ListBase *styles, const char *name, short uifont_id) { - uiStyle *style = MEM_callocN(sizeof(uiStyle), "new style"); + uiStyle *style = MEM_cnew<uiStyle>(__func__); BLI_addtail(styles, style); BLI_strncpy(style->name, name, MAX_STYLE_NAME); @@ -108,14 +108,14 @@ static uiStyle *ui_style_new(ListBase *styles, const char *name, short uifont_id static uiFont *uifont_to_blfont(int id) { - uiFont *font = U.uifonts.first; + uiFont *font = static_cast<uiFont *>(U.uifonts.first); for (; font; font = font->next) { if (font->uifont_id == id) { return font; } } - return U.uifonts.first; + return static_cast<uiFont *>(U.uifonts.first); } /* *************** draw ************************ */ @@ -198,7 +198,7 @@ void UI_fontstyle_draw(const uiFontStyle *fs, const uchar col[4], const struct uiFontStyleDraw_Params *fs_params) { - UI_fontstyle_draw_ex(fs, rect, str, str_len, col, fs_params, NULL, NULL, NULL); + UI_fontstyle_draw_ex(fs, rect, str, str_len, col, fs_params, nullptr, nullptr, nullptr); } void UI_fontstyle_draw_rotated(const uiFontStyle *fs, @@ -284,17 +284,13 @@ void UI_fontstyle_draw_simple_backdrop(const uiFontStyle *fs, const float decent = BLF_descender(fs->uifont_id); const float margin = height / 4.0f; + rctf rect; + rect.xmin = x - margin; + rect.xmax = x + width + margin; + rect.ymin = (y + decent) - margin; + rect.ymax = (y + decent) + height + margin; UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_4fv( - &(const rctf){ - .xmin = x - margin, - .xmax = x + width + margin, - .ymin = (y + decent) - margin, - .ymax = (y + decent) + height + margin, - }, - true, - margin, - col_bg); + UI_draw_roundbox_4fv(&rect, true, margin, col_bg); } BLF_position(fs->uifont_id, x, y, 0.0f); @@ -307,12 +303,12 @@ void UI_fontstyle_draw_simple_backdrop(const uiFontStyle *fs, const uiStyle *UI_style_get(void) { #if 0 - uiStyle *style = NULL; + uiStyle *style = nullptr; /* offset is two struct uiStyle pointers */ style = BLI_findstring(&U.uistyles, "Unifont Style", sizeof(style) * 2); - return (style != NULL) ? style : U.uistyles.first; + return (style != nullptr) ? style : U.uistyles.first; #else - return U.uistyles.first; + return static_cast<const uiStyle *>(U.uistyles.first); #endif } @@ -378,7 +374,7 @@ int UI_fontstyle_height_max(const uiFontStyle *fs) void uiStyleInit(void) { - const uiStyle *style = U.uistyles.first; + const uiStyle *style = static_cast<uiStyle *>(U.uistyles.first); /* recover from uninitialized dpi */ if (U.dpi == 0) { @@ -400,11 +396,11 @@ void uiStyleInit(void) blf_mono_font_render = -1; } - uiFont *font_first = U.uifonts.first; + uiFont *font_first = static_cast<uiFont *>(U.uifonts.first); /* default builtin */ - if (font_first == NULL) { - font_first = MEM_callocN(sizeof(uiFont), "ui font"); + if (font_first == nullptr) { + font_first = MEM_cnew<uiFont>(__func__); BLI_addtail(&U.uifonts, font_first); } @@ -439,7 +435,7 @@ void uiStyleInit(void) } } - if (style == NULL) { + if (style == nullptr) { style = ui_style_new(&U.uistyles, "Default Style", UIFONT_DEFAULT); } diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.cc index 728d42a9353..b796f07c24b 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.cc @@ -5,17 +5,16 @@ * \ingroup edinterface */ -#include <ctype.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> +#include <cctype> +#include <cstdio> +#include <cstdlib> +#include <cstring> #include "DNA_object_types.h" #include "DNA_screen_types.h" #include "ED_screen.h" -#include "BLI_alloca.h" #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_string.h" @@ -55,12 +54,12 @@ uiBut *uiDefAutoButR(uiBlock *block, int width, int height) { - uiBut *but = NULL; + uiBut *but = nullptr; switch (RNA_property_type(prop)) { case PROP_BOOLEAN: { if (RNA_property_array_check(prop) && index == -1) { - return NULL; + return nullptr; } if (icon && name && name[0] == '\0') { @@ -79,7 +78,7 @@ uiBut *uiDefAutoButR(uiBlock *block, 0, -1, -1, - NULL); + nullptr); } else if (icon) { but = uiDefIconTextButR_prop(block, @@ -98,7 +97,7 @@ uiBut *uiDefAutoButR(uiBlock *block, 0, -1, -1, - NULL); + nullptr); } else { but = uiDefButR_prop(block, @@ -116,7 +115,7 @@ uiBut *uiDefAutoButR(uiBlock *block, 0, -1, -1, - NULL); + nullptr); } break; } @@ -139,10 +138,10 @@ uiBut *uiDefAutoButR(uiBlock *block, 0, 0, 0, - NULL); + nullptr); } else { - return NULL; + return nullptr; } } else if (RNA_property_subtype(prop) == PROP_PERCENTAGE || @@ -162,11 +161,25 @@ uiBut *uiDefAutoButR(uiBlock *block, 0, -1, -1, - NULL); + nullptr); } else { - but = uiDefButR_prop( - block, UI_BTYPE_NUM, 0, name, x, y, width, height, ptr, prop, index, 0, 0, 0, 0, NULL); + but = uiDefButR_prop(block, + UI_BTYPE_NUM, + 0, + name, + x, + y, + width, + height, + ptr, + prop, + index, + 0, + 0, + 0, + 0, + nullptr); } if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) { @@ -191,14 +204,14 @@ uiBut *uiDefAutoButR(uiBlock *block, 0, -1, -1, - NULL); + nullptr); } else if (icon) { but = uiDefIconTextButR_prop(block, UI_BTYPE_MENU, 0, icon, - NULL, + nullptr, x, y, width, @@ -210,7 +223,7 @@ uiBut *uiDefAutoButR(uiBlock *block, 0, -1, -1, - NULL); + nullptr); } else { but = uiDefButR_prop(block, @@ -228,7 +241,7 @@ uiBut *uiDefAutoButR(uiBlock *block, 0, -1, -1, - NULL); + nullptr); } break; case PROP_STRING: @@ -248,7 +261,7 @@ uiBut *uiDefAutoButR(uiBlock *block, 0, -1, -1, - NULL); + nullptr); } else if (icon) { but = uiDefIconTextButR_prop(block, @@ -267,7 +280,7 @@ uiBut *uiDefAutoButR(uiBlock *block, 0, -1, -1, - NULL); + nullptr); } else { but = uiDefButR_prop(block, @@ -285,7 +298,7 @@ uiBut *uiDefAutoButR(uiBlock *block, 0, -1, -1, - NULL); + nullptr); } if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) { @@ -319,20 +332,21 @@ uiBut *uiDefAutoButR(uiBlock *block, 0, -1, -1, - NULL); - ui_but_add_search(but, ptr, prop, NULL, NULL); + nullptr); + ui_but_add_search(but, ptr, prop, nullptr, nullptr); break; } case PROP_COLLECTION: { char text[256]; BLI_snprintf( text, sizeof(text), IFACE_("%d items"), RNA_property_collection_length(ptr, prop)); - but = uiDefBut(block, UI_BTYPE_LABEL, 0, text, x, y, width, height, NULL, 0, 0, 0, 0, NULL); + but = uiDefBut( + block, UI_BTYPE_LABEL, 0, text, x, y, width, height, nullptr, 0, 0, 0, 0, nullptr); UI_but_flag_enable(but, UI_BUT_DISABLED); break; } default: - but = NULL; + but = nullptr; break; } @@ -414,7 +428,7 @@ eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout, case UI_BUT_LABEL_ALIGN_NONE: default: col = layout; - name = NULL; /* no smart label alignment, show default name with button */ + name = nullptr; /* no smart label alignment, show default name with button */ break; } @@ -440,7 +454,7 @@ eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout, /* *** RNA collection search menu *** */ -typedef struct CollItemSearch { +struct CollItemSearch { struct CollItemSearch *next, *prev; void *data; char *name; @@ -449,7 +463,7 @@ typedef struct CollItemSearch { bool is_id; int name_prefix_offset; uint has_sep_char : 1; -} CollItemSearch; +}; static bool add_collection_search_item(CollItemSearch *cis, const bool requires_exact_data_name, @@ -462,10 +476,11 @@ static bool add_collection_search_item(CollItemSearch *cis, * name prefix for showing the library status. */ int name_prefix_offset = cis->name_prefix_offset; if (!has_id_icon && cis->is_id && !requires_exact_data_name) { - cis->iconid = UI_icon_from_library(cis->data); + cis->iconid = UI_icon_from_library(static_cast<const ID *>(cis->data)); /* No need to re-allocate, string should be shorter than before (lib status prefix is * removed). */ - BKE_id_full_name_ui_prefix_get(name_buf, cis->data, false, UI_SEP_CHAR, &name_prefix_offset); + BKE_id_full_name_ui_prefix_get( + name_buf, static_cast<const ID *>(cis->data), false, UI_SEP_CHAR, &name_prefix_offset); BLI_assert(strlen(name_buf) <= MEM_allocN_len(cis->name)); strcpy(cis->name, name_buf); } @@ -478,15 +493,12 @@ static bool add_collection_search_item(CollItemSearch *cis, name_prefix_offset); } -void ui_rna_collection_search_update_fn(const struct bContext *C, - void *arg, - const char *str, - uiSearchItems *items, - const bool is_first) +void ui_rna_collection_search_update_fn( + const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first) { - uiRNACollectionSearch *data = arg; + uiRNACollectionSearch *data = static_cast<uiRNACollectionSearch *>(arg); const int flag = RNA_property_flag(data->target_prop); - ListBase *items_list = MEM_callocN(sizeof(ListBase), "items_list"); + ListBase *items_list = MEM_cnew<ListBase>("items_list"); const bool is_ptr_target = (RNA_property_type(data->target_prop) == PROP_POINTER); /* For non-pointer properties, UI code acts entirely based on the item's name. So the name has to * match the RNA name exactly. So only for pointer properties, the name can be modified to add @@ -497,7 +509,7 @@ void ui_rna_collection_search_update_fn(const struct bContext *C, char *name; bool has_id_icon = false; - StringSearch *search = skip_filter ? NULL : BLI_string_search_new(); + StringSearch *search = skip_filter ? nullptr : BLI_string_search_new(); /* build a temporary list of relevant items first */ int item_index = 0; @@ -522,18 +534,17 @@ void ui_rna_collection_search_update_fn(const struct bContext *C, const bool is_id = itemptr.type && RNA_struct_is_ID(itemptr.type); if (is_id) { - iconid = ui_id_icon_get(C, itemptr.data, false); + iconid = ui_id_icon_get(C, static_cast<ID *>(itemptr.data), false); if (!ELEM(iconid, 0, ICON_BLANK1)) { has_id_icon = true; } if (requires_exact_data_name) { - name = RNA_struct_name_get_alloc(&itemptr, name_buf, sizeof(name_buf), NULL); + name = RNA_struct_name_get_alloc(&itemptr, name_buf, sizeof(name_buf), nullptr); } else { - const ID *id = itemptr.data; - BKE_id_full_name_ui_prefix_get( - name_buf, itemptr.data, true, UI_SEP_CHAR, &name_prefix_offset); + const ID *id = static_cast<ID *>(itemptr.data); + BKE_id_full_name_ui_prefix_get(name_buf, id, true, UI_SEP_CHAR, &name_prefix_offset); BLI_STATIC_ASSERT(sizeof(name_buf) >= MAX_ID_FULL_NAME_UI, "Name string buffer should be big enough to hold full UI ID name"); name = name_buf; @@ -541,11 +552,11 @@ void ui_rna_collection_search_update_fn(const struct bContext *C, } } else { - name = RNA_struct_name_get_alloc(&itemptr, name_buf, sizeof(name_buf), NULL); + name = RNA_struct_name_get_alloc(&itemptr, name_buf, sizeof(name_buf), nullptr); } if (name) { - CollItemSearch *cis = MEM_callocN(sizeof(CollItemSearch), "CollectionItemSearch"); + CollItemSearch *cis = MEM_cnew<CollItemSearch>(__func__); cis->data = itemptr.data; cis->name = BLI_strdup(name); cis->index = item_index; @@ -597,7 +608,7 @@ void ui_rna_collection_search_update_fn(const struct bContext *C, int UI_icon_from_id(const ID *id) { - if (id == NULL) { + if (id == nullptr) { return ICON_NONE; } @@ -608,7 +619,7 @@ int UI_icon_from_id(const ID *id) if (ob->type == OB_EMPTY) { return ICON_EMPTY_DATA; } - return UI_icon_from_id(ob->data); + return UI_icon_from_id(static_cast<const ID *>(ob->data)); } /* otherwise get it through RNA, creating the pointer @@ -761,7 +772,7 @@ bool UI_but_online_manual_id(const uiBut *but, char *r_str, size_t maxlength) return false; } -bool UI_but_online_manual_id_from_active(const struct bContext *C, char *r_str, size_t maxlength) +bool UI_but_online_manual_id_from_active(const bContext *C, char *r_str, size_t maxlength) { uiBut *but = UI_context_active_but_get(C); @@ -861,7 +872,7 @@ void UI_but_ensure_in_view(const bContext *C, ARegion *region, const uiBut *but) * Modal Button Store API. * * Store for modal operators & handlers to register button pointers - * which are maintained while drawing or NULL when removed. + * which are maintained while drawing or nullptr when removed. * * This is needed since button pointers are continuously freed and re-allocated. * @@ -880,7 +891,7 @@ struct uiButStoreElem { uiButStore *UI_butstore_create(uiBlock *block) { - uiButStore *bs_handle = MEM_callocN(sizeof(uiButStore), __func__); + uiButStore *bs_handle = MEM_cnew<uiButStore>(__func__); bs_handle->block = block; BLI_addtail(&block->butstore, bs_handle); @@ -899,7 +910,7 @@ void UI_butstore_free(uiBlock *block, uiButStore *bs_handle) * Ideally we would manage moving the 'uiButStore', keeping a correct state. * All things considered this is the most straightforward fix - Campbell. */ - if (block != bs_handle->block && bs_handle->block != NULL) { + if (block != bs_handle->block && bs_handle->block != nullptr) { block = bs_handle->block; } @@ -912,7 +923,7 @@ void UI_butstore_free(uiBlock *block, uiButStore *bs_handle) bool UI_butstore_is_valid(uiButStore *bs) { - return (bs->block != NULL); + return (bs->block != nullptr); } bool UI_butstore_is_registered(uiBlock *block, uiBut *but) @@ -930,7 +941,7 @@ bool UI_butstore_is_registered(uiBlock *block, uiBut *but) void UI_butstore_register(uiButStore *bs_handle, uiBut **but_p) { - uiButStoreElem *bs_elem = MEM_callocN(sizeof(uiButStoreElem), __func__); + uiButStoreElem *bs_elem = MEM_cnew<uiButStoreElem>(__func__); BLI_assert(*but_p); bs_elem->but_p = but_p; @@ -968,9 +979,9 @@ bool UI_butstore_register_update(uiBlock *block, uiBut *but_dst, const uiBut *bu void UI_butstore_clear(uiBlock *block) { LISTBASE_FOREACH (uiButStore *, bs_handle, &block->butstore) { - bs_handle->block = NULL; + bs_handle->block = nullptr; LISTBASE_FOREACH (uiButStoreElem *, bs_elem, &bs_handle->items) { - *bs_elem->but_p = NULL; + *bs_elem->but_p = nullptr; } } } @@ -984,14 +995,14 @@ void UI_butstore_update(uiBlock *block) } } - if (LIKELY(block->butstore.first == NULL)) { + if (LIKELY(block->butstore.first == nullptr)) { return; } /* warning, loop-in-loop, in practice we only store <10 buttons at a time, * so this isn't going to be a problem, if that changes old-new mapping can be cached first */ LISTBASE_FOREACH (uiButStore *, bs_handle, &block->butstore) { - BLI_assert(ELEM(bs_handle->block, NULL, block) || + BLI_assert(ELEM(bs_handle->block, nullptr, block) || (block->oldblock && block->oldblock == bs_handle->block)); if (bs_handle->block == block->oldblock) { @@ -1001,7 +1012,7 @@ void UI_butstore_update(uiBlock *block) if (*bs_elem->but_p) { uiBut *but_new = ui_but_find_new(block, *bs_elem->but_p); - /* can be NULL if the buttons removed, + /* can be nullptr if the buttons removed, * NOTE: we could allow passing in a callback when buttons are removed * so the caller can cleanup */ *bs_elem->but_p = but_new; diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index b33cab3cbc6..a16c24f63cd 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1178,7 +1178,7 @@ static bool draw_widgetbase_batch_skip_draw_cache(void) { /* MacOS is known to have issues on Mac Mini and MacBook Pro with Intel Iris GPU. * For example, T78307. */ - if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_MAC, GPU_DRIVER_ANY)) { + if (GPU_type_matches_ex(GPU_DEVICE_INTEL, GPU_OS_MAC, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) { return true; } @@ -3745,8 +3745,8 @@ static void widget_numslider( widget_init(&wtb1); /* Backdrop first. */ - const float ofs = widget_radius_from_zoom(zoom, wcol); - round_box_edges(&wtb, roundboxalign, rect, ofs); + const float rad = widget_radius_from_zoom(zoom, wcol); + round_box_edges(&wtb, roundboxalign, rect, rad); wtb.draw_outline = false; widgetbase_draw(&wtb, wcol); @@ -3801,24 +3801,27 @@ static void widget_numslider( const float width = (float)BLI_rcti_size_x(rect); factor_ui = factor * width; + /* The rectangle width needs to be at least twice the corner radius for the round corners + * to be drawn properly. */ + const float min_width = 2.0f * rad; - if (factor_ui <= ofs) { - /* Left part only. */ - roundboxalign_slider &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT); - rect1.xmax = rect1.xmin + ofs; - factor_discard = factor_ui / ofs; + if (factor_ui > width - rad) { + /* Left part + middle part + right part. */ + factor_discard = factor; } - else if (factor_ui <= width - ofs) { + else if (factor_ui > min_width) { /* Left part + middle part. */ roundboxalign_slider &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT); rect1.xmax = rect1.xmin + factor_ui; } else { - /* Left part + middle part + right part. */ - factor_discard = factor; + /* Left part */ + roundboxalign_slider &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT); + rect1.xmax = rect1.xmin + min_width; + factor_discard = factor_ui / min_width; } - round_box_edges(&wtb1, roundboxalign_slider, &rect1, ofs); + round_box_edges(&wtb1, roundboxalign_slider, &rect1, rad); wtb1.draw_outline = false; widgetbase_set_uniform_discard_factor(&wtb1, factor_discard); widgetbase_draw(&wtb1, wcol); diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index 8962e1462b6..bf3c8362ce6 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -1268,59 +1268,67 @@ static void grid_axis_start_and_count( } } -typedef struct DotGridLevelInfo { - /* The factor applied to the #min_step argument. This could be easily computed in runtime, - * but seeing it together with the other values is helpful. */ - float step_factor; - /* The normalized zoom level at which the grid level starts to fade in. - * At lower zoom levels, the points will not be visible and the level will be skipped. */ - float fade_in_start_zoom; - /* The normalized zoom level at which the grid finishes fading in. - * At higher zoom levels, the points will be opaque. */ - float fade_in_end_zoom; -} DotGridLevelInfo; - -static const DotGridLevelInfo level_info[9] = { - {6.4f, -0.1f, 0.01f}, - {3.2f, 0.0f, 0.025f}, - {1.6f, 0.025f, 0.15f}, - {0.8f, 0.05f, 0.2f}, - {0.4f, 0.1f, 0.25f}, - {0.2f, 0.125f, 0.3f}, - {0.1f, 0.25f, 0.5f}, - {0.05f, 0.7f, 0.9f}, - {0.025f, 0.6f, 0.9f}, -}; - void UI_view2d_dot_grid_draw(const View2D *v2d, const int grid_color_id, const float min_step, - const int grid_levels) + const int grid_subdivisions) { - BLI_assert(grid_levels >= 0 && grid_levels < 10); + BLI_assert(grid_subdivisions >= 0 && grid_subdivisions < 4); + if (grid_subdivisions == 0) { + return; + } + const float zoom_x = (float)(BLI_rcti_size_x(&v2d->mask) + 1) / BLI_rctf_size_x(&v2d->cur); - const float zoom_normalized = (zoom_x - v2d->minzoom) / (v2d->maxzoom - v2d->minzoom); GPUVertFormat *format = immVertexFormat(); const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); const uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); - GPU_point_size(3.0f * UI_DPI_FAC); - float color[4]; - UI_GetThemeColor3fv(grid_color_id, color); + /* Scaling the dots fully with the zoom looks too busy, but a bit of size variation is nice. */ + const float min_point_size = 2.0f * UI_DPI_FAC; + const float point_size_factor = 1.5f; + const float max_point_size = point_size_factor * min_point_size; + + /* Each consecutive grid level is five times larger than the previous. */ + const int subdivision_scale = 5; + + const float view_level = logf(min_step / zoom_x) / logf(subdivision_scale); + const int largest_visible_level = (int)view_level; - for (int level = 0; level < grid_levels; level++) { - const DotGridLevelInfo *info = &level_info[level]; - const float step = min_step * info->step_factor * U.widget_unit; + for (int level_offset = 0; level_offset <= grid_subdivisions; level_offset++) { + const int level = largest_visible_level - level_offset; - const float alpha_factor = (zoom_normalized - info->fade_in_start_zoom) / - (info->fade_in_end_zoom - info->fade_in_start_zoom); - color[3] = clamp_f(BLI_easing_cubic_ease_in_out(alpha_factor, 0.0f, 1.0f, 1.0f), 0.0f, 1.0f); - if (color[3] == 0.0f) { + if (level < 0) { break; } + const float level_scale = powf(subdivision_scale, level); + const float point_size_precise = min_point_size * level_scale * zoom_x; + const float point_size_draw = ceilf( + clamp_f(point_size_precise, min_point_size, max_point_size)); + + /* To compensate the for the clamped point_size we adjust the alpha to make the overall + * brightness of the grid background more consistent. */ + const float alpha = pow2f(point_size_precise / point_size_draw); + + /* Make sure we don't draw points once the alpha gets too low. */ + const float alpha_cutoff = 0.01f; + if (alpha < alpha_cutoff) { + break; + } + const float alpha_clamped = clamp_f((1.0f + alpha_cutoff) * alpha - alpha_cutoff, 0.0f, 1.0f); + + /* If we have don't draw enough subdivision levels so they fade out naturally, we apply an + * additional fade to the last level to avoid pop in. */ + const bool last_level = level_offset == grid_subdivisions; + const float subdivision_fade = last_level ? (1.0f - fractf(view_level)) : 1.0f; + + float color[4]; + UI_GetThemeColor3fv(grid_color_id, color); + color[3] = alpha_clamped * subdivision_fade; + + const float step = min_step * level_scale; int count_x; float start_x; grid_axis_start_and_count(step, v2d->cur.xmin, v2d->cur.xmax, &start_x, &count_x); @@ -1331,6 +1339,7 @@ void UI_view2d_dot_grid_draw(const View2D *v2d, continue; } + GPU_point_size(point_size_draw); immBegin(GPU_PRIM_POINTS, count_x * count_y); /* Theoretically drawing on top of lower grid levels could be avoided, but it would also diff --git a/source/blender/editors/lattice/editlattice_select.c b/source/blender/editors/lattice/editlattice_select.c index ea99c6e23ff..54a72c7ea5d 100644 --- a/source/blender/editors/lattice/editlattice_select.c +++ b/source/blender/editors/lattice/editlattice_select.c @@ -664,7 +664,6 @@ bool ED_lattice_select_pick(bContext *C, const int mval[2], const struct SelectP break; } case SEL_OP_SET: { - ED_lattice_flags_set(vc.obedit, 0); bp->f1 |= SELECT; break; } diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 2181b652d16..1499742af54 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -4712,7 +4712,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) Object *ob = base_iter->object; if (ob->type == OB_MESH) { Mesh *me = ob->data; - if (!ID_IS_LINKED(me)) { + if (BKE_id_is_editable(bmain, &me->id)) { BMesh *bm_old = NULL; bool changed = false; diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index b99ff8296f3..630ef66504f 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -481,7 +481,8 @@ static bool layers_poll(bContext *C) { Object *ob = ED_object_context(C); ID *data = (ob) ? ob->data : NULL; - return (ob && !ID_IS_LINKED(ob) && ob->type == OB_MESH && data && !ID_IS_LINKED(data)); + return (ob && !ID_IS_LINKED(ob) && !ID_IS_OVERRIDE_LIBRARY(ob) && ob->type == OB_MESH && data && + !ID_IS_LINKED(data) && !ID_IS_OVERRIDE_LIBRARY(data)); } /*********************** Sculpt Vertex colors operators ************************/ @@ -867,7 +868,7 @@ static bool mesh_customdata_mask_clear_poll(bContext *C) return false; } - if (!ID_IS_LINKED(me)) { + if (!ID_IS_LINKED(me) && !ID_IS_OVERRIDE_LIBRARY(me)) { CustomData *data = GET_CD_DATA(me, vdata); if (CustomData_has_layer(data, CD_PAINT_MASK)) { return true; @@ -918,7 +919,7 @@ static int mesh_customdata_skin_state(bContext *C) if (ob && ob->type == OB_MESH) { Mesh *me = ob->data; - if (!ID_IS_LINKED(me)) { + if (!ID_IS_LINKED(me) && !ID_IS_OVERRIDE_LIBRARY(me)) { CustomData *data = GET_CD_DATA(me, vdata); return CustomData_has_layer(data, CD_MVERT_SKIN); } diff --git a/source/blender/editors/mesh/mesh_mirror.c b/source/blender/editors/mesh/mesh_mirror.c index b3d4757184e..82e77a88a57 100644 --- a/source/blender/editors/mesh/mesh_mirror.c +++ b/source/blender/editors/mesh/mesh_mirror.c @@ -166,7 +166,7 @@ void ED_mesh_mirrtopo_init(BMEditMesh *em, const bool is_editmode = (em != NULL); MEdge *medge = NULL, *med; - /* editmode*/ + /* Edit-mode variables. */ BMEdge *eed; BMIter iter; diff --git a/source/blender/editors/object/object_add.cc b/source/blender/editors/object/object_add.cc index b8ffaf87118..6a7920d4d75 100644 --- a/source/blender/editors/object/object_add.cc +++ b/source/blender/editors/object/object_add.cc @@ -8,6 +8,7 @@ #include <cctype> #include <cstdlib> #include <cstring> +#include <optional> #include "MEM_guardedalloc.h" @@ -1280,7 +1281,7 @@ static bool object_gpencil_add_poll(bContext *C) Scene *scene = CTX_data_scene(C); Object *obact = CTX_data_active_object(C); - if ((scene == nullptr) || (ID_IS_LINKED(scene))) { + if ((scene == nullptr) || ID_IS_LINKED(scene) || ID_IS_OVERRIDE_LIBRARY(scene)) { return false; } @@ -1629,66 +1630,100 @@ void OBJECT_OT_light_add(wmOperatorType *ot) /** \name Add Collection Instance Operator * \{ */ -static int collection_instance_add_exec(bContext *C, wmOperator *op) -{ - Main *bmain = CTX_data_main(C); +struct CollectionAddInfo { + /* The collection that is supposed to be added, determined through operator properties. */ Collection *collection; + /* The local-view bits (if any) the object should have set to become visible in current context. + */ ushort local_view_bits; + /* The transform that should be applied to the collection, determined through operator properties + * if set (e.g. to place the collection under the cursor), otherwise through context (e.g. 3D + * cursor location). */ float loc[3], rot[3]; +}; + +static std::optional<CollectionAddInfo> collection_add_info_get_from_op(bContext *C, + wmOperator *op) +{ + CollectionAddInfo add_info{}; + + Main *bmain = CTX_data_main(C); - PropertyRNA *prop_name = RNA_struct_find_property(op->ptr, "name"); PropertyRNA *prop_location = RNA_struct_find_property(op->ptr, "location"); PropertyRNA *prop_session_uuid = RNA_struct_find_property(op->ptr, "session_uuid"); + PropertyRNA *prop_name = RNA_struct_find_property(op->ptr, "name"); bool update_location_if_necessary = false; - if (RNA_property_is_set(op->ptr, prop_name)) { + if (prop_name && RNA_property_is_set(op->ptr, prop_name)) { char name[MAX_ID_NAME - 2]; RNA_property_string_get(op->ptr, prop_name, name); - collection = (Collection *)BKE_libblock_find_name(bmain, ID_GR, name); + add_info.collection = (Collection *)BKE_libblock_find_name(bmain, ID_GR, name); update_location_if_necessary = true; } else if (RNA_property_is_set(op->ptr, prop_session_uuid)) { const uint32_t session_uuid = (uint32_t)RNA_property_int_get(op->ptr, prop_session_uuid); - collection = (Collection *)BKE_libblock_find_session_uuid(bmain, ID_GR, session_uuid); + add_info.collection = (Collection *)BKE_libblock_find_session_uuid(bmain, ID_GR, session_uuid); update_location_if_necessary = true; } else { - collection = static_cast<Collection *>( + add_info.collection = static_cast<Collection *>( BLI_findlink(&bmain->collections, RNA_enum_get(op->ptr, "collection"))); } if (update_location_if_necessary) { int mval[2]; if (!RNA_property_is_set(op->ptr, prop_location) && object_add_drop_xy_get(C, op, &mval)) { - ED_object_location_from_view(C, loc); - ED_view3d_cursor3d_position(C, mval, false, loc); - RNA_property_float_set_array(op->ptr, prop_location, loc); + ED_object_location_from_view(C, add_info.loc); + ED_view3d_cursor3d_position(C, mval, false, add_info.loc); + RNA_property_float_set_array(op->ptr, prop_location, add_info.loc); } } - if (collection == nullptr) { - return OPERATOR_CANCELLED; + if (add_info.collection == nullptr) { + return std::nullopt; } - if (!ED_object_add_generic_get_opts( - C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr)) { - return OPERATOR_CANCELLED; + if (!ED_object_add_generic_get_opts(C, + op, + 'Z', + add_info.loc, + add_info.rot, + nullptr, + nullptr, + &add_info.local_view_bits, + nullptr)) { + return std::nullopt; } ViewLayer *view_layer = CTX_data_view_layer(C); /* Avoid dependency cycles. */ LayerCollection *active_lc = BKE_layer_collection_get_active(view_layer); - while (BKE_collection_cycle_find(active_lc->collection, collection)) { + while (BKE_collection_cycle_find(active_lc->collection, add_info.collection)) { active_lc = BKE_layer_collection_activate_parent(view_layer, active_lc); } - Object *ob = ED_object_add_type( - C, OB_EMPTY, collection->id.name + 2, loc, rot, false, local_view_bits); - ob->instance_collection = collection; + return add_info; +} + +static int collection_instance_add_exec(bContext *C, wmOperator *op) +{ + std::optional<CollectionAddInfo> add_info = collection_add_info_get_from_op(C, op); + if (!add_info) { + return OPERATOR_CANCELLED; + } + + Object *ob = ED_object_add_type(C, + OB_EMPTY, + add_info->collection->id.name + 2, + add_info->loc, + add_info->rot, + false, + add_info->local_view_bits); + ob->instance_collection = add_info->collection; ob->empty_drawsize = U.collection_instance_empty_size; ob->transflag |= OB_DUPLICOLLECTION; - id_us_plus(&collection->id); + id_us_plus(&add_info->collection->id); return OPERATOR_FINISHED; } @@ -1750,6 +1785,128 @@ void OBJECT_OT_collection_instance_add(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Collection Drop Operator + * + * Internal operator for collection dropping. + * + * \warning This is tied closely together to the drop-box callbacks, so it shouldn't be used on its + * own. + * + * The drop-box callback imports the collection, links it into the view-layer, selects all imported + * objects (which may include peripheral objects like parents or boolean-objects of an object in + * the collection) and activates one. Only the callback has enough info to do this reliably. Based + * on the instancing operator option, this operator then does one of two things: + * - Instancing enabled: Unlink the collection again, and instead add a collection instance empty + * at the drop position. + * - Instancing disabled: Transform the objects to the drop position, keeping all relative + * transforms of the objects to each other as is. + * + * \{ */ + +static int collection_drop_exec(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + LayerCollection *active_collection = CTX_data_layer_collection(C); + std::optional<CollectionAddInfo> add_info = collection_add_info_get_from_op(C, op); + if (!add_info) { + return OPERATOR_CANCELLED; + } + + if (RNA_boolean_get(op->ptr, "use_instance")) { + BKE_collection_child_remove(bmain, active_collection->collection, add_info->collection); + DEG_id_tag_update(&active_collection->collection->id, ID_RECALC_COPY_ON_WRITE); + DEG_relations_tag_update(bmain); + + Object *ob = ED_object_add_type(C, + OB_EMPTY, + add_info->collection->id.name + 2, + add_info->loc, + add_info->rot, + false, + add_info->local_view_bits); + ob->instance_collection = add_info->collection; + ob->empty_drawsize = U.collection_instance_empty_size; + ob->transflag |= OB_DUPLICOLLECTION; + id_us_plus(&add_info->collection->id); + } + else { + ViewLayer *view_layer = CTX_data_view_layer(C); + float delta_mat[4][4]; + unit_m4(delta_mat); + + const float scale[3] = {1.0f, 1.0f, 1.0f}; + loc_eul_size_to_mat4(delta_mat, add_info->loc, add_info->rot, scale); + + float offset[3]; + /* Reverse apply the instance offset, so toggling the Instance option doesn't cause the + * collection to jump. */ + negate_v3_v3(offset, add_info->collection->instance_offset); + translate_m4(delta_mat, UNPACK3(offset)); + + ObjectsInViewLayerParams params = {0}; + uint objects_len; + Object **objects = BKE_view_layer_array_selected_objects_params( + view_layer, nullptr, &objects_len, ¶ms); + ED_object_xform_array_m4(objects, objects_len, delta_mat); + + MEM_freeN(objects); + } + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_collection_external_asset_drop(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + /* Name should only be displayed in the drag tooltip. */ + ot->name = "Add Collection"; + ot->description = "Add the dragged collection to the scene"; + ot->idname = "OBJECT_OT_collection_external_asset_drop"; + + /* api callbacks */ + ot->invoke = object_instance_add_invoke; + ot->exec = collection_drop_exec; + ot->poll = ED_operator_objectmode; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + + /* properties */ + prop = RNA_def_int(ot->srna, + "session_uuid", + 0, + INT32_MIN, + INT32_MAX, + "Session UUID", + "Session UUID of the collection to add", + INT32_MIN, + INT32_MAX); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_SKIP_SAVE | PROP_HIDDEN)); + + ED_object_add_generic_props(ot, false); + + /* Important: Instancing option. Intentionally remembered across executions (no #PROP_SKIP_SAVE). + */ + RNA_def_boolean(ot->srna, + "use_instance", + true, + "Instance", + "Add the dropped collection as collection instance"); + + object_add_drop_xy_props(ot); + + prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", ""); + RNA_def_enum_funcs(prop, RNA_collection_itemf); + RNA_def_property_flag(prop, + (PropertyFlag)(PROP_SKIP_SAVE | PROP_HIDDEN | PROP_ENUM_NO_TRANSLATE)); + ot->prop = prop; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Add Data Instance Operator * * Use for dropping ID's from the outliner. @@ -2752,12 +2909,14 @@ static int object_convert_exec(bContext *C, wmOperator *op) * However, changing this is more design than bug-fix, not to mention convoluted code below, * so that will be for later. * But at the very least, do not do that with linked IDs! */ - if ((ID_IS_LINKED(ob) || (ob->data && ID_IS_LINKED(ob->data))) && !keep_original) { + if ((!BKE_id_is_editable(bmain, &ob->id) || + (ob->data && !BKE_id_is_editable(bmain, static_cast<ID *>(ob->data)))) && + !keep_original) { keep_original = true; - BKE_report( - op->reports, - RPT_INFO, - "Converting some linked object/object data, enforcing 'Keep Original' option to True"); + BKE_report(op->reports, + RPT_INFO, + "Converting some non-editable object/object data, enforcing 'Keep Original' " + "option to True"); } DEG_id_tag_update(&base->object->id, ID_RECALC_GEOMETRY); @@ -3631,7 +3790,7 @@ static int object_transform_to_mouse_exec(bContext *C, wmOperator *op) /* Don't transform a linked object. There's just nothing to do here in this case, so return * #OPERATOR_FINISHED. */ - if (ID_IS_LINKED(ob)) { + if (!BKE_id_is_editable(bmain, &ob->id)) { return OPERATOR_FINISHED; } diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index dbb6916dfce..d93edd2776b 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -515,7 +515,7 @@ static void multiresbake_freejob(void *bkv) /* delete here, since this delete will be called from main thread */ for (link = data->images.first; link; link = link->next) { Image *ima = (Image *)link->data; - BKE_image_free_gputextures(ima); + BKE_image_partial_update_mark_full_update(ima); } MEM_freeN(data->ob_image.array); diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index efcb47f76ab..44f05600d7d 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -180,7 +180,7 @@ static bool write_internal_bake_pixels(Image *image, void *lock; bool is_float; char *mask_buffer = NULL; - const size_t num_pixels = (size_t)width * (size_t)height; + const size_t pixels_num = (size_t)width * (size_t)height; ibuf = BKE_image_acquire_ibuf(image, NULL, &lock); @@ -189,8 +189,8 @@ static bool write_internal_bake_pixels(Image *image, } if (margin > 0 || !is_clear) { - mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask"); - RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer); + mask_buffer = MEM_callocN(sizeof(char) * pixels_num, "Bake Mask"); + RE_bake_mask_fill(pixel_array, pixels_num, mask_buffer); } is_float = (ibuf->rect_float != NULL); @@ -298,7 +298,7 @@ static bool write_internal_bake_pixels(Image *image, /* force OpenGL reload */ static void bake_targets_refresh(BakeTargets *targets) { - for (int i = 0; i < targets->num_images; i++) { + for (int i = 0; i < targets->images_num; i++) { Image *ima = targets->images[i].image; if (ima) { @@ -374,10 +374,10 @@ static bool write_external_bake_pixels(const char *filepath, /* margins */ if (margin > 0) { char *mask_buffer = NULL; - const size_t num_pixels = (size_t)width * (size_t)height; + const size_t pixels_num = (size_t)width * (size_t)height; - mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask"); - RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer); + mask_buffer = MEM_callocN(sizeof(char) * pixels_num, "Bake Mask"); + RE_bake_mask_fill(pixel_array, pixels_num, mask_buffer); RE_bake_margin(ibuf, mask_buffer, margin, margin_type, mesh_eval, uv_layer); if (mask_buffer) { @@ -670,9 +670,9 @@ static bool bake_targets_init_image_textures(const BakeAPIRender *bkr, Object *ob, ReportList *reports) { - int num_materials = ob->totcol; + int materials_num = ob->totcol; - if (num_materials == 0) { + if (materials_num == 0) { if (bkr->save_mode == R_BAKE_SAVE_INTERNAL) { BKE_report( reports, RPT_ERROR, "No active image found, add a material or bake to an external file"); @@ -688,15 +688,15 @@ static bool bake_targets_init_image_textures(const BakeAPIRender *bkr, } /* Over-allocate in case there is more materials than images. */ - targets->num_materials = num_materials; - targets->images = MEM_callocN(sizeof(BakeImage) * targets->num_materials, "BakeTargets.images"); - targets->material_to_image = MEM_callocN(sizeof(int) * targets->num_materials, + targets->materials_num = materials_num; + targets->images = MEM_callocN(sizeof(BakeImage) * targets->materials_num, "BakeTargets.images"); + targets->material_to_image = MEM_callocN(sizeof(int) * targets->materials_num, "BakeTargets.material_to_image"); /* Error handling and tag (in case multiple materials share the same image). */ BKE_main_id_tag_idcode(bkr->main, ID_IM, LIB_TAG_DOIT, false); - for (int i = 0; i < num_materials; i++) { + for (int i = 0; i < materials_num; i++) { Image *image; ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL); @@ -713,10 +713,10 @@ static bool bake_targets_init_image_textures(const BakeAPIRender *bkr, } } else { - targets->material_to_image[i] = targets->num_images; - targets->images[targets->num_images].image = image; + targets->material_to_image[i] = targets->images_num; + targets->images[targets->images_num].image = image; image->id.tag |= LIB_TAG_DOIT; - targets->num_images++; + targets->images_num++; } } @@ -733,7 +733,7 @@ static bool bake_targets_init_internal(const BakeAPIRender *bkr, } /* Saving to image datablocks. */ - for (int i = 0; i < targets->num_images; i++) { + for (int i = 0; i < targets->images_num; i++) { BakeImage *bk_image = &targets->images[i]; void *lock; ImBuf *ibuf = BKE_image_acquire_ibuf(bk_image->image, NULL, &lock); @@ -741,9 +741,9 @@ static bool bake_targets_init_internal(const BakeAPIRender *bkr, if (ibuf) { bk_image->width = ibuf->x; bk_image->height = ibuf->y; - bk_image->offset = targets->num_pixels; + bk_image->offset = targets->pixels_num; - targets->num_pixels += (size_t)ibuf->x * (size_t)ibuf->y; + targets->pixels_num += (size_t)ibuf->x * (size_t)ibuf->y; } else { BKE_image_release_ibuf(bk_image->image, ibuf, lock); @@ -765,12 +765,12 @@ static bool bake_targets_output_internal(const BakeAPIRender *bkr, { bool all_ok = true; - for (int i = 0; i < targets->num_images; i++) { + for (int i = 0; i < targets->images_num; i++) { BakeImage *bk_image = &targets->images[i]; const bool ok = write_internal_bake_pixels(bk_image->image, pixel_array + bk_image->offset, targets->result + - bk_image->offset * targets->num_channels, + bk_image->offset * targets->channels_num, bk_image->width, bk_image->height, bkr->margin, @@ -809,15 +809,15 @@ static bool bake_targets_init_external(const BakeAPIRender *bkr, } /* Saving to disk. */ - for (int i = 0; i < targets->num_images; i++) { + for (int i = 0; i < targets->images_num; i++) { BakeImage *bk_image = &targets->images[i]; bk_image->width = bkr->width; bk_image->height = bkr->height; - bk_image->offset = targets->num_pixels; + bk_image->offset = targets->pixels_num; bk_image->image = NULL; - targets->num_pixels += (size_t)bkr->width * (size_t)bkr->height; + targets->pixels_num += (size_t)bkr->width * (size_t)bkr->height; if (!bkr->is_split_materials) { break; @@ -826,7 +826,7 @@ static bool bake_targets_init_external(const BakeAPIRender *bkr, if (!bkr->is_split_materials) { /* saving a single image */ - for (int i = 0; i < targets->num_materials; i++) { + for (int i = 0; i < targets->materials_num; i++) { targets->material_to_image[i] = 0; } } @@ -844,7 +844,7 @@ static bool bake_targets_output_external(const BakeAPIRender *bkr, { bool all_ok = true; - for (int i = 0; i < targets->num_images; i++) { + for (int i = 0; i < targets->images_num; i++) { BakeImage *bk_image = &targets->images[i]; BakeData *bake = &bkr->scene->r.bake; @@ -888,7 +888,7 @@ static bool bake_targets_output_external(const BakeAPIRender *bkr, const bool ok = write_external_bake_pixels(name, pixel_array + bk_image->offset, targets->result + - bk_image->offset * targets->num_channels, + bk_image->offset * targets->channels_num, bk_image->width, bk_image->height, bkr->margin, @@ -934,11 +934,11 @@ static bool bake_targets_init_vertex_colors(BakeTargets *targets, Object *ob, Re } targets->images = MEM_callocN(sizeof(BakeImage), "BakeTargets.images"); - targets->num_images = 1; + targets->images_num = 1; targets->material_to_image = MEM_callocN(sizeof(int) * ob->totcol, "BakeTargets.material_to_image"); - targets->num_materials = ob->totcol; + targets->materials_num = ob->totcol; BakeImage *bk_image = &targets->images[0]; bk_image->width = me->totloop; @@ -946,7 +946,7 @@ static bool bake_targets_init_vertex_colors(BakeTargets *targets, Object *ob, Re bk_image->offset = 0; bk_image->image = NULL; - targets->num_pixels = bk_image->width * bk_image->height; + targets->pixels_num = bk_image->width * bk_image->height; return true; } @@ -984,10 +984,10 @@ static void bake_targets_populate_pixels_vertex_colors(BakeTargets *targets, BakePixel *pixel_array) { Mesh *me = ob->data; - const int num_pixels = targets->num_pixels; + const int pixels_num = targets->pixels_num; /* Initialize blank pixels. */ - for (int i = 0; i < num_pixels; i++) { + for (int i = 0; i < pixels_num; i++) { BakePixel *pixel = &pixel_array[i]; pixel->primitive_id = -1; @@ -1059,12 +1059,12 @@ static void bake_targets_populate_pixels_vertex_colors(BakeTargets *targets, MEM_freeN(looptri); } -static void bake_result_add_to_rgba(float rgba[4], const float *result, const int num_channels) +static void bake_result_add_to_rgba(float rgba[4], const float *result, const int channels_num) { - if (num_channels == 4) { + if (channels_num == 4) { add_v4_v4(rgba, result); } - else if (num_channels == 3) { + else if (channels_num == 3) { add_v3_v3(rgba, result); rgba[3] += 1.0f; } @@ -1082,7 +1082,7 @@ static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob) MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR); const bool mcol_valid = (mcol != NULL && U.experimental.use_sculpt_vertex_colors); MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL); - const int num_channels = targets->num_channels; + const int channels_num = targets->channels_num; const float *result = targets->result; if (mcol_valid) { @@ -1096,7 +1096,7 @@ static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob) MLoop *mloop = me->mloop; for (int i = 0; i < totloop; i++, mloop++) { const int v = mloop->v; - bake_result_add_to_rgba(mcol[v].color, &result[i * num_channels], num_channels); + bake_result_add_to_rgba(mcol[v].color, &result[i * channels_num], channels_num); num_loops_for_vertex[v]++; } @@ -1118,7 +1118,7 @@ static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob) for (int i = 0; i < totloop; i++, mloop++, mloopcol++) { float rgba[4]; zero_v4(rgba); - bake_result_add_to_rgba(rgba, &result[i * num_channels], num_channels); + bake_result_add_to_rgba(rgba, &result[i * channels_num], channels_num); if (is_noncolor) { unit_float_to_uchar_clamp_v4(&mloopcol->r, rgba); @@ -1160,13 +1160,13 @@ static bool bake_targets_init(const BakeAPIRender *bkr, } } - if (targets->num_pixels == 0) { + if (targets->pixels_num == 0) { return false; } targets->is_noncolor = is_noncolor_pass(bkr->pass_type); - targets->num_channels = RE_pass_depth(bkr->pass_type); - targets->result = MEM_callocN(sizeof(float) * targets->num_channels * targets->num_pixels, + targets->channels_num = RE_pass_depth(bkr->pass_type); + targets->result = MEM_callocN(sizeof(float) * targets->channels_num * targets->pixels_num, "bake return pixels"); return true; @@ -1182,7 +1182,7 @@ static void bake_targets_populate_pixels(const BakeAPIRender *bkr, bake_targets_populate_pixels_vertex_colors(targets, ob, me_eval, pixel_array); } else { - RE_bake_pixels_populate(me_eval, pixel_array, targets->num_pixels, targets, bkr->uv_layer); + RE_bake_pixels_populate(me_eval, pixel_array, targets->pixels_num, targets, bkr->uv_layer); } } @@ -1329,7 +1329,7 @@ static int bake(const BakeAPIRender *bkr, /* Populate the pixel array with the face data. Except if we use a cage, then * it is populated later with the cage mesh (smoothed version of the mesh). */ - pixel_array_low = MEM_mallocN(sizeof(BakePixel) * targets.num_pixels, "bake pixels low poly"); + pixel_array_low = MEM_mallocN(sizeof(BakePixel) * targets.pixels_num, "bake pixels low poly"); if ((bkr->is_selected_to_active && (ob_cage == NULL) && bkr->is_cage) == false) { bake_targets_populate_pixels(bkr, &targets, ob_low, me_low_eval, pixel_array_low); } @@ -1422,7 +1422,7 @@ static int bake(const BakeAPIRender *bkr, 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 */ - pixel_array_high = MEM_mallocN(sizeof(BakePixel) * targets.num_pixels, + pixel_array_high = MEM_mallocN(sizeof(BakePixel) * targets.pixels_num, "bake pixels high poly"); if (!RE_bake_pixels_populate_from_objects(me_low_eval, @@ -1430,7 +1430,7 @@ static int bake(const BakeAPIRender *bkr, pixel_array_high, highpoly, tot_highpoly, - targets.num_pixels, + targets.pixels_num, ob_cage != NULL, bkr->cage_extrusion, bkr->max_ray_distance, @@ -1491,16 +1491,16 @@ static int bake(const BakeAPIRender *bkr, break; } RE_bake_normal_world_to_world(pixel_array_low, - targets.num_pixels, - targets.num_channels, + targets.pixels_num, + targets.channels_num, targets.result, bkr->normal_swizzle); break; } case R_BAKE_SPACE_OBJECT: { RE_bake_normal_world_to_object(pixel_array_low, - targets.num_pixels, - targets.num_channels, + targets.pixels_num, + targets.channels_num, targets.result, ob_low_eval, bkr->normal_swizzle); @@ -1509,8 +1509,8 @@ static int bake(const BakeAPIRender *bkr, case R_BAKE_SPACE_TANGENT: { if (bkr->is_selected_to_active) { RE_bake_normal_world_to_tangent(pixel_array_low, - targets.num_pixels, - targets.num_channels, + targets.pixels_num, + targets.channels_num, targets.result, me_low_eval, bkr->normal_swizzle, @@ -1535,8 +1535,8 @@ static int bake(const BakeAPIRender *bkr, } RE_bake_normal_world_to_tangent(pixel_array_low, - targets.num_pixels, - targets.num_channels, + targets.pixels_num, + targets.channels_num, targets.result, (me_nores) ? me_nores : me_low_eval, bkr->normal_swizzle, diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index 3abf0d68eb3..6805c9144d6 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -319,11 +319,11 @@ static void data_transfer_exec_preprocess_objects(bContext *C, } me = ob->data; - if (ID_IS_LINKED(me)) { - /* Do not transfer to linked data, not supported. */ + if (ID_IS_LINKED(me) || ID_IS_OVERRIDE_LIBRARY(me)) { + /* Do not transfer to linked/override data, not supported. */ BKE_reportf(op->reports, RPT_WARNING, - "Skipping object '%s', linked data '%s' cannot be modified", + "Skipping object '%s', linked or override data '%s' cannot be modified", ob->id.name + 2, me->id.name + 2); me->id.tag &= ~LIB_TAG_DOIT; diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 7cef3e1725b..cc8644285c0 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -51,6 +51,7 @@ #include "BKE_image.h" #include "BKE_lattice.h" #include "BKE_layer.h" +#include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_mball.h" @@ -973,7 +974,7 @@ static int posemode_exec(bContext *C, wmOperator *op) const View3D *v3d = CTX_wm_view3d(C); FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) { if ((ob != obact) && (ob->type == OB_ARMATURE) && (ob->mode == OB_MODE_OBJECT) && - (!ID_IS_LINKED(ob))) { + BKE_id_is_editable(bmain, &ob->id)) { ED_object_posemode_enter_ex(bmain, ob); } } @@ -1528,6 +1529,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) } } + Main *bmain = CTX_data_main(C); LISTBASE_FOREACH (CollectionPointerLink *, ctx_ob, &ctx_objects) { /* Always un-tag all object data-blocks irrespective of our ability to operate on them. */ Object *ob = ctx_ob->ptr.data; @@ -1538,7 +1540,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) data->tag &= ~LIB_TAG_DOIT; /* Finished un-tagging, continue with regular logic. */ - if (data && ID_IS_LINKED(data)) { + if (data && !BKE_id_is_editable(bmain, data)) { has_linked_data = true; continue; } diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c index d0a6a5d44c0..573f048e6b6 100644 --- a/source/blender/editors/object/object_gpencil_modifier.c +++ b/source/blender/editors/object/object_gpencil_modifier.c @@ -26,6 +26,7 @@ #include "BKE_context.h" #include "BKE_gpencil.h" #include "BKE_gpencil_modifier.h" +#include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_object.h" #include "BKE_report.h" @@ -418,17 +419,18 @@ static bool gpencil_edit_modifier_poll_generic(bContext *C, int obtype_flag, const bool is_liboverride_allowed) { + Main *bmain = CTX_data_main(C); PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type); Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C); GpencilModifierData *mod = ptr.data; /* May be NULL. */ - if (!ob || ID_IS_LINKED(ob)) { + if (!ob || !BKE_id_is_editable(bmain, &ob->id)) { return false; } if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) { return false; } - if (ptr.owner_id && ID_IS_LINKED(ptr.owner_id)) { + if (ptr.owner_id && !BKE_id_is_editable(bmain, ptr.owner_id)) { return false; } diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index e8637b57724..b3f62f3fc0f 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -54,23 +54,26 @@ #include "object_intern.h" -static int return_editmesh_indexar(BMEditMesh *em, int *r_tot, int **r_indexar, float r_cent[3]) +static int return_editmesh_indexar(BMEditMesh *em, + int *r_indexar_num, + int **r_indexar, + float r_cent[3]) { BMVert *eve; BMIter iter; - int *index, nr, totvert = 0; + int *index, nr, indexar_num = 0; BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { - totvert++; + indexar_num++; } } - if (totvert == 0) { + if (indexar_num == 0) { return 0; } - *r_indexar = index = MEM_mallocN(4 * totvert, "hook indexar"); - *r_tot = totvert; + *r_indexar = index = MEM_mallocN(4 * indexar_num, "hook indexar"); + *r_indexar_num = indexar_num; nr = 0; zero_v3(r_cent); @@ -83,9 +86,9 @@ static int return_editmesh_indexar(BMEditMesh *em, int *r_tot, int **r_indexar, nr++; } - mul_v3_fl(r_cent, 1.0f / (float)totvert); + mul_v3_fl(r_cent, 1.0f / (float)indexar_num); - return totvert; + return indexar_num; } static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name, float r_cent[3]) @@ -97,7 +100,7 @@ static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name, if (cd_dvert_offset != -1) { const int defgrp_index = active_index - 1; - int totvert = 0; + int indexar_num = 0; MDeformVert *dvert; BMVert *eve; @@ -109,14 +112,14 @@ static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name, if (BKE_defvert_find_weight(dvert, defgrp_index) > 0.0f) { add_v3_v3(r_cent, eve->co); - totvert++; + indexar_num++; } } - if (totvert) { + if (indexar_num) { const ListBase *defbase = BKE_object_defgroup_list(obedit); bDeformGroup *dg = BLI_findlink(defbase, defgrp_index); BLI_strncpy(r_name, dg->name, sizeof(dg->name)); - mul_v3_fl(r_cent, 1.0f / (float)totvert); + mul_v3_fl(r_cent, 1.0f / (float)indexar_num); return true; } } @@ -139,7 +142,7 @@ static void select_editbmesh_hook(Object *ob, HookModifierData *hmd) BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (nr == hmd->indexar[index]) { BM_vert_select_set(em->bm, eve, true); - if (index < hmd->totindex - 1) { + if (index < hmd->indexar_num - 1) { index++; } } @@ -151,12 +154,12 @@ static void select_editbmesh_hook(Object *ob, HookModifierData *hmd) } static int return_editlattice_indexar(Lattice *editlatt, - int *r_tot, int **r_indexar, + int *r_indexar_num, float r_cent[3]) { BPoint *bp; - int *index, nr, totvert = 0, a; + int *index, nr, indexar_num = 0, a; /* count */ a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw; @@ -164,18 +167,18 @@ static int return_editlattice_indexar(Lattice *editlatt, while (a--) { if (bp->f1 & SELECT) { if (bp->hide == 0) { - totvert++; + indexar_num++; } } bp++; } - if (totvert == 0) { + if (indexar_num == 0) { return 0; } - *r_indexar = index = MEM_mallocN(4 * totvert, "hook indexar"); - *r_tot = totvert; + *r_indexar = index = MEM_mallocN(4 * indexar_num, "hook indexar"); + *r_indexar_num = indexar_num; nr = 0; zero_v3(r_cent); @@ -193,9 +196,9 @@ static int return_editlattice_indexar(Lattice *editlatt, nr++; } - mul_v3_fl(r_cent, 1.0f / (float)totvert); + mul_v3_fl(r_cent, 1.0f / (float)indexar_num); - return totvert; + return indexar_num; } static void select_editlattice_hook(Object *obedit, HookModifierData *hmd) @@ -211,7 +214,7 @@ static void select_editlattice_hook(Object *obedit, HookModifierData *hmd) while (a--) { if (hmd->indexar[index] == nr) { bp->f1 |= SELECT; - if (index < hmd->totindex - 1) { + if (index < hmd->indexar_num - 1) { index++; } } @@ -220,12 +223,15 @@ static void select_editlattice_hook(Object *obedit, HookModifierData *hmd) } } -static int return_editcurve_indexar(Object *obedit, int *r_tot, int **r_indexar, float r_cent[3]) +static int return_editcurve_indexar(Object *obedit, + int **r_indexar, + int *r_indexar_num, + float r_cent[3]) { ListBase *editnurb = object_editcurve_get(obedit); BPoint *bp; BezTriple *bezt; - int *index, a, nr, totvert = 0; + int *index, a, nr, indexar_num = 0; LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { @@ -233,13 +239,13 @@ static int return_editcurve_indexar(Object *obedit, int *r_tot, int **r_indexar, a = nu->pntsu; while (a--) { if (bezt->f1 & SELECT) { - totvert++; + indexar_num++; } if (bezt->f2 & SELECT) { - totvert++; + indexar_num++; } if (bezt->f3 & SELECT) { - totvert++; + indexar_num++; } bezt++; } @@ -249,18 +255,18 @@ static int return_editcurve_indexar(Object *obedit, int *r_tot, int **r_indexar, a = nu->pntsu * nu->pntsv; while (a--) { if (bp->f1 & SELECT) { - totvert++; + indexar_num++; } bp++; } } } - if (totvert == 0) { + if (indexar_num == 0) { return 0; } - *r_indexar = index = MEM_mallocN(sizeof(*index) * totvert, "hook indexar"); - *r_tot = totvert; + *r_indexar = index = MEM_mallocN(sizeof(*index) * indexar_num, "hook indexar"); + *r_indexar_num = indexar_num; nr = 0; zero_v3(r_cent); @@ -305,21 +311,21 @@ static int return_editcurve_indexar(Object *obedit, int *r_tot, int **r_indexar, } } - mul_v3_fl(r_cent, 1.0f / (float)totvert); + mul_v3_fl(r_cent, 1.0f / (float)indexar_num); - return totvert; + return indexar_num; } static bool object_hook_index_array(Main *bmain, Scene *scene, Object *obedit, - int *r_tot, int **r_indexar, + int *r_indexar_num, char *r_name, float r_cent[3]) { *r_indexar = NULL; - *r_tot = 0; + *r_indexar_num = 0; r_name[0] = 0; switch (obedit->type) { @@ -338,7 +344,7 @@ static bool object_hook_index_array(Main *bmain, BKE_editmesh_looptri_and_normals_calc(em); /* check selected vertices first */ - if (return_editmesh_indexar(em, r_tot, r_indexar, r_cent) == 0) { + if (return_editmesh_indexar(em, r_indexar_num, r_indexar, r_cent) == 0) { return return_editmesh_vgroup(obedit, em, r_name, r_cent); } return true; @@ -347,10 +353,10 @@ static bool object_hook_index_array(Main *bmain, case OB_SURF: ED_curve_editnurb_load(bmain, obedit); ED_curve_editnurb_make(obedit); - return return_editcurve_indexar(obedit, r_tot, r_indexar, r_cent); + return return_editcurve_indexar(obedit, r_indexar, r_indexar_num, r_cent); case OB_LATTICE: { Lattice *lt = obedit->data; - return return_editlattice_indexar(lt->editlatt->latt, r_tot, r_indexar, r_cent); + return return_editlattice_indexar(lt->editlatt->latt, r_indexar, r_indexar_num, r_cent); } default: return false; @@ -371,21 +377,21 @@ static void select_editcurve_hook(Object *obedit, HookModifierData *hmd) while (a--) { if (nr == hmd->indexar[index]) { bezt->f1 |= SELECT; - if (index < hmd->totindex - 1) { + if (index < hmd->indexar_num - 1) { index++; } } nr++; if (nr == hmd->indexar[index]) { bezt->f2 |= SELECT; - if (index < hmd->totindex - 1) { + if (index < hmd->indexar_num - 1) { index++; } } nr++; if (nr == hmd->indexar[index]) { bezt->f3 |= SELECT; - if (index < hmd->totindex - 1) { + if (index < hmd->indexar_num - 1) { index++; } } @@ -400,7 +406,7 @@ static void select_editcurve_hook(Object *obedit, HookModifierData *hmd) while (a--) { if (nr == hmd->indexar[index]) { bp->f1 |= SELECT; - if (index < hmd->totindex - 1) { + if (index < hmd->indexar_num - 1) { index++; } } @@ -514,10 +520,10 @@ static int add_hook_object(const bContext *C, HookModifierData *hmd = NULL; float cent[3]; float pose_mat[4][4]; - int tot, ok, *indexar; + int indexar_num, ok, *indexar; char name[MAX_NAME]; - ok = object_hook_index_array(bmain, scene, obedit, &tot, &indexar, name, cent); + ok = object_hook_index_array(bmain, scene, obedit, &indexar, &indexar_num, name, cent); if (!ok) { BKE_report(reports, RPT_ERROR, "Requires selected vertices or active vertex group"); @@ -545,7 +551,7 @@ static int add_hook_object(const bContext *C, hmd->object = ob; hmd->indexar = indexar; copy_v3_v3(hmd->cent, cent); - hmd->totindex = tot; + hmd->indexar_num = indexar_num; BLI_strncpy(hmd->name, name, sizeof(hmd->name)); unit_m4(pose_mat); @@ -873,7 +879,7 @@ static int object_hook_assign_exec(bContext *C, wmOperator *op) HookModifierData *hmd = NULL; float cent[3]; char name[MAX_NAME]; - int *indexar, tot; + int *indexar, indexar_num; object_hook_from_context(C, &ptr, num, &ob, &hmd); if (hmd == NULL) { @@ -883,7 +889,7 @@ static int object_hook_assign_exec(bContext *C, wmOperator *op) /* assign functionality */ - if (!object_hook_index_array(bmain, scene, ob, &tot, &indexar, name, cent)) { + if (!object_hook_index_array(bmain, scene, ob, &indexar, &indexar_num, name, cent)) { BKE_report(op->reports, RPT_WARNING, "Requires selected vertices or active vertex group"); return OPERATOR_CANCELLED; } @@ -893,7 +899,7 @@ static int object_hook_assign_exec(bContext *C, wmOperator *op) copy_v3_v3(hmd->cent, cent); hmd->indexar = indexar; - hmd->totindex = tot; + hmd->indexar_num = indexar_num; DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 490c495dad5..cb703caa8d1 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -119,6 +119,7 @@ void OBJECT_OT_pointcloud_add(struct wmOperatorType *ot); * Only used as menu. */ void OBJECT_OT_collection_instance_add(struct wmOperatorType *ot); +void OBJECT_OT_collection_external_asset_drop(struct wmOperatorType *ot); void OBJECT_OT_data_instance_add(struct wmOperatorType *ot); void OBJECT_OT_duplicates_make_real(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 7fedc2c6265..545265b18b1 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -219,9 +219,6 @@ ModifierData *ED_object_modifier_add( /* ensure skin-node customdata exists */ BKE_mesh_ensure_skin_customdata(ob->data); } - else if (type == eModifierType_Nodes) { - MOD_nodes_init(bmain, (NodesModifierData *)new_md); - } } BKE_object_modifier_set_active(ob, new_md); @@ -541,36 +538,36 @@ bool ED_object_modifier_convert(ReportList *UNUSED(reports), return false; } - int totpart = psys_eval->totcached; - int totchild = psys_eval->totchildcache; + int part_num = psys_eval->totcached; + int child_num = psys_eval->totchildcache; - if (totchild && (part->draw & PART_DRAW_PARENT) == 0) { - totpart = 0; + if (child_num && (part->draw & PART_DRAW_PARENT) == 0) { + part_num = 0; } /* count */ - int totvert = 0, totedge = 0; + int verts_num = 0, edges_num = 0; ParticleCacheKey **cache = psys_eval->pathcache; - for (int a = 0; a < totpart; a++) { + for (int a = 0; a < part_num; a++) { ParticleCacheKey *key = cache[a]; if (key->segments > 0) { - totvert += key->segments + 1; - totedge += key->segments; + verts_num += key->segments + 1; + edges_num += key->segments; } } cache = psys_eval->childcache; - for (int a = 0; a < totchild; a++) { + for (int a = 0; a < child_num; a++) { ParticleCacheKey *key = cache[a]; if (key->segments > 0) { - totvert += key->segments + 1; - totedge += key->segments; + verts_num += key->segments + 1; + edges_num += key->segments; } } - if (totvert == 0) { + if (verts_num == 0) { return false; } @@ -578,11 +575,11 @@ bool ED_object_modifier_convert(ReportList *UNUSED(reports), Object *obn = BKE_object_add(bmain, view_layer, OB_MESH, NULL); Mesh *me = obn->data; - me->totvert = totvert; - me->totedge = totedge; + me->totvert = verts_num; + me->totedge = edges_num; - me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert); - me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge); + me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, verts_num); + me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, edges_num); me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0); MVert *mvert = me->mvert; @@ -590,7 +587,7 @@ bool ED_object_modifier_convert(ReportList *UNUSED(reports), /* copy coordinates */ cache = psys_eval->pathcache; - for (int a = 0; a < totpart; a++) { + for (int a = 0; a < part_num; a++) { ParticleCacheKey *key = cache[a]; int kmax = key->segments; for (int k = 0; k <= kmax; k++, key++, cvert++, mvert++) { @@ -609,7 +606,7 @@ bool ED_object_modifier_convert(ReportList *UNUSED(reports), } cache = psys_eval->childcache; - for (int a = 0; a < totchild; a++) { + for (int a = 0; a < child_num; a++) { ParticleCacheKey *key = cache[a]; int kmax = key->segments; for (int k = 0; k <= kmax; k++, key++, cvert++, mvert++) { @@ -774,9 +771,9 @@ static bool modifier_apply_obdata( RPT_INFO, "Applied modifier only changed CV points, not tessellated/bevel vertices"); - int numVerts; - float(*vertexCos)[3] = BKE_curve_nurbs_vert_coords_alloc(&curve_eval->nurb, &numVerts); - mti->deformVerts(md_eval, &mectx, NULL, vertexCos, numVerts); + int verts_num; + float(*vertexCos)[3] = BKE_curve_nurbs_vert_coords_alloc(&curve_eval->nurb, &verts_num); + mti->deformVerts(md_eval, &mectx, NULL, vertexCos, verts_num); BKE_curve_nurbs_vert_coords_apply(&curve->nurb, vertexCos, false); MEM_freeN(vertexCos); @@ -793,9 +790,9 @@ static bool modifier_apply_obdata( return false; } - int numVerts; - float(*vertexCos)[3] = BKE_lattice_vert_coords_alloc(lattice, &numVerts); - mti->deformVerts(md_eval, &mectx, NULL, vertexCos, numVerts); + int verts_num; + float(*vertexCos)[3] = BKE_lattice_vert_coords_alloc(lattice, &verts_num); + mti->deformVerts(md_eval, &mectx, NULL, vertexCos, verts_num); BKE_lattice_vert_coords_apply(lattice, vertexCos); MEM_freeN(vertexCos); @@ -1016,6 +1013,7 @@ bool edit_modifier_poll_generic(bContext *C, const bool is_editmode_allowed, const bool is_liboverride_allowed) { + Main *bmain = CTX_data_main(C); PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type); Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C); ModifierData *mod = ptr.data; /* May be NULL. */ @@ -1024,13 +1022,13 @@ bool edit_modifier_poll_generic(bContext *C, mod = BKE_object_active_modifier(ob); } - if (!ob || ID_IS_LINKED(ob)) { + if (!ob || !BKE_id_is_editable(bmain, &ob->id)) { return false; } if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) { return false; } - if (ptr.owner_id && ID_IS_LINKED(ptr.owner_id)) { + if (ptr.owner_id && !BKE_id_is_editable(bmain, ptr.owner_id)) { return false; } @@ -1365,7 +1363,7 @@ void OBJECT_OT_modifier_move_to_index(wmOperatorType *ot) /** \name Apply Modifier Operator * \{ */ -static bool modifier_apply_poll_ex(bContext *C, bool allow_shared) +static bool modifier_apply_poll(bContext *C) { if (!edit_modifier_poll_generic(C, &RNA_Modifier, 0, false, false)) { return false; @@ -1380,10 +1378,6 @@ static bool modifier_apply_poll_ex(bContext *C, bool allow_shared) CTX_wm_operator_poll_msg_set(C, "Modifiers cannot be applied on override data"); return false; } - if (!allow_shared && (ob->data != NULL) && ID_REAL_USERS(ob->data) > 1) { - CTX_wm_operator_poll_msg_set(C, "Modifiers cannot be applied to multi-user data"); - return false; - } if (md != NULL) { if ((ob->mode & OB_MODE_SCULPT) && (find_multires_modifier_before(scene, md)) && (BKE_modifier_is_same_topology(md) == false)) { @@ -1395,11 +1389,6 @@ static bool modifier_apply_poll_ex(bContext *C, bool allow_shared) return true; } -static bool modifier_apply_poll(bContext *C) -{ - return modifier_apply_poll_ex(C, false); -} - static int modifier_apply_exec_ex(bContext *C, wmOperator *op, int apply_as, bool keep_modifier) { Main *bmain = CTX_data_main(C); @@ -1408,11 +1397,19 @@ static int modifier_apply_exec_ex(bContext *C, wmOperator *op, int apply_as, boo Object *ob = ED_object_active_context(C); ModifierData *md = edit_modifier_property_get(op, ob, 0); const bool do_report = RNA_boolean_get(op->ptr, "report"); + const bool do_single_user = RNA_boolean_get(op->ptr, "single_user"); if (md == NULL) { return OPERATOR_CANCELLED; } + if (do_single_user && ID_REAL_USERS(ob->data) > 1) { + ED_object_single_obdata_user(bmain, scene, ob); + BKE_main_id_newptr_and_tag_clear(bmain); + WM_event_add_notifier(C, NC_WINDOW, NULL); + DEG_relations_tag_update(bmain); + } + int reports_len; char name[MAX_NAME]; if (do_report) { @@ -1449,6 +1446,19 @@ static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *eve { int retval; if (edit_modifier_invoke_properties_with_hover(C, op, event, &retval)) { + PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier); + Object *ob = (ptr.owner_id != NULL) ? (Object *)ptr.owner_id : ED_object_active_context(C); + + if ((ob->data != NULL) && ID_REAL_USERS(ob->data) > 1) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "single_user"); + if (!RNA_property_is_set(op->ptr, prop)) { + RNA_property_boolean_set(op->ptr, prop, true); + } + if (RNA_property_boolean_get(op->ptr, prop)) { + return WM_operator_confirm_message( + C, op, "Make object data single-user and apply modifier"); + } + } return modifier_apply_exec(C, op); } return retval; @@ -1469,6 +1479,13 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot) edit_modifier_properties(ot); edit_modifier_report_property(ot); + + PropertyRNA *prop = RNA_def_boolean(ot->srna, + "single_user", + false, + "Make Data Single User", + "Make the object's data single user if needed"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } /** \} */ @@ -1479,7 +1496,7 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot) static bool modifier_apply_as_shapekey_poll(bContext *C) { - return modifier_apply_poll_ex(C, true); + return modifier_apply_poll(C); } static int modifier_apply_as_shapekey_exec(bContext *C, wmOperator *op) @@ -2781,9 +2798,9 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op) MEM_SAFE_FREE(mmd->dynverts); MEM_SAFE_FREE(mmd->bindweights); /* Deprecated */ MEM_SAFE_FREE(mmd->bindcos); /* Deprecated */ - mmd->totvert = 0; - mmd->totcagevert = 0; - mmd->totinfluence = 0; + mmd->verts_num = 0; + mmd->cage_verts_num = 0; + mmd->influences_num = 0; } else { /* Force modifier to run, it will call binding routine @@ -3119,7 +3136,7 @@ static int laplaciandeform_bind_exec(bContext *C, wmOperator *op) /* This is hard to know from the modifier itself whether the evaluation is * happening for binding or not. So we copy all the required data here. */ - lmd->total_verts = lmd_eval->total_verts; + lmd->verts_num = lmd_eval->verts_num; if (lmd_eval->vertexco == NULL) { MEM_SAFE_FREE(lmd->vertexco); } diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 35f5ede270d..b390cb286ee 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -98,6 +98,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_transform_to_mouse); WM_operatortype_append(OBJECT_OT_effector_add); WM_operatortype_append(OBJECT_OT_collection_instance_add); + WM_operatortype_append(OBJECT_OT_collection_external_asset_drop); WM_operatortype_append(OBJECT_OT_data_instance_add); WM_operatortype_append(OBJECT_OT_metaball_add); WM_operatortype_append(OBJECT_OT_duplicates_make_real); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 3ecf86d14ed..7be46bdb24b 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1350,7 +1350,7 @@ static int make_links_scene_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if (ID_IS_LINKED(scene_to)) { + if (!BKE_id_is_editable(bmain, &scene_to->id)) { BKE_report(op->reports, RPT_ERROR, "Cannot link objects into a linked scene"); return OPERATOR_CANCELLED; } @@ -1481,7 +1481,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op) case MAKE_LINKS_ANIMDATA: BKE_animdata_copy_id(bmain, (ID *)ob_dst, (ID *)ob_src, 0); if (ob_dst->data && ob_src->data) { - if (ID_IS_LINKED(obdata_id)) { + if (!BKE_id_is_editable(bmain, obdata_id)) { is_lib = true; break; } @@ -1525,7 +1525,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op) Curve *cu_src = ob_src->data; Curve *cu_dst = ob_dst->data; - if (ID_IS_LINKED(obdata_id)) { + if (!BKE_id_is_editable(bmain, obdata_id)) { is_lib = true; break; } @@ -1792,7 +1792,7 @@ static void single_obdata_users( ID *id; FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) { - if (!ID_IS_LINKED(ob)) { + if (BKE_id_is_editable(bmain, &ob->id)) { id = ob->data; if (single_data_needs_duplication(id)) { DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); @@ -1893,11 +1893,24 @@ static void single_obdata_users( } } +void ED_object_single_obdata_user(Main *bmain, Scene *scene, Object *ob) +{ + FOREACH_SCENE_OBJECT_BEGIN (scene, ob_iter) { + ob_iter->flag &= ~OB_DONE; + } + FOREACH_SCENE_OBJECT_END; + + /* Tag only the one object. */ + ob->flag |= OB_DONE; + + single_obdata_users(bmain, scene, NULL, NULL, OB_DONE); +} + static void single_object_action_users( Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag) { FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) { - if (!ID_IS_LINKED(ob)) { + if (BKE_id_is_editable(bmain, &ob->id)) { AnimData *adt = BKE_animdata_from_id(&ob->id); if (adt == NULL) { continue; @@ -1917,7 +1930,7 @@ static void single_objectdata_action_users( Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag) { FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) { - if (!ID_IS_LINKED(ob) && ob->data != NULL) { + if (BKE_id_is_editable(bmain, &ob->id) && ob->data != NULL) { ID *id_obdata = (ID *)ob->data; AnimData *adt = BKE_animdata_from_id(id_obdata); if (adt == NULL) { @@ -1941,7 +1954,7 @@ static void single_mat_users( int a; FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) { - if (!ID_IS_LINKED(ob)) { + if (BKE_id_is_editable(bmain, &ob->id)) { for (a = 1; a <= ob->totcol; a++) { ma = BKE_object_material_get(ob, (short)a); if (single_data_needs_duplication(&ma->id)) { @@ -2273,6 +2286,10 @@ static int make_override_library_exec(bContext *C, wmOperator *op) ID *id_root = NULL; bool is_override_instancing_object = false; + GSet *user_overrides_objects_uids = BLI_gset_new( + BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__); + bool user_overrides_from_selected_objects = false; + if (!ID_IS_LINKED(obact) && obact->instance_collection != NULL && ID_IS_LINKED(obact->instance_collection)) { if (!ID_IS_OVERRIDABLE_LIBRARY(obact->instance_collection)) { @@ -2285,6 +2302,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op) id_root = &obact->instance_collection->id; is_override_instancing_object = true; + user_overrides_from_selected_objects = false; } else if (!make_override_library_object_overridable_check(bmain, obact)) { const int i = RNA_property_enum_get(op->ptr, op->type->prop); @@ -2309,16 +2327,53 @@ static int make_override_library_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } id_root = &collection->id; + user_overrides_from_selected_objects = true; } /* Else, poll func ensures us that ID_IS_LINKED(obact) is true. */ else { id_root = &obact->id; + user_overrides_from_selected_objects = true; + } + + if (user_overrides_from_selected_objects) { + /* Only selected objects can be 'user overrides'. */ + FOREACH_SELECTED_OBJECT_BEGIN (view_layer, CTX_wm_view3d(C), ob_iter) { + BLI_gset_add(user_overrides_objects_uids, POINTER_FROM_UINT(ob_iter->id.session_uuid)); + } + FOREACH_SELECTED_OBJECT_END; + } + else { + /* Only armatures inside the root collection (and their children) can be 'user overrides'. */ + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN ((Collection *)id_root, ob_iter) { + if (ob_iter->type == OB_ARMATURE) { + BLI_gset_add(user_overrides_objects_uids, POINTER_FROM_UINT(ob_iter->id.session_uuid)); + } + } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + ID *id_root_override; const bool success = BKE_lib_override_library_create( - bmain, scene, view_layer, NULL, id_root, id_root, &obact->id, NULL); + bmain, scene, view_layer, NULL, id_root, id_root, &obact->id, &id_root_override); + + /* Define liboverrides from selected/validated objects as user defined. */ + ID *id_hierarchy_root_override = id_root_override->override_library->hierarchy_root; + ID *id_iter; + FOREACH_MAIN_ID_BEGIN (bmain, id_iter) { + if (ID_IS_LINKED(id_iter) || !ID_IS_OVERRIDE_LIBRARY_REAL(id_iter) || + id_iter->override_library->hierarchy_root != id_hierarchy_root_override) { + continue; + } + if (BLI_gset_haskey(user_overrides_objects_uids, + POINTER_FROM_UINT(id_iter->override_library->reference->session_uuid))) { + id_iter->override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED; + } + } + FOREACH_MAIN_ID_END; + + BLI_gset_free(user_overrides_objects_uids, NULL); /* Remove the instance empty from this scene, the items now have an overridden collection * instead. */ diff --git a/source/blender/editors/object/object_remesh.cc b/source/blender/editors/object/object_remesh.cc index 2e495ac6147..966df0668ca 100644 --- a/source/blender/editors/object/object_remesh.cc +++ b/source/blender/editors/object/object_remesh.cc @@ -459,7 +459,7 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev op->customdata = cd; /* Select the front facing face of the mesh bounding box. */ - BoundBox *bb = BKE_mesh_boundbox_get(cd->active_object); + const BoundBox *bb = BKE_mesh_boundbox_get(cd->active_object); /* Indices of the Bounding Box faces. */ const int BB_faces[6][4] = { diff --git a/source/blender/editors/object/object_shader_fx.c b/source/blender/editors/object/object_shader_fx.c index 973f4d4561d..dd7fc192dc1 100644 --- a/source/blender/editors/object/object_shader_fx.c +++ b/source/blender/editors/object/object_shader_fx.c @@ -25,6 +25,7 @@ #include "BLT_translation.h" #include "BKE_context.h" +#include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_object.h" #include "BKE_report.h" @@ -278,8 +279,8 @@ static bool edit_shaderfx_poll_generic(bContext *C, CTX_wm_operator_poll_msg_set(C, "Object type is not supported"); return false; } - if (ptr.owner_id != NULL && ID_IS_LINKED(ptr.owner_id)) { - CTX_wm_operator_poll_msg_set(C, "Cannot edit library data"); + if (ptr.owner_id != NULL && !BKE_id_is_editable(CTX_data_main(C), ptr.owner_id)) { + CTX_wm_operator_poll_msg_set(C, "Cannot edit library or override data"); return false; } if (!is_liboverride_allowed && BKE_shaderfx_is_nonlocal_in_liboverride(ob, fx)) { diff --git a/source/blender/editors/object/object_transform.cc b/source/blender/editors/object/object_transform.cc index afd2c048379..235ffb61738 100644 --- a/source/blender/editors/object/object_transform.cc +++ b/source/blender/editors/object/object_transform.cc @@ -587,18 +587,99 @@ static Array<Object *> sorted_selected_editable_objects(bContext *C) return sorted_objects; } +/** + * Check if we need and can handle the special multiuser case. + */ +static bool apply_objects_internal_can_multiuser(bContext *C) +{ + Object *obact = CTX_data_active_object(C); + + if (ELEM(NULL, obact, obact->data)) { + return false; + } + + if (ID_REAL_USERS(obact->data) == 1) { + return false; + } + + bool all_objects_same_data = true; + bool obact_selected = false; + + CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { + if (ob->data != obact->data) { + all_objects_same_data = false; + break; + } + + if (ob == obact) { + obact_selected = true; + } + } + CTX_DATA_END; + + return all_objects_same_data && obact_selected; +} + +/** + * Check if the current selection need to be made into single user. + * + * It assumes that all selected objects share the same object data. + */ +static bool apply_objects_internal_need_single_user(bContext *C) +{ + Object *ob = CTX_data_active_object(C); + BLI_assert(apply_objects_internal_can_multiuser(C)); + + /* Counting the number of objects is valid since it's known the + * selection is only made up of users of the active objects data. */ + return (ID_REAL_USERS(ob->data) > CTX_DATA_COUNT(C, selected_editable_objects)); +} + static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_loc, bool apply_rot, bool apply_scale, - bool do_props) + bool do_props, + bool do_single_user) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); float rsmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale; bool changed = true; + bool const do_multi_user = apply_objects_internal_can_multiuser(C); + float obact_invmat[4][4], obact_parent[4][4], obact_parentinv[4][4]; + + /* Only used when do_multi_user is set. */ + Object *obact = NULL; + bool make_single_user = false; + + if (do_multi_user) { + obact = CTX_data_active_object(C); + invert_m4_m4(obact_invmat, obact->obmat); + + Object workob; + BKE_object_workob_calc_parent(depsgraph, scene, obact, &workob); + copy_m4_m4(obact_parent, workob.obmat); + copy_m4_m4(obact_parentinv, obact->parentinv); + + if (apply_objects_internal_need_single_user(C)) { + if (do_single_user) { + make_single_user = true; + } + else { + ID *obact_data = static_cast<ID *>(obact->data); + BKE_reportf(reports, + RPT_ERROR, + "Cannot apply to a multi user: Object \"%s\", %s \"%s\", aborting", + obact->id.name + 2, + BKE_idtype_idcode_to_name(GS(obact_data->name)), + obact_data->name + 2); + return OPERATOR_CANCELLED; + } + } + } /* first check if we can execute */ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { @@ -612,7 +693,7 @@ static int apply_objects_internal(bContext *C, OB_FONT, OB_GPENCIL)) { ID *obdata = static_cast<ID *>(ob->data); - if (ID_REAL_USERS(obdata) > 1) { + if (!do_multi_user && ID_REAL_USERS(obdata) > 1) { BKE_reportf(reports, RPT_ERROR, R"(Cannot apply to a multi user: Object "%s", %s "%s", aborting)", @@ -622,10 +703,10 @@ static int apply_objects_internal(bContext *C, changed = false; } - if (ID_IS_LINKED(obdata)) { + if (ID_IS_LINKED(obdata) || ID_IS_OVERRIDE_LIBRARY(obdata)) { BKE_reportf(reports, RPT_ERROR, - R"(Cannot apply to library data: Object "%s", %s "%s", aborting)", + R"(Cannot apply to library or override data: Object "%s", %s "%s", aborting)", ob->id.name + 2, BKE_idtype_idcode_to_name(GS(obdata->name)), obdata->name + 2); @@ -728,6 +809,15 @@ static int apply_objects_internal(bContext *C, changed = false; /* now execute */ + + if (make_single_user) { + /* Make single user. */ + ED_object_single_obdata_user(bmain, scene, obact); + BKE_main_id_newptr_and_tag_clear(bmain); + WM_event_add_notifier(C, NC_WINDOW, NULL); + DEG_relations_tag_update(bmain); + } + Array<Object *> objects = sorted_selected_editable_objects(C); if (objects.is_empty()) { return OPERATOR_CANCELLED; @@ -774,7 +864,14 @@ static int apply_objects_internal(bContext *C, } /* apply to object data */ - if (ob->type == OB_MESH) { + if (do_multi_user && ob != obact) { + /* Don't apply, just set the new object data, the correct + * transformations will happen later. */ + id_us_min((ID *)ob->data); + ob->data = obact->data; + id_us_plus((ID *)ob->data); + } + else if (ob->type == OB_MESH) { Mesh *me = static_cast<Mesh *>(ob->data); if (apply_scale) { @@ -882,16 +979,53 @@ static int apply_objects_internal(bContext *C, continue; } - if (apply_loc) { - zero_v3(ob->loc); - } - if (apply_scale) { - ob->scale[0] = ob->scale[1] = ob->scale[2] = 1.0f; + if (do_multi_user && ob != obact) { + float _obmat[4][4], _iobmat[4][4]; + float _mat[4][4]; + + copy_m4_m4(_obmat, ob->obmat); + invert_m4_m4(_iobmat, _obmat); + + copy_m4_m4(_mat, _obmat); + mul_m4_m4_post(_mat, obact_invmat); + mul_m4_m4_post(_mat, obact_parent); + mul_m4_m4_post(_mat, obact_parentinv); + + if (apply_loc && apply_scale && apply_rot) { + BKE_object_apply_mat4(ob, _mat, false, true); + } + else { + Object ob_temp = blender::dna::shallow_copy(*ob); + BKE_object_apply_mat4(&ob_temp, _mat, false, true); + + if (apply_loc) { + copy_v3_v3(ob->loc, ob_temp.loc); + } + + if (apply_scale) { + copy_v3_v3(ob->scale, ob_temp.scale); + } + + if (apply_rot) { + copy_v4_v4(ob->quat, ob_temp.quat); + copy_v3_v3(ob->rot, ob_temp.rot); + copy_v3_v3(ob->rotAxis, ob_temp.rotAxis); + ob->rotAngle = ob_temp.rotAngle; + } + } } - if (apply_rot) { - zero_v3(ob->rot); - unit_qt(ob->quat); - unit_axis_angle(ob->rotAxis, &ob->rotAngle); + else { + if (apply_loc) { + zero_v3(ob->loc); + } + if (apply_scale) { + ob->scale[0] = ob->scale[1] = ob->scale[2] = 1.0f; + } + if (apply_rot) { + zero_v3(ob->rot); + unit_qt(ob->quat); + unit_axis_angle(ob->rotAxis, &ob->rotAngle); + } } Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); @@ -969,14 +1103,35 @@ static int object_transform_apply_exec(bContext *C, wmOperator *op) const bool rot = RNA_boolean_get(op->ptr, "rotation"); const bool sca = RNA_boolean_get(op->ptr, "scale"); const bool do_props = RNA_boolean_get(op->ptr, "properties"); + const bool do_single_user = RNA_boolean_get(op->ptr, "isolate_users"); if (loc || rot || sca) { - return apply_objects_internal(C, op->reports, loc, rot, sca, do_props); + return apply_objects_internal(C, op->reports, loc, rot, sca, do_props, do_single_user); } /* allow for redo */ return OPERATOR_FINISHED; } +static int object_transform_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + Object *ob = ED_object_active_context(C); + + bool can_handle_multiuser = apply_objects_internal_can_multiuser(C); + bool need_single_user = can_handle_multiuser && apply_objects_internal_need_single_user(C); + + if ((ob->data != NULL) && need_single_user) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "isolate_users"); + if (!RNA_property_is_set(op->ptr, prop)) { + RNA_property_boolean_set(op->ptr, prop, true); + } + if (RNA_property_boolean_get(op->ptr, prop)) { + return WM_operator_confirm_message( + C, op, "Create new object-data users and apply transformation"); + } + } + return object_transform_apply_exec(C, op); +} + void OBJECT_OT_transform_apply(wmOperatorType *ot) { /* identifiers */ @@ -986,6 +1141,7 @@ void OBJECT_OT_transform_apply(wmOperatorType *ot) /* api callbacks */ ot->exec = object_transform_apply_exec; + ot->invoke = object_transform_apply_invoke; ot->poll = ED_operator_objectmode; /* flags */ @@ -999,6 +1155,13 @@ void OBJECT_OT_transform_apply(wmOperatorType *ot) true, "Apply Properties", "Modify properties such as curve vertex radius, font size and bone envelope"); + PropertyRNA *prop = RNA_def_boolean(ot->srna, + "isolate_users", + false, + "Isolate Multi User Data", + "Create new object-data users if needed"); + RNA_def_property_flag(prop, PROP_HIDDEN); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /** \} */ @@ -1100,12 +1263,12 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) } /* reset flags */ - for (int object_index = 0; object_index < objects.size(); object_index++) { + for (const int object_index : objects.index_range()) { Object *ob = objects[object_index]; ob->flag &= ~OB_DONE; /* move active first */ - if (ob == obact) { + if (ob == obact && objects.size() > 1) { memmove(&objects[1], objects.data(), object_index * sizeof(Object *)); objects[0] = ob; } @@ -1138,7 +1301,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) /* Special support for instanced collections. */ if ((ob->transflag & OB_DUPLICOLLECTION) && ob->instance_collection && (ob->instance_collection->id.tag & LIB_TAG_DOIT) == 0) { - if (ID_IS_LINKED(ob->instance_collection)) { + if (!BKE_id_is_editable(bmain, &ob->instance_collection->id)) { tot_lib_error++; } else { @@ -1163,7 +1326,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) } } } - else if (ID_IS_LINKED(ob->data)) { + else if (ID_IS_LINKED(ob->data) || ID_IS_OVERRIDE_LIBRARY(ob->data)) { tot_lib_error++; } else if (ob->type == OB_MESH) { diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index f0fa693bd85..a58ffa4e0a6 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -3062,7 +3062,7 @@ static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_context(C); - if (!ob || ID_IS_LINKED(ob)) { + if (!ob || ID_IS_LINKED(ob) || ID_IS_OVERRIDE_LIBRARY(ob)) { return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 4a639e227f7..eba647a1b17 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -5406,10 +5406,10 @@ static bool particle_edit_toggle_poll(bContext *C) Object *ob = CTX_data_active_object(C); if (ob == NULL || ob->type != OB_MESH) { - return 0; + return false; } - if (!ob->data || ID_IS_LINKED(ob->data)) { - return 0; + if (!ob->data || ID_IS_LINKED(ob->data) || ID_IS_OVERRIDE_LIBRARY(ob->data)) { + return false; } return ED_object_particle_edit_mode_supported(ob); diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index 24860b9c4d8..6bea6e2c19e 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -1048,7 +1048,7 @@ static void remove_particle_systems_from_object(Object *ob_to) if (ob_to->type != OB_MESH) { return; } - if (!ob_to->data || ID_IS_LINKED(ob_to->data)) { + if (!ob_to->data || ID_IS_LINKED(ob_to->data) || ID_IS_OVERRIDE_LIBRARY(ob_to->data)) { return; } @@ -1090,7 +1090,7 @@ static bool copy_particle_systems_to_object(const bContext *C, if (ob_to->type != OB_MESH) { return false; } - if (!ob_to->data || ID_IS_LINKED(ob_to->data)) { + if (!ob_to->data || !BKE_id_is_editable(bmain, ob_to->data)) { return false; } diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c index eb799f46177..66ae2d323fd 100644 --- a/source/blender/editors/physics/rigidbody_constraint.c +++ b/source/blender/editors/physics/rigidbody_constraint.c @@ -40,12 +40,21 @@ /* ********************************************** */ /* Helper API's for RigidBody Constraint Editing */ +static bool operator_rigidbody_constraints_editable_poll(Scene *scene) +{ + if (scene == NULL || ID_IS_LINKED(scene) || ID_IS_OVERRIDE_LIBRARY(scene) || + (scene->rigidbody_world != NULL && scene->rigidbody_world->constraints != NULL && + (ID_IS_LINKED(scene->rigidbody_world->constraints) || + ID_IS_OVERRIDE_LIBRARY(scene->rigidbody_world->constraints)))) { + return false; + } + return true; +} + static bool ED_operator_rigidbody_con_active_poll(bContext *C) { Scene *scene = CTX_data_scene(C); - if (scene == NULL || ID_IS_LINKED(&scene->id) || - (scene->rigidbody_world != NULL && scene->rigidbody_world->constraints != NULL && - ID_IS_LINKED(&scene->rigidbody_world->constraints->id))) { + if (!operator_rigidbody_constraints_editable_poll(scene)) { return false; } @@ -59,9 +68,7 @@ static bool ED_operator_rigidbody_con_active_poll(bContext *C) static bool ED_operator_rigidbody_con_add_poll(bContext *C) { Scene *scene = CTX_data_scene(C); - if (scene == NULL || ID_IS_LINKED(&scene->id) || - (scene->rigidbody_world != NULL && scene->rigidbody_world->constraints != NULL && - ID_IS_LINKED(&scene->rigidbody_world->constraints->id))) { + if (!operator_rigidbody_constraints_editable_poll(scene)) { return false; } return ED_operator_object_active_editable(C); diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c index 8f69947ceb0..5ff687bce1a 100644 --- a/source/blender/editors/physics/rigidbody_object.c +++ b/source/blender/editors/physics/rigidbody_object.c @@ -44,12 +44,21 @@ /* ********************************************** */ /* Helper API's for RigidBody Objects Editing */ +static bool operator_rigidbody_editable_poll(Scene *scene) +{ + if (scene == NULL || ID_IS_LINKED(scene) || ID_IS_OVERRIDE_LIBRARY(scene) || + (scene->rigidbody_world != NULL && scene->rigidbody_world->group != NULL && + (ID_IS_LINKED(scene->rigidbody_world->group) || + ID_IS_OVERRIDE_LIBRARY(scene->rigidbody_world->group)))) { + return false; + } + return true; +} + static bool ED_operator_rigidbody_active_poll(bContext *C) { Scene *scene = CTX_data_scene(C); - if (scene == NULL || ID_IS_LINKED(&scene->id) || - (scene->rigidbody_world != NULL && scene->rigidbody_world->group != NULL && - ID_IS_LINKED(&scene->rigidbody_world->group->id))) { + if (!operator_rigidbody_editable_poll(scene)) { return false; } @@ -57,15 +66,14 @@ static bool ED_operator_rigidbody_active_poll(bContext *C) Object *ob = ED_object_active_context(C); return (ob && ob->rigidbody_object); } - return 0; + + return false; } static bool ED_operator_rigidbody_add_poll(bContext *C) { Scene *scene = CTX_data_scene(C); - if (scene == NULL || ID_IS_LINKED(&scene->id) || - (scene->rigidbody_world != NULL && scene->rigidbody_world->group != NULL && - ID_IS_LINKED(&scene->rigidbody_world->group->id))) { + if (!operator_rigidbody_editable_poll(scene)) { return false; } @@ -73,6 +81,7 @@ static bool ED_operator_rigidbody_add_poll(bContext *C) Object *ob = ED_object_active_context(C); return (ob && ob->type == OB_MESH); } + return false; } diff --git a/source/blender/editors/physics/rigidbody_world.c b/source/blender/editors/physics/rigidbody_world.c index fa90d1e64d6..a77d70d5d9b 100644 --- a/source/blender/editors/physics/rigidbody_world.c +++ b/source/blender/editors/physics/rigidbody_world.c @@ -192,7 +192,7 @@ void RIGIDBODY_OT_world_export(wmOperatorType *ot) FILE_TYPE_FOLDER, FILE_SPECIAL, FILE_SAVE, - FILE_RELPATH, + WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_DEFAULT); } diff --git a/source/blender/editors/render/render_intern.hh b/source/blender/editors/render/render_intern.hh index fc40fb06851..4135a0d97a9 100644 --- a/source/blender/editors/render/render_intern.hh +++ b/source/blender/editors/render/render_intern.hh @@ -33,6 +33,8 @@ void SCENE_OT_view_layer_add(struct wmOperatorType *ot); void SCENE_OT_view_layer_remove(struct wmOperatorType *ot); void SCENE_OT_view_layer_add_aov(struct wmOperatorType *ot); void SCENE_OT_view_layer_remove_aov(struct wmOperatorType *ot); +void SCENE_OT_view_layer_add_lightgroup(struct wmOperatorType *ot); +void SCENE_OT_view_layer_remove_lightgroup(struct wmOperatorType *ot); void SCENE_OT_light_cache_bake(struct wmOperatorType *ot); void SCENE_OT_light_cache_free(struct wmOperatorType *ot); diff --git a/source/blender/editors/render/render_ops.cc b/source/blender/editors/render/render_ops.cc index 1583ce44ee5..f671b2f950d 100644 --- a/source/blender/editors/render/render_ops.cc +++ b/source/blender/editors/render/render_ops.cc @@ -39,6 +39,8 @@ void ED_operatortypes_render() WM_operatortype_append(SCENE_OT_view_layer_remove); WM_operatortype_append(SCENE_OT_view_layer_add_aov); WM_operatortype_append(SCENE_OT_view_layer_remove_aov); + WM_operatortype_append(SCENE_OT_view_layer_add_lightgroup); + WM_operatortype_append(SCENE_OT_view_layer_remove_lightgroup); WM_operatortype_append(SCENE_OT_render_view_add); WM_operatortype_append(SCENE_OT_render_view_remove); diff --git a/source/blender/editors/render/render_preview.cc b/source/blender/editors/render/render_preview.cc index ef0f0b6225c..7404b3bf010 100644 --- a/source/blender/editors/render/render_preview.cc +++ b/source/blender/editors/render/render_preview.cc @@ -374,6 +374,14 @@ static ID *duplicate_ids(ID *id, const bool allow_failure) LIB_ID_COPY_NO_ANIMDATA); return id_copy; } + case ID_GR: { + /* Doesn't really duplicate the collection. Just creates a collection instance empty. */ + BLI_assert(BKE_previewimg_id_supports_jobs(id)); + Object *instance_empty = BKE_object_add_only_object(nullptr, OB_EMPTY, nullptr); + instance_empty->instance_collection = (Collection *)id; + instance_empty->transflag |= OB_DUPLICOLLECTION; + return &instance_empty->id; + } /* These support threading, but don't need duplicating. */ case ID_IM: case ID_BR: @@ -884,6 +892,44 @@ static void object_preview_render(IconPreview *preview, IconPreviewSize *preview /** \} */ /* -------------------------------------------------------------------- */ +/** \name Collection Preview + * + * For the most part this reuses the object preview code by creating an instance collection empty + * object and rendering that. + * + * \{ */ + +/** + * Check if the collection contains any geometry that can be rendered. Otherwise there's nothing to + * display in the preview, so don't generate one. + * Objects and sub-collections hidden in the render will be skipped. + */ +static bool collection_preview_contains_geometry_recursive(const Collection *collection) +{ + LISTBASE_FOREACH (CollectionObject *, col_ob, &collection->gobject) { + if (col_ob->ob->visibility_flag & OB_HIDE_RENDER) { + continue; + } + if (OB_TYPE_IS_GEOMETRY(col_ob->ob->type)) { + return true; + } + } + + LISTBASE_FOREACH (CollectionChild *, child_col, &collection->children) { + if (child_col->collection->flag & COLLECTION_HIDE_RENDER) { + continue; + } + if (collection_preview_contains_geometry_recursive(child_col->collection)) { + return true; + } + } + + return false; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Action Preview * \{ */ @@ -1577,6 +1623,12 @@ static void icon_preview_startjob_all_sizes(void *customdata, continue; } break; + case ID_GR: + BLI_assert(collection_preview_contains_geometry_recursive((Collection *)ip->id)); + /* A collection instance empty was created, so this can just reuse the object preview + * rendering. */ + object_preview_render(ip, cur_size); + continue; case ID_AC: action_preview_render(ip, cur_size); continue; @@ -1868,6 +1920,9 @@ bool ED_preview_id_is_supported(const ID *id) if (GS(id->name) == ID_OB) { return object_preview_is_type_supported((const Object *)id); } + if (GS(id->name) == ID_GR) { + return collection_preview_contains_geometry_recursive((const Collection *)id); + } return BKE_previewimg_id_get_p(id) != nullptr; } diff --git a/source/blender/editors/render/render_shading.cc b/source/blender/editors/render/render_shading.cc index f48ac99fe75..07a07b462ef 100644 --- a/source/blender/editors/render/render_shading.cc +++ b/source/blender/editors/render/render_shading.cc @@ -1115,6 +1115,86 @@ void SCENE_OT_view_layer_remove_aov(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ +/** \name View Layer Add Lightgroup Operator + * \{ */ + +static int view_layer_add_lightgroup_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + + BKE_view_layer_add_lightgroup(view_layer); + + if (scene->nodetree) { + ntreeCompositUpdateRLayers(scene->nodetree); + } + + DEG_id_tag_update(&scene->id, 0); + DEG_relations_tag_update(CTX_data_main(C)); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); + + return OPERATOR_FINISHED; +} + +void SCENE_OT_view_layer_add_lightgroup(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Lightgroup"; + ot->idname = "SCENE_OT_view_layer_add_lightgroup"; + ot->description = "Add a Light Group"; + + /* api callbacks */ + ot->exec = view_layer_add_lightgroup_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Layer Remove Lightgroup Operator + * \{ */ + +static int view_layer_remove_lightgroup_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + + if (view_layer->active_lightgroup == nullptr) { + return OPERATOR_FINISHED; + } + + BKE_view_layer_remove_lightgroup(view_layer, view_layer->active_lightgroup); + + if (scene->nodetree) { + ntreeCompositUpdateRLayers(scene->nodetree); + } + + DEG_id_tag_update(&scene->id, 0); + DEG_relations_tag_update(CTX_data_main(C)); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); + + return OPERATOR_FINISHED; +} + +void SCENE_OT_view_layer_remove_lightgroup(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Lightgroup"; + ot->idname = "SCENE_OT_view_layer_remove_lightgroup"; + ot->description = "Remove Active Lightgroup"; + + /* api callbacks */ + ot->exec = view_layer_remove_lightgroup_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Light Cache Bake Operator * \{ */ diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c index dbdd0957d4b..6406b0d9d52 100644 --- a/source/blender/editors/screen/screen_draw.c +++ b/source/blender/editors/screen/screen_draw.c @@ -173,7 +173,7 @@ void ED_screen_draw_edges(wmWindow *win) BLI_rcti_do_minmax_v(&scissor_rect, (int[2]){area->v3->vec.x, area->v3->vec.y}); } - if (GPU_type_matches(GPU_DEVICE_INTEL_UHD, GPU_OS_UNIX, GPU_DRIVER_ANY)) { + if (GPU_type_matches_ex(GPU_DEVICE_INTEL_UHD, GPU_OS_UNIX, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) { /* For some reason, on linux + Intel UHD Graphics 620 the driver * hangs if we don't flush before this. (See T57455) */ GPU_flush(); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index d3cb6942892..408ddfe7241 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -177,10 +177,10 @@ bool ED_operator_scene(bContext *C) bool ED_operator_scene_editable(bContext *C) { Scene *scene = CTX_data_scene(C); - if (scene && !ID_IS_LINKED(scene)) { - return true; + if (scene == NULL || !BKE_id_is_editable(CTX_data_main(C), &scene->id)) { + return false; } - return false; + return true; } bool ED_operator_objectmode(bContext *C) @@ -319,7 +319,7 @@ bool ED_operator_node_editable(bContext *C) { SpaceNode *snode = CTX_wm_space_node(C); - if (snode && snode->edittree && !ID_IS_LINKED(snode->edittree)) { + if (snode && snode->edittree && BKE_id_is_editable(CTX_data_main(C), &snode->edittree->id)) { return true; } @@ -380,8 +380,8 @@ bool ED_operator_object_active_editable_ex(bContext *C, const Object *ob) return false; } - if (ID_IS_LINKED(ob)) { - CTX_wm_operator_poll_msg_set(C, "Cannot edit library linked object"); + if (!BKE_id_is_editable(CTX_data_main(C), (ID *)ob)) { + CTX_wm_operator_poll_msg_set(C, "Cannot edit library linked or non-editable override object"); return false; } @@ -546,9 +546,10 @@ bool ED_operator_posemode(bContext *C) bool ED_operator_posemode_local(bContext *C) { if (ED_operator_posemode(C)) { + Main *bmain = CTX_data_main(C); Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); bArmature *arm = ob->data; - return !(ID_IS_LINKED(&ob->id) || ID_IS_LINKED(&arm->id)); + return (BKE_id_is_editable(bmain, &ob->id) && BKE_id_is_editable(bmain, &arm->id)); } return false; } diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc b/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc index 682cd3b47ca..1fb3931e00f 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc @@ -36,6 +36,14 @@ #include "ED_screen.h" #include "ED_view3d.h" +/** + * The code below uses a prefix naming convention to indicate the coordinate space: + * - `cu`: Local space of the curves object that is being edited. + * - `su`: Local space of the surface object. + * - `wo`: World space. + * - `re`: 2D coordinates within the region. + */ + namespace blender::ed::sculpt_paint { using blender::bke::CurvesGeometry; @@ -45,116 +53,231 @@ using blender::bke::CurvesGeometry; */ class SnakeHookOperation : public CurvesSculptStrokeOperation { private: - float2 last_mouse_position_; + float2 last_mouse_position_re_; + + CurvesBrush3D brush_3d_; + + friend struct SnakeHookOperatorExecutor; public: - void on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension) override + void on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension) override; +}; + +/** + * Utility class that actually executes the update when the stroke is updated. That's useful + * because it avoids passing a very large number of parameters between functions. + */ +struct SnakeHookOperatorExecutor { + SnakeHookOperation *self_ = nullptr; + bContext *C_ = nullptr; + Scene *scene_ = nullptr; + Object *object_ = nullptr; + ARegion *region_ = nullptr; + View3D *v3d_ = nullptr; + RegionView3D *rv3d_ = nullptr; + + CurvesSculpt *curves_sculpt_ = nullptr; + Brush *brush_ = nullptr; + float brush_radius_re_; + float brush_strength_; + eBrushFalloffShape falloff_shape_; + + Curves *curves_id_ = nullptr; + CurvesGeometry *curves_ = nullptr; + + float4x4 curves_to_world_mat_; + float4x4 world_to_curves_mat_; + + float2 brush_pos_prev_re_; + float2 brush_pos_re_; + float2 brush_pos_diff_re_; + + void execute(SnakeHookOperation &self, bContext *C, const StrokeExtension &stroke_extension) { - BLI_SCOPED_DEFER([&]() { last_mouse_position_ = stroke_extension.mouse_position; }); + BLI_SCOPED_DEFER([&]() { self.last_mouse_position_re_ = stroke_extension.mouse_position; }); + + self_ = &self; + C_ = C; + scene_ = CTX_data_scene(C); + object_ = CTX_data_active_object(C); + region_ = CTX_wm_region(C); + v3d_ = CTX_wm_view3d(C); + rv3d_ = CTX_wm_region_view3d(C); + + curves_sculpt_ = scene_->toolsettings->curves_sculpt; + brush_ = BKE_paint_brush(&curves_sculpt_->paint); + brush_radius_re_ = BKE_brush_size_get(scene_, brush_); + brush_strength_ = BKE_brush_alpha_get(scene_, brush_); + falloff_shape_ = static_cast<eBrushFalloffShape>(brush_->falloff_shape); + + curves_to_world_mat_ = object_->obmat; + world_to_curves_mat_ = curves_to_world_mat_.inverted(); + + curves_id_ = static_cast<Curves *>(object_->data); + curves_ = &CurvesGeometry::wrap(curves_id_->geometry); + + brush_pos_prev_re_ = self.last_mouse_position_re_; + brush_pos_re_ = stroke_extension.mouse_position; + brush_pos_diff_re_ = brush_pos_re_ - brush_pos_prev_re_; if (stroke_extension.is_first) { + if (falloff_shape_ == PAINT_FALLOFF_SHAPE_SPHERE) { + std::optional<CurvesBrush3D> brush_3d = sample_curves_3d_brush( + *C_, *object_, brush_pos_re_, brush_radius_re_); + if (brush_3d.has_value()) { + self_->brush_3d_ = *brush_3d; + } + } return; } - Scene &scene = *CTX_data_scene(C); - Object &object = *CTX_data_active_object(C); - ARegion *region = CTX_wm_region(C); - View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d = CTX_wm_region_view3d(C); + if (falloff_shape_ == PAINT_FALLOFF_SHAPE_SPHERE) { + this->spherical_snake_hook(); + } + else if (falloff_shape_ == PAINT_FALLOFF_SHAPE_TUBE) { + this->projected_snake_hook(); + } + else { + BLI_assert_unreachable(); + } - CurvesSculpt &curves_sculpt = *scene.toolsettings->curves_sculpt; - Brush &brush = *BKE_paint_brush(&curves_sculpt.paint); - const float brush_radius = BKE_brush_size_get(&scene, &brush); - const float brush_strength = BKE_brush_alpha_get(&scene, &brush); + curves_->tag_positions_changed(); + DEG_id_tag_update(&curves_id_->id, ID_RECALC_GEOMETRY); + ED_region_tag_redraw(region_); + } - const float4x4 ob_mat = object.obmat; - const float4x4 ob_imat = ob_mat.inverted(); + void projected_snake_hook() + { + MutableSpan<float3> positions_cu = curves_->positions(); float4x4 projection; - ED_view3d_ob_project_mat_get(rv3d, &object, projection.values); + ED_view3d_ob_project_mat_get(rv3d_, object_, projection.values); - Curves &curves_id = *static_cast<Curves *>(object.data); - CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry); - MutableSpan<float3> positions = curves.positions(); + threading::parallel_for(curves_->curves_range(), 256, [&](const IndexRange curves_range) { + for (const int curve_i : curves_range) { + const IndexRange points = curves_->points_for_curve(curve_i); + const int last_point_i = points.last(); + const float3 old_pos_cu = positions_cu[last_point_i]; - const float2 mouse_prev = last_mouse_position_; - const float2 mouse_cur = stroke_extension.mouse_position; - const float2 mouse_diff = mouse_cur - mouse_prev; + float2 old_pos_re; + ED_view3d_project_float_v2_m4(region_, old_pos_cu, old_pos_re, projection.values); - threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange curves_range) { - for (const int curve_i : curves_range) { - const IndexRange curve_points = curves.points_for_curve(curve_i); - const int last_point_i = curve_points.last(); + const float distance_to_brush_re = math::distance(old_pos_re, brush_pos_prev_re_); + if (distance_to_brush_re > brush_radius_re_) { + continue; + } - const float3 old_position = positions[last_point_i]; + const float radius_falloff = BKE_brush_curve_strength( + brush_, distance_to_brush_re, brush_radius_re_); + const float weight = brush_strength_ * radius_falloff; - float2 old_position_screen; - ED_view3d_project_float_v2_m4( - region, old_position, old_position_screen, projection.values); + const float2 new_position_re = old_pos_re + brush_pos_diff_re_ * weight; + float3 new_position_wo; + ED_view3d_win_to_3d( + v3d_, region_, curves_to_world_mat_ * old_pos_cu, new_position_re, new_position_wo); + const float3 new_position_cu = world_to_curves_mat_ * new_position_wo; - const float distance_screen = math::distance(old_position_screen, mouse_prev); - if (distance_screen > brush_radius) { + this->move_last_point_and_resample(positions_cu.slice(points), new_position_cu); + } + }); + } + + void spherical_snake_hook() + { + MutableSpan<float3> positions_cu = curves_->positions(); + + float4x4 projection; + ED_view3d_ob_project_mat_get(rv3d_, object_, projection.values); + + float3 brush_start_wo, brush_end_wo; + ED_view3d_win_to_3d(v3d_, + region_, + curves_to_world_mat_ * self_->brush_3d_.position_cu, + brush_pos_prev_re_, + brush_start_wo); + ED_view3d_win_to_3d(v3d_, + region_, + curves_to_world_mat_ * self_->brush_3d_.position_cu, + brush_pos_re_, + brush_end_wo); + const float3 brush_start_cu = world_to_curves_mat_ * brush_start_wo; + const float3 brush_end_cu = world_to_curves_mat_ * brush_end_wo; + const float3 brush_diff_cu = brush_end_cu - brush_start_cu; + + const float brush_radius_cu = self_->brush_3d_.radius_cu; + const float brush_radius_sq_cu = pow2f(brush_radius_cu); + + threading::parallel_for(curves_->curves_range(), 256, [&](const IndexRange curves_range) { + for (const int curve_i : curves_range) { + const IndexRange points = curves_->points_for_curve(curve_i); + const int last_point_i = points.last(); + const float3 old_pos_cu = positions_cu[last_point_i]; + + const float distance_to_brush_sq_cu = dist_squared_to_line_segment_v3( + old_pos_cu, brush_start_cu, brush_end_cu); + if (distance_to_brush_sq_cu > brush_radius_sq_cu) { continue; } - const float radius_falloff = pow2f(1.0f - distance_screen / brush_radius); - const float weight = brush_strength * radius_falloff; + const float distance_to_brush_cu = std::sqrt(distance_to_brush_sq_cu); + + const float radius_falloff = BKE_brush_curve_strength( + brush_, distance_to_brush_cu, brush_radius_cu); + const float weight = brush_strength_ * radius_falloff; - const float2 new_position_screen = old_position_screen + mouse_diff * weight; - float3 new_position; - ED_view3d_win_to_3d(v3d, region, ob_mat * old_position, new_position_screen, new_position); - new_position = ob_imat * new_position; + const float3 new_pos_cu = old_pos_cu + weight * brush_diff_cu; - this->move_last_point_and_resample(positions, curve_points, new_position); + this->move_last_point_and_resample(positions_cu.slice(points), new_pos_cu); } }); - - curves.tag_positions_changed(); - DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY); - ED_region_tag_redraw(region); } - void move_last_point_and_resample(MutableSpan<float3> positions, - const IndexRange curve_points, - const float3 &new_last_point_position) const + void move_last_point_and_resample(MutableSpan<float3> positions_cu, + const float3 &new_last_point_position_cu) const { - Vector<float> old_lengths; - old_lengths.append(0.0f); + Vector<float> old_lengths_cu; + old_lengths_cu.append(0.0f); /* Used to (1) normalize the segment sizes over time and (2) support making zero-length * segments */ const float extra_length = 0.001f; - for (const int segment_i : IndexRange(curve_points.size() - 1)) { - const float3 &p1 = positions[curve_points[segment_i]]; - const float3 &p2 = positions[curve_points[segment_i] + 1]; - const float length = math::distance(p1, p2); - old_lengths.append(old_lengths.last() + length + extra_length); + for (const int segment_i : IndexRange(positions_cu.size() - 1)) { + const float3 &p1_cu = positions_cu[segment_i]; + const float3 &p2_cu = positions_cu[segment_i + 1]; + const float length_cu = math::distance(p1_cu, p2_cu); + old_lengths_cu.append(old_lengths_cu.last() + length_cu + extra_length); } Vector<float> point_factors; - for (float &old_length : old_lengths) { - point_factors.append(old_length / old_lengths.last()); + for (float &old_length_cu : old_lengths_cu) { + point_factors.append(old_length_cu / old_lengths_cu.last()); } PolySpline new_spline; - new_spline.resize(curve_points.size()); - MutableSpan<float3> new_spline_positions = new_spline.positions(); - for (const int i : IndexRange(curve_points.size() - 1)) { - new_spline_positions[i] = positions[curve_points[i]]; + new_spline.resize(positions_cu.size()); + MutableSpan<float3> new_spline_positions_cu = new_spline.positions(); + for (const int i : IndexRange(positions_cu.size() - 1)) { + new_spline_positions_cu[i] = positions_cu[i]; } - new_spline_positions.last() = new_last_point_position; + new_spline_positions_cu.last() = new_last_point_position_cu; new_spline.mark_cache_invalid(); - for (const int i : IndexRange(curve_points.size())) { + for (const int i : positions_cu.index_range()) { const float factor = point_factors[i]; const Spline::LookupResult lookup = new_spline.lookup_evaluated_factor(factor); const float index_factor = lookup.evaluated_index + lookup.factor; - float3 p; + float3 p_cu; new_spline.sample_with_index_factors<float3>( - new_spline_positions, {&index_factor, 1}, {&p, 1}); - positions[curve_points[i]] = p; + new_spline_positions_cu, {&index_factor, 1}, {&p_cu, 1}); + positions_cu[i] = p_cu; } } }; +void SnakeHookOperation::on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension) +{ + SnakeHookOperatorExecutor executor; + executor.execute(*this, C, stroke_extension); +} + std::unique_ptr<CurvesSculptStrokeOperation> new_snake_hook_operation() { return std::make_unique<SnakeHookOperation>(); diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 37bc8b462aa..861da185975 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -1039,7 +1039,7 @@ static void cursor_draw_tiling_preview(const uint gpuattr, Object *ob, const float radius) { - BoundBox *bb = BKE_object_boundbox_get(ob); + const BoundBox *bb = BKE_object_boundbox_get(ob); float orgLoc[3], location[3]; int tile_pass = 0; int start[3]; diff --git a/source/blender/editors/sculpt_paint/paint_image.cc b/source/blender/editors/sculpt_paint/paint_image.cc index 0c73c2e1f43..572e5b78b74 100644 --- a/source/blender/editors/sculpt_paint/paint_image.cc +++ b/source/blender/editors/sculpt_paint/paint_image.cc @@ -272,7 +272,8 @@ static bool image_paint_poll_ex(bContext *C, bool check_tool) SpaceImage *sima = CTX_wm_space_image(C); if (sima) { - if (sima->image != nullptr && ID_IS_LINKED(sima->image)) { + if (sima->image != nullptr && + (ID_IS_LINKED(sima->image) || ID_IS_OVERRIDE_LIBRARY(sima->image))) { return false; } ARegion *region = CTX_wm_region(C); @@ -850,7 +851,7 @@ static bool texture_paint_toggle_poll(bContext *C) if (ob == nullptr || ob->type != OB_MESH) { return false; } - if (!ob->data || ID_IS_LINKED(ob->data)) { + if (ob->data == nullptr || ID_IS_LINKED(ob->data) || ID_IS_OVERRIDE_LIBRARY(ob->data)) { return false; } diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 12215083eb6..233cfc3b33d 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -6332,7 +6332,7 @@ bool ED_paint_proj_mesh_data_check( for (int i = 1; i < ob->totcol + 1; i++) { Material *ma = BKE_object_material_get(ob, i); - if (ma && !ID_IS_LINKED(ma)) { + if (ma && !ID_IS_LINKED(ma) && !ID_IS_OVERRIDE_LIBRARY(ma)) { hasmat = true; if (ma->texpaintslot == NULL) { /* refresh here just in case */ @@ -6340,7 +6340,8 @@ bool ED_paint_proj_mesh_data_check( } if (ma->texpaintslot != NULL && (ma->texpaintslot[ma->paint_active_slot].ima == NULL || - !ID_IS_LINKED(ma->texpaintslot[ma->paint_active_slot].ima))) { + !ID_IS_LINKED(ma->texpaintslot[ma->paint_active_slot].ima) || + !ID_IS_OVERRIDE_LIBRARY(ma->texpaintslot[ma->paint_active_slot].ima))) { hastex = true; break; } diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index e2f8d81fe13..c4d80d38100 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -1404,7 +1404,7 @@ static bool paint_mode_toggle_poll_test(bContext *C) if (ob == NULL || ob->type != OB_MESH) { return false; } - if (!ob->data || ID_IS_LINKED(ob->data)) { + if (!ob->data || ID_IS_LINKED(ob->data) || ID_IS_OVERRIDE_LIBRARY(ob->data)) { return false; } return true; diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index be105a23a84..3644c3177d3 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -3699,7 +3699,7 @@ static void do_tiled( SculptSession *ss = ob->sculpt; StrokeCache *cache = ss->cache; const float radius = cache->radius; - BoundBox *bb = BKE_object_boundbox_get(ob); + const BoundBox *bb = BKE_object_boundbox_get(ob); const float *bbMin = bb->vec[0]; const float *bbMax = bb->vec[6]; const float *step = sd->paint.tile_offset; diff --git a/source/blender/editors/sculpt_paint/sculpt_ops.c b/source/blender/editors/sculpt_paint/sculpt_ops.c index 53e8649585a..cd174681ccb 100644 --- a/source/blender/editors/sculpt_paint/sculpt_ops.c +++ b/source/blender/editors/sculpt_paint/sculpt_ops.c @@ -616,7 +616,7 @@ static int vertex_to_loop_colors_exec(bContext *C, wmOperator *UNUSED(op)) ID *data; data = ob->data; - if (data && ID_IS_LINKED(data)) { + if (data == NULL || ID_IS_LINKED(data) || ID_IS_OVERRIDE_LIBRARY(data)) { return OPERATOR_CANCELLED; } @@ -681,7 +681,7 @@ static int loop_to_vertex_colors_exec(bContext *C, wmOperator *UNUSED(op)) ID *data; data = ob->data; - if (data && ID_IS_LINKED(data)) { + if (data == NULL || ID_IS_LINKED(data) || ID_IS_OVERRIDE_LIBRARY(data)) { return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index f91ed5eb4f3..10fb008049d 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -207,13 +207,13 @@ static int file_browse_exec(bContext *C, wmOperator *op) /* Do this first so '//' isn't converted to '//\' on windows. */ BLI_path_slash_ensure(path); if (is_relative) { - const int path_len = BLI_strncpy_rlen(path, str, FILE_MAX); BLI_path_rel(path, BKE_main_blendfile_path(bmain)); - str = MEM_reallocN(str, path_len + 2); - BLI_strncpy(str, path, FILE_MAX); + str_len = strlen(path); + str = MEM_reallocN(str, str_len + 1); + memcpy(str, path, str_len + 1); } else { - str = MEM_reallocN(str, str_len + 2); + str = MEM_reallocN(str, str_len + 1); } } else { diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index ae0e5b23d55..65354591034 100644 --- a/source/blender/editors/space_file/fsmenu.c +++ b/source/blender/editors/space_file/fsmenu.c @@ -463,7 +463,12 @@ void fsmenu_insert_entry(struct FSMenu *fsmenu, ED_fsmenu_entry_set_icon(fsm_iter, icon); - fsmenu_entry_refresh_valid(fsm_iter); + if (flag & FS_INSERT_NO_VALIDATE) { + fsm_iter->valid = true; + } + else { + fsmenu_entry_refresh_valid(fsm_iter); + } if (fsm_prev) { if (flag & FS_INSERT_FIRST) { @@ -689,7 +694,12 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) break; } - fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, tmps, name, icon, FS_INSERT_SORTED); + fsmenu_insert_entry(fsmenu, + FS_CATEGORY_SYSTEM, + tmps, + name, + icon, + FS_INSERT_SORTED | FS_INSERT_NO_VALIDATE); } } diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc index 365a17c0a04..958a9fdfc60 100644 --- a/source/blender/editors/space_node/drawnode.cc +++ b/source/blender/editors/space_node/drawnode.cc @@ -791,6 +791,9 @@ static void node_composit_set_butfunc(bNodeType *ntype) ntype->draw_buttons = node_composit_buts_image; ntype->draw_buttons_ex = node_composit_buts_image_ex; break; + case CMP_NODE_NORMAL: + ntype->draw_buttons = node_buts_normal; + break; case CMP_NODE_CURVE_RGB: ntype->draw_buttons = node_buts_curvecol; break; @@ -1299,8 +1302,7 @@ static void std_node_socket_draw( uiItemL(row, text, 0); if (socket_needs_attribute_search(*node, *sock)) { - const bNodeTree *node_tree = (const bNodeTree *)node_ptr->owner_id; - node_geometry_add_attribute_search_button(*C, *node_tree, *node, *ptr, *row); + node_geometry_add_attribute_search_button(*C, *node, *ptr, *row); } else { uiItemR(row, ptr, "default_value", DEFAULT_FLAGS, "", 0); @@ -1556,7 +1558,6 @@ bool node_link_bezier_handles(const View2D *v2d, } /* in v0 and v3 we put begin/end points */ - int toreroute, fromreroute; if (link.fromsock) { vec[0][0] = link.fromsock->locx; vec[0][1] = link.fromsock->locy; @@ -1567,14 +1568,12 @@ bool node_link_bezier_handles(const View2D *v2d, link.fromsock->total_inputs); copy_v2_v2(vec[0], position); } - fromreroute = (link.fromnode && link.fromnode->type == NODE_REROUTE); } else { if (snode == nullptr) { return false; } copy_v2_v2(vec[0], cursor); - fromreroute = 0; } if (link.tosock) { vec[3][0] = link.tosock->locx; @@ -1586,14 +1585,12 @@ bool node_link_bezier_handles(const View2D *v2d, link.tosock->total_inputs); copy_v2_v2(vec[3], position); } - toreroute = (link.tonode && link.tonode->type == NODE_REROUTE); } else { if (snode == nullptr) { return false; } copy_v2_v2(vec[3], cursor); - toreroute = 0; } /* may be called outside of drawing (so pass spacetype) */ @@ -1607,37 +1604,12 @@ bool node_link_bezier_handles(const View2D *v2d, } const float dist = curving * 0.10f * fabsf(vec[0][0] - vec[3][0]); - const float deltax = vec[3][0] - vec[0][0]; - const float deltay = vec[3][1] - vec[0][1]; - /* check direction later, for top sockets */ - if (fromreroute) { - if (fabsf(deltax) > fabsf(deltay)) { - vec[1][1] = vec[0][1]; - vec[1][0] = vec[0][0] + (deltax > 0 ? dist : -dist); - } - else { - vec[1][0] = vec[0][0]; - vec[1][1] = vec[0][1] + (deltay > 0 ? dist : -dist); - } - } - else { - vec[1][0] = vec[0][0] + dist; - vec[1][1] = vec[0][1]; - } - if (toreroute) { - if (fabsf(deltax) > fabsf(deltay)) { - vec[2][1] = vec[3][1]; - vec[2][0] = vec[3][0] + (deltax > 0 ? -dist : dist); - } - else { - vec[2][0] = vec[3][0]; - vec[2][1] = vec[3][1] + (deltay > 0 ? -dist : dist); - } - } - else { - vec[2][0] = vec[3][0] - dist; - vec[2][1] = vec[3][1]; - } + + vec[1][0] = vec[0][0] + dist; + vec[1][1] = vec[0][1]; + + vec[2][0] = vec[3][0] - dist; + vec[2][1] = vec[3][1]; if (v2d && min_ffff(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) > v2d->cur.xmax) { return false; /* clipped */ diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 7f0c426922b..4ab81bac9aa 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -69,6 +69,7 @@ #include "NOD_geometry_nodes_eval_log.hh" #include "NOD_node_declaration.hh" +#include "FN_field.hh" #include "FN_field_cpp_type.hh" #include "node_intern.hh" /* own include */ @@ -2574,20 +2575,14 @@ static void reroute_node_draw( if (node.label[0] != '\0') { /* draw title (node label) */ BLI_strncpy(showname, node.label, sizeof(showname)); - uiDefBut(&block, - UI_BTYPE_LABEL, - 0, - showname, - (int)(rct.xmin - NODE_DYS), - (int)(rct.ymax), - (short)512, - (short)NODE_DY, - nullptr, - 0, - 0, - 0, - 0, - nullptr); + const short width = 512; + const int x = BLI_rctf_cent_x(&node.totr) - (width / 2); + const int y = node.totr.ymax; + + uiBut *label_but = uiDefBut( + &block, UI_BTYPE_LABEL, 0, showname, x, y, width, (short)NODE_DY, NULL, 0, 0, 0, 0, NULL); + + UI_but_drawflag_disable(label_but, UI_BUT_TEXT_LEFT); } /* only draw input socket. as they all are placed on the same position. diff --git a/source/blender/editors/space_node/node_geometry_attribute_search.cc b/source/blender/editors/space_node/node_geometry_attribute_search.cc index 5a6fe911a05..2536496b50d 100644 --- a/source/blender/editors/space_node/node_geometry_attribute_search.cc +++ b/source/blender/editors/space_node/node_geometry_attribute_search.cc @@ -14,11 +14,13 @@ #include "DNA_space_types.h" #include "BKE_context.h" +#include "BKE_node_tree_update.h" #include "BKE_object.h" #include "RNA_access.h" #include "RNA_enum_types.h" +#include "ED_node.h" #include "ED_screen.h" #include "ED_undo.h" @@ -38,14 +40,66 @@ using geo_log::GeometryAttributeInfo; namespace blender::ed::space_node { struct AttributeSearchData { - const bNodeTree *tree; - const bNode *node; - bNodeSocket *socket; + char node_name[MAX_NAME]; + char socket_identifier[MAX_NAME]; }; /* This class must not have a destructor, since it is used by buttons and freed with #MEM_freeN. */ BLI_STATIC_ASSERT(std::is_trivially_destructible_v<AttributeSearchData>, ""); +static Vector<const GeometryAttributeInfo *> get_attribute_info_from_context( + const bContext &C, AttributeSearchData &data) +{ + SpaceNode *snode = CTX_wm_space_node(&C); + if (!snode) { + BLI_assert_unreachable(); + return {}; + } + bNodeTree *node_tree = snode->edittree; + if (node_tree == nullptr) { + BLI_assert_unreachable(); + return {}; + } + bNode *node = nodeFindNodebyName(node_tree, data.node_name); + if (node == nullptr) { + BLI_assert_unreachable(); + return {}; + } + + /* For the attribute input node, collect attribute information from all nodes in the group. */ + if (node->type == GEO_NODE_INPUT_NAMED_ATTRIBUTE) { + const geo_log::TreeLog *tree_log = geo_log::ModifierLog::find_tree_by_node_editor_context( + *snode); + if (tree_log == nullptr) { + return {}; + } + + Vector<const GeometryAttributeInfo *> attributes; + Set<StringRef> names; + tree_log->foreach_node_log([&](const geo_log::NodeLog &node_log) { + for (const geo_log::SocketLog &socket_log : node_log.input_logs()) { + const geo_log::ValueLog *value_log = socket_log.value(); + if (const geo_log::GeometryValueLog *geo_value_log = + dynamic_cast<const geo_log::GeometryValueLog *>(value_log)) { + for (const GeometryAttributeInfo &attribute : geo_value_log->attributes()) { + if (names.add(attribute.name)) { + attributes.append(&attribute); + } + } + } + } + }); + return attributes; + } + + const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context( + *snode, data.node_name); + if (node_log == nullptr) { + return {}; + } + return node_log->lookup_available_attributes(); +} + static void attribute_search_update_fn( const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first) { @@ -55,15 +109,45 @@ static void attribute_search_update_fn( AttributeSearchData *data = static_cast<AttributeSearchData *>(arg); - SpaceNode *snode = CTX_wm_space_node(C); - const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context( - *snode, *data->node); - if (node_log == nullptr) { - return; + Vector<const GeometryAttributeInfo *> infos = get_attribute_info_from_context(*C, *data); + + /* Remove the deprecated normal attribute from the search. */ + for (const int i : infos.index_range()) { + if (infos[i]->domain == ATTR_DOMAIN_FACE && infos[i]->name == "normal") { + infos.remove(i); + break; + } } - blender::Vector<const GeometryAttributeInfo *> infos = node_log->lookup_available_attributes(); - blender::ui::attribute_search_add_items(str, true, infos, items, is_first); + ui::attribute_search_add_items(str, true, infos, items, is_first); +} + +/** + * Some custom data types don't correspond to node types and therefore can't be + * used by the named attribute input node. Find the best option or fallback to float. + */ +static CustomDataType data_type_in_attribute_input_node(const CustomDataType type) +{ + switch (type) { + case CD_PROP_FLOAT: + case CD_PROP_INT32: + case CD_PROP_FLOAT3: + case CD_PROP_COLOR: + case CD_PROP_BOOL: + return type; + case CD_MLOOPCOL: + return CD_PROP_COLOR; + case CD_PROP_STRING: + /* Unsupported currently. */ + return CD_PROP_FLOAT; + case CD_PROP_FLOAT2: + /* No 2D vector sockets currently. */ + return CD_PROP_FLOAT3; + case CD_PROP_INT8: + return CD_PROP_INT32; + default: + return CD_PROP_FLOAT; + } } static void attribute_search_exec_fn(bContext *C, void *data_v, void *item_v) @@ -71,21 +155,62 @@ static void attribute_search_exec_fn(bContext *C, void *data_v, void *item_v) if (ED_screen_animation_playing(CTX_wm_manager(C))) { return; } - if (item_v == nullptr) { + GeometryAttributeInfo *item = (GeometryAttributeInfo *)item_v; + if (item == nullptr) { + return; + } + SpaceNode *snode = CTX_wm_space_node(C); + if (!snode) { + BLI_assert_unreachable(); + return; + } + bNodeTree *node_tree = snode->edittree; + if (node_tree == nullptr) { + BLI_assert_unreachable(); return; } AttributeSearchData *data = static_cast<AttributeSearchData *>(data_v); - GeometryAttributeInfo *item = (GeometryAttributeInfo *)item_v; + bNode *node = nodeFindNodebyName(node_tree, data->node_name); + if (node == nullptr) { + BLI_assert_unreachable(); + return; + } + bNodeSocket *socket = bke::node_find_enabled_input_socket(*node, data->socket_identifier); + if (socket == nullptr) { + BLI_assert_unreachable(); + return; + } + BLI_assert(socket->type == SOCK_STRING); + + /* For the attribute input node, also adjust the type and links connected to the output. */ + if (node->type == GEO_NODE_INPUT_NAMED_ATTRIBUTE) { + NodeGeometryInputNamedAttribute &storage = *(NodeGeometryInputNamedAttribute *)node->storage; + const CustomDataType new_type = data_type_in_attribute_input_node(item->data_type); + if (new_type != storage.data_type) { + storage.data_type = new_type; + /* Make the output socket with the new type on the attribute input node active. */ + node->typeinfo->updatefunc(node_tree, node); + + /* Relink all node links to the newly active output socket. */ + bNodeSocket *output_socket = bke::node_find_enabled_output_socket(*node, "Attribute"); + LISTBASE_FOREACH (bNodeLink *, link, &node_tree->links) { + if (link->fromnode == node) { + link->fromsock = output_socket; + BKE_ntree_update_tag_link_changed(node_tree); + } + } + } + BKE_ntree_update_tag_node_property(node_tree, node); + ED_node_tree_propagate_change(C, CTX_data_main(C), node_tree); + } - bNodeSocket &socket = *data->socket; - bNodeSocketValueString *value = static_cast<bNodeSocketValueString *>(socket.default_value); + bNodeSocketValueString *value = static_cast<bNodeSocketValueString *>(socket->default_value); BLI_strncpy(value->value, item->name.c_str(), MAX_NAME); ED_undo_push(C, "Assign Attribute Name"); } void node_geometry_add_attribute_search_button(const bContext &UNUSED(C), - const bNodeTree &node_tree, const bNode &node, PointerRNA &socket_ptr, uiLayout &layout) @@ -109,8 +234,10 @@ void node_geometry_add_attribute_search_button(const bContext &UNUSED(C), 0.0f, ""); - AttributeSearchData *data = MEM_new<AttributeSearchData>( - __func__, AttributeSearchData{&node_tree, &node, (bNodeSocket *)socket_ptr.data}); + const bNodeSocket &socket = *static_cast<const bNodeSocket *>(socket_ptr.data); + AttributeSearchData *data = MEM_new<AttributeSearchData>(__func__); + BLI_strncpy(data->node_name, node.name, sizeof(data->node_name)); + BLI_strncpy(data->socket_identifier, socket.identifier, sizeof(data->socket_identifier)); UI_but_func_search_set_results_are_suggestions(but, true); UI_but_func_search_set_sep_string(but, UI_MENU_ARROW_SEP); diff --git a/source/blender/editors/space_node/node_group.cc b/source/blender/editors/space_node/node_group.cc index 789476a8179..160a379d3c6 100644 --- a/source/blender/editors/space_node/node_group.cc +++ b/source/blender/editors/space_node/node_group.cc @@ -841,6 +841,12 @@ static void node_group_make_insert_selected(const bContext &C, bNodeTree &ntree, nodeRemLink(&ntree, link); } else if (toselect && !fromselect) { + /* Remove hidden links to not create unconnected sockets in the interface. */ + if (nodeLinkIsHidden(link)) { + nodeRemLink(&ntree, link); + continue; + } + bNodeSocket *link_sock; bNode *link_node; node_socket_skip_reroutes(&ntree.links, link->tonode, link->tosock, &link_node, &link_sock); @@ -861,6 +867,12 @@ static void node_group_make_insert_selected(const bContext &C, bNodeTree &ntree, link->tosock = node_group_find_input_socket(gnode, iosock->identifier); } else if (fromselect && !toselect) { + /* Remove hidden links to not create unconnected sockets in the interface. */ + if (nodeLinkIsHidden(link)) { + nodeRemLink(&ntree, link); + continue; + } + /* First check whether the source of this link is already connected to an output. * If yes, reuse that output instead of duplicating it. */ bool connected = false; diff --git a/source/blender/editors/space_node/node_intern.hh b/source/blender/editors/space_node/node_intern.hh index cd40573607d..44163cd5ae3 100644 --- a/source/blender/editors/space_node/node_intern.hh +++ b/source/blender/editors/space_node/node_intern.hh @@ -353,7 +353,6 @@ void NODE_GGT_backdrop_corner_pin(wmGizmoGroupType *gzgt); /* node_geometry_attribute_search.cc */ void node_geometry_add_attribute_search_button(const bContext &C, - const bNodeTree &node_tree, const bNode &node, PointerRNA &socket_ptr, uiLayout &layout); diff --git a/source/blender/editors/space_node/node_templates.cc b/source/blender/editors/space_node/node_templates.cc index b63cb2eeee5..e92e0571157 100644 --- a/source/blender/editors/space_node/node_templates.cc +++ b/source/blender/editors/space_node/node_templates.cc @@ -884,7 +884,7 @@ static void ui_node_draw_input( if (node_tree->type == NTREE_GEOMETRY && snode != nullptr) { /* Only add the attribute search in the node editor, in other places there is not * enough context. */ - node_geometry_add_attribute_search_button(*C, *node_tree, *node, inputptr, *row); + node_geometry_add_attribute_search_button(*C, *node, inputptr, *row); } else { uiItemR(sub, &inputptr, "default_value", 0, "", ICON_NONE); diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt index b57525854d6..fae0e4be2a8 100644 --- a/source/blender/editors/space_outliner/CMakeLists.txt +++ b/source/blender/editors/space_outliner/CMakeLists.txt @@ -38,7 +38,8 @@ set(SRC tree/tree_display_data.cc tree/tree_display_libraries.cc tree/tree_display_orphaned.cc - tree/tree_display_override_library.cc + tree/tree_display_override_library_properties.cc + tree/tree_display_override_library_hierarchies.cc tree/tree_display_scenes.cc tree/tree_display_sequencer.cc tree/tree_display_view_layer.cc diff --git a/source/blender/editors/space_outliner/outliner_collections.cc b/source/blender/editors/space_outliner/outliner_collections.cc index a4ff44512ef..8ca2ffe6a9c 100644 --- a/source/blender/editors/space_outliner/outliner_collections.cc +++ b/source/blender/editors/space_outliner/outliner_collections.cc @@ -354,7 +354,7 @@ void outliner_collection_delete( else { LISTBASE_FOREACH (CollectionParent *, cparent, &collection->parents) { Collection *parent = cparent->collection; - if (ID_IS_LINKED(parent)) { + if (ID_IS_LINKED(parent) || ID_IS_OVERRIDE_LIBRARY(parent)) { skip = true; break; } @@ -366,7 +366,7 @@ void outliner_collection_delete( ID *scene_owner = id_type->owner_get(bmain, &parent->id); BLI_assert(GS(scene_owner->name) == ID_SCE); - if (ID_IS_LINKED(scene_owner)) { + if (ID_IS_LINKED(scene_owner) || ID_IS_OVERRIDE_LIBRARY(scene_owner)) { skip = true; break; } @@ -603,7 +603,9 @@ static int collection_duplicate_exec(bContext *C, wmOperator *op) if (ID_IS_LINKED(scene_owner) || ID_IS_OVERRIDE_LIBRARY(scene_owner)) { scene_owner = CTX_data_scene(C); - parent = ID_IS_LINKED(scene_owner) ? nullptr : scene_owner->master_collection; + parent = (ID_IS_LINKED(scene_owner) || ID_IS_OVERRIDE_LIBRARY(scene_owner)) ? + nullptr : + scene_owner->master_collection; } } @@ -1293,6 +1295,7 @@ static bool collection_disable_render_poll(bContext *C) static int collection_flag_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); @@ -1319,7 +1322,7 @@ static int collection_flag_exec(bContext *C, wmOperator *op) LayerCollection *layer_collection = reinterpret_cast<LayerCollection *>( BLI_gsetIterator_getKey(&collections_to_edit_iter)); Collection *collection = layer_collection->collection; - if (ID_IS_LINKED(collection)) { + if (!BKE_id_is_editable(bmain, &collection->id)) { continue; } if (clear) { @@ -1347,7 +1350,7 @@ static int collection_flag_exec(bContext *C, wmOperator *op) GSET_ITER (collections_to_edit_iter, data.collections_to_edit) { Collection *collection = reinterpret_cast<Collection *>( BLI_gsetIterator_getKey(&collections_to_edit_iter)); - if (ID_IS_LINKED(collection)) { + if (!BKE_id_is_editable(bmain, &collection->id)) { continue; } @@ -1600,7 +1603,7 @@ static int outliner_color_tag_set_exec(bContext *C, wmOperator *op) if (collection == scene->master_collection) { continue; } - if (ID_IS_LINKED(collection)) { + if (!BKE_id_is_editable(CTX_data_main(C), &collection->id)) { BKE_report(op->reports, RPT_WARNING, "Can't add a color tag to a linked collection"); continue; } diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.cc b/source/blender/editors/space_outliner/outliner_dragdrop.cc index 30b81b2ecb2..88640210ea3 100644 --- a/source/blender/editors/space_outliner/outliner_dragdrop.cc +++ b/source/blender/editors/space_outliner/outliner_dragdrop.cc @@ -22,6 +22,7 @@ #include "BKE_collection.h" #include "BKE_context.h" #include "BKE_layer.h" +#include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_object.h" @@ -374,7 +375,7 @@ static void parent_drop_set_parents(bContext *C, Object *object = (Object *)drag_id->id; /* Do nothing to linked data */ - if (ID_IS_LINKED(object)) { + if (!BKE_id_is_editable(bmain, &object->id)) { linked_objects = true; continue; } @@ -387,7 +388,7 @@ static void parent_drop_set_parents(bContext *C, } if (linked_objects) { - BKE_report(reports, RPT_INFO, "Can't edit library linked object(s)"); + BKE_report(reports, RPT_INFO, "Can't edit library linked or non-editable override object(s)"); } if (parent_set) { @@ -556,7 +557,7 @@ static int scene_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent Scene *scene = (Scene *)outliner_ID_drop_find(C, event, ID_SCE); Object *ob = (Object *)WM_drag_get_local_ID_from_event(event, ID_OB); - if (ELEM(nullptr, ob, scene) || ID_IS_LINKED(scene)) { + if (ELEM(nullptr, ob, scene) || !BKE_id_is_editable(bmain, &scene->id)) { return OPERATOR_CANCELLED; } @@ -748,7 +749,7 @@ static bool datastack_drop_init(bContext *C, const wmEvent *event, StackDropData ob = nullptr; } - if (ob && ID_IS_LINKED(&ob->id)) { + if (ob && !BKE_id_is_editable(CTX_data_main(C), &ob->id)) { return false; } @@ -1107,8 +1108,8 @@ struct CollectionDrop { static Collection *collection_parent_from_ID(ID *id) { - /* Can't change linked parent collections. */ - if (!id || ID_IS_LINKED(id)) { + /* Can't change linked or override parent collections. */ + if (!id || ID_IS_LINKED(id) || ID_IS_OVERRIDE_LIBRARY(id)) { return nullptr; } @@ -1134,7 +1135,7 @@ static bool collection_drop_init( } Collection *to_collection = outliner_collection_from_tree_element(te); - if (ID_IS_LINKED(to_collection)) { + if (ID_IS_LINKED(to_collection) || ID_IS_OVERRIDE_LIBRARY(to_collection)) { return false; } diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc index 9857abb3da7..d204e12b41d 100644 --- a/source/blender/editors/space_outliner/outliner_draw.cc +++ b/source/blender/editors/space_outliner/outliner_draw.cc @@ -2165,8 +2165,10 @@ static void outliner_draw_mode_column_toggle(uiBlock *block, /* Mode toggling handles its own undo state because undo steps need to be grouped. */ UI_but_flag_disable(but, UI_BUT_UNDO); - if (ID_IS_LINKED(&ob->id)) { - UI_but_disable(but, TIP_("Can't edit external library data")); + if (ID_IS_LINKED(&ob->id) || + (ID_IS_OVERRIDE_LIBRARY_REAL(ob) && + (ob->id.override_library->flag & IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED) != 0)) { + UI_but_disable(but, TIP_("Can't edit library or non-editable override data")); } } @@ -3897,6 +3899,12 @@ void draw_outliner(const bContext *C) /* Default to no emboss for outliner UI. */ UI_block_emboss_set(block, UI_EMBOSS_NONE_OR_STATUS); + if (space_outliner->outlinevis == SO_OVERRIDES_LIBRARY) { + /* Draw overrides status columns. */ + outliner_draw_overrides_warning_buts( + block, region, space_outliner, &space_outliner->tree, true); + } + if (space_outliner->outlinevis == SO_DATA_API) { int buttons_start_x = outliner_data_api_buttons_start_x(tree_width); /* draw rna buttons */ @@ -3911,11 +3919,8 @@ void draw_outliner(const bContext *C) /* draw user toggle columns */ outliner_draw_userbuts(block, region, space_outliner, &space_outliner->tree); } - else if (space_outliner->outlinevis == SO_OVERRIDES_LIBRARY) { - /* Draw overrides status columns. */ - outliner_draw_overrides_warning_buts( - block, region, space_outliner, &space_outliner->tree, true); - + else if ((space_outliner->outlinevis == SO_OVERRIDES_LIBRARY) && + (space_outliner->lib_override_view_mode == SO_LIB_OVERRIDE_VIEW_PROPERTIES)) { UI_block_emboss_set(block, UI_EMBOSS); UI_block_flag_enable(block, UI_BLOCK_NO_DRAW_OVERRIDDEN_STATE); const int x = region->v2d.cur.xmax - right_column_width; diff --git a/source/blender/editors/space_outliner/outliner_edit.cc b/source/blender/editors/space_outliner/outliner_edit.cc index ae67e7108bf..d6c5901b546 100644 --- a/source/blender/editors/space_outliner/outliner_edit.cc +++ b/source/blender/editors/space_outliner/outliner_edit.cc @@ -30,6 +30,7 @@ #include "BKE_context.h" #include "BKE_idtype.h" #include "BKE_lib_id.h" +#include "BKE_lib_override.h" #include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_main.h" diff --git a/source/blender/editors/space_outliner/outliner_select.cc b/source/blender/editors/space_outliner/outliner_select.cc index a202ded6deb..fd0ee422df0 100644 --- a/source/blender/editors/space_outliner/outliner_select.cc +++ b/source/blender/editors/space_outliner/outliner_select.cc @@ -31,6 +31,7 @@ #include "BKE_gpencil.h" #include "BKE_gpencil_modifier.h" #include "BKE_layer.h" +#include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_modifier.h" #include "BKE_object.h" @@ -116,8 +117,8 @@ static void do_outliner_item_posemode_toggle(bContext *C, Scene *scene, Base *ba Main *bmain = CTX_data_main(C); Object *ob = base->object; - if (ID_IS_LINKED(ob)) { - BKE_report(CTX_wm_reports(C), RPT_WARNING, "Cannot pose libdata"); + if (!BKE_id_is_editable(CTX_data_main(C), &ob->id)) { + BKE_report(CTX_wm_reports(C), RPT_WARNING, "Cannot pose non-editable data"); return; } diff --git a/source/blender/editors/space_outliner/outliner_tools.cc b/source/blender/editors/space_outliner/outliner_tools.cc index 0aea4521204..22e42c762ca 100644 --- a/source/blender/editors/space_outliner/outliner_tools.cc +++ b/source/blender/editors/space_outliner/outliner_tools.cc @@ -31,6 +31,7 @@ #include "BLI_blenlib.h" #include "BLI_ghash.h" +#include "BLI_set.hh" #include "BLI_utildefines.h" #include "BKE_anim_data.h" @@ -46,6 +47,7 @@ #include "BKE_lib_id.h" #include "BKE_lib_override.h" #include "BKE_lib_query.h" +#include "BKE_lib_remap.h" #include "BKE_main.h" #include "BKE_object.h" #include "BKE_report.h" @@ -87,6 +89,8 @@ static CLG_LogRef LOG = {"ed.outliner.tools"}; using namespace blender::ed::outliner; +using blender::Set; + /* -------------------------------------------------------------------- */ /** \name ID/Library/Data Set/Un-link Utilities * \{ */ @@ -755,8 +759,50 @@ struct OutlinerLibOverrideData { * instead of re-applying relevant existing ID pointer property override operations. Helps * solving broken overrides while not losing *all* of your overrides. */ bool do_resync_hierarchy_enforce; + + /** The override hierarchy root, when known/created. */ + ID *id_hierarchy_root_override; + + /** A hash of the selected tree elements' ID 'uuid'. Used to clear 'system override' flags on + * their newly-created liboverrides in post-process step of override hierarchy creation. */ + Set<uint> selected_id_uid; }; +/* Store 'UUID' of IDs of selected elements in the Outliner tree, before generating the override + * hierarchy. */ +static void id_override_library_create_hierarchy_pre_process_fn(bContext *UNUSED(C), + ReportList *UNUSED(reports), + Scene *UNUSED(scene), + TreeElement *UNUSED(te), + TreeStoreElem *UNUSED(tsep), + TreeStoreElem *tselem, + void *user_data) +{ + BLI_assert(TSE_IS_REAL_ID(tselem)); + + OutlinerLibOverrideData *data = reinterpret_cast<OutlinerLibOverrideData *>(user_data); + const bool do_hierarchy = data->do_hierarchy; + ID *id_root_reference = tselem->id; + + BLI_assert(do_hierarchy); + UNUSED_VARS_NDEBUG(do_hierarchy); + + data->selected_id_uid.add(id_root_reference->session_uuid); + + if (GS(id_root_reference->name) == ID_GR && (tselem->flag & TSE_CLOSED) != 0) { + /* If selected element is a (closed) collection, check all of its objects recursively, and also + * consider the armature ones as 'selected' (i.e. to not become system overrides). */ + Collection *root_collection = reinterpret_cast<Collection *>(id_root_reference); + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (root_collection, object_iter) { + if (id_root_reference->lib == object_iter->id.lib && object_iter->type == OB_ARMATURE) { + printf("Foooo\n"); + data->selected_id_uid.add(object_iter->id.session_uuid); + } + } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + } +} + static void id_override_library_create_fn(bContext *C, ReportList *reports, Scene *scene, @@ -782,7 +828,7 @@ static void id_override_library_create_fn(bContext *C, bool is_override_instancing_object = false; if (tsep != nullptr && tsep->type == TSE_SOME_ID && tsep->id != nullptr && GS(tsep->id->name) == ID_OB && !ID_IS_OVERRIDE_LIBRARY(tsep->id)) { - Object *ob = (Object *)tsep->id; + Object *ob = reinterpret_cast<Object *>(tsep->id); if (ob->type == OB_EMPTY && &ob->instance_collection->id == id_root_reference) { BLI_assert(GS(id_root_reference->name) == ID_GR); /* Empty instantiating the collection we override, we need to pass it to BKE overriding code @@ -895,6 +941,7 @@ static void id_override_library_create_fn(bContext *C, return; } + ID *id_root_override = nullptr; success = BKE_lib_override_library_create(bmain, CTX_data_scene(C), CTX_data_view_layer(C), @@ -902,7 +949,22 @@ static void id_override_library_create_fn(bContext *C, id_root_reference, id_hierarchy_root_reference, id_instance_hint, - nullptr); + &id_root_override); + + BLI_assert(id_root_override != nullptr); + BLI_assert(!ID_IS_LINKED(id_root_override)); + BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root_override)); + if (ID_IS_LINKED(id_hierarchy_root_reference)) { + BLI_assert( + id_root_override->override_library->hierarchy_root->override_library->reference == + id_hierarchy_root_reference); + data->id_hierarchy_root_override = id_root_override->override_library->hierarchy_root; + } + else { + BLI_assert(id_root_override->override_library->hierarchy_root == + id_hierarchy_root_reference); + data->id_hierarchy_root_override = id_root_override->override_library->hierarchy_root; + } } else if (ID_IS_OVERRIDABLE_LIBRARY(id_root_reference)) { success = BKE_lib_override_library_create_from_id(bmain, id_root_reference, true) != nullptr; @@ -926,6 +988,44 @@ static void id_override_library_create_fn(bContext *C, } } +/* Clear system override flag from newly created overrides which linked reference were previously + * selected in the Outliner tree. */ +static void id_override_library_create_hierarchy_post_process(bContext *C, + OutlinerLibOverrideData *data) +{ + Main *bmain = CTX_data_main(C); + ID *id_hierarchy_root_override = data->id_hierarchy_root_override; + + ID *id_iter; + FOREACH_MAIN_ID_BEGIN (bmain, id_iter) { + if (ID_IS_LINKED(id_iter) || !ID_IS_OVERRIDE_LIBRARY_REAL(id_iter) || + id_iter->override_library->hierarchy_root != id_hierarchy_root_override) { + continue; + } + if (data->selected_id_uid.contains(id_iter->override_library->reference->session_uuid)) { + id_iter->override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED; + } + } + FOREACH_MAIN_ID_END; +} + +static void id_override_library_toggle_flag_fn(bContext *UNUSED(C), + ReportList *UNUSED(reports), + Scene *UNUSED(scene), + TreeElement *UNUSED(te), + TreeStoreElem *UNUSED(tsep), + TreeStoreElem *tselem, + void *user_data) +{ + BLI_assert(TSE_IS_REAL_ID(tselem)); + ID *id = tselem->id; + + if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + const uint flag = POINTER_AS_UINT(user_data); + id->override_library->flag ^= flag; + } +} + static void id_override_library_reset_fn(bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), @@ -943,10 +1043,10 @@ static void id_override_library_reset_fn(bContext *C, Main *bmain = CTX_data_main(C); if (do_hierarchy) { - BKE_lib_override_library_id_hierarchy_reset(bmain, id_root); + BKE_lib_override_library_id_hierarchy_reset(bmain, id_root, false); } else { - BKE_lib_override_library_id_reset(bmain, id_root); + BKE_lib_override_library_id_reset(bmain, id_root, false); } WM_event_add_notifier(C, NC_WM | ND_DATACHANGED, nullptr); @@ -998,40 +1098,76 @@ static void id_override_library_resync_fn(bContext *C, } } -static void id_override_library_delete_fn(bContext *C, - ReportList *UNUSED(reports), - Scene *UNUSED(scene), - TreeElement *te, - TreeStoreElem *UNUSED(tsep), - TreeStoreElem *tselem, - void *UNUSED(user_data)) +static void id_override_library_clear_hierarchy_fn(bContext *C, + ReportList *UNUSED(reports), + Scene *UNUSED(scene), + TreeElement *te, + TreeStoreElem *UNUSED(tsep), + TreeStoreElem *tselem, + void *UNUSED(user_data)) { BLI_assert(TSE_IS_REAL_ID(tselem)); ID *id_root = tselem->id; - if (ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) { - Main *bmain = CTX_data_main(C); + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) { + CLOG_WARN(&LOG, "Could not delete library override of data block '%s'", id_root->name); + return; + } - id_root->tag |= LIB_TAG_DOIT; + Main *bmain = CTX_data_main(C); - /* Tag all linked parents in tree hierarchy to be also overridden. */ - while ((te = te->parent) != nullptr) { - if (!TSE_IS_REAL_ID(te->store_elem)) { - continue; - } - if (!ID_IS_OVERRIDE_LIBRARY_REAL(te->store_elem->id)) { - break; - } - te->store_elem->id->tag |= LIB_TAG_DOIT; + id_root->tag |= LIB_TAG_DOIT; + + /* Tag all override parents in tree hierarchy to be also processed. */ + while ((te = te->parent) != nullptr) { + if (!TSE_IS_REAL_ID(te->store_elem)) { + continue; } + if (!ID_IS_OVERRIDE_LIBRARY_REAL(te->store_elem->id)) { + break; + } + te->store_elem->id->tag |= LIB_TAG_DOIT; + } - BKE_lib_override_library_delete(bmain, id_root); + BKE_lib_override_library_delete(bmain, id_root); - WM_event_add_notifier(C, NC_WINDOW, nullptr); + WM_event_add_notifier(C, NC_WINDOW, nullptr); +} + +static void id_override_library_clear_single_fn(bContext *C, + ReportList *reports, + Scene *UNUSED(scene), + TreeElement *UNUSED(te), + TreeStoreElem *UNUSED(tsep), + TreeStoreElem *tselem, + void *UNUSED(user_data)) +{ + BLI_assert(TSE_IS_REAL_ID(tselem)); + Main *bmain = CTX_data_main(C); + ID *id = tselem->id; + + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + BKE_reportf(reports, + RPT_WARNING, + "Cannot clear embedded library override id '%s', only overrides of real " + "data-blocks can be directly deleted", + id->name); + return; + } + + /* If given ID is not using any other override (it's a 'leaf' in the override hierarchy), + * delete it and remap its usages to its linked reference. Otherwise, keep it as a reset system + * override. */ + if (BKE_lib_override_library_is_hierarchy_leaf(bmain, id)) { + BKE_libblock_remap(bmain, id, id->override_library->reference, ID_REMAP_SKIP_INDIRECT_USAGE); + BKE_id_delete(bmain, id); } else { - CLOG_WARN(&LOG, "Could not delete library override of data block '%s'", id_root->name); + BKE_lib_override_library_id_reset(bmain, id, true); } + + WM_event_add_notifier(C, NC_WINDOW, nullptr); + return; } static void id_fake_user_set_fn(bContext *UNUSED(C), @@ -1829,11 +1965,13 @@ enum eOutlinerIdOpTypes { OUTLINER_IDOP_LOCAL, OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE, OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY, + OUTLINER_IDOP_OVERRIDE_LIBRARY_MAKE_EDITABLE, OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET, OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY, OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY, OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY_ENFORCE, - OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY, + OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_HIERARCHY, + OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_SINGLE, OUTLINER_IDOP_SINGLE, OUTLINER_IDOP_DELETE, OUTLINER_IDOP_REMAP, @@ -1872,6 +2010,11 @@ static const EnumPropertyItem prop_id_op_types[] = { "Make Library Override Hierarchy", "Make a local override of this linked data-block, and its hierarchy of dependencies - only " "applies to active Outliner item"}, + {OUTLINER_IDOP_OVERRIDE_LIBRARY_MAKE_EDITABLE, + "OVERRIDE_LIBRARY_MAKE_EDITABLE", + 0, + "Make Library Override Editable", + "Make the library override data-block editable"}, {OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET, "OVERRIDE_LIBRARY_RESET", 0, @@ -1895,12 +2038,18 @@ static const EnumPropertyItem prop_id_op_types[] = { "Rebuild this local override from its linked reference, as well as its hierarchy of " "dependencies, enforcing that hierarchy to match the linked data (i.e. ignoring exiting " "overrides on data-blocks pointer properties)"}, - {OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY, - "OVERRIDE_LIBRARY_DELETE_HIERARCHY", + {OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_HIERARCHY, + "OVERRIDE_LIBRARY_CLEAR_HIERARCHY", 0, - "Delete Library Override Hierarchy", + "Clear Library Override Hierarchy", "Delete this local override (including its hierarchy of override dependencies) and relink " "its usages to the linked data-blocks"}, + {OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_SINGLE, + "OVERRIDE_LIBRARY_CLEAR_SINGLE", + 0, + "Clear Single Library Override", + "Delete this local override if possible, else reset it and mark it as non editable, and " + "relink its usages to the linked data-blocks"}, {0, "", 0, nullptr, nullptr}, {OUTLINER_IDOP_COPY, "COPY", ICON_COPYDOWN, "Copy", ""}, {OUTLINER_IDOP_PASTE, "PASTE", ICON_PASTEDOWN, "Paste", ""}, @@ -1944,11 +2093,19 @@ static bool outliner_id_operation_item_poll(bContext *C, return true; } return false; + case OUTLINER_IDOP_OVERRIDE_LIBRARY_MAKE_EDITABLE: + if (ID_IS_OVERRIDE_LIBRARY_REAL(tselem->id) && !ID_IS_LINKED(tselem->id)) { + if (tselem->id->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED) { + return true; + } + } + return false; case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET: case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY: case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY: case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY_ENFORCE: - case OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY: + case OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_HIERARCHY: + case OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_SINGLE: if (ID_IS_OVERRIDE_LIBRARY_REAL(tselem->id) && !ID_IS_LINKED(tselem->id)) { return true; } @@ -2115,11 +2272,32 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op) scene, space_outliner, &space_outliner->tree, + id_override_library_create_hierarchy_pre_process_fn, + &override_data); + outliner_do_libdata_operation(C, + op->reports, + scene, + space_outliner, + &space_outliner->tree, id_override_library_create_fn, &override_data); + id_override_library_create_hierarchy_post_process(C, &override_data); + ED_undo_push(C, "Overridden Data Hierarchy"); break; } + case OUTLINER_IDOP_OVERRIDE_LIBRARY_MAKE_EDITABLE: { + outliner_do_libdata_operation(C, + op->reports, + scene, + space_outliner, + &space_outliner->tree, + id_override_library_toggle_flag_fn, + POINTER_FROM_UINT(IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED)); + + ED_undo_push(C, "Make Overridden Data Editable"); + break; + } case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET: { OutlinerLibOverrideData override_data{}; outliner_do_libdata_operation(C, @@ -2172,17 +2350,26 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op) ED_undo_push(C, "Resync Overridden Data Hierarchy"); break; } - case OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY: { - OutlinerLibOverrideData override_data{}; - override_data.do_hierarchy = true; + case OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_HIERARCHY: { outliner_do_libdata_operation(C, op->reports, scene, space_outliner, &space_outliner->tree, - id_override_library_delete_fn, - &override_data); - ED_undo_push(C, "Delete Overridden Data Hierarchy"); + id_override_library_clear_hierarchy_fn, + nullptr); + ED_undo_push(C, "Clear Overridden Data Hierarchy"); + break; + } + case OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_SINGLE: { + outliner_do_libdata_operation(C, + op->reports, + scene, + space_outliner, + &space_outliner->tree, + id_override_library_clear_single_fn, + nullptr); + ED_undo_push(C, "Clear Overridden Data Hierarchy"); break; } case OUTLINER_IDOP_SINGLE: { diff --git a/source/blender/editors/space_outliner/outliner_tree.cc b/source/blender/editors/space_outliner/outliner_tree.cc index 19fe40b612e..bbd9b48c260 100644 --- a/source/blender/editors/space_outliner/outliner_tree.cc +++ b/source/blender/editors/space_outliner/outliner_tree.cc @@ -712,7 +712,8 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, else { /* do not extend Armature when we have posemode */ tselem = TREESTORE(te->parent); - if (GS(tselem->id->name) == ID_OB && ((Object *)tselem->id)->mode & OB_MODE_POSE) { + if (TSE_IS_REAL_ID(tselem) && GS(tselem->id->name) == ID_OB && + ((Object *)tselem->id)->mode & OB_MODE_POSE) { /* pass */ } else { diff --git a/source/blender/editors/space_outliner/outliner_utils.cc b/source/blender/editors/space_outliner/outliner_utils.cc index ed5a2108d3c..7526cc7ef5c 100644 --- a/source/blender/editors/space_outliner/outliner_utils.cc +++ b/source/blender/editors/space_outliner/outliner_utils.cc @@ -324,6 +324,9 @@ float outliner_right_columns_width(const SpaceOutliner *space_outliner) case SO_LIBRARIES: return 0.0f; case SO_OVERRIDES_LIBRARY: + if (space_outliner->lib_override_view_mode != SO_LIB_OVERRIDE_VIEW_PROPERTIES) { + return 0.0f; + } num_columns = OL_RNA_COL_SIZEX / UI_UNIT_X; break; case SO_ID_ORPHANS: diff --git a/source/blender/editors/space_outliner/tree/tree_display.cc b/source/blender/editors/space_outliner/tree/tree_display.cc index f9141dffd6a..141c68594e8 100644 --- a/source/blender/editors/space_outliner/tree/tree_display.cc +++ b/source/blender/editors/space_outliner/tree/tree_display.cc @@ -30,7 +30,13 @@ std::unique_ptr<AbstractTreeDisplay> AbstractTreeDisplay::createFromDisplayMode( case SO_ID_ORPHANS: return std::make_unique<TreeDisplayIDOrphans>(space_outliner); case SO_OVERRIDES_LIBRARY: - return std::make_unique<TreeDisplayOverrideLibrary>(space_outliner); + switch ((eSpaceOutliner_LibOverrideViewMode)space_outliner.lib_override_view_mode) { + case SO_LIB_OVERRIDE_VIEW_PROPERTIES: + return std::make_unique<TreeDisplayOverrideLibraryProperties>(space_outliner); + case SO_LIB_OVERRIDE_VIEW_HIERARCHIES: + return std::make_unique<TreeDisplayOverrideLibraryHierarchies>(space_outliner); + } + break; case SO_VIEW_LAYER: return std::make_unique<TreeDisplayViewLayer>(space_outliner); } diff --git a/source/blender/editors/space_outliner/tree/tree_display.hh b/source/blender/editors/space_outliner/tree/tree_display.hh index a60d3339042..327f29aa15e 100644 --- a/source/blender/editors/space_outliner/tree/tree_display.hh +++ b/source/blender/editors/space_outliner/tree/tree_display.hh @@ -35,6 +35,8 @@ struct ViewLayer; namespace blender::ed::outliner { +class TreeElementID; + /** * \brief The data to build the tree from. */ @@ -127,11 +129,11 @@ class TreeDisplayLibraries final : public AbstractTreeDisplay { /* Library Overrides Tree-Display. */ /** - * \brief Tree-Display for the Library Overrides display mode. + * \brief Tree-Display for the Library Overrides display mode, Properties view mode. */ -class TreeDisplayOverrideLibrary final : public AbstractTreeDisplay { +class TreeDisplayOverrideLibraryProperties final : public AbstractTreeDisplay { public: - TreeDisplayOverrideLibrary(SpaceOutliner &space_outliner); + TreeDisplayOverrideLibraryProperties(SpaceOutliner &space_outliner); ListBase buildTree(const TreeSourceData &source_data) override; @@ -140,6 +142,22 @@ class TreeDisplayOverrideLibrary final : public AbstractTreeDisplay { short id_filter_get() const; }; +/** + * \brief Tree-Display for the Library Overrides display mode, Hierarchies view mode. + */ +class TreeDisplayOverrideLibraryHierarchies final : public AbstractTreeDisplay { + public: + TreeDisplayOverrideLibraryHierarchies(SpaceOutliner &space_outliner); + + ListBase buildTree(const TreeSourceData &source_data) override; + + private: + ListBase build_hierarchy_for_lib_or_main(Main *bmain, + TreeElement &parent_te, + Library *lib = nullptr); + void build_hierarchy_for_ID(Main *bmain, ID &override_root_id, TreeElementID &te_id) const; +}; + /* -------------------------------------------------------------------- */ /* Video Sequencer Tree-Display */ diff --git a/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchies.cc b/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchies.cc new file mode 100644 index 00000000000..4b568a6004d --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchies.cc @@ -0,0 +1,224 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup spoutliner + */ + +#include "DNA_ID.h" +#include "DNA_collection_types.h" +#include "DNA_key_types.h" +#include "DNA_space_types.h" + +#include "BLI_listbase.h" +#include "BLI_map.hh" +#include "BLI_set.hh" + +#include "BLT_translation.h" + +#include "BKE_collection.h" +#include "BKE_lib_query.h" +#include "BKE_main.h" + +#include "../outliner_intern.hh" +#include "common.hh" +#include "tree_display.hh" +#include "tree_element_id.hh" + +namespace blender::ed::outliner { + +class AbstractTreeElement; + +TreeDisplayOverrideLibraryHierarchies::TreeDisplayOverrideLibraryHierarchies( + SpaceOutliner &space_outliner) + : AbstractTreeDisplay(space_outliner) +{ +} + +/* XXX Remove expanded subtree, we add our own items here. Expanding should probably be + * optional. */ +static void remove_expanded_children(TreeElement &te) +{ + outliner_free_tree(&te.subtree); +} + +ListBase TreeDisplayOverrideLibraryHierarchies::buildTree(const TreeSourceData &source_data) +{ + ListBase tree = {nullptr}; + + /* First step: Build "Current File" hierarchy. */ + TreeElement *current_file_te = outliner_add_element( + &space_outliner_, &tree, source_data.bmain, nullptr, TSE_ID_BASE, -1); + current_file_te->name = IFACE_("Current File"); + { + AbstractTreeElement::uncollapse_by_default(current_file_te); + build_hierarchy_for_lib_or_main(source_data.bmain, *current_file_te); + + /* Add dummy child if there's nothing to display. */ + if (BLI_listbase_is_empty(¤t_file_te->subtree)) { + TreeElement *dummy_te = outliner_add_element( + &space_outliner_, ¤t_file_te->subtree, nullptr, current_file_te, TSE_ID_BASE, 0); + dummy_te->name = IFACE_("No Library Overrides"); + } + } + + /* Second step: Build hierarchies for external libraries. */ + for (Library *lib = (Library *)source_data.bmain->libraries.first; lib; + lib = (Library *)lib->id.next) { + TreeElement *tenlib = outliner_add_element( + &space_outliner_, &tree, lib, nullptr, TSE_SOME_ID, 0); + build_hierarchy_for_lib_or_main(source_data.bmain, *tenlib, lib); + } + + /* Remove top level library elements again that don't contain any overrides. */ + LISTBASE_FOREACH_MUTABLE (TreeElement *, top_level_te, &tree) { + if (top_level_te == current_file_te) { + continue; + } + + if (BLI_listbase_is_empty(&top_level_te->subtree)) { + outliner_free_tree_element(top_level_te, &tree); + } + } + + return tree; +} + +ListBase TreeDisplayOverrideLibraryHierarchies::build_hierarchy_for_lib_or_main( + Main *bmain, TreeElement &parent_te, Library *lib) +{ + ListBase tree = {nullptr}; + + /* Keep track over which ID base elements were already added, and expand them once added. */ + Map<ID_Type, TreeElement *> id_base_te_map; + /* Index for the ID base elements ("Objects", "Materials", etc). */ + int base_index = 0; + + ID *iter_id; + FOREACH_MAIN_ID_BEGIN (bmain, iter_id) { + if (!ID_IS_OVERRIDE_LIBRARY_REAL(iter_id) || !ID_IS_OVERRIDE_LIBRARY_HIERARCHY_ROOT(iter_id)) { + continue; + } + if (iter_id->lib != lib) { + continue; + } + + TreeElement *new_base_te = id_base_te_map.lookup_or_add_cb(GS(iter_id->name), [&]() { + TreeElement *new_te = outliner_add_element(&space_outliner_, + &parent_te.subtree, + lib ? (void *)lib : bmain, + &parent_te, + TSE_ID_BASE, + base_index++); + new_te->name = outliner_idcode_to_plural(GS(iter_id->name)); + return new_te; + }); + + TreeElement *new_id_te = outliner_add_element( + &space_outliner_, &new_base_te->subtree, iter_id, new_base_te, TSE_SOME_ID, 0); + remove_expanded_children(*new_id_te); + + build_hierarchy_for_ID(bmain, *iter_id, *tree_element_cast<TreeElementID>(new_id_te)); + } + FOREACH_MAIN_ID_END; + + return tree; +} + +struct BuildHierarchyForeachIDCbData { + /* Don't allow copies, the sets below would need deep copying. */ + BuildHierarchyForeachIDCbData(const BuildHierarchyForeachIDCbData &) = delete; + + Main &bmain; + SpaceOutliner &space_outliner; + ID &override_root_id; + + /* The tree element to expand. Changes with every level of recursion. */ + TreeElementID *parent_te; + /* The ancestor IDs leading to the current ID, to avoid IDs recursing into themselves. Changes + * with every level of recursion. */ + Set<ID *> parent_ids{}; + /* The IDs that were already added to #parent_te, to avoid duplicates. Entirely new set with + * every level of recursion. */ + Set<ID *> sibling_ids{}; +}; + +static int build_hierarchy_foreach_ID_cb(LibraryIDLinkCallbackData *cb_data) +{ + if (!*cb_data->id_pointer) { + return IDWALK_RET_NOP; + } + + BuildHierarchyForeachIDCbData &build_data = *reinterpret_cast<BuildHierarchyForeachIDCbData *>( + cb_data->user_data); + /* Note that this may be an embedded ID (see #real_override_id). */ + ID &id = **cb_data->id_pointer; + /* If #id is an embedded ID, this will be set to the owner, which is a real ID and contains the + * override data. So queries of override data should be done via this, but the actual tree + * element we add is the embedded ID. */ + const ID *real_override_id = &id; + + if (ID_IS_OVERRIDE_LIBRARY_VIRTUAL(&id)) { + if (GS(id.name) == ID_KE) { + Key *key = (Key *)&id; + real_override_id = key->from; + } + else if (id.flag & LIB_EMBEDDED_DATA) { + /* TODO Needs double-checking if this handles all embedded IDs correctly. */ + real_override_id = cb_data->id_owner; + } + } + + if (!ID_IS_OVERRIDE_LIBRARY(real_override_id)) { + return IDWALK_RET_NOP; + } + /* Is this ID part of the same override hierarchy? */ + if (real_override_id->override_library->hierarchy_root != &build_data.override_root_id) { + return IDWALK_RET_NOP; + } + + /* Avoid endless recursion: If there is an ancestor for this ID already, it recurses into itself. + */ + if (build_data.parent_ids.lookup_key_default(&id, nullptr)) { + return IDWALK_RET_NOP; + } + + /* Avoid duplicates: If there is a sibling for this ID already, the same ID is just used multiple + * times by the same parent. */ + if (build_data.sibling_ids.lookup_key_default(&id, nullptr)) { + return IDWALK_RET_NOP; + } + + TreeElement *new_te = outliner_add_element(&build_data.space_outliner, + &build_data.parent_te->getLegacyElement().subtree, + &id, + &build_data.parent_te->getLegacyElement(), + TSE_SOME_ID, + 0); + remove_expanded_children(*new_te); + build_data.sibling_ids.add(&id); + + BuildHierarchyForeachIDCbData child_build_data{build_data.bmain, + build_data.space_outliner, + build_data.override_root_id, + tree_element_cast<TreeElementID>(new_te)}; + child_build_data.parent_ids = build_data.parent_ids; + child_build_data.parent_ids.add(&id); + child_build_data.sibling_ids.reserve(10); + BKE_library_foreach_ID_link( + &build_data.bmain, &id, build_hierarchy_foreach_ID_cb, &child_build_data, IDWALK_READONLY); + + return IDWALK_RET_NOP; +} + +void TreeDisplayOverrideLibraryHierarchies::build_hierarchy_for_ID(Main *bmain, + ID &override_root_id, + TreeElementID &te_id) const +{ + BuildHierarchyForeachIDCbData build_data{*bmain, space_outliner_, override_root_id, &te_id}; + build_data.parent_ids.add(&override_root_id); + + BKE_library_foreach_ID_link( + bmain, &te_id.get_ID(), build_hierarchy_foreach_ID_cb, &build_data, IDWALK_READONLY); +} + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_display_override_library.cc b/source/blender/editors/space_outliner/tree/tree_display_override_library_properties.cc index b5c0a10c834..4c57f91a0a7 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_override_library.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_override_library_properties.cc @@ -25,12 +25,12 @@ namespace blender::ed::outliner { /* Convenience/readability. */ template<typename T> using List = ListBaseWrapper<T>; -TreeDisplayOverrideLibrary::TreeDisplayOverrideLibrary(SpaceOutliner &space_outliner) +TreeDisplayOverrideLibraryProperties::TreeDisplayOverrideLibraryProperties(SpaceOutliner &space_outliner) : AbstractTreeDisplay(space_outliner) { } -ListBase TreeDisplayOverrideLibrary::buildTree(const TreeSourceData &source_data) +ListBase TreeDisplayOverrideLibraryProperties::buildTree(const TreeSourceData &source_data) { ListBase tree = add_library_contents(*source_data.bmain); @@ -44,7 +44,7 @@ ListBase TreeDisplayOverrideLibrary::buildTree(const TreeSourceData &source_data return tree; } -ListBase TreeDisplayOverrideLibrary::add_library_contents(Main &mainvar) +ListBase TreeDisplayOverrideLibraryProperties::add_library_contents(Main &mainvar) { ListBase tree = {nullptr}; @@ -69,7 +69,7 @@ ListBase TreeDisplayOverrideLibrary::add_library_contents(Main &mainvar) /* check if there's data in current id list */ for (ID *id_iter : List<ID>(lbarray[a])) { - if (ID_IS_OVERRIDE_LIBRARY_REAL(id_iter)) { + if (ID_IS_OVERRIDE_LIBRARY_REAL(id_iter) && !ID_IS_LINKED(id_iter)) { id = id_iter; break; } @@ -93,7 +93,7 @@ ListBase TreeDisplayOverrideLibrary::add_library_contents(Main &mainvar) } for (ID *id : List<ID>(lbarray[a])) { - if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + if (ID_IS_OVERRIDE_LIBRARY_REAL(id) && !ID_IS_LINKED(id)) { TreeElement *override_tree_element = outliner_add_element( &space_outliner_, lb_to_expand, id, id_base_te, TSE_LIBRARY_OVERRIDE_BASE, 0); @@ -114,7 +114,7 @@ ListBase TreeDisplayOverrideLibrary::add_library_contents(Main &mainvar) return tree; } -short TreeDisplayOverrideLibrary::id_filter_get() const +short TreeDisplayOverrideLibraryProperties::id_filter_get() const { if (space_outliner_.filter & SO_FILTER_ID_TYPE) { return space_outliner_.filter_id_type; diff --git a/source/blender/editors/space_outliner/tree/tree_element.cc b/source/blender/editors/space_outliner/tree/tree_element.cc index ca67aad00db..7fe3f08b3be 100644 --- a/source/blender/editors/space_outliner/tree/tree_element.cc +++ b/source/blender/editors/space_outliner/tree/tree_element.cc @@ -98,6 +98,13 @@ std::unique_ptr<AbstractTreeElement> AbstractTreeElement::createFromType(const i return nullptr; } +void AbstractTreeElement::uncollapse_by_default(TreeElement *legacy_te) +{ + if (!TREESTORE(legacy_te)->used) { + TREESTORE(legacy_te)->flag &= ~TSE_CLOSED; + } +} + void tree_element_expand(const AbstractTreeElement &tree_element, SpaceOutliner &space_outliner) { /* Most types can just expand. IDs optionally expand (hence the poll) and do additional, common diff --git a/source/blender/editors/space_outliner/tree/tree_element.hh b/source/blender/editors/space_outliner/tree/tree_element.hh index 6f2d803ae96..c6593a517dd 100644 --- a/source/blender/editors/space_outliner/tree/tree_element.hh +++ b/source/blender/editors/space_outliner/tree/tree_element.hh @@ -50,6 +50,19 @@ class AbstractTreeElement { return true; } + TreeElement &getLegacyElement() + { + return legacy_te_; + } + + /** + * Expand this tree element if it is displayed for the first time (as identified by its + * tree-store element). + * + * Static for now to allow doing this from the legacy tree element. + */ + static void uncollapse_by_default(TreeElement *legacy_te); + friend void tree_element_expand(const AbstractTreeElement &tree_element, SpaceOutliner &space_outliner); diff --git a/source/blender/editors/space_outliner/tree/tree_element_id.hh b/source/blender/editors/space_outliner/tree/tree_element_id.hh index b7519fe06f9..c2bbfd9f107 100644 --- a/source/blender/editors/space_outliner/tree/tree_element_id.hh +++ b/source/blender/editors/space_outliner/tree/tree_element_id.hh @@ -35,6 +35,11 @@ class TreeElementID : public AbstractTreeElement { return false; } + ID &get_ID() + { + return id_; + } + protected: /* ID types with animation data can use this. */ void expand_animation_data(SpaceOutliner &, const AnimData *) const; diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 3ccdf701a86..283bd99cd5d 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -1643,35 +1643,6 @@ void SEQUENCER_OT_split(struct wmOperatorType *ot) /** \name Duplicate Strips Operator * \{ */ -static void sequencer_backup_original_animation(Scene *scene, ListBase *list) -{ - if (scene->adt == NULL || scene->adt->action == NULL || - BLI_listbase_is_empty(&scene->adt->action->curves)) { - return; - } - - BLI_movelisttolist(list, &scene->adt->action->curves); -} - -static void sequencer_restore_original_animation(Scene *scene, ListBase *list) -{ - if (scene->adt == NULL || scene->adt->action == NULL || BLI_listbase_is_empty(list)) { - return; - } - - BLI_movelisttolist(&scene->adt->action->curves, list); -} - -static void sequencer_duplicate_animation(Scene *scene, Sequence *seq, ListBase *curves_backup) -{ - GSet *fcurves = SEQ_fcurves_by_strip_get(seq, curves_backup); - GSET_FOREACH_BEGIN (FCurve *, fcu, fcurves) { - FCurve *fcu_cpy = BKE_fcurve_copy(fcu); - BLI_addtail(&scene->adt->action->curves, fcu_cpy); - } - GSET_FOREACH_END(); -} - static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); @@ -1697,7 +1668,7 @@ static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) * original curves from backup. */ ListBase fcurves_original_backup = {NULL, NULL}; - sequencer_backup_original_animation(scene, &fcurves_original_backup); + SEQ_animation_backup_original(scene, &fcurves_original_backup); Sequence *seq = duplicated_strips.first; @@ -1712,11 +1683,11 @@ static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) SEQ_select_active_set(scene, seq); } seq->flag &= ~(SEQ_LEFTSEL + SEQ_RIGHTSEL + SEQ_LOCK); - sequencer_duplicate_animation(scene, seq, &fcurves_original_backup); + SEQ_animation_duplicate(scene, seq, &fcurves_original_backup); SEQ_ensure_unique_name(seq, scene); } - sequencer_restore_original_animation(scene, &fcurves_original_backup); + SEQ_animation_restore_original(scene, &fcurves_original_backup); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -2622,7 +2593,7 @@ static int sequencer_paste_exec(bContext *C, wmOperator *op) */ ListBase fcurves_original_backup = {NULL, NULL}; - sequencer_backup_original_animation(scene, &fcurves_original_backup); + SEQ_animation_backup_original(scene, &fcurves_original_backup); sequencer_paste_animation(C); /* Copy strips, temporarily restoring pointers to actual data-blocks. This @@ -2654,7 +2625,7 @@ static int sequencer_paste_exec(bContext *C, wmOperator *op) } } - sequencer_restore_original_animation(scene, &fcurves_original_backup); + SEQ_animation_restore_original(scene, &fcurves_original_backup); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); DEG_relations_tag_update(bmain); diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc index 0ad64db1b6d..4afa70d9ef6 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc @@ -4,6 +4,7 @@ #include "BKE_context.h" #include "BKE_editmesh.h" +#include "BKE_geometry_fields.hh" #include "BKE_global.h" #include "BKE_lib_id.h" #include "BKE_mesh.h" diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 15fea301b1c..49c0236866d 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -165,7 +165,7 @@ BLI_INLINE int text_pixel_x_to_column(SpaceText *st, const int x) static bool text_new_poll(bContext *UNUSED(C)) { - return 1; + return true; } static bool text_data_poll(bContext *C) @@ -182,15 +182,15 @@ static bool text_edit_poll(bContext *C) Text *text = CTX_data_edit_text(C); if (!text) { - return 0; + return false; } - if (ID_IS_LINKED(text)) { + if (!BKE_id_is_editable(CTX_data_main(C), &text->id)) { // BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data"); - return 0; + return false; } - return 1; + return true; } bool text_space_edit_poll(bContext *C) @@ -199,15 +199,15 @@ bool text_space_edit_poll(bContext *C) Text *text = CTX_data_edit_text(C); if (!st || !text) { - return 0; + return false; } - if (ID_IS_LINKED(text)) { + if (!BKE_id_is_editable(CTX_data_main(C), &text->id)) { // BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data"); - return 0; + return false; } - return 1; + return true; } static bool text_region_edit_poll(bContext *C) @@ -217,19 +217,19 @@ static bool text_region_edit_poll(bContext *C) ARegion *region = CTX_wm_region(C); if (!st || !text) { - return 0; + return false; } if (!region || region->regiontype != RGN_TYPE_WINDOW) { - return 0; + return false; } - if (ID_IS_LINKED(text)) { + if (!BKE_id_is_editable(CTX_data_main(C), &text->id)) { // BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data"); - return 0; + return false; } - return 1; + return true; } /** \} */ diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index e2a027837a7..3f2fbb97de1 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -8,6 +8,7 @@ #include <stdio.h> #include <string.h> +#include "DNA_collection_types.h" #include "DNA_defaults.h" #include "DNA_gpencil_types.h" #include "DNA_lightprobe_types.h" @@ -47,6 +48,7 @@ #include "ED_screen.h" #include "ED_space_api.h" #include "ED_transform.h" +#include "ED_undo.h" #include "GPU_matrix.h" @@ -562,6 +564,24 @@ static bool view3d_collection_drop_poll(bContext *C, wmDrag *drag, const wmEvent return view3d_drop_id_in_main_region_poll(C, drag, event, ID_GR); } +static bool view3d_collection_drop_poll_local_id(bContext *C, wmDrag *drag, const wmEvent *event) +{ + if (!view3d_collection_drop_poll(C, drag, event) || (drag->type != WM_DRAG_ID)) { + return false; + } + return true; +} + +static bool view3d_collection_drop_poll_external_asset(bContext *C, + wmDrag *drag, + const wmEvent *event) +{ + if (!view3d_collection_drop_poll(C, drag, event) || (drag->type != WM_DRAG_ASSET)) { + return false; + } + return true; +} + 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); @@ -682,7 +702,7 @@ static void view3d_ob_drop_matrix_from_snap(V3DSnapCursorState *snap_state, mat4_to_size(scale, ob->obmat); rescale_m4(obmat_final, scale); - BoundBox *bb = BKE_object_boundbox_get(ob); + const BoundBox *bb = BKE_object_boundbox_get(ob); if (bb) { float offset[3]; BKE_boundbox_calc_center_aabb(bb, offset); @@ -708,6 +728,8 @@ static void view3d_ob_drop_copy_local_id(wmDrag *drag, wmDropBox *drop) RNA_float_set_array(drop->ptr, "matrix", &obmat_final[0][0]); } +/* Mostly the same logic as #view3d_collection_drop_copy_external_asset(), just different enough to + * make sharing code a bit difficult. */ static void view3d_ob_drop_copy_external_asset(wmDrag *drag, wmDropBox *drop) { /* NOTE(@campbellbarton): Selection is handled here, de-selecting objects before append, @@ -749,11 +771,48 @@ static void view3d_ob_drop_copy_external_asset(wmDrag *drag, wmDropBox *drop) } } -static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop) +static void view3d_collection_drop_copy_local_id(wmDrag *drag, wmDropBox *drop) { - ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, ID_GR); + ID *id = WM_drag_get_local_ID(drag, ID_GR); + RNA_int_set(drop->ptr, "session_uuid", (int)id->session_uuid); +} + +/* Mostly the same logic as #view3d_ob_drop_copy_external_asset(), just different enough to make + * sharing code a bit difficult. */ +static void view3d_collection_drop_copy_external_asset(wmDrag *drag, wmDropBox *drop) +{ + BLI_assert(drag->type == WM_DRAG_ASSET); + + wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0); + bContext *C = asset_drag->evil_C; + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + + BKE_view_layer_base_deselect_all(view_layer); + + ID *id = WM_drag_asset_id_import(asset_drag, FILE_AUTOSELECT); + Collection *collection = (Collection *)id; + + /* TODO(sergey): Only update relations for the current scene. */ + DEG_relations_tag_update(CTX_data_main(C)); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); RNA_int_set(drop->ptr, "session_uuid", (int)id->session_uuid); + + /* Make an object active, just use the first one in the collection. */ + CollectionObject *cobject = collection->gobject.first; + Base *base = cobject ? BKE_view_layer_base_find(view_layer, cobject->ob) : NULL; + if (base) { + BLI_assert((base->flag & BASE_SELECTABLE) && (base->flag & BASE_ENABLED_VIEWPORT)); + BKE_view_layer_base_select_and_set_active(view_layer, base); + WM_main_add_notifier(NC_SCENE | ND_OB_ACTIVE, scene); + } + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + ED_outliner_select_sync_from_object_tag(C); + + /* XXX Without an undo push here, there will be a crash when the user modifies operator + * properties. The stuff we do in these drop callbacks just isn't safe over undo/redo. */ + ED_undo_push(C, "Collection_Drop"); } static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop) @@ -835,6 +894,19 @@ static void view3d_dropboxes(void) drop->draw_deactivate = view3d_ob_drop_draw_deactivate; WM_dropbox_add(lb, + "OBJECT_OT_collection_external_asset_drop", + view3d_collection_drop_poll_external_asset, + view3d_collection_drop_copy_external_asset, + WM_drag_free_imported_drag_ID, + NULL); + WM_dropbox_add(lb, + "OBJECT_OT_collection_instance_add", + view3d_collection_drop_poll_local_id, + view3d_collection_drop_copy_local_id, + WM_drag_free_imported_drag_ID, + NULL); + + WM_dropbox_add(lb, "OBJECT_OT_drop_named_material", view3d_mat_drop_poll, view3d_id_drop_copy, @@ -859,12 +931,6 @@ static void view3d_dropboxes(void) WM_drag_free_imported_drag_ID, NULL); WM_dropbox_add(lb, - "OBJECT_OT_collection_instance_add", - view3d_collection_drop_poll, - view3d_collection_drop_copy, - WM_drag_free_imported_drag_ID, - NULL); - WM_dropbox_add(lb, "OBJECT_OT_data_instance_add", view3d_object_data_drop_poll, view3d_id_drop_copy_with_type, diff --git a/source/blender/editors/space_view3d/view3d_cursor_snap.c b/source/blender/editors/space_view3d/view3d_cursor_snap.c index 53f7b3d5871..f3e45a14565 100644 --- a/source/blender/editors/space_view3d/view3d_cursor_snap.c +++ b/source/blender/editors/space_view3d/view3d_cursor_snap.c @@ -620,9 +620,6 @@ static void v3d_cursor_snap_update(V3DSnapCursorState *state, snap_elements &= ~SCE_SNAP_MODE_EDGE_PERPENDICULAR; } - eSnapSelect snap_select = (state->flag & V3D_SNAPCURSOR_SNAP_ONLY_ACTIVE) ? SNAP_ONLY_ACTIVE : - SNAP_ALL; - eSnapEditType edit_mode_type = (state->flag & V3D_SNAPCURSOR_SNAP_EDIT_GEOM_FINAL) ? SNAP_GEOM_FINAL : (state->flag & V3D_SNAPCURSOR_SNAP_EDIT_GEOM_CAGE) ? @@ -640,7 +637,7 @@ static void v3d_cursor_snap_update(V3DSnapCursorState *state, v3d, snap_elements, &(const struct SnapObjectParams){ - .snap_select = snap_select, + .snap_select = SNAP_ALL, .edit_mode_type = edit_mode_type, .use_occlusion_test = use_occlusion_test, }, diff --git a/source/blender/editors/space_view3d/view3d_gizmo_camera.c b/source/blender/editors/space_view3d/view3d_gizmo_camera.c index 4451d629a04..83f589a64c9 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_camera.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_camera.c @@ -11,6 +11,7 @@ #include "BKE_camera.h" #include "BKE_context.h" #include "BKE_layer.h" +#include "BKE_lib_id.h" #include "DNA_camera_types.h" #include "DNA_object_types.h" @@ -61,7 +62,7 @@ static bool WIDGETGROUP_camera_poll(const bContext *C, wmGizmoGroupType *UNUSED( if (ob->type == OB_CAMERA) { Camera *camera = ob->data; /* TODO: support overrides. */ - if (!ID_IS_LINKED(camera)) { + if (BKE_id_is_editable(CTX_data_main(C), &camera->id)) { return true; } } @@ -384,7 +385,7 @@ static bool WIDGETGROUP_camera_view_poll(const bContext *C, wmGizmoGroupType *UN if (rv3d->persp == RV3D_CAMOB) { if (scene->r.mode & R_BORDER) { /* TODO: support overrides. */ - if (!ID_IS_LINKED(scene)) { + if (BKE_id_is_editable(CTX_data_main(C), &scene->id)) { return true; } } diff --git a/source/blender/editors/space_view3d/view3d_navigate_fly.c b/source/blender/editors/space_view3d/view3d_navigate_fly.c index af78663fff9..399f422f411 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_fly.c +++ b/source/blender/editors/space_view3d/view3d_navigate_fly.c @@ -24,6 +24,7 @@ #include "BLI_math.h" #include "BKE_context.h" +#include "BKE_lib_id.h" #include "BKE_report.h" #include "BLT_translation.h" @@ -321,8 +322,12 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent fly->rv3d->persp = RV3D_PERSP; } - if (fly->rv3d->persp == RV3D_CAMOB && ID_IS_LINKED(fly->v3d->camera)) { - BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library"); + if (fly->rv3d->persp == RV3D_CAMOB && + !BKE_id_is_editable(CTX_data_main(C), &fly->v3d->camera->id)) { + BKE_report(op->reports, + RPT_ERROR, + "Cannot navigate a camera from an external library or non-editable override"); + return false; } diff --git a/source/blender/editors/space_view3d/view3d_navigate_walk.c b/source/blender/editors/space_view3d/view3d_navigate_walk.c index 333c99c2fca..18ed88aeec6 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_walk.c +++ b/source/blender/editors/space_view3d/view3d_navigate_walk.c @@ -22,6 +22,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_report.h" @@ -503,8 +504,11 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->rv3d->persp = RV3D_PERSP; } - if (walk->rv3d->persp == RV3D_CAMOB && ID_IS_LINKED(walk->v3d->camera)) { - BKE_report(op->reports, RPT_ERROR, "Cannot navigate a camera from an external library"); + if (walk->rv3d->persp == RV3D_CAMOB && + !BKE_id_is_editable(CTX_data_main(C), &walk->v3d->camera->id)) { + BKE_report(op->reports, + RPT_ERROR, + "Cannot navigate a camera from an external library or non-editable override"); return false; } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index d9388bc82ef..465f890d9f5 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1645,9 +1645,7 @@ static int bone_select_menu_exec(bContext *C, wmOperator *op) const int name_index = RNA_enum_get(op->ptr, "name"); const struct SelectPick_Params params = { - .sel_op = ED_select_op_from_booleans(RNA_boolean_get(op->ptr, "extend"), - RNA_boolean_get(op->ptr, "deselect"), - RNA_boolean_get(op->ptr, "toggle")), + .sel_op = ED_select_op_from_operator(op), }; View3D *v3d = CTX_wm_view3d(C); @@ -2746,11 +2744,6 @@ static bool ed_object_select_pick(bContext *C, if (params->sel_op == SEL_OP_SET) { if ((found && params->select_passthrough) && (basact->flag & BASE_SELECTED)) { found = false; - /* NOTE(@campbellbarton): Experimental behavior to set active even keeping the selection - * without this it's inconvenient to set the active object. */ - if (basact != oldbasact) { - use_activate_selected_base = true; - } } else if (found || params->deselect_all) { /* Deselect everything. */ @@ -2922,14 +2915,10 @@ static int view3d_select_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); Object *obact = CTX_data_active_object(C); - const struct SelectPick_Params params = { - .sel_op = ED_select_op_from_booleans(RNA_boolean_get(op->ptr, "extend"), - RNA_boolean_get(op->ptr, "deselect"), - RNA_boolean_get(op->ptr, "toggle")), - .deselect_all = RNA_boolean_get(op->ptr, "deselect_all"), - .select_passthrough = RNA_boolean_get(op->ptr, "select_passthrough"), - }; + struct SelectPick_Params params = {0}; + ED_select_pick_params_from_operator(op, ¶ms); + bool center = RNA_boolean_get(op->ptr, "center"); bool enumerate = RNA_boolean_get(op->ptr, "enumerate"); /* Only force object select for edit-mode to support vertex parenting, diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c index 3e788f2d643..744fc61ddcf 100644 --- a/source/blender/editors/space_view3d/view3d_utils.c +++ b/source/blender/editors/space_view3d/view3d_utils.c @@ -409,9 +409,6 @@ bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, const BoundBox *bb, fl if (bb == NULL) { return true; } - if (bb->flag & BOUNDBOX_DISABLED) { - return true; - } mul_m4_m4m4(persmatob, (float(*)[4])rv3d->persmat, obmat); @@ -423,10 +420,6 @@ bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const BoundBox *bb) if (bb == NULL) { return true; } - if (bb->flag & BOUNDBOX_DISABLED) { - return true; - } - return view3d_boundbox_clip_m4(bb, rv3d->persmatob); } diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index e7fcc401523..a56bbb1c1df 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -18,6 +18,7 @@ #include "BKE_gpencil_modifier.h" #include "BKE_idprop.h" #include "BKE_layer.h" +#include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_modifier.h" #include "BKE_object.h" @@ -84,7 +85,7 @@ static bool view3d_camera_to_view_poll(bContext *C) if (ED_view3d_context_user_region(C, &v3d, ®ion)) { RegionView3D *rv3d = region->regiondata; - if (v3d && v3d->camera && !ID_IS_LINKED(v3d->camera)) { + if (v3d && v3d->camera && BKE_id_is_editable(CTX_data_main(C), &v3d->camera->id)) { if (rv3d && (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM) == 0) { if (rv3d->persp != RV3D_CAMOB) { return true; diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt index c8033d9d767..68c4f4e76ca 100644 --- a/source/blender/editors/transform/CMakeLists.txt +++ b/source/blender/editors/transform/CMakeLists.txt @@ -90,7 +90,7 @@ set(SRC transform_orientations.c transform_snap.c transform_snap_animation.c - transform_snap_object.c + transform_snap_object.cc transform_snap_sequencer.c transform.h diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 975f4370425..4058d77f42f 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -59,8 +59,6 @@ * and being able to set it to zero is handy. */ /* #define USE_NUM_NO_ZERO */ -static void drawTransformApply(const struct bContext *C, ARegion *region, void *arg); - static void initSnapSpatial(TransInfo *t, float r_snap[2]); bool transdata_check_local_islands(TransInfo *t, short around) @@ -845,10 +843,6 @@ int transformEvent(TransInfo *t, const wmEvent *event) handled = true; } else if (event->type == MOUSEMOVE) { - if (t->modifiers & (MOD_CONSTRAINT_SELECT_AXIS | MOD_CONSTRAINT_SELECT_PLANE)) { - t->con.mode |= CON_SELECT; - } - copy_v2_v2_int(t->mval, event->mval); /* Use this for soft redraw. Might cause flicker in object mode */ @@ -1097,6 +1091,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) /* Confirm. */ postSelectConstraint(t); t->modifiers &= ~(MOD_CONSTRAINT_SELECT_AXIS | MOD_CONSTRAINT_SELECT_PLANE); + t->redraw = TREDRAW_HARD; } else { if (t->options & CTX_CAMERA) { @@ -1108,6 +1103,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) restoreTransObjects(t); transform_mode_init(t, NULL, TFM_TRACKBALL); } + t->redraw = TREDRAW_HARD; } else { t->modifiers |= (event->val == TFM_MODAL_AUTOCONSTRAINT) ? @@ -1116,13 +1112,13 @@ int transformEvent(TransInfo *t, const wmEvent *event) if (t->con.mode & CON_APPLY) { stopConstraint(t); } - else { - initSelectConstraint(t); - postSelectConstraint(t); - } + + initSelectConstraint(t); + /* Use #TREDRAW_SOFT so that #selectConstraint is only called on the next event. + * This allows us to "deselect" the constraint. */ + t->redraw = TREDRAW_SOFT; } } - t->redraw |= TREDRAW_HARD; handled = true; } break; @@ -1733,8 +1729,6 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve initTransInfo(C, t, op, event); if (t->spacetype == SPACE_VIEW3D) { - t->draw_handle_apply = ED_region_draw_cb_activate( - t->region->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW); t->draw_handle_view = ED_region_draw_cb_activate( t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW); t->draw_handle_pixel = ED_region_draw_cb_activate( @@ -1925,18 +1919,19 @@ void transformApply(bContext *C, TransInfo *t) { t->context = C; - if ((t->redraw & TREDRAW_HARD) || (t->draw_handle_apply == NULL && (t->redraw & TREDRAW_SOFT))) { + if (t->redraw == TREDRAW_HARD) { selectConstraint(t); if (t->transform) { t->transform(t, t->mval); /* calls recalcData() */ - viewRedrawForce(C, t); } - t->redraw = TREDRAW_NOTHING; } - else if (t->redraw & TREDRAW_SOFT) { + + if (t->redraw & TREDRAW_SOFT) { viewRedrawForce(C, t); } + t->redraw = TREDRAW_NOTHING; + /* If auto confirm is on, break after one pass */ if (t->options & CTX_AUTOCONFIRM) { t->state = TRANS_CONFIRM; @@ -1945,16 +1940,6 @@ void transformApply(bContext *C, TransInfo *t) t->context = NULL; } -static void drawTransformApply(const bContext *C, ARegion *UNUSED(region), void *arg) -{ - TransInfo *t = arg; - - if (t->redraw & TREDRAW_SOFT) { - t->redraw |= TREDRAW_HARD; - transformApply((bContext *)C, t); - } -} - int transformEnd(bContext *C, TransInfo *t) { int exit_code = OPERATOR_RUNNING_MODAL; diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 713cf487ac7..37478dfc187 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -188,8 +188,8 @@ typedef enum { /** #TransInfo.redraw */ typedef enum { TREDRAW_NOTHING = 0, - TREDRAW_HARD = 1, - TREDRAW_SOFT = 2, + TREDRAW_SOFT = (1 << 0), + TREDRAW_HARD = (1 << 1) | TREDRAW_SOFT, } eRedrawFlag; /** #TransInfo.helpline */ @@ -663,7 +663,6 @@ typedef struct TransInfo { int mval[2]; /** use for 3d view. */ float zfac; - void *draw_handle_apply; void *draw_handle_view; void *draw_handle_pixel; void *draw_handle_cursor; diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 81b35e4539b..0bb00032561 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -996,19 +996,10 @@ void selectConstraint(TransInfo *t) void postSelectConstraint(TransInfo *t) { - if (!(t->con.mode & CON_SELECT)) { - return; - } - - t->con.mode &= ~CON_AXIS0; - t->con.mode &= ~CON_AXIS1; - t->con.mode &= ~CON_AXIS2; t->con.mode &= ~CON_SELECT; - - setNearestAxis(t); - - startConstraint(t); - t->redraw = TREDRAW_HARD; + if (!(t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2))) { + t->con.mode &= ~CON_APPLY; + } } static void setNearestAxis2d(TransInfo *t) diff --git a/source/blender/editors/transform/transform_convert_node.c b/source/blender/editors/transform/transform_convert_node.c index 7a4b03b640c..d5d79bedbf4 100644 --- a/source/blender/editors/transform/transform_convert_node.c +++ b/source/blender/editors/transform/transform_convert_node.c @@ -129,6 +129,10 @@ void createTransNodeData(TransInfo *t) } } + if (tc->data_len == 0) { + return; + } + TransData *td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransNode TransData"); TransData2D *td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransNode TransData2D"); diff --git a/source/blender/editors/transform/transform_convert_object.c b/source/blender/editors/transform/transform_convert_object.c index b599e282959..bd6c6bb120f 100644 --- a/source/blender/editors/transform/transform_convert_object.c +++ b/source/blender/editors/transform/transform_convert_object.c @@ -13,6 +13,7 @@ #include "BKE_animsys.h" #include "BKE_context.h" #include "BKE_layer.h" +#include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_object.h" #include "BKE_pointcache.h" @@ -481,6 +482,7 @@ static void clear_trans_object_base_flags(TransInfo *t) void createTransObject(bContext *C, TransInfo *t) { + Main *bmain = CTX_data_main(C); TransData *td = NULL; TransDataExtension *tx; const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; @@ -527,7 +529,7 @@ void createTransObject(bContext *C, TransInfo *t) } /* select linked objects, but skip them later */ - if (ID_IS_LINKED(ob)) { + if (!BKE_id_is_editable(bmain, &ob->id)) { td->flag |= TD_SKIP; } diff --git a/source/blender/editors/transform/transform_convert_object_texspace.c b/source/blender/editors/transform/transform_convert_object_texspace.c index 763af1f3384..1f58ec80f02 100644 --- a/source/blender/editors/transform/transform_convert_object_texspace.c +++ b/source/blender/editors/transform/transform_convert_object_texspace.c @@ -63,7 +63,6 @@ void createTransTexspace(TransInfo *t) } td->flag = TD_SELECTED; - copy_v3_v3(td->center, ob->obmat[3]); td->ob = ob; copy_m3_m4(td->mtx, ob->obmat); @@ -77,6 +76,7 @@ void createTransTexspace(TransInfo *t) } copy_v3_v3(td->iloc, td->loc); + copy_v3_v3(td->center, td->loc); copy_v3_v3(td->ext->isize, td->ext->size); } diff --git a/source/blender/editors/transform/transform_convert_sculpt.c b/source/blender/editors/transform/transform_convert_sculpt.c index 0c6214668ba..5bf6bfa8644 100644 --- a/source/blender/editors/transform/transform_convert_sculpt.c +++ b/source/blender/editors/transform/transform_convert_sculpt.c @@ -10,6 +10,7 @@ #include "BLI_math.h" #include "BKE_context.h" +#include "BKE_lib_id.h" #include "BKE_paint.h" #include "BKE_report.h" @@ -27,7 +28,7 @@ void createTransSculpt(bContext *C, TransInfo *t) TransData *td; Scene *scene = t->scene; - if (ID_IS_LINKED(scene)) { + if (!BKE_id_is_editable(CTX_data_main(C), &scene->id)) { BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform"); return; } @@ -102,7 +103,7 @@ void recalcData_sculpt(TransInfo *t) void special_aftertrans_update__sculpt(bContext *C, TransInfo *t) { Scene *scene = t->scene; - if (ID_IS_LINKED(scene)) { + if (!BKE_id_is_editable(CTX_data_main(C), &scene->id)) { /* `ED_sculpt_init_transform` was not called in this case. */ return; } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 3b9e2a982dc..975dbc2e986 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -718,9 +718,6 @@ void postTrans(bContext *C, TransInfo *t) if (t->draw_handle_view) { ED_region_draw_cb_exit(t->region->type, t->draw_handle_view); } - if (t->draw_handle_apply) { - ED_region_draw_cb_exit(t->region->type, t->draw_handle_apply); - } if (t->draw_handle_pixel) { ED_region_draw_cb_exit(t->region->type, t->draw_handle_pixel); } diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index 955916ff437..aa8dad2b95f 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -939,7 +939,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob_iter = objects[ob_index]; - const bool use_mat_local = params->use_local_axis && (ob_iter != ob); + const bool use_mat_local = (ob_iter != ob); /* mislead counting bones... bah. We don't know the gizmo mode, could be mixed */ const int mode = TFM_ROTATION; @@ -951,7 +951,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, } /* Use channels to get stats. */ - LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { + LISTBASE_FOREACH (bPoseChannel *, pchan, &ob_iter->pose->chanbase) { if (!(pchan->bone->flag & BONE_TRANSFORM)) { continue; } diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index bf898b9053f..23619a2049a 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -579,89 +579,97 @@ static char snap_flag_from_spacetype(TransInfo *t) static short snap_mode_from_spacetype(TransInfo *t) { ToolSettings *ts = t->settings; - short r_snap_mode = SCE_SNAP_MODE_INCREMENT; if (t->spacetype == SPACE_NODE) { - r_snap_mode = ts->snap_node_mode; + return ts->snap_node_mode; } - else if (t->spacetype == SPACE_IMAGE) { - r_snap_mode = ts->snap_uv_mode; - if ((r_snap_mode & SCE_SNAP_MODE_INCREMENT) && (ts->snap_uv_flag & SCE_SNAP_ABS_GRID) && + + if (t->spacetype == SPACE_IMAGE) { + short snap_mode = ts->snap_uv_mode; + if ((snap_mode & SCE_SNAP_MODE_INCREMENT) && (ts->snap_uv_flag & SCE_SNAP_ABS_GRID) && (t->mode == TFM_TRANSLATION)) { - r_snap_mode &= ~SCE_SNAP_MODE_INCREMENT; - r_snap_mode |= SCE_SNAP_MODE_GRID; + snap_mode &= ~SCE_SNAP_MODE_INCREMENT; + snap_mode |= SCE_SNAP_MODE_GRID; } + return snap_mode; } - else if (t->spacetype == SPACE_SEQ) { - r_snap_mode = SEQ_tool_settings_snap_mode_get(t->scene); + + if (t->spacetype == SPACE_SEQ) { + return SEQ_tool_settings_snap_mode_get(t->scene); } - else if ((t->spacetype == SPACE_VIEW3D) && !(t->options & CTX_CAMERA)) { - /* All obedit types will match. */ - const int obedit_type = t->obedit_type; - if ((t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR | CTX_OBMODE_XFORM_OBDATA)) || - ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVES_LEGACY, OB_LATTICE, OB_MBALL, -1)) { - r_snap_mode = ts->snap_mode; - if ((r_snap_mode & SCE_SNAP_MODE_INCREMENT) && (ts->snap_flag & SCE_SNAP_ABS_GRID) && - (t->mode == TFM_TRANSLATION)) { - /* Special case in which snap to increments is transformed to snap to grid. */ - r_snap_mode &= ~SCE_SNAP_MODE_INCREMENT; - r_snap_mode |= SCE_SNAP_MODE_GRID; - } + + if (t->spacetype == SPACE_VIEW3D) { + if (t->options & (CTX_CAMERA | CTX_EDGE_DATA | CTX_PAINT_CURVE)) { + return SCE_SNAP_MODE_INCREMENT; } + + short snap_mode = ts->snap_mode; + if ((snap_mode & SCE_SNAP_MODE_INCREMENT) && (ts->snap_flag & SCE_SNAP_ABS_GRID) && + (t->mode == TFM_TRANSLATION)) { + /* Special case in which snap to increments is transformed to snap to grid. */ + snap_mode &= ~SCE_SNAP_MODE_INCREMENT; + snap_mode |= SCE_SNAP_MODE_GRID; + } + return snap_mode; } - else if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA)) { + + if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA)) { /* No incremental snapping. */ - r_snap_mode = 0; + return 0; } - return r_snap_mode; + return SCE_SNAP_MODE_INCREMENT; } static short snap_select_type_get(TransInfo *t) { - short r_snap_select = SNAP_ALL; - ViewLayer *view_layer = t->view_layer; Base *base_act = view_layer->basact; if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE) && !(t->options & CTX_CAMERA)) { - const int obedit_type = t->obedit_type; if (t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR | CTX_OBMODE_XFORM_OBDATA)) { /* In "Edit Strokes" mode, * snap tool can perform snap to selected or active objects (see T49632) * TODO: perform self snap in gpencil_strokes. * * When we're moving the origins, allow snapping onto our own geometry (see T69132). */ + return SNAP_ALL; } - else if ((obedit_type != -1) && - ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVES_LEGACY, OB_LATTICE, OB_MBALL)) { + + const int obedit_type = t->obedit_type; + if (obedit_type != -1) { /* Edit mode */ - /* Temporary limited to edit mode meshes, armature, curves, metaballs. */ + if (ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVES_LEGACY, OB_LATTICE, OB_MBALL)) { + /* Temporary limited to edit mode meshes, armature, curves, lattice and metaballs. */ - if ((obedit_type == OB_MESH) && (t->flag & T_PROP_EDIT)) { - /* Exclude editmesh if using proportional edit */ - r_snap_select = SNAP_NOT_ACTIVE; - } - else if (!t->tsnap.snap_self) { - r_snap_select = SNAP_NOT_ACTIVE; - } - else { - r_snap_select = SNAP_NOT_SELECTED; + if ((obedit_type == OB_MESH) && (t->flag & T_PROP_EDIT)) { + /* Exclude editmesh if using proportional edit */ + return SNAP_NOT_EDITED; + } + + if (!t->tsnap.snap_self) { + return SNAP_NOT_ACTIVE; + } + + return SNAP_NOT_SELECTED; } + + return SNAP_ALL; } - else if ((obedit_type == -1) && base_act && base_act->object && - (base_act->object->mode & OB_MODE_PARTICLE_EDIT)) { + + if (base_act && (base_act->object->mode & OB_MODE_PARTICLE_EDIT)) { /* Particles edit mode. */ + return SNAP_ALL; } - else if (obedit_type == -1) { - /* Object or pose mode. */ - r_snap_select = SNAP_NOT_SELECTED; - } + + /* Object or pose mode. */ + return SNAP_NOT_SELECTED; } - else if (ELEM(t->spacetype, SPACE_NODE, SPACE_SEQ)) { - r_snap_select = SNAP_NOT_SELECTED; + + if (ELEM(t->spacetype, SPACE_NODE, SPACE_SEQ)) { + return SNAP_NOT_SELECTED; } - return r_snap_select; + return SNAP_ALL; } static void initSnappingMode(TransInfo *t) diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.cc index 87053fe03d1..e879ca2b163 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.cc @@ -4,7 +4,7 @@ * \ingroup edtransform */ -#include <stdlib.h> +#include <cstdlib> #include "MEM_guardedalloc.h" @@ -55,11 +55,12 @@ enum eViewProj { VIEW_PROJ_PERSP = -1, }; -typedef struct SnapObjectData { - enum { - SNAP_MESH = 1, - SNAP_EDIT_MESH, - } type; +struct SnapObjectData { + enum class Type { + Mesh, + EditMesh, + }; + Type type; BVHTree *bvhtree[2]; /* MESH: loose edges, loose verts * EDIT_MESH: verts, edges. */ @@ -67,7 +68,7 @@ typedef struct SnapObjectData { union { struct { - /* SNAP_MESH */ + /* Type::Mesh */ BVHTreeFromMesh treedata_mesh; const struct MPoly *poly; uint has_looptris : 1; @@ -75,13 +76,13 @@ typedef struct SnapObjectData { uint has_loose_vert : 1; }; struct { - /* SNAP_EDIT_MESH */ + /* Type::EditMesh */ BVHTreeFromEditMesh treedata_editmesh; float min[3], max[3]; struct Mesh_Runtime *mesh_runtime; }; }; -} SnapObjectData; +}; struct SnapObjectContext { Scene *scene; @@ -129,29 +130,29 @@ struct SnapObjectContext { * \{ */ /* Mesh used for snapping. - * If NULL the BMesh should be used. */ -static Mesh *mesh_for_snap(Object *ob_eval, eSnapEditType edit_mode_type, bool *r_use_hide) + * If nullptr the BMesh should be used. */ +static const Mesh *mesh_for_snap(Object *ob_eval, eSnapEditType edit_mode_type, bool *r_use_hide) { - Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval); + const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval); bool use_hide = false; if (BKE_object_is_in_editmode(ob_eval)) { if (edit_mode_type == SNAP_GEOM_EDIT) { - return NULL; + return nullptr; } - Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob_eval); - Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob_eval); + const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob_eval); + const Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob_eval); if ((edit_mode_type == SNAP_GEOM_FINAL) && editmesh_eval_final) { if (editmesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) { - return NULL; + return nullptr; } me_eval = editmesh_eval_final; use_hide = true; } else if ((edit_mode_type == SNAP_GEOM_CAGE) && editmesh_eval_cage) { if (editmesh_eval_cage->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) { - return NULL; + return nullptr; } me_eval = editmesh_eval_cage; use_hide = true; @@ -185,24 +186,24 @@ static void bm_mesh_minmax(BMesh *bm, float r_min[3], float r_max[3]) static void snap_object_data_mesh_clear(SnapObjectData *sod) { - BLI_assert(sod->type == SNAP_MESH); + BLI_assert(sod->type == SnapObjectData::Type::Mesh); for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) { if (!sod->cached[i]) { BLI_bvhtree_free(sod->bvhtree[i]); } - sod->bvhtree[i] = NULL; + sod->bvhtree[i] = nullptr; } free_bvhtree_from_mesh(&sod->treedata_mesh); } static void snap_object_data_editmesh_clear(SnapObjectData *sod) { - BLI_assert(sod->type == SNAP_EDIT_MESH); + BLI_assert(sod->type == SnapObjectData::Type::EditMesh); for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) { if (!sod->cached[i]) { BLI_bvhtree_free(sod->bvhtree[i]); } - sod->bvhtree[i] = NULL; + sod->bvhtree[i] = nullptr; } free_bvhtree_from_editmesh(&sod->treedata_editmesh); } @@ -210,11 +211,11 @@ static void snap_object_data_editmesh_clear(SnapObjectData *sod) static void snap_object_data_clear(SnapObjectData *sod) { switch (sod->type) { - case SNAP_MESH: { + case SnapObjectData::Type::Mesh: { snap_object_data_mesh_clear(sod); break; } - case SNAP_EDIT_MESH: { + case SnapObjectData::Type::EditMesh: { snap_object_data_editmesh_clear(sod); break; } @@ -224,13 +225,15 @@ static void snap_object_data_clear(SnapObjectData *sod) static SnapObjectData *snap_object_data_lookup(SnapObjectContext *sctx, Object *ob_eval) { - SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob_eval); - if (sod == NULL) { - if (sctx->cache.data_to_object_map != NULL) { - ob_eval = BLI_ghash_lookup(sctx->cache.data_to_object_map, ob_eval->data); + SnapObjectData *sod = static_cast<SnapObjectData *>( + BLI_ghash_lookup(sctx->cache.object_map, ob_eval)); + if (sod == nullptr) { + if (sctx->cache.data_to_object_map != nullptr) { + ob_eval = static_cast<Object *>( + BLI_ghash_lookup(sctx->cache.data_to_object_map, ob_eval->data)); /* Could be NULl when mixing edit-mode and non edit-mode objects. */ - if (ob_eval != NULL) { - sod = BLI_ghash_lookup(sctx->cache.object_map, ob_eval); + if (ob_eval != nullptr) { + sod = static_cast<SnapObjectData *>(BLI_ghash_lookup(sctx->cache.object_map, ob_eval)); } } } @@ -247,9 +250,9 @@ static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, bool init = false; if (BLI_ghash_ensure_p(sctx->cache.object_map, ob_eval, &sod_p)) { - sod = *sod_p; + sod = static_cast<SnapObjectData *>(*sod_p); bool is_dirty = false; - if (sod->type != SNAP_MESH) { + if (sod->type != SnapObjectData::Type::Mesh) { is_dirty = true; } else if (sod->treedata_mesh.tree && sod->treedata_mesh.cached && @@ -290,21 +293,22 @@ static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, } } else { - sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + sod = static_cast<SnapObjectData *>(*sod_p); init = true; } if (init) { - sod->type = SNAP_MESH; + sod->type = SnapObjectData::Type::Mesh; /* The BVHTree from looptris is always required. */ - BLI_assert(sod->treedata_mesh.tree == NULL); + BLI_assert(sod->treedata_mesh.tree == nullptr); BKE_bvhtree_from_mesh_get(&sod->treedata_mesh, me_eval, use_hide ? BVHTREE_FROM_LOOPTRI_NO_HIDDEN : BVHTREE_FROM_LOOPTRI, 4); - if (sod->treedata_mesh.tree == NULL) { + if (sod->treedata_mesh.tree == nullptr) { sod->treedata_mesh.vert = me_eval->mvert; sod->treedata_mesh.vert_normals = BKE_mesh_vertex_normals_ensure(me_eval); sod->treedata_mesh.loop = me_eval->mloop; @@ -312,10 +316,10 @@ static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, BLI_assert(sod->has_looptris == false); } else { - BLI_assert(sod->treedata_mesh.vert != NULL); - BLI_assert(sod->treedata_mesh.vert_normals != NULL); - BLI_assert(sod->treedata_mesh.loop != NULL); - BLI_assert(sod->treedata_mesh.looptri != NULL); + BLI_assert(sod->treedata_mesh.vert != nullptr); + BLI_assert(sod->treedata_mesh.vert_normals != nullptr); + BLI_assert(sod->treedata_mesh.loop != nullptr); + BLI_assert(sod->treedata_mesh.looptri != nullptr); sod->has_looptris = true; } @@ -357,12 +361,12 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx, { /* Use object-data as the key in ghash since the editmesh * is used to create bvhtree and is the same for each linked object. */ - if (sctx->cache.data_to_object_map == NULL) { + if (sctx->cache.data_to_object_map == nullptr) { sctx->cache.data_to_object_map = BLI_ghash_ptr_new(__func__); } void **ob_p; if (BLI_ghash_ensure_p(sctx->cache.data_to_object_map, ob_eval->data, &ob_p)) { - ob_eval = *ob_p; + ob_eval = static_cast<Object *>(*ob_p); } else { *ob_p = ob_eval; @@ -370,10 +374,10 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx, } if (BLI_ghash_ensure_p(sctx->cache.object_map, ob_eval, &sod_p)) { - sod = *sod_p; + sod = static_cast<SnapObjectData *>(*sod_p); bool is_dirty = false; /* Check if the geometry has changed. */ - if (sod->type != SNAP_EDIT_MESH) { + if (sod->type != SnapObjectData::Type::EditMesh) { is_dirty = true; } else if (sod->treedata_editmesh.em != em) { @@ -413,12 +417,13 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx, } } else { - sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + sod = static_cast<SnapObjectData *>(*sod_p); init = true; } if (init) { - sod->type = SNAP_EDIT_MESH; + sod->type = SnapObjectData::Type::EditMesh; sod->treedata_editmesh.em = em; sod->mesh_runtime = snap_object_data_editmesh_runtime_get(ob_eval); bm_mesh_minmax(em->bm, sod->min, sod->max); @@ -433,12 +438,12 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx, /** \name Iterator * \{ */ -typedef void (*IterSnapObjsCallback)(SnapObjectContext *sctx, - const struct SnapObjectParams *params, - Object *ob_eval, - float obmat[4][4], - bool is_object_active, - void *data); +using IterSnapObjsCallback = void (*)(SnapObjectContext *sctx, + const struct SnapObjectParams *params, + Object *ob_eval, + float obmat[4][4], + bool is_object_active, + void *data); static bool snap_object_is_snappable(const SnapObjectContext *sctx, const eSnapSelect snap_select, @@ -459,7 +464,11 @@ static bool snap_object_is_snappable(const SnapObjectContext *sctx, } if (snap_select == SNAP_NOT_ACTIVE) { - return base_act == base; + return base_act != base; + } + + if (snap_select == SNAP_NOT_EDITED) { + return base->object->mode != OB_MODE_EDIT; } if (snap_select == SNAP_NOT_SELECTED) { @@ -490,14 +499,8 @@ static void iter_snap_objects(SnapObjectContext *sctx, const eSnapSelect snap_select = params->snap_select; Base *base_act = view_layer->basact; - if (snap_select == SNAP_ONLY_ACTIVE) { - Object *obj_eval = DEG_get_evaluated_object(sctx->runtime.depsgraph, base_act->object); - sob_callback(sctx, params, obj_eval, obj_eval->obmat, true, data); - return; - } - const bool is_in_object_mode = !base_act || base_act->object->mode == OB_MODE_OBJECT; - for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) { + LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { if (!snap_object_is_snappable(sctx, snap_select, base_act, base, is_in_object_mode)) { continue; } @@ -506,7 +509,7 @@ static void iter_snap_objects(SnapObjectContext *sctx, Object *obj_eval = DEG_get_evaluated_object(sctx->runtime.depsgraph, base->object); if (obj_eval->transflag & OB_DUPLI || BKE_object_has_geometry_set_instances(obj_eval)) { ListBase *lb = object_duplilist(sctx->runtime.depsgraph, sctx->scene, obj_eval); - for (DupliObject *dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { + LISTBASE_FOREACH (DupliObject *, dupli_ob, lb) { BLI_assert(DEG_is_evaluated_object(dupli_ob->ob)); sob_callback(sctx, params, dupli_ob->ob, dupli_ob->mat, is_object_active, data); } @@ -554,7 +557,7 @@ static struct SnapObjectHitDepth *hit_depth_create(const float depth, const float obmat[4][4], uint ob_uuid) { - struct SnapObjectHitDepth *hit = MEM_mallocN(sizeof(*hit), __func__); + struct SnapObjectHitDepth *hit = MEM_new<SnapObjectHitDepth>(__func__); hit->depth = depth; copy_v3_v3(hit->co, co); @@ -570,8 +573,8 @@ static struct SnapObjectHitDepth *hit_depth_create(const float depth, static int hit_depth_cmp(const void *arg1, const void *arg2) { - const struct SnapObjectHitDepth *h1 = arg1; - const struct SnapObjectHitDepth *h2 = arg2; + const struct SnapObjectHitDepth *h1 = static_cast<const struct SnapObjectHitDepth *>(arg1); + const struct SnapObjectHitDepth *h2 = static_cast<const struct SnapObjectHitDepth *>(arg2); int val = 0; if (h1->depth < h2->depth) { @@ -586,7 +589,7 @@ static int hit_depth_cmp(const void *arg1, const void *arg2) static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) { - struct RayCastAll_Data *data = userdata; + struct RayCastAll_Data *data = static_cast<struct RayCastAll_Data *>(userdata); data->raycast_callback(data->bvhdata, index, ray, hit); if (hit->index != -1) { /* Get all values in world-space. */ @@ -715,11 +718,11 @@ static bool raycastMesh(SnapObjectContext *sctx, } /* Test BoundBox */ - BoundBox *bb = BKE_object_boundbox_get(ob_eval); + const BoundBox *bb = BKE_object_boundbox_get(ob_eval); if (bb) { /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */ if (!isect_ray_aabb_v3_simple( - ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &len_diff, NULL)) { + ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &len_diff, nullptr)) { return retval; } } @@ -739,14 +742,14 @@ static bool raycastMesh(SnapObjectContext *sctx, BVHTreeFromMesh *treedata = &sod->treedata_mesh; - if (treedata->tree == NULL) { + if (treedata->tree == nullptr) { return retval; } float timat[3][3]; /* transpose inverse matrix for normals */ transpose_m3_m4(timat, imat); - BLI_assert(treedata->raycast_callback != NULL); + BLI_assert(treedata->raycast_callback != nullptr); if (r_hit_list) { struct RayCastAll_Data data; @@ -772,10 +775,9 @@ static bool raycastMesh(SnapObjectContext *sctx, retval = data.retval; } else { - BVHTreeRayHit hit = { - .index = -1, - .dist = local_depth, - }; + BVHTreeRayHit hit{}; + hit.index = -1; + hit.dist = local_depth; if (BLI_bvhtree_ray_cast(treedata->tree, ray_start_local, @@ -859,7 +861,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx, /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */ if (!isect_ray_aabb_v3_simple( - ray_start_local, ray_normal_local, sod->min, sod->max, &len_diff, NULL)) { + ray_start_local, ray_normal_local, sod->min, sod->max, &len_diff, nullptr)) { return retval; } @@ -877,7 +879,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx, BVHTreeFromEditMesh *treedata = &sod->treedata_editmesh; - if (treedata->tree == NULL) { + if (treedata->tree == nullptr) { /* Operators only update the editmesh looptris of the original mesh. */ BLI_assert(sod->treedata_editmesh.em == BKE_editmesh_from_object(DEG_get_original_object(ob_eval))); @@ -894,8 +896,16 @@ static bool raycastEditMesh(SnapObjectContext *sctx, sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data); - bvhtree_from_editmesh_looptri_ex( - treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, 0, NULL, NULL); + bvhtree_from_editmesh_looptri_ex(treedata, + em, + elem_mask, + looptri_num_active, + 0.0f, + 4, + 6, + BVHTREE_FROM_EM_LOOPTRI, + nullptr, + nullptr); MEM_freeN(elem_mask); } @@ -907,10 +917,10 @@ static bool raycastEditMesh(SnapObjectContext *sctx, 4, BVHTREE_FROM_EM_LOOPTRI, &sod->mesh_runtime->bvh_cache, - sod->mesh_runtime->eval_mutex); + static_cast<ThreadMutex *>(sod->mesh_runtime->eval_mutex)); } - if (treedata->tree == NULL) { + if (treedata->tree == nullptr) { return retval; } } @@ -943,10 +953,9 @@ static bool raycastEditMesh(SnapObjectContext *sctx, retval = data.retval; } else { - BVHTreeRayHit hit = { - .index = -1, - .dist = local_depth, - }; + BVHTreeRayHit hit{}; + hit.index = -1; + hit.dist = local_depth; if (BLI_bvhtree_ray_cast(treedata->tree, ray_start_local, @@ -1013,7 +1022,7 @@ static void raycast_obj_fn(SnapObjectContext *sctx, bool is_object_active, void *data) { - struct RaycastObjUserData *dt = data; + RaycastObjUserData *dt = static_cast<RaycastObjUserData *>(data); const uint ob_index = dt->ob_index++; bool use_occlusion_test = dt->use_occlusion_test; /* read/write args */ @@ -1032,8 +1041,8 @@ static void raycast_obj_fn(SnapObjectContext *sctx, case OB_MESH: { const eSnapEditType edit_mode_type = params->edit_mode_type; bool use_hide = false; - Mesh *me_eval = mesh_for_snap(ob_eval, edit_mode_type, &use_hide); - if (me_eval == NULL) { + const Mesh *me_eval = mesh_for_snap(ob_eval, edit_mode_type, &use_hide); + if (me_eval == nullptr) { /* Operators only update the editmesh looptris of the original mesh. */ BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob_eval)); retval = raycastEditMesh(sctx, @@ -1154,20 +1163,19 @@ static bool raycastObjects(SnapObjectContext *sctx, } } - struct RaycastObjUserData data = { - .ray_start = ray_start, - .ray_dir = ray_dir, - .ob_index = 0, - .ray_depth = ray_depth, - .r_loc = r_loc, - .r_no = r_no, - .r_index = r_index, - .r_ob = r_ob, - .r_obmat = r_obmat, - .r_hit_list = r_hit_list, - .use_occlusion_test = params->use_occlusion_test, - .ret = false, - }; + RaycastObjUserData data = {}; + data.ray_start = ray_start; + data.ray_dir = ray_dir; + data.ob_index = 0; + data.ray_depth = ray_depth; + data.r_loc = r_loc; + data.r_no = r_no; + data.r_index = r_index; + data.r_ob = r_ob; + data.r_obmat = r_obmat; + data.r_hit_list = r_hit_list; + data.use_occlusion_test = params->use_occlusion_test; + data.ret = false; iter_snap_objects(sctx, params, raycast_obj_fn, &data); @@ -1211,24 +1219,24 @@ static bool snap_bound_box_check_dist(const float min[3], struct Nearest2dUserData; -typedef void (*Nearest2DGetVertCoCallback)(const int index, - const struct Nearest2dUserData *data, - const float **r_co); -typedef void (*Nearest2DGetEdgeVertsCallback)(const int index, +using Nearest2DGetVertCoCallback = void (*)(const int index, + const struct Nearest2dUserData *data, + const float **r_co); +using Nearest2DGetEdgeVertsCallback = void (*)(const int index, + const struct Nearest2dUserData *data, + int r_v_index[2]); +using Nearest2DGetTriVertsCallback = void (*)(const int index, const struct Nearest2dUserData *data, - int r_v_index[2]); -typedef void (*Nearest2DGetTriVertsCallback)(const int index, - const struct Nearest2dUserData *data, - int r_v_index[3]); + int r_v_index[3]); /* Equal the previous one */ -typedef void (*Nearest2DGetTriEdgesCallback)(const int index, +using Nearest2DGetTriEdgesCallback = void (*)(const int index, + const struct Nearest2dUserData *data, + int r_e_index[3]); +using Nearest2DCopyVertNoCallback = void (*)(const int index, const struct Nearest2dUserData *data, - int r_e_index[3]); -typedef void (*Nearest2DCopyVertNoCallback)(const int index, - const struct Nearest2dUserData *data, - float r_no[3]); + float r_no[3]); -typedef struct Nearest2dUserData { +struct Nearest2dUserData { Nearest2DGetVertCoCallback get_vert_co; Nearest2DGetEdgeVertsCallback get_edge_verts_index; Nearest2DGetTriVertsCallback get_tri_verts_index; @@ -1250,7 +1258,7 @@ typedef struct Nearest2dUserData { bool is_persp; bool use_backface_culling; -} Nearest2dUserData; +}; static void cb_mvert_co_get(const int index, const Nearest2dUserData *data, const float **r_co) { @@ -1386,7 +1394,7 @@ static void cb_snap_vert(void *userdata, const int clip_plane_len, BVHTreeNearest *nearest) { - Nearest2dUserData *data = userdata; + Nearest2dUserData *data = static_cast<Nearest2dUserData *>(userdata); const float *co; data->get_vert_co(index, data, &co); @@ -1410,7 +1418,7 @@ static void cb_snap_edge(void *userdata, const int clip_plane_len, BVHTreeNearest *nearest) { - struct Nearest2dUserData *data = userdata; + Nearest2dUserData *data = static_cast<Nearest2dUserData *>(userdata); int vindex[2]; data->get_edge_verts_index(index, data, vindex); @@ -1439,7 +1447,7 @@ static void cb_snap_edge_verts(void *userdata, const int clip_plane_len, BVHTreeNearest *nearest) { - struct Nearest2dUserData *data = userdata; + Nearest2dUserData *data = static_cast<Nearest2dUserData *>(userdata); int vindex[2]; data->get_edge_verts_index(index, data, vindex); @@ -1459,7 +1467,7 @@ static void cb_snap_tri_edges(void *userdata, const int clip_plane_len, BVHTreeNearest *nearest) { - Nearest2dUserData *data = userdata; + Nearest2dUserData *data = static_cast<Nearest2dUserData *>(userdata); if (data->use_backface_culling) { int vindex[3]; @@ -1494,7 +1502,7 @@ static void cb_snap_tri_verts(void *userdata, const int clip_plane_len, BVHTreeNearest *nearest) { - struct Nearest2dUserData *data = userdata; + Nearest2dUserData *data = static_cast<Nearest2dUserData *>(userdata); int vindex[3]; data->get_tri_verts_index(index, data, vindex); @@ -1523,7 +1531,7 @@ static void nearest2d_data_init(SnapObjectData *sod, bool use_backface_culling, Nearest2dUserData *r_nearest2d) { - if (sod->type == SNAP_MESH) { + if (sod->type == SnapObjectData::Type::Mesh) { r_nearest2d->get_vert_co = cb_mvert_co_get; r_nearest2d->get_edge_verts_index = cb_medge_verts_get; r_nearest2d->copy_vert_no = cb_mvert_no_copy; @@ -1537,12 +1545,12 @@ static void nearest2d_data_init(SnapObjectData *sod, r_nearest2d->looptri = sod->treedata_mesh.looptri; } else { - BLI_assert(sod->type == SNAP_EDIT_MESH); + BLI_assert(sod->type == SnapObjectData::Type::EditMesh); r_nearest2d->get_vert_co = cb_bvert_co_get; r_nearest2d->get_edge_verts_index = cb_bedge_verts_get; r_nearest2d->copy_vert_no = cb_bvert_no_copy; - r_nearest2d->get_tri_verts_index = NULL; - r_nearest2d->get_tri_edges_index = NULL; + r_nearest2d->get_tri_verts_index = nullptr; + r_nearest2d->get_tri_edges_index = nullptr; r_nearest2d->bm = sod->treedata_editmesh.em->bm; } @@ -1583,26 +1591,25 @@ static short snap_mesh_polygon(SnapObjectContext *sctx, mul_v4_m4v4(clip_planes_local[i], tobmat, sctx->runtime.clip_plane[i]); } - BVHTreeNearest nearest = { - .index = -1, - .dist_sq = square_f(*dist_px), - }; + BVHTreeNearest nearest{}; + nearest.index = -1; + nearest.dist_sq = square_f(*dist_px); SnapObjectData *sod = snap_object_data_lookup(sctx, ob_eval); - BLI_assert(sod != NULL); + BLI_assert(sod != nullptr); Nearest2dUserData nearest2d; nearest2d_data_init( sod, sctx->runtime.view_proj == VIEW_PROJ_PERSP, params->use_backface_culling, &nearest2d); - if (sod->type == SNAP_MESH) { + if (sod->type == SnapObjectData::Type::Mesh) { BVHTreeFromMesh *treedata = &sod->treedata_mesh; const MPoly *mp = &sod->poly[*r_index]; const MLoop *ml = &treedata->loop[mp->loopstart]; if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) { elem = SCE_SNAP_MODE_EDGE; - BLI_assert(treedata->edge != NULL); + BLI_assert(treedata->edge != nullptr); for (int i = mp->totloop; i--; ml++) { cb_snap_edge(&nearest2d, ml->e, @@ -1625,7 +1632,7 @@ static short snap_mesh_polygon(SnapObjectContext *sctx, } } else { - BLI_assert(sod->type == SNAP_EDIT_MESH); + BLI_assert(sod->type == SnapObjectData::Type::EditMesh); BMEditMesh *em = sod->treedata_editmesh.em; BM_mesh_elem_table_ensure(em->bm, BM_FACE); @@ -1702,7 +1709,7 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, } SnapObjectData *sod = snap_object_data_lookup(sctx, ob_eval); - BLI_assert(sod != NULL); + BLI_assert(sod != nullptr); Nearest2dUserData nearest2d; nearest2d_data_init( @@ -1724,10 +1731,9 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, &neasrest_precalc, lpmat, sctx->runtime.win_size, sctx->runtime.mval); } - BVHTreeNearest nearest = { - .index = -1, - .dist_sq = square_f(original_dist_px), - }; + BVHTreeNearest nearest{}; + nearest.index = -1; + nearest.dist_sq = square_f(original_dist_px); float lambda; if (!isect_ray_line_v3(neasrest_precalc.ray_origin, @@ -1749,7 +1755,7 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, int v_id = lambda < 0.5f ? 0 : 1; if (test_projected_vert_dist(&neasrest_precalc, - NULL, + nullptr, 0, nearest2d.is_persp, v_pair[v_id], @@ -1775,7 +1781,7 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, mid_v3_v3v3(vmid, v_pair[0], v_pair[1]); if (test_projected_vert_dist(&neasrest_precalc, - NULL, + nullptr, 0, nearest2d.is_persp, vmid, @@ -1802,7 +1808,7 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, &neasrest_precalc, sctx->runtime.pmat, sctx->runtime.win_size, sctx->runtime.mval); if (test_projected_vert_dist(&neasrest_precalc, - NULL, + nullptr, 0, nearest2d.is_persp, v_near, @@ -1855,12 +1861,12 @@ static short snapArmature(SnapObjectContext *sctx, dist_squared_to_projected_aabb_precalc( &neasrest_precalc, lpmat, sctx->runtime.win_size, sctx->runtime.mval); - bArmature *arm = ob_eval->data; - const bool is_editmode = arm->edbo != NULL; + bArmature *arm = static_cast<bArmature *>(ob_eval->data); + const bool is_editmode = arm->edbo != nullptr; if (is_editmode == false) { /* Test BoundBox */ - BoundBox *bb = BKE_armature_boundbox_get(ob_eval); + const BoundBox *bb = BKE_armature_boundbox_get(ob_eval); if (bb && !snap_bound_box_check_dist(bb->vec[0], bb->vec[6], lpmat, @@ -2015,7 +2021,7 @@ static short snapCurve(SnapObjectContext *sctx, return 0; } - Curve *cu = ob_eval->data; + Curve *cu = static_cast<Curve *>(ob_eval->data); float dist_px_sq = square_f(*dist_px); float lpmat[4][4]; @@ -2060,7 +2066,7 @@ static short snapCurve(SnapObjectContext *sctx, bool is_persp = sctx->runtime.view_proj == VIEW_PROJ_PERSP; bool skip_selected = params->snap_select == SNAP_NOT_SELECTED; - for (Nurb *nu = (use_obedit ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, (use_obedit ? &cu->editnurb->nurbs : &cu->nurb)) { for (int u = 0; u < nu->pntsu; u++) { if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX) { if (use_obedit) { @@ -2243,7 +2249,7 @@ static short snapCamera(const SnapObjectContext *sctx, MovieClip *clip = BKE_object_movieclip_get(scene, object, false); MovieTracking *tracking; - if (clip == NULL) { + if (clip == nullptr) { return snap_object_center(sctx, object, obmat, dist_px, r_loc, r_no, r_index); } if (object->transflag & OB_DUPLI) { @@ -2262,11 +2268,8 @@ static short snapCamera(const SnapObjectContext *sctx, dist_squared_to_projected_aabb_precalc( &neasrest_precalc, sctx->runtime.pmat, sctx->runtime.win_size, sctx->runtime.mval); - MovieTrackingObject *tracking_object; - for (tracking_object = tracking->objects.first; tracking_object; - tracking_object = tracking_object->next) { + LISTBASE_FOREACH (MovieTrackingObject *, tracking_object, &tracking->objects) { ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object); - MovieTrackingTrack *track; float reconstructed_camera_mat[4][4], reconstructed_camera_imat[4][4]; float(*vertex_obmat)[4]; @@ -2277,7 +2280,7 @@ static short snapCamera(const SnapObjectContext *sctx, invert_m4_m4(reconstructed_camera_imat, reconstructed_camera_mat); } - for (track = tracksbase->first; track; track = track->next) { + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) { float bundle_pos[3]; if ((track->flag & TRACK_HAS_BUNDLE) == 0) { @@ -2322,7 +2325,7 @@ static short snapCamera(const SnapObjectContext *sctx, static short snapMesh(SnapObjectContext *sctx, const struct SnapObjectParams *params, Object *ob_eval, - Mesh *me_eval, + const Mesh *me_eval, const float obmat[4][4], bool use_hide, /* read/write args */ @@ -2346,7 +2349,7 @@ static short snapMesh(SnapObjectContext *sctx, float dist_px_sq = square_f(*dist_px); /* Test BoundBox */ - BoundBox *bb = BKE_object_boundbox_get(ob_eval); + const BoundBox *bb = BKE_object_boundbox_get(ob_eval); if (bb && !snap_bound_box_check_dist( bb->vec[0], bb->vec[6], lpmat, sctx->runtime.win_size, sctx->runtime.mval, dist_px_sq)) { @@ -2358,10 +2361,10 @@ static short snapMesh(SnapObjectContext *sctx, BVHTreeFromMesh *treedata, treedata_tmp; treedata = &sod->treedata_mesh; - if (sod->has_loose_edge && sod->bvhtree[0] == NULL) { + if (sod->has_loose_edge && sod->bvhtree[0] == nullptr) { sod->bvhtree[0] = BKE_bvhtree_from_mesh_get( &treedata_tmp, me_eval, BVHTREE_FROM_LOOSEEDGES, 2); - if (sod->bvhtree[0] == NULL) { + if (sod->bvhtree[0] == nullptr) { sod->has_loose_edge = false; } sod->cached[0] = treedata_tmp.cached; @@ -2374,10 +2377,10 @@ static short snapMesh(SnapObjectContext *sctx, } if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX) { - if (sod->has_loose_vert && sod->bvhtree[1] == NULL) { + if (sod->has_loose_vert && sod->bvhtree[1] == nullptr) { sod->bvhtree[1] = BKE_bvhtree_from_mesh_get( &treedata_tmp, me_eval, BVHTREE_FROM_LOOSEVERTS, 2); - if (sod->bvhtree[1] == NULL) { + if (sod->bvhtree[1] == nullptr) { sod->has_loose_vert = false; } sod->cached[1] = treedata_tmp.cached; @@ -2398,10 +2401,10 @@ static short snapMesh(SnapObjectContext *sctx, nearest2d_data_init( sod, sctx->runtime.view_proj == VIEW_PROJ_PERSP, params->use_backface_culling, &nearest2d); - BVHTreeNearest nearest = { - .index = -1, - .dist_sq = dist_px_sq, - }; + BVHTreeNearest nearest{}; + nearest.index = -1; + nearest.dist_sq = dist_px_sq; + int last_index = nearest.index; short elem = SCE_SNAP_MODE_VERTEX; @@ -2551,10 +2554,11 @@ static short snapEditMesh(SnapObjectContext *sctx, } if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX) { - BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[0]}; + BVHTreeFromEditMesh treedata{}; + treedata.tree = sod->bvhtree[0]; - if (treedata.tree == NULL) { - BLI_bitmap *verts_mask = NULL; + if (treedata.tree == nullptr) { + BLI_bitmap *verts_mask = nullptr; int verts_num_active = -1; if (sctx->callbacks.edit_mesh.test_vert_fn) { verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__); @@ -2565,8 +2569,16 @@ static short snapEditMesh(SnapObjectContext *sctx, (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn, sctx->callbacks.edit_mesh.user_data); - bvhtree_from_editmesh_verts_ex( - &treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL, NULL); + bvhtree_from_editmesh_verts_ex(&treedata, + em, + verts_mask, + verts_num_active, + 0.0f, + 2, + 6, + BVHTREE_FROM_VERTS, + nullptr, + nullptr); MEM_freeN(verts_mask); } else { @@ -2583,10 +2595,11 @@ static short snapEditMesh(SnapObjectContext *sctx, } if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) { - BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[1]}; + BVHTreeFromEditMesh treedata{}; + treedata.tree = sod->bvhtree[1]; - if (treedata.tree == NULL) { - BLI_bitmap *edges_mask = NULL; + if (treedata.tree == nullptr) { + BLI_bitmap *edges_mask = nullptr; int edges_num_active = -1; if (sctx->callbacks.edit_mesh.test_edge_fn) { edges_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__); @@ -2597,8 +2610,16 @@ static short snapEditMesh(SnapObjectContext *sctx, (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn, sctx->callbacks.edit_mesh.user_data); - bvhtree_from_editmesh_edges_ex( - &treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL, NULL); + bvhtree_from_editmesh_edges_ex(&treedata, + em, + edges_mask, + edges_num_active, + 0.0f, + 2, + 6, + BVHTREE_FROM_VERTS, + nullptr, + nullptr); MEM_freeN(edges_mask); } else { @@ -2607,7 +2628,7 @@ static short snapEditMesh(SnapObjectContext *sctx, 2, BVHTREE_FROM_EM_EDGES, &sod->mesh_runtime->bvh_cache, - sod->mesh_runtime->eval_mutex); + static_cast<ThreadMutex *>(sod->mesh_runtime->eval_mutex)); } sod->bvhtree[1] = treedata.tree; sod->cached[1] = treedata.cached; @@ -2618,10 +2639,10 @@ static short snapEditMesh(SnapObjectContext *sctx, nearest2d_data_init( sod, sctx->runtime.view_proj == VIEW_PROJ_PERSP, params->use_backface_culling, &nearest2d); - BVHTreeNearest nearest = { - .index = -1, - .dist_sq = dist_px_sq, - }; + BVHTreeNearest nearest{}; + nearest.index = -1; + nearest.dist_sq = dist_px_sq; + short elem = SCE_SNAP_MODE_VERTEX; float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4]; @@ -2713,15 +2734,15 @@ static void snap_obj_fn(SnapObjectContext *sctx, bool is_object_active, void *data) { - struct SnapObjUserData *dt = data; + SnapObjUserData *dt = static_cast<SnapObjUserData *>(data); short retval = 0; switch (ob_eval->type) { case OB_MESH: { const eSnapEditType edit_mode_type = params->edit_mode_type; bool use_hide; - Mesh *me_eval = mesh_for_snap(ob_eval, edit_mode_type, &use_hide); - if (me_eval == NULL) { + const Mesh *me_eval = mesh_for_snap(ob_eval, edit_mode_type, &use_hide); + if (me_eval == nullptr) { /* Operators only update the editmesh looptris of the original mesh. */ BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob_eval)); retval = snapEditMesh( @@ -2762,7 +2783,7 @@ static void snap_obj_fn(SnapObjectContext *sctx, break; /* Use ATTR_FALLTHROUGH if we want to snap to the generated mesh. */ case OB_SURF: case OB_FONT: { - Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval); + const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval); if (mesh_eval) { retval |= snapMesh(sctx, params, @@ -2835,15 +2856,14 @@ static short snapObjectsRay(SnapObjectContext *sctx, Object **r_ob, float r_obmat[4][4]) { - struct SnapObjUserData data = { - .dist_px = dist_px, - .r_loc = r_loc, - .r_no = r_no, - .r_ob = r_ob, - .r_index = r_index, - .r_obmat = r_obmat, - .ret = 0, - }; + SnapObjUserData data = {}; + data.dist_px = dist_px; + data.r_loc = r_loc; + data.r_no = r_no; + data.r_ob = r_ob; + data.r_index = r_index; + data.r_obmat = r_obmat; + data.ret = 0; iter_snap_objects(sctx, params, snap_obj_fn, &data); @@ -2858,7 +2878,7 @@ static short snapObjectsRay(SnapObjectContext *sctx, SnapObjectContext *ED_transform_snap_object_context_create(Scene *scene, int flag) { - SnapObjectContext *sctx = MEM_callocN(sizeof(*sctx), __func__); + SnapObjectContext *sctx = MEM_cnew<SnapObjectContext>(__func__); sctx->flag = flag; @@ -2866,7 +2886,7 @@ SnapObjectContext *ED_transform_snap_object_context_create(Scene *scene, int fla sctx->cache.object_map = BLI_ghash_ptr_new(__func__); /* Initialize as needed (edit-mode only). */ - sctx->cache.data_to_object_map = NULL; + sctx->cache.data_to_object_map = nullptr; sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); return sctx; @@ -2874,15 +2894,15 @@ SnapObjectContext *ED_transform_snap_object_context_create(Scene *scene, int fla static void snap_object_data_free(void *sod_v) { - SnapObjectData *sod = sod_v; + SnapObjectData *sod = static_cast<SnapObjectData *>(sod_v); snap_object_data_clear(sod); } void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx) { - BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free); - if (sctx->cache.data_to_object_map != NULL) { - BLI_ghash_free(sctx->cache.data_to_object_map, NULL, NULL); + BLI_ghash_free(sctx->cache.object_map, nullptr, snap_object_data_free); + if (sctx->cache.data_to_object_map != nullptr) { + BLI_ghash_free(sctx->cache.data_to_object_map, nullptr, nullptr); } BLI_memarena_free(sctx->cache.mem_arena); @@ -2919,8 +2939,17 @@ bool ED_transform_snap_object_project_ray_ex(SnapObjectContext *sctx, sctx->runtime.depsgraph = depsgraph; sctx->runtime.v3d = v3d; - return raycastObjects( - sctx, params, ray_start, ray_normal, ray_depth, r_loc, r_no, r_index, r_ob, r_obmat, NULL); + return raycastObjects(sctx, + params, + ray_start, + ray_normal, + ray_depth, + r_loc, + r_no, + r_index, + r_ob, + r_obmat, + nullptr); } bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx, @@ -2944,8 +2973,17 @@ bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx, float ray_depth_prev = ray_depth; #endif - bool retval = raycastObjects( - sctx, params, ray_start, ray_normal, &ray_depth, NULL, NULL, NULL, NULL, NULL, r_hit_list); + bool retval = raycastObjects(sctx, + params, + ray_start, + ray_normal, + &ray_depth, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + r_hit_list); /* meant to be readonly for 'all' hits, ensure it is */ #ifdef DEBUG @@ -2988,9 +3026,9 @@ static bool transform_snap_context_project_ray_impl(SnapObjectContext *sctx, ray_depth, r_co, r_no, - NULL, - NULL, - NULL); + nullptr, + nullptr, + nullptr); return ret; } @@ -3006,7 +3044,7 @@ bool ED_transform_snap_object_project_ray(SnapObjectContext *sctx, float r_no[3]) { float ray_depth_fallback; - if (ray_depth == NULL) { + if (ray_depth == nullptr) { ray_depth_fallback = BVH_RAYCAST_DIST_MAX; ray_depth = &ray_depth_fallback; } @@ -3043,7 +3081,7 @@ static short transform_snap_context_project_view3d_mixed_impl( short retval = 0; bool has_hit = false; - Object *ob_eval = NULL; + Object *ob_eval = nullptr; float loc[3]; /* Not all snapping callbacks set the normal, * initialize this since any hit copies both the `loc` and `no`. */ @@ -3051,14 +3089,14 @@ static short transform_snap_context_project_view3d_mixed_impl( float obmat[4][4]; int index = -1; - const RegionView3D *rv3d = region->regiondata; + const RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata); bool use_occlusion_test = params->use_occlusion_test && !XRAY_ENABLED(v3d); if (snap_to_flag & SCE_SNAP_MODE_FACE || use_occlusion_test) { float ray_start[3], ray_normal[3]; if (!ED_view3d_win_to_ray_clipped_ex( - depsgraph, region, v3d, mval, NULL, ray_normal, ray_start, true)) { + depsgraph, region, v3d, mval, nullptr, ray_normal, ray_start, true)) { return 0; } @@ -3074,7 +3112,7 @@ static short transform_snap_context_project_view3d_mixed_impl( &index, &ob_eval, obmat, - NULL); + nullptr); if (has_hit) { if (r_face_nor) { @@ -3119,10 +3157,10 @@ static short transform_snap_context_project_view3d_mixed_impl( } planes_from_projmat(sctx->runtime.pmat, - NULL, - NULL, - NULL, - NULL, + nullptr, + nullptr, + nullptr, + nullptr, sctx->runtime.clip_plane[0], sctx->runtime.clip_plane[1]); @@ -3255,10 +3293,10 @@ short ED_transform_snap_object_project_view3d(SnapObjectContext *sctx, dist_px, r_loc, r_no, - NULL, - NULL, - NULL, - NULL); + nullptr, + nullptr, + nullptr, + nullptr); } bool ED_transform_snap_object_project_all_view3d_ex(SnapObjectContext *sctx, @@ -3274,7 +3312,7 @@ bool ED_transform_snap_object_project_all_view3d_ex(SnapObjectContext *sctx, float ray_start[3], ray_normal[3]; if (!ED_view3d_win_to_ray_clipped_ex( - depsgraph, region, v3d, mval, NULL, ray_normal, ray_start, true)) { + depsgraph, region, v3d, mval, nullptr, ray_normal, ray_start, true)) { return false; } diff --git a/source/blender/editors/util/ed_transverts.c b/source/blender/editors/util/ed_transverts.c index c1e093d5555..8d8f7733877 100644 --- a/source/blender/editors/util/ed_transverts.c +++ b/source/blender/editors/util/ed_transverts.c @@ -33,7 +33,7 @@ #include "ED_transverts.h" /* own include */ -/* copied from editobject.c, now uses (almost) proper depgraph */ +/* copied from editobject.c, now uses (almost) proper depsgraph. */ void ED_transverts_update_obedit(TransVertStore *tvs, Object *obedit) { const int mode = tvs->mode; diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index 32d405df841..f07364cd4d3 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -19,6 +19,7 @@ #include "BKE_collection.h" #include "BKE_global.h" +#include "BKE_lib_id.h" #include "BKE_lib_remap.h" #include "BKE_main.h" #include "BKE_material.h" @@ -124,8 +125,9 @@ void ED_editors_init(bContext *C) if (obact == NULL || ob->type != obact->type) { continue; } - /* Object mode is enforced for linked data (or their obdata). */ - if (ID_IS_LINKED(ob) || (ob_data != NULL && ID_IS_LINKED(ob_data))) { + /* Object mode is enforced for non-editable data (or their obdata). */ + if (!BKE_id_is_editable(bmain, &ob->id) || + (ob_data != NULL && !BKE_id_is_editable(bmain, ob_data))) { continue; } diff --git a/source/blender/editors/util/ed_util_ops.cc b/source/blender/editors/util/ed_util_ops.cc index 25deacbcdd1..ccc28353518 100644 --- a/source/blender/editors/util/ed_util_ops.cc +++ b/source/blender/editors/util/ed_util_ops.cc @@ -226,7 +226,8 @@ static int lib_id_fake_user_toggle_exec(bContext *C, wmOperator *op) ID *id = (ID *)idptr.data; - if (ID_IS_LINKED(id) || (ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) { + if (!BKE_id_is_editable(CTX_data_main(C), id) || + (ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) { BKE_report(op->reports, RPT_ERROR, "Data-block type does not support fake user"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/util/select_utils.c b/source/blender/editors/util/select_utils.c index 380c7ed0e43..53f9aca8e8d 100644 --- a/source/blender/editors/util/select_utils.c +++ b/source/blender/editors/util/select_utils.c @@ -10,6 +10,12 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "DNA_windowmanager_types.h" + +#include "RNA_access.h" + +#include "WM_types.h" + #include "ED_select_utils.h" int ED_select_op_action(const eSelectOp sel_op, const bool is_select, const bool is_inside) @@ -113,8 +119,12 @@ bool ED_select_similar_compare_float_tree(const KDTree_1d *tree, return false; } -eSelectOp ED_select_op_from_booleans(const bool extend, const bool deselect, const bool toggle) +eSelectOp ED_select_op_from_operator(wmOperator *op) { + const bool extend = RNA_boolean_get(op->ptr, "extend"); + const bool deselect = RNA_boolean_get(op->ptr, "deselect"); + const bool toggle = RNA_boolean_get(op->ptr, "toggle"); + if (extend) { return SEL_OP_ADD; } @@ -126,3 +136,11 @@ eSelectOp ED_select_op_from_booleans(const bool extend, const bool deselect, con } return SEL_OP_SET; } + +void ED_select_pick_params_from_operator(wmOperator *op, struct SelectPick_Params *params) +{ + memset(params, 0x0, sizeof(*params)); + params->sel_op = ED_select_op_from_operator(op); + params->deselect_all = RNA_boolean_get(op->ptr, "deselect_all"); + params->select_passthrough = RNA_boolean_get(op->ptr, "select_passthrough"); +} diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt index f8a192e3254..761e7cd091e 100644 --- a/source/blender/editors/uvedit/CMakeLists.txt +++ b/source/blender/editors/uvedit/CMakeLists.txt @@ -7,6 +7,7 @@ set(INC ../../blentranslation ../../bmesh ../../depsgraph + ../../geometry ../../gpu ../../makesdna ../../makesrna @@ -24,7 +25,6 @@ set(SRC uvedit_draw.c uvedit_islands.c uvedit_ops.c - uvedit_parametrizer.c uvedit_path.c uvedit_rip.c uvedit_select.c @@ -32,7 +32,6 @@ set(SRC uvedit_unwrap_ops.c uvedit_intern.h - uvedit_parametrizer.h ) set(LIB diff --git a/source/blender/editors/uvedit/uvedit_islands.c b/source/blender/editors/uvedit/uvedit_islands.c index 59992d23e2e..e1752ae5a29 100644 --- a/source/blender/editors/uvedit/uvedit_islands.c +++ b/source/blender/editors/uvedit/uvedit_islands.c @@ -5,7 +5,7 @@ * * Utilities for manipulating UV islands. * - * \note This is similar to `uvedit_parametrizer.c`, + * \note This is similar to `GEO_uv_parametrizer.h`, * however the data structures there don't support arbitrary topology * such as an edge with 3 or more faces using it. * This API uses #BMesh data structures and doesn't have limitations for manifold meshes. diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.h b/source/blender/editors/uvedit/uvedit_parametrizer.h deleted file mode 100644 index f234fbe2ace..00000000000 --- a/source/blender/editors/uvedit/uvedit_parametrizer.h +++ /dev/null @@ -1,99 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#pragma once - -/** \file - * \ingroup eduv - */ - -#include "BLI_sys_types.h" /* for intptr_t support */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void ParamHandle; /* handle to a set of charts */ -typedef intptr_t ParamKey; /* (hash) key for identifying verts and faces */ -typedef enum ParamBool { - PARAM_TRUE = 1, - PARAM_FALSE = 0, -} ParamBool; - -/* Chart construction: - * ------------------- - * - faces and seams may only be added between construct_{begin|end} - * - the pointers to co and uv are stored, rather than being copied - * - vertices are implicitly created - * - in construct_end the mesh will be split up according to the seams - * - the resulting charts must be: - * - manifold, connected, open (at least one boundary loop) - * - output will be written to the uv pointers - */ - -ParamHandle *param_construct_begin(void); - -void param_aspect_ratio(ParamHandle *handle, float aspx, float aspy); - -void param_face_add(ParamHandle *handle, - ParamKey key, - int nverts, - ParamKey *vkeys, - float *co[4], - float *uv[4], - ParamBool *pin, - ParamBool *select); - -void param_edge_set_seam(ParamHandle *handle, ParamKey *vkeys); - -void param_construct_end(ParamHandle *handle, - ParamBool fill, - ParamBool topology_from_uvs, - int *count_fail); -void param_delete(ParamHandle *handle); - -/* Least Squares Conformal Maps: - * ----------------------------- - * - charts with less than two pinned vertices are assigned 2 pins - * - lscm is divided in three steps: - * - begin: compute matrix and its factorization (expensive) - * - solve using pinned coordinates (cheap) - * - end: clean up - * - uv coordinates are allowed to change within begin/end, for - * quick re-solving - */ - -void param_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf); -void param_lscm_solve(ParamHandle *handle, int *count_changed, int *count_failed); -void param_lscm_end(ParamHandle *handle); - -/* Stretch */ - -void param_stretch_begin(ParamHandle *handle); -void param_stretch_blend(ParamHandle *handle, float blend); -void param_stretch_iter(ParamHandle *handle); -void param_stretch_end(ParamHandle *handle); - -/* Area Smooth */ - -void param_smooth_area(ParamHandle *handle); - -/* Packing */ - -void param_pack(ParamHandle *handle, float margin, bool do_rotate, bool ignore_pinned); - -/* Average area for all charts */ - -void param_average(ParamHandle *handle, bool ignore_pinned); - -/* Simple x,y scale */ - -void param_scale(ParamHandle *handle, float x, float y); - -/* Flushing */ - -void param_flush(ParamHandle *handle); -void param_flush_restore(ParamHandle *handle); - -#ifdef __cplusplus -} -#endif diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c index ed4aa6985c4..1287804d9ee 100644 --- a/source/blender/editors/uvedit/uvedit_select.c +++ b/source/blender/editors/uvedit/uvedit_select.c @@ -2052,7 +2052,7 @@ static int uv_select_more_less(bContext *C, const bool select) } /* If the current face is not selected and at least one neighboring face is - * selected, then tag the current face to grow selection.*/ + * selected, then tag the current face to grow selection. */ if (sel_state == (NEIGHBORING_FACE_IS_SEL | CURR_FACE_IS_UNSEL)) { BM_elem_flag_enable(efa, BM_ELEM_TAG); changed = true; @@ -2622,13 +2622,9 @@ static int uv_select_exec(bContext *C, wmOperator *op) float co[2]; RNA_float_get_array(op->ptr, "location", co); - const struct SelectPick_Params params = { - .sel_op = ED_select_op_from_booleans(RNA_boolean_get(op->ptr, "extend"), - RNA_boolean_get(op->ptr, "deselect"), - RNA_boolean_get(op->ptr, "toggle")), - .deselect_all = RNA_boolean_get(op->ptr, "deselect_all"), - .select_passthrough = RNA_boolean_get(op->ptr, "select_passthrough"), - }; + + struct SelectPick_Params params = {0}; + ED_select_pick_params_from_operator(op, ¶ms); const bool changed = uv_mouse_select(C, co, ¶ms); @@ -3382,7 +3378,8 @@ static void uv_select_flush_from_tag_loop(const Scene *scene, Object *obedit, co * but dealing with sticky modes for vertex selections is best done in a separate function. * * \note Current behavior is selecting only; deselecting can be added but the behavior isn't - * required anywhere.*/ + * required anywhere. + */ static void uv_select_flush_from_loop_edge_flag(const Scene *scene, BMEditMesh *em) { const ToolSettings *ts = scene->toolsettings; diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index 63300656fda..609fa72d56b 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -46,6 +46,8 @@ #include "DEG_depsgraph.h" +#include "GEO_uv_parametrizer.h" + #include "PIL_time.h" #include "UI_interface.h" @@ -64,7 +66,6 @@ #include "WM_types.h" #include "uvedit_intern.h" -#include "uvedit_parametrizer.h" /* -------------------------------------------------------------------- */ /** \name Utility Functions @@ -319,7 +320,7 @@ static void construct_param_handle_face_add(ParamHandle *handle, select[i] = uvedit_uv_select_test(scene, l, cd_loop_uv_offset); } - param_face_add(handle, key, i, vkeys, co, uv, pin, select); + GEO_uv_parametrizer_face_add(handle, key, i, vkeys, co, uv, pin, select); } /* See: construct_param_handle_multi to handle multiple objects at once. */ @@ -338,7 +339,7 @@ static ParamHandle *construct_param_handle(const Scene *scene, const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - handle = param_construct_begin(); + handle = GEO_uv_parametrizer_construct_begin(); if (options->correct_aspect) { float aspx, aspy; @@ -346,7 +347,7 @@ static ParamHandle *construct_param_handle(const Scene *scene, ED_uvedit_get_aspect(ob, &aspx, &aspy); if (aspx != aspy) { - param_aspect_ratio(handle, aspx, aspy); + GEO_uv_parametrizer_aspect_ratio(handle, aspx, aspy); } } @@ -385,15 +386,15 @@ static ParamHandle *construct_param_handle(const Scene *scene, ParamKey vkeys[2]; vkeys[0] = (ParamKey)BM_elem_index_get(eed->v1); vkeys[1] = (ParamKey)BM_elem_index_get(eed->v2); - param_edge_set_seam(handle, vkeys); + GEO_uv_parametrizer_edge_set_seam(handle, vkeys); } } } - param_construct_end(handle, - options->fill_holes, - options->topology_from_uvs, - result_info ? &result_info->count_failed : NULL); + GEO_uv_parametrizer_construct_end(handle, + options->fill_holes, + options->topology_from_uvs, + result_info ? &result_info->count_failed : NULL); return handle; } @@ -414,7 +415,7 @@ static ParamHandle *construct_param_handle_multi(const Scene *scene, BMIter iter, liter; int i; - handle = param_construct_begin(); + handle = GEO_uv_parametrizer_construct_begin(); if (options->correct_aspect) { Object *ob = objects[0]; @@ -422,7 +423,7 @@ static ParamHandle *construct_param_handle_multi(const Scene *scene, ED_uvedit_get_aspect(ob, &aspx, &aspy); if (aspx != aspy) { - param_aspect_ratio(handle, aspx, aspy); + GEO_uv_parametrizer_aspect_ratio(handle, aspx, aspy); } } @@ -474,14 +475,15 @@ static ParamHandle *construct_param_handle_multi(const Scene *scene, ParamKey vkeys[2]; vkeys[0] = (ParamKey)BM_elem_index_get(eed->v1); vkeys[1] = (ParamKey)BM_elem_index_get(eed->v2); - param_edge_set_seam(handle, vkeys); + GEO_uv_parametrizer_edge_set_seam(handle, vkeys); } } } offset += bm->totface; } - param_construct_end(handle, options->fill_holes, options->topology_from_uvs, count_fail); + GEO_uv_parametrizer_construct_end( + handle, options->fill_holes, options->topology_from_uvs, count_fail); return handle; } @@ -560,7 +562,7 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene, const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - handle = param_construct_begin(); + handle = GEO_uv_parametrizer_construct_begin(); if (options->correct_aspect) { float aspx, aspy; @@ -568,7 +570,7 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene, ED_uvedit_get_aspect(ob, &aspx, &aspy); if (aspx != aspy) { - param_aspect_ratio(handle, aspx, aspy); + GEO_uv_parametrizer_aspect_ratio(handle, aspx, aspy); } } @@ -689,7 +691,7 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene, &pin[3], &select[3]); - param_face_add(handle, key, 4, vkeys, co, uv, pin, select); + GEO_uv_parametrizer_face_add(handle, key, 4, vkeys, co, uv, pin, select); } /* these are calculated from original mesh too */ @@ -698,14 +700,14 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene, ParamKey vkeys[2]; vkeys[0] = (ParamKey)edge->v1; vkeys[1] = (ParamKey)edge->v2; - param_edge_set_seam(handle, vkeys); + GEO_uv_parametrizer_edge_set_seam(handle, vkeys); } } - param_construct_end(handle, - options->fill_holes, - options->topology_from_uvs, - result_info ? &result_info->count_failed : NULL); + GEO_uv_parametrizer_construct_end(handle, + options->fill_holes, + options->topology_from_uvs, + result_info ? &result_info->count_failed : NULL); /* cleanup */ MEM_freeN(faceMap); @@ -764,9 +766,9 @@ static bool minimize_stretch_init(bContext *C, wmOperator *op) ms->handle = construct_param_handle_multi(scene, objects, objects_len, &options, NULL); ms->lasttime = PIL_check_seconds_timer(); - param_stretch_begin(ms->handle); + GEO_uv_parametrizer_stretch_begin(ms->handle); if (ms->blend != 0.0f) { - param_stretch_blend(ms->handle, ms->blend); + GEO_uv_parametrizer_stretch_blend(ms->handle, ms->blend); } op->customdata = ms; @@ -782,8 +784,8 @@ static void minimize_stretch_iteration(bContext *C, wmOperator *op, bool interac ToolSettings *ts = scene->toolsettings; const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0; - param_stretch_blend(ms->handle, ms->blend); - param_stretch_iter(ms->handle); + GEO_uv_parametrizer_stretch_blend(ms->handle, ms->blend); + GEO_uv_parametrizer_stretch_iter(ms->handle); ms->i++; RNA_int_set(op->ptr, "iterations", ms->i); @@ -791,7 +793,7 @@ static void minimize_stretch_iteration(bContext *C, wmOperator *op, bool interac if (interactive && (PIL_check_seconds_timer() - ms->lasttime > 0.5)) { char str[UI_MAX_DRAW_STR]; - param_flush(ms->handle); + GEO_uv_parametrizer_flush(ms->handle); if (area) { BLI_snprintf(str, sizeof(str), TIP_("Minimize Stretch. Blend %.2f"), ms->blend); @@ -831,14 +833,14 @@ static void minimize_stretch_exit(bContext *C, wmOperator *op, bool cancel) } if (cancel) { - param_flush_restore(ms->handle); + GEO_uv_parametrizer_flush_restore(ms->handle); } else { - param_flush(ms->handle); + GEO_uv_parametrizer_flush(ms->handle); } - param_stretch_end(ms->handle); - param_delete(ms->handle); + GEO_uv_parametrizer_stretch_end(ms->handle); + GEO_uv_parametrizer_delete(ms->handle); for (uint ob_index = 0; ob_index < ms->objects_len; ob_index++) { Object *obedit = ms->objects_edit[ob_index]; @@ -1014,9 +1016,9 @@ static void uvedit_pack_islands(const Scene *scene, Object *ob, BMesh *bm) ParamHandle *handle; handle = construct_param_handle(scene, ob, bm, &options, NULL); - param_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned); - param_flush(handle); - param_delete(handle); + GEO_uv_parametrizer_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned); + GEO_uv_parametrizer_flush(handle); + GEO_uv_parametrizer_delete(handle); } /** @@ -1034,9 +1036,9 @@ static void uvedit_pack_islands_multi(const Scene *scene, { ParamHandle *handle; handle = construct_param_handle_multi(scene, objects, objects_len, options, NULL); - param_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned); - param_flush(handle); - param_delete(handle); + GEO_uv_parametrizer_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned); + GEO_uv_parametrizer_flush(handle); + GEO_uv_parametrizer_delete(handle); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -1167,9 +1169,9 @@ static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op)) } ParamHandle *handle = construct_param_handle_multi(scene, objects, objects_len, &options, NULL); - param_average(handle, false); - param_flush(handle); - param_delete(handle); + GEO_uv_parametrizer_average(handle, false); + GEO_uv_parametrizer_flush(handle); + GEO_uv_parametrizer_delete(handle); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -1239,7 +1241,7 @@ void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit) handle = construct_param_handle(scene, obedit, em->bm, &options, NULL); } - param_lscm_begin(handle, PARAM_TRUE, abf); + GEO_uv_parametrizer_lscm_begin(handle, PARAM_TRUE, abf); /* Create or increase size of g_live_unwrap.handles array */ if (g_live_unwrap.handles == NULL) { @@ -1261,8 +1263,8 @@ void ED_uvedit_live_unwrap_re_solve(void) { if (g_live_unwrap.handles) { for (int i = 0; i < g_live_unwrap.len; i++) { - param_lscm_solve(g_live_unwrap.handles[i], NULL, NULL); - param_flush(g_live_unwrap.handles[i]); + GEO_uv_parametrizer_lscm_solve(g_live_unwrap.handles[i], NULL, NULL); + GEO_uv_parametrizer_flush(g_live_unwrap.handles[i]); } } } @@ -1271,11 +1273,11 @@ void ED_uvedit_live_unwrap_end(short cancel) { if (g_live_unwrap.handles) { for (int i = 0; i < g_live_unwrap.len; i++) { - param_lscm_end(g_live_unwrap.handles[i]); + GEO_uv_parametrizer_lscm_end(g_live_unwrap.handles[i]); if (cancel) { - param_flush_restore(g_live_unwrap.handles[i]); + GEO_uv_parametrizer_flush_restore(g_live_unwrap.handles[i]); } - param_delete(g_live_unwrap.handles[i]); + GEO_uv_parametrizer_delete(g_live_unwrap.handles[i]); } MEM_freeN(g_live_unwrap.handles); g_live_unwrap.handles = NULL; @@ -1731,17 +1733,17 @@ static void uvedit_unwrap(const Scene *scene, handle = construct_param_handle(scene, obedit, em->bm, options, result_info); } - param_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0); - param_lscm_solve(handle, - result_info ? &result_info->count_changed : NULL, - result_info ? &result_info->count_failed : NULL); - param_lscm_end(handle); + GEO_uv_parametrizer_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0); + GEO_uv_parametrizer_lscm_solve(handle, + result_info ? &result_info->count_changed : NULL, + result_info ? &result_info->count_failed : NULL); + GEO_uv_parametrizer_lscm_end(handle); - param_average(handle, true); + GEO_uv_parametrizer_average(handle, true); - param_flush(handle); + GEO_uv_parametrizer_flush(handle); - param_delete(handle); + GEO_uv_parametrizer_delete(handle); } static void uvedit_unwrap_multi(const Scene *scene, diff --git a/source/blender/freestyle/intern/python/BPy_Convert.cpp b/source/blender/freestyle/intern/python/BPy_Convert.cpp index 55a33720465..02ed3f463c7 100644 --- a/source/blender/freestyle/intern/python/BPy_Convert.cpp +++ b/source/blender/freestyle/intern/python/BPy_Convert.cpp @@ -569,7 +569,7 @@ bool Vec3r_ptr_from_PyObject(PyObject *obj, Vec3r &vec) bool Vec2f_ptr_from_Vector(PyObject *obj, Vec2f &vec) { - if (!VectorObject_Check(obj) || ((VectorObject *)obj)->size != 2) { + if (!VectorObject_Check(obj) || ((VectorObject *)obj)->vec_num != 2) { return false; } if (BaseMath_ReadCallback((BaseMathObject *)obj) == -1) { @@ -582,7 +582,7 @@ bool Vec2f_ptr_from_Vector(PyObject *obj, Vec2f &vec) bool Vec3f_ptr_from_Vector(PyObject *obj, Vec3f &vec) { - if (!VectorObject_Check(obj) || ((VectorObject *)obj)->size != 3) { + if (!VectorObject_Check(obj) || ((VectorObject *)obj)->vec_num != 3) { return false; } if (BaseMath_ReadCallback((BaseMathObject *)obj) == -1) { @@ -596,7 +596,7 @@ bool Vec3f_ptr_from_Vector(PyObject *obj, Vec3f &vec) bool Vec3r_ptr_from_Vector(PyObject *obj, Vec3r &vec) { - if (!VectorObject_Check(obj) || ((VectorObject *)obj)->size != 3) { + if (!VectorObject_Check(obj) || ((VectorObject *)obj)->vec_num != 3) { return false; } if (BaseMath_ReadCallback((BaseMathObject *)obj) == -1) { @@ -758,7 +758,7 @@ bool Vec3r_ptr_from_PyTuple(PyObject *obj, Vec3r &vec) bool float_array_from_PyObject(PyObject *obj, float *v, int n) { - if (VectorObject_Check(obj) && ((VectorObject *)obj)->size == n) { + if (VectorObject_Check(obj) && ((VectorObject *)obj)->vec_num == n) { if (BaseMath_ReadCallback((BaseMathObject *)obj) == -1) { return false; } diff --git a/source/blender/functions/FN_multi_function_builder.hh b/source/blender/functions/FN_multi_function_builder.hh index 7ba368d9a9d..2eaada5dea0 100644 --- a/source/blender/functions/FN_multi_function_builder.hh +++ b/source/blender/functions/FN_multi_function_builder.hh @@ -49,8 +49,11 @@ template<typename In1, typename Out1> class CustomMF_SI_SO : public MultiFunctio return [=](IndexMask mask, const VArray<In1> &in1, MutableSpan<Out1> out1) { /* Devirtualization results in a 2-3x speedup for some simple functions. */ devirtualize_varray(in1, [&](const auto &in1) { - mask.foreach_index( - [&](int i) { new (static_cast<void *>(&out1[i])) Out1(element_fn(in1[i])); }); + mask.to_best_mask_type([&](const auto &mask) { + for (const int64_t i : mask) { + new (static_cast<void *>(&out1[i])) Out1(element_fn(in1[i])); + } + }); }); }; } @@ -102,8 +105,11 @@ class CustomMF_SI_SI_SO : public MultiFunction { MutableSpan<Out1> out1) { /* Devirtualization results in a 2-3x speedup for some simple functions. */ devirtualize_varray2(in1, in2, [&](const auto &in1, const auto &in2) { - mask.foreach_index( - [&](int i) { new (static_cast<void *>(&out1[i])) Out1(element_fn(in1[i], in2[i])); }); + mask.to_best_mask_type([&](const auto &mask) { + for (const int64_t i : mask) { + new (static_cast<void *>(&out1[i])) Out1(element_fn(in1[i], in2[i])); + } + }); }); }; } @@ -160,9 +166,11 @@ class CustomMF_SI_SI_SI_SO : public MultiFunction { const VArray<In2> &in2, const VArray<In3> &in3, MutableSpan<Out1> out1) { - mask.foreach_index([&](int i) { + /* Virtual arrays are not devirtualized yet, to avoid generating lots of code without further + * consideration. */ + for (const int64_t i : mask) { new (static_cast<void *>(&out1[i])) Out1(element_fn(in1[i], in2[i], in3[i])); - }); + } }; } @@ -223,9 +231,11 @@ class CustomMF_SI_SI_SI_SI_SO : public MultiFunction { const VArray<In3> &in3, const VArray<In4> &in4, MutableSpan<Out1> out1) { - mask.foreach_index([&](int i) { + /* Virtual arrays are not devirtualized yet, to avoid generating lots of code without further + * consideration. */ + for (const int64_t i : mask) { new (static_cast<void *>(&out1[i])) Out1(element_fn(in1[i], in2[i], in3[i], in4[i])); - }); + } }; } @@ -268,7 +278,11 @@ template<typename Mut1> class CustomMF_SM : public MultiFunction { template<typename ElementFuncT> static FunctionT create_function(ElementFuncT element_fn) { return [=](IndexMask mask, MutableSpan<Mut1> mut1) { - mask.foreach_index([&](int i) { element_fn(mut1[i]); }); + mask.to_best_mask_type([&](const auto &mask) { + for (const int64_t i : mask) { + element_fn(mut1[i]); + } + }); }; } @@ -304,9 +318,11 @@ template<typename From, typename To> class CustomMF_Convert : public MultiFuncti const VArray<From> &inputs = params.readonly_single_input<From>(0); MutableSpan<To> outputs = params.uninitialized_single_output<To>(1); - for (int64_t i : mask) { - new (static_cast<void *>(&outputs[i])) To(inputs[i]); - } + mask.to_best_mask_type([&](const auto &mask) { + for (int64_t i : mask) { + new (static_cast<void *>(&outputs[i])) To(inputs[i]); + } + }); } }; @@ -366,7 +382,11 @@ template<typename T> class CustomMF_Constant : public MultiFunction { void call(IndexMask mask, MFParams params, MFContext UNUSED(context)) const override { MutableSpan<T> output = params.uninitialized_single_output<T>(0); - mask.foreach_index([&](int i) { new (&output[i]) T(value_); }); + mask.to_best_mask_type([&](const auto &mask) { + for (const int64_t i : mask) { + new (&output[i]) T(value_); + } + }); } uint64_t hash() const override diff --git a/source/blender/functions/intern/field.cc b/source/blender/functions/intern/field.cc index 9f742f11ce4..986d6ddc19e 100644 --- a/source/blender/functions/intern/field.cc +++ b/source/blender/functions/intern/field.cc @@ -489,7 +489,7 @@ void evaluate_constant_field(const GField &field, void *r_value) { if (field.node().depends_on_input()) { const CPPType &type = field.cpp_type(); - type.copy_construct(type.default_value(), r_value); + type.value_initialize(r_value); return; } diff --git a/source/blender/geometry/CMakeLists.txt b/source/blender/geometry/CMakeLists.txt index 0aae19d2eda..8716d6c8f67 100644 --- a/source/blender/geometry/CMakeLists.txt +++ b/source/blender/geometry/CMakeLists.txt @@ -9,6 +9,7 @@ set(INC ../functions ../makesdna ../makesrna + ../../../intern/eigen ../../../intern/guardedalloc ${CMAKE_BINARY_DIR}/source/blender/makesdna/intern ) @@ -18,11 +19,13 @@ set(SRC intern/mesh_to_curve_convert.cc intern/point_merge_by_distance.cc intern/realize_instances.cc + intern/uv_parametrizer.c GEO_mesh_merge_by_distance.hh GEO_mesh_to_curve.hh GEO_point_merge_by_distance.hh GEO_realize_instances.hh + GEO_uv_parametrizer.h ) set(LIB diff --git a/source/blender/geometry/GEO_uv_parametrizer.h b/source/blender/geometry/GEO_uv_parametrizer.h new file mode 100644 index 00000000000..e25889a0923 --- /dev/null +++ b/source/blender/geometry/GEO_uv_parametrizer.h @@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +#include "BLI_sys_types.h" /* for intptr_t support */ + +/** \file + * \ingroup geo + */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void ParamHandle; /* handle to a set of charts */ +typedef intptr_t ParamKey; /* (hash) key for identifying verts and faces */ +typedef enum ParamBool { + PARAM_TRUE = 1, + PARAM_FALSE = 0, +} ParamBool; + +/* -------------------------------------------------------------------- */ +/** \name Chart Construction: + * + * Faces and seams may only be added between #GEO_uv_parametrizer_construct_begin and + * #GEO_uv_parametrizer_construct_end. + * + * The pointers to `co` and `uv` are stored, rather than being copied. Vertices are implicitly + * created. + * + * In #GEO_uv_parametrizer_construct_end the mesh will be split up according to the seams. The + * resulting charts must be manifold, connected and open (at least one boundary loop). The output + * will be written to the `uv` pointers. + * + * \{ */ + +ParamHandle *GEO_uv_parametrizer_construct_begin(void); + +void GEO_uv_parametrizer_aspect_ratio(ParamHandle *handle, float aspx, float aspy); + +void GEO_uv_parametrizer_face_add(ParamHandle *handle, + ParamKey key, + int nverts, + ParamKey *vkeys, + float *co[4], + float *uv[4], + ParamBool *pin, + ParamBool *select); + +void GEO_uv_parametrizer_edge_set_seam(ParamHandle *handle, ParamKey *vkeys); + +void GEO_uv_parametrizer_construct_end(ParamHandle *handle, + ParamBool fill, + ParamBool topology_from_uvs, + int *count_fail); +void GEO_uv_parametrizer_delete(ParamHandle *handle); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Least Squares Conformal Maps: + * + * Charts with less than two pinned vertices are assigned two pins. LSCM is divided to three steps: + * + * 1. Begin: compute matrix and its factorization (expensive). + * 2. Solve using pinned coordinates (cheap). + * 3. End: clean up. + * + * UV coordinates are allowed to change within begin/end, for quick re-solving. + * + * \{ */ + +void GEO_uv_parametrizer_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf); +void GEO_uv_parametrizer_lscm_solve(ParamHandle *handle, int *count_changed, int *count_failed); +void GEO_uv_parametrizer_lscm_end(ParamHandle *handle); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stretch + * \{ */ + +void GEO_uv_parametrizer_stretch_begin(ParamHandle *handle); +void GEO_uv_parametrizer_stretch_blend(ParamHandle *handle, float blend); +void GEO_uv_parametrizer_stretch_iter(ParamHandle *handle); +void GEO_uv_parametrizer_stretch_end(ParamHandle *handle); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Area Smooth + * \{ */ + +void GEO_uv_parametrizer_smooth_area(ParamHandle *handle); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Packing + * \{ */ + +void GEO_uv_parametrizer_pack(ParamHandle *handle, + float margin, + bool do_rotate, + bool ignore_pinned); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Average area for all charts + * \{ */ + +void GEO_uv_parametrizer_average(ParamHandle *handle, bool ignore_pinned); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Simple x,y scale + * \{ */ + +void GEO_uv_parametrizer_scale(ParamHandle *handle, float x, float y); + +/* -------------------------------------------------------------------- */ +/** \name Flushing + * \{ */ + +void GEO_uv_parametrizer_flush(ParamHandle *handle); +void GEO_uv_parametrizer_flush_restore(ParamHandle *handle); + +/** \} */ + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/geometry/intern/uv_parametrizer.c index 5ad326c19e5..7b63dcb5ff0 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.c +++ b/source/blender/geometry/intern/uv_parametrizer.c @@ -16,7 +16,7 @@ #include "BLI_rand.h" #include "BLI_utildefines.h" -#include "uvedit_parametrizer.h" +#include "GEO_uv_parametrizer.h" #include <math.h> #include <stdio.h> @@ -622,14 +622,14 @@ static void p_chart_topological_sanity_check(PChart *chart) PEdge *e; for (v = chart->verts; v; v = v->nextlink) { - param_test_equals_ptr("v->edge->vert", v, v->edge->vert); + GEO_uv_parametrizer_test_equals_ptr("v->edge->vert", v, v->edge->vert); } for (e = chart->edges; e; e = e->nextlink) { if (e->pair) { - param_test_equals_ptr("e->pair->pair", e, e->pair->pair); - param_test_equals_ptr("pair->vert", e->vert, e->pair->next->vert); - param_test_equals_ptr("pair->next->vert", e->next->vert, e->pair->vert); + GEO_uv_parametrizer_test_equals_ptr("e->pair->pair", e, e->pair->pair); + GEO_uv_parametrizer_test_equals_ptr("pair->vert", e->vert, e->pair->next->vert); + GEO_uv_parametrizer_test_equals_ptr("pair->next->vert", e->next->vert, e->pair->vert); } } } @@ -2119,7 +2119,7 @@ static void p_collapse_cost_vertex(PVert *vert, float *r_mincost, PEdge **r_mine enext = p_wheel_edge_next(e); if (enext == NULL) { - /* the other boundary edge, where we only have the pair halfedge */ + /* The other boundary edge, where we only have the pair half-edge. */ pair = e->next->next; if (p_collapse_allowed(NULL, pair)) { @@ -4359,7 +4359,7 @@ static void p_smooth(PChart *chart) /* Exported */ -ParamHandle *param_construct_begin(void) +ParamHandle *GEO_uv_parametrizer_construct_begin(void) { PHandle *handle = MEM_callocN(sizeof(*handle), "PHandle"); handle->construction_chart = p_chart_new(handle); @@ -4378,7 +4378,7 @@ ParamHandle *param_construct_begin(void) return (ParamHandle *)handle; } -void param_aspect_ratio(ParamHandle *handle, float aspx, float aspy) +void GEO_uv_parametrizer_aspect_ratio(ParamHandle *handle, float aspx, float aspy) { PHandle *phandle = (PHandle *)handle; @@ -4387,7 +4387,7 @@ void param_aspect_ratio(ParamHandle *handle, float aspx, float aspy) phandle->do_aspect = true; } -void param_delete(ParamHandle *handle) +void GEO_uv_parametrizer_delete(ParamHandle *handle) { PHandle *phandle = (PHandle *)handle; int i; @@ -4472,20 +4472,20 @@ static void p_add_ngon(ParamHandle *handle, ParamBool tri_pin[3] = {pin[v0], pin[v1], pin[v2]}; ParamBool tri_select[3] = {select[v0], select[v1], select[v2]}; - param_face_add(handle, key, 3, tri_vkeys, tri_co, tri_uv, tri_pin, tri_select); + GEO_uv_parametrizer_face_add(handle, key, 3, tri_vkeys, tri_co, tri_uv, tri_pin, tri_select); } BLI_memarena_clear(arena); } -void param_face_add(ParamHandle *handle, - ParamKey key, - int nverts, - ParamKey *vkeys, - float *co[4], - float *uv[4], - ParamBool *pin, - ParamBool *select) +void GEO_uv_parametrizer_face_add(ParamHandle *handle, + ParamKey key, + int nverts, + ParamKey *vkeys, + float *co[4], + float *uv[4], + ParamBool *pin, + ParamBool *select) { PHandle *phandle = (PHandle *)handle; @@ -4514,7 +4514,7 @@ void param_face_add(ParamHandle *handle, } } -void param_edge_set_seam(ParamHandle *handle, ParamKey *vkeys) +void GEO_uv_parametrizer_edge_set_seam(ParamHandle *handle, ParamKey *vkeys) { PHandle *phandle = (PHandle *)handle; PEdge *e; @@ -4527,10 +4527,10 @@ void param_edge_set_seam(ParamHandle *handle, ParamKey *vkeys) } } -void param_construct_end(ParamHandle *handle, - ParamBool fill, - ParamBool topology_from_uvs, - int *count_fail) +void GEO_uv_parametrizer_construct_end(ParamHandle *handle, + ParamBool fill, + ParamBool topology_from_uvs, + int *count_fail) { PHandle *phandle = (PHandle *)handle; PChart *chart = phandle->construction_chart; @@ -4581,7 +4581,7 @@ void param_construct_end(ParamHandle *handle, phandle->state = PHANDLE_STATE_CONSTRUCTED; } -void param_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf) +void GEO_uv_parametrizer_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf) { PHandle *phandle = (PHandle *)handle; PFace *f; @@ -4598,7 +4598,7 @@ void param_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf) } } -void param_lscm_solve(ParamHandle *handle, int *count_changed, int *count_failed) +void GEO_uv_parametrizer_lscm_solve(ParamHandle *handle, int *count_changed, int *count_failed) { PHandle *phandle = (PHandle *)handle; PChart *chart; @@ -4638,7 +4638,7 @@ void param_lscm_solve(ParamHandle *handle, int *count_changed, int *count_failed } } -void param_lscm_end(ParamHandle *handle) +void GEO_uv_parametrizer_lscm_end(ParamHandle *handle) { PHandle *phandle = (PHandle *)handle; int i; @@ -4655,7 +4655,7 @@ void param_lscm_end(ParamHandle *handle) phandle->state = PHANDLE_STATE_CONSTRUCTED; } -void param_stretch_begin(ParamHandle *handle) +void GEO_uv_parametrizer_stretch_begin(ParamHandle *handle) { PHandle *phandle = (PHandle *)handle; PChart *chart; @@ -4685,7 +4685,7 @@ void param_stretch_begin(ParamHandle *handle) } } -void param_stretch_blend(ParamHandle *handle, float blend) +void GEO_uv_parametrizer_stretch_blend(ParamHandle *handle, float blend) { PHandle *phandle = (PHandle *)handle; @@ -4693,7 +4693,7 @@ void param_stretch_blend(ParamHandle *handle, float blend) phandle->blend = blend; } -void param_stretch_iter(ParamHandle *handle) +void GEO_uv_parametrizer_stretch_iter(ParamHandle *handle) { PHandle *phandle = (PHandle *)handle; PChart *chart; @@ -4707,7 +4707,7 @@ void param_stretch_iter(ParamHandle *handle) } } -void param_stretch_end(ParamHandle *handle) +void GEO_uv_parametrizer_stretch_end(ParamHandle *handle) { PHandle *phandle = (PHandle *)handle; @@ -4718,7 +4718,7 @@ void param_stretch_end(ParamHandle *handle) phandle->rng = NULL; } -void param_smooth_area(ParamHandle *handle) +void GEO_uv_parametrizer_smooth_area(ParamHandle *handle) { PHandle *phandle = (PHandle *)handle; int i; @@ -4738,7 +4738,7 @@ void param_smooth_area(ParamHandle *handle) } /* don't pack, just rotate (used for better packing) */ -static void param_pack_rotate(ParamHandle *handle, bool ignore_pinned) +static void GEO_uv_parametrizer_pack_rotate(ParamHandle *handle, bool ignore_pinned) { PChart *chart; int i; @@ -4756,7 +4756,10 @@ static void param_pack_rotate(ParamHandle *handle, bool ignore_pinned) } } -void param_pack(ParamHandle *handle, float margin, bool do_rotate, bool ignore_pinned) +void GEO_uv_parametrizer_pack(ParamHandle *handle, + float margin, + bool do_rotate, + bool ignore_pinned) { /* box packing variables */ BoxPack *boxarray, *box; @@ -4775,11 +4778,11 @@ void param_pack(ParamHandle *handle, float margin, bool do_rotate, bool ignore_p /* this could be its own function */ if (do_rotate) { - param_pack_rotate(handle, ignore_pinned); + GEO_uv_parametrizer_pack_rotate(handle, ignore_pinned); } if (phandle->aspx != phandle->aspy) { - param_scale(handle, 1.0f / phandle->aspx, 1.0f / phandle->aspy); + GEO_uv_parametrizer_scale(handle, 1.0f / phandle->aspx, 1.0f / phandle->aspy); } /* we may not use all these boxes */ @@ -4856,11 +4859,11 @@ void param_pack(ParamHandle *handle, float margin, bool do_rotate, bool ignore_p MEM_freeN(boxarray); if (phandle->aspx != phandle->aspy) { - param_scale(handle, phandle->aspx, phandle->aspy); + GEO_uv_parametrizer_scale(handle, phandle->aspx, phandle->aspy); } } -void param_average(ParamHandle *handle, bool ignore_pinned) +void GEO_uv_parametrizer_average(ParamHandle *handle, bool ignore_pinned) { PChart *chart; int i; @@ -4927,7 +4930,7 @@ void param_average(ParamHandle *handle, bool ignore_pinned) } } -void param_scale(ParamHandle *handle, float x, float y) +void GEO_uv_parametrizer_scale(ParamHandle *handle, float x, float y) { PHandle *phandle = (PHandle *)handle; PChart *chart; @@ -4939,7 +4942,7 @@ void param_scale(ParamHandle *handle, float x, float y) } } -void param_flush(ParamHandle *handle) +void GEO_uv_parametrizer_flush(ParamHandle *handle) { PHandle *phandle = (PHandle *)handle; PChart *chart; @@ -4961,7 +4964,7 @@ void param_flush(ParamHandle *handle) } } -void param_flush_restore(ParamHandle *handle) +void GEO_uv_parametrizer_flush_restore(ParamHandle *handle) { PHandle *phandle = (PHandle *)handle; PChart *chart; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c index fba83579ab1..f3669673094 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c @@ -132,10 +132,10 @@ static void generate_geometry(GpencilModifierData *md, /* Get bounbox for relative offset. */ float size[3] = {0.0f, 0.0f, 0.0f}; if (mmd->flag & GP_ARRAY_USE_RELATIVE) { - BoundBox *bb = BKE_object_boundbox_get(ob); + BoundBox bb; const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {1.0f, 1.0f, 1.0f}; - BKE_boundbox_init_from_minmax(bb, min, max); - BKE_boundbox_calc_size_aabb(bb, size); + BKE_boundbox_init_from_minmax(&bb, min, max); + BKE_boundbox_calc_size_aabb(&bb, size); mul_v3_fl(size, 2.0f); /* Need a minimum size (for flat drawings). */ CLAMP3_MIN(size, 0.01f); diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c index 1a69a6a8a38..930ebb78b46 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c @@ -6,6 +6,7 @@ */ #include <stdio.h> +#include <stdlib.h> #include "MEM_guardedalloc.h" @@ -13,6 +14,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_sort.h" #include "BLT_translation.h" @@ -25,9 +27,12 @@ #include "DNA_screen_types.h" #include "BKE_context.h" +#include "BKE_deform.h" #include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" #include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" +#include "BKE_modifier.h" #include "BKE_screen.h" #include "UI_interface.h" @@ -99,17 +104,22 @@ static void gpf_clear_all_strokes(bGPDframe *gpf) * NOTE: This won't be called if all points are present/removed */ static void reduce_stroke_points(bGPdata *gpd, + bGPDframe *gpf, bGPDstroke *gps, - const int num_points, + const int points_num, const eBuildGpencil_Transition transition) { - bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * num_points, __func__); + if (points_num == 0) { + clear_stroke(gpf, gps); + return; + } + bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * points_num, __func__); MDeformVert *new_dvert = NULL; - if ((gps->dvert != NULL) && (num_points > 0)) { - new_dvert = MEM_callocN(sizeof(MDeformVert) * num_points, __func__); + if ((gps->dvert != NULL) && (points_num > 0)) { + new_dvert = MEM_callocN(sizeof(MDeformVert) * points_num, __func__); } - /* Which end should points be removed from */ + /* Which end should points be removed from. */ switch (transition) { case GP_BUILD_TRANSITION_GROW: /* Show in forward order = * Remove ungrown-points from end of stroke. */ @@ -117,12 +127,12 @@ static void reduce_stroke_points(bGPdata *gpd, * Remove dead-points from end of stroke. */ { /* copy over point data */ - memcpy(new_points, gps->points, sizeof(bGPDspoint) * num_points); - if ((gps->dvert != NULL) && (num_points > 0)) { - memcpy(new_dvert, gps->dvert, sizeof(MDeformVert) * num_points); + memcpy(new_points, gps->points, sizeof(bGPDspoint) * points_num); + if ((gps->dvert != NULL) && (points_num > 0)) { + memcpy(new_dvert, gps->dvert, sizeof(MDeformVert) * points_num); /* free unused point weights */ - for (int i = num_points; i < gps->totpoints; i++) { + for (int i = points_num; i < gps->totpoints; i++) { MDeformVert *dvert = &gps->dvert[i]; BKE_gpencil_free_point_weights(dvert); } @@ -131,16 +141,16 @@ static void reduce_stroke_points(bGPdata *gpd, } /* Hide in forward order = Remove points from start of stroke */ - case GP_BUILD_TRANSITION_FADE: { - /* num_points is the number of points left after reducing. + case GP_BUILD_TRANSITION_VANISH: { + /* points_num is the number of points left after reducing. * We need to know how many to remove */ - const int offset = gps->totpoints - num_points; + const int offset = gps->totpoints - points_num; /* copy over point data */ - memcpy(new_points, gps->points + offset, sizeof(bGPDspoint) * num_points); - if ((gps->dvert != NULL) && (num_points > 0)) { - memcpy(new_dvert, gps->dvert + offset, sizeof(MDeformVert) * num_points); + memcpy(new_points, gps->points + offset, sizeof(bGPDspoint) * points_num); + if ((gps->dvert != NULL) && (points_num > 0)) { + memcpy(new_dvert, gps->dvert + offset, sizeof(MDeformVert) * points_num); /* free unused weights */ for (int i = 0; i < offset; i++) { @@ -161,12 +171,63 @@ static void reduce_stroke_points(bGPdata *gpd, MEM_SAFE_FREE(gps->dvert); gps->points = new_points; gps->dvert = new_dvert; - gps->totpoints = num_points; + gps->totpoints = points_num; /* Calc geometry data. */ BKE_gpencil_stroke_geometry_update(gpd, gps); } +static void fade_stroke_points(bGPDstroke *gps, + const int starting_index, + const int ending_index, + const float starting_weight, + const float ending_weight, + const int target_def_nr, + const eBuildGpencil_Transition transition, + const float thickness_strength, + const float opacity_strength) +{ + MDeformVert *dvert; + + int range = ending_index - starting_index; + if (!range) { + range = 1; + } + + /* Which end should points be removed from */ + switch (transition) { + /* Because starting_weight and ending_weight are set in correct order before calling this + * function, those three modes can use the same interpolation code. */ + case GP_BUILD_TRANSITION_GROW: + case GP_BUILD_TRANSITION_SHRINK: + case GP_BUILD_TRANSITION_VANISH: { + for (int i = starting_index; i <= ending_index; i++) { + float weight = interpf( + ending_weight, starting_weight, (float)(i - starting_index) / range); + if (target_def_nr >= 0) { + dvert = &gps->dvert[i]; + MDeformWeight *dw = BKE_defvert_ensure_index(dvert, target_def_nr); + if (dw) { + dw->weight = weight; + CLAMP(dw->weight, 0.0f, 1.0f); + } + } + if (thickness_strength > 1e-5) { + gps->points[i].pressure *= interpf(weight, 1.0f, thickness_strength); + } + if (opacity_strength > 1e-5) { + gps->points[i].strength *= interpf(weight, 1.0f, opacity_strength); + } + } + break; + } + + default: + printf("ERROR: Unknown transition %d in %s()\n", (int)transition, __func__); + break; + } +} + /* --------------------------------------------- */ /* Stroke Data Table Entry - This represents one stroke being generated */ @@ -178,11 +239,26 @@ typedef struct tStrokeBuildDetails { /* Number of points - Cache for more convenient access */ int totpoints; + + /* Distance to control object, used to sort the strokes if set. */ + float distance; } tStrokeBuildDetails; +static int cmp_stroke_build_details(const void *ps1, const void *ps2) +{ + tStrokeBuildDetails *p1 = (tStrokeBuildDetails *)ps1; + tStrokeBuildDetails *p2 = (tStrokeBuildDetails *)ps2; + return p1->distance > p2->distance ? 1 : (p1->distance == p2->distance ? 0 : -1); +} + /* Sequential and additive - Show strokes one after the other. */ -static void build_sequential( - BuildGpencilModifierData *mmd, bGPdata *gpd, bGPDframe *gpf, float fac, bool additive) +static void build_sequential(Object *ob, + BuildGpencilModifierData *mmd, + bGPdata *gpd, + bGPDframe *gpf, + const int target_def_nr, + float fac, + bool additive) { size_t tot_strokes = BLI_listbase_count(&gpf->strokes); size_t start_stroke; @@ -222,6 +298,26 @@ static void build_sequential( cell->totpoints = gps->totpoints; totpoints += cell->totpoints; + + /* Compute distance to control object if set, and build according to that order. */ + if (mmd->object) { + float sv1[3], sv2[3]; + mul_v3_m4v3(sv1, ob->obmat, &gps->points[0].x); + mul_v3_m4v3(sv2, ob->obmat, &gps->points[gps->totpoints - 1].x); + float dist_l = len_v3v3(sv1, mmd->object->loc); + float dist_r = len_v3v3(sv2, mmd->object->loc); + if (dist_r < dist_l) { + BKE_gpencil_stroke_flip(gps); + cell->distance = dist_r; + } + else { + cell->distance = dist_l; + } + } + } + + if (mmd->object) { + qsort(table, tot_strokes, sizeof(tStrokeBuildDetails), cmp_stroke_build_details); } /* 2.2) Second pass - Compute the overall indices for points */ @@ -240,6 +336,17 @@ static void build_sequential( /* 3) Determine the global indices for points that should be visible */ size_t first_visible = 0; size_t last_visible = 0; + /* Need signed numbers because the representation of fading offset would exceed the beginning and + * the end of offsets. */ + int fade_start = 0; + int fade_end = 0; + + bool fading_enabled = (mmd->flag & GP_BUILD_USE_FADING); + + float set_fade_fac = fading_enabled ? mmd->fade_fac : 0.0f; + float use_fac = interpf(1 + set_fade_fac, 0, fac); + float use_fade_fac = use_fac - set_fade_fac; + CLAMP(use_fade_fac, 0.0f, 1.0f); switch (mmd->transition) { /* Show in forward order @@ -247,7 +354,9 @@ static void build_sequential( */ case GP_BUILD_TRANSITION_GROW: first_visible = 0; /* always visible */ - last_visible = (size_t)roundf(totpoints * fac); + last_visible = (size_t)roundf(totpoints * use_fac); + fade_start = (int)roundf(totpoints * use_fade_fac); + fade_end = last_visible; break; /* Hide in reverse order @@ -255,15 +364,19 @@ static void build_sequential( */ case GP_BUILD_TRANSITION_SHRINK: first_visible = 0; /* always visible (until last point removed) */ - last_visible = (size_t)(totpoints * (1.0f - fac)); + last_visible = (size_t)(totpoints * (1.0f + set_fade_fac - use_fac)); + fade_start = (int)roundf(totpoints * (1.0f - use_fade_fac - set_fade_fac)); + fade_end = last_visible; break; /* Hide in forward order * - As fac increases, the early points start getting hidden */ - case GP_BUILD_TRANSITION_FADE: - first_visible = (size_t)(totpoints * fac); + case GP_BUILD_TRANSITION_VANISH: + first_visible = (size_t)(totpoints * use_fade_fac); last_visible = totpoints; /* i.e. visible until the end, unless first overlaps this */ + fade_start = first_visible; + fade_end = (int)roundf(totpoints * use_fac); break; } @@ -277,19 +390,43 @@ static void build_sequential( clear_stroke(gpf, cell->gps); } else { + if (fade_start != fade_end && (int)cell->start_idx < fade_end && + (int)cell->end_idx > fade_start) { + int start_index = fade_start - cell->start_idx; + int end_index = cell->totpoints + fade_end - cell->end_idx - 1; + CLAMP(start_index, 0, cell->totpoints - 1); + CLAMP(end_index, 0, cell->totpoints - 1); + float start_weight = ratiof(fade_start, fade_end, cell->start_idx + start_index); + float end_weight = ratiof(fade_start, fade_end, cell->start_idx + end_index); + if (mmd->transition != GP_BUILD_TRANSITION_VANISH) { + start_weight = 1.0f - start_weight; + end_weight = 1.0f - end_weight; + } + fade_stroke_points(cell->gps, + start_index, + end_index, + start_weight, + end_weight, + target_def_nr, + mmd->transition, + mmd->fade_thickness_strength, + mmd->fade_opacity_strength); + /* Calc geometry data. */ + BKE_gpencil_stroke_geometry_update(gpd, cell->gps); + } /* Some proportion of stroke is visible */ if ((first_visible <= cell->start_idx) && (last_visible >= cell->end_idx)) { /* Do nothing - whole stroke is visible */ } else if (first_visible > cell->start_idx) { /* Starts partway through this stroke */ - int num_points = cell->end_idx - first_visible; - reduce_stroke_points(gpd, cell->gps, num_points, mmd->transition); + int points_num = cell->end_idx - first_visible; + reduce_stroke_points(gpd, gpf, cell->gps, points_num, mmd->transition); } else { /* Ends partway through this stroke */ - int num_points = last_visible - cell->start_idx; - reduce_stroke_points(gpd, cell->gps, num_points, mmd->transition); + int points_num = last_visible - cell->start_idx; + reduce_stroke_points(gpd, gpf, cell->gps, points_num, mmd->transition); } } } @@ -304,6 +441,7 @@ static void build_sequential( static void build_concurrent(BuildGpencilModifierData *mmd, bGPdata *gpd, bGPDframe *gpf, + const int target_def_nr, float fac) { bGPDstroke *gps, *gps_next; @@ -323,6 +461,12 @@ static void build_concurrent(BuildGpencilModifierData *mmd, return; } + bool fading_enabled = (mmd->flag & GP_BUILD_USE_FADING); + float set_fade_fac = fading_enabled ? mmd->fade_fac : 0.0f; + float use_fac = interpf(1 + set_fade_fac, 0, fac); + use_fac = reverse ? use_fac - set_fade_fac : use_fac; + int fade_points = set_fade_fac * max_points; + /* 2) For each stroke, determine how it should be handled */ for (gps = gpf->strokes.first; gps; gps = gps_next) { gps_next = gps->next; @@ -333,31 +477,19 @@ static void build_concurrent(BuildGpencilModifierData *mmd, const float relative_len = (float)gps->totpoints / (float)max_points; /* Determine how many points should be left in the stroke */ - int num_points = 0; + int points_num = 0; switch (mmd->time_alignment) { case GP_BUILD_TIMEALIGN_START: /* all start on frame 1 */ { - /* Build effect occurs over when fac = 0, to fac = relative_len */ - if (fac <= relative_len) { - /* Scale fac to fit relative_len */ - const float scaled_fac = fac / MAX2(relative_len, PSEUDOINVERSE_EPSILON); + /* Scale fac to fit relative_len */ + const float scaled_fac = use_fac / MAX2(relative_len, PSEUDOINVERSE_EPSILON); - if (reverse) { - num_points = (int)roundf((1.0f - scaled_fac) * gps->totpoints); - } - else { - num_points = (int)roundf(scaled_fac * gps->totpoints); - } + if (reverse) { + points_num = (int)roundf((1.0f - scaled_fac) * gps->totpoints); } else { - /* Build effect has ended */ - if (reverse) { - num_points = 0; - } - else { - num_points = gps->totpoints; - } + points_num = (int)roundf(scaled_fac * gps->totpoints); } break; @@ -368,24 +500,13 @@ static void build_concurrent(BuildGpencilModifierData *mmd, */ const float start_fac = 1.0f - relative_len; - if (fac >= start_fac) { - const float scaled_fac = (fac - start_fac) / MAX2(relative_len, PSEUDOINVERSE_EPSILON); + const float scaled_fac = (use_fac - start_fac) / MAX2(relative_len, PSEUDOINVERSE_EPSILON); - if (reverse) { - num_points = (int)roundf((1.0f - scaled_fac) * gps->totpoints); - } - else { - num_points = (int)roundf(scaled_fac * gps->totpoints); - } + if (reverse) { + points_num = (int)roundf((1.0f - scaled_fac) * gps->totpoints); } else { - /* Build effect hasn't started */ - if (reverse) { - num_points = gps->totpoints; - } - else { - num_points = 0; - } + points_num = (int)roundf(scaled_fac * gps->totpoints); } break; @@ -393,21 +514,54 @@ static void build_concurrent(BuildGpencilModifierData *mmd, } /* Modify the stroke geometry */ - if (num_points <= 0) { + if (points_num <= 0) { /* Nothing Left - Delete the stroke */ clear_stroke(gpf, gps); } - else if (num_points < gps->totpoints) { - /* Remove some points */ - reduce_stroke_points(gpd, gps, num_points, mmd->transition); + else { + int more_points = points_num - gps->totpoints; + CLAMP(more_points, 0, fade_points + 1); + float max_weight = (float)(points_num + more_points) / fade_points; + CLAMP(max_weight, 0.0f, 1.0f); + int starting_index = mmd->transition == GP_BUILD_TRANSITION_VANISH ? + gps->totpoints - points_num - more_points : + points_num - 1 - fade_points + more_points; + int ending_index = mmd->transition == GP_BUILD_TRANSITION_VANISH ? + gps->totpoints - points_num + fade_points - more_points : + points_num - 1 + more_points; + float starting_weight = mmd->transition == GP_BUILD_TRANSITION_VANISH ? + ((float)more_points / fade_points) : + max_weight; + float ending_weight = mmd->transition == GP_BUILD_TRANSITION_VANISH ? + max_weight : + ((float)more_points / fade_points); + CLAMP(starting_index, 0, gps->totpoints - 1); + CLAMP(ending_index, 0, gps->totpoints - 1); + fade_stroke_points(gps, + starting_index, + ending_index, + starting_weight, + ending_weight, + target_def_nr, + mmd->transition, + mmd->fade_thickness_strength, + mmd->fade_opacity_strength); + if (points_num < gps->totpoints) { + /* Remove some points */ + reduce_stroke_points(gpd, gpf, gps, points_num, mmd->transition); + } } } } /* --------------------------------------------- */ -static void generate_geometry( - GpencilModifierData *md, Depsgraph *depsgraph, bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf) +static void generate_geometry(GpencilModifierData *md, + Depsgraph *depsgraph, + Object *ob, + bGPdata *gpd, + bGPDlayer *gpl, + bGPDframe *gpf) { BuildGpencilModifierData *mmd = (BuildGpencilModifierData *)md; if (mmd->mode == GP_BUILD_MODE_ADDITIVE) { @@ -450,6 +604,25 @@ static void generate_geometry( } } + int target_def_nr = -1; + if (mmd->flag & GP_BUILD_USE_FADING) { + /* If there are weight output, initialize it with a default weight of 1. */ + target_def_nr = BKE_object_defgroup_name_index(ob, mmd->target_vgname); + if (target_def_nr >= 0) { + LISTBASE_FOREACH (bGPDstroke *, fgps, &gpf->strokes) { + BKE_gpencil_dvert_ensure(fgps); + /* Assign a initial weight of 1, and only process those who needs additional fading. */ + for (int j = 0; j < fgps->totpoints; j++) { + MDeformVert *dvert = &fgps->dvert[j]; + MDeformWeight *dw = BKE_defvert_ensure_index(dvert, target_def_nr); + if (dw) { + dw->weight = 1.0f; + } + } + } + } + } + /* Early exit if outside of the frame range for this modifier * (e.g. to have one forward, and one backwards modifier) */ @@ -517,15 +690,15 @@ static void generate_geometry( /* Time management mode */ switch (mmd->mode) { case GP_BUILD_MODE_SEQUENTIAL: - build_sequential(mmd, gpd, gpf, fac, false); + build_sequential(ob, mmd, gpd, gpf, target_def_nr, fac, false); break; case GP_BUILD_MODE_CONCURRENT: - build_concurrent(mmd, gpd, gpf, fac); + build_concurrent(mmd, gpd, gpf, target_def_nr, fac); break; case GP_BUILD_MODE_ADDITIVE: - build_sequential(mmd, gpd, gpf, fac, true); + build_sequential(ob, mmd, gpd, gpf, target_def_nr, fac, true); break; default: @@ -547,7 +720,7 @@ static void generateStrokes(GpencilModifierData *md, Depsgraph *depsgraph, Objec if (gpf == NULL) { continue; } - generate_geometry(md, depsgraph, gpd, gpl, gpf); + generate_geometry(md, depsgraph, ob, gpd, gpl, gpf); } } @@ -583,7 +756,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiItemS(layout); - row = uiLayoutRowWithHeading(layout, true, IFACE_("Use Factor")); + row = uiLayoutRowWithHeading(layout, true, IFACE_("Factor")); uiLayoutSetPropDecorate(row, false); uiItemR(row, ptr, "use_percentage", 0, "", ICON_NONE); sub = uiLayoutRow(row, true); @@ -591,6 +764,12 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiItemR(sub, ptr, "percentage_factor", 0, "", ICON_NONE); uiItemDecoratorR(row, ptr, "percentage_factor", 0); + uiItemS(layout); + + if (ELEM(mode, GP_BUILD_MODE_SEQUENTIAL, GP_BUILD_MODE_ADDITIVE)) { + uiItemR(layout, ptr, "object", 0, NULL, ICON_NONE); + } + /* Check for incompatible time modifier. */ Object *ob = ob_ptr.data; GpencilModifierData *md = ptr->data; @@ -624,6 +803,40 @@ static void frame_range_panel_draw(const bContext *UNUSED(C), Panel *panel) uiItemR(col, ptr, "frame_end", 0, IFACE_("End"), ICON_NONE); } +static void fading_header_draw(const bContext *UNUSED(C), Panel *panel) +{ + uiLayout *layout = panel->layout; + + PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL); + + uiItemR(layout, ptr, "use_fading", 0, IFACE_("Fade"), ICON_NONE); +} + +static void fading_panel_draw(const bContext *UNUSED(C), Panel *panel) +{ + uiLayout *col; + uiLayout *layout = panel->layout; + + PointerRNA ob_ptr; + PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, &ob_ptr); + + uiLayoutSetPropSep(layout, true); + + uiItemR(layout, ptr, "fade_factor", 0, IFACE_("Factor"), ICON_NONE); + + col = uiLayoutColumn(layout, true); + uiItemR(col, ptr, "fade_thickness_strength", 0, IFACE_("Thickness"), ICON_NONE); + uiItemR(col, ptr, "fade_opacity_strength", 0, IFACE_("Opacity"), ICON_NONE); + + uiItemPointerR(layout, + ptr, + "target_vertex_group", + &ob_ptr, + "vertex_groups", + IFACE_("Weight Output"), + ICON_NONE); +} + static void mask_panel_draw(const bContext *UNUSED(C), Panel *panel) { gpencil_modifier_masking_panel_draw(panel, false, false); @@ -636,9 +849,30 @@ static void panelRegister(ARegionType *region_type) gpencil_modifier_subpanel_register( region_type, "frame_range", "", frame_range_header_draw, frame_range_panel_draw, panel_type); gpencil_modifier_subpanel_register( + region_type, "fading", "", fading_header_draw, fading_panel_draw, panel_type); + gpencil_modifier_subpanel_register( region_type, "_mask", "Influence", NULL, mask_panel_draw, panel_type); } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + BuildGpencilModifierData *mmd = (BuildGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->object, IDWALK_CB_NOP); +} + +static void updateDepsgraph(GpencilModifierData *md, + const ModifierUpdateDepsgraphContext *ctx, + const int UNUSED(mode)) +{ + BuildGpencilModifierData *lmd = (BuildGpencilModifierData *)md; + if (lmd->object != NULL) { + DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_GEOMETRY, "Build Modifier"); + DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_TRANSFORM, "Build Modifier"); + } + DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Build Modifier"); +} + /* ******************************************** */ GpencilModifierTypeInfo modifierType_Gpencil_Build = { @@ -658,9 +892,9 @@ GpencilModifierTypeInfo modifierType_Gpencil_Build = { /* initData */ initData, /* freeData */ NULL, /* isDisabled */ NULL, - /* updateDepsgraph */ NULL, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* panelRegister */ panelRegister, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c index eb51a247d87..1992ebd1508 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c @@ -178,7 +178,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) col = uiLayoutColumn(layout, false); uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_edit_position")); - uiItemR(col, ptr, "keep_shape", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_keep_shape", 0, NULL, ICON_NONE); gpencil_modifier_panel_end(layout, ptr); } diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c index c96321b67aa..08737c19eef 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c @@ -1783,7 +1783,7 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu BM_mesh_elem_hflag_disable_all(bm, BM_FACE | BM_EDGE, BM_ELEM_TAG, false); BM_mesh_triangulate( - bm, MOD_TRIANGULATE_QUAD_FIXED, MOD_TRIANGULATE_NGON_BEAUTY, 4, false, NULL, NULL, NULL); + bm, MOD_TRIANGULATE_QUAD_BEAUTY, MOD_TRIANGULATE_NGON_BEAUTY, 4, false, NULL, NULL, NULL); BM_mesh_normals_update(bm); BM_mesh_elem_table_ensure(bm, BM_VERT | BM_EDGE | BM_FACE); BM_mesh_elem_index_ensure(bm, BM_VERT | BM_EDGE | BM_FACE); @@ -2095,7 +2095,7 @@ static bool lineart_geometry_check_visible(double (*model_view_proj)[4], double shift_y, Object *use_ob) { - BoundBox *bb = BKE_object_boundbox_get(use_ob); + const BoundBox *bb = BKE_object_boundbox_get(use_ob); if (!bb) { /* For lights and empty stuff there will be no bbox. */ return false; diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 1840b5447e3..3e12426acdc 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -414,6 +414,8 @@ list(APPEND INC ${CMAKE_CURRENT_BINARY_DIR}) set(SRC_SHADER_CREATE_INFOS ../draw/engines/gpencil/shaders/infos/gpencil_info.hh ../draw/engines/gpencil/shaders/infos/gpencil_vfx_info.hh + ../draw/engines/overlay/shaders/infos/armature_info.hh + ../draw/engines/overlay/shaders/infos/edit_mode_info.hh ../draw/engines/workbench/shaders/infos/workbench_composite_info.hh ../draw/engines/workbench/shaders/infos/workbench_effect_antialiasing_info.hh ../draw/engines/workbench/shaders/infos/workbench_effect_cavity_info.hh @@ -503,16 +505,32 @@ endif() if(WITH_GPU_SHADER_BUILDER) - add_executable(shader_builder - intern/gpu_shader_builder.cc - intern/gpu_shader_builder_stubs.cc - ${shader_create_info_list_file} - ) + # TODO(@fclem) Fix this mess. + if(APPLE) + add_executable(shader_builder + intern/gpu_shader_builder.cc + ${shader_create_info_list_file} + ) + + setup_platform_linker_flags(shader_builder) + + target_link_libraries(shader_builder PUBLIC + bf_blenkernel + buildinfoobj + ) + else() + add_executable(shader_builder + intern/gpu_shader_builder.cc + intern/gpu_shader_builder_stubs.cc + ${shader_create_info_list_file} + ) + + target_link_libraries(shader_builder PUBLIC + bf_blenkernel + ${PLATFORM_LINKLIBS} + ) + endif() - target_link_libraries(shader_builder PUBLIC - bf_blenkernel - ${PLATFORM_LINKLIBS} - ) target_include_directories(shader_builder PRIVATE ${INC} ${CMAKE_CURRENT_BINARY_DIR}) set(SRC_BAKED_CREATE_INFOS_FILE ${CMAKE_CURRENT_BINARY_DIR}/shader_baked.hh) diff --git a/source/blender/gpu/GPU_primitive.h b/source/blender/gpu/GPU_primitive.h index 66759cf22d7..4860b037bfb 100644 --- a/source/blender/gpu/GPU_primitive.h +++ b/source/blender/gpu/GPU_primitive.h @@ -20,10 +20,12 @@ typedef enum { GPU_PRIM_LINES, GPU_PRIM_TRIS, GPU_PRIM_LINE_STRIP, - GPU_PRIM_LINE_LOOP, /* GL has this, Vulkan does not */ + GPU_PRIM_LINE_LOOP, /* GL has this, Vulkan and Metal do not */ GPU_PRIM_TRI_STRIP, - GPU_PRIM_TRI_FAN, + GPU_PRIM_TRI_FAN, /* Metal API does not support this. */ + /* Metal API does not support ADJ primitive types but + * handled via the geometry-shader-alternative path. */ GPU_PRIM_LINES_ADJ, GPU_PRIM_TRIS_ADJ, GPU_PRIM_LINE_STRIP_ADJ, diff --git a/source/blender/gpu/intern/gpu_batch_presets.c b/source/blender/gpu/intern/gpu_batch_presets.c index c1c884ed028..ab5e23a846c 100644 --- a/source/blender/gpu/intern/gpu_batch_presets.c +++ b/source/blender/gpu/intern/gpu_batch_presets.c @@ -19,6 +19,7 @@ #include "GPU_batch.h" #include "GPU_batch_presets.h" /* own include */ #include "GPU_batch_utils.h" +#include "GPU_context.h" /* -------------------------------------------------------------------- */ /** \name Local Structures @@ -320,11 +321,12 @@ GPUBatch *GPU_batch_preset_quad(void) GPUVertBuf *vbo = GPU_vertbuf_create_with_format(preset_2d_format()); GPU_vertbuf_data_alloc(vbo, 4); - float pos_data[4][2] = {{0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}}; + float pos_data[4][2] = {{0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}}; GPU_vertbuf_attr_fill(vbo, g_presets_2d.attr_id.pos, pos_data); /* Don't fill the color. */ - g_presets_2d.batch.quad = GPU_batch_create_ex(GPU_PRIM_TRI_FAN, vbo, NULL, GPU_BATCH_OWNS_VBO); + g_presets_2d.batch.quad = GPU_batch_create_ex( + GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO); gpu_batch_presets_register(g_presets_2d.batch.quad); } diff --git a/source/blender/gpu/intern/gpu_shader_create_info.cc b/source/blender/gpu/intern/gpu_shader_create_info.cc index aef1984687d..0dd82d4ea44 100644 --- a/source/blender/gpu/intern/gpu_shader_create_info.cc +++ b/source/blender/gpu/intern/gpu_shader_create_info.cc @@ -65,6 +65,9 @@ void ShaderCreateInfo::finalize() if (info.early_fragment_test_) { early_fragment_test_ = true; } + if (info.depth_write_ != DepthWrite::ANY) { + depth_write_ = info.depth_write_; + } validate(info); @@ -102,8 +105,6 @@ void ShaderCreateInfo::finalize() assert_no_overlap(compute_source_.is_empty(), "Compute source already existing"); compute_source_ = info.compute_source_; } - - do_static_compilation_ = do_static_compilation_ || info.do_static_compilation_; } if (auto_resource_location_) { @@ -264,9 +265,14 @@ bool gpu_shader_create_info_compile_all() { using namespace blender::gpu; int success = 0; + int skipped = 0; int total = 0; for (ShaderCreateInfo *info : g_create_infos->values()) { if (info->do_static_compilation_) { + if (GPU_compute_shader_support() == false && info->compute_source_ != nullptr) { + skipped++; + continue; + } total++; GPUShader *shader = GPU_shader_create_from_info( reinterpret_cast<const GPUShaderCreateInfo *>(info)); @@ -322,12 +328,11 @@ bool gpu_shader_create_info_compile_all() GPU_shader_free(shader); } } - printf("===============================\n"); - printf("Shader Test compilation result: \n"); - printf("%d Total\n", total); - printf("%d Passed\n", success); - printf("%d Failed\n", total - success); - printf("===============================\n"); + printf("Shader Test compilation result: %d / %d passed", success, total); + if (skipped > 0) { + printf(" (skipped %d for compatibility reasons)", skipped); + } + printf("\n"); return success == total; } diff --git a/source/blender/gpu/intern/gpu_shader_create_info.hh b/source/blender/gpu/intern/gpu_shader_create_info.hh index 9984295457c..51008993353 100644 --- a/source/blender/gpu/intern/gpu_shader_create_info.hh +++ b/source/blender/gpu/intern/gpu_shader_create_info.hh @@ -130,6 +130,17 @@ enum class BuiltinBits { }; ENUM_OPERATORS(BuiltinBits, BuiltinBits::WORK_GROUP_SIZE); +/** + * Follow convention described in: + * https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_conservative_depth.txt + */ +enum class DepthWrite { + ANY = 0, + GREATER, + LESS, + UNCHANGED, +}; + /* Samplers & images. */ enum class ImageType { /** Color samplers/image. */ @@ -273,6 +284,8 @@ struct ShaderCreateInfo { bool auto_resource_location_ = false; /** If true, force depth and stencil tests to always happen before fragment shader invocation. */ bool early_fragment_test_ = false; + /** Allow optimization when fragment shader writes to `gl_FragDepth`. */ + DepthWrite depth_write_ = DepthWrite::ANY; /** * Maximum length of all the resource names including each null terminator. * Only for names used by gpu::ShaderInterface. @@ -695,6 +708,13 @@ struct ShaderCreateInfo { return *(Self *)this; } + /* Defines how the fragment shader will write to gl_FragDepth. */ + Self &depth_write(DepthWrite value) + { + depth_write_ = value; + return *(Self *)this; + } + Self &auto_resource_location(bool value) { auto_resource_location_ = value; diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 7bffafd7f9d..a0efe12f523 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -197,7 +197,7 @@ void GPU_viewport_bind_from_offscreen(GPUViewport *viewport, /* XR surfaces will already check for texture size changes and free if necessary (see * #wm_xr_session_surface_offscreen_ensure()), so don't free here as it has a significant * performance impact (leads to texture re-creation in #gpu_viewport_textures_create() every VR - * drawing iteration).*/ + * drawing iteration). */ if (!is_xr_surface) { gpu_viewport_textures_free(viewport); } diff --git a/source/blender/gpu/metal/mtl_backend.mm b/source/blender/gpu/metal/mtl_backend.mm index e1da371bd0b..00d73ba5d71 100644 --- a/source/blender/gpu/metal/mtl_backend.mm +++ b/source/blender/gpu/metal/mtl_backend.mm @@ -363,7 +363,7 @@ void MTLBackend::capabilities_init(MTLContext *ctx) MTLBackend::capabilities.supports_family_mac2); GCaps.compute_shader_support = false; /* TODO(Metal): Add compute support. */ GCaps.shader_storage_buffer_objects_support = - false; /* TODO(Metal): implement Storage Buffer support.*/ + false; /* TODO(Metal): implement Storage Buffer support. */ /* Maximum buffer bindings: 31. Consider required slot for uniforms/UBOs/Vertex attributes. * Can use argument buffers if a higher limit is required. */ diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index 2c9cbdb99d8..610fd5d980f 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -479,7 +479,14 @@ void GLBackend::capabilities_init() glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &GCaps.max_batch_indices); glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &GCaps.max_batch_vertices); glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &GCaps.max_vertex_attribs); - glGetIntegerv(GL_MAX_VARYING_FLOATS, &GCaps.max_varying_floats); + if (GPU_type_matches(GPU_DEVICE_APPLE, GPU_OS_MAC, GPU_DRIVER_OFFICIAL)) { + /* Due to a bug, querying GL_MAX_VARYING_FLOATS is emitting GL_INVALID_ENUM. + * Force use minimum required value. */ + GCaps.max_varying_floats = 32; + } + else { + glGetIntegerv(GL_MAX_VARYING_FLOATS, &GCaps.max_varying_floats); + } glGetIntegerv(GL_NUM_EXTENSIONS, &GCaps.extensions_len); GCaps.extension_get = gl_extension_get; @@ -502,9 +509,11 @@ void GLBackend::capabilities_init() glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &GLContext::max_texture_3d_size); glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GLContext::max_cubemap_size); glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &GLContext::max_ubo_binds); - glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &GLContext::max_ssbo_binds); glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GLContext::max_ubo_size); - glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &GLContext::max_ssbo_size); + if (GCaps.shader_storage_buffer_objects_support) { + glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &GLContext::max_ssbo_binds); + glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &GLContext::max_ssbo_size); + } GLContext::base_instance_support = GLEW_ARB_base_instance; GLContext::clear_texture_support = GLEW_ARB_clear_texture; GLContext::copy_image_support = GLEW_ARB_copy_image; diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc index 5a55a2e8020..5938444ce49 100644 --- a/source/blender/gpu/opengl/gl_shader.cc +++ b/source/blender/gpu/opengl/gl_shader.cc @@ -217,6 +217,20 @@ static const char *to_string(const PrimitiveOut &layout) } } +static const char *to_string(const DepthWrite &value) +{ + switch (value) { + case DepthWrite::ANY: + return "depth_any"; + case DepthWrite::GREATER: + return "depth_greater"; + case DepthWrite::LESS: + return "depth_less"; + default: + return "depth_unchanged"; + } +} + static void print_image_type(std::ostream &os, const ImageType &type, const ShaderCreateInfo::Resource::BindType bind_type) @@ -585,6 +599,9 @@ std::string GLShader::fragment_interface_declare(const ShaderCreateInfo &info) c if (info.early_fragment_test_) { ss << "layout(early_fragment_tests) in;\n"; } + if (GLEW_VERSION_4_2 || GLEW_ARB_conservative_depth) { + ss << "layout(" << to_string(info.depth_write_) << ") out float gl_FragDepth;\n"; + } ss << "\n/* Outputs. */\n"; for (const ShaderCreateInfo::FragOut &output : info.fragment_outputs_) { ss << "layout(location = " << output.index; @@ -868,7 +885,7 @@ GLuint GLShader::create_shader_stage(GLenum gl_stage, MutableSpan<const char *> { GLuint shader = glCreateShader(gl_stage); if (shader == 0) { - fprintf(stderr, "GLShader: Error: Could not create shader object."); + fprintf(stderr, "GLShader: Error: Could not create shader object.\n"); return 0; } diff --git a/source/blender/gpu/opengl/gl_shader_log.cc b/source/blender/gpu/opengl/gl_shader_log.cc index 1d922916e4c..64567174d17 100644 --- a/source/blender/gpu/opengl/gl_shader_log.cc +++ b/source/blender/gpu/opengl/gl_shader_log.cc @@ -39,7 +39,8 @@ char *GLLogParser::parse_line(char *log_line, GPULogItem &log_item) if ((log_item.cursor.row != -1) && (log_item.cursor.column != -1)) { if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_OFFICIAL) || - GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_MAC, GPU_DRIVER_OFFICIAL)) { + GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_MAC, GPU_DRIVER_OFFICIAL) || + GPU_type_matches(GPU_DEVICE_APPLE, GPU_OS_MAC, GPU_DRIVER_OFFICIAL)) { /* 0:line */ log_item.cursor.row = log_item.cursor.column; log_item.cursor.column = -1; diff --git a/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl index 903c602c5d6..11bb311740c 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl @@ -16,14 +16,6 @@ void main() vec2 uv; vec2 co; -#ifdef GPU_METAL -/* Metal API does not support Triangle fan primitive topology. - * When this shader is called using Triangle-Strip, vertex ID's - * are in a different order. */ -# define GPU_PRIM_TRI_STRIP -#endif - -#ifdef GPU_PRIM_TRI_STRIP if (gl_VertexID == 0) { co = rect_geom.xw; uv = rect_icon.xw; @@ -40,24 +32,6 @@ void main() co = rect_geom.zy; uv = rect_icon.zy; } -#else - if (gl_VertexID == 0) { - co = rect_geom.xy; - uv = rect_icon.xy; - } - else if (gl_VertexID == 1) { - co = rect_geom.xw; - uv = rect_icon.xw; - } - else if (gl_VertexID == 2) { - co = rect_geom.zw; - uv = rect_icon.zw; - } - else { - co = rect_geom.zy; - uv = rect_icon.zy; - } -#endif gl_Position = ModelViewProjectionMatrix * vec4(co, 0.0f, 1.0f); texCoord_interp = uv; diff --git a/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl b/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl index cdc716db7a4..3edf0e31799 100644 --- a/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl +++ b/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl @@ -7,13 +7,13 @@ uniform vec4 WorldClipPlanes[6]; # define _world_clip_planes_calc_clip_distance(wpos, _clipplanes) \ { \ - vec4 pos = vec4(wpos, 1.0); \ - gl_ClipDistance[0] = dot(_clipplanes[0], pos); \ - gl_ClipDistance[1] = dot(_clipplanes[1], pos); \ - gl_ClipDistance[2] = dot(_clipplanes[2], pos); \ - gl_ClipDistance[3] = dot(_clipplanes[3], pos); \ - gl_ClipDistance[4] = dot(_clipplanes[4], pos); \ - gl_ClipDistance[5] = dot(_clipplanes[5], pos); \ + vec4 _pos = vec4(wpos, 1.0); \ + gl_ClipDistance[0] = dot(_clipplanes[0], _pos); \ + gl_ClipDistance[1] = dot(_clipplanes[1], _pos); \ + gl_ClipDistance[2] = dot(_clipplanes[2], _pos); \ + gl_ClipDistance[3] = dot(_clipplanes[3], _pos); \ + gl_ClipDistance[4] = dot(_clipplanes[4], _pos); \ + gl_ClipDistance[5] = dot(_clipplanes[5], _pos); \ } /* When all shaders are builtin shaders are migrated this could be applied directly. */ diff --git a/source/blender/gpu/shaders/gpu_shader_colorspace_lib.glsl b/source/blender/gpu/shaders/gpu_shader_colorspace_lib.glsl index 7d69cba5017..abd4592dc9d 100644 --- a/source/blender/gpu/shaders/gpu_shader_colorspace_lib.glsl +++ b/source/blender/gpu/shaders/gpu_shader_colorspace_lib.glsl @@ -6,13 +6,13 @@ uniform bool srgbTarget = false; #endif -vec4 blender_srgb_to_framebuffer_space(vec4 col) +vec4 blender_srgb_to_framebuffer_space(vec4 in_color) { if (srgbTarget) { - vec3 c = max(col.rgb, vec3(0.0)); + vec3 c = max(in_color.rgb, vec3(0.0)); vec3 c1 = c * (1.0 / 12.92); vec3 c2 = pow((c + 0.055) * (1.0 / 1.055), vec3(2.4)); - col.rgb = mix(c1, c2, step(vec3(0.04045), c)); + in_color.rgb = mix(c1, c2, step(vec3(0.04045), c)); } - return col; + return in_color; } diff --git a/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl index 23e9f9bc20f..bc108462007 100644 --- a/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl @@ -1,10 +1,10 @@ #ifndef USE_GPU_SHADER_CREATE_INFO in vec4 finalColor; out vec4 fragColor; -#endif -#if defined(VERT) +# if defined(VERT) in float vertexCrease; +# endif #endif void main() diff --git a/source/blender/gpu/shaders/opengl/glsl_shader_defines.glsl b/source/blender/gpu/shaders/opengl/glsl_shader_defines.glsl index a5fce2e71c3..0515a737e6e 100644 --- a/source/blender/gpu/shaders/opengl/glsl_shader_defines.glsl +++ b/source/blender/gpu/shaders/opengl/glsl_shader_defines.glsl @@ -1,3 +1,13 @@ + +/* Texture format tokens -- Type explictness required by other Graphics APIs. */ +#define depth2D sampler2D +#define depth2DArray sampler2DArray +#define depth2DMS sampler2DMS +#define depth2DMSArray sampler2DMSArray +#define depthCube samplerCube +#define depthCubeArray samplerCubeArray +#define depth2DArrayShadow sampler2DArrayShadow + /* Backend Functions. */ #define select(A, B, mask) mix(A, B, mask) diff --git a/source/blender/io/alembic/exporter/abc_writer_abstract.cc b/source/blender/io/alembic/exporter/abc_writer_abstract.cc index c277e5e2710..6c50583ad62 100644 --- a/source/blender/io/alembic/exporter/abc_writer_abstract.cc +++ b/source/blender/io/alembic/exporter/abc_writer_abstract.cc @@ -98,7 +98,7 @@ const Imath::Box3d &ABCAbstractWriter::bounding_box() const void ABCAbstractWriter::update_bounding_box(Object *object) { - BoundBox *bb = BKE_object_boundbox_get(object); + const BoundBox *bb = BKE_object_boundbox_get(object); if (!bb) { if (object->type != OB_CAMERA) { diff --git a/source/blender/io/alembic/exporter/abc_writer_curves.cc b/source/blender/io/alembic/exporter/abc_writer_curves.cc index 95f296c2cf7..07bce8fcf7a 100644 --- a/source/blender/io/alembic/exporter/abc_writer_curves.cc +++ b/source/blender/io/alembic/exporter/abc_writer_curves.cc @@ -73,6 +73,7 @@ void ABCCurveWriter::do_write(HierarchyContext &context) Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first); for (; nurbs; nurbs = nurbs->next) { + const size_t current_point_count = verts.size(); if (nurbs->bp) { curve_basis = Alembic::AbcGeom::kNoBasis; curve_type = Alembic::AbcGeom::kVariableOrder; @@ -142,7 +143,7 @@ void ABCCurveWriter::do_write(HierarchyContext &context) } orders.push_back(nurbs->orderu); - vert_counts.push_back(verts.size()); + vert_counts.push_back(verts.size() - current_point_count); } Alembic::AbcGeom::OFloatGeomParam::Sample width_sample; diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc index 205ab788e6d..700d91791a8 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc +++ b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc @@ -222,7 +222,7 @@ void GpencilExporterPDF::export_stroke_to_polyline(bGPDlayer *gpl, /* Get the thickness in pixels using a simple 1 point stroke. */ bGPDstroke *gps_temp = BKE_gpencil_stroke_duplicate(gps, false, false); gps_temp->totpoints = 1; - gps_temp->points = MEM_cnew<bGPDspoint>("gp_stroke_points"); + gps_temp->points = MEM_new<bGPDspoint>("gp_stroke_points"); const bGPDspoint *pt_src = &gps->points[0]; bGPDspoint *pt_dst = &gps_temp->points[0]; copy_v3_v3(&pt_dst->x, &pt_src->x); diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc b/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc index 5d33a2806bd..2601ad05ea7 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc +++ b/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc @@ -292,7 +292,7 @@ void GpencilExporterSVG::export_stroke_to_polyline(bGPDlayer *gpl, /* Get the thickness in pixels using a simple 1 point stroke. */ bGPDstroke *gps_temp = BKE_gpencil_stroke_duplicate(gps, false, false); gps_temp->totpoints = 1; - gps_temp->points = MEM_cnew<bGPDspoint>("gp_stroke_points"); + gps_temp->points = MEM_new<bGPDspoint>("gp_stroke_points"); bGPDspoint *pt_src = &gps->points[0]; bGPDspoint *pt_dst = &gps_temp->points[0]; copy_v3_v3(&pt_dst->x, &pt_src->x); diff --git a/source/blender/io/usd/intern/usd_writer_material.cc b/source/blender/io/usd/intern/usd_writer_material.cc index b548a666ef7..1bfc0e50f69 100644 --- a/source/blender/io/usd/intern/usd_writer_material.cc +++ b/source/blender/io/usd/intern/usd_writer_material.cc @@ -255,8 +255,8 @@ void create_input(pxr::UsdShadeShader &shader, const InputSpec &spec, const void /* Find the UVMAP node input to the given texture image node and convert it * to a USD primvar reader shader. If no UVMAP node is found, create a primvar - * reader for the given default uv set. The primvar reader will be attached to - * the 'st' input of the given USD texture shader. */ + * reader for the given default uv set. The primvar reader will be attached to + * the 'st' input of the given USD texture shader. */ static void create_uvmap_shader(const USDExporterContext &usd_export_context, bNode *tex_node, pxr::UsdShadeMaterial &usd_material, @@ -359,7 +359,7 @@ static void export_in_memory_texture(Image *ima, BLI_split_file_part(image_abs_path, file_name, FILE_MAX); } else { - /* Use the image name for the file name. */ + /* Use the image name for the file name. */ strcpy(file_name, ima->id.name + 2); } @@ -452,7 +452,7 @@ static bNode *traverse_channel(bNodeSocket *input, const short target_type) } /* Returns the first occurrence of a principled BSDF or a diffuse BSDF node found in the given - * material's node tree. Returns null if no instance of either type was found.*/ + * material's node tree. Returns null if no instance of either type was found. */ static bNode *find_bsdf_node(Material *material) { LISTBASE_FOREACH (bNode *, node, &material->nodetree->nodes) { diff --git a/source/blender/io/wavefront_obj/CMakeLists.txt b/source/blender/io/wavefront_obj/CMakeLists.txt index 8045d51e0da..cc375577b52 100644 --- a/source/blender/io/wavefront_obj/CMakeLists.txt +++ b/source/blender/io/wavefront_obj/CMakeLists.txt @@ -13,6 +13,7 @@ set(INC ../../makesrna ../../nodes ../../windowmanager + ../../../../extern/fmtlib/include ../../../../intern/guardedalloc ) diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc index acfdaa29b52..f78ef334d4d 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc @@ -525,24 +525,21 @@ void MTLWriter::write_texture_map( const MTLMaterial &mtl_material, const Map<const eMTLSyntaxElement, tex_map_XX>::Item &texture_map) { - std::string translation; - std::string scale; - std::string map_bump_strength; - /* Optional strings should have their own leading spaces. */ + std::string options; + /* Option strings should have their own leading spaces. */ if (texture_map.value.translation != float3{0.0f, 0.0f, 0.0f}) { - translation.append(" -s ").append(float3_to_string(texture_map.value.translation)); + options.append(" -o ").append(float3_to_string(texture_map.value.translation)); } if (texture_map.value.scale != float3{1.0f, 1.0f, 1.0f}) { - scale.append(" -o ").append(float3_to_string(texture_map.value.scale)); + options.append(" -s ").append(float3_to_string(texture_map.value.scale)); } if (texture_map.key == eMTLSyntaxElement::map_Bump && mtl_material.map_Bump_strength > 0.0001f) { - map_bump_strength.append(" -bm ").append(std::to_string(mtl_material.map_Bump_strength)); + options.append(" -bm ").append(std::to_string(mtl_material.map_Bump_strength)); } #define SYNTAX_DISPATCH(eMTLSyntaxElement) \ if (texture_map.key == eMTLSyntaxElement) { \ - fmt_handler_.write<eMTLSyntaxElement>(translation + scale + map_bump_strength, \ - texture_map.value.image_path); \ + fmt_handler_.write<eMTLSyntaxElement>(options, texture_map.value.image_path); \ return; \ } diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_io.hh b/source/blender/io/wavefront_obj/exporter/obj_export_io.hh index 3bee93b36a5..0d7c089ec14 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_io.hh +++ b/source/blender/io/wavefront_obj/exporter/obj_export_io.hh @@ -8,7 +8,6 @@ #include <cstdio> #include <string> -#include <system_error> #include <type_traits> #include <vector> @@ -17,6 +16,11 @@ #include "BLI_string_ref.hh" #include "BLI_utility_mixins.hh" +/* SEP macro from BLI path utils clashes with SEP symbol in fmt headers. */ +#undef SEP +#define FMT_HEADER_ONLY +#include <fmt/format.h> + namespace blender::io::obj { enum class eFileType { @@ -124,40 +128,40 @@ constexpr FormattingSyntax syntax_elem_to_formatting(const eOBJSyntaxElement key { switch (key) { case eOBJSyntaxElement::vertex_coords: { - return {"v %f %f %f\n", 3, is_type_float<T...>}; + return {"v {:.6f} {:.6f} {:.6f}\n", 3, is_type_float<T...>}; } case eOBJSyntaxElement::uv_vertex_coords: { - return {"vt %f %f\n", 2, is_type_float<T...>}; + return {"vt {:.6f} {:.6f}\n", 2, is_type_float<T...>}; } case eOBJSyntaxElement::normal: { - return {"vn %.4f %.4f %.4f\n", 3, is_type_float<T...>}; + return {"vn {:.4f} {:.4f} {:.4f}\n", 3, is_type_float<T...>}; } case eOBJSyntaxElement::poly_element_begin: { return {"f", 0, is_type_string_related<T...>}; } case eOBJSyntaxElement::vertex_uv_normal_indices: { - return {" %d/%d/%d", 3, is_type_integral<T...>}; + return {" {}/{}/{}", 3, is_type_integral<T...>}; } case eOBJSyntaxElement::vertex_normal_indices: { - return {" %d//%d", 2, is_type_integral<T...>}; + return {" {}//{}", 2, is_type_integral<T...>}; } case eOBJSyntaxElement::vertex_uv_indices: { - return {" %d/%d", 2, is_type_integral<T...>}; + return {" {}/{}", 2, is_type_integral<T...>}; } case eOBJSyntaxElement::vertex_indices: { - return {" %d", 1, is_type_integral<T...>}; + return {" {}", 1, is_type_integral<T...>}; } case eOBJSyntaxElement::poly_usemtl: { - return {"usemtl %s\n", 1, is_type_string_related<T...>}; + return {"usemtl {}\n", 1, is_type_string_related<T...>}; } case eOBJSyntaxElement::edge: { - return {"l %d %d\n", 2, is_type_integral<T...>}; + return {"l {} {}\n", 2, is_type_integral<T...>}; } case eOBJSyntaxElement::cstype: { return {"cstype bspline\n", 0, is_type_string_related<T...>}; } case eOBJSyntaxElement::nurbs_degree: { - return {"deg %d\n", 1, is_type_integral<T...>}; + return {"deg {}\n", 1, is_type_integral<T...>}; } case eOBJSyntaxElement::curve_element_begin: { return {"curv 0.0 1.0", 0, is_type_string_related<T...>}; @@ -166,7 +170,7 @@ constexpr FormattingSyntax syntax_elem_to_formatting(const eOBJSyntaxElement key return {"parm u 0.0", 0, is_type_string_related<T...>}; } case eOBJSyntaxElement::nurbs_parameters: { - return {" %f", 1, is_type_float<T...>}; + return {" {:.6f}", 1, is_type_float<T...>}; } case eOBJSyntaxElement::nurbs_parameter_end: { return {" 1.0\n", 0, is_type_string_related<T...>}; @@ -184,19 +188,19 @@ constexpr FormattingSyntax syntax_elem_to_formatting(const eOBJSyntaxElement key return {"\n", 0, is_type_string_related<T...>}; } case eOBJSyntaxElement::mtllib: { - return {"mtllib %s\n", 1, is_type_string_related<T...>}; + return {"mtllib {}\n", 1, is_type_string_related<T...>}; } case eOBJSyntaxElement::smooth_group: { - return {"s %d\n", 1, is_type_integral<T...>}; + return {"s {}\n", 1, is_type_integral<T...>}; } case eOBJSyntaxElement::object_group: { - return {"g %s\n", 1, is_type_string_related<T...>}; + return {"g {}\n", 1, is_type_string_related<T...>}; } case eOBJSyntaxElement::object_name: { - return {"o %s\n", 1, is_type_string_related<T...>}; + return {"o {}\n", 1, is_type_string_related<T...>}; } case eOBJSyntaxElement::string: { - return {"%s", 1, is_type_string_related<T...>}; + return {"{}", 1, is_type_string_related<T...>}; } } } @@ -206,56 +210,56 @@ constexpr FormattingSyntax syntax_elem_to_formatting(const eMTLSyntaxElement key { switch (key) { case eMTLSyntaxElement::newmtl: { - return {"newmtl %s\n", 1, is_type_string_related<T...>}; + return {"newmtl {}\n", 1, is_type_string_related<T...>}; } case eMTLSyntaxElement::Ni: { - return {"Ni %.6f\n", 1, is_type_float<T...>}; + return {"Ni {:.6f}\n", 1, is_type_float<T...>}; } case eMTLSyntaxElement::d: { - return {"d %.6f\n", 1, is_type_float<T...>}; + return {"d {:.6f}\n", 1, is_type_float<T...>}; } case eMTLSyntaxElement::Ns: { - return {"Ns %.6f\n", 1, is_type_float<T...>}; + return {"Ns {:.6f}\n", 1, is_type_float<T...>}; } case eMTLSyntaxElement::illum: { - return {"illum %d\n", 1, is_type_integral<T...>}; + return {"illum {}\n", 1, is_type_integral<T...>}; } case eMTLSyntaxElement::Ka: { - return {"Ka %.6f %.6f %.6f\n", 3, is_type_float<T...>}; + return {"Ka {:.6f} {:.6f} {:.6f}\n", 3, is_type_float<T...>}; } case eMTLSyntaxElement::Kd: { - return {"Kd %.6f %.6f %.6f\n", 3, is_type_float<T...>}; + return {"Kd {:.6f} {:.6f} {:.6f}\n", 3, is_type_float<T...>}; } case eMTLSyntaxElement::Ks: { - return {"Ks %.6f %.6f %.6f\n", 3, is_type_float<T...>}; + return {"Ks {:.6f} {:.6f} {:.6f}\n", 3, is_type_float<T...>}; } case eMTLSyntaxElement::Ke: { - return {"Ke %.6f %.6f %.6f\n", 3, is_type_float<T...>}; + return {"Ke {:.6f} {:.6f} {:.6f}\n", 3, is_type_float<T...>}; } - /* Keep only one space between options since filepaths may have leading spaces too. */ + /* Note: first texture map related argument, if present, will have its own leading space. */ case eMTLSyntaxElement::map_Kd: { - return {"map_Kd %s %s\n", 2, is_type_string_related<T...>}; + return {"map_Kd{} {}\n", 2, is_type_string_related<T...>}; } case eMTLSyntaxElement::map_Ks: { - return {"map_Ks %s %s\n", 2, is_type_string_related<T...>}; + return {"map_Ks{} {}\n", 2, is_type_string_related<T...>}; } case eMTLSyntaxElement::map_Ns: { - return {"map_Ns %s %s\n", 2, is_type_string_related<T...>}; + return {"map_Ns{} {}\n", 2, is_type_string_related<T...>}; } case eMTLSyntaxElement::map_d: { - return {"map_d %s %s\n", 2, is_type_string_related<T...>}; + return {"map_d{} {}\n", 2, is_type_string_related<T...>}; } case eMTLSyntaxElement::map_refl: { - return {"map_refl %s %s\n", 2, is_type_string_related<T...>}; + return {"map_refl{} {}\n", 2, is_type_string_related<T...>}; } case eMTLSyntaxElement::map_Ke: { - return {"map_Ke %s %s\n", 2, is_type_string_related<T...>}; + return {"map_Ke{} {}\n", 2, is_type_string_related<T...>}; } case eMTLSyntaxElement::map_Bump: { - return {"map_Bump %s %s\n", 2, is_type_string_related<T...>}; + return {"map_Bump{} {}\n", 2, is_type_string_related<T...>}; } case eMTLSyntaxElement::string: { - return {"%s", 1, is_type_string_related<T...>}; + return {"{}", 1, is_type_string_related<T...>}; } } } @@ -270,9 +274,7 @@ constexpr FormattingSyntax syntax_elem_to_formatting(const eMTLSyntaxElement key * Call write_fo_file once in a while to write the memory buffer(s) * into the given file. */ -template<eFileType filetype, - size_t buffer_chunk_size = 64 * 1024, - size_t write_local_buffer_size = 1024> +template<eFileType filetype, size_t buffer_chunk_size = 64 * 1024> class FormatHandler : NonCopyable, NonMovable { private: typedef std::vector<char> VectorChar; @@ -299,7 +301,7 @@ class FormatHandler : NonCopyable, NonMovable { return blocks_.size(); } - void append_from(FormatHandler<filetype, buffer_chunk_size, write_local_buffer_size> &v) + void append_from(FormatHandler<filetype, buffer_chunk_size> &v) { blocks_.insert(blocks_.end(), std::make_move_iterator(v.blocks_.begin()), @@ -328,33 +330,6 @@ class FormatHandler : NonCopyable, NonMovable { } private: - /* Remove this after upgrading to C++20. */ - template<typename T> using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>; - - /** - * Make #std::string etc., usable for `fprintf` family. int float etc. are not affected. - * \return: `const char *` or the original argument if the argument is - * not related to #std::string. - */ - template<typename T> constexpr auto convert_to_primitive(T &&arg) const - { - if constexpr (std::is_same_v<remove_cvref_t<T>, std::string> || - std::is_same_v<remove_cvref_t<T>, blender::StringRefNull>) { - return arg.c_str(); - } - else if constexpr (std::is_same_v<remove_cvref_t<T>, blender::StringRef>) { - BLI_STATIC_ASSERT( - (always_false<T>::value), - "Null-terminated string not present. Please use blender::StringRefNull instead."); - /* Another trick to cause a compile-time error: returning nothing to #std::printf. */ - return; - } - else { - /* For int, float etc. */ - return std::forward<T>(arg); - } - } - /* Ensure the last block contains at least this amount of free space. * If not, add a new block with max of block size & the amount of space needed. */ void ensure_space(size_t at_least) @@ -365,38 +340,15 @@ class FormatHandler : NonCopyable, NonMovable { } } - template<typename... T> constexpr void write_impl(const char *fmt, T &&...args) + template<typename... T> void write_impl(const char *fmt, T &&...args) { - if constexpr (sizeof...(T) == 0) { - /* No arguments: just emit the format string. */ - size_t len = strlen(fmt); - ensure_space(len); - VectorChar &bb = blocks_.back(); - bb.insert(bb.end(), fmt, fmt + len); - } - else { - /* Format into a local buffer. */ - char buf[write_local_buffer_size]; - int needed = std::snprintf( - buf, write_local_buffer_size, fmt, convert_to_primitive(std::forward<T>(args))...); - if (needed < 0) - throw std::system_error( - errno, std::system_category(), "Failed to format obj export string into a buffer"); - ensure_space(needed + 1); /* Ensure space for zero terminator. */ - VectorChar &bb = blocks_.back(); - if (needed < write_local_buffer_size) { - /* String formatted successfully into the local buffer, copy it. */ - bb.insert(bb.end(), buf, buf + needed); - } - else { - /* Would need more space than the local buffer: insert said space and format again into - * that. */ - size_t bbEnd = bb.size(); - bb.insert(bb.end(), needed, ' '); - std::snprintf( - bb.data() + bbEnd, needed + 1, fmt, convert_to_primitive(std::forward<T>(args))...); - } - } + /* Format into a local buffer. */ + fmt::memory_buffer buf; + fmt::format_to(fmt::appender(buf), fmt, std::forward<T>(args)...); + size_t len = buf.size(); + ensure_space(len); + VectorChar &bb = blocks_.back(); + bb.insert(bb.end(), buf.begin(), buf.end()); } }; diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mtl.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mtl.cc index b8814b1bdd3..c48d5a5f7f0 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mtl.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mtl.cc @@ -287,14 +287,15 @@ static void store_image_textures(const nodes::NodeRef *bsdf_node, /* Find sockets linked to "Color" socket in normal map node. */ linked_sockets_to_dest_id(normal_map_node, *node_tree, "Color", linked_sockets); } - else if (texture_map.key == eMTLSyntaxElement::map_Ke) { - float emission_strength = 0.0f; - copy_property_from_node(SOCK_FLOAT, bnode, "Emission Strength", {&emission_strength, 1}); - if (emission_strength == 0.0f) { - continue; - } - } else { + /* Skip emission map if emission strength is zero. */ + if (texture_map.key == eMTLSyntaxElement::map_Ke) { + float emission_strength = 0.0f; + copy_property_from_node(SOCK_FLOAT, bnode, "Emission Strength", {&emission_strength, 1}); + if (emission_strength == 0.0f) { + continue; + } + } /* Find sockets linked to the destination socket of interest, in P-BSDF node. */ linked_sockets_to_dest_id( bnode, *node_tree, texture_map.value.dest_socket_id, linked_sockets); diff --git a/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc b/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc index b8fecfb25f3..a3512595fa7 100644 --- a/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc +++ b/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc @@ -241,7 +241,7 @@ TEST(obj_exporter_writer, mtllib) TEST(obj_exporter_writer, format_handler_buffer_chunking) { /* Use a tiny buffer chunk size, so that the test below ends up creating several blocks. */ - FormatHandler<eFileType::OBJ, 16, 8> h; + FormatHandler<eFileType::OBJ, 16> h; h.write<eOBJSyntaxElement::object_name>("abc"); h.write<eOBJSyntaxElement::object_name>("abcd"); h.write<eOBJSyntaxElement::object_name>("abcde"); @@ -486,6 +486,19 @@ TEST_F(obj_exporter_regression_test, cubes_positioned) _export.params); } +/* Note: texture paths in the resulting mtl file currently are always + * as they are stored in the source .blend file; not relative to where + * the export is done. When that is properly fixed, the expected .mtl + * file should be updated. */ +TEST_F(obj_exporter_regression_test, cubes_with_textures) +{ + OBJExportParamsDefault _export; + compare_obj_export_to_golden("io_tests/blend_geometry/cubes_with_textures.blend", + "io_tests/obj/cubes_with_textures.obj", + "io_tests/obj/cubes_with_textures.mtl", + _export.params); +} + TEST_F(obj_exporter_regression_test, suzanne_all_data) { OBJExportParamsDefault _export; diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index c3132eeab3d..3ebf085443a 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -319,6 +319,11 @@ enum { * because it was created as an single override, outside of any hierarchy consideration). */ IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY = 1 << 0, + /** + * The override ID is required for the system to work (because of ID dependencies), but is not + * seen as editable by the user. + */ + IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED = 1 << 1, }; /* watch it: Sequence has identical beginning. */ diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 564f34b1f72..1382efca409 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -138,7 +138,7 @@ typedef struct BrushGpencilSettings { } BrushGpencilSettings; typedef struct BrushCurvesSculptSettings { - /* Number of curves added by the add brush. */ + /** Number of curves added by the add brush. */ int add_amount; } BrushCurvesSculptSettings; diff --git a/source/blender/makesdna/DNA_defs.h b/source/blender/makesdna/DNA_defs.h index bfeb809b369..bbce4839506 100644 --- a/source/blender/makesdna/DNA_defs.h +++ b/source/blender/makesdna/DNA_defs.h @@ -86,6 +86,9 @@ template<class T> class ShallowDataConstRef { const T &ref_; }; +template<class T> class ShallowZeroInitializeTag { +}; + } // namespace blender::dna::internal # define DNA_DEFINE_CXX_METHODS(class_name) \ @@ -108,6 +111,18 @@ template<class T> class ShallowDataConstRef { _DNA_internal_memcpy(this, ref.get_pointer(), sizeof(class_name)); \ } \ return *this; \ + } \ + /* Create object which memory is filled with zeros. */ \ + class_name(const blender::dna::internal::ShallowZeroInitializeTag<class_name> /*tag*/) \ + : class_name() \ + { \ + _DNA_internal_memzero(this, sizeof(class_name)); \ + } \ + class_name &operator=( \ + const blender::dna::internal::ShallowZeroInitializeTag<class_name> /*tag*/) \ + { \ + _DNA_internal_memzero(this, sizeof(class_name)); \ + return *this; \ } namespace blender::dna { @@ -126,18 +141,12 @@ template<class T> return internal::ShallowDataConstRef(other); } -/* Fill underlying memory used by DNA object with zeroes. */ -template<class T> inline void zero_memory(T &object) -{ - /* TODO(sergey): Consider adding static assert for T being a trivial type. */ - _DNA_internal_memzero(&object, sizeof(T)); -} - -/* Copy memory from one DNA object to another. */ -template<class T> inline void copy_memory(T &dst, const T &src) +/* DNA object initializer which leads to an object which underlying memory is filled with zeroes. + */ +template<class T> +[[nodiscard]] inline internal::ShallowZeroInitializeTag<T> shallow_zero_initialize() { - /* TODO(sergey): Consider adding static assert for T being a trivial type. */ - _DNA_internal_memcpy(&dst, &src, sizeof(T)); + return internal::ShallowZeroInitializeTag<T>(); } } // namespace blender::dna diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index 7568dc5ff9a..6603ed1a078 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -392,9 +392,20 @@ typedef struct BuildGpencilModifierData { * For the "Concurrent" mode, when should "shorter" strips start/end. */ short time_alignment; + + /** Build origin control object. */ + struct Object *object; + /** Factor of the stroke (used instead of frame evaluation. */ float percentage_fac; - char _pad[4]; + + /** Weight fading at the end of the stroke. */ + float fade_fac; + /** Target vertexgroup name, MAX_VGROUP_NAME. */ + char target_vgname[64]; + /** Fading strength of opacity and thickness */ + float fade_opacity_strength; + float fade_thickness_strength; } BuildGpencilModifierData; typedef enum eBuildGpencil_Mode { @@ -412,7 +423,7 @@ typedef enum eBuildGpencil_Transition { /* Hide in reverse order */ GP_BUILD_TRANSITION_SHRINK = 1, /* Hide in forward order */ - GP_BUILD_TRANSITION_FADE = 2, + GP_BUILD_TRANSITION_VANISH = 2, } eBuildGpencil_Transition; typedef enum eBuildGpencil_TimeAlignment { @@ -435,6 +446,7 @@ typedef enum eBuildGpencil_Flag { /* Use a percentage instead of frame number to evaluate strokes. */ GP_BUILD_PERCENTAGE = (1 << 4), + GP_BUILD_USE_FADING = (1 << 5), } eBuildGpencil_Flag; typedef struct LatticeGpencilModifierData { diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 8a30a7e8c99..4a1b639122a 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -48,6 +48,8 @@ typedef struct bGPDcontrolpoint { } bGPDcontrolpoint; typedef struct bGPDspoint_Runtime { + DNA_DEFINE_CXX_METHODS(bGPDspoint_Runtime) + /** Original point (used to dereference evaluated data) */ struct bGPDspoint *pt_orig; /** Original index array position */ @@ -61,6 +63,8 @@ typedef struct bGPDspoint_Runtime { * This assumes that the bottom-left corner is (0,0) */ typedef struct bGPDspoint { + DNA_DEFINE_CXX_METHODS(bGPDspoint) + /** Co-ordinates of point (usually 2d, but can be 3d as well). */ float x, y, z; /** Pressure of input device (from 0 to 1) at this point. */ @@ -120,6 +124,8 @@ typedef struct bGPDtriangle { /* color of palettes */ typedef struct bGPDpalettecolor { + DNA_DEFINE_CXX_METHODS(bGPDpalettecolor) + struct bGPDpalettecolor *next, *prev; /** Color name. Must be unique. */ char info[64]; @@ -148,6 +154,8 @@ typedef enum eGPDpalettecolor_Flag { /* palette of colors */ typedef struct bGPDpalette { + DNA_DEFINE_CXX_METHODS(bGPDpalette) + struct bGPDpalette *next, *prev; /** Pointer to individual colors. */ @@ -203,6 +211,8 @@ typedef enum eGPDcurve_point_Flag { /* Curve for Bezier Editing. */ typedef struct bGPDcurve { + DNA_DEFINE_CXX_METHODS(bGPDcurve) + /** Array of BezTriple. */ bGPDcurve_point *curve_points; /** Total number of curve points. */ @@ -225,6 +235,8 @@ typedef enum bGPDcurve_Flag { /* Runtime temp data for bGPDstroke */ typedef struct bGPDstroke_Runtime { + DNA_DEFINE_CXX_METHODS(bGPDstroke_Runtime) + /** temporary layer name only used during copy/paste to put the stroke in the original layer */ char tmp_layerinfo[128]; @@ -248,6 +260,8 @@ typedef struct bGPDstroke_Runtime { * drawn by the user in one 'mouse-down'->'mouse-up' operation */ typedef struct bGPDstroke { + DNA_DEFINE_CXX_METHODS(bGPDstroke) + struct bGPDstroke *next, *prev; /** Array of data-points for stroke. */ @@ -369,6 +383,8 @@ typedef enum eGPDstroke_Arrowstyle { /* Runtime temp data for bGPDframe */ typedef struct bGPDframe_Runtime { + DNA_DEFINE_CXX_METHODS(bGPDframe_Runtime) + /** Index of this frame in the listbase of frames. */ int frameid; /** Onion offset from active frame. 0 if not onion. INT_MAX to bypass frame. */ @@ -382,6 +398,8 @@ typedef struct bGPDframe_Runtime { * -> Acts as storage for the 'image' formed by strokes */ typedef struct bGPDframe { + DNA_DEFINE_CXX_METHODS(bGPDframe) + struct bGPDframe *next, *prev; /** List of the simplified 'strokes' that make up the frame's data. */ @@ -416,6 +434,8 @@ typedef enum eGPDframe_Flag { /* List of masking layers. */ typedef struct bGPDlayer_Mask { + DNA_DEFINE_CXX_METHODS(bGPDlayer_Mask) + struct bGPDlayer_Mask *next, *prev; char name[128]; short flag; @@ -434,6 +454,8 @@ typedef enum ebGPDlayer_Mask_Flag { /* Runtime temp data for bGPDlayer */ typedef struct bGPDlayer_Runtime { + DNA_DEFINE_CXX_METHODS(bGPDlayer_Runtime) + /** Id for dynamic icon used to show annotation color preview for layer. */ int icon_id; char _pad[4]; @@ -443,6 +465,8 @@ typedef struct bGPDlayer_Runtime { /* Grease-Pencil Annotations - 'Layer' */ typedef struct bGPDlayer { + DNA_DEFINE_CXX_METHODS(bGPDlayer) + struct bGPDlayer *next, *prev; /** List of annotations to display for frames (bGPDframe list). */ @@ -580,6 +604,8 @@ typedef enum eGPLayerBlendModes { /* Runtime temp data for bGPdata */ typedef struct bGPdata_Runtime { + DNA_DEFINE_CXX_METHODS(bGPdata_Runtime) + /** Stroke buffer. */ void *sbuffer; /** Temp batches cleared after drawing. */ @@ -642,6 +668,8 @@ typedef struct bGPgrid { /* Grease-Pencil Annotations - 'DataBlock' */ typedef struct bGPdata { + DNA_DEFINE_CXX_METHODS(bGPdata) + /** Grease Pencil data is a data-block. */ ID id; /** Animation data - for animating draw settings. */ diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h index 7b6fe3773f8..d5f7e25bb80 100644 --- a/source/blender/makesdna/DNA_layer_types.h +++ b/source/blender/makesdna/DNA_layer_types.h @@ -124,6 +124,21 @@ typedef struct ViewLayerAOV { * matches `eViewLayerAOVType` */ int type; } ViewLayerAOV; + +/* Lightgroup Renderpass definition. */ +typedef struct ViewLayerLightgroup { + struct ViewLayerLightgroup *next, *prev; + + /* Name of the Lightgroup */ + char name[64]; +} ViewLayerLightgroup; + +/* Lightgroup membership information. */ +typedef struct LightgroupMembership { + /* Name of the Lightgroup */ + char name[64]; +} LightgroupMembership; + typedef struct ViewLayer { struct ViewLayer *next, *prev; /** MAX_NAME. */ @@ -164,6 +179,10 @@ typedef struct ViewLayer { ListBase aovs; ViewLayerAOV *active_aov; + /* List containing the 'ViewLayerLightgroup`s */ + ListBase lightgroups; + ViewLayerLightgroup *active_lightgroup; + /* Runtime data */ /** ViewLayerEngineData. */ ListBase drawdata; diff --git a/source/blender/makesdna/DNA_modifier_defaults.h b/source/blender/makesdna/DNA_modifier_defaults.h index 299ac4e2fbe..77730ce254c 100644 --- a/source/blender/makesdna/DNA_modifier_defaults.h +++ b/source/blender/makesdna/DNA_modifier_defaults.h @@ -309,7 +309,7 @@ .falloff = 0.0f, \ .curfalloff = NULL, \ .indexar = NULL, \ - .totindex = 0, \ + .indexar_num = 0, \ .force = 1.0f, \ .name = "", \ } @@ -317,7 +317,7 @@ #define _DNA_DEFAULT_LaplacianDeformModifierData \ { \ .anchor_grp_name = "", \ - .total_verts = 0, \ + .verts_num = 0, \ .repeat = 1, \ .vertexco = NULL, \ .cache_system = NULL, \ @@ -381,13 +381,13 @@ .bindinfluences = NULL, \ .bindoffsets = NULL, \ .bindcagecos = NULL, \ - .totvert = 0, \ - .totcagevert = 0, \ + .verts_num = 0, \ + .cage_verts_num = 0, \ .dyngrid = NULL, \ .dyninfluences = NULL, \ .dynverts = NULL, \ .dyngridsize = 0, \ - .totinfluence = 0, \ + .influences_num = 0, \ .dyncellmin = {0.0f, 0.0f, 0.0f}, \ .dyncellwidth = 0.0f, \ .bindmat = _DNA_DEFAULT_UNIT_M4, \ @@ -621,7 +621,7 @@ .mesh = NULL, \ .bvhtree = NULL, \ .cfra = 0, \ - .numverts = 0, \ + .verts_num = 0, \ } #define _DNA_DEFAULT_SurfaceDeformModifierData \ @@ -630,9 +630,9 @@ .target = NULL, \ .verts = NULL, \ .falloff = 4.0f, \ - .num_mesh_verts = 0, \ - .num_bind_verts = 0, \ - .numpoly = 0, \ + .mesh_verts_num = 0, \ + .bind_verts_num = 0, \ + .polys_num = 0, \ .flags = 0, \ .mat = _DNA_DEFAULT_UNIT_M4, \ .strength = 1.0f, \ @@ -650,7 +650,7 @@ #define _DNA_DEFAULT_UVProjectModifierData \ { \ .projectors = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, \ - .num_projectors = 1, \ + .projectors_num = 1, \ .aspectx = 1.0f, \ .aspecty = 1.0f, \ .scalex = 1.0f, \ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 807a615f7f9..11825de4b33 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -617,7 +617,7 @@ typedef struct UVProjectModifierData { */ struct Object *projectors[10]; char _pad2[4]; - int num_projectors; + int projectors_num; float aspectx, aspecty; float scalex, scaley; /** MAX_CUSTOMDATA_LAYER_NAME. */ @@ -812,7 +812,7 @@ typedef struct HookModifierData { /** If NULL, it's using vertexgroup. */ int *indexar; - int totindex; + int indexar_num; float force; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char name[64]; @@ -895,7 +895,7 @@ typedef struct SurfaceModifierData { /** Bounding volume hierarchy of the mesh faces. */ struct BVHTreeFromMesh *bvhtree; - int cfra, numverts; + int cfra, verts_num; } SurfaceModifierData; typedef struct BooleanModifierData { @@ -945,7 +945,7 @@ typedef struct MDefInfluence { typedef struct MDefCell { int offset; - int totinfluence; + int influences_num; } MDefCell; typedef struct MeshDeformModifierData { @@ -967,7 +967,7 @@ typedef struct MeshDeformModifierData { /** Coordinates that cage was bound with. */ float *bindcagecos; /** Total vertices in mesh and cage. */ - int totvert, totcagevert; + int verts_num, cage_verts_num; /* result of dynamic binding */ /** Grid with dynamic binding cell points. */ @@ -979,7 +979,7 @@ typedef struct MeshDeformModifierData { /** Size of the dynamic bind grid. */ int dyngridsize; /** Total number of vertex influences. */ - int totinfluence; + int influences_num; /** Offset of the dynamic bind grid. */ float dyncellmin[3]; /** Width of dynamic bind cell. */ @@ -998,7 +998,7 @@ typedef struct MeshDeformModifierData { struct MeshDeformModifierData *mmd, struct Mesh *cagemesh, float *vertexcos, - int totvert, + int verts_num, float cagemat[4][4]); } MeshDeformModifierData; @@ -2018,7 +2018,7 @@ typedef struct LaplacianDeformModifierData { ModifierData modifier; /** MAX_VGROUP_NAME. */ char anchor_grp_name[64]; - int total_verts, repeat; + int verts_num, repeat; float *vertexco; /** Runtime only. */ void *cache_system; @@ -2201,7 +2201,7 @@ enum { typedef struct SDefBind { unsigned int *vert_inds; - unsigned int numverts; + unsigned int verts_num; int mode; float *vert_weights; float normal_dist; @@ -2210,7 +2210,7 @@ typedef struct SDefBind { typedef struct SDefVert { SDefBind *binds; - unsigned int numbinds; + unsigned int binds_num; unsigned int vertex_idx; } SDefVert; @@ -2223,7 +2223,7 @@ typedef struct SurfaceDeformModifierData { /** Vertex bind data. */ SDefVert *verts; float falloff; - unsigned int num_mesh_verts, num_bind_verts, numpoly; + unsigned int mesh_verts_num, bind_verts_num, polys_num; int flags; float mat[4][4]; float strength; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 99d7e15fa7a..73539bea8ee 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1189,7 +1189,7 @@ typedef struct NodeCryptomatte { /** Legacy attributes */ /* Number of input sockets. */ - int num_inputs; + int inputs_num; char _pad[4]; NodeCryptomatte_Runtime runtime; diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index c3708e25ee7..54627e711ff 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -31,6 +31,7 @@ struct Curve; struct FluidsimSettings; struct GeometrySet; struct Ipo; +struct LightgroupMembership; struct Material; struct Mesh; struct Object; @@ -93,7 +94,7 @@ typedef struct BoundBox { /** #BoundBox.flag */ enum { - BOUNDBOX_DISABLED = (1 << 0), + /* BOUNDBOX_DISABLED = (1 << 0), */ /* UNUSED */ BOUNDBOX_DIRTY = (1 << 1), }; @@ -203,7 +204,7 @@ typedef struct Object_Runtime { float (*crazyspace_deform_imats)[3][3]; float (*crazyspace_deform_cos)[3]; - int crazyspace_num_verts; + int crazyspace_verts_num; int _pad3[3]; } Object_Runtime; @@ -434,8 +435,10 @@ typedef struct Object { ObjectLineArt lineart; + /** Lightgroup membership information. */ + struct LightgroupMembership *lightgroup; + /** Runtime evaluation data (keep last). */ - void *_pad9; Object_Runtime runtime; } Object; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index e6b2f2769b8..ed049bb6a9d 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1113,7 +1113,7 @@ typedef struct GP_Sculpt_Settings { /** Threshold for intersections */ float isect_threshold; char _pad[4]; - /** Multiframe edit falloff effect by frame. */ + /** Multi-frame edit falloff effect by frame. */ struct CurveMapping *cur_falloff; /** Curve used for primitive tools. */ struct CurveMapping *cur_primitive; @@ -1990,7 +1990,7 @@ enum { /* sequencer seq_prev_type seq_rend_type */ -/** #RenderData.engine (scene.c) */ +/** #RenderData.engine (scene.cc) */ extern const char *RE_engine_id_BLENDER_EEVEE; extern const char *RE_engine_id_BLENDER_WORKBENCH; extern const char *RE_engine_id_CYCLES; @@ -2017,7 +2017,10 @@ extern const char *RE_engine_id_CYCLES; ((v3d == NULL) || (((1 << (base)->object->type) & (v3d)->object_type_exclude_select) == 0)) && \ (((base)->flag & BASE_SELECTABLE) != 0)) #define BASE_SELECTED(v3d, base) (BASE_VISIBLE(v3d, base) && (((base)->flag & BASE_SELECTED) != 0)) -#define BASE_EDITABLE(v3d, base) (BASE_VISIBLE(v3d, base) && !ID_IS_LINKED((base)->object)) +#define BASE_EDITABLE(v3d, base) \ + (BASE_VISIBLE(v3d, base) && !ID_IS_LINKED((base)->object) && \ + (!ID_IS_OVERRIDE_LIBRARY_REAL((base)->object) || \ + ((base)->object->id.override_library->flag & IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED) == 0)) #define BASE_SELECTED_EDITABLE(v3d, base) \ (BASE_EDITABLE(v3d, base) && (((base)->flag & BASE_SELECTED) != 0)) diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index d32757cc868..c1eee109630 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -540,7 +540,7 @@ enum { AREA_FLAG_STACKED_FULLSCREEN = (1 << 7), /** Update action zones (even if the mouse is not intersecting them). */ AREA_FLAG_ACTIONZONES_UPDATE = (1 << 8), - /** For offscreen areas. */ + /** For off-screen areas. */ AREA_FLAG_OFFSCREEN = (1 << 9), }; diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index f538917143b..e9bf3126c97 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -280,8 +280,12 @@ typedef struct SpaceOutliner { char search_string[64]; struct TreeStoreElem search_tse; - short flag, outlinevis, storeflag; + short flag; + short outlinevis; + short lib_override_view_mode; + short storeflag; char search_flags; + char _pad[6]; /** Selection syncing flag (#WM_OUTLINER_SYNC_SELECT_FROM_OBJECT and similar flags). */ char sync_select_dirty; @@ -388,6 +392,14 @@ typedef enum eSpaceOutliner_Mode { SO_OVERRIDES_LIBRARY = 16, } eSpaceOutliner_Mode; +/** #SpaceOutliner.outlinevis */ +typedef enum eSpaceOutliner_LibOverrideViewMode { + /* View all overrides with RNA buttons to edit the overridden values. */ + SO_LIB_OVERRIDE_VIEW_PROPERTIES = 0, + /* View entire override hierarchies (relationships between overriden data-blocks). */ + SO_LIB_OVERRIDE_VIEW_HIERARCHIES = 1, +} eSpaceOutliner_LibOverrideViewMode; + /** #SpaceOutliner.storeflag */ typedef enum eSpaceOutliner_StoreFlag { /* cleanup tree */ @@ -989,12 +1001,6 @@ typedef enum eFileSelectType { FILE_SPECIAL = 9, } eFileSelectType; -/** File-selector op property -> action. */ -typedef enum eFileSel_Action { - FILE_OPENFILE = 0, - FILE_SAVE = 1, -} eFileSel_Action; - /** * #FileSelectParams.flag / `sfile->params->flag`. * \note short flag, also used as 16 lower bits of flags in link/append code diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h index 497b99eb04d..88f2e0c9407 100644 --- a/source/blender/makesdna/DNA_world_types.h +++ b/source/blender/makesdna/DNA_world_types.h @@ -16,6 +16,7 @@ extern "C" { struct AnimData; struct Ipo; +struct LightgroupMembership; struct bNodeTree; #ifndef MAX_MTEX @@ -70,6 +71,9 @@ typedef struct World { /* nodes */ struct bNodeTree *nodetree; + /* Lightgroup membership information. */ + struct LightgroupMembership *lightgroup; + /** Runtime. */ ListBase gpumaterial; } World; diff --git a/source/blender/makesdna/intern/dna_rename_defs.h b/source/blender/makesdna/intern/dna_rename_defs.h index b2896c80db3..86649357433 100644 --- a/source/blender/makesdna/intern/dna_rename_defs.h +++ b/source/blender/makesdna/intern/dna_rename_defs.h @@ -74,31 +74,45 @@ DNA_STRUCT_RENAME_ELEM(FluidDomainSettings, guiding_parent, guide_parent) DNA_STRUCT_RENAME_ELEM(FluidDomainSettings, guiding_source, guide_source) DNA_STRUCT_RENAME_ELEM(FluidDomainSettings, guiding_vel_factor, guide_vel_factor) DNA_STRUCT_RENAME_ELEM(FluidEffectorSettings, guiding_mode, guide_mode) +DNA_STRUCT_RENAME_ELEM(HookModifierData, totindex, indexar_num) DNA_STRUCT_RENAME_ELEM(Image, name, filepath) +DNA_STRUCT_RENAME_ELEM(LaplacianDeformModifierData, total_verts, verts_num) DNA_STRUCT_RENAME_ELEM(Library, name, filepath) DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, line_types, edge_types) DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, transparency_flags, mask_switches) DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, transparency_mask, material_mask_bits) +DNA_STRUCT_RENAME_ELEM(MDefCell, totinfluence, influences_num) DNA_STRUCT_RENAME_ELEM(MaskLayer, restrictflag, visibility_flag) DNA_STRUCT_RENAME_ELEM(MaterialLineArt, transparency_mask, material_mask_bits) +DNA_STRUCT_RENAME_ELEM(MeshDeformModifierData, totcagevert, cage_verts_num) +DNA_STRUCT_RENAME_ELEM(MeshDeformModifierData, totinfluence, influences_num) +DNA_STRUCT_RENAME_ELEM(MeshDeformModifierData, totvert, verts_num) DNA_STRUCT_RENAME_ELEM(MovieClip, name, filepath) +DNA_STRUCT_RENAME_ELEM(NodeCryptomatte, num_inputs, inputs_num) 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, restrictflag, visibility_flag) DNA_STRUCT_RENAME_ELEM(Object, size, scale) +DNA_STRUCT_RENAME_ELEM(Object_Runtime, crazyspace_num_verts, crazyspace_verts_num) DNA_STRUCT_RENAME_ELEM(ParticleSettings, child_nbr, child_percent) 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) DNA_STRUCT_RENAME_ELEM(ParticleSettings, ren_child_nbr, child_render_percent) -DNA_STRUCT_RENAME_ELEM(RigidBodyWorld, steps_per_second, substeps_per_frame) DNA_STRUCT_RENAME_ELEM(RenderData, bake_filter, bake_margin) +DNA_STRUCT_RENAME_ELEM(RigidBodyWorld, steps_per_second, substeps_per_frame) +DNA_STRUCT_RENAME_ELEM(SDefBind, numverts, verts_num) +DNA_STRUCT_RENAME_ELEM(SDefVert, numbinds, binds_num) DNA_STRUCT_RENAME_ELEM(SpaceSeq, overlay_type, overlay_frame_type) -DNA_STRUCT_RENAME_ELEM(SurfaceDeformModifierData, numverts, num_bind_verts) +DNA_STRUCT_RENAME_ELEM(SurfaceDeformModifierData, num_mesh_verts, mesh_verts_num) +DNA_STRUCT_RENAME_ELEM(SurfaceDeformModifierData, numpoly, polys_num) +DNA_STRUCT_RENAME_ELEM(SurfaceDeformModifierData, numverts, bind_verts_num) +DNA_STRUCT_RENAME_ELEM(SurfaceModifierData, numverts, verts_num) DNA_STRUCT_RENAME_ELEM(Text, name, filepath) DNA_STRUCT_RENAME_ELEM(ThemeSpace, scrubbing_background, time_scrub_background) DNA_STRUCT_RENAME_ELEM(ThemeSpace, show_back_grad, background_type) +DNA_STRUCT_RENAME_ELEM(UVProjectModifierData, num_projectors, projectors_num) DNA_STRUCT_RENAME_ELEM(UserDef, gp_manhattendist, gp_manhattandist) DNA_STRUCT_RENAME_ELEM(VFont, name, filepath) DNA_STRUCT_RENAME_ELEM(View3D, far, clip_end) diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 4292c270b6f..e1e655fad4b 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -802,7 +802,7 @@ void RNA_collection_clear(PointerRNA *ptr, const char *name); bool RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, bool use_ghost); bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop); void RNA_property_unset(PointerRNA *ptr, PropertyRNA *prop); -/** See #RNA_property_is_set_ex documentation. */ +/** See #RNA_property_is_set_ex documentation. */ bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost); bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier); bool RNA_property_is_idprop(const PropertyRNA *prop); diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 82d90a5c54b..d3b7e380afa 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -762,7 +762,8 @@ static void rna_ID_override_library_reset(ID *id, IDOverrideLibrary *UNUSED(override_library), Main *bmain, ReportList *reports, - bool do_hierarchy) + bool do_hierarchy, + bool set_system_override) { if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { BKE_reportf(reports, RPT_ERROR, "ID '%s' isn't an override", id->name); @@ -770,10 +771,10 @@ static void rna_ID_override_library_reset(ID *id, } if (do_hierarchy) { - BKE_lib_override_library_id_hierarchy_reset(bmain, id); + BKE_lib_override_library_id_hierarchy_reset(bmain, id, set_system_override); } else { - BKE_lib_override_library_id_reset(bmain, id); + BKE_lib_override_library_id_reset(bmain, id, set_system_override); } WM_main_add_notifier(NC_WM | ND_LIB_OVERRIDE_CHANGED, NULL); @@ -1832,6 +1833,17 @@ static void rna_def_ID_override_library(BlenderRNA *brna) "hierarchy, or as a single, isolated and autonomous override"); RNA_def_property_update(prop, NC_WM | ND_LIB_OVERRIDE_CHANGED, NULL); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + + prop = RNA_def_boolean(srna, + "is_system_override", + false, + "Is System Override", + "Whether this library override exists only for the override hierarchy, " + "or if it is actually editable by the user"); + RNA_def_property_update(prop, NC_WM | ND_LIB_OVERRIDE_CHANGED, NULL); + RNA_def_property_boolean_sdna(prop, NULL, "flag", IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); prop = RNA_def_collection(srna, "properties", @@ -1858,6 +1870,11 @@ static void rna_def_ID_override_library(BlenderRNA *brna) true, "", "Also reset all the dependencies of this override to match their reference linked IDs"); + RNA_def_boolean(func, + "set_system_override", + false, + "", + "Reset all user-editable overrides as (non-editable) system overrides"); func = RNA_def_function(srna, "destroy", "rna_ID_override_library_destroy"); RNA_def_function_ui_description( @@ -1987,6 +2004,8 @@ static void rna_def_ID(BlenderRNA *brna) prop = RNA_def_pointer( srna, "override_library", "IDOverrideLibrary", "Library Override", "Library override data"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, + PROPOVERRIDE_NO_COMPARISON | PROPOVERRIDE_OVERRIDABLE_LIBRARY); prop = RNA_def_pointer(srna, "preview", diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index b4617321f44..5690d864a75 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -32,8 +32,10 @@ #include "BKE_collection.h" #include "BKE_context.h" #include "BKE_fcurve.h" +#include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_idtype.h" +#include "BKE_lib_override.h" #include "BKE_main.h" #include "BKE_node.h" #include "BKE_report.h" @@ -1930,17 +1932,29 @@ static bool rna_property_editable_do(PointerRNA *ptr, /* Handle linked or liboverride ID cases. */ const bool is_linked_prop_exception = (prop->flag & PROP_LIB_EXCEPTION) != 0; - if (ID_IS_LINKED(id) && !is_linked_prop_exception) { + if (ID_IS_LINKED(id)) { + if (is_linked_prop_exception) { + return true; + } if (r_info != NULL && (*r_info)[0] == '\0') { *r_info = N_("Can't edit this property from a linked data-block"); } return false; } - if (ID_IS_OVERRIDE_LIBRARY(id) && !RNA_property_overridable_get(ptr, prop_orig)) { - if (r_info != NULL && (*r_info)[0] == '\0') { - *r_info = N_("Can't edit this property from an override data-block"); + if (ID_IS_OVERRIDE_LIBRARY(id)) { + const bool is_liboverride_system = BKE_lib_override_library_is_system_defined(G_MAIN, id); + if (!RNA_property_overridable_get(ptr, prop_orig)) { + if (r_info != NULL && (*r_info)[0] == '\0') { + *r_info = N_("Can't edit this property from an override data-block"); + } + return false; + } + if (is_liboverride_system && !is_linked_prop_exception) { + if (r_info != NULL && (*r_info)[0] == '\0') { + *r_info = N_("Can't edit this property from a system override data-block"); + } + return false; } - return false; } /* At this point, property is owned by a local ID and therefore fully editable. */ @@ -6012,13 +6026,29 @@ char *RNA_path_struct_property_py(PointerRNA *ptr, PropertyRNA *prop, int index) char *RNA_path_property_py(const PointerRNA *UNUSED(ptr), PropertyRNA *prop, int index) { + const bool is_rna = (prop->magic == RNA_MAGIC); + const char *propname = RNA_property_identifier(prop); char *ret; if ((index == -1) || (RNA_property_array_check(prop) == false)) { - ret = BLI_sprintfN("%s", RNA_property_identifier(prop)); + if (is_rna) { + ret = BLI_strdup(propname); + } + else { + char propname_esc[MAX_IDPROP_NAME * 2]; + BLI_str_escape(propname_esc, propname, sizeof(propname_esc)); + ret = BLI_sprintfN("[\"%s\"]", propname_esc); + } } else { - ret = BLI_sprintfN("%s[%d]", RNA_property_identifier(prop), index); + if (is_rna) { + ret = BLI_sprintfN("%s[%d]", propname, index); + } + else { + char propname_esc[MAX_IDPROP_NAME * 2]; + BLI_str_escape(propname_esc, propname, sizeof(propname_esc)); + ret = BLI_sprintfN("[\"%s\"][%d]", propname_esc, index); + } } return ret; diff --git a/source/blender/makesrna/intern/rna_access_compare_override.c b/source/blender/makesrna/intern/rna_access_compare_override.c index cce310e4b6d..5974788884e 100644 --- a/source/blender/makesrna/intern/rna_access_compare_override.c +++ b/source/blender/makesrna/intern/rna_access_compare_override.c @@ -612,10 +612,6 @@ static bool rna_property_override_operation_apply(Main *bmain, ptr_item_src, ptr_item_storage, opop); - if (success) { - RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst); - } - return success; } diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index ba7f3c55460..4f07cb235fa 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -680,7 +680,7 @@ static FCurve *rna_Driver_find(AnimData *adt, return BKE_fcurve_find(&adt->drivers, data_path, index); } -bool rna_AnimaData_override_apply(Main *UNUSED(bmain), +bool rna_AnimaData_override_apply(Main *bmain, PointerRNA *ptr_dst, PointerRNA *ptr_src, PointerRNA *ptr_storage, @@ -707,11 +707,13 @@ bool rna_AnimaData_override_apply(Main *UNUSED(bmain), if (adt_dst == NULL && adt_src != NULL) { /* Copy anim data from reference into final local ID. */ BKE_animdata_copy_id(NULL, ptr_dst->owner_id, ptr_src->owner_id, 0); + RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst); return true; } else if (adt_dst != NULL && adt_src == NULL) { /* Override has cleared/removed anim data from its reference. */ BKE_animdata_free(ptr_dst->owner_id, true); + RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst); return true; } @@ -722,7 +724,7 @@ bool rna_NLA_tracks_override_apply(Main *bmain, PointerRNA *ptr_dst, PointerRNA *ptr_src, PointerRNA *UNUSED(ptr_storage), - PropertyRNA *UNUSED(prop_dst), + PropertyRNA *prop_dst, PropertyRNA *UNUSED(prop_src), PropertyRNA *UNUSED(prop_storage), const int UNUSED(len_dst), @@ -771,6 +773,8 @@ bool rna_NLA_tracks_override_apply(Main *bmain, BLI_insertlinkafter(&anim_data_dst->nla_tracks, nla_track_anchor, nla_track_dst); // printf("%s: We inserted a NLA Track...\n", __func__); + + RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst); return true; } diff --git a/source/blender/makesrna/intern/rna_collection.c b/source/blender/makesrna/intern/rna_collection.c index eceabe65a67..599d36c0af7 100644 --- a/source/blender/makesrna/intern/rna_collection.c +++ b/source/blender/makesrna/intern/rna_collection.c @@ -138,7 +138,7 @@ static bool rna_Collection_objects_override_apply(Main *bmain, PointerRNA *ptr_dst, PointerRNA *UNUSED(ptr_src), PointerRNA *UNUSED(ptr_storage), - PropertyRNA *UNUSED(prop_dst), + PropertyRNA *prop_dst, PropertyRNA *UNUSED(prop_src), PropertyRNA *UNUSED(prop_storage), const int UNUSED(len_dst), @@ -185,6 +185,7 @@ static bool rna_Collection_objects_override_apply(Main *bmain, BKE_main_collection_sync(bmain); } + RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst); return true; } @@ -245,7 +246,7 @@ static bool rna_Collection_children_override_apply(Main *bmain, PointerRNA *ptr_dst, PointerRNA *UNUSED(ptr_src), PointerRNA *UNUSED(ptr_storage), - PropertyRNA *UNUSED(prop_dst), + PropertyRNA *prop_dst, PropertyRNA *UNUSED(prop_src), PropertyRNA *UNUSED(prop_storage), const int UNUSED(len_dst), @@ -287,6 +288,7 @@ static bool rna_Collection_children_override_apply(Main *bmain, BKE_collection_object_cache_free(coll_dst); BKE_main_collection_sync(bmain); + RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst); return true; } diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index ba94fbe88e5..9a9b6d582e5 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -848,10 +848,6 @@ static float rna_GPencilStrokePoints_weight_get(bGPDstroke *stroke, } MDeformVert *pt_dvert = stroke->dvert + point_index; - if ((pt_dvert) && (pt_dvert->totweight <= vertex_group_index || vertex_group_index < 0)) { - BKE_report(reports, RPT_ERROR, "Groups: index out of range"); - return -1.0f; - } MDeformWeight *dw = BKE_defvert_find_index(pt_dvert, vertex_group_index); if (dw) { diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index 9e25ddaf790..b09d8a4738d 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -382,6 +382,7 @@ RNA_GP_MOD_VGROUP_NAME_SET(WeightAngle, vgname); RNA_GP_MOD_VGROUP_NAME_SET(Lineart, vgname); RNA_GP_MOD_VGROUP_NAME_SET(Shrinkwrap, vgname); RNA_GP_MOD_VGROUP_NAME_SET(Envelope, vgname); +RNA_GP_MOD_VGROUP_NAME_SET(Build, target_vgname); # undef RNA_GP_MOD_VGROUP_NAME_SET @@ -416,6 +417,7 @@ RNA_GP_MOD_OBJECT_SET(Mirror, object, OB_EMPTY); RNA_GP_MOD_OBJECT_SET(WeightProx, object, OB_EMPTY); RNA_GP_MOD_OBJECT_SET(Shrinkwrap, target, OB_MESH); RNA_GP_MOD_OBJECT_SET(Shrinkwrap, aux_target, OB_MESH); +RNA_GP_MOD_OBJECT_SET(Build, object, OB_EMPTY); # undef RNA_GP_MOD_OBJECT_SET @@ -1031,7 +1033,7 @@ static void rna_def_modifier_gpencilsmooth(BlenderRNA *brna) prop, "Step", "Number of times to apply smooth (high numbers can reduce fps)"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "keep_shape", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_keep_shape", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SMOOTH_KEEP_SHAPE); RNA_def_property_ui_text(prop, "Keep Shape", "Smooth the details, but keep the overall shape"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); @@ -2133,10 +2135,10 @@ static void rna_def_modifier_gpencilbuild(BlenderRNA *brna) "Shrink", "Hide points from the end of each stroke to the start " "(e.g. for animating lines being erased)"}, - {GP_BUILD_TRANSITION_FADE, - "FADE", + {GP_BUILD_TRANSITION_VANISH, + "FADE", /* "Fade" is the original id string kept for compatibility purpose. */ 0, - "Fade", + "Vanish", "Hide points in the order they occur in each stroke " "(e.g. for animating ink fading or vanishing after getting drawn)"}, {0, NULL, 0, NULL, NULL}, @@ -2242,6 +2244,43 @@ static void rna_def_modifier_gpencilbuild(BlenderRNA *brna) RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "use_fading", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BUILD_USE_FADING); + RNA_def_property_ui_text(prop, "Use Fading", "Fade out strokes instead of directly cutting off"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "fade_factor", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "fade_fac"); + RNA_def_property_ui_text(prop, "Fade Factor", "Defines how much of the stroke is fading in/out"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "target_vertex_group", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "target_vgname"); + RNA_def_property_ui_text(prop, "Vertex Group", "Output Vertex group"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_BuildGpencilModifier_target_vgname_set"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "fade_opacity_strength", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "fade_opacity_strength"); + RNA_def_property_ui_text( + prop, "Opacity Strength", "How much strength fading applies on top of stroke opacity"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "fade_thickness_strength", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "fade_thickness_strength"); + RNA_def_property_ui_text( + prop, "Thickness Strength", "How much strength fading applies on top of stroke thickness"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); + RNA_def_property_ui_text(prop, "Object", "Object used as build starting position"); + RNA_def_property_pointer_funcs(prop, NULL, "rna_BuildGpencilModifier_object_set", NULL, NULL); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update"); + /* Filters - Layer */ prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "layername"); @@ -3745,7 +3784,7 @@ static void rna_def_modifier_gpencildash(BlenderRNA *brna) prop = RNA_def_property(srna, "use_cyclic", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DASH_USE_CYCLIC); - RNA_def_property_ui_text(prop, "Use Cyclic", "Enable cyclic on individual stroke dashes"); + RNA_def_property_ui_text(prop, "Cyclic", "Enable cyclic on individual stroke dashes"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); srna = RNA_def_struct(brna, "DashGpencilModifierData", "GpencilModifier"); diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 84f083cb37a..0df0be07fee 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -355,6 +355,10 @@ void rna_ViewLayer_active_aov_index_range( PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax); int rna_ViewLayer_active_aov_index_get(PointerRNA *ptr); void rna_ViewLayer_active_aov_index_set(PointerRNA *ptr, int value); +void rna_ViewLayer_active_lightgroup_index_range( + PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax); +int rna_ViewLayer_active_lightgroup_index_get(PointerRNA *ptr); +void rna_ViewLayer_active_lightgroup_index_set(PointerRNA *ptr, int value); /** * Set `r_rna_path` with the base view-layer path. * `rna_path_buffer_size` should be at least `sizeof(ViewLayer.name) * 3`. diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index b239260c8eb..6c621604e40 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -92,6 +92,7 @@ # include "DNA_volume_types.h" # include "DNA_world_types.h" +# include "ED_node.h" # include "ED_screen.h" # include "BLT_translation.h" @@ -291,6 +292,7 @@ static struct bNodeTree *rna_Main_nodetree_new(Main *bmain, const char *name, in bNodeTreeType *typeinfo = rna_node_tree_type_from_enum(type); if (typeinfo) { bNodeTree *ntree = ntreeAddTree(bmain, safe_name, typeinfo->idname); + ED_node_tree_propagate_change(NULL, bmain, ntree); id_us_min(&ntree->id); return ntree; diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 2ef2e776842..4f9a10c9993 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -687,7 +687,7 @@ static void rna_UVProject_projectors_begin(CollectionPropertyIterator *iter, Poi { UVProjectModifierData *uvp = (UVProjectModifierData *)ptr->data; rna_iterator_array_begin( - iter, (void *)uvp->projectors, sizeof(Object *), uvp->num_projectors, 0, NULL); + iter, (void *)uvp->projectors, sizeof(Object *), uvp->projectors_num, 0, NULL); } static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr) @@ -895,7 +895,7 @@ static void rna_HookModifier_object_set(PointerRNA *ptr, BKE_object_modifier_hook_reset(owner, hmd); } -static bool rna_HookModifier_object_override_apply(Main *UNUSED(bmain), +static bool rna_HookModifier_object_override_apply(Main *bmain, PointerRNA *ptr_dst, PointerRNA *ptr_src, PointerRNA *ptr_storage, @@ -933,6 +933,7 @@ static bool rna_HookModifier_object_override_apply(Main *UNUSED(bmain), /* The only case where we do want default behavior (with matrix reset). */ BKE_object_modifier_hook_reset(owner, hmd); } + RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst); return true; } @@ -949,15 +950,15 @@ static int rna_HookModifier_vertex_indices_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION]) { HookModifierData *hmd = ptr->data; - int totindex = hmd->indexar ? hmd->totindex : 0; - return (length[0] = totindex); + int indexar_num = hmd->indexar ? hmd->indexar_num : 0; + return (length[0] = indexar_num); } static void rna_HookModifier_vertex_indices_get(PointerRNA *ptr, int *values) { HookModifierData *hmd = ptr->data; if (hmd->indexar != NULL) { - memcpy(values, hmd->indexar, sizeof(int) * hmd->totindex); + memcpy(values, hmd->indexar, sizeof(int) * hmd->indexar_num); } } @@ -968,7 +969,7 @@ static void rna_HookModifier_vertex_indices_set(HookModifierData *hmd, { if (indices_len == 0) { MEM_SAFE_FREE(hmd->indexar); - hmd->totindex = 0; + hmd->indexar_num = 0; } else { /* Reject negative indices. */ @@ -998,7 +999,7 @@ static void rna_HookModifier_vertex_indices_set(HookModifierData *hmd, /* Success - save the new array. */ MEM_SAFE_FREE(hmd->indexar); hmd->indexar = buffer; - hmd->totindex = indices_len; + hmd->indexar_num = indices_len; } } @@ -1148,8 +1149,8 @@ static void rna_UVProjectModifier_num_projectors_set(PointerRNA *ptr, int value) UVProjectModifierData *md = (UVProjectModifierData *)ptr->data; int a; - md->num_projectors = CLAMPIS(value, 1, MOD_UVPROJECT_MAXPROJECTORS); - for (a = md->num_projectors; a < MOD_UVPROJECT_MAXPROJECTORS; a++) { + md->projectors_num = CLAMPIS(value, 1, MOD_UVPROJECT_MAXPROJECTORS); + for (a = md->projectors_num; a < MOD_UVPROJECT_MAXPROJECTORS; a++) { md->projectors[a] = NULL; } } @@ -3104,7 +3105,7 @@ static void rna_def_modifier_uvproject(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Modifier_update"); prop = RNA_def_property(srna, "projector_count", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "num_projectors"); + RNA_def_property_int_sdna(prop, NULL, "projectors_num"); RNA_def_property_ui_text(prop, "Number of Projectors", "Number of projectors to use"); RNA_def_property_int_funcs(prop, NULL, "rna_UVProjectModifier_num_projectors_set", NULL); RNA_def_property_range(prop, 1, MOD_UVPROJECT_MAXPROJECTORS); @@ -4081,7 +4082,8 @@ static void rna_def_modifier_bevel(BlenderRNA *brna) prop = RNA_def_property(srna, "segments", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "res"); - RNA_def_property_range(prop, 1, 100); + RNA_def_property_range(prop, 1, 1000); + RNA_def_property_ui_range(prop, 1, 100, 1, -1); RNA_def_property_ui_text(prop, "Segments", "Number of segments for round edges/verts"); RNA_def_property_update(prop, 0, "rna_BevelModifier_update_segments"); diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 7164f24c2f7..f995ee3383e 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -200,12 +200,6 @@ static EnumPropertyItem instance_items_nogroup[] = { {0, NULL, 0, NULL, NULL}, }; -static EnumPropertyItem instance_items_pointcloud[] = { - {0, "NONE", 0, "None", ""}, - {OB_DUPLIVERTS, "POINTS", 0, "Points", "Instantiate child objects on all points"}, - {0, NULL, 0, NULL, NULL}, -}; - static EnumPropertyItem instance_items_empty[] = { {0, "NONE", 0, "None", ""}, INSTANCE_ITEM_COLLECTION, @@ -652,7 +646,7 @@ static void rna_Object_parent_set(PointerRNA *ptr, } } -static bool rna_Object_parent_override_apply(Main *UNUSED(bmain), +static bool rna_Object_parent_override_apply(Main *bmain, PointerRNA *ptr_dst, PointerRNA *ptr_src, PointerRNA *ptr_storage, @@ -689,6 +683,7 @@ static bool rna_Object_parent_override_apply(Main *UNUSED(bmain), else { ob->parent = parent_src; } + RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst); return true; } @@ -760,9 +755,6 @@ static const EnumPropertyItem *rna_Object_instance_type_itemf(bContext *UNUSED(C if (ob->type == OB_EMPTY) { item = instance_items_empty; } - else if (ob->type == OB_POINTCLOUD) { - item = instance_items_pointcloud; - } else if (ob->type == OB_FONT) { item = instance_items_font; } @@ -1676,11 +1668,11 @@ static bConstraint *rna_Object_constraints_copy(Object *object, Main *bmain, Poi return new_con; } -bool rna_Object_constraints_override_apply(Main *UNUSED(bmain), +bool rna_Object_constraints_override_apply(Main *bmain, PointerRNA *ptr_dst, PointerRNA *ptr_src, PointerRNA *UNUSED(ptr_storage), - PropertyRNA *UNUSED(prop_dst), + PropertyRNA *prop_dst, PropertyRNA *UNUSED(prop_src), PropertyRNA *UNUSED(prop_storage), const int UNUSED(len_dst), @@ -1725,6 +1717,7 @@ bool rna_Object_constraints_override_apply(Main *UNUSED(bmain), BKE_constraint_unique_name(con_dst, &ob_dst->constraints); // printf("%s: We inserted a constraint...\n", __func__); + RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst); return true; } @@ -1795,7 +1788,7 @@ bool rna_Object_modifiers_override_apply(Main *bmain, PointerRNA *ptr_dst, PointerRNA *ptr_src, PointerRNA *UNUSED(ptr_storage), - PropertyRNA *UNUSED(prop_dst), + PropertyRNA *prop_dst, PropertyRNA *UNUSED(prop_src), PropertyRNA *UNUSED(prop_storage), const int UNUSED(len_dst), @@ -1856,6 +1849,7 @@ bool rna_Object_modifiers_override_apply(Main *bmain, BLI_insertlinkafter(&ob_dst->modifiers, mod_anchor, mod_dst); // printf("%s: We inserted a modifier '%s'...\n", __func__, mod_dst->name); + RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst); return true; } @@ -1892,7 +1886,7 @@ bool rna_Object_greasepencil_modifiers_override_apply(Main *bmain, PointerRNA *ptr_dst, PointerRNA *ptr_src, PointerRNA *UNUSED(ptr_storage), - PropertyRNA *UNUSED(prop_dst), + PropertyRNA *prop_dst, PropertyRNA *UNUSED(prop_src), PropertyRNA *UNUSED(prop_storage), const int UNUSED(len_dst), @@ -1941,6 +1935,7 @@ bool rna_Object_greasepencil_modifiers_override_apply(Main *bmain, BLI_insertlinkafter(&ob_dst->greasepencil_modifiers, mod_anchor, mod_dst); // printf("%s: We inserted a gpencil modifier '%s'...\n", __func__, mod_dst->name); + RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst); return true; } @@ -1976,7 +1971,7 @@ static void rna_Object_shaderfx_clear(Object *object, bContext *C) static void rna_Object_boundbox_get(PointerRNA *ptr, float *values) { Object *ob = (Object *)ptr->owner_id; - BoundBox *bb = BKE_object_boundbox_get(ob); + const BoundBox *bb = BKE_object_boundbox_get(ob); if (bb) { memcpy(values, bb->vec, sizeof(bb->vec)); } @@ -2297,6 +2292,21 @@ static int rna_Object_mesh_symmetry_yz_editable(PointerRNA *ptr, const char **UN return PROP_EDITABLE; } +void rna_Object_lightgroup_get(PointerRNA *ptr, char *value) +{ + BKE_lightgroup_membership_get(((Object *)ptr->owner_id)->lightgroup, value); +} + +int rna_Object_lightgroup_length(PointerRNA *ptr) +{ + return BKE_lightgroup_membership_length(((Object *)ptr->owner_id)->lightgroup); +} + +void rna_Object_lightgroup_set(PointerRNA *ptr, const char *value) +{ + BKE_lightgroup_membership_set(&((Object *)ptr->owner_id)->lightgroup, value); +} + #else static void rna_def_vertex_group(BlenderRNA *brna) @@ -3780,6 +3790,15 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_editable_func(prop, "rna_Object_mesh_symmetry_yz_editable"); RNA_def_property_ui_text(prop, "Z", "Enable mesh symmetry in the Z axis"); + /* Lightgroup Membership */ + prop = RNA_def_property(srna, "lightgroup", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs(prop, + "rna_Object_lightgroup_get", + "rna_Object_lightgroup_length", + "rna_Object_lightgroup_set"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Lightgroup", "Lightgroup that the object belongs to"); + RNA_define_lib_overridable(false); /* anim */ diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index ece1c5e5815..6967f78026a 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -594,7 +594,7 @@ static void rna_Object_ray_cast(Object *ob, } /* Test BoundBox first (efficiency) */ - BoundBox *bb = BKE_object_boundbox_get(ob); + const BoundBox *bb = BKE_object_boundbox_get(ob); float distmin; /* Needed for valid distance check from #isect_ray_aabb_v3_simple() call. */ diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 8579f188428..ce4b1a193a3 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -49,6 +49,8 @@ static const EnumPropertyItem effector_shape_items[] = { # include "BLI_math_base.h" +# include "RNA_access.h" + /* type specific return values only used from functions */ static const EnumPropertyItem curve_shape_items[] = { {PFIELD_SHAPE_POINT, "POINT", 0, "Point", "Field originates from the object center"}, @@ -239,6 +241,33 @@ static void rna_Cache_toggle_disk_cache(Main *UNUSED(bmain), Scene *UNUSED(scene } } +bool rna_Cache_use_disk_cache_override_apply(Main *UNUSED(bmain), + PointerRNA *ptr_dst, + PointerRNA *ptr_src, + PointerRNA *UNUSED(ptr_storage), + PropertyRNA *prop_dst, + PropertyRNA *prop_src, + PropertyRNA *UNUSED(prop_storage), + const int UNUSED(len_dst), + const int UNUSED(len_src), + const int UNUSED(len_storage), + PointerRNA *UNUSED(ptr_item_dst), + PointerRNA *UNUSED(ptr_item_src), + PointerRNA *UNUSED(ptr_item_storage), + IDOverrideLibraryPropertyOperation *opop) +{ + BLI_assert(RNA_property_type(prop_dst) == PROP_BOOLEAN); + BLI_assert(opop->operation == IDOVERRIDE_LIBRARY_OP_REPLACE); + UNUSED_VARS_NDEBUG(opop); + + RNA_property_boolean_set(ptr_dst, prop_dst, RNA_property_boolean_get(ptr_src, prop_src)); + + /* DO NOT call `RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst);`, that would trigger + * the whole 'update from mem point cache' process, ending up in the complete deletion of an + * existing diskcache if any. */ + return true; +} + static void rna_Cache_idname_change(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { Object *ob = NULL; @@ -407,7 +436,7 @@ int rna_Cache_info_length(PointerRNA *ptr) PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache); - if (cache->flag & PTCACHE_FLAG_INFO_DIRTY) { + if (pid.cache != NULL && pid.cache->flag & PTCACHE_FLAG_INFO_DIRTY) { BKE_ptcache_update_info(&pid); } @@ -983,6 +1012,7 @@ static void rna_def_pointcache_common(StructRNA *srna) RNA_def_property_ui_text( prop, "Disk Cache", "Save cache files to disk (.blend file must be saved first)"); RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_toggle_disk_cache"); + RNA_def_property_override_funcs(prop, NULL, NULL, "rna_Cache_use_disk_cache_override_apply"); prop = RNA_def_property(srna, "is_outdated", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_OUTDATED); @@ -1016,6 +1046,7 @@ static void rna_def_pointcache_common(StructRNA *srna) prop = RNA_def_property(srna, "info", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "info"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON); /* Note that we do not actually need a getter here, `rna_Cache_info_length` will update the info * string just as well. */ RNA_def_property_string_funcs(prop, NULL, "rna_Cache_info_length", NULL); diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 8b59962d858..2390fdd72f0 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -644,11 +644,11 @@ static bConstraint *rna_PoseChannel_constraints_copy(ID *id, return new_con; } -bool rna_PoseChannel_constraints_override_apply(Main *UNUSED(bmain), +bool rna_PoseChannel_constraints_override_apply(Main *bmain, PointerRNA *ptr_dst, PointerRNA *ptr_src, PointerRNA *UNUSED(ptr_storage), - PropertyRNA *UNUSED(prop_dst), + PropertyRNA *prop_dst, PropertyRNA *UNUSED(prop_src), PropertyRNA *UNUSED(prop_storage), const int UNUSED(len_dst), @@ -694,6 +694,7 @@ bool rna_PoseChannel_constraints_override_apply(Main *UNUSED(bmain), BKE_constraint_unique_name(con_dst, &pchan_dst->constraints); // printf("%s: We inserted a constraint...\n", __func__); + RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst); return true; } diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index 8f1847c00f4..373df6b7444 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -2297,7 +2297,7 @@ bool rna_property_override_store_default(Main *UNUSED(bmain), return changed; } -bool rna_property_override_apply_default(Main *UNUSED(bmain), +bool rna_property_override_apply_default(Main *bmain, PointerRNA *ptr_dst, PointerRNA *ptr_src, PointerRNA *ptr_storage, @@ -2319,6 +2319,8 @@ bool rna_property_override_apply_default(Main *UNUSED(bmain), const int index = is_array ? opop->subitem_reference_index : 0; const short override_op = opop->operation; + bool ret_success = true; + switch (RNA_property_type(prop_dst)) { case PROP_BOOLEAN: if (is_array && index == -1) { @@ -2355,7 +2357,7 @@ bool rna_property_override_apply_default(Main *UNUSED(bmain), return false; } } - return true; + break; case PROP_INT: if (is_array && index == -1) { int array_stack_a[RNA_STACK_ARRAY], array_stack_b[RNA_STACK_ARRAY]; @@ -2434,7 +2436,7 @@ bool rna_property_override_apply_default(Main *UNUSED(bmain), return false; } } - return true; + break; case PROP_FLOAT: if (is_array && index == -1) { float array_stack_a[RNA_STACK_ARRAY], array_stack_b[RNA_STACK_ARRAY]; @@ -2527,7 +2529,7 @@ bool rna_property_override_apply_default(Main *UNUSED(bmain), return false; } } - return true; + break; case PROP_ENUM: { const int value = RNA_property_enum_get(ptr_src, prop_src); @@ -2540,7 +2542,7 @@ bool rna_property_override_apply_default(Main *UNUSED(bmain), BLI_assert_msg(0, "Unsupported RNA override operation on enum"); return false; } - return true; + break; } case PROP_POINTER: { PointerRNA value = RNA_property_pointer_get(ptr_src, prop_src); @@ -2553,7 +2555,7 @@ bool rna_property_override_apply_default(Main *UNUSED(bmain), BLI_assert_msg(0, "Unsupported RNA override operation on pointer"); return false; } - return true; + break; } case PROP_STRING: { char buff[256]; @@ -2571,7 +2573,7 @@ bool rna_property_override_apply_default(Main *UNUSED(bmain), if (value != buff) { MEM_freeN(value); } - return true; + break; } case PROP_COLLECTION: { /* We only support IDProperty-based collection insertion here. */ @@ -2636,19 +2638,27 @@ bool rna_property_override_apply_default(Main *UNUSED(bmain), IDProperty *item_idprop_dst = item_ptr_dst.data; IDP_CopyPropertyContent(item_idprop_dst, item_idprop_src); - return RNA_property_collection_move(ptr_dst, prop_dst, item_index_added, item_index_dst); + ret_success = RNA_property_collection_move( + ptr_dst, prop_dst, item_index_added, item_index_dst); + break; } default: BLI_assert_msg(0, "Unsupported RNA override operation on collection"); return false; } + break; } default: BLI_assert(0); return false; } - return false; + /* Default apply callback always call property update. */ + if (ret_success) { + RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst); + } + + return ret_success; } # undef RNA_PROPERTY_GET_SINGLE diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 6be2c361ba9..0960d246257 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1767,6 +1767,10 @@ void rna_ViewLayer_pass_update(Main *bmain, Scene *activescene, PointerRNA *ptr) ViewLayerAOV *aov = (ViewLayerAOV *)ptr->data; view_layer = BKE_view_layer_find_with_aov(scene, aov); } + else if (ptr->type == &RNA_Lightgroup) { + ViewLayerLightgroup *lightgroup = (ViewLayerLightgroup *)ptr->data; + view_layer = BKE_view_layer_find_with_lightgroup(scene, lightgroup); + } if (view_layer) { RenderEngineType *engine_type = RE_engines_find(scene->r.engine); @@ -1878,7 +1882,7 @@ static void rna_Scene_editmesh_select_mode_update(bContext *C, PointerRNA *UNUSE static void rna_Scene_uv_select_mode_update(bContext *C, PointerRNA *UNUSED(ptr)) { /* Makes sure that the UV selection states are consistent with the current UV select mode and - * sticky mode.*/ + * sticky mode. */ ED_uvedit_selectmode_clean_multi(C); } @@ -2447,6 +2451,49 @@ void rna_ViewLayer_active_aov_index_set(PointerRNA *ptr, int value) view_layer->active_aov = aov; } +void rna_ViewLayer_active_lightgroup_index_range( + PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) +{ + ViewLayer *view_layer = (ViewLayer *)ptr->data; + + *min = 0; + *max = max_ii(0, BLI_listbase_count(&view_layer->lightgroups) - 1); +} + +int rna_ViewLayer_active_lightgroup_index_get(PointerRNA *ptr) +{ + ViewLayer *view_layer = (ViewLayer *)ptr->data; + return BLI_findindex(&view_layer->lightgroups, view_layer->active_lightgroup); +} + +void rna_ViewLayer_active_lightgroup_index_set(PointerRNA *ptr, int value) +{ + ViewLayer *view_layer = (ViewLayer *)ptr->data; + ViewLayerLightgroup *lightgroup = BLI_findlink(&view_layer->lightgroups, value); + view_layer->active_lightgroup = lightgroup; +} + +static void rna_ViewLayerLightgroup_name_get(PointerRNA *ptr, char *value) +{ + ViewLayerLightgroup *lightgroup = (ViewLayerLightgroup *)ptr->data; + BLI_strncpy(value, lightgroup->name, sizeof(lightgroup->name)); +} + +static int rna_ViewLayerLightgroup_name_length(PointerRNA *ptr) +{ + ViewLayerLightgroup *lightgroup = (ViewLayerLightgroup *)ptr->data; + return strlen(lightgroup->name); +} + +static void rna_ViewLayerLightgroup_name_set(PointerRNA *ptr, const char *value) +{ + ViewLayerLightgroup *lightgroup = (ViewLayerLightgroup *)ptr->data; + Scene *scene = (Scene *)ptr->owner_id; + ViewLayer *view_layer = BKE_view_layer_find_with_lightgroup(scene, lightgroup); + + BKE_view_layer_rename_lightgroup(view_layer, lightgroup, value); +} + /* Fake value, used internally (not saved to DNA). */ # define V3D_ORIENT_DEFAULT -1 @@ -4156,6 +4203,43 @@ static void rna_def_view_layer_aov(BlenderRNA *brna) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); } +static void rna_def_view_layer_lightgroups(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + /* PropertyRNA *prop; */ + + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "Lightgroups"); + srna = RNA_def_struct(brna, "Lightgroups", NULL); + RNA_def_struct_sdna(srna, "ViewLayer"); + RNA_def_struct_ui_text(srna, "List of Lightgroups", "Collection of Lightgroups"); + + func = RNA_def_function(srna, "add", "BKE_view_layer_add_lightgroup"); + parm = RNA_def_pointer(func, "lightgroup", "Lightgroup", "", "Newly created Lightgroup"); + RNA_def_function_return(func, parm); +} + +static void rna_def_view_layer_lightgroup(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + srna = RNA_def_struct(brna, "Lightgroup", NULL); + RNA_def_struct_sdna(srna, "ViewLayerLightgroup"); + RNA_def_struct_ui_text(srna, "Light Group", ""); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_string_funcs(prop, + "rna_ViewLayerLightgroup_name_get", + "rna_ViewLayerLightgroup_name_length", + "rna_ViewLayerLightgroup_name_set"); + RNA_def_property_ui_text(prop, "Name", "Name of the Lightgroup"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); + RNA_def_struct_name_property(srna, prop); +} + void rna_def_view_layer_common(BlenderRNA *brna, StructRNA *srna, const bool scene) { PropertyRNA *prop; @@ -4226,6 +4310,25 @@ void rna_def_view_layer_common(BlenderRNA *brna, StructRNA *srna, const bool sce RNA_def_property_ui_text(prop, "Active AOV Index", "Index of active aov"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + prop = RNA_def_property(srna, "lightgroups", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "lightgroups", NULL); + RNA_def_property_struct_type(prop, "Lightgroup"); + RNA_def_property_ui_text(prop, "Light Groups", ""); + rna_def_view_layer_lightgroups(brna, prop); + + prop = RNA_def_property(srna, "active_lightgroup", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "Lightgroup"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Light Groups", "Active Lightgroup"); + + prop = RNA_def_property(srna, "active_lightgroup_index", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_funcs(prop, + "rna_ViewLayer_active_lightgroup_index_get", + "rna_ViewLayer_active_lightgroup_index_set", + "rna_ViewLayer_active_lightgroup_index_range"); + RNA_def_property_ui_text(prop, "Active Lightgroup Index", "Index of active lightgroup"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + prop = RNA_def_property(srna, "use_pass_cryptomatte_object", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "cryptomatte_flag", VIEW_LAYER_CRYPTOMATTE_OBJECT); RNA_def_property_ui_text( @@ -8088,6 +8191,7 @@ void RNA_def_scene(BlenderRNA *brna) rna_def_scene_display(brna); rna_def_scene_eevee(brna); rna_def_view_layer_aov(brna); + rna_def_view_layer_lightgroup(brna); rna_def_view_layer_eevee(brna); rna_def_scene_gpencil(brna); RNA_define_animate_sdna(true); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 3839b3ba6a4..e21c10166ab 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -3593,6 +3593,21 @@ static void rna_def_space_outliner(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem lib_override_view_mode[] = { + {SO_LIB_OVERRIDE_VIEW_PROPERTIES, + "PROPERTIES", + ICON_NONE, + "Properties", + "Display all local override data-blocks with their overridden properties and buttons to " + "edit them"}, + {SO_LIB_OVERRIDE_VIEW_HIERARCHIES, + "HIERARCHIES", + ICON_NONE, + "Hierarchies", + "Display library override relationships"}, + {0, NULL, 0, NULL, NULL}, + }; + static const EnumPropertyItem filter_state_items[] = { {SO_FILTER_OB_ALL, "ALL", 0, "All", "Show all objects in the view layer"}, {SO_FILTER_OB_VISIBLE, "VISIBLE", 0, "Visible", "Show visible objects"}, @@ -3612,6 +3627,13 @@ static void rna_def_space_outliner(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Display Mode", "Type of information to display"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL); + prop = RNA_def_property(srna, "lib_override_view_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, lib_override_view_mode); + RNA_def_property_ui_text(prop, + "Library Override View Mode", + "Choose different visualizations of library override data"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL); + prop = RNA_def_property(srna, "filter_text", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "search_string"); RNA_def_property_ui_text(prop, "Display Filter", "Live search filtering string"); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 164564241ed..fd2bb9cb7cc 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2923,8 +2923,8 @@ static void rna_def_userdef_theme_space_node(BlenderRNA *brna) prop = RNA_def_property(srna, "grid_levels", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "grid_levels"); - RNA_def_property_int_default(prop, 7); - RNA_def_property_range(prop, 0, 9); + RNA_def_property_int_default(prop, 3); + RNA_def_property_range(prop, 0, 3); RNA_def_property_ui_text( prop, "Grid Levels", "Number of subdivisions for the dot grid displayed in the background"); RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c index 04008665342..d1049eef2c7 100644 --- a/source/blender/makesrna/intern/rna_world.c +++ b/source/blender/makesrna/intern/rna_world.c @@ -22,6 +22,7 @@ # include "MEM_guardedalloc.h" # include "BKE_context.h" +# include "BKE_layer.h" # include "BKE_main.h" # include "BKE_texture.h" @@ -84,6 +85,21 @@ static void rna_World_use_nodes_update(bContext *C, PointerRNA *ptr) rna_World_draw_update(bmain, scene, ptr); } +void rna_World_lightgroup_get(PointerRNA *ptr, char *value) +{ + BKE_lightgroup_membership_get(((World *)ptr->owner_id)->lightgroup, value); +} + +int rna_World_lightgroup_length(PointerRNA *ptr) +{ + return BKE_lightgroup_membership_length(((World *)ptr->owner_id)->lightgroup); +} + +void rna_World_lightgroup_set(PointerRNA *ptr, const char *value) +{ + BKE_lightgroup_membership_set(&((World *)ptr->owner_id)->lightgroup, value); +} + #else static void rna_def_lighting(BlenderRNA *brna) @@ -234,6 +250,13 @@ void RNA_def_world(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Use Nodes", "Use shader nodes to render the world"); RNA_def_property_update(prop, 0, "rna_World_use_nodes_update"); + /* Lightgroup Membership */ + prop = RNA_def_property(srna, "lightgroup", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs( + prop, "rna_World_lightgroup_get", "rna_World_lightgroup_length", "rna_World_lightgroup_set"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Lightgroup", "Lightgroup that the world belongs to"); + rna_def_lighting(brna); rna_def_world_mist(brna); } diff --git a/source/blender/modifiers/MOD_nodes.h b/source/blender/modifiers/MOD_nodes.h index 053fb6e3244..4a3ccd8ecd1 100644 --- a/source/blender/modifiers/MOD_nodes.h +++ b/source/blender/modifiers/MOD_nodes.h @@ -17,8 +17,6 @@ extern "C" { */ void MOD_nodes_update_interface(struct Object *object, struct NodesModifierData *nmd); -void MOD_nodes_init(struct Main *bmain, struct NodesModifierData *nmd); - #ifdef __cplusplus } #endif diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index 5d37ac79fa6..f6e8a26f0e1 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -132,7 +132,7 @@ static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { ArmatureModifierData *amd = (ArmatureModifierData *)md; @@ -142,7 +142,7 @@ static void deformVerts(ModifierData *md, ctx->object, vertexCos, NULL, - numVerts, + verts_num, amd->deformflag, amd->vert_coords_prev, amd->defgrp_name, @@ -157,10 +157,10 @@ static void deformVertsEM(ModifierData *md, struct BMEditMesh *em, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { if (mesh != NULL) { - deformVerts(md, ctx, mesh, vertexCos, numVerts); + deformVerts(md, ctx, mesh, vertexCos, verts_num); return; } @@ -172,7 +172,7 @@ static void deformVertsEM(ModifierData *md, ctx->object, vertexCos, NULL, - numVerts, + verts_num, amd->deformflag, amd->vert_coords_prev, amd->defgrp_name, @@ -188,7 +188,7 @@ static void deformMatricesEM(ModifierData *md, Mesh *UNUSED(mesh), float (*vertexCos)[3], float (*defMats)[3][3], - int numVerts) + int verts_num) { ArmatureModifierData *amd = (ArmatureModifierData *)md; @@ -196,7 +196,7 @@ static void deformMatricesEM(ModifierData *md, ctx->object, vertexCos, defMats, - numVerts, + verts_num, amd->deformflag, NULL, amd->defgrp_name, @@ -208,16 +208,17 @@ static void deformMatrices(ModifierData *md, Mesh *mesh, float (*vertexCos)[3], float (*defMats)[3][3], - int numVerts) + int verts_num) { ArmatureModifierData *amd = (ArmatureModifierData *)md; - Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false); + Mesh *mesh_src = MOD_deform_mesh_eval_get( + ctx->object, NULL, mesh, NULL, verts_num, false, false); BKE_armature_deform_coords_with_mesh(amd->object, ctx->object, vertexCos, defMats, - numVerts, + verts_num, amd->deformflag, NULL, amd->defgrp_name, diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index b237f952287..758858c8b1d 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -139,17 +139,17 @@ static void svert_from_mvert(SortVertsElem *sv, /** * Take as inputs two sets of verts, to be processed for detection of doubles and mapping. - * Each set of verts is defined by its start within mverts array and its num_verts; + * Each set of verts is defined by its start within mverts array and its verts_num; * It builds a mapping for all vertices within source, * to vertices within target, or -1 if no double found. - * The int doubles_map[num_verts_source] array must have been allocated by caller. + * The `int doubles_map[verts_source_num]` array must have been allocated by caller. */ static void dm_mvert_map_doubles(int *doubles_map, const MVert *mverts, const int target_start, - const int target_num_verts, + const int target_verts_num, const int source_start, - const int source_num_verts, + const int source_verts_num, const float dist) { const float dist3 = ((float)M_SQRT3 + 0.00005f) * dist; /* Just above sqrt(3) */ @@ -158,12 +158,12 @@ static void dm_mvert_map_doubles(int *doubles_map, SortVertsElem *sve_source, *sve_target, *sve_target_low_bound; bool target_scan_completed; - target_end = target_start + target_num_verts; - source_end = source_start + source_num_verts; + target_end = target_start + target_verts_num; + source_end = source_start + source_verts_num; /* build array of MVerts to be tested for merging */ - sorted_verts_target = MEM_malloc_arrayN(target_num_verts, sizeof(SortVertsElem), __func__); - sorted_verts_source = MEM_malloc_arrayN(source_num_verts, sizeof(SortVertsElem), __func__); + sorted_verts_target = MEM_malloc_arrayN(target_verts_num, sizeof(SortVertsElem), __func__); + sorted_verts_source = MEM_malloc_arrayN(source_verts_num, sizeof(SortVertsElem), __func__); /* Copy target vertices index and cos into SortVertsElem array */ svert_from_mvert(sorted_verts_target, mverts + target_start, target_start, target_end); @@ -172,8 +172,8 @@ static void dm_mvert_map_doubles(int *doubles_map, svert_from_mvert(sorted_verts_source, mverts + source_start, source_start, source_end); /* sort arrays according to sum of vertex coordinates (sumco) */ - qsort(sorted_verts_target, target_num_verts, sizeof(SortVertsElem), svert_sum_cmp); - qsort(sorted_verts_source, source_num_verts, sizeof(SortVertsElem), svert_sum_cmp); + qsort(sorted_verts_target, target_verts_num, sizeof(SortVertsElem), svert_sum_cmp); + qsort(sorted_verts_source, source_verts_num, sizeof(SortVertsElem), svert_sum_cmp); sve_target_low_bound = sorted_verts_target; i_target_low_bound = 0; @@ -181,7 +181,7 @@ static void dm_mvert_map_doubles(int *doubles_map, /* Scan source vertices, in #SortVertsElem sorted array, * all the while maintaining the lower bound of possible doubles in target vertices. */ - for (i_source = 0, sve_source = sorted_verts_source; i_source < source_num_verts; + for (i_source = 0, sve_source = sorted_verts_source; i_source < source_verts_num; i_source++, sve_source++) { int best_target_vertex = -1; float best_dist_sq = dist * dist; @@ -202,13 +202,13 @@ static void dm_mvert_map_doubles(int *doubles_map, /* Skip all target vertices that are more than dist3 lower in terms of sumco */ /* and advance the overall lower bound, applicable to all remaining vertices as well. */ - while ((i_target_low_bound < target_num_verts) && + while ((i_target_low_bound < target_verts_num) && (sve_target_low_bound->sum_co < sve_source_sumco - dist3)) { i_target_low_bound++; sve_target_low_bound++; } /* If end of target list reached, then no more possible doubles */ - if (i_target_low_bound >= target_num_verts) { + if (i_target_low_bound >= target_verts_num) { doubles_map[sve_source->vertex_num] = -1; target_scan_completed = true; continue; @@ -221,7 +221,7 @@ static void dm_mvert_map_doubles(int *doubles_map, /* i_target will scan vertices in the * [v_source_sumco - dist3; v_source_sumco + dist3] range */ - while ((i_target < target_num_verts) && (sve_target->sum_co <= sve_source_sumco + dist3)) { + while ((i_target < target_verts_num) && (sve_target->sum_co <= sve_source_sumco + dist3)) { /* Testing distance for candidate double in target */ /* v_target is within dist3 of v_source in terms of sumco; check real distance */ float dist_sq; @@ -478,7 +478,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, } /* About 67 million vertices max seems a decent limit for now. */ - const size_t max_num_vertices = 1 << 26; + const size_t max_vertices_num = 1 << 26; /* calculate the maximum number of copies which will fit within the * prescribed length */ @@ -496,7 +496,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, * vertices. */ if (((size_t)count * (size_t)chunk_nverts + (size_t)start_cap_nverts + - (size_t)end_cap_nverts) > max_num_vertices) { + (size_t)end_cap_nverts) > max_vertices_num) { count = 1; offset_is_too_small = true; } @@ -518,7 +518,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, * vertices. */ else if (((size_t)count * (size_t)chunk_nverts + (size_t)start_cap_nverts + - (size_t)end_cap_nverts) > max_num_vertices) { + (size_t)end_cap_nverts) > max_vertices_num) { count = 1; BKE_modifier_set_error(ctx->object, &amd->modifier, diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c index cd77abfca50..61959d242d8 100644 --- a/source/blender/modifiers/intern/MOD_build.c +++ b/source/blender/modifiers/intern/MOD_build.c @@ -46,9 +46,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(bmd, DNA_struct_default_get(BuildModifierData), modifier); } -static bool dependsOnTime(struct Scene *UNUSED(scene), - ModifierData *UNUSED(md), - const int UNUSED(dag_eval_mode)) +static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md)) { return true; } @@ -58,7 +56,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct Mesh *result; BuildModifierData *bmd = (BuildModifierData *)md; int i, j, k; - int numFaces_dst, numEdges_dst, numLoops_dst = 0; + int faces_dst_num, edges_dst_num, loops_dst_num = 0; int *vertMap, *edgeMap, *faceMap; float frac; MPoly *mpoly_dst; @@ -71,21 +69,21 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct /* maps edge indices in old mesh to indices in new mesh */ GHash *edgeHash2 = BLI_ghash_int_new("build ed apply gh"); - const int numVert_src = mesh->totvert; - const int numEdge_src = mesh->totedge; - const int numPoly_src = mesh->totpoly; + const int vert_src_num = mesh->totvert; + const int edge_src_num = mesh->totedge; + const int poly_src_num = mesh->totpoly; MPoly *mpoly_src = mesh->mpoly; MLoop *mloop_src = mesh->mloop; MEdge *medge_src = mesh->medge; MVert *mvert_src = mesh->mvert; - vertMap = MEM_malloc_arrayN(numVert_src, sizeof(*vertMap), "build modifier vertMap"); - edgeMap = MEM_malloc_arrayN(numEdge_src, sizeof(*edgeMap), "build modifier edgeMap"); - faceMap = MEM_malloc_arrayN(numPoly_src, sizeof(*faceMap), "build modifier faceMap"); + vertMap = MEM_malloc_arrayN(vert_src_num, sizeof(*vertMap), "build modifier vertMap"); + edgeMap = MEM_malloc_arrayN(edge_src_num, sizeof(*edgeMap), "build modifier edgeMap"); + faceMap = MEM_malloc_arrayN(poly_src_num, sizeof(*faceMap), "build modifier faceMap"); - range_vn_i(vertMap, numVert_src, 0); - range_vn_i(edgeMap, numEdge_src, 0); - range_vn_i(faceMap, numPoly_src, 0); + range_vn_i(vertMap, vert_src_num, 0); + range_vn_i(edgeMap, edge_src_num, 0); + range_vn_i(faceMap, poly_src_num, 0); struct Scene *scene = DEG_get_input_scene(ctx->depsgraph); frac = (BKE_scene_ctime_get(scene) - bmd->start) / bmd->length; @@ -94,17 +92,17 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct frac = 1.0f - frac; } - numFaces_dst = numPoly_src * frac; - numEdges_dst = numEdge_src * frac; + faces_dst_num = poly_src_num * frac; + edges_dst_num = edge_src_num * frac; /* if there's at least one face, build based on faces */ - if (numFaces_dst) { + if (faces_dst_num) { MPoly *mpoly, *mp; MLoop *ml, *mloop; uintptr_t hash_num, hash_num_alt; if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) { - BLI_array_randomize(faceMap, sizeof(*faceMap), numPoly_src, bmd->seed); + BLI_array_randomize(faceMap, sizeof(*faceMap), poly_src_num, bmd->seed); } /* get the set of all vert indices that will be in the final mesh, @@ -113,7 +111,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct mpoly = mpoly_src; mloop = mloop_src; hash_num = 0; - for (i = 0; i < numFaces_dst; i++) { + for (i = 0; i < faces_dst_num; i++) { mp = mpoly + faceMap[i]; ml = mloop + mp->loopstart; @@ -125,7 +123,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct } } - numLoops_dst += mp->totloop; + loops_dst_num += mp->totloop; } BLI_assert(hash_num == BLI_ghash_len(vertHash)); @@ -134,7 +132,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct */ hash_num = 0; hash_num_alt = 0; - for (i = 0; i < numEdge_src; i++, hash_num_alt++) { + for (i = 0; i < edge_src_num; i++, hash_num_alt++) { MEdge *me = medge_src + i; if (BLI_ghash_haskey(vertHash, POINTER_FROM_INT(me->v1)) && @@ -146,12 +144,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct } BLI_assert(hash_num == BLI_ghash_len(edgeHash)); } - else if (numEdges_dst) { + else if (edges_dst_num) { MEdge *medge, *me; uintptr_t hash_num; if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) { - BLI_array_randomize(edgeMap, sizeof(*edgeMap), numEdge_src, bmd->seed); + BLI_array_randomize(edgeMap, sizeof(*edgeMap), edge_src_num, bmd->seed); } /* get the set of all vert indices that will be in the final mesh, @@ -160,7 +158,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct medge = medge_src; hash_num = 0; BLI_assert(hash_num == BLI_ghash_len(vertHash)); - for (i = 0; i < numEdges_dst; i++) { + for (i = 0; i < edges_dst_num; i++) { void **val_p; me = medge + edgeMap[i]; @@ -176,7 +174,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct BLI_assert(hash_num == BLI_ghash_len(vertHash)); /* get the set of edges that will be in the new mesh */ - for (i = 0; i < numEdges_dst; i++) { + for (i = 0; i < edges_dst_num; i++) { j = BLI_ghash_len(edgeHash); BLI_ghash_insert(edgeHash, POINTER_FROM_INT(j), POINTER_FROM_INT(edgeMap[i])); @@ -184,23 +182,23 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct } } else { - int numVerts = numVert_src * frac; + int verts_num = vert_src_num * frac; if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) { - BLI_array_randomize(vertMap, sizeof(*vertMap), numVert_src, bmd->seed); + BLI_array_randomize(vertMap, sizeof(*vertMap), vert_src_num, bmd->seed); } /* get the set of all vert indices that will be in the final mesh, * mapped to the new indices */ - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { BLI_ghash_insert(vertHash, POINTER_FROM_INT(vertMap[i]), POINTER_FROM_INT(i)); } } /* now we know the number of verts, edges and faces, we can create the mesh. */ result = BKE_mesh_new_nomain_from_template( - mesh, BLI_ghash_len(vertHash), BLI_ghash_len(edgeHash), 0, numLoops_dst, numFaces_dst); + mesh, BLI_ghash_len(vertHash), BLI_ghash_len(edgeHash), 0, loops_dst_num, faces_dst_num); /* copy the vertices across */ GHASH_ITER (gh_iter, vertHash) { @@ -237,7 +235,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct /* copy the faces across, remapping indices */ k = 0; - for (i = 0; i < numFaces_dst; i++) { + for (i = 0; i < faces_dst_num; i++) { MPoly *source; MPoly *dest; diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c index fb395631451..3916551bc90 100644 --- a/source/blender/modifiers/intern/MOD_cast.c +++ b/source/blender/modifiers/intern/MOD_cast.c @@ -96,7 +96,7 @@ static void sphere_do(CastModifierData *cmd, Object *ob, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { MDeformVert *dvert = NULL; const bool invert_vgroup = (cmd->flag & MOD_CAST_INVERT_VGROUP) != 0; @@ -159,17 +159,17 @@ static void sphere_do(CastModifierData *cmd, } if (len <= 0) { - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { len += len_v3v3(center, vertexCos[i]); } - len /= numVerts; + len /= verts_num; if (len == 0.0f) { len = 10.0f; } } - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { float tmp_co[3]; copy_v3_v3(tmp_co, vertexCos[i]); @@ -237,7 +237,7 @@ static void cuboid_do(CastModifierData *cmd, Object *ob, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { MDeformVert *dvert = NULL; int defgrp_index; @@ -312,13 +312,13 @@ static void cuboid_do(CastModifierData *cmd, /* let the center of the ctrl_ob be part of the bound box: */ minmax_v3v3_v3(min, max, center); - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { sub_v3_v3v3(vec, vertexCos[i], center); minmax_v3v3_v3(min, max, vec); } } else { - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { minmax_v3v3_v3(min, max, vertexCos[i]); } } @@ -347,7 +347,7 @@ static void cuboid_do(CastModifierData *cmd, bb[4][2] = bb[5][2] = bb[6][2] = bb[7][2] = max[2]; /* ready to apply the effect, one vertex at a time */ - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { int octant, coord; float d[3], dmax, apex[3], fbb; float tmp_co[3]; @@ -460,21 +460,21 @@ static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { CastModifierData *cmd = (CastModifierData *)md; Mesh *mesh_src = NULL; if (ctx->object->type == OB_MESH && cmd->defgrp_name[0] != '\0') { /* mesh_src is only needed for vgroups. */ - mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false); } if (cmd->type == MOD_CAST_TYPE_CUBOID) { - cuboid_do(cmd, ctx, ctx->object, mesh_src, vertexCos, numVerts); + cuboid_do(cmd, ctx, ctx->object, mesh_src, vertexCos, verts_num); } else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */ - sphere_do(cmd, ctx, ctx->object, mesh_src, vertexCos, numVerts); + sphere_do(cmd, ctx, ctx->object, mesh_src, vertexCos, verts_num); } if (!ELEM(mesh_src, NULL, mesh)) { @@ -487,17 +487,18 @@ static void deformVertsEM(ModifierData *md, struct BMEditMesh *editData, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { CastModifierData *cmd = (CastModifierData *)md; Mesh *mesh_src = NULL; if (cmd->defgrp_name[0] != '\0') { - mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get( + ctx->object, editData, mesh, NULL, verts_num, false, false); } if (mesh && mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA) { - BLI_assert(mesh->totvert == numVerts); + BLI_assert(mesh->totvert == verts_num); } /* TODO(Campbell): use edit-mode data only (remove this line). */ @@ -506,10 +507,10 @@ static void deformVertsEM(ModifierData *md, } if (cmd->type == MOD_CAST_TYPE_CUBOID) { - cuboid_do(cmd, ctx, ctx->object, mesh_src, vertexCos, numVerts); + cuboid_do(cmd, ctx, ctx->object, mesh_src, vertexCos, verts_num); } else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */ - sphere_do(cmd, ctx, ctx->object, mesh_src, vertexCos, numVerts); + sphere_do(cmd, ctx, ctx->object, mesh_src, vertexCos, verts_num); } if (!ELEM(mesh_src, NULL, mesh)) { diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index 4bc79a9dd45..185b05b4cf9 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -78,7 +78,7 @@ static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { Mesh *mesh_src; ClothModifierData *clmd = (ClothModifierData *)md; @@ -94,7 +94,7 @@ static void deformVerts(ModifierData *md, } if (mesh == NULL) { - mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, NULL, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, NULL, NULL, verts_num, false, false); } else { /* Not possible to use get_mesh() in this case as we'll modify its vertices @@ -118,7 +118,7 @@ static void deformVerts(ModifierData *md, &mesh_src->vdata, CD_CLOTH_ORCO, CD_CALLOC, NULL, mesh_src->totvert); } - memcpy(layerorco, kb->data, sizeof(float[3]) * numVerts); + memcpy(layerorco, kb->data, sizeof(float[3]) * verts_num); } } @@ -201,9 +201,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla tclmd->solver_result = NULL; } -static bool dependsOnTime(struct Scene *UNUSED(scene), - ModifierData *UNUSED(md), - const int UNUSED(dag_eval_mode)) +static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md)) { return true; } diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c index 33a5934d2b0..1cb308bb2a0 100644 --- a/source/blender/modifiers/intern/MOD_collision.c +++ b/source/blender/modifiers/intern/MOD_collision.c @@ -80,9 +80,7 @@ static void freeData(ModifierData *md) } } -static bool dependsOnTime(struct Scene *UNUSED(scene), - ModifierData *UNUSED(md), - const int UNUSED(dag_eval_mode)) +static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md)) { return true; } @@ -91,7 +89,7 @@ static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { CollisionModifierData *collmd = (CollisionModifierData *)md; Mesh *mesh_src; @@ -109,7 +107,7 @@ static void deformVerts(ModifierData *md, } if (mesh == NULL) { - mesh_src = MOD_deform_mesh_eval_get(ob, NULL, NULL, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get(ob, NULL, NULL, NULL, verts_num, false, false); } else { /* Not possible to use get_mesh() in this case as we'll modify its vertices @@ -268,9 +266,9 @@ static void blendRead(BlendDataReader *UNUSED(reader), ModifierData *md) collmd->xnew = newdataadr(fd, collmd->xnew); collmd->mfaces = newdataadr(fd, collmd->mfaces); - collmd->current_x = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_x"); - collmd->current_xnew = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_xnew"); - collmd->current_v = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_v"); + collmd->current_x = MEM_calloc_arrayN(collmd->mvert_num, sizeof(MVert), "current_x"); + collmd->current_xnew = MEM_calloc_arrayN(collmd->mvert_num, sizeof(MVert), "current_xnew"); + collmd->current_v = MEM_calloc_arrayN(collmd->mvert_num, sizeof(MVert), "current_v"); #endif collmd->x = NULL; diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c index b61419eb663..52162eaacc5 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.c +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c @@ -111,13 +111,13 @@ static void requiredDataMask(Object *UNUSED(ob), /* check individual weights for changes and cache values */ static void mesh_get_weights(MDeformVert *dvert, const int defgrp_index, - const uint numVerts, + const uint verts_num, const bool use_invert_vgroup, float *smooth_weights) { uint i; - for (i = 0; i < numVerts; i++, dvert++) { + for (i = 0; i < verts_num; i++, dvert++) { const float w = BKE_defvert_find_weight(dvert, defgrp_index); if (use_invert_vgroup == false) { @@ -170,25 +170,25 @@ static void mesh_get_boundaries(Mesh *mesh, float *smooth_weights) static void smooth_iter__simple(CorrectiveSmoothModifierData *csmd, Mesh *mesh, float (*vertexCos)[3], - uint numVerts, + uint verts_num, const float *smooth_weights, uint iterations) { const float lambda = csmd->lambda; uint i; - const uint numEdges = (uint)mesh->totedge; + const uint edges_num = (uint)mesh->totedge; const MEdge *edges = mesh->medge; float *vertex_edge_count_div; struct SmoothingData_Simple { float delta[3]; - } *smooth_data = MEM_calloc_arrayN(numVerts, sizeof(*smooth_data), __func__); + } *smooth_data = MEM_calloc_arrayN(verts_num, sizeof(*smooth_data), __func__); - vertex_edge_count_div = MEM_calloc_arrayN(numVerts, sizeof(float), __func__); + vertex_edge_count_div = MEM_calloc_arrayN(verts_num, sizeof(float), __func__); /* calculate as floats to avoid int->float conversion in #smooth_iter */ - for (i = 0; i < numEdges; i++) { + for (i = 0; i < edges_num; i++) { vertex_edge_count_div[edges[i].v1] += 1.0f; vertex_edge_count_div[edges[i].v2] += 1.0f; } @@ -196,14 +196,14 @@ static void smooth_iter__simple(CorrectiveSmoothModifierData *csmd, /* a little confusing, but we can include 'lambda' and smoothing weight * here to avoid multiplying for every iteration */ if (smooth_weights == NULL) { - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { vertex_edge_count_div[i] = lambda * (vertex_edge_count_div[i] ? (1.0f / vertex_edge_count_div[i]) : 1.0f); } } else { - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { vertex_edge_count_div[i] = smooth_weights[i] * lambda * (vertex_edge_count_div[i] ? (1.0f / vertex_edge_count_div[i]) : 1.0f); @@ -214,7 +214,7 @@ static void smooth_iter__simple(CorrectiveSmoothModifierData *csmd, /* Main Smoothing Loop */ while (iterations--) { - for (i = 0; i < numEdges; i++) { + for (i = 0; i < edges_num; i++) { struct SmoothingData_Simple *sd_v1; struct SmoothingData_Simple *sd_v2; float edge_dir[3]; @@ -228,7 +228,7 @@ static void smooth_iter__simple(CorrectiveSmoothModifierData *csmd, sub_v3_v3(sd_v2->delta, edge_dir); } - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { struct SmoothingData_Simple *sd = &smooth_data[i]; madd_v3_v3fl(vertexCos[i], sd->delta, vertex_edge_count_div[i]); /* zero for the next iteration (saves memset on entire array) */ @@ -246,12 +246,12 @@ static void smooth_iter__simple(CorrectiveSmoothModifierData *csmd, static void smooth_iter__length_weight(CorrectiveSmoothModifierData *csmd, Mesh *mesh, float (*vertexCos)[3], - uint numVerts, + uint verts_num, const float *smooth_weights, uint iterations) { const float eps = FLT_EPSILON * 10.0f; - const uint numEdges = (uint)mesh->totedge; + const uint edges_num = (uint)mesh->totedge; /* NOTE: the way this smoothing method works, its approx half as strong as the simple-smooth, * and 2.0 rarely spikes, double the value for consistent behavior. */ const float lambda = csmd->lambda * 2.0f; @@ -262,11 +262,11 @@ static void smooth_iter__length_weight(CorrectiveSmoothModifierData *csmd, struct SmoothingData_Weighted { float delta[3]; float edge_length_sum; - } *smooth_data = MEM_calloc_arrayN(numVerts, sizeof(*smooth_data), __func__); + } *smooth_data = MEM_calloc_arrayN(verts_num, sizeof(*smooth_data), __func__); /* calculate as floats to avoid int->float conversion in #smooth_iter */ - vertex_edge_count = MEM_calloc_arrayN(numVerts, sizeof(float), __func__); - for (i = 0; i < numEdges; i++) { + vertex_edge_count = MEM_calloc_arrayN(verts_num, sizeof(float), __func__); + for (i = 0; i < edges_num; i++) { vertex_edge_count[edges[i].v1] += 1.0f; vertex_edge_count[edges[i].v2] += 1.0f; } @@ -275,7 +275,7 @@ static void smooth_iter__length_weight(CorrectiveSmoothModifierData *csmd, /* Main Smoothing Loop */ while (iterations--) { - for (i = 0; i < numEdges; i++) { + for (i = 0; i < edges_num; i++) { struct SmoothingData_Weighted *sd_v1; struct SmoothingData_Weighted *sd_v2; float edge_dir[3]; @@ -299,7 +299,7 @@ static void smooth_iter__length_weight(CorrectiveSmoothModifierData *csmd, if (smooth_weights == NULL) { /* fast-path */ - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { struct SmoothingData_Weighted *sd = &smooth_data[i]; /* Divide by sum of all neighbor distances (weighted) and amount of neighbors, * (mean average). */ @@ -320,7 +320,7 @@ static void smooth_iter__length_weight(CorrectiveSmoothModifierData *csmd, } } else { - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { struct SmoothingData_Weighted *sd = &smooth_data[i]; const float div = sd->edge_length_sum * vertex_edge_count[i]; if (div > eps) { @@ -340,18 +340,18 @@ static void smooth_iter__length_weight(CorrectiveSmoothModifierData *csmd, static void smooth_iter(CorrectiveSmoothModifierData *csmd, Mesh *mesh, float (*vertexCos)[3], - uint numVerts, + uint verts_num, const float *smooth_weights, uint iterations) { switch (csmd->smooth_type) { case MOD_CORRECTIVESMOOTH_SMOOTH_LENGTH_WEIGHT: - smooth_iter__length_weight(csmd, mesh, vertexCos, numVerts, smooth_weights, iterations); + smooth_iter__length_weight(csmd, mesh, vertexCos, verts_num, smooth_weights, iterations); break; /* case MOD_CORRECTIVESMOOTH_SMOOTH_SIMPLE: */ default: - smooth_iter__simple(csmd, mesh, vertexCos, numVerts, smooth_weights, iterations); + smooth_iter__simple(csmd, mesh, vertexCos, verts_num, smooth_weights, iterations); break; } } @@ -361,23 +361,23 @@ static void smooth_verts(CorrectiveSmoothModifierData *csmd, MDeformVert *dvert, const int defgrp_index, float (*vertexCos)[3], - uint numVerts) + uint verts_num) { float *smooth_weights = NULL; if (dvert || (csmd->flag & MOD_CORRECTIVESMOOTH_PIN_BOUNDARY)) { - smooth_weights = MEM_malloc_arrayN(numVerts, sizeof(float), __func__); + smooth_weights = MEM_malloc_arrayN(verts_num, sizeof(float), __func__); if (dvert) { mesh_get_weights(dvert, defgrp_index, - numVerts, + verts_num, (csmd->flag & MOD_CORRECTIVESMOOTH_INVERT_VGROUP) != 0, smooth_weights); } else { - copy_vn_fl(smooth_weights, (int)numVerts, 1.0f); + copy_vn_fl(smooth_weights, (int)verts_num, 1.0f); } if (csmd->flag & MOD_CORRECTIVESMOOTH_PIN_BOUNDARY) { @@ -385,7 +385,7 @@ static void smooth_verts(CorrectiveSmoothModifierData *csmd, } } - smooth_iter(csmd, mesh, vertexCos, numVerts, smooth_weights, (uint)csmd->repeat); + smooth_iter(csmd, mesh, vertexCos, verts_num, smooth_weights, (uint)csmd->repeat); if (smooth_weights) { MEM_freeN(smooth_weights); @@ -522,29 +522,29 @@ static void calc_deltas(CorrectiveSmoothModifierData *csmd, MDeformVert *dvert, const int defgrp_index, const float (*rest_coords)[3], - uint numVerts) + uint verts_num) { float(*smooth_vertex_coords)[3] = MEM_dupallocN(rest_coords); float(*tangent_spaces)[3][3]; uint i; - tangent_spaces = MEM_calloc_arrayN(numVerts, sizeof(float[3][3]), __func__); + tangent_spaces = MEM_calloc_arrayN(verts_num, sizeof(float[3][3]), __func__); - if (csmd->delta_cache.totverts != numVerts) { + if (csmd->delta_cache.totverts != verts_num) { MEM_SAFE_FREE(csmd->delta_cache.deltas); } /* allocate deltas if they have not yet been allocated, otherwise we will just write over them */ if (!csmd->delta_cache.deltas) { - csmd->delta_cache.totverts = numVerts; - csmd->delta_cache.deltas = MEM_malloc_arrayN(numVerts, sizeof(float[3]), __func__); + csmd->delta_cache.totverts = verts_num; + csmd->delta_cache.deltas = MEM_malloc_arrayN(verts_num, sizeof(float[3]), __func__); } - smooth_verts(csmd, mesh, dvert, defgrp_index, smooth_vertex_coords, numVerts); + smooth_verts(csmd, mesh, dvert, defgrp_index, smooth_vertex_coords, verts_num); calc_tangent_spaces(mesh, smooth_vertex_coords, tangent_spaces); - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { float imat[3][3], delta[3]; #ifdef USE_TANGENT_CALC_INLINE @@ -567,7 +567,7 @@ static void correctivesmooth_modifier_do(ModifierData *md, Object *ob, Mesh *mesh, float (*vertexCos)[3], - uint numVerts, + uint verts_num, struct BMEditMesh *em) { CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md; @@ -591,7 +591,7 @@ static void correctivesmooth_modifier_do(ModifierData *md, if (DEG_is_active(depsgraph)) { BLI_assert(csmd->bind_coords == NULL); csmd->bind_coords = MEM_dupallocN(vertexCos); - csmd->bind_coords_num = numVerts; + csmd->bind_coords_num = verts_num; BLI_assert(csmd->bind_coords != NULL); /* Copy bound data to the original modifier. */ CorrectiveSmoothModifierData *csmd_orig = (CorrectiveSmoothModifierData *) @@ -605,7 +605,7 @@ static void correctivesmooth_modifier_do(ModifierData *md, } if (UNLIKELY(use_only_smooth)) { - smooth_verts(csmd, mesh, dvert, defgrp_index, vertexCos, numVerts); + smooth_verts(csmd, mesh, dvert, defgrp_index, vertexCos, verts_num); return; } @@ -616,9 +616,9 @@ static void correctivesmooth_modifier_do(ModifierData *md, /* If the number of verts has changed, the bind is invalid, so we do nothing */ if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) { - if (csmd->bind_coords_num != numVerts) { + if (csmd->bind_coords_num != verts_num) { BKE_modifier_set_error( - ob, md, "Bind vertex count mismatch: %u to %u", csmd->bind_coords_num, numVerts); + ob, md, "Bind vertex count mismatch: %u to %u", csmd->bind_coords_num, verts_num); goto error; } } @@ -631,16 +631,16 @@ static void correctivesmooth_modifier_do(ModifierData *md, else { uint me_numVerts = (uint)((em) ? em->bm->totvert : ((Mesh *)ob->data)->totvert); - if (me_numVerts != numVerts) { + if (me_numVerts != verts_num) { BKE_modifier_set_error( - ob, md, "Original vertex count mismatch: %u to %u", me_numVerts, numVerts); + ob, md, "Original vertex count mismatch: %u to %u", me_numVerts, verts_num); goto error; } } } /* check to see if our deltas are still valid */ - if (!csmd->delta_cache.deltas || (csmd->delta_cache.totverts != numVerts) || + if (!csmd->delta_cache.deltas || (csmd->delta_cache.totverts != verts_num) || force_delta_cache_update) { const float(*rest_coords)[3]; bool is_rest_coords_alloc = false; @@ -649,7 +649,7 @@ static void correctivesmooth_modifier_do(ModifierData *md, if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) { /* caller needs to do sanity check here */ - csmd->bind_coords_num = numVerts; + csmd->bind_coords_num = verts_num; rest_coords = csmd->bind_coords; } else { @@ -657,7 +657,7 @@ static void correctivesmooth_modifier_do(ModifierData *md, rest_coords = em ? BKE_editmesh_vert_coords_alloc_orco(em, &me_numVerts) : BKE_mesh_vert_coords_alloc(ob->data, &me_numVerts); - BLI_assert((uint)me_numVerts == numVerts); + BLI_assert((uint)me_numVerts == verts_num); is_rest_coords_alloc = true; } @@ -665,7 +665,7 @@ static void correctivesmooth_modifier_do(ModifierData *md, TIMEIT_START(corrective_smooth_deltas); #endif - calc_deltas(csmd, mesh, dvert, defgrp_index, rest_coords, numVerts); + calc_deltas(csmd, mesh, dvert, defgrp_index, rest_coords, verts_num); #ifdef DEBUG_TIME TIMEIT_END(corrective_smooth_deltas); @@ -677,7 +677,7 @@ static void correctivesmooth_modifier_do(ModifierData *md, if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) { /* this could be a check, but at this point it _must_ be valid */ - BLI_assert(csmd->bind_coords_num == numVerts && csmd->delta_cache.deltas); + BLI_assert(csmd->bind_coords_num == verts_num && csmd->delta_cache.deltas); } #ifdef DEBUG_TIME @@ -685,7 +685,7 @@ static void correctivesmooth_modifier_do(ModifierData *md, #endif /* do the actual delta mush */ - smooth_verts(csmd, mesh, dvert, defgrp_index, vertexCos, numVerts); + smooth_verts(csmd, mesh, dvert, defgrp_index, vertexCos, verts_num); { uint i; @@ -693,11 +693,11 @@ static void correctivesmooth_modifier_do(ModifierData *md, float(*tangent_spaces)[3][3]; const float scale = csmd->scale; /* calloc, since values are accumulated */ - tangent_spaces = MEM_calloc_arrayN(numVerts, sizeof(float[3][3]), __func__); + tangent_spaces = MEM_calloc_arrayN(verts_num, sizeof(float[3][3]), __func__); calc_tangent_spaces(mesh, vertexCos, tangent_spaces); - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { float delta[3]; #ifdef USE_TANGENT_CALC_INLINE @@ -727,12 +727,13 @@ static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { - Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false); + Mesh *mesh_src = MOD_deform_mesh_eval_get( + ctx->object, NULL, mesh, NULL, verts_num, false, false); correctivesmooth_modifier_do( - md, ctx->depsgraph, ctx->object, mesh_src, vertexCos, (uint)numVerts, NULL); + md, ctx->depsgraph, ctx->object, mesh_src, vertexCos, (uint)verts_num, NULL); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); @@ -744,10 +745,10 @@ static void deformVertsEM(ModifierData *md, struct BMEditMesh *editData, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { Mesh *mesh_src = MOD_deform_mesh_eval_get( - ctx->object, editData, mesh, NULL, numVerts, false, false); + ctx->object, editData, mesh, NULL, verts_num, false, false); /* TODO(Campbell): use edit-mode data only (remove this line). */ if (mesh_src != NULL) { @@ -755,7 +756,7 @@ static void deformVertsEM(ModifierData *md, } correctivesmooth_modifier_do( - md, ctx->depsgraph, ctx->object, mesh_src, vertexCos, (uint)numVerts, editData); + md, ctx->depsgraph, ctx->object, mesh_src, vertexCos, (uint)verts_num, editData); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c index 5b22b933823..a82b999f4dc 100644 --- a/source/blender/modifiers/intern/MOD_curve.c +++ b/source/blender/modifiers/intern/MOD_curve.c @@ -104,14 +104,14 @@ static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { CurveModifierData *cmd = (CurveModifierData *)md; Mesh *mesh_src = NULL; if (ctx->object->type == OB_MESH && cmd->name[0] != '\0') { /* mesh_src is only needed for vgroups. */ - mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false); } struct MDeformVert *dvert = NULL; @@ -124,7 +124,7 @@ static void deformVerts(ModifierData *md, BKE_curve_deform_coords(cmd->object, ctx->object, vertexCos, - numVerts, + verts_num, dvert, defgrp_index, cmd->flag, @@ -140,10 +140,10 @@ static void deformVertsEM(ModifierData *md, BMEditMesh *em, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { if (mesh != NULL) { - deformVerts(md, ctx, mesh, vertexCos, numVerts); + deformVerts(md, ctx, mesh, vertexCos, verts_num); return; } @@ -162,7 +162,7 @@ static void deformVertsEM(ModifierData *md, BKE_curve_deform_coords_with_editmesh(cmd->object, ctx->object, vertexCos, - numVerts, + verts_num, defgrp_index, cmd->flag, cmd->defaxis - 1, @@ -172,7 +172,7 @@ static void deformVertsEM(ModifierData *md, BKE_curve_deform_coords(cmd->object, ctx->object, vertexCos, - numVerts, + verts_num, NULL, defgrp_index, cmd->flag, diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index 2f35ffb3e18..7ad7d6eef3d 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -80,9 +80,7 @@ static void requiredDataMask(Object *UNUSED(ob), } } -static bool dependsOnTime(struct Scene *UNUSED(scene), - ModifierData *md, - const int UNUSED(dag_eval_mode)) +static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md) { DisplaceModifierData *dmd = (DisplaceModifierData *)md; @@ -269,7 +267,7 @@ static void displaceModifier_do(DisplaceModifierData *dmd, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - const int numVerts) + const int verts_num) { Object *ob = ctx->object; MVert *mvert; @@ -299,7 +297,7 @@ static void displaceModifier_do(DisplaceModifierData *dmd, Tex *tex_target = dmd->texture; if (tex_target != NULL) { - tex_co = MEM_calloc_arrayN((size_t)numVerts, sizeof(*tex_co), "displaceModifier_do tex_co"); + tex_co = MEM_calloc_arrayN((size_t)verts_num, sizeof(*tex_co), "displaceModifier_do tex_co"); MOD_get_texture_coords((MappingInfoModifierData *)dmd, ctx, ob, mesh, vertexCos, tex_co); MOD_init_texture((MappingInfoModifierData *)dmd, ctx); @@ -319,9 +317,9 @@ static void displaceModifier_do(DisplaceModifierData *dmd, } clnors = CustomData_get_layer(ldata, CD_NORMAL); - vert_clnors = MEM_malloc_arrayN(numVerts, sizeof(*vert_clnors), __func__); + vert_clnors = MEM_malloc_arrayN(verts_num, sizeof(*vert_clnors), __func__); BKE_mesh_normals_loop_to_vertex( - numVerts, mesh->mloop, mesh->totloop, (const float(*)[3])clnors, vert_clnors); + verts_num, mesh->mloop, mesh->totloop, (const float(*)[3])clnors, vert_clnors); } else { direction = MOD_DISP_DIR_NOR; @@ -355,8 +353,8 @@ static void displaceModifier_do(DisplaceModifierData *dmd, } TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.use_threading = (numVerts > 512); - BLI_task_parallel_range(0, numVerts, &data, displaceModifier_do_task, &settings); + settings.use_threading = (verts_num > 512); + BLI_task_parallel_range(0, verts_num, &data, displaceModifier_do_task, &settings); if (data.pool != NULL) { BKE_image_pool_free(data.pool); @@ -375,11 +373,12 @@ static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { - Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false); + Mesh *mesh_src = MOD_deform_mesh_eval_get( + ctx->object, NULL, mesh, NULL, verts_num, false, false); - displaceModifier_do((DisplaceModifierData *)md, ctx, mesh_src, vertexCos, numVerts); + displaceModifier_do((DisplaceModifierData *)md, ctx, mesh_src, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); @@ -391,17 +390,17 @@ static void deformVertsEM(ModifierData *md, struct BMEditMesh *editData, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { Mesh *mesh_src = MOD_deform_mesh_eval_get( - ctx->object, editData, mesh, NULL, numVerts, false, false); + ctx->object, editData, mesh, NULL, verts_num, false, false); /* TODO(Campbell): use edit-mode data only (remove this line). */ if (mesh_src != NULL) { BKE_mesh_wrapper_ensure_mdata(mesh_src); } - displaceModifier_do((DisplaceModifierData *)md, ctx, mesh_src, vertexCos, numVerts); + displaceModifier_do((DisplaceModifierData *)md, ctx, mesh_src, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c index 64f603b99a9..f8cf80b673c 100644 --- a/source/blender/modifiers/intern/MOD_dynamicpaint.c +++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c @@ -142,9 +142,7 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte } } -static bool dependsOnTime(struct Scene *UNUSED(scene), - ModifierData *UNUSED(md), - const int UNUSED(dag_eval_mode)) +static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md)) { return true; } diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index 33b090b9577..87ff648f13d 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -71,9 +71,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla temd->facepa = NULL; } -static bool dependsOnTime(struct Scene *UNUSED(scene), - ModifierData *UNUSED(md), - const int UNUSED(dag_eval_mode)) +static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md)) { return true; } @@ -279,12 +277,12 @@ static void remap_faces_3_6_9_12(Mesh *mesh, } static void remap_uvs_3_6_9_12( - Mesh *mesh, Mesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3) + Mesh *mesh, Mesh *split, int layers_num, int i, int cur, int c0, int c1, int c2, int c3) { MTFace *mf, *df1, *df2, *df3; int l; - for (l = 0; l < numlayer; l++) { + for (l = 0; l < layers_num; l++) { mf = CustomData_get_layer_n(&split->fdata, CD_MTFACE, l); df1 = mf + cur; df2 = df1 + 1; @@ -339,12 +337,12 @@ static void remap_faces_5_10(Mesh *mesh, } static void remap_uvs_5_10( - Mesh *mesh, Mesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3) + Mesh *mesh, Mesh *split, int layers_num, int i, int cur, int c0, int c1, int c2, int c3) { MTFace *mf, *df1, *df2; int l; - for (l = 0; l < numlayer; l++) { + for (l = 0; l < layers_num; l++) { mf = CustomData_get_layer_n(&split->fdata, CD_MTFACE, l); df1 = mf + cur; df2 = df1 + 1; @@ -411,12 +409,12 @@ static void remap_faces_15(Mesh *mesh, } static void remap_uvs_15( - Mesh *mesh, Mesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3) + Mesh *mesh, Mesh *split, int layers_num, int i, int cur, int c0, int c1, int c2, int c3) { MTFace *mf, *df1, *df2, *df3, *df4; int l; - for (l = 0; l < numlayer; l++) { + for (l = 0; l < layers_num; l++) { mf = CustomData_get_layer_n(&split->fdata, CD_MTFACE, l); df1 = mf + cur; df2 = df1 + 1; @@ -487,12 +485,12 @@ static void remap_faces_7_11_13_14(Mesh *mesh, } static void remap_uvs_7_11_13_14( - Mesh *mesh, Mesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3) + Mesh *mesh, Mesh *split, int layers_num, int i, int cur, int c0, int c1, int c2, int c3) { MTFace *mf, *df1, *df2, *df3; int l; - for (l = 0; l < numlayer; l++) { + for (l = 0; l < layers_num; l++) { mf = CustomData_get_layer_n(&split->fdata, CD_MTFACE, l); df1 = mf + cur; df2 = df1 + 1; @@ -547,12 +545,12 @@ static void remap_faces_19_21_22(Mesh *mesh, } static void remap_uvs_19_21_22( - Mesh *mesh, Mesh *split, int numlayer, int i, int cur, int c0, int c1, int c2) + Mesh *mesh, Mesh *split, int layers_num, int i, int cur, int c0, int c1, int c2) { MTFace *mf, *df1, *df2; int l; - for (l = 0; l < numlayer; l++) { + for (l = 0; l < layers_num; l++) { mf = CustomData_get_layer_n(&split->fdata, CD_MTFACE, l); df1 = mf + cur; df2 = df1 + 1; @@ -609,12 +607,12 @@ static void remap_faces_23(Mesh *mesh, } static void remap_uvs_23( - Mesh *mesh, Mesh *split, int numlayer, int i, int cur, int c0, int c1, int c2) + Mesh *mesh, Mesh *split, int layers_num, int i, int cur, int c0, int c1, int c2) { MTFace *mf, *df1, *df2; int l; - for (l = 0; l < numlayer; l++) { + for (l = 0; l < layers_num; l++) { mf = CustomData_get_layer_n(&split->fdata, CD_MTFACE, l); df1 = mf + cur; df2 = df1 + 1; @@ -653,7 +651,7 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) int *fs, totesplit = 0, totfsplit = 0, curdupface = 0; int i, v1, v2, v3, v4, esplit, v[4] = {0, 0, 0, 0}, /* To quite gcc barking... */ uv[4] = {0, 0, 0, 0}; /* To quite gcc barking... */ - int numlayer; + int layers_num; uint ed_v1, ed_v2; edgehash = BLI_edgehash_new(__func__); @@ -728,7 +726,7 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) split_m = BKE_mesh_new_nomain_from_template(mesh, totesplit, 0, totface + totfsplit, 0, 0); - numlayer = CustomData_number_of_layers(&split_m->fdata, CD_MTFACE); + layers_num = CustomData_number_of_layers(&split_m->fdata, CD_MTFACE); /* copy new faces & verts (is it really this painful with custom data??) */ for (i = 0; i < totvert; i++) { @@ -814,23 +812,23 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) case 12: remap_faces_3_6_9_12( mesh, split_m, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]); - if (numlayer) { - remap_uvs_3_6_9_12(mesh, split_m, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]); + if (layers_num) { + remap_uvs_3_6_9_12(mesh, split_m, layers_num, i, curdupface, uv[0], uv[1], uv[2], uv[3]); } break; case 5: case 10: remap_faces_5_10( mesh, split_m, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]); - if (numlayer) { - remap_uvs_5_10(mesh, split_m, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]); + if (layers_num) { + remap_uvs_5_10(mesh, split_m, layers_num, i, curdupface, uv[0], uv[1], uv[2], uv[3]); } break; case 15: remap_faces_15( mesh, split_m, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]); - if (numlayer) { - remap_uvs_15(mesh, split_m, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]); + if (layers_num) { + remap_uvs_15(mesh, split_m, layers_num, i, curdupface, uv[0], uv[1], uv[2], uv[3]); } break; case 7: @@ -839,8 +837,9 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) case 14: remap_faces_7_11_13_14( mesh, split_m, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]); - if (numlayer) { - remap_uvs_7_11_13_14(mesh, split_m, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]); + if (layers_num) { + remap_uvs_7_11_13_14( + mesh, split_m, layers_num, i, curdupface, uv[0], uv[1], uv[2], uv[3]); } break; case 19: @@ -848,15 +847,15 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) case 22: remap_faces_19_21_22( mesh, split_m, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2]); - if (numlayer) { - remap_uvs_19_21_22(mesh, split_m, numlayer, i, curdupface, uv[0], uv[1], uv[2]); + if (layers_num) { + remap_uvs_19_21_22(mesh, split_m, layers_num, i, curdupface, uv[0], uv[1], uv[2]); } break; case 23: remap_faces_23( mesh, split_m, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2]); - if (numlayer) { - remap_uvs_23(mesh, split_m, numlayer, i, curdupface, uv[0], uv[1], uv[2]); + if (layers_num) { + remap_uvs_23(mesh, split_m, layers_num, i, curdupface, uv[0], uv[1], uv[2]); } break; case 0: diff --git a/source/blender/modifiers/intern/MOD_fluid.c b/source/blender/modifiers/intern/MOD_fluid.c index a4c34df7ccf..562f0df510d 100644 --- a/source/blender/modifiers/intern/MOD_fluid.c +++ b/source/blender/modifiers/intern/MOD_fluid.c @@ -151,9 +151,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * #endif /* WITH_FLUID */ } -static bool dependsOnTime(struct Scene *UNUSED(scene), - ModifierData *UNUSED(md), - const int UNUSED(dag_eval_mode)) +static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md)) { return true; } diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c index 513000e3ad6..1000bbf45d6 100644 --- a/source/blender/modifiers/intern/MOD_hook.c +++ b/source/blender/modifiers/intern/MOD_hook.c @@ -152,14 +152,14 @@ struct HookData_cb { bool invert_vgroup; }; -static BLI_bitmap *hook_index_array_to_bitmap(HookModifierData *hmd, const int numVerts) +static BLI_bitmap *hook_index_array_to_bitmap(HookModifierData *hmd, const int verts_num) { - BLI_bitmap *indexar_used = BLI_BITMAP_NEW(numVerts, __func__); + BLI_bitmap *indexar_used = BLI_BITMAP_NEW(verts_num, __func__); int i; int *index_pt; - for (i = 0, index_pt = hmd->indexar; i < hmd->totindex; i++, index_pt++) { + for (i = 0, index_pt = hmd->indexar; i < hmd->indexar_num; i++, index_pt++) { const int j = *index_pt; - if (j < numVerts) { + if (j < verts_num) { BLI_BITMAP_ENABLE(indexar_used, i); } } @@ -275,7 +275,7 @@ static void deformVerts_do(HookModifierData *hmd, Mesh *mesh, BMEditMesh *em, float (*vertexCos)[3], - int numVerts) + int verts_num) { Object *ob_target = hmd->object; bPoseChannel *pchan = BKE_pose_channel_find_name(ob_target->pose, hmd->subtarget); @@ -365,15 +365,15 @@ static void deformVerts_do(HookModifierData *hmd, const int *origindex_ar; /* if mesh is present and has original index data, use it */ if (mesh && (origindex_ar = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX))) { - int numVerts_orig = numVerts; + int verts_orig_num = verts_num; if (ob->type == OB_MESH) { const Mesh *me_orig = ob->data; - numVerts_orig = me_orig->totvert; + verts_orig_num = me_orig->totvert; } - BLI_bitmap *indexar_used = hook_index_array_to_bitmap(hmd, numVerts_orig); - for (i = 0; i < numVerts; i++) { + BLI_bitmap *indexar_used = hook_index_array_to_bitmap(hmd, verts_orig_num); + for (i = 0; i < verts_num; i++) { int i_orig = origindex_ar[i]; - BLI_assert(i_orig < numVerts_orig); + BLI_assert(i_orig < verts_orig_num); if (BLI_BITMAP_TEST(indexar_used, i_orig)) { hook_co_apply(&hd, i, dvert ? &dvert[i] : NULL); } @@ -382,8 +382,8 @@ static void deformVerts_do(HookModifierData *hmd, } else { /* missing mesh or ORIGINDEX */ if ((em != NULL) && (hd.defgrp_index != -1)) { - BLI_assert(em->bm->totvert == numVerts); - BLI_bitmap *indexar_used = hook_index_array_to_bitmap(hmd, numVerts); + BLI_assert(em->bm->totvert == verts_num); + BLI_bitmap *indexar_used = hook_index_array_to_bitmap(hmd, verts_num); BMIter iter; BMVert *v; BM_ITER_MESH_INDEX (v, &iter, em->bm, BM_VERTS_OF_MESH, i) { @@ -395,9 +395,9 @@ static void deformVerts_do(HookModifierData *hmd, MEM_freeN(indexar_used); } else { - for (i = 0, index_pt = hmd->indexar; i < hmd->totindex; i++, index_pt++) { + for (i = 0, index_pt = hmd->indexar; i < hmd->indexar_num; i++, index_pt++) { const int j = *index_pt; - if (j < numVerts) { + if (j < verts_num) { hook_co_apply(&hd, j, dvert ? &dvert[j] : NULL); } } @@ -406,7 +406,7 @@ static void deformVerts_do(HookModifierData *hmd, } else if (hd.defgrp_index != -1) { /* vertex group hook */ if (em != NULL) { - BLI_assert(em->bm->totvert == numVerts); + BLI_assert(em->bm->totvert == verts_num); BMIter iter; BMVert *v; BM_ITER_MESH_INDEX (v, &iter, em->bm, BM_VERTS_OF_MESH, i) { @@ -416,7 +416,7 @@ static void deformVerts_do(HookModifierData *hmd, } else { BLI_assert(dvert != NULL); - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { hook_co_apply(&hd, i, &dvert[i]); } } @@ -427,12 +427,13 @@ static void deformVerts(struct ModifierData *md, const struct ModifierEvalContext *ctx, struct Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { HookModifierData *hmd = (HookModifierData *)md; - Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false); + Mesh *mesh_src = MOD_deform_mesh_eval_get( + ctx->object, NULL, mesh, NULL, verts_num, false, false); - deformVerts_do(hmd, ctx, ctx->object, mesh_src, NULL, vertexCos, numVerts); + deformVerts_do(hmd, ctx, ctx->object, mesh_src, NULL, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); @@ -444,11 +445,11 @@ static void deformVertsEM(struct ModifierData *md, struct BMEditMesh *editData, struct Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { HookModifierData *hmd = (HookModifierData *)md; - deformVerts_do(hmd, ctx, ctx->object, mesh, mesh ? NULL : editData, vertexCos, numVerts); + deformVerts_do(hmd, ctx, ctx->object, mesh, mesh ? NULL : editData, vertexCos, verts_num); } static void panel_draw(const bContext *UNUSED(C), Panel *panel) @@ -526,7 +527,7 @@ static void blendWrite(BlendWriter *writer, const ModifierData *md) BKE_curvemapping_blend_write(writer, hmd->curfalloff); } - BLO_write_int32_array(writer, hmd->totindex, hmd->indexar); + BLO_write_int32_array(writer, hmd->indexar_num, hmd->indexar); } static void blendRead(BlendDataReader *reader, ModifierData *md) @@ -538,7 +539,7 @@ static void blendRead(BlendDataReader *reader, ModifierData *md) BKE_curvemapping_blend_read(reader, hmd->curfalloff); } - BLO_read_int32_array(reader, hmd->totindex, &hmd->indexar); + BLO_read_int32_array(reader, hmd->indexar_num, &hmd->indexar); } ModifierTypeInfo modifierType_Hook = { diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c index d5f3902379d..239cb7f5a5a 100644 --- a/source/blender/modifiers/intern/MOD_laplaciandeform.c +++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c @@ -58,10 +58,10 @@ enum { typedef struct LaplacianSystem { bool is_matrix_computed; bool has_solution; - int total_verts; - int total_edges; - int total_tris; - int total_anchors; + int verts_num; + int edges_num; + int tris_num; + int anchors_num; int repeat; char anchor_grp_name[64]; /* Vertex Group name */ float (*co)[3]; /* Original vertex coordinates */ @@ -84,20 +84,20 @@ static LaplacianSystem *newLaplacianSystem(void) sys->is_matrix_computed = false; sys->has_solution = false; - sys->total_verts = 0; - sys->total_edges = 0; - sys->total_anchors = 0; - sys->total_tris = 0; + sys->verts_num = 0; + sys->edges_num = 0; + sys->anchors_num = 0; + sys->tris_num = 0; sys->repeat = 1; sys->anchor_grp_name[0] = '\0'; return sys; } -static LaplacianSystem *initLaplacianSystem(int totalVerts, - int totalEdges, - int totalTris, - int totalAnchors, +static LaplacianSystem *initLaplacianSystem(int verts_num, + int edges_num, + int tris_num, + int anchors_num, const char defgrpName[64], int iterations) { @@ -105,18 +105,18 @@ static LaplacianSystem *initLaplacianSystem(int totalVerts, sys->is_matrix_computed = false; sys->has_solution = false; - sys->total_verts = totalVerts; - sys->total_edges = totalEdges; - sys->total_tris = totalTris; - sys->total_anchors = totalAnchors; + sys->verts_num = verts_num; + sys->edges_num = edges_num; + sys->tris_num = tris_num; + sys->anchors_num = anchors_num; sys->repeat = iterations; BLI_strncpy(sys->anchor_grp_name, defgrpName, sizeof(sys->anchor_grp_name)); - sys->co = MEM_malloc_arrayN(totalVerts, sizeof(float[3]), "DeformCoordinates"); - sys->no = MEM_calloc_arrayN(totalVerts, sizeof(float[3]), "DeformNormals"); - sys->delta = MEM_calloc_arrayN(totalVerts, sizeof(float[3]), "DeformDeltas"); - sys->tris = MEM_malloc_arrayN(totalTris, sizeof(int[3]), "DeformFaces"); - sys->index_anchors = MEM_malloc_arrayN((totalAnchors), sizeof(int), "DeformAnchors"); - sys->unit_verts = MEM_calloc_arrayN(totalVerts, sizeof(int), "DeformUnitVerts"); + sys->co = MEM_malloc_arrayN(verts_num, sizeof(float[3]), "DeformCoordinates"); + sys->no = MEM_calloc_arrayN(verts_num, sizeof(float[3]), "DeformNormals"); + sys->delta = MEM_calloc_arrayN(verts_num, sizeof(float[3]), "DeformDeltas"); + sys->tris = MEM_malloc_arrayN(tris_num, sizeof(int[3]), "DeformFaces"); + sys->index_anchors = MEM_malloc_arrayN((anchors_num), sizeof(int), "DeformAnchors"); + sys->unit_verts = MEM_calloc_arrayN(verts_num, sizeof(int), "DeformUnitVerts"); return sys; } @@ -146,7 +146,7 @@ static void createFaceRingMap(const int mvert_tot, MeshElemMap **r_map, int **r_indices) { - int i, j, totalr = 0; + int i, j, indices_num = 0; int *indices, *index_iter; MeshElemMap *map = MEM_calloc_arrayN(mvert_tot, sizeof(MeshElemMap), "DeformRingMap"); const MLoopTri *mlt; @@ -156,10 +156,10 @@ static void createFaceRingMap(const int mvert_tot, for (j = 0; j < 3; j++) { const uint v_index = mloop[mlt->tri[j]].v; map[v_index].count++; - totalr++; + indices_num++; } } - indices = MEM_calloc_arrayN(totalr, sizeof(int), "DeformRingIndex"); + indices = MEM_calloc_arrayN(indices_num, sizeof(int), "DeformRingIndex"); index_iter = indices; for (i = 0; i < mvert_tot; i++) { map[i].indices = index_iter; @@ -184,7 +184,7 @@ static void createVertRingMap(const int mvert_tot, int **r_indices) { MeshElemMap *map = MEM_calloc_arrayN(mvert_tot, sizeof(MeshElemMap), "DeformNeighborsMap"); - int i, vid[2], totalr = 0; + int i, vid[2], indices_num = 0; int *indices, *index_iter; const MEdge *me; @@ -193,9 +193,9 @@ static void createVertRingMap(const int mvert_tot, vid[1] = me->v2; map[vid[0]].count++; map[vid[1]].count++; - totalr += 2; + indices_num += 2; } - indices = MEM_calloc_arrayN(totalr, sizeof(int), "DeformNeighborsIndex"); + indices = MEM_calloc_arrayN(indices_num, sizeof(int), "DeformNeighborsIndex"); index_iter = indices; for (i = 0; i < mvert_tot; i++) { map[i].indices = index_iter; @@ -253,7 +253,7 @@ static void initLaplacianMatrix(LaplacianSystem *sys) int i = 3, j, ti; int idv[3]; - for (ti = 0; ti < sys->total_tris; ti++) { + for (ti = 0; ti < sys->tris_num; ti++) { const uint *vidt = sys->tris[ti]; const float *co[3]; @@ -305,7 +305,7 @@ static void computeImplictRotations(LaplacianSystem *sys) float minj, mjt, qj[3], vj[3]; int i, j, ln; - for (i = 0; i < sys->total_verts; i++) { + for (i = 0; i < sys->verts_num; i++) { normalize_v3(sys->no[i]); vidn = sys->ringv_map[i].indices; ln = sys->ringv_map[i].count; @@ -329,10 +329,10 @@ static void rotateDifferentialCoordinates(LaplacianSystem *sys) float alpha, beta, gamma; float pj[3], ni[3], di[3]; float uij[3], dun[3], e2[3], pi[3], fni[3], vn[3][3]; - int i, j, num_fni, k, fi; + int i, j, fidn_num, k, fi; int *fidn; - for (i = 0; i < sys->total_verts; i++) { + for (i = 0; i < sys->verts_num; i++) { copy_v3_v3(pi, sys->co[i]); copy_v3_v3(ni, sys->no[i]); k = sys->unit_verts[i]; @@ -351,8 +351,8 @@ static void rotateDifferentialCoordinates(LaplacianSystem *sys) pi[1] = EIG_linear_solver_variable_get(sys->context, 1, i); pi[2] = EIG_linear_solver_variable_get(sys->context, 2, i); zero_v3(ni); - num_fni = sys->ringf_map[i].count; - for (fi = 0; fi < num_fni; fi++) { + fidn_num = sys->ringf_map[i].count; + for (fi = 0; fi < fidn_num; fi++) { const uint *vin; fidn = sys->ringf_map[i].indices; vin = sys->tris[fidn[fi]]; @@ -395,8 +395,8 @@ static void rotateDifferentialCoordinates(LaplacianSystem *sys) static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3]) { int vid, i, j, n, na; - n = sys->total_verts; - na = sys->total_anchors; + n = sys->verts_num; + na = sys->anchors_num; if (!sys->is_matrix_computed) { sys->context = EIG_linear_least_squares_solver_new(n + na, n, 3); @@ -447,7 +447,7 @@ static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3]) } } if (sys->has_solution) { - for (vid = 0; vid < sys->total_verts; vid++) { + for (vid = 0; vid < sys->verts_num; vid++) { vertexCos[vid][0] = EIG_linear_solver_variable_get(sys->context, 0, vid); vertexCos[vid][1] = EIG_linear_solver_variable_get(sys->context, 1, vid); vertexCos[vid][2] = EIG_linear_solver_variable_get(sys->context, 2, vid); @@ -493,7 +493,7 @@ static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3]) } } if (sys->has_solution) { - for (vid = 0; vid < sys->total_verts; vid++) { + for (vid = 0; vid < sys->verts_num; vid++) { vertexCos[vid][0] = EIG_linear_solver_variable_get(sys->context, 0, vid); vertexCos[vid][1] = EIG_linear_solver_variable_get(sys->context, 1, vid); vertexCos[vid][2] = EIG_linear_solver_variable_get(sys->context, 2, vid); @@ -520,11 +520,11 @@ static bool isValidVertexGroup(LaplacianDeformModifierData *lmd, Object *ob, Mes } static void initSystem( - LaplacianDeformModifierData *lmd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int numVerts) + LaplacianDeformModifierData *lmd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int verts_num) { int i; int defgrp_index; - int total_anchors; + int anchors_num; float wpaint; MDeformVert *dvert = NULL; MDeformVert *dv = NULL; @@ -532,18 +532,18 @@ static void initSystem( const bool invert_vgroup = (lmd->flag & MOD_LAPLACIANDEFORM_INVERT_VGROUP) != 0; if (isValidVertexGroup(lmd, ob, mesh)) { - int *index_anchors = MEM_malloc_arrayN(numVerts, sizeof(int), __func__); /* over-alloc */ + int *index_anchors = MEM_malloc_arrayN(verts_num, sizeof(int), __func__); /* over-alloc */ const MLoopTri *mlooptri; const MLoop *mloop; STACK_DECLARE(index_anchors); - STACK_INIT(index_anchors, numVerts); + STACK_INIT(index_anchors, verts_num); MOD_get_vgroup(ob, mesh, lmd->anchor_grp_name, &dvert, &defgrp_index); BLI_assert(dvert != NULL); dv = dvert; - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { wpaint = invert_vgroup ? 1.0f - BKE_defvert_find_weight(dv, defgrp_index) : BKE_defvert_find_weight(dv, defgrp_index); dv++; @@ -552,20 +552,20 @@ static void initSystem( } } - total_anchors = STACK_SIZE(index_anchors); - lmd->cache_system = initLaplacianSystem(numVerts, + anchors_num = STACK_SIZE(index_anchors); + lmd->cache_system = initLaplacianSystem(verts_num, mesh->totedge, BKE_mesh_runtime_looptri_len(mesh), - total_anchors, + anchors_num, lmd->anchor_grp_name, lmd->repeat); sys = (LaplacianSystem *)lmd->cache_system; - memcpy(sys->index_anchors, index_anchors, sizeof(int) * total_anchors); - memcpy(sys->co, vertexCos, sizeof(float[3]) * numVerts); + memcpy(sys->index_anchors, index_anchors, sizeof(int) * anchors_num); + memcpy(sys->co, vertexCos, sizeof(float[3]) * verts_num); MEM_freeN(index_anchors); - lmd->vertexco = MEM_malloc_arrayN(numVerts, sizeof(float[3]), "ModDeformCoordinates"); - memcpy(lmd->vertexco, vertexCos, sizeof(float[3]) * numVerts); - lmd->total_verts = numVerts; + lmd->vertexco = MEM_malloc_arrayN(verts_num, sizeof(float[3]), "ModDeformCoordinates"); + memcpy(lmd->vertexco, vertexCos, sizeof(float[3]) * verts_num); + lmd->verts_num = verts_num; createFaceRingMap(mesh->totvert, BKE_mesh_runtime_looptri_ensure(mesh), @@ -579,7 +579,7 @@ static void initSystem( mlooptri = BKE_mesh_runtime_looptri_ensure(mesh); mloop = mesh->mloop; - for (i = 0; i < sys->total_tris; i++) { + for (i = 0; i < sys->tris_num; i++) { sys->tris[i][0] = mloop[mlooptri[i].tri[0]].v; sys->tris[i][1] = mloop[mlooptri[i].tri[1]].v; sys->tris[i][2] = mloop[mlooptri[i].tri[2]].v; @@ -590,21 +590,21 @@ static void initSystem( static int isSystemDifferent(LaplacianDeformModifierData *lmd, Object *ob, Mesh *mesh, - int numVerts) + int verts_num) { int i; int defgrp_index; - int total_anchors = 0; + int anchors_num = 0; float wpaint; MDeformVert *dvert = NULL; MDeformVert *dv = NULL; LaplacianSystem *sys = (LaplacianSystem *)lmd->cache_system; const bool invert_vgroup = (lmd->flag & MOD_LAPLACIANDEFORM_INVERT_VGROUP) != 0; - if (sys->total_verts != numVerts) { + if (sys->verts_num != verts_num) { return LAPDEFORM_SYSTEM_CHANGE_VERTEXES; } - if (sys->total_edges != mesh->totedge) { + if (sys->edges_num != mesh->totedge) { return LAPDEFORM_SYSTEM_CHANGE_EDGES; } if (!STREQ(lmd->anchor_grp_name, sys->anchor_grp_name)) { @@ -615,15 +615,15 @@ static int isSystemDifferent(LaplacianDeformModifierData *lmd, return LAPDEFORM_SYSTEM_CHANGE_NOT_VALID_GROUP; } dv = dvert; - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { wpaint = invert_vgroup ? 1.0f - BKE_defvert_find_weight(dv, defgrp_index) : BKE_defvert_find_weight(dv, defgrp_index); dv++; if (wpaint > 0.0f) { - total_anchors++; + anchors_num++; } } - if (sys->total_anchors != total_anchors) { + if (sys->anchors_num != anchors_num) { return LAPDEFORM_SYSTEM_ONLY_CHANGE_ANCHORS; } @@ -631,7 +631,7 @@ static int isSystemDifferent(LaplacianDeformModifierData *lmd, } static void LaplacianDeformModifier_do( - LaplacianDeformModifierData *lmd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int numVerts) + LaplacianDeformModifierData *lmd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int verts_num) { float(*filevertexCos)[3]; int sysdif; @@ -643,22 +643,22 @@ static void LaplacianDeformModifier_do( deleteLaplacianSystem(sys); lmd->cache_system = NULL; } - lmd->total_verts = 0; + lmd->verts_num = 0; MEM_SAFE_FREE(lmd->vertexco); return; } if (lmd->cache_system) { - sysdif = isSystemDifferent(lmd, ob, mesh, numVerts); + sysdif = isSystemDifferent(lmd, ob, mesh, verts_num); sys = lmd->cache_system; if (sysdif) { if (ELEM(sysdif, LAPDEFORM_SYSTEM_ONLY_CHANGE_ANCHORS, LAPDEFORM_SYSTEM_ONLY_CHANGE_GROUP)) { - filevertexCos = MEM_malloc_arrayN(numVerts, sizeof(float[3]), "TempModDeformCoordinates"); - memcpy(filevertexCos, lmd->vertexco, sizeof(float[3]) * numVerts); + filevertexCos = MEM_malloc_arrayN(verts_num, sizeof(float[3]), "TempModDeformCoordinates"); + memcpy(filevertexCos, lmd->vertexco, sizeof(float[3]) * verts_num); MEM_SAFE_FREE(lmd->vertexco); - lmd->total_verts = 0; + lmd->verts_num = 0; deleteLaplacianSystem(sys); lmd->cache_system = NULL; - initSystem(lmd, ob, mesh, filevertexCos, numVerts); + initSystem(lmd, ob, mesh, filevertexCos, verts_num); sys = lmd->cache_system; /* may have been reallocated */ MEM_SAFE_FREE(filevertexCos); if (sys) { @@ -668,11 +668,11 @@ static void LaplacianDeformModifier_do( else { if (sysdif == LAPDEFORM_SYSTEM_CHANGE_VERTEXES) { BKE_modifier_set_error( - ob, &lmd->modifier, "Vertices changed from %d to %d", lmd->total_verts, numVerts); + ob, &lmd->modifier, "Vertices changed from %d to %d", lmd->verts_num, verts_num); } else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_EDGES) { BKE_modifier_set_error( - ob, &lmd->modifier, "Edges changed from %d to %d", sys->total_edges, mesh->totedge); + ob, &lmd->modifier, "Edges changed from %d to %d", sys->edges_num, mesh->totedge); } else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_NOT_VALID_GROUP) { BKE_modifier_set_error(ob, @@ -695,18 +695,18 @@ static void LaplacianDeformModifier_do( lmd->anchor_grp_name); lmd->flag &= ~MOD_LAPLACIANDEFORM_BIND; } - else if (lmd->total_verts > 0 && lmd->total_verts == numVerts) { - filevertexCos = MEM_malloc_arrayN(numVerts, sizeof(float[3]), "TempDeformCoordinates"); - memcpy(filevertexCos, lmd->vertexco, sizeof(float[3]) * numVerts); + else if (lmd->verts_num > 0 && lmd->verts_num == verts_num) { + filevertexCos = MEM_malloc_arrayN(verts_num, sizeof(float[3]), "TempDeformCoordinates"); + memcpy(filevertexCos, lmd->vertexco, sizeof(float[3]) * verts_num); MEM_SAFE_FREE(lmd->vertexco); - lmd->total_verts = 0; - initSystem(lmd, ob, mesh, filevertexCos, numVerts); + lmd->verts_num = 0; + initSystem(lmd, ob, mesh, filevertexCos, verts_num); sys = lmd->cache_system; MEM_SAFE_FREE(filevertexCos); laplacianDeformPreview(sys, vertexCos); } else { - initSystem(lmd, ob, mesh, vertexCos, numVerts); + initSystem(lmd, ob, mesh, vertexCos, verts_num); sys = lmd->cache_system; laplacianDeformPreview(sys, vertexCos); } @@ -762,12 +762,13 @@ static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { - Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false); + Mesh *mesh_src = MOD_deform_mesh_eval_get( + ctx->object, NULL, mesh, NULL, verts_num, false, false); LaplacianDeformModifier_do( - (LaplacianDeformModifierData *)md, ctx->object, mesh_src, vertexCos, numVerts); + (LaplacianDeformModifierData *)md, ctx->object, mesh_src, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); @@ -779,10 +780,10 @@ static void deformVertsEM(ModifierData *md, struct BMEditMesh *editData, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { Mesh *mesh_src = MOD_deform_mesh_eval_get( - ctx->object, editData, mesh, NULL, numVerts, false, false); + ctx->object, editData, mesh, NULL, verts_num, false, false); /* TODO(Campbell): use edit-mode data only (remove this line). */ if (mesh_src != NULL) { @@ -790,7 +791,7 @@ static void deformVertsEM(ModifierData *md, } LaplacianDeformModifier_do( - (LaplacianDeformModifierData *)md, ctx->object, mesh_src, vertexCos, numVerts); + (LaplacianDeformModifierData *)md, ctx->object, mesh_src, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); @@ -805,7 +806,7 @@ static void freeData(ModifierData *md) deleteLaplacianSystem(sys); } MEM_SAFE_FREE(lmd->vertexco); - lmd->total_verts = 0; + lmd->verts_num = 0; } static void panel_draw(const bContext *UNUSED(C), Panel *panel) @@ -846,14 +847,14 @@ static void blendWrite(BlendWriter *writer, const ModifierData *md) { LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)md; - BLO_write_float3_array(writer, lmd->total_verts, lmd->vertexco); + BLO_write_float3_array(writer, lmd->verts_num, lmd->vertexco); } static void blendRead(BlendDataReader *reader, ModifierData *md) { LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)md; - BLO_read_float3_array(reader, lmd->total_verts, &lmd->vertexco); + BLO_read_float3_array(reader, lmd->verts_num, &lmd->vertexco); lmd->cache_system = NULL; } diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c index effe2a5af90..11abe9a4d0a 100644 --- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c @@ -45,12 +45,12 @@ struct BLaplacianSystem { 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 numLoops; /* Number of edges. */ - int numPolys; /* Number of faces. */ - int numVerts; /* Number of verts. */ - short *numNeFa; /* Number of neighbors faces around vertex. */ - short *numNeEd; /* Number of neighbors Edges around vertex. */ + int edges_num; /* Number of edges. */ + int loops_num; /* Number of edges. */ + int polys_num; /* Number of faces. */ + int verts_num; /* Number of verts. */ + short *ne_fa_num; /* Number of neighbors faces around vertex. */ + short *ne_ed_num; /* Number of neighbors Edges around vertex. */ bool *zerola; /* Is zero area or length. */ /* Pointers to data. */ @@ -71,7 +71,7 @@ static bool is_disabled(const struct Scene *scene, ModifierData *md, bool useRen static float compute_volume(const float center[3], float (*vertexCos)[3], const MPoly *mpoly, - int numPolys, + int polys_num, const MLoop *mloop); static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numPolys, @@ -89,8 +89,8 @@ static void delete_laplacian_system(LaplacianSystem *sys) { MEM_SAFE_FREE(sys->eweights); MEM_SAFE_FREE(sys->fweights); - MEM_SAFE_FREE(sys->numNeEd); - MEM_SAFE_FREE(sys->numNeFa); + MEM_SAFE_FREE(sys->ne_ed_num); + MEM_SAFE_FREE(sys->ne_fa_num); MEM_SAFE_FREE(sys->ring_areas); MEM_SAFE_FREE(sys->vlengths); MEM_SAFE_FREE(sys->vweights); @@ -108,14 +108,14 @@ 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[3]) * sys->numLoops); - memset(sys->numNeEd, val, sizeof(short) * sys->numVerts); - memset(sys->numNeFa, val, sizeof(short) * sys->numVerts); - 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); + memset(sys->eweights, val, sizeof(float) * sys->edges_num); + memset(sys->fweights, val, sizeof(float[3]) * sys->loops_num); + memset(sys->ne_ed_num, val, sizeof(short) * sys->verts_num); + memset(sys->ne_fa_num, val, sizeof(short) * sys->verts_num); + memset(sys->ring_areas, val, sizeof(float) * sys->verts_num); + memset(sys->vlengths, val, sizeof(float) * sys->verts_num); + memset(sys->vweights, val, sizeof(float) * sys->verts_num); + memset(sys->zerola, val, sizeof(bool) * sys->verts_num); } static LaplacianSystem *init_laplacian_system(int a_numEdges, @@ -125,19 +125,19 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, { LaplacianSystem *sys; sys = MEM_callocN(sizeof(LaplacianSystem), "ModLaplSmoothSystem"); - sys->numEdges = a_numEdges; - sys->numPolys = a_numPolys; - sys->numLoops = a_numLoops; - sys->numVerts = a_numVerts; - - sys->eweights = MEM_calloc_arrayN(sys->numEdges, sizeof(float), __func__); - sys->fweights = MEM_calloc_arrayN(sys->numLoops, sizeof(float[3]), __func__); - sys->numNeEd = MEM_calloc_arrayN(sys->numVerts, sizeof(short), __func__); - sys->numNeFa = MEM_calloc_arrayN(sys->numVerts, sizeof(short), __func__); - 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(bool), __func__); + sys->edges_num = a_numEdges; + sys->polys_num = a_numPolys; + sys->loops_num = a_numLoops; + sys->verts_num = a_numVerts; + + sys->eweights = MEM_calloc_arrayN(sys->edges_num, sizeof(float), __func__); + sys->fweights = MEM_calloc_arrayN(sys->loops_num, sizeof(float[3]), __func__); + sys->ne_ed_num = MEM_calloc_arrayN(sys->verts_num, sizeof(short), __func__); + sys->ne_fa_num = MEM_calloc_arrayN(sys->verts_num, sizeof(short), __func__); + sys->ring_areas = MEM_calloc_arrayN(sys->verts_num, sizeof(float), __func__); + sys->vlengths = MEM_calloc_arrayN(sys->verts_num, sizeof(float), __func__); + sys->vweights = MEM_calloc_arrayN(sys->verts_num, sizeof(float), __func__); + sys->zerola = MEM_calloc_arrayN(sys->verts_num, sizeof(bool), __func__); return sys; } @@ -145,13 +145,13 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, static float compute_volume(const float center[3], float (*vertexCos)[3], const MPoly *mpoly, - int numPolys, + int polys_num, const MLoop *mloop) { int i; float vol = 0.0f; - for (i = 0; i < numPolys; i++) { + for (i = 0; i < polys_num; i++) { const MPoly *mp = &mpoly[i]; const MLoop *l_first = &mloop[mp->loopstart]; const MLoop *l_prev = l_first + 1; @@ -174,7 +174,7 @@ static void volume_preservation(LaplacianSystem *sys, float vini, float vend, sh if (vend != 0.0f) { beta = pow(vini / vend, 1.0f / 3.0f); - for (i = 0; i < sys->numVerts; i++) { + for (i = 0; i < sys->verts_num; i++) { if (flag & MOD_LAPLACIANSMOOTH_X) { sys->vertexCos[i][0] = (sys->vertexCos[i][0] - sys->vert_centroid[0]) * beta + sys->vert_centroid[0]; @@ -199,15 +199,15 @@ static void init_laplacian_matrix(LaplacianSystem *sys) int i; uint idv1, idv2; - for (i = 0; i < sys->numEdges; i++) { + for (i = 0; i < sys->edges_num; i++) { idv1 = sys->medges[i].v1; idv2 = sys->medges[i].v2; v1 = sys->vertexCos[idv1]; v2 = sys->vertexCos[idv2]; - sys->numNeEd[idv1] = sys->numNeEd[idv1] + 1; - sys->numNeEd[idv2] = sys->numNeEd[idv2] + 1; + sys->ne_ed_num[idv1] = sys->ne_ed_num[idv1] + 1; + sys->ne_ed_num[idv2] = sys->ne_ed_num[idv2] + 1; w1 = len_v3v3(v1, v2); if (w1 < sys->min_area) { sys->zerola[idv1] = true; @@ -220,7 +220,7 @@ static void init_laplacian_matrix(LaplacianSystem *sys) sys->eweights[i] = w1; } - for (i = 0; i < sys->numPolys; i++) { + for (i = 0; i < sys->polys_num; i++) { const MPoly *mp = &sys->mpoly[i]; const MLoop *l_next = &sys->mloop[mp->loopstart]; const MLoop *l_term = l_next + mp->totloop; @@ -233,7 +233,7 @@ static void init_laplacian_matrix(LaplacianSystem *sys) const float *v_next = sys->vertexCos[l_next->v]; const uint l_curr_index = l_curr - sys->mloop; - sys->numNeFa[l_curr->v] += 1; + sys->ne_fa_num[l_curr->v] += 1; areaf = area_tri_v3(v_prev, v_curr, v_next); @@ -258,11 +258,12 @@ static void init_laplacian_matrix(LaplacianSystem *sys) sys->vweights[l_prev->v] += w1 + w2; } } - for (i = 0; i < sys->numEdges; i++) { + for (i = 0; i < sys->edges_num; i++) { idv1 = sys->medges[i].v1; idv2 = sys->medges[i].v2; /* if is boundary, apply scale-dependent umbrella operator only with neighbors in boundary */ - if (sys->numNeEd[idv1] != sys->numNeFa[idv1] && sys->numNeEd[idv2] != sys->numNeFa[idv2]) { + if (sys->ne_ed_num[idv1] != sys->ne_fa_num[idv1] && + sys->ne_ed_num[idv2] != sys->ne_fa_num[idv2]) { sys->vlengths[idv1] += sys->eweights[i]; sys->vlengths[idv2] += sys->eweights[i]; } @@ -274,7 +275,7 @@ static void fill_laplacian_matrix(LaplacianSystem *sys) int i; uint idv1, idv2; - for (i = 0; i < sys->numPolys; i++) { + for (i = 0; i < sys->polys_num; i++) { const MPoly *mp = &sys->mpoly[i]; const MLoop *l_next = &sys->mloop[mp->loopstart]; const MLoop *l_term = l_next + mp->totloop; @@ -285,7 +286,8 @@ 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 vertex. */ - if (sys->numNeEd[l_curr->v] == sys->numNeFa[l_curr->v] && sys->zerola[l_curr->v] == false) { + if (sys->ne_ed_num[l_curr->v] == sys->ne_fa_num[l_curr->v] && + sys->zerola[l_curr->v] == false) { EIG_linear_solver_matrix_add(sys->context, l_curr->v, l_next->v, @@ -295,7 +297,8 @@ 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] == false) { + if (sys->ne_ed_num[l_next->v] == sys->ne_fa_num[l_next->v] && + sys->zerola[l_next->v] == false) { EIG_linear_solver_matrix_add(sys->context, l_next->v, l_curr->v, @@ -305,7 +308,8 @@ 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] == false) { + if (sys->ne_ed_num[l_prev->v] == sys->ne_fa_num[l_prev->v] && + sys->zerola[l_prev->v] == false) { EIG_linear_solver_matrix_add(sys->context, l_prev->v, l_curr->v, @@ -318,12 +322,13 @@ static void fill_laplacian_matrix(LaplacianSystem *sys) } } - for (i = 0; i < sys->numEdges; i++) { + for (i = 0; i < sys->edges_num; i++) { idv1 = sys->medges[i].v1; idv2 = sys->medges[i].v2; /* Is boundary */ - if (sys->numNeEd[idv1] != sys->numNeFa[idv1] && sys->numNeEd[idv2] != sys->numNeFa[idv2] && - sys->zerola[idv1] == false && sys->zerola[idv2] == false) { + if (sys->ne_ed_num[idv1] != sys->ne_fa_num[idv1] && + sys->ne_ed_num[idv2] != sys->ne_fa_num[idv2] && 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( @@ -340,12 +345,12 @@ static void validate_solution(LaplacianSystem *sys, short flag, float lambda, fl if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) { vini = compute_volume( - sys->vert_centroid, sys->vertexCos, sys->mpoly, sys->numPolys, sys->mloop); + sys->vert_centroid, sys->vertexCos, sys->mpoly, sys->polys_num, sys->mloop); } - for (i = 0; i < sys->numVerts; i++) { + for (i = 0; i < sys->verts_num; i++) { 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); + lam = sys->ne_ed_num[i] == sys->ne_fa_num[i] ? (lambda >= 0.0f ? 1.0f : -1.0f) : + (lambda_border >= 0.0f ? 1.0f : -1.0f); if (flag & MOD_LAPLACIANSMOOTH_X) { sys->vertexCos[i][0] += lam * ((float)EIG_linear_solver_variable_get(sys->context, 0, i) - sys->vertexCos[i][0]); @@ -362,13 +367,13 @@ static void validate_solution(LaplacianSystem *sys, short flag, float lambda, fl } if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) { vend = compute_volume( - sys->vert_centroid, sys->vertexCos, sys->mpoly, sys->numPolys, sys->mloop); + sys->vert_centroid, sys->vertexCos, sys->mpoly, sys->polys_num, sys->mloop); volume_preservation(sys, vini, vend, flag); } } static void laplaciansmoothModifier_do( - LaplacianSmoothModifierData *smd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int numVerts) + LaplacianSmoothModifierData *smd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int verts_num) { LaplacianSystem *sys; MDeformVert *dvert = NULL; @@ -378,7 +383,7 @@ static void laplaciansmoothModifier_do( int defgrp_index; const bool invert_vgroup = (smd->flag & MOD_LAPLACIANSMOOTH_INVERT_VGROUP) != 0; - sys = init_laplacian_system(mesh->totedge, mesh->totpoly, mesh->totloop, numVerts); + sys = init_laplacian_system(mesh->totedge, mesh->totpoly, mesh->totloop, verts_num); if (!sys) { return; } @@ -395,12 +400,12 @@ static void laplaciansmoothModifier_do( sys->vert_centroid[2] = 0.0f; memset_laplacian_system(sys, 0); - sys->context = EIG_linear_least_squares_solver_new(numVerts, numVerts, 3); + sys->context = EIG_linear_least_squares_solver_new(verts_num, verts_num, 3); init_laplacian_matrix(sys); for (iter = 0; iter < smd->repeat; iter++) { - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { EIG_linear_solver_variable_set(sys->context, 0, i, vertexCos[i][0]); EIG_linear_solver_variable_set(sys->context, 1, i, vertexCos[i][1]); EIG_linear_solver_variable_set(sys->context, 2, i, vertexCos[i][2]); @@ -408,12 +413,12 @@ static void laplaciansmoothModifier_do( add_v3_v3(sys->vert_centroid, vertexCos[i]); } } - if (iter == 0 && numVerts > 0) { - mul_v3_fl(sys->vert_centroid, 1.0f / (float)numVerts); + if (iter == 0 && verts_num > 0) { + mul_v3_fl(sys->vert_centroid, 1.0f / (float)verts_num); } dv = dvert; - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { EIG_linear_solver_right_hand_side_add(sys->context, 0, i, vertexCos[i][0]); EIG_linear_solver_right_hand_side_add(sys->context, 1, i, vertexCos[i][1]); EIG_linear_solver_right_hand_side_add(sys->context, 2, i, vertexCos[i][2]); @@ -433,7 +438,7 @@ static void laplaciansmoothModifier_do( sys->vweights[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda) * wpaint / w; w = sys->vlengths[i]; sys->vlengths[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda_border) * wpaint * 2.0f / w; - if (sys->numNeEd[i] == sys->numNeFa[i]) { + if (sys->ne_ed_num[i] == sys->ne_fa_num[i]) { EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f + fabsf(smd->lambda) * wpaint); } else { @@ -447,7 +452,7 @@ static void laplaciansmoothModifier_do( w = sys->vlengths[i]; sys->vlengths[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda_border) * wpaint * 2.0f / w; - if (sys->numNeEd[i] == sys->numNeFa[i]) { + if (sys->ne_ed_num[i] == sys->ne_fa_num[i]) { EIG_linear_solver_matrix_add(sys->context, i, i, @@ -522,18 +527,18 @@ static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { Mesh *mesh_src; - if (numVerts == 0) { + if (verts_num == 0) { return; } - mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false); laplaciansmoothModifier_do( - (LaplacianSmoothModifierData *)md, ctx->object, mesh_src, vertexCos, numVerts); + (LaplacianSmoothModifierData *)md, ctx->object, mesh_src, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); @@ -545,15 +550,15 @@ static void deformVertsEM(ModifierData *md, struct BMEditMesh *editData, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { Mesh *mesh_src; - if (numVerts == 0) { + if (verts_num == 0) { return; } - mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, verts_num, false, false); /* TODO(Campbell): use edit-mode data only (remove this line). */ if (mesh_src != NULL) { @@ -561,7 +566,7 @@ static void deformVertsEM(ModifierData *md, } laplaciansmoothModifier_do( - (LaplacianSmoothModifierData *)md, ctx->object, mesh_src, vertexCos, numVerts); + (LaplacianSmoothModifierData *)md, ctx->object, mesh_src, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c index 1017f6cca1a..832372304a0 100644 --- a/source/blender/modifiers/intern/MOD_lattice.c +++ b/source/blender/modifiers/intern/MOD_lattice.c @@ -94,18 +94,18 @@ static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, struct Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { LatticeModifierData *lmd = (LatticeModifierData *)md; struct Mesh *mesh_src = MOD_deform_mesh_eval_get( - ctx->object, NULL, mesh, NULL, numVerts, false, false); + ctx->object, NULL, mesh, NULL, verts_num, false, false); MOD_previous_vcos_store(md, vertexCos); /* if next modifier needs original vertices */ BKE_lattice_deform_coords_with_mesh(lmd->object, ctx->object, vertexCos, - numVerts, + verts_num, lmd->flag, lmd->name, lmd->strength, @@ -121,10 +121,10 @@ static void deformVertsEM(ModifierData *md, struct BMEditMesh *em, struct Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { if (mesh != NULL) { - deformVerts(md, ctx, mesh, vertexCos, numVerts); + deformVerts(md, ctx, mesh, vertexCos, verts_num); return; } @@ -133,7 +133,7 @@ static void deformVertsEM(ModifierData *md, MOD_previous_vcos_store(md, vertexCos); /* if next modifier needs original vertices */ BKE_lattice_deform_coords_with_editmesh( - lmd->object, ctx->object, vertexCos, numVerts, lmd->flag, lmd->name, lmd->strength, em); + lmd->object, ctx->object, vertexCos, verts_num, lmd->flag, lmd->name, lmd->strength, em); } static void panel_draw(const bContext *UNUSED(C), Panel *panel) diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc index 1cb720f4b02..cb26bd1b26b 100644 --- a/source/blender/modifiers/intern/MOD_mask.cc +++ b/source/blender/modifiers/intern/MOD_mask.cc @@ -145,58 +145,58 @@ static void invert_boolean_array(MutableSpan<bool> array) static void compute_masked_vertices(Span<bool> vertex_mask, MutableSpan<int> r_vertex_map, - uint *r_num_masked_vertices) + uint *r_verts_masked_num) { BLI_assert(vertex_mask.size() == r_vertex_map.size()); - uint num_masked_vertices = 0; + uint verts_masked_num = 0; for (uint i_src : r_vertex_map.index_range()) { if (vertex_mask[i_src]) { - r_vertex_map[i_src] = num_masked_vertices; - num_masked_vertices++; + r_vertex_map[i_src] = verts_masked_num; + verts_masked_num++; } else { r_vertex_map[i_src] = -1; } } - *r_num_masked_vertices = num_masked_vertices; + *r_verts_masked_num = verts_masked_num; } static void computed_masked_edges(const Mesh *mesh, Span<bool> vertex_mask, MutableSpan<int> r_edge_map, - uint *r_num_masked_edges) + uint *r_edges_masked_num) { BLI_assert(mesh->totedge == r_edge_map.size()); - uint num_masked_edges = 0; + uint edges_masked_num = 0; for (int i : IndexRange(mesh->totedge)) { const MEdge &edge = mesh->medge[i]; /* only add if both verts will be in new mesh */ if (vertex_mask[edge.v1] && vertex_mask[edge.v2]) { - r_edge_map[i] = num_masked_edges; - num_masked_edges++; + r_edge_map[i] = edges_masked_num; + edges_masked_num++; } else { r_edge_map[i] = -1; } } - *r_num_masked_edges = num_masked_edges; + *r_edges_masked_num = edges_masked_num; } static void computed_masked_edges_smooth(const Mesh *mesh, Span<bool> vertex_mask, MutableSpan<int> r_edge_map, - uint *r_num_masked_edges, - uint *r_num_add_vertices) + uint *r_edges_masked_num, + uint *r_verts_add_num) { BLI_assert(mesh->totedge == r_edge_map.size()); - uint num_masked_edges = 0; - uint num_add_vertices = 0; + uint edges_masked_num = 0; + uint verts_add_num = 0; for (int i : IndexRange(mesh->totedge)) { const MEdge &edge = mesh->medge[i]; @@ -204,36 +204,36 @@ static void computed_masked_edges_smooth(const Mesh *mesh, bool v1 = vertex_mask[edge.v1]; bool v2 = vertex_mask[edge.v2]; if (v1 && v2) { - r_edge_map[i] = num_masked_edges; - num_masked_edges++; + r_edge_map[i] = edges_masked_num; + edges_masked_num++; } else if (v1 != v2) { r_edge_map[i] = -2; - num_add_vertices++; + verts_add_num++; } else { r_edge_map[i] = -1; } } - num_masked_edges += num_add_vertices; - *r_num_masked_edges = num_masked_edges; - *r_num_add_vertices = num_add_vertices; + edges_masked_num += verts_add_num; + *r_edges_masked_num = edges_masked_num; + *r_verts_add_num = verts_add_num; } static void computed_masked_polygons(const Mesh *mesh, Span<bool> vertex_mask, Vector<int> &r_masked_poly_indices, Vector<int> &r_loop_starts, - uint *r_num_masked_polys, - uint *r_num_masked_loops) + uint *r_polys_masked_num, + uint *r_loops_masked_num) { BLI_assert(mesh->totvert == vertex_mask.size()); r_masked_poly_indices.reserve(mesh->totpoly); r_loop_starts.reserve(mesh->totpoly); - uint num_masked_loops = 0; + uint loops_masked_num = 0; for (int i : IndexRange(mesh->totpoly)) { const MPoly &poly_src = mesh->mpoly[i]; @@ -248,35 +248,35 @@ static void computed_masked_polygons(const Mesh *mesh, if (all_verts_in_mask) { r_masked_poly_indices.append_unchecked(i); - r_loop_starts.append_unchecked(num_masked_loops); - num_masked_loops += poly_src.totloop; + r_loop_starts.append_unchecked(loops_masked_num); + loops_masked_num += poly_src.totloop; } } - *r_num_masked_polys = r_masked_poly_indices.size(); - *r_num_masked_loops = num_masked_loops; + *r_polys_masked_num = r_masked_poly_indices.size(); + *r_loops_masked_num = loops_masked_num; } static void compute_interpolated_polygons(const Mesh *mesh, Span<bool> vertex_mask, - uint num_add_vertices, - uint num_masked_loops, + uint verts_add_num, + uint loops_masked_num, Vector<int> &r_masked_poly_indices, Vector<int> &r_loop_starts, - uint *r_num_add_edges, - uint *r_num_add_polys, - uint *r_num_add_loops) + uint *r_edges_add_num, + uint *r_polys_add_num, + uint *r_loops_add_num) { BLI_assert(mesh->totvert == vertex_mask.size()); /* Can't really know ahead of time how much space to use exactly. Estimate limit instead. */ /* NOTE: this reserve can only lift the capacity if there are ngons, which get split. */ - r_masked_poly_indices.reserve(r_masked_poly_indices.size() + num_add_vertices); - r_loop_starts.reserve(r_loop_starts.size() + num_add_vertices); + r_masked_poly_indices.reserve(r_masked_poly_indices.size() + verts_add_num); + r_loop_starts.reserve(r_loop_starts.size() + verts_add_num); - uint num_add_edges = 0; - uint num_add_polys = 0; - uint num_add_loops = 0; + uint edges_add_num = 0; + uint polys_add_num = 0; + uint loops_add_num = 0; for (int i : IndexRange(mesh->totpoly)) { const MPoly &poly_src = mesh->mpoly[i]; @@ -306,10 +306,10 @@ static void compute_interpolated_polygons(const Mesh *mesh, else if (!v_loop_in_mask && v_loop_in_mask_last) { BLI_assert(dst_totloop > 2); r_masked_poly_indices.append(i); - r_loop_starts.append(num_masked_loops + num_add_loops); - num_add_loops += dst_totloop; - num_add_polys++; - num_add_edges++; + r_loop_starts.append(loops_masked_num + loops_add_num); + loops_add_num += dst_totloop; + polys_add_num++; + edges_add_num++; dst_totloop = -1; } else if (v_loop_in_mask && v_loop_in_mask_last) { @@ -322,9 +322,9 @@ static void compute_interpolated_polygons(const Mesh *mesh, } } - *r_num_add_edges = num_add_edges; - *r_num_add_polys = num_add_polys; - *r_num_add_loops = num_add_loops; + *r_edges_add_num = edges_add_num; + *r_polys_add_num = polys_add_num; + *r_loops_add_num = loops_add_num; } static void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh, @@ -363,15 +363,15 @@ static void add_interp_verts_copy_edges_to_new_mesh(const Mesh &src_mesh, MDeformVert *dvert, int defgrp_index, float threshold, - uint num_masked_edges, - uint num_add_verts, + uint edges_masked_num, + uint verts_add_num, MutableSpan<int> r_edge_map) { BLI_assert(src_mesh.totvert == vertex_mask.size()); BLI_assert(src_mesh.totedge == r_edge_map.size()); - uint vert_index = dst_mesh.totvert - num_add_verts; - uint edge_index = num_masked_edges - num_add_verts; + uint vert_index = dst_mesh.totvert - verts_add_num; + uint edge_index = edges_masked_num - verts_add_num; for (int i_src : IndexRange(src_mesh.totedge)) { if (r_edge_map[i_src] != -1) { int i_dst = r_edge_map[i_src]; @@ -416,7 +416,7 @@ static void add_interp_verts_copy_edges_to_new_mesh(const Mesh &src_mesh, } } BLI_assert(vert_index == dst_mesh.totvert); - BLI_assert(edge_index == num_masked_edges); + BLI_assert(edge_index == edges_masked_num); } static void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, @@ -448,9 +448,9 @@ static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, Span<int> edge_map, Span<int> masked_poly_indices, Span<int> new_loop_starts, - int num_masked_polys) + int polys_masked_num) { - for (const int i_dst : IndexRange(num_masked_polys)) { + for (const int i_dst : IndexRange(polys_masked_num)) { const int i_src = masked_poly_indices[i_dst]; const MPoly &mp_src = src_mesh.mpoly[i_src]; @@ -483,14 +483,14 @@ static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh, float threshold, Span<int> masked_poly_indices, Span<int> new_loop_starts, - int num_masked_polys, - int num_add_edges) + int polys_masked_num, + int edges_add_num) { - int edge_index = dst_mesh.totedge - num_add_edges; + int edge_index = dst_mesh.totedge - edges_add_num; int sub_poly_index = 0; int last_i_src = -1; for (const int i_dst : - IndexRange(num_masked_polys, masked_poly_indices.size() - num_masked_polys)) { + IndexRange(polys_masked_num, masked_poly_indices.size() - polys_masked_num)) { const int i_src = masked_poly_indices[i_dst]; if (i_src == last_i_src) { sub_poly_index++; @@ -662,53 +662,52 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx) } Array<int> vertex_map(mesh->totvert); - uint num_masked_vertices; - compute_masked_vertices(vertex_mask, vertex_map, &num_masked_vertices); + uint verts_masked_num; + compute_masked_vertices(vertex_mask, vertex_map, &verts_masked_num); Array<int> edge_map(mesh->totedge); - uint num_masked_edges; - uint num_add_vertices; + uint edges_masked_num; + uint verts_add_num; if (use_interpolation) { - computed_masked_edges_smooth( - mesh, vertex_mask, edge_map, &num_masked_edges, &num_add_vertices); + computed_masked_edges_smooth(mesh, vertex_mask, edge_map, &edges_masked_num, &verts_add_num); } else { - computed_masked_edges(mesh, vertex_mask, edge_map, &num_masked_edges); - num_add_vertices = 0; + computed_masked_edges(mesh, vertex_mask, edge_map, &edges_masked_num); + verts_add_num = 0; } Vector<int> masked_poly_indices; Vector<int> new_loop_starts; - uint num_masked_polys; - uint num_masked_loops; + uint polys_masked_num; + uint loops_masked_num; computed_masked_polygons(mesh, vertex_mask, masked_poly_indices, new_loop_starts, - &num_masked_polys, - &num_masked_loops); + &polys_masked_num, + &loops_masked_num); - uint num_add_edges = 0; - uint num_add_polys = 0; - uint num_add_loops = 0; + uint edges_add_num = 0; + uint polys_add_num = 0; + uint loops_add_num = 0; if (use_interpolation) { compute_interpolated_polygons(mesh, vertex_mask, - num_add_vertices, - num_masked_loops, + verts_add_num, + loops_masked_num, masked_poly_indices, new_loop_starts, - &num_add_edges, - &num_add_polys, - &num_add_loops); + &edges_add_num, + &polys_add_num, + &loops_add_num); } Mesh *result = BKE_mesh_new_nomain_from_template(mesh, - num_masked_vertices + num_add_vertices, - num_masked_edges + num_add_edges, + verts_masked_num + verts_add_num, + edges_masked_num + edges_add_num, 0, - num_masked_loops + num_add_loops, - num_masked_polys + num_add_polys); + loops_masked_num + loops_add_num, + polys_masked_num + polys_add_num); copy_masked_vertices_to_new_mesh(*mesh, *result, vertex_map); if (use_interpolation) { @@ -719,8 +718,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx) dvert, defgrp_index, mmd->threshold, - num_masked_edges, - num_add_vertices, + edges_masked_num, + verts_add_num, edge_map); } else { @@ -732,7 +731,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx) edge_map, masked_poly_indices, new_loop_starts, - num_masked_polys); + polys_masked_num); if (use_interpolation) { add_interpolated_polys_to_new_mesh(*mesh, *result, @@ -744,8 +743,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx) mmd->threshold, masked_poly_indices, new_loop_starts, - num_masked_polys, - num_add_edges); + polys_masked_num, + edges_add_num); } BKE_mesh_calc_edges_loose(result); diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c index 3e022a5951d..6f065797b43 100644 --- a/source/blender/modifiers/intern/MOD_meshcache.c +++ b/source/blender/modifiers/intern/MOD_meshcache.c @@ -54,9 +54,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(mcmd, DNA_struct_default_get(MeshCacheModifierData), modifier); } -static bool dependsOnTime(struct Scene *UNUSED(scene), - ModifierData *md, - const int UNUSED(dag_eval_mode)) +static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md) { MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md; return (mcmd->play_mode == MOD_MESHCACHE_PLAY_CFEA); @@ -77,7 +75,7 @@ static void meshcache_do(MeshCacheModifierData *mcmd, Object *ob, Mesh *mesh, float (*vertexCos_Real)[3], - int numVerts) + int verts_num) { const bool use_factor = mcmd->factor < 1.0f; int influence_group_index; @@ -87,7 +85,7 @@ static void meshcache_do(MeshCacheModifierData *mcmd, float(*vertexCos_Store)[3] = (use_factor || influence_group_index != -1 || (mcmd->deform_mode == MOD_MESHCACHE_DEFORM_INTEGRATE)) ? MEM_malloc_arrayN( - numVerts, sizeof(*vertexCos_Store), __func__) : + verts_num, sizeof(*vertexCos_Store), __func__) : NULL; float(*vertexCos)[3] = vertexCos_Store ? vertexCos_Store : vertexCos_Real; @@ -151,11 +149,11 @@ static void meshcache_do(MeshCacheModifierData *mcmd, switch (mcmd->type) { case MOD_MESHCACHE_TYPE_MDD: ok = MOD_meshcache_read_mdd_times( - filepath, vertexCos, numVerts, mcmd->interp, time, fps, mcmd->time_mode, &err_str); + filepath, vertexCos, verts_num, mcmd->interp, time, fps, mcmd->time_mode, &err_str); break; case MOD_MESHCACHE_TYPE_PC2: ok = MOD_meshcache_read_pc2_times( - filepath, vertexCos, numVerts, mcmd->interp, time, fps, mcmd->time_mode, &err_str); + filepath, vertexCos, verts_num, mcmd->interp, time, fps, mcmd->time_mode, &err_str); break; default: ok = false; @@ -171,7 +169,7 @@ static void meshcache_do(MeshCacheModifierData *mcmd, if (UNLIKELY(ob->type != OB_MESH)) { BKE_modifier_set_error(ob, &mcmd->modifier, "'Integrate' only valid for Mesh objects"); } - else if (UNLIKELY(me->totvert != numVerts)) { + else if (UNLIKELY(me->totvert != verts_num)) { BKE_modifier_set_error(ob, &mcmd->modifier, "'Integrate' original mesh vertex mismatch"); } else if (UNLIKELY(me->totpoly == 0)) { @@ -182,11 +180,11 @@ static void meshcache_do(MeshCacheModifierData *mcmd, int i; float(*vertexCos_Source)[3] = MEM_malloc_arrayN( - numVerts, sizeof(*vertexCos_Source), __func__); - float(*vertexCos_New)[3] = MEM_malloc_arrayN(numVerts, sizeof(*vertexCos_New), __func__); + verts_num, sizeof(*vertexCos_Source), __func__); + float(*vertexCos_New)[3] = MEM_malloc_arrayN(verts_num, sizeof(*vertexCos_New), __func__); MVert *mv = me->mvert; - for (i = 0; i < numVerts; i++, mv++) { + for (i = 0; i < verts_num; i++, mv++) { copy_v3_v3(vertexCos_Source[i], mv->co); } @@ -204,7 +202,7 @@ static void meshcache_do(MeshCacheModifierData *mcmd, ); /* write the corrected locations back into the result */ - memcpy(vertexCos, vertexCos_New, sizeof(*vertexCos) * numVerts); + memcpy(vertexCos, vertexCos_New, sizeof(*vertexCos) * verts_num); MEM_freeN(vertexCos_Source); MEM_freeN(vertexCos_New); @@ -244,7 +242,7 @@ static void meshcache_do(MeshCacheModifierData *mcmd, if (use_matrix) { int i; - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { mul_m3_v3(mat, vertexCos[i]); } } @@ -260,7 +258,7 @@ static void meshcache_do(MeshCacheModifierData *mcmd, mcmd->factor : 0.0f; if (mesh->dvert != NULL) { - for (int i = 0; i < numVerts; i++) { + for (int i = 0; i < verts_num; i++) { /* For each vertex, compute its blending factor between the mesh cache (for `fac = 0`) * and the former position of the vertex (for `fac = 1`). */ const MDeformVert *currentIndexDVert = dvert + i; @@ -275,10 +273,10 @@ static void meshcache_do(MeshCacheModifierData *mcmd, } else if (use_factor) { /* Influence_group_index is -1. */ - interp_vn_vn(*vertexCos_Real, *vertexCos_Store, mcmd->factor, numVerts * 3); + interp_vn_vn(*vertexCos_Real, *vertexCos_Store, mcmd->factor, verts_num * 3); } else { - memcpy(vertexCos_Real, vertexCos_Store, sizeof(*vertexCos_Store) * numVerts); + memcpy(vertexCos_Real, vertexCos_Store, sizeof(*vertexCos_Store) * verts_num); } } @@ -290,7 +288,7 @@ static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md; Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); @@ -299,9 +297,9 @@ static void deformVerts(ModifierData *md, if (ctx->object->type == OB_MESH && mcmd->defgrp_name[0] != '\0') { /* `mesh_src` is only needed for vertex groups. */ - mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false); } - meshcache_do(mcmd, scene, ctx->object, mesh_src, vertexCos, numVerts); + meshcache_do(mcmd, scene, ctx->object, mesh_src, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); @@ -313,7 +311,7 @@ static void deformVertsEM(ModifierData *md, struct BMEditMesh *editData, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md; Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); @@ -322,13 +320,14 @@ static void deformVertsEM(ModifierData *md, if (ctx->object->type == OB_MESH && mcmd->defgrp_name[0] != '\0') { /* `mesh_src` is only needed for vertex groups. */ - mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get( + ctx->object, editData, mesh, NULL, verts_num, false, false); } if (mesh_src != NULL) { BKE_mesh_wrapper_ensure_mdata(mesh_src); } - meshcache_do(mcmd, scene, ctx->object, mesh_src, vertexCos, numVerts); + meshcache_do(mcmd, scene, ctx->object, mesh_src, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); diff --git a/source/blender/modifiers/intern/MOD_meshcache_mdd.c b/source/blender/modifiers/intern/MOD_meshcache_mdd.c index 66b5f3ff9b2..67a01b1c8d5 100644 --- a/source/blender/modifiers/intern/MOD_meshcache_mdd.c +++ b/source/blender/modifiers/intern/MOD_meshcache_mdd.c @@ -96,22 +96,22 @@ static bool meshcache_read_mdd_range_from_time(FILE *fp, return false; } - size_t num_frames_read = 0; - size_t num_frames_expect = mdd_head.frame_tot; + size_t frames_num_read = 0; + size_t frames_num_expect = mdd_head.frame_tot; errno = 0; for (i = 0; i < mdd_head.frame_tot; i++) { - num_frames_read += fread(&f_time, sizeof(float), 1, fp); + frames_num_read += fread(&f_time, sizeof(float), 1, fp); #ifdef __LITTLE_ENDIAN__ BLI_endian_switch_float(&f_time); #endif if (f_time >= time) { - num_frames_expect = i + 1; + frames_num_expect = i + 1; break; } f_time_prev = f_time; } - if (num_frames_read != num_frames_expect) { + if (frames_num_read != frames_num_expect) { *err_str = errno ? strerror(errno) : "Timestamp read failed"; return false; } @@ -160,14 +160,14 @@ bool MOD_meshcache_read_mdd_index(FILE *fp, return false; } - size_t num_verts_read = 0; + size_t verts_read_num = 0; errno = 0; if (factor >= 1.0f) { #if 1 float *vco = *vertexCos; uint i; for (i = mdd_head.verts_tot; i != 0; i--, vco += 3) { - num_verts_read += fread(vco, sizeof(float[3]), 1, fp); + verts_read_num += fread(vco, sizeof(float[3]), 1, fp); # ifdef __LITTLE_ENDIAN__ BLI_endian_switch_float(vco + 0); @@ -192,7 +192,7 @@ bool MOD_meshcache_read_mdd_index(FILE *fp, uint i; for (i = mdd_head.verts_tot; i != 0; i--, vco += 3) { float tvec[3]; - num_verts_read += fread(tvec, sizeof(float[3]), 1, fp); + verts_read_num += fread(tvec, sizeof(float[3]), 1, fp); #ifdef __LITTLE_ENDIAN__ BLI_endian_switch_float(tvec + 0); @@ -206,7 +206,7 @@ bool MOD_meshcache_read_mdd_index(FILE *fp, } } - if (num_verts_read != mdd_head.verts_tot) { + if (verts_read_num != mdd_head.verts_tot) { *err_str = errno ? strerror(errno) : "Vertex coordinate read failed"; return false; } diff --git a/source/blender/modifiers/intern/MOD_meshcache_pc2.c b/source/blender/modifiers/intern/MOD_meshcache_pc2.c index 54ea27d0085..27fea20bb13 100644 --- a/source/blender/modifiers/intern/MOD_meshcache_pc2.c +++ b/source/blender/modifiers/intern/MOD_meshcache_pc2.c @@ -137,13 +137,13 @@ bool MOD_meshcache_read_pc2_index(FILE *fp, return false; } - size_t num_verts_read = 0; + size_t verts_read_num = 0; errno = 0; if (factor >= 1.0f) { float *vco = *vertexCos; uint i; for (i = pc2_head.verts_tot; i != 0; i--, vco += 3) { - num_verts_read += fread(vco, sizeof(float[3]), 1, fp); + verts_read_num += fread(vco, sizeof(float[3]), 1, fp); #ifdef __BIG_ENDIAN__ BLI_endian_switch_float(vco + 0); @@ -158,7 +158,7 @@ bool MOD_meshcache_read_pc2_index(FILE *fp, uint i; for (i = pc2_head.verts_tot; i != 0; i--, vco += 3) { float tvec[3]; - num_verts_read += fread(tvec, sizeof(float[3]), 1, fp); + verts_read_num += fread(tvec, sizeof(float[3]), 1, fp); #ifdef __BIG_ENDIAN__ BLI_endian_switch_float(tvec + 0); @@ -172,7 +172,7 @@ bool MOD_meshcache_read_pc2_index(FILE *fp, } } - if (num_verts_read != pc2_head.verts_tot) { + if (verts_read_num != pc2_head.verts_tot) { *err_str = errno ? strerror(errno) : "Vertex coordinate read failed"; return false; } diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index f15cdfe0c4e..09e6819a2ae 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -222,7 +222,7 @@ static float meshdeform_dynamic_bind(MeshDeformModifierData *mmd, float (*dco)[3 cell = &mmd->dyngrid[a]; inf = mmd->dyninfluences + cell->offset; - for (j = 0; j < cell->totinfluence; j++, inf++) { + for (j = 0; j < cell->influences_num; j++, inf++) { cageco = dco[inf->vertex]; cageweight = weight * inf->weight; #ifdef BLI_HAVE_SSE2 @@ -324,7 +324,7 @@ static void meshdeformModifier_do(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + const int verts_num) { MeshDeformModifierData *mmd = (MeshDeformModifierData *)md; Object *ob = ctx->object; @@ -333,7 +333,7 @@ static void meshdeformModifier_do(ModifierData *md, MDeformVert *dvert = NULL; float imat[4][4], cagemat[4][4], iobmat[4][4], icagemat[3][3], cmat[4][4]; float(*dco)[3] = NULL, (*bindcagecos)[3]; - int a, totvert, totcagevert, defgrp_index; + int a, cage_verts_num, defgrp_index; MeshdeformUserdata data; static int recursive_bind_sentinel = 0; @@ -375,7 +375,7 @@ static void meshdeformModifier_do(ModifierData *md, } if (!recursive_bind_sentinel) { recursive_bind_sentinel = 1; - mmd->bindfunc(ob, mmd, cagemesh, (float *)vertexCos, numVerts, cagemat); + mmd->bindfunc(ob, mmd, cagemesh, (float *)vertexCos, verts_num, cagemat); recursive_bind_sentinel = 0; } @@ -383,16 +383,15 @@ static void meshdeformModifier_do(ModifierData *md, } /* verify we have compatible weights */ - totvert = numVerts; - totcagevert = BKE_mesh_wrapper_vert_len(cagemesh); + cage_verts_num = BKE_mesh_wrapper_vert_len(cagemesh); - if (mmd->totvert != totvert) { - BKE_modifier_set_error(ob, md, "Vertices changed from %d to %d", mmd->totvert, totvert); + if (mmd->verts_num != verts_num) { + BKE_modifier_set_error(ob, md, "Vertices changed from %d to %d", mmd->verts_num, verts_num); goto finally; } - else if (mmd->totcagevert != totcagevert) { + else if (mmd->cage_verts_num != cage_verts_num) { BKE_modifier_set_error( - ob, md, "Cage vertices changed from %d to %d", mmd->totcagevert, totcagevert); + ob, md, "Cage vertices changed from %d to %d", mmd->cage_verts_num, cage_verts_num); goto finally; } else if (mmd->bindcagecos == NULL) { @@ -403,14 +402,14 @@ static void meshdeformModifier_do(ModifierData *md, /* We allocate 1 element extra to make it possible to * load the values to SSE registers, which are float4. */ - dco = MEM_calloc_arrayN((totcagevert + 1), sizeof(*dco), "MDefDco"); - zero_v3(dco[totcagevert]); + dco = MEM_calloc_arrayN((cage_verts_num + 1), sizeof(*dco), "MDefDco"); + zero_v3(dco[cage_verts_num]); /* setup deformation data */ - BKE_mesh_wrapper_vert_coords_copy(cagemesh, dco, totcagevert); + BKE_mesh_wrapper_vert_coords_copy(cagemesh, dco, cage_verts_num); bindcagecos = (float(*)[3])mmd->bindcagecos; - for (a = 0; a < totcagevert; a++) { + for (a = 0; a < cage_verts_num; a++) { /* Get cage vertex in world-space with binding transform. */ float co[3]; mul_v3_m4v3(co, mmd->bindmat, dco[a]); @@ -433,7 +432,7 @@ static void meshdeformModifier_do(ModifierData *md, TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.min_iter_per_thread = 16; - BLI_task_parallel_range(0, totvert, &data, meshdeform_vert_task, &settings); + BLI_task_parallel_range(0, verts_num, &data, meshdeform_vert_task, &settings); finally: MEM_SAFE_FREE(dco); @@ -443,13 +442,14 @@ static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { - Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false); + Mesh *mesh_src = MOD_deform_mesh_eval_get( + ctx->object, NULL, mesh, NULL, verts_num, false, false); MOD_previous_vcos_store(md, vertexCos); /* if next modifier needs original vertices */ - meshdeformModifier_do(md, ctx, mesh_src, vertexCos, numVerts); + meshdeformModifier_do(md, ctx, mesh_src, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); @@ -461,17 +461,17 @@ static void deformVertsEM(ModifierData *md, struct BMEditMesh *editData, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { Mesh *mesh_src = MOD_deform_mesh_eval_get( - ctx->object, editData, mesh, NULL, numVerts, false, false); + ctx->object, editData, mesh, NULL, verts_num, false, false); /* TODO(Campbell): use edit-mode data only (remove this line). */ if (mesh_src != NULL) { BKE_mesh_wrapper_ensure_mdata(mesh_src); } - meshdeformModifier_do(md, ctx, mesh_src, vertexCos, numVerts); + meshdeformModifier_do(md, ctx, mesh_src, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); @@ -484,42 +484,42 @@ void BKE_modifier_mdef_compact_influences(ModifierData *md) { MeshDeformModifierData *mmd = (MeshDeformModifierData *)md; float weight, *weights, totweight; - int totinfluence, totvert, totcagevert, a, b; + int influences_num, verts_num, cage_verts_num, a, b; weights = mmd->bindweights; if (!weights) { return; } - totvert = mmd->totvert; - totcagevert = mmd->totcagevert; + verts_num = mmd->verts_num; + cage_verts_num = mmd->cage_verts_num; /* count number of influences above threshold */ - for (b = 0; b < totvert; b++) { - for (a = 0; a < totcagevert; a++) { - weight = weights[a + b * totcagevert]; + for (b = 0; b < verts_num; b++) { + for (a = 0; a < cage_verts_num; a++) { + weight = weights[a + b * cage_verts_num]; if (weight > MESHDEFORM_MIN_INFLUENCE) { - mmd->totinfluence++; + mmd->influences_num++; } } } /* allocate bind influences */ mmd->bindinfluences = MEM_calloc_arrayN( - mmd->totinfluence, sizeof(MDefInfluence), "MDefBindInfluence"); - mmd->bindoffsets = MEM_calloc_arrayN((totvert + 1), sizeof(int), "MDefBindOffset"); + mmd->influences_num, sizeof(MDefInfluence), "MDefBindInfluence"); + mmd->bindoffsets = MEM_calloc_arrayN((verts_num + 1), sizeof(int), "MDefBindOffset"); /* write influences */ - totinfluence = 0; + influences_num = 0; - for (b = 0; b < totvert; b++) { - mmd->bindoffsets[b] = totinfluence; + for (b = 0; b < verts_num; b++) { + mmd->bindoffsets[b] = influences_num; totweight = 0.0f; /* sum total weight */ - for (a = 0; a < totcagevert; a++) { - weight = weights[a + b * totcagevert]; + for (a = 0; a < cage_verts_num; a++) { + weight = weights[a + b * cage_verts_num]; if (weight > MESHDEFORM_MIN_INFLUENCE) { totweight += weight; @@ -527,18 +527,18 @@ void BKE_modifier_mdef_compact_influences(ModifierData *md) } /* assign weights normalized */ - for (a = 0; a < totcagevert; a++) { - weight = weights[a + b * totcagevert]; + for (a = 0; a < cage_verts_num; a++) { + weight = weights[a + b * cage_verts_num]; if (weight > MESHDEFORM_MIN_INFLUENCE) { - mmd->bindinfluences[totinfluence].weight = weight / totweight; - mmd->bindinfluences[totinfluence].vertex = a; - totinfluence++; + mmd->bindinfluences[influences_num].weight = weight / totweight; + mmd->bindinfluences[influences_num].vertex = a; + influences_num++; } } } - mmd->bindoffsets[b] = totinfluence; + mmd->bindoffsets[b] = influences_num; /* free */ MEM_freeN(mmd->bindweights); @@ -586,12 +586,12 @@ static void blendWrite(BlendWriter *writer, const ModifierData *md) MeshDeformModifierData *mmd = (MeshDeformModifierData *)md; int size = mmd->dyngridsize; - BLO_write_struct_array(writer, MDefInfluence, mmd->totinfluence, mmd->bindinfluences); - BLO_write_int32_array(writer, mmd->totvert + 1, mmd->bindoffsets); - BLO_write_float3_array(writer, mmd->totcagevert, mmd->bindcagecos); + BLO_write_struct_array(writer, MDefInfluence, mmd->influences_num, mmd->bindinfluences); + BLO_write_int32_array(writer, mmd->verts_num + 1, mmd->bindoffsets); + BLO_write_float3_array(writer, mmd->cage_verts_num, mmd->bindcagecos); BLO_write_struct_array(writer, MDefCell, size * size * size, mmd->dyngrid); - BLO_write_struct_array(writer, MDefInfluence, mmd->totinfluence, mmd->dyninfluences); - BLO_write_int32_array(writer, mmd->totvert, mmd->dynverts); + BLO_write_struct_array(writer, MDefInfluence, mmd->influences_num, mmd->dyninfluences); + BLO_write_int32_array(writer, mmd->verts_num, mmd->dynverts); } static void blendRead(BlendDataReader *reader, ModifierData *md) @@ -599,15 +599,15 @@ static void blendRead(BlendDataReader *reader, ModifierData *md) MeshDeformModifierData *mmd = (MeshDeformModifierData *)md; BLO_read_data_address(reader, &mmd->bindinfluences); - BLO_read_int32_array(reader, mmd->totvert + 1, &mmd->bindoffsets); - BLO_read_float3_array(reader, mmd->totcagevert, &mmd->bindcagecos); + BLO_read_int32_array(reader, mmd->verts_num + 1, &mmd->bindoffsets); + BLO_read_float3_array(reader, mmd->cage_verts_num, &mmd->bindcagecos); BLO_read_data_address(reader, &mmd->dyngrid); BLO_read_data_address(reader, &mmd->dyninfluences); - BLO_read_int32_array(reader, mmd->totvert, &mmd->dynverts); + BLO_read_int32_array(reader, mmd->verts_num, &mmd->dynverts); /* Deprecated storage. */ - BLO_read_float_array(reader, mmd->totvert, &mmd->bindweights); - BLO_read_float3_array(reader, mmd->totcagevert, &mmd->bindcos); + BLO_read_float_array(reader, mmd->verts_num, &mmd->bindweights); + BLO_read_float3_array(reader, mmd->cage_verts_num, &mmd->bindcos); } ModifierTypeInfo modifierType_MeshDeform = { diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.cc b/source/blender/modifiers/intern/MOD_meshsequencecache.cc index cfc5b17f37e..eadfdcf5baa 100644 --- a/source/blender/modifiers/intern/MOD_meshsequencecache.cc +++ b/source/blender/modifiers/intern/MOD_meshsequencecache.cc @@ -106,7 +106,7 @@ static bool isDisabled(const struct Scene *UNUSED(scene), static Mesh *generate_bounding_box_mesh(Object *object, Mesh *org_mesh) { - BoundBox *bb = BKE_object_boundbox_get(object); + const BoundBox *bb = BKE_object_boundbox_get(object); Mesh *result = BKE_mesh_new_nomain_from_template(org_mesh, 8, 0, 0, 24, 6); MVert *mvert = result->mvert; @@ -169,7 +169,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Do not process data if using a render procedural, return a box instead for displaying in the * viewport. */ - if (BKE_cache_file_uses_render_procedural(cache_file, scene, DEG_get_mode(ctx->depsgraph))) { + if (BKE_cache_file_uses_render_procedural(cache_file, scene)) { return generate_bounding_box_mesh(ctx->object, org_mesh); } @@ -263,15 +263,15 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * #endif } -static bool dependsOnTime(Scene *scene, ModifierData *md, const int dag_eval_mode) +static bool dependsOnTime(Scene *scene, ModifierData *md) { #if defined(WITH_USD) || defined(WITH_ALEMBIC) MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md); /* Do not evaluate animations if using the render engine procedural. */ return (mcmd->cache_file != nullptr) && - !BKE_cache_file_uses_render_procedural(mcmd->cache_file, scene, dag_eval_mode); + !BKE_cache_file_uses_render_procedural(mcmd->cache_file, scene); #else - UNUSED_VARS(scene, md, dag_eval_mode); + UNUSED_VARS(scene, md); return false; #endif } diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c index cc6f23073a3..a4c5ddac5c9 100644 --- a/source/blender/modifiers/intern/MOD_multires.c +++ b/source/blender/modifiers/intern/MOD_multires.c @@ -281,7 +281,7 @@ static void deformMatrices(ModifierData *md, Mesh *mesh, float (*vertex_cos)[3], float (*deform_matrices)[3][3], - int num_verts) + int verts_num) { #if !defined(WITH_OPENSUBDIV) @@ -313,7 +313,7 @@ static void deformMatrices(ModifierData *md, return; } BKE_subdiv_displacement_attach_from_multires(subdiv, mesh, mmd); - BKE_subdiv_deform_coarse_vertices(subdiv, mesh, vertex_cos, num_verts); + BKE_subdiv_deform_coarse_vertices(subdiv, mesh, vertex_cos, verts_num); if (subdiv != runtime_data->subdiv) { BKE_subdiv_free(subdiv); } diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index e94f8e50fec..7545bae43b3 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -36,6 +36,7 @@ #include "BKE_attribute_math.hh" #include "BKE_customdata.h" +#include "BKE_geometry_fields.hh" #include "BKE_geometry_set_instances.hh" #include "BKE_global.h" #include "BKE_idprop.h" @@ -315,9 +316,7 @@ static bool check_tree_for_time_node(const bNodeTree &tree, return false; } -static bool dependsOnTime(struct Scene *UNUSED(scene), - ModifierData *md, - const int UNUSED(dag_eval_mode)) +static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md) { const NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md); const bNodeTree *tree = nmd->node_group; @@ -732,33 +731,6 @@ void MOD_nodes_update_interface(Object *object, NodesModifierData *nmd) DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY); } -void MOD_nodes_init(Main *bmain, NodesModifierData *nmd) -{ - bNodeTree *ntree = ntreeAddTree(bmain, "Geometry Nodes", ntreeType_Geometry->idname); - nmd->node_group = ntree; - - ntreeAddSocketInterface(ntree, SOCK_IN, "NodeSocketGeometry", "Geometry"); - ntreeAddSocketInterface(ntree, SOCK_OUT, "NodeSocketGeometry", "Geometry"); - - bNode *group_input_node = nodeAddStaticNode(nullptr, ntree, NODE_GROUP_INPUT); - bNode *group_output_node = nodeAddStaticNode(nullptr, ntree, NODE_GROUP_OUTPUT); - - nodeSetSelected(group_input_node, false); - nodeSetSelected(group_output_node, false); - - group_input_node->locx = -200 - group_input_node->width; - group_output_node->locx = 200; - group_output_node->flag |= NODE_DO_OUTPUT; - - nodeAddLink(ntree, - group_output_node, - (bNodeSocket *)group_output_node->inputs.first, - group_input_node, - (bNodeSocket *)group_input_node->outputs.first); - - BKE_ntree_update_main_tree(bmain, ntree, nullptr); -} - static void initialize_group_input(NodesModifierData &nmd, const OutputSocketRef &socket, void *r_value) diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc index 8e5f9dc429f..68207d84015 100644 --- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc +++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc @@ -1662,7 +1662,7 @@ class GeometryNodesEvaluator { void construct_default_value(const CPPType &type, void *r_value) { - type.copy_construct(type.default_value(), r_value); + type.value_initialize(r_value); } NodeState &get_node_state(const DNode node) @@ -1915,7 +1915,7 @@ void NodeParamsProvider::set_default_remaining_outputs() const CPPType *type = get_socket_cpp_type(socket); BLI_assert(type != nullptr); void *buffer = allocator.allocate(type->size(), type->alignment()); - type->copy_construct(type->default_value(), buffer); + type->value_initialize(buffer); evaluator_.forward_output(socket, {type, buffer}, run_state_); output_state.has_been_computed = true; } diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index 94b35c42247..fe05f48a868 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -43,7 +43,7 @@ static void generate_vert_coordinates(Mesh *mesh, Object *ob, Object *ob_center, const float offset[3], - const int num_verts, + const int verts_num, float (*r_cos)[3], float r_size[3]) { @@ -108,7 +108,7 @@ static void generate_vert_coordinates(Mesh *mesh, /* Else, no need to change coordinates! */ if (do_diff) { - int i = num_verts; + int i = verts_num; while (i--) { add_v3_v3(r_cos[i], diff); } @@ -122,11 +122,11 @@ static void mix_normals(const float mix_factor, const bool use_invert_vgroup, const float mix_limit, const short mix_mode, - const int num_verts, + const int verts_num, MLoop *mloop, float (*nos_old)[3], float (*nos_new)[3], - const int num_loops) + const int loops_num) { /* Mix with org normals... */ float *facs = NULL, *wfac; @@ -134,12 +134,12 @@ static void mix_normals(const float mix_factor, int i; if (dvert) { - facs = MEM_malloc_arrayN((size_t)num_loops, sizeof(*facs), __func__); + facs = MEM_malloc_arrayN((size_t)loops_num, sizeof(*facs), __func__); BKE_defvert_extract_vgroup_to_loopweights( - dvert, defgrp_index, num_verts, mloop, num_loops, facs, use_invert_vgroup); + dvert, defgrp_index, verts_num, mloop, loops_num, facs, use_invert_vgroup); } - for (i = num_loops, no_new = nos_new, no_old = nos_old, wfac = facs; i--; + for (i = loops_num, no_new = nos_new, no_old = nos_old, wfac = facs; i--; no_new++, no_old++, wfac++) { const float fac = facs ? *wfac * mix_factor : mix_factor; @@ -177,14 +177,14 @@ static bool polygons_check_flip(MLoop *mloop, CustomData *ldata, MPoly *mpoly, float (*polynors)[3], - const int num_polys) + const int polys_num) { MPoly *mp; MDisps *mdisp = CustomData_get_layer(ldata, CD_MDISPS); int i; bool flipped = false; - for (i = 0, mp = mpoly; i < num_polys; i++, mp++) { + for (i = 0, mp = mpoly; i < polys_num; i++, mp++) { float norsum[3] = {0.0f}; float(*no)[3]; int j; @@ -222,26 +222,26 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd, const int defgrp_index, const bool use_invert_vgroup, MVert *mvert, - const int num_verts, + const int verts_num, MEdge *medge, - const int num_edges, + const int edges_num, MLoop *mloop, - const int num_loops, + const int loops_num, MPoly *mpoly, - const int num_polys) + const int polys_num) { Object *ob_target = enmd->target; const bool do_polynors_fix = (enmd->flag & MOD_NORMALEDIT_NO_POLYNORS_FIX) == 0; int i; - float(*cos)[3] = MEM_malloc_arrayN((size_t)num_verts, sizeof(*cos), __func__); - float(*nos)[3] = MEM_malloc_arrayN((size_t)num_loops, sizeof(*nos), __func__); + float(*cos)[3] = MEM_malloc_arrayN((size_t)verts_num, sizeof(*cos), __func__); + float(*nos)[3] = MEM_malloc_arrayN((size_t)loops_num, sizeof(*nos), __func__); float size[3]; - BLI_bitmap *done_verts = BLI_BITMAP_NEW((size_t)num_verts, __func__); + BLI_bitmap *done_verts = BLI_BITMAP_NEW((size_t)verts_num, __func__); - generate_vert_coordinates(mesh, ob, ob_target, enmd->offset, num_verts, cos, size); + generate_vert_coordinates(mesh, ob, ob_target, enmd->offset, verts_num, cos, size); /** * size gives us our spheroid coefficients `(A, B, C)`. @@ -283,7 +283,7 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd, float(*no)[3]; /* We reuse cos to now store the ellipsoid-normal of the verts! */ - for (i = num_loops, ml = mloop, no = nos; i--; ml++, no++) { + for (i = loops_num, ml = mloop, no = nos; i--; ml++, no++) { const int vidx = ml->v; float *co = cos[vidx]; @@ -313,31 +313,31 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd, use_invert_vgroup, mix_limit, mix_mode, - num_verts, + verts_num, mloop, loopnors, nos, - num_loops); + loops_num); } if (do_polynors_fix && polygons_check_flip( - mloop, nos, &mesh->ldata, mpoly, BKE_mesh_poly_normals_for_write(mesh), num_polys)) { + mloop, nos, &mesh->ldata, mpoly, BKE_mesh_poly_normals_for_write(mesh), polys_num)) { /* We need to recompute vertex normals! */ BKE_mesh_normals_tag_dirty(mesh); } BKE_mesh_normals_loop_custom_set(mvert, BKE_mesh_vertex_normals_ensure(mesh), - num_verts, + verts_num, medge, - num_edges, + edges_num, mloop, nos, - num_loops, + loops_num, mpoly, polynors, - num_polys, + polys_num, clnors); MEM_freeN(cos); @@ -359,20 +359,20 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd, const int defgrp_index, const bool use_invert_vgroup, MVert *mvert, - const int num_verts, + const int verts_num, MEdge *medge, - const int num_edges, + const int edges_num, MLoop *mloop, - const int num_loops, + const int loops_num, MPoly *mpoly, - const int num_polys) + const int polys_num) { Object *ob_target = enmd->target; const bool do_polynors_fix = (enmd->flag & MOD_NORMALEDIT_NO_POLYNORS_FIX) == 0; const bool use_parallel_normals = (enmd->flag & MOD_NORMALEDIT_USE_DIRECTION_PARALLEL) != 0; - float(*nos)[3] = MEM_malloc_arrayN((size_t)num_loops, sizeof(*nos), __func__); + float(*nos)[3] = MEM_malloc_arrayN((size_t)loops_num, sizeof(*nos), __func__); float target_co[3]; int i; @@ -390,20 +390,20 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd, sub_v3_v3v3(no, target_co, enmd->offset); normalize_v3(no); - for (i = num_loops; i--;) { + for (i = loops_num; i--;) { copy_v3_v3(nos[i], no); } } else { - float(*cos)[3] = MEM_malloc_arrayN((size_t)num_verts, sizeof(*cos), __func__); - generate_vert_coordinates(mesh, ob, ob_target, NULL, num_verts, cos, NULL); + float(*cos)[3] = MEM_malloc_arrayN((size_t)verts_num, sizeof(*cos), __func__); + generate_vert_coordinates(mesh, ob, ob_target, NULL, verts_num, cos, NULL); - BLI_bitmap *done_verts = BLI_BITMAP_NEW((size_t)num_verts, __func__); + BLI_bitmap *done_verts = BLI_BITMAP_NEW((size_t)verts_num, __func__); MLoop *ml; float(*no)[3]; /* We reuse cos to now store the 'to target' normal of the verts! */ - for (i = num_loops, no = nos, ml = mloop; i--; no++, ml++) { + for (i = loops_num, no = nos, ml = mloop; i--; no++, ml++) { const int vidx = ml->v; float *co = cos[vidx]; @@ -428,30 +428,30 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd, use_invert_vgroup, mix_limit, mix_mode, - num_verts, + verts_num, mloop, loopnors, nos, - num_loops); + loops_num); } if (do_polynors_fix && polygons_check_flip( - mloop, nos, &mesh->ldata, mpoly, BKE_mesh_poly_normals_for_write(mesh), num_polys)) { + mloop, nos, &mesh->ldata, mpoly, BKE_mesh_poly_normals_for_write(mesh), polys_num)) { BKE_mesh_normals_tag_dirty(mesh); } BKE_mesh_normals_loop_custom_set(mvert, BKE_mesh_vertex_normals_ensure(mesh), - num_verts, + verts_num, medge, - num_edges, + edges_num, mloop, nos, - num_loops, + loops_num, mpoly, polynors, - num_polys, + polys_num, clnors); MEM_freeN(nos); @@ -519,10 +519,10 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, result = mesh; } - const int num_verts = result->totvert; - const int num_edges = result->totedge; - const int num_loops = result->totloop; - const int num_polys = result->totpoly; + const int verts_num = result->totvert; + const int edges_num = result->totedge; + const int loops_num = result->totloop; + const int polys_num = result->totpoly; MVert *mvert = result->mvert; MEdge *medge = result->medge; MLoop *mloop = result->mloop; @@ -541,20 +541,20 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, clnors = CustomData_get_layer(ldata, CD_CUSTOMLOOPNORMAL); if (use_current_clnors) { - clnors = CustomData_duplicate_referenced_layer(ldata, CD_CUSTOMLOOPNORMAL, num_loops); - loopnors = MEM_malloc_arrayN((size_t)num_loops, sizeof(*loopnors), __func__); + clnors = CustomData_duplicate_referenced_layer(ldata, CD_CUSTOMLOOPNORMAL, loops_num); + loopnors = MEM_malloc_arrayN((size_t)loops_num, sizeof(*loopnors), __func__); BKE_mesh_normals_loop_split(mvert, vert_normals, - num_verts, + verts_num, medge, - num_edges, + edges_num, mloop, loopnors, - num_loops, + loops_num, mpoly, poly_normals, - num_polys, + polys_num, true, result->smoothresh, NULL, @@ -563,7 +563,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, } if (clnors == NULL) { - clnors = CustomData_add_layer(ldata, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, num_loops); + clnors = CustomData_add_layer(ldata, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, loops_num); } MOD_get_vgroup(ob, result, enmd->defgrp_name, &dvert, &defgrp_index); @@ -583,13 +583,13 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, defgrp_index, use_invert_vgroup, mvert, - num_verts, + verts_num, medge, - num_edges, + edges_num, mloop, - num_loops, + loops_num, mpoly, - num_polys); + polys_num); } else if (enmd->mode == MOD_NORMALEDIT_MODE_DIRECTIONAL) { normalEditModifier_do_directional(enmd, @@ -606,13 +606,13 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, defgrp_index, use_invert_vgroup, mvert, - num_verts, + verts_num, medge, - num_edges, + edges_num, mloop, - num_loops, + loops_num, mpoly, - num_polys); + polys_num); } MEM_SAFE_FREE(loopnors); diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index c1423347413..6ded702ceda 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -249,8 +249,8 @@ static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig, co GenerateOceanGeometryData gogd; - int num_verts; - int num_polys; + int verts_num; + int polys_num; const bool use_threading = resolution > 4; @@ -259,8 +259,8 @@ static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig, co gogd.res_x = gogd.rx * omd->repeat_x; gogd.res_y = gogd.ry * omd->repeat_y; - num_verts = (gogd.res_x + 1) * (gogd.res_y + 1); - num_polys = gogd.res_x * gogd.res_y; + verts_num = (gogd.res_x + 1) * (gogd.res_y + 1); + polys_num = gogd.res_x * gogd.res_y; gogd.sx = omd->size * omd->spatial_size; gogd.sy = omd->size * omd->spatial_size; @@ -270,7 +270,7 @@ static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig, co gogd.sx /= gogd.rx; gogd.sy /= gogd.ry; - result = BKE_mesh_new_nomain(num_verts, 0, 0, num_polys * 4, num_polys); + result = BKE_mesh_new_nomain(verts_num, 0, 0, polys_num * 4, polys_num); BKE_mesh_copy_parameters_for_eval(result, mesh_orig); gogd.mverts = result->mvert; @@ -292,7 +292,7 @@ static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig, co /* add uvs */ if (CustomData_number_of_layers(&result->ldata, CD_MLOOPUV) < MAX_MTFACE) { gogd.mloopuvs = CustomData_add_layer( - &result->ldata, CD_MLOOPUV, CD_CALLOC, NULL, num_polys * 4); + &result->ldata, CD_MLOOPUV, CD_CALLOC, NULL, polys_num * 4); if (gogd.mloopuvs) { /* unlikely to fail */ gogd.ix = 1.0 / gogd.rx; @@ -377,23 +377,23 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes if (omd->flag & MOD_OCEAN_GENERATE_FOAM) { if (CustomData_number_of_layers(&result->ldata, CD_MLOOPCOL) < MAX_MCOL) { - const int num_polys = result->totpoly; - const int num_loops = result->totloop; + const int polys_num = result->totpoly; + const int loops_num = result->totloop; MLoop *mloops = result->mloop; MLoopCol *mloopcols = CustomData_add_layer_named( - &result->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, num_loops, omd->foamlayername); + &result->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, loops_num, omd->foamlayername); MLoopCol *mloopcols_spray = NULL; if (omd->flag & MOD_OCEAN_GENERATE_SPRAY) { mloopcols_spray = CustomData_add_layer_named( - &result->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, num_loops, omd->spraylayername); + &result->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, loops_num, omd->spraylayername); } if (mloopcols) { /* unlikely to fail */ MPoly *mpolys = result->mpoly; MPoly *mp; - for (i = 0, mp = mpolys; i < num_polys; i++, mp++) { + for (i = 0, mp = mpolys; i < polys_num; i++, mp++) { MLoop *ml = &mloops[mp->loopstart]; MLoopCol *mlcol = &mloopcols[mp->loopstart]; @@ -449,9 +449,9 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes /* NOTE: tried to parallelized that one and previous foam loop, * but gives 20% slower results... odd. */ { - const int num_verts = result->totvert; + const int verts_num = result->totvert; - for (i = 0; i < num_verts; i++) { + for (i = 0; i < verts_num; i++) { float *vco = mverts[i].co; const float u = OCEAN_CO(size_co_inv, vco[0]); const float v = OCEAN_CO(size_co_inv, vco[1]); diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c index 6c2651bae1f..7df7ba7c1db 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.c +++ b/source/blender/modifiers/intern/MOD_particlesystem.c @@ -100,7 +100,7 @@ static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { Mesh *mesh_src = mesh; ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; @@ -118,7 +118,8 @@ static void deformVerts(ModifierData *md, } if (mesh_src == NULL) { - mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, NULL, vertexCos, numVerts, false, true); + mesh_src = MOD_deform_mesh_eval_get( + ctx->object, NULL, NULL, vertexCos, verts_num, false, true); if (mesh_src == NULL) { return; } @@ -235,7 +236,7 @@ static void deformVertsEM(ModifierData *md, BMEditMesh *editData, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { const bool do_temp_mesh = (mesh == NULL); if (do_temp_mesh) { @@ -243,7 +244,7 @@ static void deformVertsEM(ModifierData *md, BM_mesh_bm_to_me(NULL, editData->bm, mesh, &((BMeshToMeshParams){0})); } - deformVerts(md, ob, mesh, vertexCos, numVerts); + deformVerts(md, ob, mesh, vertexCos, verts_num); if (derivedData) { BKE_id_free(NULL, mesh); diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c index 5d6be527b2d..6953e89dfc2 100644 --- a/source/blender/modifiers/intern/MOD_shapekey.c +++ b/source/blender/modifiers/intern/MOD_shapekey.c @@ -27,14 +27,14 @@ static void deformVerts(ModifierData *UNUSED(md), const ModifierEvalContext *ctx, Mesh *UNUSED(mesh), float (*vertexCos)[3], - int numVerts) + int verts_num) { Key *key = BKE_key_from_object(ctx->object); if (key && key->block.first) { int deformedVerts_tot; BKE_key_evaluate_object_ex( - ctx->object, &deformedVerts_tot, (float *)vertexCos, sizeof(*vertexCos) * numVerts); + ctx->object, &deformedVerts_tot, (float *)vertexCos, sizeof(*vertexCos) * verts_num); } } @@ -43,7 +43,7 @@ static void deformMatrices(ModifierData *md, Mesh *mesh, float (*vertexCos)[3], float (*defMats)[3][3], - int numVerts) + int verts_num) { Key *key = BKE_key_from_object(ctx->object); KeyBlock *kb = BKE_keyblock_from_object(ctx->object); @@ -51,7 +51,7 @@ static void deformMatrices(ModifierData *md, (void)vertexCos; /* unused */ - if (kb && kb->totelem == numVerts && kb != key->refkey) { + if (kb && kb->totelem == verts_num && kb != key->refkey) { int a; if (ctx->object->shapeflag & OB_SHAPE_LOCK) { @@ -61,12 +61,12 @@ static void deformMatrices(ModifierData *md, scale_m3_fl(scale, kb->curval); } - for (a = 0; a < numVerts; a++) { + for (a = 0; a < verts_num; a++) { copy_m3_m3(defMats[a], scale); } } - deformVerts(md, ctx, mesh, vertexCos, numVerts); + deformVerts(md, ctx, mesh, vertexCos, verts_num); } static void deformVertsEM(ModifierData *md, @@ -74,12 +74,12 @@ static void deformVertsEM(ModifierData *md, struct BMEditMesh *UNUSED(editData), Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { Key *key = BKE_key_from_object(ctx->object); if (key && key->type == KEY_RELATIVE) { - deformVerts(md, ctx, mesh, vertexCos, numVerts); + deformVerts(md, ctx, mesh, vertexCos, verts_num); } } @@ -89,7 +89,7 @@ static void deformMatricesEM(ModifierData *UNUSED(md), Mesh *UNUSED(mesh), float (*vertexCos)[3], float (*defMats)[3][3], - int numVerts) + int verts_num) { Key *key = BKE_key_from_object(ctx->object); KeyBlock *kb = BKE_keyblock_from_object(ctx->object); @@ -97,11 +97,11 @@ static void deformMatricesEM(ModifierData *UNUSED(md), (void)vertexCos; /* unused */ - if (kb && kb->totelem == numVerts && kb != key->refkey) { + if (kb && kb->totelem == verts_num && kb != key->refkey) { int a; scale_m3_fl(scale, kb->curval); - for (a = 0; a < numVerts; a++) { + for (a = 0; a < verts_num; a++) { copy_m3_m3(defMats[a], scale); } } diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c index 21f8f90585d..488df3d6f4c 100644 --- a/source/blender/modifiers/intern/MOD_shrinkwrap.c +++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c @@ -98,7 +98,7 @@ static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { ShrinkwrapModifierData *swmd = (ShrinkwrapModifierData *)md; struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); @@ -108,7 +108,7 @@ static void deformVerts(ModifierData *md, (swmd->shrinkType == MOD_SHRINKWRAP_PROJECT)) { /* mesh_src is needed for vgroups, but also used as ShrinkwrapCalcData.vert when projecting. * Avoid time-consuming mesh conversion for curves when not projecting. */ - mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false); } struct MDeformVert *dvert = NULL; @@ -116,7 +116,7 @@ static void deformVerts(ModifierData *md, MOD_get_vgroup(ctx->object, mesh_src, swmd->vgroup_name, &dvert, &defgrp_index); shrinkwrapModifier_deform( - swmd, ctx, scene, ctx->object, mesh_src, dvert, defgrp_index, vertexCos, numVerts); + swmd, ctx, scene, ctx->object, mesh_src, dvert, defgrp_index, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); @@ -128,14 +128,15 @@ static void deformVertsEM(ModifierData *md, struct BMEditMesh *editData, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { ShrinkwrapModifierData *swmd = (ShrinkwrapModifierData *)md; struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); Mesh *mesh_src = NULL; if ((swmd->vgroup_name[0] != '\0') || (swmd->shrinkType == MOD_SHRINKWRAP_PROJECT)) { - mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get( + ctx->object, editData, mesh, NULL, verts_num, false, false); } /* TODO(Campbell): use edit-mode data only (remove this line). */ @@ -150,7 +151,7 @@ static void deformVertsEM(ModifierData *md, } shrinkwrapModifier_deform( - swmd, ctx, scene, ctx->object, mesh_src, dvert, defgrp_index, vertexCos, numVerts); + swmd, ctx, scene, ctx->object, mesh_src, dvert, defgrp_index, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c index 4fbef6f54ae..e3c7f1c423b 100644 --- a/source/blender/modifiers/intern/MOD_simpledeform.c +++ b/source/blender/modifiers/intern/MOD_simpledeform.c @@ -288,7 +288,7 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object *ob, struct Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { int i; float smd_limit[2], smd_factor; @@ -355,7 +355,7 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, float lower = FLT_MAX; float upper = -FLT_MAX; - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { float tmp[3]; copy_v3_v3(tmp, vertexCos[i]); @@ -401,7 +401,7 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, /* Do deformation. */ TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - BLI_task_parallel_range(0, numVerts, (void *)&deform_pool_data, simple_helper, &settings); + BLI_task_parallel_range(0, verts_num, (void *)&deform_pool_data, simple_helper, &settings); } /* SimpleDeform */ @@ -446,17 +446,17 @@ static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, struct Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { SimpleDeformModifierData *sdmd = (SimpleDeformModifierData *)md; Mesh *mesh_src = NULL; if (ctx->object->type == OB_MESH && sdmd->vgroup_name[0] != '\0') { /* mesh_src is only needed for vgroups. */ - mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false); } - SimpleDeformModifier_do(sdmd, ctx, ctx->object, mesh_src, vertexCos, numVerts); + SimpleDeformModifier_do(sdmd, ctx, ctx->object, mesh_src, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); @@ -468,14 +468,15 @@ static void deformVertsEM(ModifierData *md, struct BMEditMesh *editData, struct Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { SimpleDeformModifierData *sdmd = (SimpleDeformModifierData *)md; Mesh *mesh_src = NULL; if (ctx->object->type == OB_MESH && sdmd->vgroup_name[0] != '\0') { /* mesh_src is only needed for vgroups. */ - mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get( + ctx->object, editData, mesh, NULL, verts_num, false, false); } /* TODO(Campbell): use edit-mode data only (remove this line). */ @@ -483,7 +484,7 @@ static void deformVertsEM(ModifierData *md, BKE_mesh_wrapper_ensure_mdata(mesh_src); } - SimpleDeformModifier_do(sdmd, ctx, ctx->object, mesh_src, vertexCos, numVerts); + SimpleDeformModifier_do(sdmd, ctx, ctx->object, mesh_src, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 6ab6dc5d4c8..b950578ff1b 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -649,14 +649,14 @@ static void connection_node_frames(int v, } static SkinNode *build_frames( - const MVert *mvert, int totvert, const MVertSkin *nodes, const MeshElemMap *emap, EMat *emat) + const MVert *mvert, int verts_num, const MVertSkin *nodes, const MeshElemMap *emap, EMat *emat) { SkinNode *skin_nodes; int v; - skin_nodes = MEM_calloc_arrayN(totvert, sizeof(SkinNode), "build_frames.skin_nodes"); + skin_nodes = MEM_calloc_arrayN(verts_num, sizeof(SkinNode), "build_frames.skin_nodes"); - for (v = 0; v < totvert; v++) { + for (v = 0; v < verts_num; v++) { if (emap[v].count <= 1) { end_node_frames(v, skin_nodes, mvert, nodes, emap, emat); } @@ -766,10 +766,10 @@ static void build_emats_stack(BLI_Stack *stack, static EMat *build_edge_mats(const MVertSkin *vs, const MVert *mvert, - int totvert, + const int verts_num, const MEdge *medge, const MeshElemMap *emap, - int totedge, + const int edges_num, bool *has_valid_root) { BLI_Stack *stack; @@ -780,12 +780,12 @@ static EMat *build_edge_mats(const MVertSkin *vs, stack = BLI_stack_new(sizeof(stack_elem), "build_edge_mats.stack"); - visited_e = BLI_BITMAP_NEW(totedge, "build_edge_mats.visited_e"); - emat = MEM_calloc_arrayN(totedge, sizeof(EMat), "build_edge_mats.emat"); + visited_e = BLI_BITMAP_NEW(edges_num, "build_edge_mats.visited_e"); + emat = MEM_calloc_arrayN(edges_num, sizeof(EMat), "build_edge_mats.emat"); /* Edge matrices are built from the root nodes, add all roots with * children to the stack */ - for (v = 0; v < totvert; v++) { + for (v = 0; v < verts_num; v++) { if (vs[v].flag & MVERT_SKIN_ROOT) { if (emap[v].count >= 1) { const MEdge *e = &medge[emap[v].indices[0]]; @@ -800,7 +800,7 @@ static EMat *build_edge_mats(const MVertSkin *vs, *has_valid_root = true; } - else if (totedge == 0) { + else if (edges_num == 0) { /* Vertex-only mesh is valid, mark valid root as well (will display error otherwise). */ *has_valid_root = true; break; @@ -837,7 +837,7 @@ static int calc_edge_subdivisions(const MVert *mvert, float avg_radius; const bool v1_branch = degree[e->v1] > 2; const bool v2_branch = degree[e->v2] > 2; - int num_subdivisions; + int subdivisions_num; /* If either end is a branch node marked 'loose', don't subdivide * the edge (or subdivide just twice if both are branches) */ @@ -854,27 +854,27 @@ static int calc_edge_subdivisions(const MVert *mvert, if (avg_radius != 0.0f) { /* possible (but unlikely) that we overflow INT_MAX */ - float num_subdivisions_fl; + float subdivisions_num_fl; const float edge_len = len_v3v3(mvert[e->v1].co, mvert[e->v2].co); - num_subdivisions_fl = (edge_len / avg_radius); - if (num_subdivisions_fl < NUM_SUBDIVISIONS_MAX) { - num_subdivisions = (int)num_subdivisions_fl; + subdivisions_num_fl = (edge_len / avg_radius); + if (subdivisions_num_fl < NUM_SUBDIVISIONS_MAX) { + subdivisions_num = (int)subdivisions_num_fl; } else { - num_subdivisions = NUM_SUBDIVISIONS_MAX; + subdivisions_num = NUM_SUBDIVISIONS_MAX; } } else { - num_subdivisions = 0; + subdivisions_num = 0; } /* If both ends are branch nodes, two intermediate nodes are * required */ - if (num_subdivisions < 2 && v1_branch && v2_branch) { - num_subdivisions = 2; + if (subdivisions_num < 2 && v1_branch && v2_branch) { + subdivisions_num = 2; } - return num_subdivisions; + return subdivisions_num; #undef NUM_SUBDIVISIONS_MAX } @@ -888,8 +888,8 @@ static Mesh *subdivide_base(Mesh *orig) MVert *origvert, *outvert; MEdge *origedge, *outedge, *e; MDeformVert *origdvert, *outdvert; - int totorigvert, totorigedge; - int totsubd, *degree, *edge_subd; + int orig_vert_num, orig_edge_num; + int subd_num, *degree, *edge_subd; int i, j, k, u, v; float radrat; @@ -897,29 +897,29 @@ static Mesh *subdivide_base(Mesh *orig) origvert = orig->mvert; origedge = orig->medge; origdvert = orig->dvert; - totorigvert = orig->totvert; - totorigedge = orig->totedge; + orig_vert_num = orig->totvert; + orig_edge_num = orig->totedge; /* Get degree of all vertices */ - degree = MEM_calloc_arrayN(totorigvert, sizeof(int), "degree"); - for (i = 0; i < totorigedge; i++) { + degree = MEM_calloc_arrayN(orig_vert_num, sizeof(int), "degree"); + for (i = 0; i < orig_edge_num; i++) { degree[origedge[i].v1]++; degree[origedge[i].v2]++; } /* Per edge, store how many subdivisions are needed */ - edge_subd = MEM_calloc_arrayN((uint)totorigedge, sizeof(int), "edge_subd"); - for (i = 0, totsubd = 0; i < totorigedge; i++) { + edge_subd = MEM_calloc_arrayN((uint)orig_edge_num, sizeof(int), "edge_subd"); + for (i = 0, subd_num = 0; i < orig_edge_num; i++) { edge_subd[i] += calc_edge_subdivisions(origvert, orignode, &origedge[i], degree); BLI_assert(edge_subd[i] >= 0); - totsubd += edge_subd[i]; + subd_num += edge_subd[i]; } MEM_freeN(degree); /* Allocate output mesh */ result = BKE_mesh_new_nomain_from_template( - orig, totorigvert + totsubd, totorigedge + totsubd, 0, 0, 0); + orig, orig_vert_num + subd_num, orig_edge_num + subd_num, 0, 0, 0); outvert = result->mvert; outedge = result->medge; @@ -927,16 +927,16 @@ static Mesh *subdivide_base(Mesh *orig) outdvert = result->dvert; /* Copy original vertex data */ - CustomData_copy_data(&orig->vdata, &result->vdata, 0, 0, totorigvert); + CustomData_copy_data(&orig->vdata, &result->vdata, 0, 0, orig_vert_num); /* Subdivide edges */ - for (i = 0, v = totorigvert; i < totorigedge; i++) { + for (i = 0, v = orig_vert_num; i < orig_edge_num; i++) { struct { /* Vertex group number */ int def_nr; float w1, w2; } *vgroups = NULL, *vg; - int totvgroup = 0; + int vgroups_num = 0; e = &origedge[i]; @@ -950,8 +950,8 @@ static Mesh *subdivide_base(Mesh *orig) vg = NULL; for (k = 0; k < dv2->totweight; k++) { if (dv1->dw[j].def_nr == dv2->dw[k].def_nr) { - vg = &vgroups[totvgroup]; - totvgroup++; + vg = &vgroups[vgroups_num]; + vgroups_num++; break; } } @@ -986,7 +986,7 @@ static Mesh *subdivide_base(Mesh *orig) interp_v3_v3v3(outnode[v].radius, orignode[e->v1].radius, orignode[e->v2].radius, t); /* Interpolate vertex group weights */ - for (k = 0; k < totvgroup; k++) { + for (k = 0; k < vgroups_num; k++) { float weight; vg = &vgroups[k]; @@ -1561,14 +1561,14 @@ static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd) } static void skin_merge_close_frame_verts(SkinNode *skin_nodes, - int totvert, + int verts_num, const MeshElemMap *emap, const MEdge *medge) { Frame **hull_frames; int v, tothullframe; - for (v = 0; v < totvert; v++) { + for (v = 0; v < verts_num; v++) { /* Only check branch nodes */ if (!skin_nodes[v].totframe) { hull_frames = collect_hull_frames(v, skin_nodes, emap, medge, &tothullframe); @@ -1578,11 +1578,11 @@ static void skin_merge_close_frame_verts(SkinNode *skin_nodes, } } -static void skin_update_merged_vertices(SkinNode *skin_nodes, int totvert) +static void skin_update_merged_vertices(SkinNode *skin_nodes, int verts_num) { int v; - for (v = 0; v < totvert; v++) { + for (v = 0; v < verts_num; v++) { SkinNode *sn = &skin_nodes[v]; int i, j; @@ -1601,11 +1601,11 @@ static void skin_update_merged_vertices(SkinNode *skin_nodes, int totvert) } } -static void skin_fix_hull_topology(BMesh *bm, SkinNode *skin_nodes, int totvert) +static void skin_fix_hull_topology(BMesh *bm, SkinNode *skin_nodes, int verts_num) { int v; - for (v = 0; v < totvert; v++) { + for (v = 0; v < verts_num; v++) { SkinNode *sn = &skin_nodes[v]; int j; @@ -1626,11 +1626,11 @@ static void skin_fix_hull_topology(BMesh *bm, SkinNode *skin_nodes, int totvert) } } -static void skin_output_end_nodes(SkinOutput *so, SkinNode *skin_nodes, int totvert) +static void skin_output_end_nodes(SkinOutput *so, SkinNode *skin_nodes, int verts_num) { int v; - for (v = 0; v < totvert; v++) { + for (v = 0; v < verts_num; v++) { SkinNode *sn = &skin_nodes[v]; /* Assuming here just two frames */ if (sn->flag & SEAM_FRAME) { @@ -1676,11 +1676,11 @@ static void skin_output_end_nodes(SkinOutput *so, SkinNode *skin_nodes, int totv static void skin_output_connections(SkinOutput *so, SkinNode *skin_nodes, const MEdge *medge, - int totedge) + int edges_num) { int e; - for (e = 0; e < totedge; e++) { + for (e = 0; e < edges_num; e++) { SkinNode *a, *b; a = &skin_nodes[medge[e].v1]; b = &skin_nodes[medge[e].v2]; @@ -1713,7 +1713,7 @@ static void skin_output_connections(SkinOutput *so, static void skin_smooth_hulls(BMesh *bm, SkinNode *skin_nodes, - int totvert, + int verts_num, const SkinModifierData *smd) { BMIter iter, eiter; @@ -1726,7 +1726,7 @@ static void skin_smooth_hulls(BMesh *bm, /* Mark all frame vertices */ BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false); - for (i = 0; i < totvert; i++) { + for (i = 0; i < verts_num; i++) { for (j = 0; j < skin_nodes[i].totframe; j++) { Frame *frame = &skin_nodes[i].frames[j]; @@ -1780,13 +1780,16 @@ static void skin_smooth_hulls(BMesh *bm, } /* Returns true if all hulls are successfully built, false otherwise */ -static bool skin_output_branch_hulls( - SkinOutput *so, SkinNode *skin_nodes, int totvert, const MeshElemMap *emap, const MEdge *medge) +static bool skin_output_branch_hulls(SkinOutput *so, + SkinNode *skin_nodes, + int verts_num, + const MeshElemMap *emap, + const MEdge *medge) { bool result = true; int v; - for (v = 0; v < totvert; v++) { + for (v = 0; v < verts_num; v++) { SkinNode *sn = &skin_nodes[v]; /* Branch node hulls */ @@ -1812,10 +1815,10 @@ typedef enum eSkinErrorFlag { } eSkinErrorFlag; static BMesh *build_skin(SkinNode *skin_nodes, - int totvert, + int verts_num, const MeshElemMap *emap, const MEdge *medge, - int totedge, + int edges_num, const MDeformVert *input_dvert, SkinModifierData *smd, eSkinErrorFlag *r_error) @@ -1841,19 +1844,19 @@ static BMesh *build_skin(SkinNode *skin_nodes, /* Check for mergeable frame corners around hulls before * outputting vertices */ - skin_merge_close_frame_verts(skin_nodes, totvert, emap, medge); + skin_merge_close_frame_verts(skin_nodes, verts_num, emap, medge); /* Write out all frame vertices to the mesh */ - for (v = 0; v < totvert; v++) { + for (v = 0; v < verts_num; v++) { if (skin_nodes[v].totframe) { output_frames(so.bm, &skin_nodes[v], input_dvert ? &input_dvert[v] : NULL); } } /* Update vertex pointers for merged frame corners */ - skin_update_merged_vertices(skin_nodes, totvert); + skin_update_merged_vertices(skin_nodes, verts_num); - if (!skin_output_branch_hulls(&so, skin_nodes, totvert, emap, medge)) { + if (!skin_output_branch_hulls(&so, skin_nodes, verts_num, emap, medge)) { *r_error |= SKIN_ERROR_HULL; } @@ -1871,12 +1874,12 @@ static BMesh *build_skin(SkinNode *skin_nodes, * creating all hull faces, but before creating any other * faces. */ - skin_fix_hull_topology(so.bm, skin_nodes, totvert); + skin_fix_hull_topology(so.bm, skin_nodes, verts_num); - skin_smooth_hulls(so.bm, skin_nodes, totvert, smd); + skin_smooth_hulls(so.bm, skin_nodes, verts_num, smd); - skin_output_end_nodes(&so, skin_nodes, totvert); - skin_output_connections(&so, skin_nodes, medge, totedge); + skin_output_end_nodes(&so, skin_nodes, verts_num); + skin_output_connections(&so, skin_nodes, medge, edges_num); hull_merge_triangles(&so, smd); bmesh_edit_end(so.bm, 0); @@ -1912,7 +1915,7 @@ static Mesh *base_skin(Mesh *origmesh, SkinModifierData *smd, eSkinErrorFlag *r_ MVert *mvert; MEdge *medge; MDeformVert *dvert; - int totvert, totedge; + int verts_num, edges_num; bool has_valid_root = false; nodes = CustomData_get_layer(&origmesh->vdata, CD_MVERT_SKIN); @@ -1920,17 +1923,17 @@ static Mesh *base_skin(Mesh *origmesh, SkinModifierData *smd, eSkinErrorFlag *r_ mvert = origmesh->mvert; dvert = origmesh->dvert; medge = origmesh->medge; - totvert = origmesh->totvert; - totedge = origmesh->totedge; + verts_num = origmesh->totvert; + edges_num = origmesh->totedge; - BKE_mesh_vert_edge_map_create(&emap, &emapmem, medge, totvert, totedge); + BKE_mesh_vert_edge_map_create(&emap, &emapmem, medge, verts_num, edges_num); - emat = build_edge_mats(nodes, mvert, totvert, medge, emap, totedge, &has_valid_root); - skin_nodes = build_frames(mvert, totvert, nodes, emap, emat); + emat = build_edge_mats(nodes, mvert, verts_num, medge, emap, edges_num, &has_valid_root); + skin_nodes = build_frames(mvert, verts_num, nodes, emap, emat); MEM_freeN(emat); emat = NULL; - bm = build_skin(skin_nodes, totvert, emap, medge, totedge, dvert, smd, r_error); + bm = build_skin(skin_nodes, verts_num, emap, medge, edges_num, dvert, smd, r_error); MEM_freeN(skin_nodes); MEM_freeN(emap); diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c index 4236147c1f3..5439083d9a7 100644 --- a/source/blender/modifiers/intern/MOD_smooth.c +++ b/source/blender/modifiers/intern/MOD_smooth.c @@ -76,21 +76,21 @@ static void requiredDataMask(Object *UNUSED(ob), } static void smoothModifier_do( - SmoothModifierData *smd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int numVerts) + SmoothModifierData *smd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int verts_num) { if (mesh == NULL) { return; } float(*accumulated_vecs)[3] = MEM_calloc_arrayN( - (size_t)numVerts, sizeof(*accumulated_vecs), __func__); + (size_t)verts_num, sizeof(*accumulated_vecs), __func__); if (!accumulated_vecs) { return; } - uint *num_accumulated_vecs = MEM_calloc_arrayN( - (size_t)numVerts, sizeof(*num_accumulated_vecs), __func__); - if (!num_accumulated_vecs) { + uint *accumulated_vecs_count = MEM_calloc_arrayN( + (size_t)verts_num, sizeof(*accumulated_vecs_count), __func__); + if (!accumulated_vecs_count) { MEM_freeN(accumulated_vecs); return; } @@ -100,7 +100,7 @@ static void smoothModifier_do( const bool invert_vgroup = (smd->flag & MOD_SMOOTH_INVERT_VGROUP) != 0; MEdge *medges = mesh->medge; - const int num_edges = mesh->totedge; + const int edges_num = mesh->totedge; MDeformVert *dvert; int defgrp_index; @@ -108,31 +108,31 @@ static void smoothModifier_do( for (int j = 0; j < smd->repeat; j++) { if (j != 0) { - memset(accumulated_vecs, 0, sizeof(*accumulated_vecs) * (size_t)numVerts); - memset(num_accumulated_vecs, 0, sizeof(*num_accumulated_vecs) * (size_t)numVerts); + memset(accumulated_vecs, 0, sizeof(*accumulated_vecs) * (size_t)verts_num); + memset(accumulated_vecs_count, 0, sizeof(*accumulated_vecs_count) * (size_t)verts_num); } - for (int i = 0; i < num_edges; i++) { + for (int i = 0; i < edges_num; i++) { float fvec[3]; const uint idx1 = medges[i].v1; const uint idx2 = medges[i].v2; mid_v3_v3v3(fvec, vertexCos[idx1], vertexCos[idx2]); - num_accumulated_vecs[idx1]++; + accumulated_vecs_count[idx1]++; add_v3_v3(accumulated_vecs[idx1], fvec); - num_accumulated_vecs[idx2]++; + accumulated_vecs_count[idx2]++; add_v3_v3(accumulated_vecs[idx2], fvec); } const short flag = smd->flag; if (dvert) { MDeformVert *dv = dvert; - for (int i = 0; i < numVerts; i++, dv++) { + for (int i = 0; i < verts_num; i++, dv++) { float *vco_orig = vertexCos[i]; - if (num_accumulated_vecs[i] > 0) { - mul_v3_fl(accumulated_vecs[i], 1.0f / (float)num_accumulated_vecs[i]); + if (accumulated_vecs_count[i] > 0) { + mul_v3_fl(accumulated_vecs[i], 1.0f / (float)accumulated_vecs_count[i]); } float *vco_new = accumulated_vecs[i]; @@ -156,10 +156,10 @@ static void smoothModifier_do( } } else { /* no vertex group */ - for (int i = 0; i < numVerts; i++) { + for (int i = 0; i < verts_num; i++) { float *vco_orig = vertexCos[i]; - if (num_accumulated_vecs[i] > 0) { - mul_v3_fl(accumulated_vecs[i], 1.0f / (float)num_accumulated_vecs[i]); + if (accumulated_vecs_count[i] > 0) { + mul_v3_fl(accumulated_vecs[i], 1.0f / (float)accumulated_vecs_count[i]); } float *vco_new = accumulated_vecs[i]; @@ -177,22 +177,22 @@ static void smoothModifier_do( } MEM_freeN(accumulated_vecs); - MEM_freeN(num_accumulated_vecs); + MEM_freeN(accumulated_vecs_count); } static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { SmoothModifierData *smd = (SmoothModifierData *)md; Mesh *mesh_src = NULL; /* mesh_src is needed for vgroups, and taking edges into account. */ - mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false); - smoothModifier_do(smd, ctx->object, mesh_src, vertexCos, numVerts); + smoothModifier_do(smd, ctx->object, mesh_src, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); @@ -204,18 +204,18 @@ static void deformVertsEM(ModifierData *md, struct BMEditMesh *editData, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { SmoothModifierData *smd = (SmoothModifierData *)md; Mesh *mesh_src = NULL; /* mesh_src is needed for vgroups, and taking edges into account. */ - mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, verts_num, false, false); /* TODO(campbell): use edit-mode data only (remove this line). */ BKE_mesh_wrapper_ensure_mdata(mesh_src); - smoothModifier_do(smd, ctx->object, mesh_src, vertexCos, numVerts); + smoothModifier_do(smd, ctx->object, mesh_src, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c index ae90240dd3f..d8379cc870a 100644 --- a/source/blender/modifiers/intern/MOD_softbody.c +++ b/source/blender/modifiers/intern/MOD_softbody.c @@ -40,16 +40,14 @@ static void deformVerts(ModifierData *UNUSED(md), const ModifierEvalContext *ctx, Mesh *UNUSED(derivedData), float (*vertexCos)[3], - int numVerts) + int verts_num) { Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); sbObjectStep( - ctx->depsgraph, scene, ctx->object, DEG_get_ctime(ctx->depsgraph), vertexCos, numVerts); + ctx->depsgraph, scene, ctx->object, DEG_get_ctime(ctx->depsgraph), vertexCos, verts_num); } -static bool dependsOnTime(struct Scene *UNUSED(scene), - ModifierData *UNUSED(md), - const int UNUSED(dag_eval_mode)) +static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md)) { return true; } diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.c b/source/blender/modifiers/intern/MOD_solidify_extrude.c index fdaf7bd41d1..80af23054e4 100644 --- a/source/blender/modifiers/intern/MOD_solidify_extrude.c +++ b/source/blender/modifiers/intern/MOD_solidify_extrude.c @@ -55,14 +55,14 @@ BLI_INLINE bool edgeref_is_init(const EdgeFaceRef *edge_ref) */ static void mesh_calc_hq_normal(Mesh *mesh, const float (*poly_nors)[3], float (*r_vert_nors)[3]) { - int i, numVerts, numEdges, numPolys; + int i, verts_num, edges_num, polys_num; MPoly *mpoly, *mp; MLoop *mloop, *ml; MEdge *medge, *ed; - numVerts = mesh->totvert; - numEdges = mesh->totedge; - numPolys = mesh->totpoly; + verts_num = mesh->totvert; + edges_num = mesh->totedge; + polys_num = mesh->totpoly; mpoly = mesh->mpoly; medge = mesh->medge; mloop = mesh->mloop; @@ -71,7 +71,7 @@ static void mesh_calc_hq_normal(Mesh *mesh, const float (*poly_nors)[3], float ( /* Doesn't work here! */ #if 0 - mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, numVerts); + mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, verts_num); cddm->mvert = mv; #endif @@ -79,12 +79,12 @@ static void mesh_calc_hq_normal(Mesh *mesh, const float (*poly_nors)[3], float ( { EdgeFaceRef *edge_ref_array = MEM_calloc_arrayN( - (size_t)numEdges, sizeof(EdgeFaceRef), "Edge Connectivity"); + (size_t)edges_num, sizeof(EdgeFaceRef), "Edge Connectivity"); EdgeFaceRef *edge_ref; float edge_normal[3]; /* Add an edge reference if it's not there, pointing back to the face index. */ - for (i = 0; i < numPolys; i++, mp++) { + for (i = 0; i < polys_num; i++, mp++) { int j; ml = mloop + mp->loopstart; @@ -110,7 +110,7 @@ static void mesh_calc_hq_normal(Mesh *mesh, const float (*poly_nors)[3], float ( } } - for (i = 0, ed = medge, edge_ref = edge_ref_array; i < numEdges; i++, ed++, edge_ref++) { + for (i = 0, ed = medge, edge_ref = edge_ref_array; i < edges_num; i++, ed++, edge_ref++) { /* Get the edge vert indices, and edge value (the face indices that use it) */ if (edgeref_is_init(edge_ref) && (edge_ref->p1 != -1)) { @@ -141,7 +141,7 @@ static void mesh_calc_hq_normal(Mesh *mesh, const float (*poly_nors)[3], float ( /* normalize vertex normals and assign */ const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh); - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { if (normalize_v3(r_vert_nors[i]) == 0.0f) { copy_v3_v3(r_vert_nors[i], vert_normals[i]); } @@ -164,10 +164,10 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex MEdge *ed, *medge, *orig_medge; MLoop *ml, *mloop, *orig_mloop; MPoly *mp, *mpoly, *orig_mpoly; - const uint numVerts = (uint)mesh->totvert; - const uint numEdges = (uint)mesh->totedge; - const uint numPolys = (uint)mesh->totpoly; - const uint numLoops = (uint)mesh->totloop; + const uint verts_num = (uint)mesh->totvert; + const uint edges_num = (uint)mesh->totedge; + const uint polys_num = (uint)mesh->totpoly; + const uint loops_num = (uint)mesh->totloop; uint newLoops = 0, newPolys = 0, newEdges = 0, newVerts = 0, rimVerts = 0; /* Only use material offsets if we have 2 or more materials. */ @@ -184,7 +184,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex STACK_DECLARE(new_edge_arr); uint *old_vert_arr = MEM_calloc_arrayN( - numVerts, sizeof(*old_vert_arr), "old_vert_arr in solidify"); + verts_num, sizeof(*old_vert_arr), "old_vert_arr in solidify"); uint *edge_users = NULL; int *edge_order = NULL; @@ -233,33 +233,34 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex poly_nors = BKE_mesh_poly_normals_ensure(mesh); } - STACK_INIT(new_vert_arr, numVerts * 2); - STACK_INIT(new_edge_arr, numEdges * 2); + STACK_INIT(new_vert_arr, verts_num * 2); + STACK_INIT(new_edge_arr, edges_num * 2); if (do_rim) { - BLI_bitmap *orig_mvert_tag = BLI_BITMAP_NEW(numVerts, __func__); + BLI_bitmap *orig_mvert_tag = BLI_BITMAP_NEW(verts_num, __func__); uint eidx; uint i; #define INVALID_UNUSED ((uint)-1) #define INVALID_PAIR ((uint)-2) - new_vert_arr = MEM_malloc_arrayN(numVerts, 2 * sizeof(*new_vert_arr), __func__); - new_edge_arr = MEM_malloc_arrayN(((numEdges * 2) + numVerts), sizeof(*new_edge_arr), __func__); + new_vert_arr = MEM_malloc_arrayN(verts_num, 2 * sizeof(*new_vert_arr), __func__); + new_edge_arr = MEM_malloc_arrayN( + ((edges_num * 2) + verts_num), sizeof(*new_edge_arr), __func__); - edge_users = MEM_malloc_arrayN(numEdges, sizeof(*edge_users), "solid_mod edges"); - edge_order = MEM_malloc_arrayN(numEdges, sizeof(*edge_order), "solid_mod order"); + edge_users = MEM_malloc_arrayN(edges_num, sizeof(*edge_users), "solid_mod edges"); + edge_order = MEM_malloc_arrayN(edges_num, sizeof(*edge_order), "solid_mod order"); /* save doing 2 loops here... */ #if 0 - copy_vn_i(edge_users, numEdges, INVALID_UNUSED); + copy_vn_i(edge_users, edges_num, INVALID_UNUSED); #endif - for (eidx = 0, ed = orig_medge; eidx < numEdges; eidx++, ed++) { + for (eidx = 0, ed = orig_medge; eidx < edges_num; eidx++, ed++) { edge_users[eidx] = INVALID_UNUSED; } - for (i = 0, mp = orig_mpoly; i < numPolys; i++, mp++) { + for (i = 0, mp = orig_mpoly; i < polys_num; i++, mp++) { MLoop *ml_prev; int j; @@ -272,7 +273,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex if (edge_users[eidx] == INVALID_UNUSED) { ed = orig_medge + eidx; BLI_assert(ELEM(ml_prev->v, ed->v1, ed->v2) && ELEM(ml->v, ed->v1, ed->v2)); - edge_users[eidx] = (ml_prev->v > ml->v) == (ed->v1 < ed->v2) ? i : (i + numPolys); + edge_users[eidx] = (ml_prev->v > ml->v) == (ed->v1 < ed->v2) ? i : (i + polys_num); edge_order[eidx] = j; } else { @@ -282,7 +283,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex } } - for (eidx = 0, ed = orig_medge; eidx < numEdges; eidx++, ed++) { + for (eidx = 0, ed = orig_medge; eidx < edges_num; eidx++, ed++) { if (!ELEM(edge_users[eidx], INVALID_UNUSED, INVALID_PAIR)) { BLI_BITMAP_ENABLE(orig_mvert_tag, ed->v1); BLI_BITMAP_ENABLE(orig_mvert_tag, ed->v2); @@ -292,7 +293,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex } } - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { if (BLI_BITMAP_TEST(orig_mvert_tag, i)) { old_vert_arr[i] = STACK_SIZE(new_vert_arr); STACK_PUSH(new_vert_arr, i); @@ -319,16 +320,16 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex } if (smd->flag & MOD_SOLIDIFY_NORMAL_CALC) { - vert_nors = MEM_calloc_arrayN(numVerts, sizeof(float[3]), "mod_solid_vno_hq"); + vert_nors = MEM_calloc_arrayN(verts_num, sizeof(float[3]), "mod_solid_vno_hq"); mesh_calc_hq_normal(mesh, poly_nors, vert_nors); } result = BKE_mesh_new_nomain_from_template(mesh, - (int)((numVerts * stride) + newVerts), - (int)((numEdges * stride) + newEdges + rimVerts), + (int)((verts_num * stride) + newVerts), + (int)((edges_num * stride) + newEdges + rimVerts), 0, - (int)((numLoops * stride) + newLoops), - (int)((numPolys * stride) + newPolys)); + (int)((loops_num * stride) + newLoops), + (int)((polys_num * stride) + newPolys)); mpoly = result->mpoly; mloop = result->mloop; @@ -341,69 +342,69 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex } if (do_shell) { - CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, (int)numVerts); - CustomData_copy_data(&mesh->vdata, &result->vdata, 0, (int)numVerts, (int)numVerts); + CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, (int)verts_num); + CustomData_copy_data(&mesh->vdata, &result->vdata, 0, (int)verts_num, (int)verts_num); - CustomData_copy_data(&mesh->edata, &result->edata, 0, 0, (int)numEdges); - CustomData_copy_data(&mesh->edata, &result->edata, 0, (int)numEdges, (int)numEdges); + CustomData_copy_data(&mesh->edata, &result->edata, 0, 0, (int)edges_num); + CustomData_copy_data(&mesh->edata, &result->edata, 0, (int)edges_num, (int)edges_num); - CustomData_copy_data(&mesh->ldata, &result->ldata, 0, 0, (int)numLoops); + CustomData_copy_data(&mesh->ldata, &result->ldata, 0, 0, (int)loops_num); /* DO NOT copy here the 'copied' part of loop data, we want to reverse loops * (so that winding of copied face get reversed, so that normals get reversed * and point in expected direction...). * If we also copy data here, then this data get overwritten * (and allocated memory becomes memleak). */ - CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, (int)numPolys); - CustomData_copy_data(&mesh->pdata, &result->pdata, 0, (int)numPolys, (int)numPolys); + CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, (int)polys_num); + CustomData_copy_data(&mesh->pdata, &result->pdata, 0, (int)polys_num, (int)polys_num); } else { int i, j; - CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, (int)numVerts); - for (i = 0, j = (int)numVerts; i < numVerts; i++) { + CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, (int)verts_num); + for (i = 0, j = (int)verts_num; i < verts_num; i++) { if (old_vert_arr[i] != INVALID_UNUSED) { CustomData_copy_data(&mesh->vdata, &result->vdata, i, j, 1); j++; } } - CustomData_copy_data(&mesh->edata, &result->edata, 0, 0, (int)numEdges); + CustomData_copy_data(&mesh->edata, &result->edata, 0, 0, (int)edges_num); - for (i = 0, j = (int)numEdges; i < numEdges; i++) { + for (i = 0, j = (int)edges_num; i < edges_num; i++) { if (!ELEM(edge_users[i], INVALID_UNUSED, INVALID_PAIR)) { MEdge *ed_src, *ed_dst; CustomData_copy_data(&mesh->edata, &result->edata, i, j, 1); ed_src = &medge[i]; ed_dst = &medge[j]; - ed_dst->v1 = old_vert_arr[ed_src->v1] + numVerts; - ed_dst->v2 = old_vert_arr[ed_src->v2] + numVerts; + ed_dst->v1 = old_vert_arr[ed_src->v1] + verts_num; + ed_dst->v2 = old_vert_arr[ed_src->v2] + verts_num; j++; } } /* will be created later */ - CustomData_copy_data(&mesh->ldata, &result->ldata, 0, 0, (int)numLoops); - CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, (int)numPolys); + CustomData_copy_data(&mesh->ldata, &result->ldata, 0, 0, (int)loops_num); + CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, (int)polys_num); } /* initializes: (i_end, do_shell_align, mv). */ #define INIT_VERT_ARRAY_OFFSETS(test) \ if (((ofs_new >= ofs_orig) == do_flip) == test) { \ - i_end = numVerts; \ + i_end = verts_num; \ do_shell_align = true; \ mv = mvert; \ } \ else { \ if (do_shell) { \ - i_end = numVerts; \ + i_end = verts_num; \ do_shell_align = true; \ } \ else { \ i_end = newVerts; \ do_shell_align = false; \ } \ - mv = &mvert[numVerts]; \ + mv = &mvert[verts_num]; \ } \ (void)0 @@ -412,7 +413,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex if (do_shell) { uint i; - mp = mpoly + numPolys; + mp = mpoly + polys_num; for (i = 0; i < mesh->totpoly; i++, mp++) { const int loop_end = mp->totloop - 1; MLoop *ml2; @@ -457,14 +458,14 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex mp->loopstart += mesh->totloop; for (j = 0; j < mp->totloop; j++) { - ml2[j].e += numEdges; - ml2[j].v += numVerts; + ml2[j].e += edges_num; + ml2[j].v += verts_num; } } - for (i = 0, ed = medge + numEdges; i < numEdges; i++, ed++) { - ed->v1 += numVerts; - ed->v2 += numVerts; + for (i = 0, ed = medge + edges_num; i < edges_num; i++, ed++) { + ed->v1 += verts_num; + ed->v2 += verts_num; } } @@ -483,9 +484,9 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex float *edge_angs = NULL; if (do_clamp) { - vert_lens = MEM_malloc_arrayN(numVerts, sizeof(float), "vert_lens"); - copy_vn_fl(vert_lens, (int)numVerts, FLT_MAX); - for (uint i = 0; i < numEdges; i++) { + vert_lens = MEM_malloc_arrayN(verts_num, sizeof(float), "vert_lens"); + copy_vn_fl(vert_lens, (int)verts_num, FLT_MAX); + for (uint i = 0; i < edges_num; i++) { const float ed_len_sq = len_squared_v3v3(mvert[medge[i].v1].co, mvert[medge[i].v2].co); vert_lens[medge[i].v1] = min_ff(vert_lens[medge[i].v1], ed_len_sq); vert_lens[medge[i].v2] = min_ff(vert_lens[medge[i].v2], ed_len_sq); @@ -495,23 +496,23 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex if (do_angle_clamp || do_bevel_convex) { uint eidx; if (do_angle_clamp) { - vert_angs = MEM_malloc_arrayN(numVerts, sizeof(float), "vert_angs"); - copy_vn_fl(vert_angs, (int)numVerts, 0.5f * M_PI); + vert_angs = MEM_malloc_arrayN(verts_num, sizeof(float), "vert_angs"); + copy_vn_fl(vert_angs, (int)verts_num, 0.5f * M_PI); } if (do_bevel_convex) { - edge_angs = MEM_malloc_arrayN(numEdges, sizeof(float), "edge_angs"); + edge_angs = MEM_malloc_arrayN(edges_num, sizeof(float), "edge_angs"); if (!do_rim) { - edge_users = MEM_malloc_arrayN(numEdges, sizeof(*edge_users), "solid_mod edges"); + edge_users = MEM_malloc_arrayN(edges_num, sizeof(*edge_users), "solid_mod edges"); } } uint(*edge_user_pairs)[2] = MEM_malloc_arrayN( - numEdges, sizeof(*edge_user_pairs), "edge_user_pairs"); - for (eidx = 0; eidx < numEdges; eidx++) { + edges_num, sizeof(*edge_user_pairs), "edge_user_pairs"); + for (eidx = 0; eidx < edges_num; eidx++) { edge_user_pairs[eidx][0] = INVALID_UNUSED; edge_user_pairs[eidx][1] = INVALID_UNUSED; } mp = orig_mpoly; - for (uint i = 0; i < numPolys; i++, mp++) { + for (uint i = 0; i < polys_num; i++, mp++) { ml = orig_mloop + mp->loopstart; MLoop *ml_prev = ml + (mp->totloop - 1); @@ -533,7 +534,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex } ed = orig_medge; float e[3]; - for (uint i = 0; i < numEdges; i++, ed++) { + for (uint i = 0; i < edges_num; i++, ed++) { if (!ELEM(edge_user_pairs[i][0], INVALID_UNUSED, INVALID_PAIR) && !ELEM(edge_user_pairs[i][1], INVALID_UNUSED, INVALID_PAIR)) { const float *n0 = poly_nors[edge_user_pairs[i][0]]; @@ -658,7 +659,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex } if (do_bevel_convex) { - for (uint i = 0; i < numEdges; i++) { + for (uint i = 0; i < edges_num; i++) { if (edge_users[i] == INVALID_PAIR) { float angle = edge_angs[i]; medge[i].bweight = (char)clamp_i( @@ -668,8 +669,8 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex 0, 255); if (do_shell) { - medge[i + numEdges].bweight = (char)clamp_i( - (int)medge[i + numEdges].bweight + + medge[i + edges_num].bweight = (char)clamp_i( + (int)medge[i + edges_num].bweight + (int)((angle > M_PI ? clamp_f(bevel_convex, 0.0f, 1.0f) : clamp_f(bevel_convex, -1.0f, 0.0f)) * 255), @@ -697,19 +698,19 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex #endif /* same as EM_solidify() in editmesh_lib.c */ float *vert_angles = MEM_calloc_arrayN( - numVerts, sizeof(float[2]), "mod_solid_pair"); /* 2 in 1 */ - float *vert_accum = vert_angles + numVerts; + verts_num, sizeof(float[2]), "mod_solid_pair"); /* 2 in 1 */ + float *vert_accum = vert_angles + verts_num; uint vidx; uint i; if (vert_nors == NULL) { - vert_nors = MEM_malloc_arrayN(numVerts, sizeof(float[3]), "mod_solid_vno"); - for (i = 0, mv = mvert; i < numVerts; i++, mv++) { + vert_nors = MEM_malloc_arrayN(verts_num, sizeof(float[3]), "mod_solid_vno"); + for (i = 0, mv = mvert; i < verts_num; i++, mv++) { copy_v3_v3(vert_nors[i], mesh_vert_normals[i]); } } - for (i = 0, mp = mpoly; i < numPolys; i++, mp++) { + for (i = 0, mp = mpoly; i < polys_num; i++, mp++) { /* #BKE_mesh_calc_poly_angles logic is inlined here */ float nor_prev[3]; float nor_next[3]; @@ -765,14 +766,14 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex float scalar; if (defgrp_invert) { - for (i = 0; i < numVerts; i++, dv++) { + for (i = 0; i < verts_num; i++, dv++) { scalar = 1.0f - BKE_defvert_find_weight(dv, defgrp_index); scalar = offset_fac_vg + (scalar * offset_fac_vg_inv); vert_angles[i] *= scalar; } } else { - for (i = 0; i < numVerts; i++, dv++) { + for (i = 0; i < verts_num; i++, dv++) { scalar = BKE_defvert_find_weight(dv, defgrp_index); scalar = offset_fac_vg + (scalar * offset_fac_vg_inv); vert_angles[i] *= scalar; @@ -788,22 +789,22 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex if (do_angle_clamp || do_bevel_convex) { uint eidx; if (do_angle_clamp) { - vert_angs = MEM_malloc_arrayN(numVerts, sizeof(float), "vert_angs even"); - copy_vn_fl(vert_angs, (int)numVerts, 0.5f * M_PI); + vert_angs = MEM_malloc_arrayN(verts_num, sizeof(float), "vert_angs even"); + copy_vn_fl(vert_angs, (int)verts_num, 0.5f * M_PI); } if (do_bevel_convex) { - edge_angs = MEM_malloc_arrayN(numEdges, sizeof(float), "edge_angs even"); + edge_angs = MEM_malloc_arrayN(edges_num, sizeof(float), "edge_angs even"); if (!do_rim) { - edge_users = MEM_malloc_arrayN(numEdges, sizeof(*edge_users), "solid_mod edges"); + edge_users = MEM_malloc_arrayN(edges_num, sizeof(*edge_users), "solid_mod edges"); } } uint(*edge_user_pairs)[2] = MEM_malloc_arrayN( - numEdges, sizeof(*edge_user_pairs), "edge_user_pairs"); - for (eidx = 0; eidx < numEdges; eidx++) { + edges_num, sizeof(*edge_user_pairs), "edge_user_pairs"); + for (eidx = 0; eidx < edges_num; eidx++) { edge_user_pairs[eidx][0] = INVALID_UNUSED; edge_user_pairs[eidx][1] = INVALID_UNUSED; } - for (i = 0, mp = orig_mpoly; i < numPolys; i++, mp++) { + for (i = 0, mp = orig_mpoly; i < polys_num; i++, mp++) { ml = orig_mloop + mp->loopstart; MLoop *ml_prev = ml + (mp->totloop - 1); @@ -825,7 +826,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex } ed = orig_medge; float e[3]; - for (i = 0; i < numEdges; i++, ed++) { + for (i = 0; i < edges_num; i++, ed++) { if (!ELEM(edge_user_pairs[i][0], INVALID_UNUSED, INVALID_PAIR) && !ELEM(edge_user_pairs[i][1], INVALID_UNUSED, INVALID_PAIR)) { const float *n0 = poly_nors[edge_user_pairs[i][0]]; @@ -852,16 +853,16 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex const float clamp_fac = 1 + (do_angle_clamp ? fabsf(smd->offset_fac) : 0); const float offset = fabsf(smd->offset) * smd->offset_clamp * clamp_fac; if (offset > FLT_EPSILON) { - float *vert_lens_sq = MEM_malloc_arrayN(numVerts, sizeof(float), "vert_lens_sq"); + float *vert_lens_sq = MEM_malloc_arrayN(verts_num, sizeof(float), "vert_lens_sq"); const float offset_sq = offset * offset; - copy_vn_fl(vert_lens_sq, (int)numVerts, FLT_MAX); - for (i = 0; i < numEdges; i++) { + copy_vn_fl(vert_lens_sq, (int)verts_num, FLT_MAX); + for (i = 0; i < edges_num; i++) { const float ed_len = len_squared_v3v3(mvert[medge[i].v1].co, mvert[medge[i].v2].co); vert_lens_sq[medge[i].v1] = min_ff(vert_lens_sq[medge[i].v1], ed_len); vert_lens_sq[medge[i].v2] = min_ff(vert_lens_sq[medge[i].v2], ed_len); } if (do_angle_clamp) { - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { float cos_ang = cosf(vert_angs[i] * 0.5f); if (cos_ang > 0) { float max_off = sqrtf(vert_lens_sq[i]) * 0.5f / cos_ang; @@ -873,7 +874,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex MEM_freeN(vert_angs); } else { - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { if (vert_lens_sq[i] < offset_sq) { float scalar = sqrtf(vert_lens_sq[i]) / offset; vert_angles[i] *= scalar; @@ -885,7 +886,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex } if (do_bevel_convex) { - for (i = 0; i < numEdges; i++) { + for (i = 0; i < edges_num; i++) { if (edge_users[i] == INVALID_PAIR) { float angle = edge_angs[i]; medge[i].bweight = (char)clamp_i( @@ -895,8 +896,8 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex 0, 255); if (do_shell) { - medge[i + numEdges].bweight = (char)clamp_i( - (int)medge[i + numEdges].bweight + + medge[i + edges_num].bweight = (char)clamp_i( + (int)medge[i + edges_num].bweight + (int)((angle > M_PI ? clamp_f(bevel_convex, 0, 1) : clamp_f(bevel_convex, -1, 0)) * 255), @@ -959,8 +960,8 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex else if (do_shell) { uint i; /* flip vertex normals for copied verts */ - mv = mvert + numVerts; - for (i = 0; i < numVerts; i++) { + mv = mvert + verts_num; + for (i = 0; i < verts_num; i++) { negate_v3((float *)mesh_vert_normals[i]); } } @@ -982,14 +983,14 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex for (uint i = 0; i < rimVerts; i++) { BKE_defvert_ensure_index(&result->dvert[new_vert_arr[i]], rim_defgrp_index)->weight = 1.0f; - BKE_defvert_ensure_index(&result->dvert[(do_shell ? new_vert_arr[i] : i) + numVerts], + BKE_defvert_ensure_index(&result->dvert[(do_shell ? new_vert_arr[i] : i) + verts_num], rim_defgrp_index) ->weight = 1.0f; } } if (shell_defgrp_index != -1) { - for (uint i = numVerts; i < result->totvert; i++) { + for (uint i = verts_num; i < result->totvert; i++) { BKE_defvert_ensure_index(&result->dvert[i], shell_defgrp_index)->weight = 1.0f; } } @@ -1014,7 +1015,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex const bool do_side_normals = !BKE_mesh_vertex_normals_are_dirty(result); /* annoying to allocate these since we only need the edge verts, */ float(*edge_vert_nos)[3] = do_side_normals ? - MEM_calloc_arrayN(numVerts, sizeof(float[3]), __func__) : + MEM_calloc_arrayN(verts_num, sizeof(float[3]), __func__) : NULL; float nor[3]; #endif @@ -1032,11 +1033,11 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex /* add faces & edges */ origindex_edge = CustomData_get_layer(&result->edata, CD_ORIGINDEX); - orig_ed = (origindex_edge) ? &origindex_edge[(numEdges * stride) + newEdges] : NULL; - ed = &medge[(numEdges * stride) + newEdges]; /* start after copied edges */ + orig_ed = (origindex_edge) ? &origindex_edge[(edges_num * stride) + newEdges] : NULL; + ed = &medge[(edges_num * stride) + newEdges]; /* start after copied edges */ for (i = 0; i < rimVerts; i++, ed++) { ed->v1 = new_vert_arr[i]; - ed->v2 = (do_shell ? new_vert_arr[i] : i) + numVerts; + ed->v2 = (do_shell ? new_vert_arr[i] : i) + verts_num; ed->flag |= ME_EDGEDRAW | ME_EDGERENDER; if (orig_ed) { @@ -1050,8 +1051,8 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex } /* faces */ - mp = mpoly + (numPolys * stride); - ml = mloop + (numLoops * stride); + mp = mpoly + (polys_num * stride); + ml = mloop + (loops_num * stride); j = 0; for (i = 0; i < newPolys; i++, mp++) { uint eidx = new_edge_arr[i]; @@ -1059,8 +1060,8 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex int k1, k2; bool flip; - if (pidx >= numPolys) { - pidx -= numPolys; + if (pidx >= polys_num) { + pidx -= polys_num; flip = true; } else { @@ -1071,8 +1072,8 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex /* copy most of the face settings */ CustomData_copy_data( - &mesh->pdata, &result->pdata, (int)pidx, (int)((numPolys * stride) + i), 1); - mp->loopstart = (int)(j + (numLoops * stride)); + &mesh->pdata, &result->pdata, (int)pidx, (int)((polys_num * stride) + i), 1); + mp->loopstart = (int)(j + (loops_num * stride)); mp->flag = mpoly[pidx].flag; /* notice we use 'mp->totloop' which is later overwritten, @@ -1087,39 +1088,39 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex mp->totloop = 4; CustomData_copy_data( - &mesh->ldata, &result->ldata, k2, (int)((numLoops * stride) + j + 0), 1); + &mesh->ldata, &result->ldata, k2, (int)((loops_num * stride) + j + 0), 1); CustomData_copy_data( - &mesh->ldata, &result->ldata, k1, (int)((numLoops * stride) + j + 1), 1); + &mesh->ldata, &result->ldata, k1, (int)((loops_num * stride) + j + 1), 1); CustomData_copy_data( - &mesh->ldata, &result->ldata, k1, (int)((numLoops * stride) + j + 2), 1); + &mesh->ldata, &result->ldata, k1, (int)((loops_num * stride) + j + 2), 1); CustomData_copy_data( - &mesh->ldata, &result->ldata, k2, (int)((numLoops * stride) + j + 3), 1); + &mesh->ldata, &result->ldata, k2, (int)((loops_num * stride) + j + 3), 1); if (flip == false) { ml[j].v = ed->v1; ml[j++].e = eidx; ml[j].v = ed->v2; - ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v2] + newEdges; + ml[j++].e = (edges_num * stride) + old_vert_arr[ed->v2] + newEdges; - ml[j].v = (do_shell ? ed->v2 : old_vert_arr[ed->v2]) + numVerts; - ml[j++].e = (do_shell ? eidx : i) + numEdges; + ml[j].v = (do_shell ? ed->v2 : old_vert_arr[ed->v2]) + verts_num; + ml[j++].e = (do_shell ? eidx : i) + edges_num; - ml[j].v = (do_shell ? ed->v1 : old_vert_arr[ed->v1]) + numVerts; - ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v1] + newEdges; + ml[j].v = (do_shell ? ed->v1 : old_vert_arr[ed->v1]) + verts_num; + ml[j++].e = (edges_num * stride) + old_vert_arr[ed->v1] + newEdges; } else { ml[j].v = ed->v2; ml[j++].e = eidx; ml[j].v = ed->v1; - ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v1] + newEdges; + ml[j++].e = (edges_num * stride) + old_vert_arr[ed->v1] + newEdges; - ml[j].v = (do_shell ? ed->v1 : old_vert_arr[ed->v1]) + numVerts; - ml[j++].e = (do_shell ? eidx : i) + numEdges; + ml[j].v = (do_shell ? ed->v1 : old_vert_arr[ed->v1]) + verts_num; + ml[j++].e = (do_shell ? eidx : i) + edges_num; - ml[j].v = (do_shell ? ed->v2 : old_vert_arr[ed->v2]) + numVerts; - ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v2] + newEdges; + ml[j].v = (do_shell ? ed->v2 : old_vert_arr[ed->v2]) + verts_num; + ml[j++].e = (edges_num * stride) + old_vert_arr[ed->v2] + newEdges; } if (origindex_edge) { @@ -1141,7 +1142,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex if (crease_inner) { /* crease += crease_inner; without wrapping */ - char *cr = &(medge[numEdges + (do_shell ? eidx : i)].crease); + char *cr = &(medge[edges_num + (do_shell ? eidx : i)].crease); int tcr = *cr + crease_inner; *cr = tcr > 255 ? 255 : tcr; } @@ -1163,13 +1164,13 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex #ifdef SOLIDIFY_SIDE_NORMALS if (do_side_normals) { const MEdge *ed_orig = medge; - ed = medge + (numEdges * stride); + ed = medge + (edges_num * stride); for (i = 0; i < rimVerts; i++, ed++, ed_orig++) { float nor_cpy[3]; int k; /* NOTE: only the first vertex (lower half of the index) is calculated. */ - BLI_assert(ed->v1 < numVerts); + BLI_assert(ed->v1 < verts_num); normalize_v3_v3(nor_cpy, edge_vert_nos[ed_orig->v1]); for (k = 0; k < 2; k++) { /* loop over both verts of the edge */ diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c index d896cab4688..8a84cd0a3bf 100644 --- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c +++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c @@ -141,11 +141,11 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, MEdge *ed, *medge, *orig_medge; MLoop *ml, *mloop, *orig_mloop; MPoly *mp, *mpoly, *orig_mpoly; - const uint numVerts = (uint)mesh->totvert; - const uint numEdges = (uint)mesh->totedge; - const uint numPolys = (uint)mesh->totpoly; + const uint verts_num = (uint)mesh->totvert; + const uint edges_num = (uint)mesh->totedge; + const uint polys_num = (uint)mesh->totpoly; - if (numPolys == 0 && numVerts != 0) { + if (polys_num == 0 && verts_num != 0) { return mesh; } @@ -193,28 +193,28 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, orig_mloop = mesh->mloop; orig_mpoly = mesh->mpoly; - uint numNewVerts = 0; - uint numNewEdges = 0; - uint numNewLoops = 0; - uint numNewPolys = 0; + uint new_verts_num = 0; + uint new_edges_num = 0; + uint new_loops_num = 0; + uint new_polys_num = 0; #define MOD_SOLIDIFY_EMPTY_TAG ((uint)-1) /* Calculate only face normals. Copied because they are modified directly below. */ - float(*poly_nors)[3] = MEM_malloc_arrayN(numPolys, sizeof(float[3]), __func__); - memcpy(poly_nors, BKE_mesh_poly_normals_ensure(mesh), sizeof(float[3]) * numPolys); + float(*poly_nors)[3] = MEM_malloc_arrayN(polys_num, sizeof(float[3]), __func__); + memcpy(poly_nors, BKE_mesh_poly_normals_ensure(mesh), sizeof(float[3]) * polys_num); NewFaceRef *face_sides_arr = MEM_malloc_arrayN( - numPolys * 2, sizeof(*face_sides_arr), "face_sides_arr in solidify"); + polys_num * 2, sizeof(*face_sides_arr), "face_sides_arr in solidify"); bool *null_faces = (smd->nonmanifold_offset_mode == MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_CONSTRAINTS) ? - MEM_calloc_arrayN(numPolys, sizeof(*null_faces), "null_faces in solidify") : + MEM_calloc_arrayN(polys_num, sizeof(*null_faces), "null_faces in solidify") : NULL; uint largest_ngon = 3; /* Calculate face to #NewFaceRef map. */ { mp = orig_mpoly; - for (uint i = 0; i < numPolys; i++, mp++) { + for (uint i = 0; i < polys_num; i++, mp++) { /* Make normals for faces without area (should really be avoided though). */ if (len_squared_v3(poly_nors[i]) < 0.5f) { MEdge *e = orig_medge + orig_mloop[mp->loopstart].e; @@ -244,18 +244,18 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, } /* add to final mesh face count */ if (do_shell) { - numNewPolys += 2; - numNewLoops += (uint)mp->totloop * 2; + new_polys_num += 2; + new_loops_num += (uint)mp->totloop * 2; } } } uint *edge_adj_faces_len = MEM_calloc_arrayN( - numEdges, sizeof(*edge_adj_faces_len), "edge_adj_faces_len in solidify"); + edges_num, sizeof(*edge_adj_faces_len), "edge_adj_faces_len in solidify"); /* Count for each edge how many faces it has adjacent. */ { mp = orig_mpoly; - for (uint i = 0; i < numPolys; i++, mp++) { + for (uint i = 0; i < polys_num; i++, mp++) { ml = orig_mloop + mp->loopstart; for (uint j = 0; j < mp->totloop; j++, ml++) { edge_adj_faces_len[ml->e]++; @@ -265,16 +265,16 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, /* Original edge to #NewEdgeRef map. */ NewEdgeRef ***orig_edge_data_arr = MEM_calloc_arrayN( - numEdges, sizeof(*orig_edge_data_arr), "orig_edge_data_arr in solidify"); + edges_num, sizeof(*orig_edge_data_arr), "orig_edge_data_arr in solidify"); /* Original edge length cache. */ float *orig_edge_lengths = MEM_calloc_arrayN( - numEdges, sizeof(*orig_edge_lengths), "orig_edge_lengths in solidify"); + edges_num, sizeof(*orig_edge_lengths), "orig_edge_lengths in solidify"); /* Edge groups for every original vert. */ EdgeGroup **orig_vert_groups_arr = MEM_calloc_arrayN( - numVerts, sizeof(*orig_vert_groups_arr), "orig_vert_groups_arr in solidify"); + verts_num, sizeof(*orig_vert_groups_arr), "orig_vert_groups_arr in solidify"); /* vertex map used to map duplicates. */ - uint *vm = MEM_malloc_arrayN(numVerts, sizeof(*vm), "orig_vert_map in solidify"); - for (uint i = 0; i < numVerts; i++) { + uint *vm = MEM_malloc_arrayN(verts_num, sizeof(*vm), "orig_vert_map in solidify"); + for (uint i = 0; i < verts_num; i++) { vm[i] = i; } @@ -286,12 +286,12 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, /* Vert edge adjacent map. */ OldVertEdgeRef **vert_adj_edges = MEM_calloc_arrayN( - numVerts, sizeof(*vert_adj_edges), "vert_adj_edges in solidify"); + verts_num, sizeof(*vert_adj_edges), "vert_adj_edges in solidify"); /* Original vertex positions (changed for degenerated geometry). */ float(*orig_mvert_co)[3] = MEM_malloc_arrayN( - numVerts, sizeof(*orig_mvert_co), "orig_mvert_co in solidify"); + verts_num, sizeof(*orig_mvert_co), "orig_mvert_co in solidify"); /* Fill in the original vertex positions. */ - for (uint i = 0; i < numVerts; i++) { + for (uint i = 0; i < verts_num; i++) { orig_mvert_co[i][0] = orig_mvert[i].co[0]; orig_mvert_co[i][1] = orig_mvert[i].co[1]; orig_mvert_co[i][2] = orig_mvert[i].co[2]; @@ -300,12 +300,12 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, /* Create edge to #NewEdgeRef map. */ { OldEdgeFaceRef **edge_adj_faces = MEM_calloc_arrayN( - numEdges, sizeof(*edge_adj_faces), "edge_adj_faces in solidify"); + edges_num, sizeof(*edge_adj_faces), "edge_adj_faces in solidify"); /* Create link_faces for edges. */ { mp = orig_mpoly; - for (uint i = 0; i < numPolys; i++, mp++) { + for (uint i = 0; i < polys_num; i++, mp++) { ml = orig_mloop + mp->loopstart; for (uint j = 0; j < mp->totloop; j++, ml++) { const uint edge = ml->e; @@ -342,19 +342,19 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, float edgedir[3] = {0, 0, 0}; uint *vert_adj_edges_len = MEM_calloc_arrayN( - numVerts, sizeof(*vert_adj_edges_len), "vert_adj_edges_len in solidify"); + verts_num, sizeof(*vert_adj_edges_len), "vert_adj_edges_len in solidify"); /* Calculate edge lengths and len vert_adj edges. */ { bool *face_singularity = MEM_calloc_arrayN( - numPolys, sizeof(*face_singularity), "face_sides_arr in solidify"); + polys_num, sizeof(*face_singularity), "face_sides_arr in solidify"); const float merge_tolerance_sqr = smd->merge_tolerance * smd->merge_tolerance; uint *combined_verts = MEM_calloc_arrayN( - numVerts, sizeof(*combined_verts), "combined_verts in solidify"); + verts_num, sizeof(*combined_verts), "combined_verts in solidify"); ed = orig_medge; - for (uint i = 0; i < numEdges; i++, ed++) { + for (uint i = 0; i < edges_num; i++, ed++) { if (edge_adj_faces_len[i] > 0) { uint v1 = vm[ed->v1]; uint v2 = vm[ed->v2]; @@ -373,7 +373,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, /* This check is very slow. It would need the vertex edge links to get * accelerated that are not yet available at this point. */ bool can_merge = true; - for (uint k = 0; k < numEdges && can_merge; k++) { + for (uint k = 0; k < edges_num && can_merge; k++) { if (k != i && edge_adj_faces_len[k] > 0 && (ELEM(vm[orig_medge[k].v1], v1, v2) != ELEM(vm[orig_medge[k].v2], v1, v2))) { for (uint j = 0; j < edge_adj_faces[k]->faces_len && can_merge; j++) { @@ -402,7 +402,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, (combined_verts[v2] + 1) / (float)(combined_verts[v1] + combined_verts[v2] + 2)); add_v3_v3(orig_mvert_co[v1], edgedir); - for (uint j = v2; j < numVerts; j++) { + for (uint j = v2; j < verts_num; j++) { if (vm[j] == v2) { vm[j] = v1; } @@ -412,7 +412,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, combined_verts[v1] += combined_verts[v2] + 1; if (do_shell) { - numNewLoops -= edge_adj_faces_len[i] * 2; + new_loops_num -= edge_adj_faces_len[i] * 2; } edge_adj_faces_len[i] = 0; @@ -430,7 +430,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, } /* remove zero faces in a second pass */ ed = orig_medge; - for (uint i = 0; i < numEdges; i++, ed++) { + for (uint i = 0; i < edges_num; i++, ed++) { const uint v1 = vm[ed->v1]; const uint v2 = vm[ed->v2]; if (v1 == v2 && edge_adj_faces[i]) { @@ -449,14 +449,14 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, face_singularity[face] = true; /* remove from final mesh poly count */ if (do_shell) { - numNewPolys -= 2; + new_polys_num -= 2; } } } } if (do_shell) { - numNewLoops -= edge_adj_faces_len[i] * 2; + new_loops_num -= edge_adj_faces_len[i] * 2; } edge_adj_faces_len[i] = 0; @@ -474,7 +474,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, /* Create vert_adj_edges for verts. */ { ed = orig_medge; - for (uint i = 0; i < numEdges; i++, ed++) { + for (uint i = 0; i < edges_num; i++, ed++) { if (edge_adj_faces_len[i] > 0) { const uint vs[2] = {vm[ed->v1], vm[ed->v2]}; uint invalid_edge_index = 0; @@ -545,8 +545,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, } /* remove from final face count */ if (do_shell) { - numNewPolys -= 2 * j; - numNewLoops -= 4 * j; + new_polys_num -= 2 * j; + new_loops_num -= 4 * j; } const uint len = i_adj_faces->faces_len + invalid_adj_faces->faces_len - 2 * j; uint *adj_faces = MEM_malloc_arrayN( @@ -595,7 +595,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, ed = orig_medge; /* Iterate over edges and only check the faces around an edge for duplicates * (performance optimization). */ - for (uint i = 0; i < numEdges; i++, ed++) { + for (uint i = 0; i < edges_num; i++, ed++) { if (edge_adj_faces_len[i] > 0) { const OldEdgeFaceRef *adj_faces = edge_adj_faces[i]; uint adj_len = adj_faces->faces_len; @@ -674,7 +674,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, } } else if (e_adj_faces->used > 1) { - for (uint n = 0; n < numEdges; n++) { + for (uint n = 0; n < edges_num; n++) { if (edge_adj_faces[n] == e_adj_faces && edge_adj_faces_len[n] > 0) { edge_adj_faces_len[n]--; if (edge_adj_faces_len[n] == 0) { @@ -689,8 +689,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, } } if (do_shell) { - numNewPolys -= 2; - numNewLoops -= 2 * (uint)del_loops; + new_polys_num -= 2; + new_loops_num -= 2 * (uint)del_loops; } break; } @@ -704,7 +704,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, /* Create #NewEdgeRef array. */ { ed = orig_medge; - for (uint i = 0; i < numEdges; i++, ed++) { + for (uint i = 0; i < edges_num; i++, ed++) { const uint v1 = vm[ed->v1]; const uint v2 = vm[ed->v2]; if (edge_adj_faces_len[i] > 0) { @@ -807,8 +807,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, (adj_faces_reversed[0] ? 1 : 0); if (do_rim) { /* Only add the loops parallel to the edge for now. */ - numNewLoops += 2; - numNewPolys++; + new_loops_num += 2; + new_polys_num++; } } @@ -864,13 +864,13 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, MEM_freeN(sorted_faces); orig_edge_data_arr[i] = new_edges; if (do_shell || (adj_len == 1 && do_rim)) { - numNewEdges += new_edges_len; + new_edges_num += new_edges_len; } } } } - for (uint i = 0; i < numEdges; i++) { + for (uint i = 0; i < edges_num; i++) { if (edge_adj_faces[i]) { if (edge_adj_faces[i]->used > 1) { edge_adj_faces[i]->used--; @@ -888,7 +888,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, /* Create sorted edge groups for every vert. */ { OldVertEdgeRef **adj_edges_ptr = vert_adj_edges; - for (uint i = 0; i < numVerts; i++, adj_edges_ptr++) { + for (uint i = 0; i < verts_num; i++, adj_edges_ptr++) { if (*adj_edges_ptr != NULL && (*adj_edges_ptr)->edges_len >= 2) { EdgeGroup *edge_groups; @@ -1305,7 +1305,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, uint added = 0; if (do_shell || (do_rim && !g->is_orig_closed)) { BLI_assert(g->new_vert == MOD_SOLIDIFY_EMPTY_TAG); - g->new_vert = numNewVerts++; + g->new_vert = new_verts_num++; if (do_rim || (do_shell && g->split)) { new_verts++; contains_splits += (g->split != 0); @@ -1321,23 +1321,23 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, last_added = added; if (!(g + 1)->valid || g->topo_group != (g + 1)->topo_group) { if (new_verts > 2) { - numNewPolys++; - numNewEdges += new_verts; + new_polys_num++; + new_edges_num += new_verts; open_edges += (uint)(first_added < last_added); open_edges -= (uint)(open_edges && !contains_open_splits); if (do_shell && do_rim) { - numNewLoops += new_verts * 2; + new_loops_num += new_verts * 2; } else if (do_shell) { - numNewLoops += new_verts * 2 - open_edges; + new_loops_num += new_verts * 2 - open_edges; } else { // do_rim - numNewLoops += new_verts * 2 + open_edges - contains_splits; + new_loops_num += new_verts * 2 + open_edges - contains_splits; } } else if (new_verts == 2) { - numNewEdges++; - numNewLoops += 2u - (uint)(!(do_rim && do_shell) && contains_open_splits); + new_edges_num++; + new_loops_num += 2u - (uint)(!(do_rim && do_shell) && contains_open_splits); } new_verts = 0; contains_open_splits = false; @@ -1356,7 +1356,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, /* Free vert_adj_edges memory. */ { uint i = 0; - for (OldVertEdgeRef **p = vert_adj_edges; i < numVerts; i++, p++) { + for (OldVertEdgeRef **p = vert_adj_edges; i < verts_num; i++, p++) { if (*p) { MEM_freeN((*p)->edges); MEM_freeN(*p); @@ -1375,10 +1375,10 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, float *face_weight = NULL; if (do_flat_faces) { - face_weight = MEM_malloc_arrayN(numPolys, sizeof(*face_weight), "face_weight in solidify"); + face_weight = MEM_malloc_arrayN(polys_num, sizeof(*face_weight), "face_weight in solidify"); mp = orig_mpoly; - for (uint i = 0; i < numPolys; i++, mp++) { + for (uint i = 0; i < polys_num; i++, mp++) { float scalar_vgroup = 1.0f; int loopend = mp->loopstart + mp->totloop; ml = orig_mloop + mp->loopstart; @@ -1399,7 +1399,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, mv = orig_mvert; gs_ptr = orig_vert_groups_arr; - for (uint i = 0; i < numVerts; i++, mv++, gs_ptr++) { + for (uint i = 0; i < verts_num; i++, mv++, gs_ptr++) { if (*gs_ptr) { EdgeGroup *g = *gs_ptr; for (uint j = 0; g->valid; j++, g++) { @@ -1912,7 +1912,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, uint singularity_edges_len = 1; singularity_edges = MEM_malloc_arrayN( singularity_edges_len, sizeof(*singularity_edges), "singularity_edges in solidify"); - for (NewEdgeRef ***new_edges = orig_edge_data_arr; i < numEdges; i++, new_edges++) { + for (NewEdgeRef ***new_edges = orig_edge_data_arr; i < edges_num; i++, new_edges++) { if (*new_edges && (do_shell || edge_adj_faces_len[i] == 1) && (**new_edges)->old_edge == i) { for (NewEdgeRef **l = *new_edges; *l; l++) { if ((*l)->link_edge_groups[0]->is_singularity && @@ -1940,12 +1940,12 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, singularity_edges[totsingularity][1] = v2; totsingularity++; if (edge_adj_faces_len[i] == 1 && do_rim) { - numNewLoops -= 2; - numNewPolys--; + new_loops_num -= 2; + new_polys_num--; } } else { - numNewEdges--; + new_edges_num--; } } } @@ -1954,8 +1954,12 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, } /* Create Mesh *result with proper capacity. */ - result = BKE_mesh_new_nomain_from_template( - mesh, (int)(numNewVerts), (int)(numNewEdges), 0, (int)(numNewLoops), (int)(numNewPolys)); + result = BKE_mesh_new_nomain_from_template(mesh, + (int)(new_verts_num), + (int)(new_edges_num), + 0, + (int)(new_loops_num), + (int)(new_polys_num)); mpoly = result->mpoly; mloop = result->mloop; @@ -1997,7 +2001,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, /* Make_new_verts. */ { gs_ptr = orig_vert_groups_arr; - for (uint i = 0; i < numVerts; i++, gs_ptr++) { + for (uint i = 0; i < verts_num; i++, gs_ptr++) { EdgeGroup *gs = *gs_ptr; if (gs) { EdgeGroup *g = gs; @@ -2018,7 +2022,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, { uint i = 0; edge_index += totsingularity; - for (NewEdgeRef ***new_edges = orig_edge_data_arr; i < numEdges; i++, new_edges++) { + for (NewEdgeRef ***new_edges = orig_edge_data_arr; i < edges_num; i++, new_edges++) { if (*new_edges && (do_shell || edge_adj_faces_len[i] == 1) && (**new_edges)->old_edge == i) { for (NewEdgeRef **l = *new_edges; *l; l++) { if ((*l)->new_edge != MOD_SOLIDIFY_EMPTY_TAG) { @@ -2089,7 +2093,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, * } */ gs_ptr = orig_vert_groups_arr; - for (uint i = 0; i < numVerts; i++, gs_ptr++) { + for (uint i = 0; i < verts_num; i++, gs_ptr++) { EdgeGroup *gs = *gs_ptr; /* check if the vertex is present (may be dissolved because of proximity) */ if (gs) { @@ -2110,7 +2114,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, { gs_ptr = orig_vert_groups_arr; mv = orig_mvert; - for (uint i = 0; i < numVerts; i++, gs_ptr++, mv++) { + for (uint i = 0; i < verts_num; i++, gs_ptr++, mv++) { EdgeGroup *gs = *gs_ptr; if (gs) { EdgeGroup *g = gs; @@ -2317,7 +2321,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, /* Make boundary faces. */ if (do_rim) { - for (uint i = 0; i < numEdges; i++) { + for (uint i = 0; i < edges_num; i++) { if (edge_adj_faces_len[i] == 1 && orig_edge_data_arr[i] && (*orig_edge_data_arr[i])->old_edge == i) { NewEdgeRef **new_edges = orig_edge_data_arr[i]; @@ -2473,7 +2477,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, largest_ngon * 2, sizeof(*face_verts), "face_verts in solidify"); uint *face_edges = MEM_malloc_arrayN( largest_ngon * 2, sizeof(*face_edges), "face_edges in solidify"); - for (uint i = 0; i < numPolys * 2; i++, fr++) { + for (uint i = 0; i < polys_num * 2; i++, fr++) { const uint loopstart = (uint)fr->face->loopstart; uint totloop = (uint)fr->face->totloop; uint valid_edges = 0; @@ -2561,37 +2565,37 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, MEM_freeN(face_verts); MEM_freeN(face_edges); } - if (edge_index != numNewEdges) { + if (edge_index != new_edges_num) { BKE_modifier_set_error(ctx->object, md, "Internal Error: edges array wrong size: %u instead of %u", - numNewEdges, + new_edges_num, edge_index); } - if (poly_index != numNewPolys) { + if (poly_index != new_polys_num) { BKE_modifier_set_error(ctx->object, md, "Internal Error: polys array wrong size: %u instead of %u", - numNewPolys, + new_polys_num, poly_index); } - if (loop_index != numNewLoops) { + if (loop_index != new_loops_num) { BKE_modifier_set_error(ctx->object, md, "Internal Error: loops array wrong size: %u instead of %u", - numNewLoops, + new_loops_num, loop_index); } - BLI_assert(edge_index == numNewEdges); - BLI_assert(poly_index == numNewPolys); - BLI_assert(loop_index == numNewLoops); + BLI_assert(edge_index == new_edges_num); + BLI_assert(poly_index == new_polys_num); + BLI_assert(loop_index == new_loops_num); /* Free remaining memory */ { MEM_freeN(vm); MEM_freeN(edge_adj_faces_len); uint i = 0; - for (EdgeGroup **p = orig_vert_groups_arr; i < numVerts; i++, p++) { + for (EdgeGroup **p = orig_vert_groups_arr; i < verts_num; i++, p++) { if (*p) { for (EdgeGroup *eg = *p; eg->valid; eg++) { MEM_freeN(eg->edges); @@ -2600,8 +2604,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, } } MEM_freeN(orig_vert_groups_arr); - i = numEdges; - for (NewEdgeRef ***p = orig_edge_data_arr + (numEdges - 1); i > 0; i--, p--) { + i = edges_num; + for (NewEdgeRef ***p = orig_edge_data_arr + (edges_num - 1); i > 0; i--, p--) { if (*p && (**p)->old_edge == i - 1) { for (NewEdgeRef **l = *p; *l; l++) { MEM_freeN(*l); @@ -2612,7 +2616,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, MEM_freeN(orig_edge_data_arr); MEM_freeN(orig_edge_lengths); i = 0; - for (NewFaceRef *p = face_sides_arr; i < numPolys * 2; i++, p++) { + for (NewFaceRef *p = face_sides_arr; i < polys_num * 2; i++, p++) { MEM_freeN(p->link_edges); } MEM_freeN(face_sides_arr); diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c index 973009236ec..249d09e5d2e 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.c +++ b/source/blender/modifiers/intern/MOD_subsurf.c @@ -283,7 +283,7 @@ static void deformMatrices(ModifierData *md, Mesh *mesh, float (*vertex_cos)[3], float (*deform_matrices)[3][3], - int num_verts) + int verts_num) { #if !defined(WITH_OPENSUBDIV) BKE_modifier_set_error(ctx->object, md, "Disabled, built without OpenSubdiv"); @@ -307,7 +307,7 @@ static void deformMatrices(ModifierData *md, /* Happens on bad topology, but also on empty input mesh. */ return; } - BKE_subdiv_deform_coarse_vertices(subdiv, mesh, vertex_cos, num_verts); + BKE_subdiv_deform_coarse_vertices(subdiv, mesh, vertex_cos, verts_num); if (subdiv != runtime_data->subdiv) { BKE_subdiv_free(subdiv); } diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c index 4ca2e67c334..3e75e325e44 100644 --- a/source/blender/modifiers/intern/MOD_surface.c +++ b/source/blender/modifiers/intern/MOD_surface.c @@ -83,9 +83,7 @@ static void freeData(ModifierData *md) } } -static bool dependsOnTime(struct Scene *UNUSED(scene), - ModifierData *UNUSED(md), - const int UNUSED(dag_eval_mode)) +static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md)) { return true; } @@ -94,7 +92,7 @@ static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { SurfaceModifierData *surmd = (SurfaceModifierData *)md; const int cfra = (int)DEG_get_ctime(ctx->depsgraph); @@ -116,7 +114,7 @@ static void deformVerts(ModifierData *md, surmd->mesh = (Mesh *)BKE_id_copy_ex(NULL, (ID *)mesh, NULL, LIB_ID_COPY_LOCALIZE); } else { - surmd->mesh = MOD_deform_mesh_eval_get(ctx->object, NULL, NULL, NULL, numVerts, false, false); + surmd->mesh = MOD_deform_mesh_eval_get(ctx->object, NULL, NULL, NULL, verts_num, false, false); } if (!ctx->object->pd) { @@ -125,7 +123,7 @@ static void deformVerts(ModifierData *md, } if (surmd->mesh) { - uint numverts = 0, i = 0; + uint mesh_verts_num = 0, i = 0; int init = 0; float *vec; MVert *x, *v; @@ -133,9 +131,9 @@ static void deformVerts(ModifierData *md, BKE_mesh_vert_coords_apply(surmd->mesh, vertexCos); BKE_mesh_calc_normals(surmd->mesh); - numverts = surmd->mesh->totvert; + mesh_verts_num = surmd->mesh->totvert; - if (numverts != surmd->numverts || surmd->x == NULL || surmd->v == NULL || + if (mesh_verts_num != surmd->verts_num || surmd->x == NULL || surmd->v == NULL || cfra != surmd->cfra + 1) { if (surmd->x) { MEM_freeN(surmd->x); @@ -146,16 +144,16 @@ static void deformVerts(ModifierData *md, surmd->v = NULL; } - surmd->x = MEM_calloc_arrayN(numverts, sizeof(MVert), "MVert"); - surmd->v = MEM_calloc_arrayN(numverts, sizeof(MVert), "MVert"); + surmd->x = MEM_calloc_arrayN(mesh_verts_num, sizeof(MVert), "MVert"); + surmd->v = MEM_calloc_arrayN(mesh_verts_num, sizeof(MVert), "MVert"); - surmd->numverts = numverts; + surmd->verts_num = mesh_verts_num; init = 1; } /* convert to global coordinates and calculate velocity */ - for (i = 0, x = surmd->x, v = surmd->v; i < numverts; i++, x++, v++) { + for (i = 0, x = surmd->x, v = surmd->v; i < mesh_verts_num; i++, x++, v++) { vec = surmd->mesh->mvert[i].co; mul_m4_v3(ctx->object->obmat, vec); @@ -210,7 +208,7 @@ static void blendRead(BlendDataReader *UNUSED(reader), ModifierData *md) surmd->bvhtree = NULL; surmd->x = NULL; surmd->v = NULL; - surmd->numverts = 0; + surmd->verts_num = 0; } ModifierTypeInfo modifierType_Surface = { diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index 6926893e188..a80918b8d2b 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -135,7 +135,7 @@ typedef struct SDefBindPoly { /** Index of the input polygon. */ uint index; /** Number of vertices in this face. */ - uint numverts; + uint verts_num; /** * This polygons loop-start. * \note that we could look this up from the polygon. @@ -152,8 +152,8 @@ typedef struct SDefBindPoly { typedef struct SDefBindWeightData { SDefBindPoly *bind_polys; - uint numpoly; - uint numbinds; + uint polys_num; + uint binds_num; } SDefBindWeightData; typedef struct SDefDeformData { @@ -209,9 +209,9 @@ static void freeData(ModifierData *md) SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; if (smd->verts) { - for (int i = 0; i < smd->num_bind_verts; i++) { + for (int i = 0; i < smd->bind_verts_num; i++) { if (smd->verts[i].binds) { - for (int j = 0; j < smd->verts[i].numbinds; j++) { + for (int j = 0; j < smd->verts[i].binds_num; j++) { MEM_SAFE_FREE(smd->verts[i].binds[j].vert_inds); MEM_SAFE_FREE(smd->verts[i].binds[j].vert_weights); } @@ -234,11 +234,11 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla if (smd->verts) { tsmd->verts = MEM_dupallocN(smd->verts); - for (int i = 0; i < smd->num_bind_verts; i++) { + for (int i = 0; i < smd->bind_verts_num; i++) { if (smd->verts[i].binds) { tsmd->verts[i].binds = MEM_dupallocN(smd->verts[i].binds); - for (int j = 0; j < smd->verts[i].numbinds; j++) { + for (int j = 0; j < smd->verts[i].binds_num; j++) { if (smd->verts[i].binds[j].vert_inds) { tsmd->verts[i].binds[j].vert_inds = MEM_dupallocN(smd->verts[i].binds[j].vert_inds); } @@ -283,8 +283,8 @@ static void freeAdjacencyMap(SDefAdjacencyArray *const vert_edges, static int buildAdjacencyMap(const MPoly *poly, const MEdge *edge, const MLoop *const mloop, - const uint numpoly, - const uint numedges, + const uint polys_num, + const uint edges_num, SDefAdjacencyArray *const vert_edges, SDefAdjacency *adj, SDefEdgePolys *const edge_polys) @@ -292,7 +292,7 @@ static int buildAdjacencyMap(const MPoly *poly, const MLoop *loop; /* Find polygons adjacent to edges. */ - for (int i = 0; i < numpoly; i++, poly++) { + for (int i = 0; i < polys_num; i++, poly++) { loop = &mloop[poly->loopstart]; for (int j = 0; j < poly->totloop; j++, loop++) { @@ -312,7 +312,7 @@ static int buildAdjacencyMap(const MPoly *poly, } /* Find edges adjacent to vertices */ - for (int i = 0; i < numedges; i++, edge++) { + for (int i = 0; i < edges_num; i++, edge++) { adj->next = vert_edges[edge->v1].first; adj->index = i; vert_edges[edge->v1].first = adj; @@ -457,7 +457,7 @@ static void freeBindData(SDefBindWeightData *const bwdata) SDefBindPoly *bpoly = bwdata->bind_polys; if (bwdata->bind_polys) { - for (int i = 0; i < bwdata->numpoly; bpoly++, i++) { + for (int i = 0; i < bwdata->polys_num; bpoly++, i++) { MEM_SAFE_FREE(bpoly->coords); MEM_SAFE_FREE(bpoly->coords_v2); } @@ -498,9 +498,9 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, return NULL; } - bwdata->numpoly = data->vert_edges[nearest].num / 2; + bwdata->polys_num = data->vert_edges[nearest].num / 2; - bpoly = MEM_calloc_arrayN(bwdata->numpoly, sizeof(*bpoly), "SDefBindPoly"); + bpoly = MEM_calloc_arrayN(bwdata->polys_num, sizeof(*bpoly), "SDefBindPoly"); if (bpoly == NULL) { freeBindData(bwdata); data->success = MOD_SDEF_BIND_RESULT_MEM_ERR; @@ -518,7 +518,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, { bpoly = bwdata->bind_polys; - for (int j = 0; j < bwdata->numpoly; bpoly++, j++) { + for (int j = 0; j < bwdata->polys_num; bpoly++, j++) { /* If coords isn't allocated, we have reached the first uninitialized `bpoly`. */ if ((bpoly->index == edge_polys[edge_ind].polys[i]) || (!bpoly->coords)) { break; @@ -541,7 +541,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, poly = &data->mpoly[bpoly->index]; loop = &data->mloop[poly->loopstart]; - bpoly->numverts = poly->totloop; + bpoly->verts_num = poly->totloop; bpoly->loopstart = poly->loopstart; bpoly->coords = MEM_malloc_arrayN( @@ -719,7 +719,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, } } - avg_point_dist /= bwdata->numpoly; + avg_point_dist /= bwdata->polys_num; /* If weights 1 and 2 are not infinite, loop over all adjacent edges again, * and build adjacency dependent angle data (depends on all polygons having been computed) */ @@ -736,7 +736,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, /* Find bind polys corresponding to the edge's adjacent polys */ bpoly = bwdata->bind_polys; - for (int i = 0, j = 0; (i < bwdata->numpoly) && (j < epolys->num); bpoly++, i++) { + for (int i = 0, j = 0; (i < bwdata->polys_num) && (j < epolys->num); bpoly++, i++) { if (ELEM(bpoly->index, epolys->polys[0], epolys->polys[1])) { bpolys[j] = bpoly; @@ -776,7 +776,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, if (!inf_weight_flags) { bpoly = bwdata->bind_polys; - for (int i = 0; i < bwdata->numpoly; bpoly++, i++) { + for (int i = 0; i < bwdata->polys_num; bpoly++, i++) { float corner_angle_weights[2]; float scale_weight, sqr, inv_sqr; @@ -856,7 +856,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, else if (!(inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_DIST)) { bpoly = bwdata->bind_polys; - for (int i = 0; i < bwdata->numpoly; bpoly++, i++) { + for (int i = 0; i < bwdata->polys_num; bpoly++, i++) { /* Scale the point distance weight by average point distance, and introduce falloff */ bpoly->weight_dist /= avg_point_dist; bpoly->weight_dist = powf(bpoly->weight_dist, data->falloff); @@ -871,7 +871,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, /* Final loop, to compute actual weights */ bpoly = bwdata->bind_polys; - for (int i = 0; i < bwdata->numpoly; bpoly++, i++) { + for (int i = 0; i < bwdata->polys_num; bpoly++, i++) { /* Weight computation from components */ if (inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_DIST) { bpoly->weight = bpoly->weight_dist < FLT_EPSILON ? 1.0f : 0.0f; @@ -898,7 +898,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, bpoly = bwdata->bind_polys; - for (int i = 0; i < bwdata->numpoly; bpoly++, i++) { + for (int i = 0; i < bwdata->polys_num; bpoly++, i++) { bpoly->weight /= tot_weight; /* Evaluate if this poly is relevant to bind */ @@ -907,15 +907,15 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, * should be negligible... */ if (bpoly->weight >= FLT_EPSILON) { if (bpoly->inside) { - bwdata->numbinds += 1; + bwdata->binds_num += 1; } else { if (bpoly->dominant_angle_weight < FLT_EPSILON || 1.0f - bpoly->dominant_angle_weight < FLT_EPSILON) { - bwdata->numbinds += 1; + bwdata->binds_num += 1; } else { - bwdata->numbinds += 2; + bwdata->binds_num += 2; } } } @@ -958,7 +958,7 @@ static void bindVert(void *__restrict userdata, if (data->success != MOD_SDEF_BIND_RESULT_SUCCESS) { sdvert->binds = NULL; - sdvert->numbinds = 0; + sdvert->binds_num = 0; return; } @@ -975,7 +975,7 @@ static void bindVert(void *__restrict userdata, if (weight <= 0) { sdvert->binds = NULL; - sdvert->numbinds = 0; + sdvert->binds_num = 0; return; } } @@ -985,53 +985,53 @@ static void bindVert(void *__restrict userdata, if (bwdata == NULL) { sdvert->binds = NULL; - sdvert->numbinds = 0; + sdvert->binds_num = 0; return; } - sdvert->binds = MEM_calloc_arrayN(bwdata->numbinds, sizeof(*sdvert->binds), "SDefVertBindData"); + sdvert->binds = MEM_calloc_arrayN(bwdata->binds_num, sizeof(*sdvert->binds), "SDefVertBindData"); if (sdvert->binds == NULL) { data->success = MOD_SDEF_BIND_RESULT_MEM_ERR; - sdvert->numbinds = 0; + sdvert->binds_num = 0; return; } - sdvert->numbinds = bwdata->numbinds; + sdvert->binds_num = bwdata->binds_num; sdbind = sdvert->binds; bpoly = bwdata->bind_polys; - for (int i = 0; i < bwdata->numbinds; bpoly++) { + for (int i = 0; i < bwdata->binds_num; bpoly++) { if (bpoly->weight >= FLT_EPSILON) { if (bpoly->inside) { const MLoop *loop = &data->mloop[bpoly->loopstart]; sdbind->influence = bpoly->weight; - sdbind->numverts = bpoly->numverts; + sdbind->verts_num = bpoly->verts_num; sdbind->mode = MOD_SDEF_MODE_NGON; sdbind->vert_weights = MEM_malloc_arrayN( - bpoly->numverts, sizeof(*sdbind->vert_weights), "SDefNgonVertWeights"); + bpoly->verts_num, sizeof(*sdbind->vert_weights), "SDefNgonVertWeights"); if (sdbind->vert_weights == NULL) { data->success = MOD_SDEF_BIND_RESULT_MEM_ERR; return; } sdbind->vert_inds = MEM_malloc_arrayN( - bpoly->numverts, sizeof(*sdbind->vert_inds), "SDefNgonVertInds"); + bpoly->verts_num, sizeof(*sdbind->vert_inds), "SDefNgonVertInds"); if (sdbind->vert_inds == NULL) { data->success = MOD_SDEF_BIND_RESULT_MEM_ERR; return; } interp_weights_poly_v2( - sdbind->vert_weights, bpoly->coords_v2, bpoly->numverts, bpoly->point_v2); + sdbind->vert_weights, bpoly->coords_v2, bpoly->verts_num, bpoly->point_v2); /* Re-project vert based on weights and original poly verts, * to reintroduce poly non-planarity */ zero_v3(point_co_proj); - for (int j = 0; j < bpoly->numverts; j++, loop++) { + for (int j = 0; j < bpoly->verts_num; j++, loop++) { madd_v3_v3fl(point_co_proj, bpoly->coords[j], sdbind->vert_weights[j]); sdbind->vert_inds[j] = loop->v; } @@ -1048,7 +1048,7 @@ static void bindVert(void *__restrict userdata, if (1.0f - bpoly->dominant_angle_weight >= FLT_EPSILON) { sdbind->influence = bpoly->weight * (1.0f - bpoly->dominant_angle_weight); - sdbind->numverts = bpoly->numverts; + sdbind->verts_num = bpoly->verts_num; sdbind->mode = MOD_SDEF_MODE_CENTROID; sdbind->vert_weights = MEM_malloc_arrayN( @@ -1059,7 +1059,7 @@ static void bindVert(void *__restrict userdata, } sdbind->vert_inds = MEM_malloc_arrayN( - bpoly->numverts, sizeof(*sdbind->vert_inds), "SDefCentVertInds"); + bpoly->verts_num, sizeof(*sdbind->vert_inds), "SDefCentVertInds"); if (sdbind->vert_inds == NULL) { data->success = MOD_SDEF_BIND_RESULT_MEM_ERR; return; @@ -1068,7 +1068,7 @@ static void bindVert(void *__restrict userdata, sortPolyVertsEdge(sdbind->vert_inds, &data->mloop[bpoly->loopstart], bpoly->edge_inds[bpoly->dominant_edge], - bpoly->numverts); + bpoly->verts_num); copy_v3_v3(v1, data->targetCos[sdbind->vert_inds[0]]); copy_v3_v3(v2, data->targetCos[sdbind->vert_inds[1]]); @@ -1095,7 +1095,7 @@ static void bindVert(void *__restrict userdata, if (bpoly->dominant_angle_weight >= FLT_EPSILON) { sdbind->influence = bpoly->weight * bpoly->dominant_angle_weight; - sdbind->numverts = bpoly->numverts; + sdbind->verts_num = bpoly->verts_num; sdbind->mode = MOD_SDEF_MODE_LOOPTRI; sdbind->vert_weights = MEM_malloc_arrayN( @@ -1106,7 +1106,7 @@ static void bindVert(void *__restrict userdata, } sdbind->vert_inds = MEM_malloc_arrayN( - bpoly->numverts, sizeof(*sdbind->vert_inds), "SDefTriVertInds"); + bpoly->verts_num, sizeof(*sdbind->vert_inds), "SDefTriVertInds"); if (sdbind->vert_inds == NULL) { data->success = MOD_SDEF_BIND_RESULT_MEM_ERR; return; @@ -1115,7 +1115,7 @@ static void bindVert(void *__restrict userdata, sortPolyVertsTri(sdbind->vert_inds, &data->mloop[bpoly->loopstart], bpoly->edge_vert_inds[0], - bpoly->numverts); + bpoly->verts_num); copy_v3_v3(v1, data->targetCos[sdbind->vert_inds[0]]); copy_v3_v3(v2, data->targetCos[sdbind->vert_inds[1]]); @@ -1149,25 +1149,25 @@ static void bindVert(void *__restrict userdata, /* Remove vertices without bind data from the bind array. */ static void compactSparseBinds(SurfaceDeformModifierData *smd) { - smd->num_bind_verts = 0; + smd->bind_verts_num = 0; - for (uint i = 0; i < smd->num_mesh_verts; i++) { - if (smd->verts[i].numbinds > 0) { - smd->verts[smd->num_bind_verts++] = smd->verts[i]; + for (uint i = 0; i < smd->mesh_verts_num; i++) { + if (smd->verts[i].binds_num > 0) { + smd->verts[smd->bind_verts_num++] = smd->verts[i]; } } smd->verts = MEM_reallocN_id( - smd->verts, sizeof(*smd->verts) * smd->num_bind_verts, "SDefBindVerts (sparse)"); + smd->verts, sizeof(*smd->verts) * smd->bind_verts_num, "SDefBindVerts (sparse)"); } static bool surfacedeformBind(Object *ob, SurfaceDeformModifierData *smd_orig, SurfaceDeformModifierData *smd_eval, float (*vertexCos)[3], - uint numverts, - uint tnumpoly, - uint tnumverts, + uint verts_num, + uint tpolys_num, + uint tverts_num, Mesh *target, Mesh *mesh) { @@ -1176,26 +1176,26 @@ static bool surfacedeformBind(Object *ob, const MPoly *mpoly = target->mpoly; const MEdge *medge = target->medge; const MLoop *mloop = target->mloop; - uint tnumedges = target->totedge; + uint tedges_num = target->totedge; int adj_result; SDefAdjacencyArray *vert_edges; SDefAdjacency *adj_array; SDefEdgePolys *edge_polys; - vert_edges = MEM_calloc_arrayN(tnumverts, sizeof(*vert_edges), "SDefVertEdgeMap"); + vert_edges = MEM_calloc_arrayN(tverts_num, sizeof(*vert_edges), "SDefVertEdgeMap"); if (vert_edges == NULL) { BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); return false; } - adj_array = MEM_malloc_arrayN(tnumedges, 2 * sizeof(*adj_array), "SDefVertEdge"); + adj_array = MEM_malloc_arrayN(tedges_num, 2 * sizeof(*adj_array), "SDefVertEdge"); if (adj_array == NULL) { BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); MEM_freeN(vert_edges); return false; } - edge_polys = MEM_calloc_arrayN(tnumedges, sizeof(*edge_polys), "SDefEdgeFaceMap"); + edge_polys = MEM_calloc_arrayN(tedges_num, sizeof(*edge_polys), "SDefEdgeFaceMap"); if (edge_polys == NULL) { BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); MEM_freeN(vert_edges); @@ -1203,7 +1203,7 @@ static bool surfacedeformBind(Object *ob, return false; } - smd_orig->verts = MEM_malloc_arrayN(numverts, sizeof(*smd_orig->verts), "SDefBindVerts"); + smd_orig->verts = MEM_malloc_arrayN(verts_num, sizeof(*smd_orig->verts), "SDefBindVerts"); if (smd_orig->verts == NULL) { BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); freeAdjacencyMap(vert_edges, adj_array, edge_polys); @@ -1220,7 +1220,7 @@ static bool surfacedeformBind(Object *ob, } adj_result = buildAdjacencyMap( - mpoly, medge, mloop, tnumpoly, tnumedges, vert_edges, adj_array, edge_polys); + mpoly, medge, mloop, tpolys_num, tedges_num, vert_edges, adj_array, edge_polys); if (adj_result == MOD_SDEF_BIND_RESULT_NONMANY_ERR) { BKE_modifier_set_error( @@ -1232,8 +1232,8 @@ static bool surfacedeformBind(Object *ob, return false; } - smd_orig->num_mesh_verts = numverts; - smd_orig->numpoly = tnumpoly; + smd_orig->mesh_verts_num = verts_num; + smd_orig->polys_num = tpolys_num; int defgrp_index; MDeformVert *dvert; @@ -1249,7 +1249,7 @@ static bool surfacedeformBind(Object *ob, .medge = medge, .mloop = mloop, .looptri = BKE_mesh_runtime_looptri_ensure(target), - .targetCos = MEM_malloc_arrayN(tnumverts, sizeof(float[3]), "SDefTargetBindVertArray"), + .targetCos = MEM_malloc_arrayN(tverts_num, sizeof(float[3]), "SDefTargetBindVertArray"), .bind_verts = smd_orig->verts, .vertexCos = vertexCos, .falloff = smd_orig->falloff, @@ -1268,14 +1268,14 @@ static bool surfacedeformBind(Object *ob, invert_m4_m4(data.imat, smd_orig->mat); - for (int i = 0; i < tnumverts; i++) { + for (int i = 0; i < tverts_num; i++) { mul_v3_m4v3(data.targetCos[i], smd_orig->mat, mvert[i].co); } TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.use_threading = (numverts > 10000); - BLI_task_parallel_range(0, numverts, &data, bindVert, &settings); + settings.use_threading = (verts_num > 10000); + BLI_task_parallel_range(0, verts_num, &data, bindVert, &settings); MEM_freeN(data.targetCos); @@ -1283,7 +1283,7 @@ static bool surfacedeformBind(Object *ob, compactSparseBinds(smd_orig); } else { - smd_orig->num_bind_verts = numverts; + smd_orig->bind_verts_num = verts_num; } if (data.success == MOD_SDEF_BIND_RESULT_MEM_ERR) { @@ -1311,7 +1311,7 @@ static bool surfacedeformBind(Object *ob, BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Target contains invalid polygons"); freeData((ModifierData *)smd_orig); } - else if (smd_orig->num_bind_verts == 0 || !smd_orig->verts) { + else if (smd_orig->bind_verts_num == 0 || !smd_orig->verts) { data.success = MOD_SDEF_BIND_RESULT_GENERIC_ERR; BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "No vertices were bound"); freeData((ModifierData *)smd_orig); @@ -1329,7 +1329,7 @@ static void deformVert(void *__restrict userdata, { const SDefDeformData *const data = (SDefDeformData *)userdata; const SDefBind *sdbind = data->bind_verts[index].binds; - const int num_binds = data->bind_verts[index].numbinds; + const int sdbind_num = data->bind_verts[index].binds_num; const unsigned int vertex_idx = data->bind_verts[index].vertex_idx; float *const vertexCos = data->vertexCos[vertex_idx]; float norm[3], temp[3], offset[3]; @@ -1355,8 +1355,8 @@ static void deformVert(void *__restrict userdata, /* Allocate a `coords_buffer` that fits all the temp-data. */ int max_verts = 0; - for (int j = 0; j < num_binds; j++) { - max_verts = MAX2(max_verts, sdbind[j].numverts); + for (int j = 0; j < sdbind_num; j++) { + max_verts = MAX2(max_verts, sdbind[j].verts_num); } const bool big_buffer = max_verts > 256; @@ -1369,12 +1369,12 @@ static void deformVert(void *__restrict userdata, coords_buffer = BLI_array_alloca(coords_buffer, max_verts); } - for (int j = 0; j < num_binds; j++, sdbind++) { - for (int k = 0; k < sdbind->numverts; k++) { + for (int j = 0; j < sdbind_num; j++, sdbind++) { + for (int k = 0; k < sdbind->verts_num; k++) { copy_v3_v3(coords_buffer[k], data->targetCos[sdbind->vert_inds[k]]); } - normal_poly_v3(norm, coords_buffer, sdbind->numverts); + normal_poly_v3(norm, coords_buffer, sdbind->verts_num); zero_v3(temp); switch (sdbind->mode) { @@ -1388,7 +1388,7 @@ static void deformVert(void *__restrict userdata, /* ---------- ngon mode ---------- */ case MOD_SDEF_MODE_NGON: { - for (int k = 0; k < sdbind->numverts; k++) { + for (int k = 0; k < sdbind->verts_num; k++) { madd_v3_v3fl(temp, coords_buffer[k], sdbind->vert_weights[k]); } break; @@ -1397,7 +1397,7 @@ static void deformVert(void *__restrict userdata, /* ---------- centroid mode ---------- */ case MOD_SDEF_MODE_CENTROID: { float cent[3]; - mid_v3_v3_array(cent, coords_buffer, sdbind->numverts); + mid_v3_v3_array(cent, coords_buffer, sdbind->verts_num); madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[0]], sdbind->vert_weights[0]); madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[1]], sdbind->vert_weights[1]); @@ -1425,13 +1425,13 @@ static void deformVert(void *__restrict userdata, static void surfacedeformModifier_do(ModifierData *md, const ModifierEvalContext *ctx, float (*vertexCos)[3], - uint numverts, + uint verts_num, Object *ob, Mesh *mesh) { SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; Mesh *target; - uint tnumverts, tnumpoly; + uint tverts_num, tpolys_num; /* Exit function if bind flag is not set (free bind data if any). */ if (!(smd->flags & MOD_SDEF_BIND)) { @@ -1453,8 +1453,8 @@ static void surfacedeformModifier_do(ModifierData *md, return; } - tnumverts = BKE_mesh_wrapper_vert_len(target); - tnumpoly = BKE_mesh_wrapper_poly_len(target); + tverts_num = BKE_mesh_wrapper_vert_len(target); + tpolys_num = BKE_mesh_wrapper_poly_len(target); /* If not bound, execute bind. */ if (smd->verts == NULL) { @@ -1474,7 +1474,7 @@ static void surfacedeformModifier_do(ModifierData *md, BKE_mesh_wrapper_ensure_mdata(target); if (!surfacedeformBind( - ob, smd_orig, smd, vertexCos, numverts, tnumpoly, tnumverts, target, mesh)) { + ob, smd_orig, smd, vertexCos, verts_num, tpolys_num, tverts_num, target, mesh)) { smd->flags &= ~MOD_SDEF_BIND; } /* Early abort, this is binding 'call', no need to perform whole evaluation. */ @@ -1482,14 +1482,14 @@ static void surfacedeformModifier_do(ModifierData *md, } /* Poly count checks */ - if (smd->num_mesh_verts != numverts) { + if (smd->mesh_verts_num != verts_num) { BKE_modifier_set_error( - ob, md, "Vertices changed from %u to %u", smd->num_mesh_verts, numverts); + ob, md, "Vertices changed from %u to %u", smd->mesh_verts_num, verts_num); return; } - if (smd->numpoly != tnumpoly) { + if (smd->polys_num != tpolys_num) { BKE_modifier_set_error( - ob, md, "Target polygons changed from %u to %u", smd->numpoly, tnumpoly); + ob, md, "Target polygons changed from %u to %u", smd->polys_num, tpolys_num); return; } @@ -1507,7 +1507,7 @@ static void surfacedeformModifier_do(ModifierData *md, /* Actual vertex location update starts here */ SDefDeformData data = { .bind_verts = smd->verts, - .targetCos = MEM_malloc_arrayN(tnumverts, sizeof(float[3]), "SDefTargetVertArray"), + .targetCos = MEM_malloc_arrayN(tverts_num, sizeof(float[3]), "SDefTargetVertArray"), .vertexCos = vertexCos, .dvert = dvert, .defgrp_index = defgrp_index, @@ -1516,12 +1516,12 @@ static void surfacedeformModifier_do(ModifierData *md, }; if (data.targetCos != NULL) { - BKE_mesh_wrapper_vert_coords_copy_with_mat4(target, data.targetCos, tnumverts, smd->mat); + BKE_mesh_wrapper_vert_coords_copy_with_mat4(target, data.targetCos, tverts_num, smd->mat); TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.use_threading = (smd->num_bind_verts > 10000); - BLI_task_parallel_range(0, smd->num_bind_verts, &data, deformVert, &settings); + settings.use_threading = (smd->bind_verts_num > 10000); + BLI_task_parallel_range(0, smd->bind_verts_num, &data, deformVert, &settings); MEM_freeN(data.targetCos); } @@ -1531,17 +1531,17 @@ static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; Mesh *mesh_src = NULL; if (smd->defgrp_name[0] != '\0') { /* Only need to use mesh_src when a vgroup is used. */ - mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false); } - surfacedeformModifier_do(md, ctx, vertexCos, numVerts, ctx->object, mesh_src); + surfacedeformModifier_do(md, ctx, vertexCos, verts_num, ctx->object, mesh_src); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); @@ -1553,17 +1553,17 @@ static void deformVertsEM(ModifierData *md, struct BMEditMesh *em, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; Mesh *mesh_src = NULL; if (smd->defgrp_name[0] != '\0') { /* Only need to use mesh_src when a vgroup is used. */ - mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, verts_num, false, false); } - surfacedeformModifier_do(md, ctx, vertexCos, numVerts, ctx->object, mesh_src); + surfacedeformModifier_do(md, ctx, vertexCos, verts_num, ctx->object, mesh_src); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); @@ -1633,23 +1633,23 @@ static void blendWrite(BlendWriter *writer, const ModifierData *md) { const SurfaceDeformModifierData *smd = (const SurfaceDeformModifierData *)md; - BLO_write_struct_array(writer, SDefVert, smd->num_bind_verts, smd->verts); + BLO_write_struct_array(writer, SDefVert, smd->bind_verts_num, smd->verts); if (smd->verts) { - for (int i = 0; i < smd->num_bind_verts; i++) { - BLO_write_struct_array(writer, SDefBind, smd->verts[i].numbinds, smd->verts[i].binds); + for (int i = 0; i < smd->bind_verts_num; i++) { + BLO_write_struct_array(writer, SDefBind, smd->verts[i].binds_num, smd->verts[i].binds); if (smd->verts[i].binds) { - for (int j = 0; j < smd->verts[i].numbinds; j++) { + for (int j = 0; j < smd->verts[i].binds_num; j++) { BLO_write_uint32_array( - writer, smd->verts[i].binds[j].numverts, smd->verts[i].binds[j].vert_inds); + writer, smd->verts[i].binds[j].verts_num, smd->verts[i].binds[j].vert_inds); if (ELEM(smd->verts[i].binds[j].mode, MOD_SDEF_MODE_CENTROID, MOD_SDEF_MODE_LOOPTRI)) { BLO_write_float3_array(writer, 1, smd->verts[i].binds[j].vert_weights); } else { BLO_write_float_array( - writer, smd->verts[i].binds[j].numverts, smd->verts[i].binds[j].vert_weights); + writer, smd->verts[i].binds[j].verts_num, smd->verts[i].binds[j].vert_weights); } } } @@ -1664,20 +1664,20 @@ static void blendRead(BlendDataReader *reader, ModifierData *md) BLO_read_data_address(reader, &smd->verts); if (smd->verts) { - for (int i = 0; i < smd->num_bind_verts; i++) { + for (int i = 0; i < smd->bind_verts_num; i++) { BLO_read_data_address(reader, &smd->verts[i].binds); if (smd->verts[i].binds) { - for (int j = 0; j < smd->verts[i].numbinds; j++) { + for (int j = 0; j < smd->verts[i].binds_num; j++) { BLO_read_uint32_array( - reader, smd->verts[i].binds[j].numverts, &smd->verts[i].binds[j].vert_inds); + reader, smd->verts[i].binds[j].verts_num, &smd->verts[i].binds[j].vert_inds); if (ELEM(smd->verts[i].binds[j].mode, MOD_SDEF_MODE_CENTROID, MOD_SDEF_MODE_LOOPTRI)) { BLO_read_float3_array(reader, 1, &smd->verts[i].binds[j].vert_weights); } else { BLO_read_float_array( - reader, smd->verts[i].binds[j].numverts, &smd->verts[i].binds[j].vert_weights); + reader, smd->verts[i].binds[j].verts_num, &smd->verts[i].binds[j].vert_weights); } } } diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c index e560a859735..d7e57c1f6e5 100644 --- a/source/blender/modifiers/intern/MOD_triangulate.c +++ b/source/blender/modifiers/intern/MOD_triangulate.c @@ -43,7 +43,7 @@ static Mesh *triangulate_mesh(Mesh *mesh, { Mesh *result; BMesh *bm; - int total_edges, i; + int edges_num, i; MEdge *me; CustomData_MeshMasks cd_mask_extra = { .vmask = CD_MASK_ORIGINDEX, .emask = CD_MASK_ORIGINDEX, .pmask = CD_MASK_ORIGINDEX}; @@ -81,11 +81,11 @@ static Mesh *triangulate_mesh(Mesh *mesh, CustomData_set_layer_flag(&result->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); } - total_edges = result->totedge; + edges_num = result->totedge; me = result->medge; /* force drawing of all edges (seems to be omitted in CDDM_from_bmesh) */ - for (i = 0; i < total_edges; i++, me++) { + for (i = 0; i < edges_num; i++, me++) { me->flag |= ME_EDGEDRAW | ME_EDGERENDER; } diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index a8c52108cc0..a58e8e23147 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -63,7 +63,7 @@ void MOD_get_texture_coords(MappingInfoModifierData *dmd, float (*cos)[3], float (*r_texco)[3]) { - const int numVerts = mesh->totvert; + const int verts_num = mesh->totvert; int i; int texmapping = dmd->texmapping; float mapref_imat[4][4]; @@ -97,8 +97,8 @@ void MOD_get_texture_coords(MappingInfoModifierData *dmd, MPoly *mpoly = mesh->mpoly; MPoly *mp; MLoop *mloop = mesh->mloop; - BLI_bitmap *done = BLI_BITMAP_NEW(numVerts, __func__); - const int numPolys = mesh->totpoly; + BLI_bitmap *done = BLI_BITMAP_NEW(verts_num, __func__); + const int polys_num = mesh->totpoly; char uvname[MAX_CUSTOMDATA_LAYER_NAME]; MLoopUV *mloop_uv; @@ -106,7 +106,7 @@ void MOD_get_texture_coords(MappingInfoModifierData *dmd, mloop_uv = CustomData_get_layer_named(&mesh->ldata, CD_MLOOPUV, uvname); /* verts are given the UV from the first face that uses them */ - for (i = 0, mp = mpoly; i < numPolys; i++, mp++) { + for (i = 0, mp = mpoly; i < polys_num; i++, mp++) { uint fidx = mp->totloop - 1; do { @@ -132,7 +132,7 @@ void MOD_get_texture_coords(MappingInfoModifierData *dmd, } MVert *mv = mesh->mvert; - for (i = 0; i < numVerts; i++, mv++, r_texco++) { + for (i = 0; i < verts_num; i++, mv++, r_texco++) { switch (texmapping) { case MOD_DISP_MAP_LOCAL: copy_v3_v3(*r_texco, cos != NULL ? *cos : mv->co); @@ -169,7 +169,7 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob, struct BMEditMesh *em, Mesh *mesh, const float (*vertexCos)[3], - const int num_verts, + const int verts_num, const bool use_normals, const bool use_orco) { @@ -212,7 +212,7 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob, /* Currently, that may not be the case every time * (texts e.g. tend to give issues, * also when deforming curve points instead of generated curve geometry... ). */ - if (mesh != NULL && mesh->totvert != num_verts) { + if (mesh != NULL && mesh->totvert != verts_num) { BKE_id_free(NULL, mesh); mesh = NULL; } @@ -227,7 +227,7 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob, } if (mesh && mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA) { - BLI_assert(mesh->totvert == num_verts); + BLI_assert(mesh->totvert == verts_num); } return mesh; diff --git a/source/blender/modifiers/intern/MOD_util.h b/source/blender/modifiers/intern/MOD_util.h index 4578d2c4862..aef254b1103 100644 --- a/source/blender/modifiers/intern/MOD_util.h +++ b/source/blender/modifiers/intern/MOD_util.h @@ -37,7 +37,7 @@ struct Mesh *MOD_deform_mesh_eval_get(struct Object *ob, struct BMEditMesh *em, struct Mesh *mesh, const float (*vertexCos)[3], - int num_verts, + int verts_num, bool use_normals, bool use_orco); diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index 642aac17efd..d4d7ecef283 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -72,7 +72,7 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte { UVProjectModifierData *umd = (UVProjectModifierData *)md; bool do_add_own_transform = false; - for (int i = 0; i < umd->num_projectors; i++) { + for (int i = 0; i < umd->projectors_num; i++) { if (umd->projectors[i] != NULL) { DEG_add_object_relation( ctx->node, umd->projectors[i], DEG_OB_COMP_TRANSFORM, "UV Project Modifier"); @@ -98,11 +98,11 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, { float(*coords)[3], (*co)[3]; MLoopUV *mloop_uv; - int i, numVerts, numPolys, numLoops; + int i, verts_num, polys_num, loops_num; MPoly *mpoly, *mp; MLoop *mloop; Projector projectors[MOD_UVPROJECT_MAXPROJECTORS]; - int num_projectors = 0; + int projectors_num = 0; char uvname[MAX_CUSTOMDATA_LAYER_NAME]; float aspx = umd->aspectx ? umd->aspectx : 1.0f; float aspy = umd->aspecty ? umd->aspecty : 1.0f; @@ -110,13 +110,13 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, float scay = umd->scaley ? umd->scaley : 1.0f; int free_uci = 0; - for (i = 0; i < umd->num_projectors; i++) { + for (i = 0; i < umd->projectors_num; i++) { if (umd->projectors[i] != NULL) { - projectors[num_projectors++].ob = umd->projectors[i]; + projectors[projectors_num++].ob = umd->projectors[i]; } } - if (num_projectors == 0) { + if (projectors_num == 0) { return mesh; } @@ -131,7 +131,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, CustomData_validate_layer_name(&mesh->ldata, CD_MLOOPUV, umd->uvlayer_name, uvname); /* calculate a projection matrix and normal for each projector */ - for (i = 0; i < num_projectors; i++) { + for (i = 0; i < projectors_num; i++) { float tmpmat[4][4]; float offsetmat[4][4]; Camera *cam = NULL; @@ -184,23 +184,23 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, mul_mat3_m4_v3(projectors[i].ob->obmat, projectors[i].normal); } - numPolys = mesh->totpoly; - numLoops = mesh->totloop; + polys_num = mesh->totpoly; + loops_num = mesh->totloop; /* make sure we are not modifying the original UV map */ mloop_uv = CustomData_duplicate_referenced_layer_named( - &mesh->ldata, CD_MLOOPUV, uvname, numLoops); + &mesh->ldata, CD_MLOOPUV, uvname, loops_num); - coords = BKE_mesh_vert_coords_alloc(mesh, &numVerts); + coords = BKE_mesh_vert_coords_alloc(mesh, &verts_num); /* Convert coords to world-space. */ - for (i = 0, co = coords; i < numVerts; i++, co++) { + for (i = 0, co = coords; i < verts_num; i++, co++) { mul_m4_v3(ob->obmat, *co); } /* if only one projector, project coords to UVs */ - if (num_projectors == 1 && projectors[0].uci == NULL) { - for (i = 0, co = coords; i < numVerts; i++, co++) { + if (projectors_num == 1 && projectors[0].uci == NULL) { + for (i = 0, co = coords; i < verts_num; i++, co++) { mul_project_m4_v3(projectors[0].projmat, *co); } } @@ -209,8 +209,8 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, mloop = mesh->mloop; /* apply coords as UVs */ - for (i = 0, mp = mpoly; i < numPolys; i++, mp++) { - if (num_projectors == 1) { + for (i = 0, mp = mpoly; i < polys_num; i++, mp++) { + if (projectors_num == 1) { if (projectors[0].uci) { uint fidx = mp->totloop - 1; do { @@ -246,7 +246,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, best_dot = dot_v3v3(projectors[0].normal, face_no); best_projector = &projectors[0]; - for (j = 1; j < num_projectors; j++) { + for (j = 1; j < projectors_num; j++) { float tmp_dot = dot_v3v3(projectors[j].normal, face_no); if (tmp_dot > best_dot) { best_dot = tmp_dot; @@ -277,7 +277,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, if (free_uci) { int j; - for (j = 0; j < num_projectors; j++) { + for (j = 0; j < projectors_num; j++) { if (projectors[j].uci) { MEM_freeN(projectors[j].uci); } diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c index 0574b1897de..a15efdaa381 100644 --- a/source/blender/modifiers/intern/MOD_uvwarp.c +++ b/source/blender/modifiers/intern/MOD_uvwarp.c @@ -130,7 +130,7 @@ static void uv_warp_compute(void *__restrict userdata, static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { UVWarpModifierData *umd = (UVWarpModifierData *)md; - int numPolys, numLoops; + int polys_num, loops_num; MPoly *mpoly; MLoop *mloop; MLoopUV *mloopuv; @@ -196,14 +196,14 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* make sure we're using an existing layer */ CustomData_validate_layer_name(&mesh->ldata, CD_MLOOPUV, umd->uvlayer_name, uvname); - numPolys = mesh->totpoly; - numLoops = mesh->totloop; + polys_num = mesh->totpoly; + loops_num = mesh->totloop; mpoly = mesh->mpoly; mloop = mesh->mloop; /* make sure we are not modifying the original UV map */ mloopuv = CustomData_duplicate_referenced_layer_named( - &mesh->ldata, CD_MLOOPUV, uvname, numLoops); + &mesh->ldata, CD_MLOOPUV, uvname, loops_num); MOD_get_vgroup(ctx->object, mesh, umd->vgroup_name, &dvert, &defgrp_index); UVWarpData data = { @@ -217,8 +217,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * }; TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.use_threading = (numPolys > 1000); - BLI_task_parallel_range(0, numPolys, &data, uv_warp_compute, &settings); + settings.use_threading = (polys_num > 1000); + BLI_task_parallel_range(0, polys_num, &data, uv_warp_compute, &settings); mesh->runtime.is_original = false; diff --git a/source/blender/modifiers/intern/MOD_volume_displace.cc b/source/blender/modifiers/intern/MOD_volume_displace.cc index c4a822125ba..059cfdbdd4e 100644 --- a/source/blender/modifiers/intern/MOD_volume_displace.cc +++ b/source/blender/modifiers/intern/MOD_volume_displace.cc @@ -82,9 +82,7 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void walk(userData, ob, md, "texture"); } -static bool dependsOnTime(struct Scene *UNUSED(scene), - ModifierData *md, - const int UNUSED(dag_eval_mode)) +static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md) { VolumeDisplaceModifierData *vdmd = reinterpret_cast<VolumeDisplaceModifierData *>(md); if (vdmd->texture) { diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c index 045b8e16736..e95d2983639 100644 --- a/source/blender/modifiers/intern/MOD_warp.c +++ b/source/blender/modifiers/intern/MOD_warp.c @@ -103,9 +103,7 @@ static void matrix_from_obj_pchan(float mat[4][4], } } -static bool dependsOnTime(struct Scene *UNUSED(scene), - ModifierData *md, - const int UNUSED(dag_eval_mode)) +static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md) { WarpModifierData *wmd = (WarpModifierData *)md; @@ -181,7 +179,7 @@ static void warpModifier_do(WarpModifierData *wmd, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { Object *ob = ctx->object; float obinv[4][4]; @@ -245,13 +243,13 @@ static void warpModifier_do(WarpModifierData *wmd, Tex *tex_target = wmd->texture; if (mesh != NULL && tex_target != NULL) { - tex_co = MEM_malloc_arrayN(numVerts, sizeof(*tex_co), "warpModifier_do tex_co"); + tex_co = MEM_malloc_arrayN(verts_num, sizeof(*tex_co), "warpModifier_do tex_co"); MOD_get_texture_coords((MappingInfoModifierData *)wmd, ctx, ob, mesh, vertexCos, tex_co); MOD_init_texture((MappingInfoModifierData *)wmd, ctx); } - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { float *co = vertexCos[i]; if (wmd->falloff_type == eWarp_Falloff_None || @@ -344,17 +342,17 @@ static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { WarpModifierData *wmd = (WarpModifierData *)md; Mesh *mesh_src = NULL; if (wmd->defgrp_name[0] != '\0' || wmd->texture != NULL) { /* mesh_src is only needed for vgroups and textures. */ - mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false); } - warpModifier_do(wmd, ctx, mesh_src, vertexCos, numVerts); + warpModifier_do(wmd, ctx, mesh_src, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); @@ -366,14 +364,14 @@ static void deformVertsEM(ModifierData *md, struct BMEditMesh *em, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { WarpModifierData *wmd = (WarpModifierData *)md; Mesh *mesh_src = NULL; if (wmd->defgrp_name[0] != '\0' || wmd->texture != NULL) { /* mesh_src is only needed for vgroups and textures. */ - mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, verts_num, false, false); } /* TODO(Campbell): use edit-mode data only (remove this line). */ @@ -381,7 +379,7 @@ static void deformVertsEM(ModifierData *md, BKE_mesh_wrapper_ensure_mdata(mesh_src); } - warpModifier_do(wmd, ctx, mesh_src, vertexCos, numVerts); + warpModifier_do(wmd, ctx, mesh_src, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c index 9518cc253e7..73b26dc29cd 100644 --- a/source/blender/modifiers/intern/MOD_wave.c +++ b/source/blender/modifiers/intern/MOD_wave.c @@ -55,9 +55,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(wmd, DNA_struct_default_get(WaveModifierData), modifier); } -static bool dependsOnTime(struct Scene *UNUSED(scene), - ModifierData *UNUSED(md), - const int UNUSED(dag_eval_mode)) +static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md)) { return true; } @@ -133,7 +131,7 @@ static void waveModifier_do(WaveModifierData *md, Object *ob, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { WaveModifierData *wmd = (WaveModifierData *)md; MVert *mvert = NULL; @@ -188,7 +186,7 @@ static void waveModifier_do(WaveModifierData *md, Tex *tex_target = wmd->texture; if (mesh != NULL && tex_target != NULL) { - tex_co = MEM_malloc_arrayN(numVerts, sizeof(*tex_co), "waveModifier_do tex_co"); + tex_co = MEM_malloc_arrayN(verts_num, sizeof(*tex_co), "waveModifier_do tex_co"); MOD_get_texture_coords((MappingInfoModifierData *)wmd, ctx, ob, mesh, vertexCos, tex_co); MOD_init_texture((MappingInfoModifierData *)wmd, ctx); @@ -199,7 +197,7 @@ static void waveModifier_do(WaveModifierData *md, float falloff_inv = falloff != 0.0f ? 1.0f / falloff : 1.0f; int i; - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { float *co = vertexCos[i]; float x = co[0] - wmd->startx; float y = co[1] - wmd->starty; @@ -299,19 +297,20 @@ static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { WaveModifierData *wmd = (WaveModifierData *)md; Mesh *mesh_src = NULL; if (wmd->flag & MOD_WAVE_NORM) { - mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, vertexCos, numVerts, true, false); + mesh_src = MOD_deform_mesh_eval_get( + ctx->object, NULL, mesh, vertexCos, verts_num, true, false); } else if (wmd->texture != NULL || wmd->defgrp_name[0] != '\0') { - mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false); } - waveModifier_do(wmd, ctx, ctx->object, mesh_src, vertexCos, numVerts); + waveModifier_do(wmd, ctx, ctx->object, mesh_src, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); @@ -323,17 +322,18 @@ static void deformVertsEM(ModifierData *md, struct BMEditMesh *editData, Mesh *mesh, float (*vertexCos)[3], - int numVerts) + int verts_num) { WaveModifierData *wmd = (WaveModifierData *)md; Mesh *mesh_src = NULL; if (wmd->flag & MOD_WAVE_NORM) { mesh_src = MOD_deform_mesh_eval_get( - ctx->object, editData, mesh, vertexCos, numVerts, true, false); + ctx->object, editData, mesh, vertexCos, verts_num, true, false); } else if (wmd->texture != NULL || wmd->defgrp_name[0] != '\0') { - mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false); + mesh_src = MOD_deform_mesh_eval_get( + ctx->object, editData, mesh, NULL, verts_num, false, false); } /* TODO(Campbell): use edit-mode data only (remove this line). */ @@ -341,7 +341,7 @@ static void deformVertsEM(ModifierData *md, BKE_mesh_wrapper_ensure_mdata(mesh_src); } - waveModifier_do(wmd, ctx, ctx->object, mesh_src, vertexCos, numVerts); + waveModifier_do(wmd, ctx, ctx->object, mesh_src, vertexCos, verts_num); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c index 873372a35b8..c79dbdb0b1a 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.c +++ b/source/blender/modifiers/intern/MOD_weighted_normal.c @@ -58,7 +58,7 @@ static int modepair_cmp_by_val_inverse(const void *p1, const void *p2) typedef struct WeightedNormalDataAggregateItem { float normal[3]; - int num_loops; /* Count number of loops using this item so far. */ + int loops_num; /* Count number of loops using this item so far. */ float curr_val; /* Current max val for this item. */ int curr_strength; /* Current max strength encountered for this item. */ } WeightedNormalDataAggregateItem; @@ -66,10 +66,10 @@ typedef struct WeightedNormalDataAggregateItem { #define NUM_CACHED_INVERSE_POWERS_OF_WEIGHT 128 typedef struct WeightedNormalData { - const int numVerts; - const int numEdges; - const int numLoops; - const int numPolys; + const int verts_num; + const int edges_num; + const int loops_num; + const int polys_num; MVert *mvert; const float (*vert_normals)[3]; @@ -116,7 +116,7 @@ static bool check_item_poly_strength(WeightedNormalData *wn_data, if (mp_strength > item_data->curr_strength) { item_data->curr_strength = mp_strength; item_data->curr_val = 0.0f; - item_data->num_loops = 0; + item_data->loops_num = 0; zero_v3(item_data->normal); } @@ -160,20 +160,20 @@ static void aggregate_item_normal(WeightedNormalModifierData *wnmd, } if (!compare_ff(item_data->curr_val, curr_val, wnmd->thresh)) { /* item's curr_val and present value differ more than threshold, update. */ - item_data->num_loops++; + item_data->loops_num++; item_data->curr_val = curr_val; } /* Exponentially divided weight for each normal * (since a few values will be used by most cases, we cache those). */ - const int num_loops = item_data->num_loops; - if (num_loops < NUM_CACHED_INVERSE_POWERS_OF_WEIGHT && - cached_inverse_powers_of_weight[num_loops] == 0.0f) { - cached_inverse_powers_of_weight[num_loops] = 1.0f / powf(weight, num_loops); + const int loops_num = item_data->loops_num; + if (loops_num < NUM_CACHED_INVERSE_POWERS_OF_WEIGHT && + cached_inverse_powers_of_weight[loops_num] == 0.0f) { + cached_inverse_powers_of_weight[loops_num] = 1.0f / powf(weight, loops_num); } - const float inverted_n_weight = num_loops < NUM_CACHED_INVERSE_POWERS_OF_WEIGHT ? - cached_inverse_powers_of_weight[num_loops] : - 1.0f / powf(weight, num_loops); + const float inverted_n_weight = loops_num < NUM_CACHED_INVERSE_POWERS_OF_WEIGHT ? + cached_inverse_powers_of_weight[loops_num] : + 1.0f / powf(weight, loops_num); madd_v3_v3fl(item_data->normal, polynors[mp_index], curr_val * inverted_n_weight); } @@ -181,10 +181,10 @@ static void aggregate_item_normal(WeightedNormalModifierData *wnmd, static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, WeightedNormalData *wn_data) { - const int numVerts = wn_data->numVerts; - const int numEdges = wn_data->numEdges; - const int numLoops = wn_data->numLoops; - const int numPolys = wn_data->numPolys; + const int verts_num = wn_data->verts_num; + const int edges_num = wn_data->edges_num; + const int loops_num = wn_data->loops_num; + const int polys_num = wn_data->polys_num; MVert *mvert = wn_data->mvert; MEdge *medge = wn_data->medge; @@ -214,39 +214,39 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, float(*loop_normals)[3] = NULL; WeightedNormalDataAggregateItem *items_data = NULL; - int num_items = 0; + int items_num = 0; if (keep_sharp) { - BLI_bitmap *done_loops = BLI_BITMAP_NEW(numLoops, __func__); + BLI_bitmap *done_loops = BLI_BITMAP_NEW(loops_num, __func__); /* This will give us loop normal spaces, * we do not actually care about computed loop_normals for now... */ - loop_normals = MEM_calloc_arrayN((size_t)numLoops, sizeof(*loop_normals), __func__); + loop_normals = MEM_calloc_arrayN((size_t)loops_num, sizeof(*loop_normals), __func__); BKE_mesh_normals_loop_split(mvert, wn_data->vert_normals, - numVerts, + verts_num, medge, - numEdges, + edges_num, mloop, loop_normals, - numLoops, + loops_num, mpoly, polynors, - numPolys, + polys_num, true, split_angle, &lnors_spacearr, has_clnors ? clnors : NULL, loop_to_poly); - num_items = lnors_spacearr.num_spaces; - items_data = MEM_calloc_arrayN((size_t)num_items, sizeof(*items_data), __func__); + items_num = lnors_spacearr.spaces_num; + items_data = MEM_calloc_arrayN((size_t)items_num, sizeof(*items_data), __func__); /* In this first loop, we assign each WeightedNormalDataAggregateItem * to its smooth fan of loops (aka lnor space). */ MPoly *mp; int mp_index; int item_index; - for (mp = mpoly, mp_index = 0, item_index = 0; mp_index < numPolys; mp++, mp_index++) { + for (mp = mpoly, mp_index = 0, item_index = 0; mp_index < polys_num; mp++, mp_index++) { int ml_index = mp->loopstart; const int ml_end_index = ml_index + mp->totloop; @@ -255,7 +255,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, /* Smooth fan of this loop has already been processed, skip it. */ continue; } - BLI_assert(item_index < num_items); + BLI_assert(item_index < items_num); WeightedNormalDataAggregateItem *itdt = &items_data[item_index]; itdt->curr_strength = FACE_STRENGTH_WEAK; @@ -280,10 +280,10 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, MEM_freeN(done_loops); } else { - num_items = numVerts; - items_data = MEM_calloc_arrayN((size_t)num_items, sizeof(*items_data), __func__); + items_num = verts_num; + items_data = MEM_calloc_arrayN((size_t)items_num, sizeof(*items_data), __func__); if (use_face_influence) { - for (int item_index = 0; item_index < num_items; item_index++) { + for (int item_index = 0; item_index < items_num; item_index++) { items_data[item_index].curr_strength = FACE_STRENGTH_WEAK; } } @@ -292,7 +292,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, switch (mode) { case MOD_WEIGHTEDNORMAL_MODE_FACE: - for (int i = 0; i < numPolys; i++) { + for (int i = 0; i < polys_num; i++) { const int mp_index = mode_pair[i].index; const float mp_val = mode_pair[i].val; @@ -312,7 +312,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, case MOD_WEIGHTEDNORMAL_MODE_FACE_ANGLE: BLI_assert(loop_to_poly != NULL); - for (int i = 0; i < numLoops; i++) { + for (int i = 0; i < loops_num; i++) { const int ml_index = mode_pair[i].index; const float ml_val = mode_pair[i].val; @@ -330,7 +330,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, } /* Validate computed weighted normals. */ - for (int item_index = 0; item_index < num_items; item_index++) { + for (int item_index = 0; item_index < items_num; item_index++) { if (normalize_v3(items_data[item_index].normal) < CLNORS_VALID_VEC_LEN) { zero_v3(items_data[item_index].normal); } @@ -341,7 +341,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, * Note that loop_normals is already populated with clnors * (before this modifier is applied, at start of this function), * so no need to recompute them here. */ - for (int ml_index = 0; ml_index < numLoops; ml_index++) { + for (int ml_index = 0; ml_index < loops_num; ml_index++) { WeightedNormalDataAggregateItem *item_data = lnors_spacearr.lspacearr[ml_index]->user_data; if (!is_zero_v3(item_data->normal)) { copy_v3_v3(loop_normals[ml_index], item_data->normal); @@ -350,15 +350,15 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, BKE_mesh_normals_loop_custom_set(mvert, wn_data->vert_normals, - numVerts, + verts_num, medge, - numEdges, + edges_num, mloop, loop_normals, - numLoops, + loops_num, mpoly, polynors, - numPolys, + polys_num, clnors); } else { @@ -372,9 +372,9 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, * But think we can live with it for now, * and it makes code simpler & cleaner. */ float(*vert_normals)[3] = MEM_calloc_arrayN( - (size_t)numVerts, sizeof(*loop_normals), __func__); + (size_t)verts_num, sizeof(*loop_normals), __func__); - for (int ml_index = 0; ml_index < numLoops; ml_index++) { + for (int ml_index = 0; ml_index < loops_num; ml_index++) { const int mv_index = mloop[ml_index].v; copy_v3_v3(vert_normals[mv_index], items_data[mv_index].normal); } @@ -382,39 +382,39 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, BKE_mesh_normals_loop_custom_from_vertices_set(mvert, wn_data->vert_normals, vert_normals, - numVerts, + verts_num, medge, - numEdges, + edges_num, mloop, - numLoops, + loops_num, mpoly, polynors, - numPolys, + polys_num, clnors); MEM_freeN(vert_normals); } else { - loop_normals = MEM_calloc_arrayN((size_t)numLoops, sizeof(*loop_normals), __func__); + loop_normals = MEM_calloc_arrayN((size_t)loops_num, sizeof(*loop_normals), __func__); BKE_mesh_normals_loop_split(mvert, wn_data->vert_normals, - numVerts, + verts_num, medge, - numEdges, + edges_num, mloop, loop_normals, - numLoops, + loops_num, mpoly, polynors, - numPolys, + polys_num, true, split_angle, NULL, has_clnors ? clnors : NULL, loop_to_poly); - for (int ml_index = 0; ml_index < numLoops; ml_index++) { + for (int ml_index = 0; ml_index < loops_num; ml_index++) { const int item_index = mloop[ml_index].v; if (!is_zero_v3(items_data[item_index].normal)) { copy_v3_v3(loop_normals[ml_index], items_data[item_index].normal); @@ -423,15 +423,15 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, BKE_mesh_normals_loop_custom_set(mvert, wn_data->vert_normals, - numVerts, + verts_num, medge, - numEdges, + edges_num, mloop, loop_normals, - numLoops, + loops_num, mpoly, polynors, - numPolys, + polys_num, clnors); } } @@ -444,7 +444,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, static void wn_face_area(WeightedNormalModifierData *wnmd, WeightedNormalData *wn_data) { - const int numPolys = wn_data->numPolys; + const int polys_num = wn_data->polys_num; MVert *mvert = wn_data->mvert; MLoop *mloop = wn_data->mloop; @@ -453,15 +453,15 @@ static void wn_face_area(WeightedNormalModifierData *wnmd, WeightedNormalData *w MPoly *mp; int mp_index; - ModePair *face_area = MEM_malloc_arrayN((size_t)numPolys, sizeof(*face_area), __func__); + ModePair *face_area = MEM_malloc_arrayN((size_t)polys_num, sizeof(*face_area), __func__); ModePair *f_area = face_area; - for (mp_index = 0, mp = mpoly; mp_index < numPolys; mp_index++, mp++, f_area++) { + for (mp_index = 0, mp = mpoly; mp_index < polys_num; mp_index++, mp++, f_area++) { f_area->val = BKE_mesh_calc_poly_area(mp, &mloop[mp->loopstart], mvert); f_area->index = mp_index; } - qsort(face_area, numPolys, sizeof(*face_area), modepair_cmp_by_val_inverse); + qsort(face_area, polys_num, sizeof(*face_area), modepair_cmp_by_val_inverse); wn_data->mode_pair = face_area; apply_weights_vertex_normal(wnmd, wn_data); @@ -469,8 +469,8 @@ static void wn_face_area(WeightedNormalModifierData *wnmd, WeightedNormalData *w static void wn_corner_angle(WeightedNormalModifierData *wnmd, WeightedNormalData *wn_data) { - const int numLoops = wn_data->numLoops; - const int numPolys = wn_data->numPolys; + const int loops_num = wn_data->loops_num; + const int polys_num = wn_data->polys_num; MVert *mvert = wn_data->mvert; MLoop *mloop = wn_data->mloop; @@ -479,11 +479,11 @@ static void wn_corner_angle(WeightedNormalModifierData *wnmd, WeightedNormalData MPoly *mp; int mp_index; - int *loop_to_poly = MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__); + int *loop_to_poly = MEM_malloc_arrayN((size_t)loops_num, sizeof(*loop_to_poly), __func__); - ModePair *corner_angle = MEM_malloc_arrayN((size_t)numLoops, sizeof(*corner_angle), __func__); + ModePair *corner_angle = MEM_malloc_arrayN((size_t)loops_num, sizeof(*corner_angle), __func__); - for (mp_index = 0, mp = mpoly; mp_index < numPolys; mp_index++, mp++) { + for (mp_index = 0, mp = mpoly; mp_index < polys_num; mp_index++, mp++) { MLoop *ml_start = &mloop[mp->loopstart]; float *index_angle = MEM_malloc_arrayN((size_t)mp->totloop, sizeof(*index_angle), __func__); @@ -501,7 +501,7 @@ static void wn_corner_angle(WeightedNormalModifierData *wnmd, WeightedNormalData MEM_freeN(index_angle); } - qsort(corner_angle, numLoops, sizeof(*corner_angle), modepair_cmp_by_val_inverse); + qsort(corner_angle, loops_num, sizeof(*corner_angle), modepair_cmp_by_val_inverse); wn_data->loop_to_poly = loop_to_poly; wn_data->mode_pair = corner_angle; @@ -510,8 +510,8 @@ static void wn_corner_angle(WeightedNormalModifierData *wnmd, WeightedNormalData static void wn_face_with_angle(WeightedNormalModifierData *wnmd, WeightedNormalData *wn_data) { - const int numLoops = wn_data->numLoops; - const int numPolys = wn_data->numPolys; + const int loops_num = wn_data->loops_num; + const int polys_num = wn_data->polys_num; MVert *mvert = wn_data->mvert; MLoop *mloop = wn_data->mloop; @@ -520,11 +520,11 @@ static void wn_face_with_angle(WeightedNormalModifierData *wnmd, WeightedNormalD MPoly *mp; int mp_index; - int *loop_to_poly = MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__); + int *loop_to_poly = MEM_malloc_arrayN((size_t)loops_num, sizeof(*loop_to_poly), __func__); - ModePair *combined = MEM_malloc_arrayN((size_t)numLoops, sizeof(*combined), __func__); + ModePair *combined = MEM_malloc_arrayN((size_t)loops_num, sizeof(*combined), __func__); - for (mp_index = 0, mp = mpoly; mp_index < numPolys; mp_index++, mp++) { + for (mp_index = 0, mp = mpoly; mp_index < polys_num; mp_index++, mp++) { MLoop *ml_start = &mloop[mp->loopstart]; float face_area = BKE_mesh_calc_poly_area(mp, ml_start, mvert); @@ -544,7 +544,7 @@ static void wn_face_with_angle(WeightedNormalModifierData *wnmd, WeightedNormalD MEM_freeN(index_angle); } - qsort(combined, numLoops, sizeof(*combined), modepair_cmp_by_val_inverse); + qsort(combined, loops_num, sizeof(*combined), modepair_cmp_by_val_inverse); wn_data->loop_to_poly = loop_to_poly; wn_data->mode_pair = combined; @@ -575,10 +575,10 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * Mesh *result; result = (Mesh *)BKE_id_copy_ex(NULL, &mesh->id, NULL, LIB_ID_COPY_LOCALIZE); - const int numVerts = result->totvert; - const int numEdges = result->totedge; - const int numLoops = result->totloop; - const int numPolys = result->totpoly; + const int verts_num = result->totvert; + const int edges_num = result->totedge; + const int loops_num = result->totloop; + const int polys_num = result->totpoly; MEdge *medge = result->medge; MPoly *mpoly = result->mpoly; @@ -611,7 +611,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * * it helps when generating clnor spaces and default normals. */ const bool has_clnors = clnors != NULL; if (!clnors) { - clnors = CustomData_add_layer(ldata, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, numLoops); + clnors = CustomData_add_layer(ldata, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, loops_num); } MDeformVert *dvert; @@ -619,10 +619,10 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * MOD_get_vgroup(ctx->object, mesh, wnmd->defgrp_name, &dvert, &defgrp_index); WeightedNormalData wn_data = { - .numVerts = numVerts, - .numEdges = numEdges, - .numLoops = numLoops, - .numPolys = numPolys, + .verts_num = verts_num, + .edges_num = edges_num, + .loops_num = loops_num, + .polys_num = polys_num, .mvert = mvert, .vert_normals = BKE_mesh_vertex_normals_ensure(result), diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.c b/source/blender/modifiers/intern/MOD_weightvg_util.c index a5c901dbe7a..b251825cd95 100644 --- a/source/blender/modifiers/intern/MOD_weightvg_util.c +++ b/source/blender/modifiers/intern/MOD_weightvg_util.c @@ -135,7 +135,7 @@ void weightvg_do_mask(const ModifierEvalContext *ctx, float(*tex_co)[3]; /* See mapping note below... */ MappingInfoModifierData t_map; - const int numVerts = mesh->totvert; + const int verts_num = mesh->totvert; /* Use new generic get_texture_coords, but do not modify our DNA struct for it... * XXX Why use a ModifierData stuff here ? Why not a simple, generic struct for parameters? @@ -148,7 +148,7 @@ void weightvg_do_mask(const ModifierEvalContext *ctx, BLI_strncpy(t_map.uvlayer_name, tex_uvlayer_name, sizeof(t_map.uvlayer_name)); t_map.texmapping = tex_mapping; - tex_co = MEM_calloc_arrayN(numVerts, sizeof(*tex_co), "WeightVG Modifier, TEX mode, tex_co"); + tex_co = MEM_calloc_arrayN(verts_num, sizeof(*tex_co), "WeightVG Modifier, TEX mode, tex_co"); MOD_get_texture_coords(&t_map, ctx, ob, mesh, NULL, tex_co); MOD_init_texture(&t_map, ctx); diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c index bce8ce82423..2c733542e51 100644 --- a/source/blender/modifiers/intern/MOD_weightvgedit.c +++ b/source/blender/modifiers/intern/MOD_weightvgedit.c @@ -97,9 +97,7 @@ static void requiredDataMask(Object *UNUSED(ob), /* No need to ask for CD_PREVIEW_MLOOPCOL... */ } -static bool dependsOnTime(struct Scene *UNUSED(scene), - ModifierData *md, - const int UNUSED(dag_eval_mode)) +static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md) { WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md; @@ -176,12 +174,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * #endif /* Get number of verts. */ - const int numVerts = mesh->totvert; + const int verts_num = mesh->totvert; /* Check if we can just return the original mesh. * Must have verts and therefore verts assigned to vgroups to do anything useful! */ - if ((numVerts == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) { + if ((verts_num == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) { return mesh; } @@ -201,11 +199,11 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } if (has_mdef) { - dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, numVerts); + dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, verts_num); } else { /* Add a valid data layer! */ - dvert = CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, numVerts); + dvert = CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, verts_num); } /* Ultimate security check. */ if (!dvert) { @@ -214,10 +212,10 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * mesh->dvert = dvert; /* Get org weights, assuming 0.0 for vertices not in given vgroup. */ - org_w = MEM_malloc_arrayN(numVerts, sizeof(float), "WeightVGEdit Modifier, org_w"); - new_w = MEM_malloc_arrayN(numVerts, sizeof(float), "WeightVGEdit Modifier, new_w"); - dw = MEM_malloc_arrayN(numVerts, sizeof(MDeformWeight *), "WeightVGEdit Modifier, dw"); - for (i = 0; i < numVerts; i++) { + org_w = MEM_malloc_arrayN(verts_num, sizeof(float), "WeightVGEdit Modifier, org_w"); + new_w = MEM_malloc_arrayN(verts_num, sizeof(float), "WeightVGEdit Modifier, new_w"); + dw = MEM_malloc_arrayN(verts_num, sizeof(MDeformWeight *), "WeightVGEdit Modifier, dw"); + for (i = 0; i < verts_num; i++) { dw[i] = BKE_defvert_find_index(&dvert[i], defgrp_index); if (dw[i]) { org_w[i] = new_w[i] = dw[i]->weight; @@ -237,7 +235,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * rng = BLI_rng_new_srandom(BLI_ghashutil_strhash(ctx->object->id.name + 2)); } - weightvg_do_map(numVerts, new_w, wmd->falloff_type, do_invert_mapping, wmd->cmap_curve, rng); + weightvg_do_map(verts_num, new_w, wmd->falloff_type, do_invert_mapping, wmd->cmap_curve, rng); if (rng) { BLI_rng_free(rng); @@ -247,7 +245,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Do masking. */ struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); weightvg_do_mask(ctx, - numVerts, + verts_num, NULL, org_w, new_w, @@ -268,7 +266,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * weightvg_update_vg(dvert, defgrp_index, dw, - numVerts, + verts_num, NULL, org_w, do_add, diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index 7f9bf9d1e80..b827d41e80a 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -145,9 +145,7 @@ static void requiredDataMask(Object *UNUSED(ob), /* No need to ask for CD_PREVIEW_MLOOPCOL... */ } -static bool dependsOnTime(struct Scene *UNUSED(scene), - ModifierData *md, - const int UNUSED(dag_eval_mode)) +static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md) { WeightVGMixModifierData *wmd = (WeightVGMixModifierData *)md; @@ -213,7 +211,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * float *org_w; float *new_w; int *tidx, *indices = NULL; - int numIdx = 0; + int index_num = 0; int i; const bool invert_vgroup_mask = (wmd->flag & MOD_WVG_MIX_INVERT_VGROUP_MASK) != 0; const bool do_normalize = (wmd->flag & MOD_WVG_MIX_WEIGHTS_NORMALIZE) != 0; @@ -233,12 +231,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * #endif /* Get number of verts. */ - const int numVerts = mesh->totvert; + const int verts_num = mesh->totvert; /* Check if we can just return the original mesh. * Must have verts and therefore verts assigned to vgroups to do anything useful! */ - if ((numVerts == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) { + if ((verts_num == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) { return mesh; } @@ -266,11 +264,11 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } if (has_mdef) { - dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, numVerts); + dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, verts_num); } else { /* Add a valid data layer! */ - dvert = CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, numVerts); + dvert = CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, verts_num); } /* Ultimate security check. */ if (!dvert) { @@ -279,107 +277,107 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * mesh->dvert = dvert; /* Find out which vertices to work on. */ - tidx = MEM_malloc_arrayN(numVerts, sizeof(int), "WeightVGMix Modifier, tidx"); - tdw1 = MEM_malloc_arrayN(numVerts, sizeof(MDeformWeight *), "WeightVGMix Modifier, tdw1"); - tdw2 = MEM_malloc_arrayN(numVerts, sizeof(MDeformWeight *), "WeightVGMix Modifier, tdw2"); + tidx = MEM_malloc_arrayN(verts_num, sizeof(int), "WeightVGMix Modifier, tidx"); + tdw1 = MEM_malloc_arrayN(verts_num, sizeof(MDeformWeight *), "WeightVGMix Modifier, tdw1"); + tdw2 = MEM_malloc_arrayN(verts_num, sizeof(MDeformWeight *), "WeightVGMix Modifier, tdw2"); switch (wmd->mix_set) { case MOD_WVG_SET_A: /* All vertices in first vgroup. */ - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { MDeformWeight *dw = BKE_defvert_find_index(&dvert[i], defgrp_index); if (dw) { - tdw1[numIdx] = dw; - tdw2[numIdx] = (defgrp_index_other >= 0) ? - BKE_defvert_find_index(&dvert[i], defgrp_index_other) : - NULL; - tidx[numIdx++] = i; + tdw1[index_num] = dw; + tdw2[index_num] = (defgrp_index_other >= 0) ? + BKE_defvert_find_index(&dvert[i], defgrp_index_other) : + NULL; + tidx[index_num++] = i; } } break; case MOD_WVG_SET_B: /* All vertices in second vgroup. */ - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { MDeformWeight *dw = (defgrp_index_other >= 0) ? BKE_defvert_find_index(&dvert[i], defgrp_index_other) : NULL; if (dw) { - tdw1[numIdx] = BKE_defvert_find_index(&dvert[i], defgrp_index); - tdw2[numIdx] = dw; - tidx[numIdx++] = i; + tdw1[index_num] = BKE_defvert_find_index(&dvert[i], defgrp_index); + tdw2[index_num] = dw; + tidx[index_num++] = i; } } break; case MOD_WVG_SET_OR: /* All vertices in one vgroup or the other. */ - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { MDeformWeight *adw = BKE_defvert_find_index(&dvert[i], defgrp_index); MDeformWeight *bdw = (defgrp_index_other >= 0) ? BKE_defvert_find_index(&dvert[i], defgrp_index_other) : NULL; if (adw || bdw) { - tdw1[numIdx] = adw; - tdw2[numIdx] = bdw; - tidx[numIdx++] = i; + tdw1[index_num] = adw; + tdw2[index_num] = bdw; + tidx[index_num++] = i; } } break; case MOD_WVG_SET_AND: /* All vertices in both vgroups. */ - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { MDeformWeight *adw = BKE_defvert_find_index(&dvert[i], defgrp_index); MDeformWeight *bdw = (defgrp_index_other >= 0) ? BKE_defvert_find_index(&dvert[i], defgrp_index_other) : NULL; if (adw && bdw) { - tdw1[numIdx] = adw; - tdw2[numIdx] = bdw; - tidx[numIdx++] = i; + tdw1[index_num] = adw; + tdw2[index_num] = bdw; + tidx[index_num++] = i; } } break; case MOD_WVG_SET_ALL: default: /* Use all vertices. */ - for (i = 0; i < numVerts; i++) { + for (i = 0; i < verts_num; i++) { tdw1[i] = BKE_defvert_find_index(&dvert[i], defgrp_index); tdw2[i] = (defgrp_index_other >= 0) ? BKE_defvert_find_index(&dvert[i], defgrp_index_other) : NULL; } - numIdx = -1; + index_num = -1; break; } - if (numIdx == 0) { + if (index_num == 0) { /* Use no vertices! Hence, return org data. */ MEM_freeN(tdw1); MEM_freeN(tdw2); MEM_freeN(tidx); return mesh; } - if (numIdx != -1) { - indices = MEM_malloc_arrayN(numIdx, sizeof(int), "WeightVGMix Modifier, indices"); - memcpy(indices, tidx, sizeof(int) * numIdx); - dw1 = MEM_malloc_arrayN(numIdx, sizeof(MDeformWeight *), "WeightVGMix Modifier, dw1"); - memcpy(dw1, tdw1, sizeof(MDeformWeight *) * numIdx); + if (index_num != -1) { + indices = MEM_malloc_arrayN(index_num, sizeof(int), "WeightVGMix Modifier, indices"); + memcpy(indices, tidx, sizeof(int) * index_num); + dw1 = MEM_malloc_arrayN(index_num, sizeof(MDeformWeight *), "WeightVGMix Modifier, dw1"); + memcpy(dw1, tdw1, sizeof(MDeformWeight *) * index_num); MEM_freeN(tdw1); - dw2 = MEM_malloc_arrayN(numIdx, sizeof(MDeformWeight *), "WeightVGMix Modifier, dw2"); - memcpy(dw2, tdw2, sizeof(MDeformWeight *) * numIdx); + dw2 = MEM_malloc_arrayN(index_num, sizeof(MDeformWeight *), "WeightVGMix Modifier, dw2"); + memcpy(dw2, tdw2, sizeof(MDeformWeight *) * index_num); MEM_freeN(tdw2); } else { /* Use all vertices. */ - numIdx = numVerts; + index_num = verts_num; /* Just copy MDeformWeight pointers arrays, they will be freed at the end. */ dw1 = tdw1; dw2 = tdw2; } MEM_freeN(tidx); - org_w = MEM_malloc_arrayN(numIdx, sizeof(float), "WeightVGMix Modifier, org_w"); - new_w = MEM_malloc_arrayN(numIdx, sizeof(float), "WeightVGMix Modifier, new_w"); + org_w = MEM_malloc_arrayN(index_num, sizeof(float), "WeightVGMix Modifier, org_w"); + new_w = MEM_malloc_arrayN(index_num, sizeof(float), "WeightVGMix Modifier, new_w"); /* Mix weights. */ - for (i = 0; i < numIdx; i++) { + for (i = 0; i < index_num; i++) { float weight2; if (invert_vgroup_a) { org_w[i] = 1.0f - (dw1[i] ? dw1[i]->weight : wmd->default_weight_a); @@ -400,7 +398,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Do masking. */ struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); weightvg_do_mask(ctx, - numIdx, + index_num, indices, org_w, new_w, @@ -420,13 +418,22 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Update (add to) vgroup. * XXX Depending on the MOD_WVG_SET_xxx option chosen, we might have to add vertices to vgroup. */ - weightvg_update_vg( - dvert, defgrp_index, dw1, numIdx, indices, org_w, true, -FLT_MAX, false, 0.0f, do_normalize); + weightvg_update_vg(dvert, + defgrp_index, + dw1, + index_num, + indices, + org_w, + true, + -FLT_MAX, + false, + 0.0f, + do_normalize); /* If weight preview enabled... */ #if 0 /* XXX Currently done in mod stack :/ */ if (do_prev) { - DM_update_weight_mcol(ob, dm, 0, org_w, numIdx, indices); + DM_update_weight_mcol(ob, dm, 0, org_w, index_num, indices); } #endif diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 647db5c5aa4..43a90b2a4ac 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -143,7 +143,7 @@ static void vert2geom_task_cb_ex(void *__restrict userdata, /** * Find nearest vertex and/or edge and/or face, for each vertex (adapted from shrinkwrap.c). */ -static void get_vert2geom_distance(int numVerts, +static void get_vert2geom_distance(int verts_num, float (*v_cos)[3], float *dist_v, float *dist_e, @@ -194,10 +194,10 @@ static void get_vert2geom_distance(int numVerts, TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.use_threading = (numVerts > 10000); + settings.use_threading = (verts_num > 10000); settings.userdata_chunk = &data_chunk; settings.userdata_chunk_size = sizeof(data_chunk); - BLI_task_parallel_range(0, numVerts, &data, vert2geom_task_cb_ex, &settings); + BLI_task_parallel_range(0, verts_num, &data, vert2geom_task_cb_ex, &settings); if (dist_v) { free_bvhtree_from_mesh(&treeData_v); @@ -215,11 +215,11 @@ static void get_vert2geom_distance(int numVerts, * Note that it works in final world space (i.e. with constraints etc. applied). */ static void get_vert2ob_distance( - int numVerts, float (*v_cos)[3], float *dist, Object *ob, Object *obr) + int verts_num, float (*v_cos)[3], float *dist, Object *ob, Object *obr) { /* Vertex and ref object coordinates. */ float v_wco[3]; - uint i = numVerts; + uint i = verts_num; while (i-- > 0) { /* Get world-coordinates of the vertex (constraints and anim included). */ @@ -347,9 +347,7 @@ static void requiredDataMask(Object *UNUSED(ob), /* No need to ask for CD_PREVIEW_MLOOPCOL... */ } -static bool dependsOnTime(struct Scene *UNUSED(scene), - ModifierData *md, - const int UNUSED(dag_eval_mode)) +static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md) { WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *)md; @@ -435,7 +433,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * float *org_w = NULL; float *new_w = NULL; int *tidx, *indices = NULL; - int numIdx = 0; + int index_num = 0; int i; const bool invert_vgroup_mask = (wmd->proximity_flags & MOD_WVG_PROXIMITY_INVERT_VGROUP_MASK) != 0; @@ -450,12 +448,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * #endif /* Get number of verts. */ - const int numVerts = mesh->totvert; + const int verts_num = mesh->totvert; /* Check if we can just return the original mesh. * Must have verts and therefore verts assigned to vgroups to do anything useful! */ - if ((numVerts == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) { + if ((verts_num == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) { return mesh; } @@ -477,7 +475,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * return mesh; } - dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, numVerts); + dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, verts_num); /* Ultimate security check. */ if (!dvert) { return mesh; @@ -485,31 +483,31 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * mesh->dvert = dvert; /* Find out which vertices to work on (all vertices in vgroup), and get their relevant weight. */ - tidx = MEM_malloc_arrayN(numVerts, sizeof(int), "WeightVGProximity Modifier, tidx"); - tw = MEM_malloc_arrayN(numVerts, sizeof(float), "WeightVGProximity Modifier, tw"); - tdw = MEM_malloc_arrayN(numVerts, sizeof(MDeformWeight *), "WeightVGProximity Modifier, tdw"); - for (i = 0; i < numVerts; i++) { + tidx = MEM_malloc_arrayN(verts_num, sizeof(int), "WeightVGProximity Modifier, tidx"); + tw = MEM_malloc_arrayN(verts_num, sizeof(float), "WeightVGProximity Modifier, tw"); + tdw = MEM_malloc_arrayN(verts_num, sizeof(MDeformWeight *), "WeightVGProximity Modifier, tdw"); + for (i = 0; i < verts_num; i++) { MDeformWeight *_dw = BKE_defvert_find_index(&dvert[i], defgrp_index); if (_dw) { - tidx[numIdx] = i; - tw[numIdx] = _dw->weight; - tdw[numIdx++] = _dw; + tidx[index_num] = i; + tw[index_num] = _dw->weight; + tdw[index_num++] = _dw; } } /* If no vertices found, return org data! */ - if (numIdx == 0) { + if (index_num == 0) { MEM_freeN(tidx); MEM_freeN(tw); MEM_freeN(tdw); return mesh; } - if (numIdx != numVerts) { - indices = MEM_malloc_arrayN(numIdx, sizeof(int), "WeightVGProximity Modifier, indices"); - memcpy(indices, tidx, sizeof(int) * numIdx); - org_w = MEM_malloc_arrayN(numIdx, sizeof(float), "WeightVGProximity Modifier, org_w"); - memcpy(org_w, tw, sizeof(float) * numIdx); - dw = MEM_malloc_arrayN(numIdx, sizeof(MDeformWeight *), "WeightVGProximity Modifier, dw"); - memcpy(dw, tdw, sizeof(MDeformWeight *) * numIdx); + if (index_num != verts_num) { + indices = MEM_malloc_arrayN(index_num, sizeof(int), "WeightVGProximity Modifier, indices"); + memcpy(indices, tidx, sizeof(int) * index_num); + org_w = MEM_malloc_arrayN(index_num, sizeof(float), "WeightVGProximity Modifier, org_w"); + memcpy(org_w, tw, sizeof(float) * index_num); + dw = MEM_malloc_arrayN(index_num, sizeof(MDeformWeight *), "WeightVGProximity Modifier, dw"); + memcpy(dw, tdw, sizeof(MDeformWeight *) * index_num); MEM_freeN(tw); MEM_freeN(tdw); } @@ -517,14 +515,14 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * org_w = tw; dw = tdw; } - new_w = MEM_malloc_arrayN(numIdx, sizeof(float), "WeightVGProximity Modifier, new_w"); + new_w = MEM_malloc_arrayN(index_num, sizeof(float), "WeightVGProximity Modifier, new_w"); MEM_freeN(tidx); /* Get our vertex coordinates. */ - if (numIdx != numVerts) { + if (index_num != verts_num) { float(*tv_cos)[3] = BKE_mesh_vert_coords_alloc(mesh, NULL); - v_cos = MEM_malloc_arrayN(numIdx, sizeof(float[3]), "WeightVGProximity Modifier, v_cos"); - for (i = 0; i < numIdx; i++) { + v_cos = MEM_malloc_arrayN(index_num, sizeof(float[3]), "WeightVGProximity Modifier, v_cos"); + for (i = 0; i < index_num; i++) { copy_v3_v3(v_cos[i], tv_cos[indices[i]]); } MEM_freeN(tv_cos); @@ -536,7 +534,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Compute wanted distances. */ if (wmd->proximity_mode == MOD_WVG_PROXIMITY_OBJECT) { const float dist = get_ob2ob_distance(ob, obr); - for (i = 0; i < numIdx; i++) { + for (i = 0; i < index_num; i++) { new_w[i] = dist; } } @@ -556,16 +554,17 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * BKE_mesh_wrapper_ensure_mdata(target_mesh); SpaceTransform loc2trgt; - float *dists_v = use_trgt_verts ? MEM_malloc_arrayN(numIdx, sizeof(float), "dists_v") : + float *dists_v = use_trgt_verts ? MEM_malloc_arrayN(index_num, sizeof(float), "dists_v") : NULL; - float *dists_e = use_trgt_edges ? MEM_malloc_arrayN(numIdx, sizeof(float), "dists_e") : + float *dists_e = use_trgt_edges ? MEM_malloc_arrayN(index_num, sizeof(float), "dists_e") : NULL; - float *dists_f = use_trgt_faces ? MEM_malloc_arrayN(numIdx, sizeof(float), "dists_f") : + float *dists_f = use_trgt_faces ? MEM_malloc_arrayN(index_num, sizeof(float), "dists_f") : NULL; BLI_SPACE_TRANSFORM_SETUP(&loc2trgt, ob, obr); - get_vert2geom_distance(numIdx, v_cos, dists_v, dists_e, dists_f, target_mesh, &loc2trgt); - for (i = 0; i < numIdx; i++) { + get_vert2geom_distance( + index_num, v_cos, dists_v, dists_e, dists_f, target_mesh, &loc2trgt); + for (i = 0; i < index_num; i++) { new_w[i] = dists_v ? dists_v[i] : FLT_MAX; if (dists_e) { new_w[i] = min_ff(dists_e[i], new_w[i]); @@ -581,18 +580,18 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } /* Else, fall back to default obj2vert behavior. */ else { - get_vert2ob_distance(numIdx, v_cos, new_w, ob, obr); + get_vert2ob_distance(index_num, v_cos, new_w, ob, obr); } } else { - get_vert2ob_distance(numIdx, v_cos, new_w, ob, obr); + get_vert2ob_distance(index_num, v_cos, new_w, ob, obr); } } /* Map distances to weights. */ do_map(ob, new_w, - numIdx, + index_num, wmd->min_dist, wmd->max_dist, wmd->falloff_type, @@ -602,7 +601,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Do masking. */ struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); weightvg_do_mask(ctx, - numIdx, + index_num, indices, org_w, new_w, @@ -621,12 +620,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Update vgroup. Note we never add nor remove vertices from vgroup here. */ weightvg_update_vg( - dvert, defgrp_index, dw, numIdx, indices, org_w, false, 0.0f, false, 0.0f, do_normalize); + dvert, defgrp_index, dw, index_num, indices, org_w, false, 0.0f, false, 0.0f, do_normalize); /* If weight preview enabled... */ #if 0 /* XXX Currently done in mod stack :/ */ if (do_prev) { - DM_update_weight_mcol(ob, dm, 0, org_w, numIdx, indices); + DM_update_weight_mcol(ob, dm, 0, org_w, index_num, indices); } #endif diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index dc0965f5d71..96a1904abdd 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -6,6 +6,7 @@ #include "FN_multi_function_builder.hh" #include "BKE_attribute_access.hh" +#include "BKE_geometry_fields.hh" #include "BKE_geometry_set.hh" #include "BKE_geometry_set_instances.hh" diff --git a/source/blender/nodes/NOD_geometry_nodes_eval_log.hh b/source/blender/nodes/NOD_geometry_nodes_eval_log.hh index 319fcdeebb7..16332be5179 100644 --- a/source/blender/nodes/NOD_geometry_nodes_eval_log.hh +++ b/source/blender/nodes/NOD_geometry_nodes_eval_log.hh @@ -26,6 +26,8 @@ #include "NOD_derived_node_tree.hh" +#include "FN_field.hh" + #include <chrono> struct SpaceNode; @@ -353,6 +355,8 @@ class ModifierLog { static const TreeLog *find_tree_by_node_editor_context(const SpaceNode &snode); static const NodeLog *find_node_by_node_editor_context(const SpaceNode &snode, const bNode &node); + static const NodeLog *find_node_by_node_editor_context(const SpaceNode &snode, + const StringRef node_name); static const SocketLog *find_socket_by_node_editor_context(const SpaceNode &snode, const bNode &node, const bNodeSocket &socket); diff --git a/source/blender/nodes/composite/nodes/node_composite_cryptomatte.cc b/source/blender/nodes/composite/nodes/node_composite_cryptomatte.cc index 162ef07a6dd..67d861aad9f 100644 --- a/source/blender/nodes/composite/nodes/node_composite_cryptomatte.cc +++ b/source/blender/nodes/composite/nodes/node_composite_cryptomatte.cc @@ -323,8 +323,8 @@ bNodeSocket *ntreeCompositCryptomatteAddSocket(bNodeTree *ntree, bNode *node) BLI_assert(node->type == CMP_NODE_CRYPTOMATTE_LEGACY); NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage); char sockname[32]; - n->num_inputs++; - BLI_snprintf(sockname, sizeof(sockname), "Crypto %.2d", n->num_inputs - 1); + n->inputs_num++; + BLI_snprintf(sockname, sizeof(sockname), "Crypto %.2d", n->inputs_num - 1); bNodeSocket *sock = nodeAddStaticSocket( ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, nullptr, sockname); return sock; @@ -334,12 +334,12 @@ int ntreeCompositCryptomatteRemoveSocket(bNodeTree *ntree, bNode *node) { BLI_assert(node->type == CMP_NODE_CRYPTOMATTE_LEGACY); NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage); - if (n->num_inputs < 2) { + if (n->inputs_num < 2) { return 0; } bNodeSocket *sock = static_cast<bNodeSocket *>(node->inputs.last); nodeRemoveSocket(ntree, node, sock); - n->num_inputs--; + n->inputs_num--; return 1; } diff --git a/source/blender/nodes/composite/nodes/node_composite_normal.cc b/source/blender/nodes/composite/nodes/node_composite_normal.cc index c04e4bed660..b4dd0bbacd0 100644 --- a/source/blender/nodes/composite/nodes/node_composite_normal.cc +++ b/source/blender/nodes/composite/nodes/node_composite_normal.cc @@ -14,11 +14,15 @@ namespace blender::nodes::node_composite_normal_cc { static void cmp_node_normal_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Vector>(N_("Normal")) - .default_value({1.0f, 1.0f, 1.0f}) + .default_value({0.0f, 0.0f, 1.0f}) + .min(-1.0f) + .max(1.0f) + .subtype(PROP_DIRECTION); + b.add_output<decl::Vector>(N_("Normal")) + .default_value({0.0f, 0.0f, 1.0f}) .min(-1.0f) .max(1.0f) .subtype(PROP_DIRECTION); - b.add_output<decl::Vector>(N_("Normal")); b.add_output<decl::Float>(N_("Dot")); } diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh index 5b7211e44b4..7af3159bbf8 100644 --- a/source/blender/nodes/geometry/node_geometry_util.hh +++ b/source/blender/nodes/geometry/node_geometry_util.hh @@ -81,4 +81,14 @@ void separate_geometry(GeometrySet &geometry_set, std::optional<CustomDataType> node_data_type_to_custom_data_type(eNodeSocketDatatype type); std::optional<CustomDataType> node_socket_to_custom_data_type(const bNodeSocket &socket); +class SplineLengthFieldInput final : public GeometryFieldInput { + public: + SplineLengthFieldInput(); + GVArray get_varray_for_context(const GeometryComponent &component, + AttributeDomain domain, + IndexMask mask) const final; + uint64_t hash() const override; + bool is_equal_to(const fn::FieldNode &other) const override; +}; + } // namespace blender::nodes diff --git a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc index 6794671f707..4792fada98b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc @@ -30,25 +30,25 @@ static Mesh *hull_from_bullet(const Mesh *mesh, Span<float3> coords) { plConvexHull hull = plConvexHullCompute((float(*)[3])coords.data(), coords.size()); - const int num_verts = plConvexHullNumVertices(hull); - const int num_faces = num_verts <= 2 ? 0 : plConvexHullNumFaces(hull); - const int num_loops = num_verts <= 2 ? 0 : plConvexHullNumLoops(hull); + const int verts_num = plConvexHullNumVertices(hull); + const int faces_num = verts_num <= 2 ? 0 : plConvexHullNumFaces(hull); + const int loops_num = verts_num <= 2 ? 0 : plConvexHullNumLoops(hull); /* Half as many edges as loops, because the mesh is manifold. */ - const int num_edges = num_verts == 2 ? 1 : num_verts < 2 ? 0 : num_loops / 2; + const int edges_num = verts_num == 2 ? 1 : verts_num < 2 ? 0 : loops_num / 2; /* Create Mesh *result with proper capacity. */ Mesh *result; if (mesh) { result = BKE_mesh_new_nomain_from_template( - mesh, num_verts, num_edges, 0, num_loops, num_faces); + mesh, verts_num, edges_num, 0, loops_num, faces_num); } else { - result = BKE_mesh_new_nomain(num_verts, num_edges, 0, num_loops, num_faces); + result = BKE_mesh_new_nomain(verts_num, edges_num, 0, loops_num, faces_num); BKE_id_material_eval_ensure_default_slot(&result->id); } /* Copy vertices. */ - for (const int i : IndexRange(num_verts)) { + for (const int i : IndexRange(verts_num)) { float co[3]; int original_index; plConvexHullGetVertex(hull, i, co, &original_index); @@ -73,9 +73,9 @@ static Mesh *hull_from_bullet(const Mesh *mesh, Span<float3> coords) /* NOTE: ConvexHull from Bullet uses a half-edge data structure * for its mesh. To convert that, each half-edge needs to be converted * to a loop and edges need to be created from that. */ - Array<MLoop> mloop_src(num_loops); + Array<MLoop> mloop_src(loops_num); uint edge_index = 0; - for (const int i : IndexRange(num_loops)) { + for (const int i : IndexRange(loops_num)) { int v_from; int v_to; plConvexHullGetLoop(hull, i, &v_from, &v_to); @@ -95,7 +95,7 @@ static Mesh *hull_from_bullet(const Mesh *mesh, Span<float3> coords) edge_index++; } } - if (num_edges == 1) { + if (edges_num == 1) { /* In this case there are no loops. */ MEdge &edge = result->medge[0]; edge.v1 = 0; @@ -103,13 +103,13 @@ static Mesh *hull_from_bullet(const Mesh *mesh, Span<float3> coords) edge.flag |= ME_EDGEDRAW | ME_EDGERENDER | ME_LOOSEEDGE; edge_index++; } - BLI_assert(edge_index == num_edges); + BLI_assert(edge_index == edges_num); /* Copy faces. */ Array<int> loops; int j = 0; MLoop *loop = result->mloop; - for (const int i : IndexRange(num_faces)) { + for (const int i : IndexRange(faces_num)) { const int len = plConvexHullGetFaceSize(hull, i); BLI_assert(len > 2); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc index 81ca87eec25..95ea978541c 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc @@ -551,8 +551,8 @@ static std::unique_ptr<CurveEval> fillet_curve(const CurveEval &input_curve, Span<SplinePtr> input_splines = input_curve.splines(); std::unique_ptr<CurveEval> output_curve = std::make_unique<CurveEval>(); - const int num_splines = input_splines.size(); - output_curve->resize(num_splines); + const int splines_num = input_splines.size(); + output_curve->resize(splines_num); MutableSpan<SplinePtr> output_splines = output_curve->splines(); Array<int> spline_offsets = input_curve.control_point_offsets(); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_length.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_length.cc index d5769c691c8..11eb472a6e2 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_length.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_length.cc @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -#include "BKE_spline.hh" +#include "BKE_curves.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_curve_length_cc { @@ -18,11 +19,18 @@ static void node_geo_exec(GeoNodeExecParams params) params.set_default_remaining_outputs(); return; } - const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_set.get_curves_for_read()); + + const Curves &curves_id = *curve_set.get_curves_for_read(); + const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); + const VArray<bool> cyclic = curves.cyclic(); + + curves.ensure_evaluated_lengths(); + float length = 0.0f; - for (const SplinePtr &spline : curve->splines()) { - length += spline->length(); + for (const int i : curves.curves_range()) { + length += curves.evaluated_length_total_for_curve(i, cyclic[i]); } + params.set_output("Length", length); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc index 5a4c2ad1660..139b17138fa 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc @@ -1,11 +1,13 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ #include "BLI_array.hh" +#include "BLI_index_mask_ops.hh" +#include "BLI_length_parameterize.hh" #include "BLI_task.hh" #include "BLI_timeit.hh" #include "BKE_attribute_math.hh" -#include "BKE_spline.hh" +#include "BKE_curves.hh" #include "UI_interface.h" #include "UI_resources.h" @@ -23,7 +25,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input<decl::Int>(N_("Count")).default_value(10).min(1).max(100000).supports_field(); b.add_input<decl::Float>(N_("Length")) .default_value(0.1f) - .min(0.001f) + .min(0.01f) .supports_field() .subtype(PROP_DISTANCE); b.add_output<decl::Geometry>(N_("Curve")); @@ -54,195 +56,549 @@ static void node_update(bNodeTree *ntree, bNode *node) nodeSetSocketAvailability(ntree, length_socket, mode == GEO_NODE_CURVE_RESAMPLE_LENGTH); } -struct SampleModeParam { - GeometryNodeCurveResampleMode mode; - std::optional<Field<float>> length; - std::optional<Field<int>> count; - Field<bool> selection; +/** Returns the number of evaluated points in each curve. Used to deselect curves with none. */ +class EvaluatedCountFieldInput final : public GeometryFieldInput { + public: + EvaluatedCountFieldInput() : GeometryFieldInput(CPPType::get<int>(), "Evaluated Point Count") + { + category_ = Category::Generated; + } + + GVArray get_varray_for_context(const GeometryComponent &component, + const AttributeDomain domain, + IndexMask UNUSED(mask)) const final + { + if (component.type() == GEO_COMPONENT_TYPE_CURVE && domain == ATTR_DOMAIN_CURVE && + !component.is_empty()) { + const CurveComponent &curve_component = static_cast<const CurveComponent &>(component); + const Curves &curves_id = *curve_component.get_for_read(); + const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); + curves.ensure_evaluated_offsets(); + return VArray<int>::ForFunc(curves.curves_num(), [&](const int64_t index) -> int { + return curves.evaluated_points_for_curve(index).size(); + }); + } + return {}; + } + + uint64_t hash() const override + { + /* Some random constant hash. */ + return 234905872379865; + } + + bool is_equal_to(const fn::FieldNode &other) const override + { + return dynamic_cast<const EvaluatedCountFieldInput *>(&other) != nullptr; + } }; -static SplinePtr resample_spline(const Spline &src, const int count) +/** + * Return true if the attribute should be copied/interpolated to the result curves. + * Don't output attributes that correspond to curve types that have no curves in the result. + */ +static bool interpolate_attribute_to_curves(const AttributeIDRef &attribute_id, + const std::array<int, CURVE_TYPES_NUM> &type_counts) { - std::unique_ptr<PolySpline> dst = std::make_unique<PolySpline>(); - Spline::copy_base_settings(src, *dst); - - if (src.evaluated_edges_size() < 1 || count == 1) { - dst->resize(1); - dst->positions().first() = src.positions().first(); - dst->radii().first() = src.radii().first(); - dst->tilts().first() = src.tilts().first(); - - src.attributes.foreach_attribute( - [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { - std::optional<GSpan> src_attribute = src.attributes.get_for_read(attribute_id); - if (dst->attributes.create(attribute_id, meta_data.data_type)) { - std::optional<GMutableSpan> dst_attribute = dst->attributes.get_for_write( - attribute_id); - if (dst_attribute) { - src_attribute->type().copy_assign(src_attribute->data(), dst_attribute->data()); - return true; - } - } - BLI_assert_unreachable(); - return false; - }, - ATTR_DOMAIN_POINT); - return dst; + if (!attribute_id.is_named()) { + return true; } + if (ELEM(attribute_id.name(), + "handle_type_left", + "handle_type_right", + "handle_left", + "handle_right")) { + return type_counts[CURVE_TYPE_BEZIER] != 0; + } + if (ELEM(attribute_id.name(), "nurbs_weight")) { + return type_counts[CURVE_TYPE_NURBS] != 0; + } + return true; +} - dst->resize(count); +/** + * Return true if the attribute should be copied to poly curves. + */ +static bool interpolate_attribute_to_poly_curve(const AttributeIDRef &attribute_id) +{ + static const Set<StringRef> no_interpolation{{ + "handle_type_left", + "handle_type_right", + "handle_position_right", + "handle_position_left", + "nurbs_weight", + }}; + return !(attribute_id.is_named() && no_interpolation.contains(attribute_id.name())); +} - Array<float> uniform_samples = src.sample_uniform_index_factors(count); +/** + * Retrieve spans from source and result attributes. + */ +static void retrieve_attribute_spans(const Span<AttributeIDRef> ids, + const CurveComponent &src_component, + CurveComponent &dst_component, + Vector<GSpan> &src, + Vector<GMutableSpan> &dst, + Vector<OutputAttribute> &dst_attributes) +{ + for (const int i : ids.index_range()) { + GVArray src_attribute = src_component.attribute_try_get_for_read(ids[i], ATTR_DOMAIN_POINT); + BLI_assert(src_attribute); + src.append(src_attribute.get_internal_span()); + + const CustomDataType data_type = bke::cpp_type_to_custom_data_type(src_attribute.type()); + OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only( + ids[i], ATTR_DOMAIN_POINT, data_type); + dst.append(dst_attribute.as_span()); + dst_attributes.append(std::move(dst_attribute)); + } +} - src.sample_with_index_factors<float3>( - src.evaluated_positions(), uniform_samples, dst->positions()); +struct AttributesForInterpolation : NonCopyable, NonMovable { + Vector<GSpan> src; + Vector<GMutableSpan> dst; - src.sample_with_index_factors<float>( - src.interpolate_to_evaluated(src.radii()), uniform_samples, dst->radii()); + Vector<OutputAttribute> dst_attributes; - src.sample_with_index_factors<float>( - src.interpolate_to_evaluated(src.tilts()), uniform_samples, dst->tilts()); + Vector<GSpan> src_no_interpolation; + Vector<GMutableSpan> dst_no_interpolation; +}; - src.attributes.foreach_attribute( - [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { - std::optional<GSpan> input_attribute = src.attributes.get_for_read(attribute_id); - if (dst->attributes.create(attribute_id, meta_data.data_type)) { - std::optional<GMutableSpan> output_attribute = dst->attributes.get_for_write( - attribute_id); - if (output_attribute) { - src.sample_with_index_factors(src.interpolate_to_evaluated(*input_attribute), - uniform_samples, - *output_attribute); - return true; - } +/** + * Gather a set of all generic attribute IDs to copy to the result curves. + */ +static void gather_point_attributes_to_interpolate(const CurveComponent &src_component, + CurveComponent &dst_component, + AttributesForInterpolation &result) +{ + const Curves &dst_curves_id = *dst_component.get_for_read(); + const bke::CurvesGeometry &dst_curves = bke::CurvesGeometry::wrap(dst_curves_id.geometry); + const std::array<int, CURVE_TYPES_NUM> type_counts = dst_curves.count_curve_types(); + + VectorSet<AttributeIDRef> ids; + VectorSet<AttributeIDRef> ids_no_interpolation; + src_component.attribute_foreach( + [&](const AttributeIDRef &id, const AttributeMetaData meta_data) { + if (meta_data.domain != ATTR_DOMAIN_POINT) { + return true; + } + if (!interpolate_attribute_to_curves(id, type_counts)) { + return true; + } + if (interpolate_attribute_to_poly_curve(id)) { + ids.add_new(id); + } + else { + ids_no_interpolation.add_new(id); } + return true; + }); + + /* Position is handled differently since it has non-generic interpolation for Bezier + * curves and because the evaluated positions are cached for each evaluated point. */ + ids.remove_contained("position"); + + retrieve_attribute_spans( + ids, src_component, dst_component, result.src, result.dst, result.dst_attributes); + + /* Attributes that aren't interpolated like Bezier handles still have to be be copied + * to the result when there are any unselected curves of the corresponding type. */ + retrieve_attribute_spans(ids_no_interpolation, + src_component, + dst_component, + result.src_no_interpolation, + result.dst_no_interpolation, + result.dst_attributes); +} - BLI_assert_unreachable(); - return false; - }, - ATTR_DOMAIN_POINT); +/** + * Copy the provided point attribute values between all curves in the #curve_ranges index + * ranges, assuming that all curves are the same size in #src_curves and #dst_curves. + */ +template<typename T> +static void copy_between_curves(const bke::CurvesGeometry &src_curves, + const bke::CurvesGeometry &dst_curves, + const Span<IndexRange> curve_ranges, + const Span<T> src, + const MutableSpan<T> dst) +{ + threading::parallel_for(curve_ranges.index_range(), 512, [&](IndexRange range) { + for (const IndexRange range : curve_ranges.slice(range)) { + const IndexRange src_points = src_curves.points_for_curves(range); + const IndexRange dst_points = dst_curves.points_for_curves(range); + /* The arrays might be large, so a threaded copy might make sense here too. */ + dst.slice(dst_points).copy_from(src.slice(src_points)); + } + }); +} +static void copy_between_curves(const bke::CurvesGeometry &src_curves, + const bke::CurvesGeometry &dst_curves, + const Span<IndexRange> unselected_ranges, + const GSpan src, + const GMutableSpan dst) +{ + attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { + using T = decltype(dummy); + copy_between_curves(src_curves, dst_curves, unselected_ranges, src.typed<T>(), dst.typed<T>()); + }); +} - return dst; +/** + * Copy the size of every curve in #curve_ranges to the corresponding index in #counts. + */ +static void fill_curve_counts(const bke::CurvesGeometry &src_curves, + const Span<IndexRange> curve_ranges, + MutableSpan<int> counts) +{ + threading::parallel_for(curve_ranges.index_range(), 512, [&](IndexRange ranges_range) { + for (const IndexRange curves_range : curve_ranges.slice(ranges_range)) { + for (const int i : curves_range) { + counts[i] = src_curves.points_for_curve(i).size(); + } + } + }); } -static SplinePtr resample_spline_evaluated(const Spline &src) +/** + * Turn an array of sizes into the offset at each index including all previous sizes. + */ +static void accumulate_counts_to_offsets(MutableSpan<int> counts_to_offsets) { - std::unique_ptr<PolySpline> dst = std::make_unique<PolySpline>(); - Spline::copy_base_settings(src, *dst); - dst->resize(src.evaluated_points_size()); - - dst->positions().copy_from(src.evaluated_positions()); - dst->positions().copy_from(src.evaluated_positions()); - src.interpolate_to_evaluated(src.radii()).materialize(dst->radii()); - src.interpolate_to_evaluated(src.tilts()).materialize(dst->tilts()); - - src.attributes.foreach_attribute( - [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { - std::optional<GSpan> src_attribute = src.attributes.get_for_read(attribute_id); - if (dst->attributes.create(attribute_id, meta_data.data_type)) { - std::optional<GMutableSpan> dst_attribute = dst->attributes.get_for_write(attribute_id); - if (dst_attribute) { - src.interpolate_to_evaluated(*src_attribute).materialize(dst_attribute->data()); - return true; + int total = 0; + for (const int i : counts_to_offsets.index_range().drop_back(1)) { + const int count = counts_to_offsets[i]; + BLI_assert(count > 0); + counts_to_offsets[i] = total; + total += count; + } + counts_to_offsets.last() = total; +} + +/** + * Create new curves where the selected curves have been resampled with a number of uniform-length + * samples defined by the count field. Interpolate attributes to the result, with an accuracy that + * depends on the curve's resolution parameter. + * + * \warning The values provided by the #count_field must be 1 or greater. + * \warning Curves with no evaluated points must not be selected. + */ +static Curves *resample_to_uniform_count(const CurveComponent &src_component, + const Field<bool> &selection_field, + const Field<int> &count_field) +{ + const Curves &src_curves_id = *src_component.get_for_read(); + const bke::CurvesGeometry &src_curves = bke::CurvesGeometry::wrap(src_curves_id.geometry); + + /* Create the new curves without any points and evaluate the final count directly + * into the offsets array, in order to be accumulated into offsets later. */ + Curves *dst_curves_id = bke::curves_new_nomain(0, src_curves.curves_num()); + bke::CurvesGeometry &dst_curves = bke::CurvesGeometry::wrap(dst_curves_id->geometry); + CurveComponent dst_component; + dst_component.replace(dst_curves_id, GeometryOwnershipType::Editable); + /* Directly copy curve attributes, since they stay the same (except for curve types). */ + CustomData_copy(&src_curves.curve_data, + &dst_curves.curve_data, + CD_MASK_ALL, + CD_DUPLICATE, + src_curves.curves_num()); + MutableSpan<int> dst_offsets = dst_curves.offsets(); + + GeometryComponentFieldContext field_context{src_component, ATTR_DOMAIN_CURVE}; + fn::FieldEvaluator evaluator{field_context, src_curves.curves_num()}; + evaluator.set_selection(selection_field); + evaluator.add_with_destination(count_field, dst_offsets); + evaluator.evaluate(); + const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); + const Vector<IndexRange> unselected_ranges = selection.extract_ranges_invert( + src_curves.curves_range(), nullptr); + + /* Fill the counts for the curves that aren't selected and accumulate the counts into offsets. */ + fill_curve_counts(src_curves, unselected_ranges, dst_offsets); + accumulate_counts_to_offsets(dst_offsets); + dst_curves.resize(dst_offsets.last(), dst_curves.curves_num()); + + /* All resampled curves are poly curves. */ + dst_curves.curve_types().fill_indices(selection, CURVE_TYPE_POLY); + + VArray<bool> curves_cyclic = src_curves.cyclic(); + VArray<int8_t> curve_types = src_curves.curve_types(); + Span<float3> evaluated_positions = src_curves.evaluated_positions(); + MutableSpan<float3> dst_positions = dst_curves.positions(); + + AttributesForInterpolation attributes; + gather_point_attributes_to_interpolate(src_component, dst_component, attributes); + + src_curves.ensure_evaluated_lengths(); + + /* Sampling arbitrary attributes works by first interpolating them to the curve's standard + * "evaluated points" and then interpolating that result with the uniform samples. This is + * potentially wasteful when down-sampling a curve to many fewer points. There are two possible + * solutions: only sample the necessary points for interpolation, or first sample curve + * parameter/segment indices and evaluate the curve directly. */ + Array<int> sample_indices(dst_curves.points_num()); + Array<float> sample_factors(dst_curves.points_num()); + + /* Use a "for each group of curves: for each attribute: for each curve" pattern to work on + * smaller sections of data that ideally fit into CPU cache better than simply one attribute at a + * time or one curve at a time. */ + threading::parallel_for(selection.index_range(), 512, [&](IndexRange selection_range) { + const IndexMask sliced_selection = selection.slice(selection_range); + + Vector<std::byte> evaluated_buffer; + + /* Gather uniform samples based on the accumulated lengths of the original curve. */ + for (const int i_curve : sliced_selection) { + const bool cyclic = curves_cyclic[i_curve]; + const IndexRange dst_points = dst_curves.points_for_curve(i_curve); + length_parameterize::create_uniform_samples( + src_curves.evaluated_lengths_for_curve(i_curve, cyclic), + curves_cyclic[i_curve], + sample_indices.as_mutable_span().slice(dst_points), + sample_factors.as_mutable_span().slice(dst_points)); + } + + /* For every attribute, evaluate attributes from every curve in the range in the original + * curve's "evaluated points", then use linear interpolation to sample to the result. */ + for (const int i_attribute : attributes.dst.index_range()) { + attribute_math::convert_to_static_type(attributes.src[i_attribute].type(), [&](auto dummy) { + using T = decltype(dummy); + Span<T> src = attributes.src[i_attribute].typed<T>(); + MutableSpan<T> dst = attributes.dst[i_attribute].typed<T>(); + + for (const int i_curve : sliced_selection) { + const IndexRange src_points = src_curves.points_for_curve(i_curve); + const IndexRange dst_points = dst_curves.points_for_curve(i_curve); + + if (curve_types[i_curve] == CURVE_TYPE_POLY) { + length_parameterize::linear_interpolation(src.slice(src_points), + sample_indices.as_span().slice(dst_points), + sample_factors.as_span().slice(dst_points), + dst.slice(dst_points)); + } + else { + const int evaluated_size = src_curves.evaluated_points_for_curve(i_curve).size(); + evaluated_buffer.clear(); + evaluated_buffer.resize(sizeof(T) * evaluated_size); + MutableSpan<T> evaluated = evaluated_buffer.as_mutable_span().cast<T>(); + src_curves.interpolate_to_evaluated(i_curve, src.slice(src_points), evaluated); + + length_parameterize::linear_interpolation(evaluated.as_span(), + sample_indices.as_span().slice(dst_points), + sample_factors.as_span().slice(dst_points), + dst.slice(dst_points)); } } + }); + } - BLI_assert_unreachable(); - return true; - }, - ATTR_DOMAIN_POINT); + /* Interpolate the evaluated positions to the resampled curves. */ + for (const int i_curve : sliced_selection) { + const IndexRange src_points = src_curves.evaluated_points_for_curve(i_curve); + const IndexRange dst_points = dst_curves.points_for_curve(i_curve); + length_parameterize::linear_interpolation(evaluated_positions.slice(src_points), + sample_indices.as_span().slice(dst_points), + sample_factors.as_span().slice(dst_points), + dst_positions.slice(dst_points)); + } - return dst; + /* Fill the default value for non-interpolating attributes that still must be copied. */ + for (GMutableSpan dst : attributes.dst_no_interpolation) { + for (const int i_curve : sliced_selection) { + const IndexRange dst_points = dst_curves.points_for_curve(i_curve); + dst.type().value_initialize_n(dst.slice(dst_points).data(), dst_points.size()); + } + } + }); + + /* Any attribute data from unselected curve points can be directly copied. */ + for (const int i : attributes.src.index_range()) { + copy_between_curves( + src_curves, dst_curves, unselected_ranges, attributes.src[i], attributes.dst[i]); + } + for (const int i : attributes.src_no_interpolation.index_range()) { + copy_between_curves(src_curves, + dst_curves, + unselected_ranges, + attributes.src_no_interpolation[i], + attributes.dst_no_interpolation[i]); + } + + /* Copy positions for unselected curves. */ + Span<float3> src_positions = src_curves.positions(); + copy_between_curves(src_curves, dst_curves, unselected_ranges, src_positions, dst_positions); + + for (OutputAttribute &attribute : attributes.dst_attributes) { + attribute.save(); + } + + return dst_curves_id; } -static std::unique_ptr<CurveEval> resample_curve(const CurveComponent *component, - const SampleModeParam &mode_param) +/** + * Evaluate each selected curve to its implicit evaluated points. + * + * \warning Curves with no evaluated points must not be selected. + */ +static Curves *resample_to_evaluated(const CurveComponent &src_component, + const Field<bool> &selection_field) { - const std::unique_ptr<CurveEval> input_curve = curves_to_curve_eval(*component->get_for_read()); - GeometryComponentFieldContext field_context{*component, ATTR_DOMAIN_CURVE}; - const int domain_size = component->attribute_domain_size(ATTR_DOMAIN_CURVE); - - Span<SplinePtr> input_splines = input_curve->splines(); - - std::unique_ptr<CurveEval> output_curve = std::make_unique<CurveEval>(); - output_curve->resize(input_splines.size()); - MutableSpan<SplinePtr> output_splines = output_curve->splines(); - - if (mode_param.mode == GEO_NODE_CURVE_RESAMPLE_COUNT) { - fn::FieldEvaluator evaluator{field_context, domain_size}; - evaluator.add(*mode_param.count); - evaluator.add(mode_param.selection); - evaluator.evaluate(); - const VArray<int> &cuts = evaluator.get_evaluated<int>(0); - const VArray<bool> &selections = evaluator.get_evaluated<bool>(1); - - threading::parallel_for(input_splines.index_range(), 128, [&](IndexRange range) { - for (const int i : range) { - BLI_assert(mode_param.count); - if (selections[i] && input_splines[i]->evaluated_points_size() > 0) { - output_splines[i] = resample_spline(*input_splines[i], std::max(cuts[i], 1)); - } - else { - output_splines[i] = input_splines[i]->copy(); + const Curves &src_curves_id = *src_component.get_for_read(); + const bke::CurvesGeometry &src_curves = bke::CurvesGeometry::wrap(src_curves_id.geometry); + + GeometryComponentFieldContext field_context{src_component, ATTR_DOMAIN_CURVE}; + fn::FieldEvaluator evaluator{field_context, src_curves.curves_num()}; + evaluator.set_selection(selection_field); + evaluator.evaluate(); + const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); + const Vector<IndexRange> unselected_ranges = selection.extract_ranges_invert( + src_curves.curves_range(), nullptr); + + Curves *dst_curves_id = bke::curves_new_nomain(0, src_curves.curves_num()); + bke::CurvesGeometry &dst_curves = bke::CurvesGeometry::wrap(dst_curves_id->geometry); + CurveComponent dst_component; + dst_component.replace(dst_curves_id, GeometryOwnershipType::Editable); + /* Directly copy curve attributes, since they stay the same (except for curve types). */ + CustomData_copy(&src_curves.curve_data, + &dst_curves.curve_data, + CD_MASK_ALL, + CD_DUPLICATE, + src_curves.curves_num()); + /* All resampled curves are poly curves. */ + dst_curves.curve_types().fill_indices(selection, CURVE_TYPE_POLY); + MutableSpan<int> dst_offsets = dst_curves.offsets(); + + src_curves.ensure_evaluated_offsets(); + threading::parallel_for(selection.index_range(), 4096, [&](IndexRange range) { + for (const int i : selection.slice(range)) { + dst_offsets[i] = src_curves.evaluated_points_for_curve(i).size(); + } + }); + fill_curve_counts(src_curves, unselected_ranges, dst_offsets); + accumulate_counts_to_offsets(dst_offsets); + + dst_curves.resize(dst_offsets.last(), dst_curves.curves_num()); + + /* Create the correct number of uniform-length samples for every selected curve. */ + Span<float3> evaluated_positions = src_curves.evaluated_positions(); + MutableSpan<float3> dst_positions = dst_curves.positions(); + + AttributesForInterpolation attributes; + gather_point_attributes_to_interpolate(src_component, dst_component, attributes); + + threading::parallel_for(selection.index_range(), 512, [&](IndexRange selection_range) { + const IndexMask sliced_selection = selection.slice(selection_range); + + /* Evaluate generic point attributes directly to the result attributes. */ + for (const int i_attribute : attributes.dst.index_range()) { + attribute_math::convert_to_static_type(attributes.src[i_attribute].type(), [&](auto dummy) { + using T = decltype(dummy); + Span<T> src = attributes.src[i_attribute].typed<T>(); + MutableSpan<T> dst = attributes.dst[i_attribute].typed<T>(); + + for (const int i_curve : sliced_selection) { + const IndexRange src_points = src_curves.points_for_curve(i_curve); + const IndexRange dst_points = dst_curves.points_for_curve(i_curve); + src_curves.interpolate_to_evaluated( + i_curve, src.slice(src_points), dst.slice(dst_points)); } + }); + } + + /* Copy the evaluated positions to the selected curves. */ + for (const int i_curve : sliced_selection) { + const IndexRange src_points = src_curves.evaluated_points_for_curve(i_curve); + const IndexRange dst_points = dst_curves.points_for_curve(i_curve); + dst_positions.slice(dst_points).copy_from(evaluated_positions.slice(src_points)); + } + + /* Fill the default value for non-interpolating attributes that still must be copied. */ + for (GMutableSpan dst : attributes.dst_no_interpolation) { + for (const int i_curve : sliced_selection) { + const IndexRange dst_points = dst_curves.points_for_curve(i_curve); + dst.type().value_initialize_n(dst.slice(dst_points).data(), dst_points.size()); } - }); + } + }); + + /* Any attribute data from unselected curve points can be directly copied. */ + for (const int i : attributes.src.index_range()) { + copy_between_curves( + src_curves, dst_curves, unselected_ranges, attributes.src[i], attributes.dst[i]); } - else if (mode_param.mode == GEO_NODE_CURVE_RESAMPLE_LENGTH) { - fn::FieldEvaluator evaluator{field_context, domain_size}; - evaluator.add(*mode_param.length); - evaluator.add(mode_param.selection); - evaluator.evaluate(); - const VArray<float> &lengths = evaluator.get_evaluated<float>(0); - const VArray<bool> &selections = evaluator.get_evaluated<bool>(1); - - threading::parallel_for(input_splines.index_range(), 128, [&](IndexRange range) { - for (const int i : range) { - if (selections[i] && input_splines[i]->evaluated_points_size() > 0) { - /* Don't allow asymptotic count increase for low resolution values. */ - const float divide_length = std::max(lengths[i], 0.0001f); - const float spline_length = input_splines[i]->length(); - const int count = std::max(int(spline_length / divide_length) + 1, 1); - output_splines[i] = resample_spline(*input_splines[i], count); - } - else { - output_splines[i] = input_splines[i]->copy(); - } - } - }); + for (const int i : attributes.src_no_interpolation.index_range()) { + copy_between_curves(src_curves, + dst_curves, + unselected_ranges, + attributes.src_no_interpolation[i], + attributes.dst_no_interpolation[i]); } - else if (mode_param.mode == GEO_NODE_CURVE_RESAMPLE_EVALUATED) { - fn::FieldEvaluator evaluator{field_context, domain_size}; - evaluator.add(mode_param.selection); - evaluator.evaluate(); - const VArray<bool> &selections = evaluator.get_evaluated<bool>(0); - - threading::parallel_for(input_splines.index_range(), 128, [&](IndexRange range) { - for (const int i : range) { - if (selections[i] && input_splines[i]->evaluated_points_size() > 0) { - output_splines[i] = resample_spline_evaluated(*input_splines[i]); - } - else { - output_splines[i] = input_splines[i]->copy(); - } - } - }); + + /* Copy positions for unselected curves. */ + Span<float3> src_positions = src_curves.positions(); + copy_between_curves(src_curves, dst_curves, unselected_ranges, src_positions, dst_positions); + + for (OutputAttribute &attribute : attributes.dst_attributes) { + attribute.save(); } - output_curve->attributes = input_curve->attributes; - return output_curve; + + return dst_curves_id; } -static void geometry_set_curve_resample(GeometrySet &geometry_set, - const SampleModeParam &mode_param) +/** + * Create a resampled curve point count field for both "uniform" options. + * The complexity is handled here in order to make the actual resampling functions simpler. + */ +static Field<int> get_curve_count_field(GeoNodeExecParams params, + const GeometryNodeCurveResampleMode mode) { - if (!geometry_set.has_curves()) { - return; + if (mode == GEO_NODE_CURVE_RESAMPLE_COUNT) { + static fn::CustomMF_SI_SO<int, int> max_one_fn("Clamp Above One", + [](int value) { return std::max(1, value); }); + auto clamp_op = std::make_shared<FieldOperation>( + FieldOperation(max_one_fn, {Field<int>(params.extract_input<Field<int>>("Count"))})); + + return Field<int>(std::move(clamp_op)); } - std::unique_ptr<CurveEval> output_curve = resample_curve( - geometry_set.get_component_for_read<CurveComponent>(), mode_param); + if (mode == GEO_NODE_CURVE_RESAMPLE_LENGTH) { + static fn::CustomMF_SI_SI_SO<float, float, int> get_count_fn( + "Length Input to Count", [](const float curve_length, const float sample_length) { + /* Find the number of sampled segments by dividing the total length by + * the sample length. Then there is one more sampled point than segment. */ + const int count = int(curve_length / sample_length) + 1; + return std::max(1, count); + }); + + auto get_count_op = std::make_shared<FieldOperation>( + FieldOperation(get_count_fn, + {Field<float>(std::make_shared<SplineLengthFieldInput>()), + params.extract_input<Field<float>>("Length")})); + + return Field<int>(std::move(get_count_op)); + } + + BLI_assert_unreachable(); + return {}; +} + +/** + * Create a selection field that removes curves without any evaluated points (invalid NURBS curves) + * from the original selection provided to the node. This is here to simplify the sampling actual + * resampling code. + */ +static Field<bool> get_selection_field(GeoNodeExecParams params) +{ + static fn::CustomMF_SI_SI_SO<bool, int, bool> get_selection_fn( + "Create Curve Selection", [](const bool orig_selection, const int evaluated_points_num) { + return orig_selection && evaluated_points_num > 1; + }); + + auto selection_op = std::make_shared<FieldOperation>( + FieldOperation(get_selection_fn, + {params.extract_input<Field<bool>>("Selection"), + Field<int>(std::make_shared<EvaluatedCountFieldInput>())})); - geometry_set.replace_curves(curve_eval_to_curves(*output_curve)); + return Field<bool>(std::move(selection_op)); } static void node_geo_exec(GeoNodeExecParams params) @@ -252,25 +608,38 @@ static void node_geo_exec(GeoNodeExecParams params) const NodeGeometryCurveResample &storage = node_storage(params.node()); const GeometryNodeCurveResampleMode mode = (GeometryNodeCurveResampleMode)storage.mode; - SampleModeParam mode_param; - mode_param.mode = mode; - mode_param.selection = params.extract_input<Field<bool>>("Selection"); + const Field<bool> selection = get_selection_field(params); - if (mode == GEO_NODE_CURVE_RESAMPLE_COUNT) { - Field<int> count = params.extract_input<Field<int>>("Count"); - if (count < 1) { - params.set_default_remaining_outputs(); - return; + switch (mode) { + case GEO_NODE_CURVE_RESAMPLE_COUNT: + case GEO_NODE_CURVE_RESAMPLE_LENGTH: { + Field<int> count = get_curve_count_field(params, mode); + + geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + if (!geometry_set.has_curves()) { + return; + } + + Curves *result = resample_to_uniform_count( + *geometry_set.get_component_for_read<CurveComponent>(), selection, count); + + geometry_set.replace_curves(result); + }); + break; } - mode_param.count.emplace(count); - } - else if (mode == GEO_NODE_CURVE_RESAMPLE_LENGTH) { - Field<float> resolution = params.extract_input<Field<float>>("Length"); - mode_param.length.emplace(resolution); - } + case GEO_NODE_CURVE_RESAMPLE_EVALUATED: + geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + if (!geometry_set.has_curves()) { + return; + } - geometry_set.modify_geometry_sets( - [&](GeometrySet &geometry_set) { geometry_set_curve_resample(geometry_set, mode_param); }); + Curves *result = resample_to_evaluated( + *geometry_set.get_component_for_read<CurveComponent>(), selection); + + geometry_set.replace_curves(result); + }); + break; + } params.set_output("Curve", std::move(geometry_set)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_set_handle_type.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_set_handle_type.cc index e8ba78816a5..169f808c473 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_set_handle_type.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_set_handle_type.cc @@ -1,6 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -#include "BKE_spline.hh" +#include <atomic> + +#include "BKE_curves.hh" #include "UI_interface.h" #include "UI_resources.h" @@ -49,6 +51,33 @@ static HandleType handle_type_from_input_type(GeometryNodeCurveHandleType type) return BEZIER_HANDLE_AUTO; } +static void set_type_in_component(CurveComponent &component, + const GeometryNodeCurveHandleMode mode, + const HandleType new_handle_type, + const Field<bool> &selection_field) +{ + Curves &curves_id = *component.get_for_write(); + bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); + + GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_POINT}; + fn::FieldEvaluator evaluator{field_context, curves.points_num()}; + evaluator.set_selection(selection_field); + evaluator.evaluate(); + const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); + + if (mode & GEO_NODE_CURVE_HANDLE_LEFT) { + curves.handle_types_left().fill_indices(selection, new_handle_type); + } + if (mode & GEO_NODE_CURVE_HANDLE_RIGHT) { + curves.handle_types_right().fill_indices(selection, new_handle_type); + } + + /* Eagerly calculate automatically derived handle positions if necessary. */ + if (ELEM(new_handle_type, BEZIER_HANDLE_AUTO, BEZIER_HANDLE_VECTOR, BEZIER_HANDLE_ALIGN)) { + curves.calculate_bezier_auto_handles(); + } +} + static void node_geo_exec(GeoNodeExecParams params) { const NodeGeometryCurveSetHandles &storage = node_storage(params.node()); @@ -58,62 +87,33 @@ static void node_geo_exec(GeoNodeExecParams params) GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve"); Field<bool> selection_field = params.extract_input<Field<bool>>("Selection"); - bool has_bezier_spline = false; + const HandleType new_handle_type = handle_type_from_input_type(type); + + std::atomic<bool> has_curves = false; + std::atomic<bool> has_bezier = false; + geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { if (!geometry_set.has_curves()) { return; } - - /* Retrieve data for write access so we can avoid new allocations for the handles data. */ - CurveComponent &curve_component = geometry_set.get_component_for_write<CurveComponent>(); - std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_component.get_for_read()); - MutableSpan<SplinePtr> splines = curve->splines(); - - GeometryComponentFieldContext field_context{curve_component, ATTR_DOMAIN_POINT}; - const int domain_size = curve_component.attribute_domain_size(ATTR_DOMAIN_POINT); - - fn::FieldEvaluator selection_evaluator{field_context, domain_size}; - selection_evaluator.add(selection_field); - selection_evaluator.evaluate(); - const VArray<bool> &selection = selection_evaluator.get_evaluated<bool>(0); - - const HandleType new_handle_type = handle_type_from_input_type(type); - int point_index = 0; - - for (SplinePtr &spline : splines) { - if (spline->type() != CURVE_TYPE_BEZIER) { - point_index += spline->positions().size(); - continue; - } - - has_bezier_spline = true; - BezierSpline &bezier_spline = static_cast<BezierSpline &>(*spline); - if (ELEM(new_handle_type, BEZIER_HANDLE_FREE, BEZIER_HANDLE_ALIGN)) { - /* In this case the automatically calculated handle types need to be "baked", because - * they're possibly changing from a type that is calculated automatically to a type that - * is positioned manually. */ - bezier_spline.ensure_auto_handles(); - } - - for (int i_point : IndexRange(bezier_spline.size())) { - if (selection[point_index]) { - if (mode & GEO_NODE_CURVE_HANDLE_LEFT) { - bezier_spline.handle_types_left()[i_point] = new_handle_type; - } - if (mode & GEO_NODE_CURVE_HANDLE_RIGHT) { - bezier_spline.handle_types_right()[i_point] = new_handle_type; - } - } - point_index++; - } - bezier_spline.mark_cache_invalid(); + has_curves = true; + const CurveComponent &component = *geometry_set.get_component_for_read<CurveComponent>(); + if (!component.attribute_exists("handle_type_left") || + !component.attribute_exists("handle_type_right")) { + return; } + has_bezier = true; - curve_component.replace(curve_eval_to_curves(*curve)); + set_type_in_component(geometry_set.get_component_for_write<CurveComponent>(), + mode, + new_handle_type, + selection_field); }); - if (!has_bezier_spline) { - params.error_message_add(NodeWarningType::Info, TIP_("No Bezier splines in input curve")); + + if (has_curves && !has_bezier) { + params.error_message_add(NodeWarningType::Info, TIP_("Input curves do not have Bezier type")); } + params.set_output("Curve", std::move(geometry_set)); } } // namespace blender::nodes::node_geo_curve_set_handle_type_cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc index 3edaccba506..62fae8b8eca 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc @@ -2,7 +2,7 @@ #include "BLI_task.hh" -#include "BKE_spline.hh" +#include "BKE_curves.hh" #include "node_geometry_util.hh" @@ -26,168 +26,160 @@ static void node_declare(NodeDeclarationBuilder &b) } /** - * A basic interpolation from the point domain to the spline domain would be useless, since the - * average parameter for each spline would just be 0.5, or close to it. Instead, the parameter for - * each spline is the portion of the total length at the start of the spline. + * For lengths on the curve domain, a basic interpolation from the point domain would be useless, + * since the average parameter for each curve would just be 0.5, or close to it. Instead, the + * value for each curve is defined as the portion of the total length of all curves at its start. */ -static Array<float> curve_length_spline_domain(const CurveEval &curve, - const IndexMask UNUSED(mask)) +static Array<float> accumulated_lengths_curve_domain(const bke::CurvesGeometry &curves) { - Span<SplinePtr> splines = curve.splines(); + curves.ensure_evaluated_lengths(); + + Array<float> lengths(curves.curves_num()); + VArray<bool> cyclic = curves.cyclic(); float length = 0.0f; - Array<float> lengths(splines.size()); - for (const int i : splines.index_range()) { + for (const int i : curves.curves_range()) { lengths[i] = length; - length += splines[i]->length(); - } - return lengths; -} - -/** - * The parameter at each control point is the factor at the corresponding evaluated point. - */ -static void calculate_bezier_lengths(const BezierSpline &spline, MutableSpan<float> lengths) -{ - Span<int> offsets = spline.control_point_offsets(); - Span<float> lengths_eval = spline.evaluated_lengths(); - for (const int i : IndexRange(1, spline.size() - 1)) { - lengths[i] = lengths_eval[offsets[i] - 1]; + length += curves.evaluated_length_total_for_curve(i, cyclic[i]); } -} -/** - * The parameter for poly splines is simply the evaluated lengths divided by the total length. - */ -static void calculate_poly_length(const PolySpline &spline, MutableSpan<float> lengths) -{ - Span<float> lengths_eval = spline.evaluated_lengths(); - if (spline.is_cyclic()) { - lengths.drop_front(1).copy_from(lengths_eval.drop_back(1)); - } - else { - lengths.drop_front(1).copy_from(lengths_eval); - } + return lengths; } /** - * Since NURBS control points do not necessarily coincide with the evaluated curve's path, and - * each control point doesn't correspond well to a specific evaluated point, the parameter at - * each point is not well defined. So instead, treat the control points as if they were a poly - * spline. + * Return the length of each control point along each curve, starting at zero for the first point. + * Importantly, this is different than the length at each evaluated point. The implementation is + * different for every curve type: + * - Catmull Rom Curves: Use the resolution to find the evaluated point for each control point. + * - Poly Curves: Copy the evaluated lengths, but we need to add a zero to the front of the array. + * - Bezier Curves: Use the evaluated offsets to find the evaluated point for each control point. + * - NURBS Curves: Treat the control points as if they were a poly curve, because there + * is no obvious mapping from each control point to a specific evaluated point. */ -static void calculate_nurbs_lengths(const NURBSpline &spline, MutableSpan<float> lengths) -{ - Span<float3> positions = spline.positions(); - Array<float> control_point_lengths(spline.size()); - float length = 0.0f; - for (const int i : IndexRange(positions.size() - 1)) { - lengths[i] = length; - length += math::distance(positions[i], positions[i + 1]); - } - lengths.last() = length; -} - -static Array<float> curve_length_point_domain(const CurveEval &curve) +static Array<float> curve_length_point_domain(const bke::CurvesGeometry &curves) { - Span<SplinePtr> splines = curve.splines(); - Array<int> offsets = curve.control_point_offsets(); - const int total_size = offsets.last(); - Array<float> lengths(total_size); - - threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) { - for (const int i : range) { - const Spline &spline = *splines[i]; - MutableSpan spline_factors{lengths.as_mutable_span().slice(offsets[i], spline.size())}; - spline_factors.first() = 0.0f; - switch (splines[i]->type()) { - case CURVE_TYPE_BEZIER: { - calculate_bezier_lengths(static_cast<const BezierSpline &>(spline), spline_factors); + curves.ensure_evaluated_lengths(); + const VArray<int8_t> types = curves.curve_types(); + const VArray<int> resolution = curves.resolution(); + const VArray<bool> cyclic = curves.cyclic(); + + Array<float> result(curves.points_num()); + VArray<int> resolutions = curves.resolution(); + + threading::parallel_for(curves.curves_range(), 128, [&](IndexRange range) { + for (const int i_curve : range) { + const IndexRange points = curves.points_for_curve(i_curve); + const Span<float> evaluated_lengths = curves.evaluated_lengths_for_curve(i_curve, + cyclic[i_curve]); + MutableSpan<float> lengths = result.as_mutable_span().slice(points); + lengths.first() = 0.0f; + switch (types[i_curve]) { + case CURVE_TYPE_CATMULL_ROM: { + const int resolution = resolutions[i_curve]; + for (const int i : IndexRange(points.size()).drop_front(1).drop_back(1)) { + lengths[i] = evaluated_lengths[resolution * i - 1]; + } break; } - case CURVE_TYPE_POLY: { - calculate_poly_length(static_cast<const PolySpline &>(spline), spline_factors); + case CURVE_TYPE_POLY: + lengths.drop_front(1).copy_from(evaluated_lengths.take_front(lengths.size() - 1)); break; - } - case CURVE_TYPE_NURBS: { - calculate_nurbs_lengths(static_cast<const NURBSpline &>(spline), spline_factors); + case CURVE_TYPE_BEZIER: { + const Span<int> offsets = curves.bezier_evaluated_offsets_for_curve(i_curve); + for (const int i : IndexRange(points.size()).drop_front(1).drop_back(1)) { + lengths[i] = evaluated_lengths[offsets[i] - 1]; + } break; } - case CURVE_TYPE_CATMULL_ROM: { - BLI_assert_unreachable(); + case CURVE_TYPE_NURBS: { + const Span<float3> positions = curves.positions().slice(points); + float length = 0.0f; + for (const int i : positions.index_range().drop_back(1)) { + lengths[i] = length; + length += math::distance(positions[i], positions[i + 1]); + } + lengths.last() = length; break; } } } }); - return lengths; + return result; } -static VArray<float> construct_curve_parameter_varray(const CurveEval &curve, - const IndexMask mask, +static VArray<float> construct_curve_parameter_varray(const bke::CurvesGeometry &curves, + const IndexMask UNUSED(mask), const AttributeDomain domain) { + VArray<bool> cyclic = curves.cyclic(); + if (domain == ATTR_DOMAIN_POINT) { - Span<SplinePtr> splines = curve.splines(); - Array<float> values = curve_length_point_domain(curve); - - const Array<int> offsets = curve.control_point_offsets(); - for (const int i_spline : curve.splines().index_range()) { - const Spline &spline = *splines[i_spline]; - const float spline_length = spline.length(); - const float spline_length_inv = spline_length == 0.0f ? 0.0f : 1.0f / spline_length; - for (const int i : IndexRange(spline.size())) { - values[offsets[i_spline] + i] *= spline_length_inv; + Array<float> result = curve_length_point_domain(curves); + MutableSpan<float> lengths = result.as_mutable_span(); + + threading::parallel_for(curves.curves_range(), 1024, [&](IndexRange range) { + for (const int i_curve : range) { + const float total_length = curves.evaluated_length_total_for_curve(i_curve, + cyclic[i_curve]); + const float factor = total_length == 0.0f ? 0.0f : 1.0f / total_length; + MutableSpan<float> curve_lengths = lengths.slice(curves.points_for_curve(i_curve)); + for (float &value : curve_lengths) { + value *= factor; + } } - } - return VArray<float>::ForContainer(std::move(values)); + }); + return VArray<float>::ForContainer(std::move(result)); } if (domain == ATTR_DOMAIN_CURVE) { - Array<float> values = curve.accumulated_spline_lengths(); - const float total_length_inv = values.last() == 0.0f ? 0.0f : 1.0f / values.last(); - for (const int i : mask) { - values[i] *= total_length_inv; + Array<float> lengths = accumulated_lengths_curve_domain(curves); + + const int last_index = curves.curves_num() - 1; + const int total_length = lengths.last() + curves.evaluated_length_total_for_curve( + last_index, cyclic[last_index]); + const float factor = total_length == 0.0f ? 0.0f : 1.0f / total_length; + for (float &value : lengths) { + value *= factor; } - return VArray<float>::ForContainer(std::move(values)); + return VArray<float>::ForContainer(std::move(lengths)); } return {}; } -static VArray<float> construct_curve_length_varray(const CurveEval &curve, - const IndexMask mask, +static VArray<float> construct_curve_length_varray(const bke::CurvesGeometry &curves, + const IndexMask UNUSED(mask), const AttributeDomain domain) { + curves.ensure_evaluated_lengths(); + if (domain == ATTR_DOMAIN_POINT) { - Array<float> lengths = curve_length_point_domain(curve); + Array<float> lengths = curve_length_point_domain(curves); return VArray<float>::ForContainer(std::move(lengths)); } if (domain == ATTR_DOMAIN_CURVE) { - if (curve.splines().size() == 1) { - Array<float> lengths(1, 0.0f); - return VArray<float>::ForContainer(std::move(lengths)); - } - - Array<float> lengths = curve_length_spline_domain(curve, mask); + Array<float> lengths = accumulated_lengths_curve_domain(curves); return VArray<float>::ForContainer(std::move(lengths)); } return {}; } -static VArray<int> construct_index_on_spline_varray(const CurveEval &curve, +static VArray<int> construct_index_on_spline_varray(const bke::CurvesGeometry &curves, const IndexMask UNUSED(mask), const AttributeDomain domain) { if (domain == ATTR_DOMAIN_POINT) { - Array<int> output(curve.total_control_point_size()); - int output_index = 0; - for (int spline_index : curve.splines().index_range()) { - for (int point_index : IndexRange(curve.splines()[spline_index]->size())) { - output[output_index++] = point_index; + Array<int> result(curves.points_num()); + MutableSpan<int> span = result.as_mutable_span(); + threading::parallel_for(curves.curves_range(), 1024, [&](IndexRange range) { + for (const int i_curve : range) { + MutableSpan<int> indices = span.slice(curves.points_for_curve(i_curve)); + for (const int i : indices.index_range()) { + indices[i] = i; + } } - } - return VArray<int>::ForContainer(std::move(output)); + }); + return VArray<int>::ForContainer(std::move(result)); } return {}; } @@ -206,9 +198,9 @@ class CurveParameterFieldInput final : public GeometryFieldInput { if (component.type() == GEO_COMPONENT_TYPE_CURVE) { const CurveComponent &curve_component = static_cast<const CurveComponent &>(component); if (curve_component.has_curves()) { - const std::unique_ptr<CurveEval> curve = curves_to_curve_eval( - *curve_component.get_for_read()); - return construct_curve_parameter_varray(*curve, mask, domain); + const Curves &curves_id = *curve_component.get_for_read(); + const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); + return construct_curve_parameter_varray(curves, mask, domain); } } return {}; @@ -240,8 +232,9 @@ class CurveLengthFieldInput final : public GeometryFieldInput { if (component.type() == GEO_COMPONENT_TYPE_CURVE) { const CurveComponent &curve_component = static_cast<const CurveComponent &>(component); if (curve_component.has_curves()) { - std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_component.get_for_read()); - return construct_curve_length_varray(*curve, mask, domain); + const Curves &curves_id = *curve_component.get_for_read(); + const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); + return construct_curve_length_varray(curves, mask, domain); } } return {}; @@ -273,9 +266,9 @@ class IndexOnSplineFieldInput final : public GeometryFieldInput { if (component.type() == GEO_COMPONENT_TYPE_CURVE) { const CurveComponent &curve_component = static_cast<const CurveComponent &>(component); if (curve_component.has_curves()) { - const std::unique_ptr<CurveEval> curve = curves_to_curve_eval( - *curve_component.get_for_read()); - return construct_index_on_spline_varray(*curve, mask, domain); + const Curves &curves_id = *curve_component.get_for_read(); + const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); + return construct_index_on_spline_varray(curves, mask, domain); } } return {}; diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc index cf6837817c2..c3b1a141f4a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc @@ -168,12 +168,12 @@ static void copy_attributes_based_on_map(const Map<AttributeIDRef, AttributeKind static void copy_face_corner_attributes(const Map<AttributeIDRef, AttributeKind> &attributes, const GeometryComponent &in_component, GeometryComponent &out_component, - const int num_selected_loops, + const int selected_loops_num, const Span<int> selected_poly_indices, const Mesh &mesh_in) { Vector<int64_t> indices; - indices.reserve(num_selected_loops); + indices.reserve(selected_loops_num); for (const int src_poly_index : selected_poly_indices) { const MPoly &src_poly = mesh_in.mpoly[src_poly_index]; const int src_loop_start = src_poly.loopstart; @@ -546,47 +546,47 @@ static void separate_instance_selection(GeometrySet &geometry_set, static void compute_selected_vertices_from_vertex_selection(const Span<bool> vertex_selection, const bool invert, MutableSpan<int> r_vertex_map, - int *r_num_selected_vertices) + int *r_selected_vertices_num) { BLI_assert(vertex_selection.size() == r_vertex_map.size()); - int num_selected_vertices = 0; + int selected_verts_num = 0; for (const int i : r_vertex_map.index_range()) { if (vertex_selection[i] != invert) { - r_vertex_map[i] = num_selected_vertices; - num_selected_vertices++; + r_vertex_map[i] = selected_verts_num; + selected_verts_num++; } else { r_vertex_map[i] = -1; } } - *r_num_selected_vertices = num_selected_vertices; + *r_selected_vertices_num = selected_verts_num; } static void compute_selected_edges_from_vertex_selection(const Mesh &mesh, const Span<bool> vertex_selection, const bool invert, MutableSpan<int> r_edge_map, - int *r_num_selected_edges) + int *r_selected_edges_num) { BLI_assert(mesh.totedge == r_edge_map.size()); - int num_selected_edges = 0; + int selected_edges_num = 0; for (const int i : IndexRange(mesh.totedge)) { const MEdge &edge = mesh.medge[i]; /* Only add the edge if both vertices will be in the new mesh. */ if (vertex_selection[edge.v1] != invert && vertex_selection[edge.v2] != invert) { - r_edge_map[i] = num_selected_edges; - num_selected_edges++; + r_edge_map[i] = selected_edges_num; + selected_edges_num++; } else { r_edge_map[i] = -1; } } - *r_num_selected_edges = num_selected_edges; + *r_selected_edges_num = selected_edges_num; } static void compute_selected_polygons_from_vertex_selection(const Mesh &mesh, @@ -594,15 +594,15 @@ static void compute_selected_polygons_from_vertex_selection(const Mesh &mesh, const bool invert, Vector<int> &r_selected_poly_indices, Vector<int> &r_loop_starts, - int *r_num_selected_polys, - int *r_num_selected_loops) + int *r_selected_polys_num, + int *r_selected_loops_num) { BLI_assert(mesh.totvert == vertex_selection.size()); r_selected_poly_indices.reserve(mesh.totpoly); r_loop_starts.reserve(mesh.totloop); - int num_selected_loops = 0; + int selected_loops_num = 0; for (const int i : IndexRange(mesh.totpoly)) { const MPoly &poly_src = mesh.mpoly[i]; @@ -617,13 +617,13 @@ static void compute_selected_polygons_from_vertex_selection(const Mesh &mesh, if (all_verts_in_selection) { r_selected_poly_indices.append_unchecked(i); - r_loop_starts.append_unchecked(num_selected_loops); - num_selected_loops += poly_src.totloop; + r_loop_starts.append_unchecked(selected_loops_num); + selected_loops_num += poly_src.totloop; } } - *r_num_selected_polys = r_selected_poly_indices.size(); - *r_num_selected_loops = num_selected_loops; + *r_selected_polys_num = r_selected_poly_indices.size(); + *r_selected_loops_num = selected_loops_num; } /** @@ -636,25 +636,25 @@ static void compute_selected_vertices_and_edges_from_edge_selection( const bool invert, MutableSpan<int> r_vertex_map, MutableSpan<int> r_edge_map, - int *r_num_selected_vertices, - int *r_num_selected_edges) + int *r_selected_vertices_num, + int *r_selected_edges_num) { BLI_assert(mesh.totedge == edge_selection.size()); - int num_selected_edges = 0; - int num_selected_vertices = 0; + int selected_edges_num = 0; + int selected_verts_num = 0; for (const int i : IndexRange(mesh.totedge)) { const MEdge &edge = mesh.medge[i]; if (edge_selection[i] != invert) { - r_edge_map[i] = num_selected_edges; - num_selected_edges++; + r_edge_map[i] = selected_edges_num; + selected_edges_num++; if (r_vertex_map[edge.v1] == -1) { - r_vertex_map[edge.v1] = num_selected_vertices; - num_selected_vertices++; + r_vertex_map[edge.v1] = selected_verts_num; + selected_verts_num++; } if (r_vertex_map[edge.v2] == -1) { - r_vertex_map[edge.v2] = num_selected_vertices; - num_selected_vertices++; + r_vertex_map[edge.v2] = selected_verts_num; + selected_verts_num++; } } else { @@ -662,8 +662,8 @@ static void compute_selected_vertices_and_edges_from_edge_selection( } } - *r_num_selected_vertices = num_selected_vertices; - *r_num_selected_edges = num_selected_edges; + *r_selected_vertices_num = selected_verts_num; + *r_selected_edges_num = selected_edges_num; } /** @@ -673,22 +673,22 @@ static void compute_selected_edges_from_edge_selection(const Mesh &mesh, const Span<bool> edge_selection, const bool invert, MutableSpan<int> r_edge_map, - int *r_num_selected_edges) + int *r_selected_edges_num) { BLI_assert(mesh.totedge == edge_selection.size()); - int num_selected_edges = 0; + int selected_edges_num = 0; for (const int i : IndexRange(mesh.totedge)) { if (edge_selection[i] != invert) { - r_edge_map[i] = num_selected_edges; - num_selected_edges++; + r_edge_map[i] = selected_edges_num; + selected_edges_num++; } else { r_edge_map[i] = -1; } } - *r_num_selected_edges = num_selected_edges; + *r_selected_edges_num = selected_edges_num; } /** @@ -700,13 +700,13 @@ static void compute_selected_polygons_from_edge_selection(const Mesh &mesh, const bool invert, Vector<int> &r_selected_poly_indices, Vector<int> &r_loop_starts, - int *r_num_selected_polys, - int *r_num_selected_loops) + int *r_selected_polys_num, + int *r_selected_loops_num) { r_selected_poly_indices.reserve(mesh.totpoly); r_loop_starts.reserve(mesh.totloop); - int num_selected_loops = 0; + int selected_loops_num = 0; for (const int i : IndexRange(mesh.totpoly)) { const MPoly &poly_src = mesh.mpoly[i]; @@ -721,13 +721,13 @@ static void compute_selected_polygons_from_edge_selection(const Mesh &mesh, if (all_edges_in_selection) { r_selected_poly_indices.append_unchecked(i); - r_loop_starts.append_unchecked(num_selected_loops); - num_selected_loops += poly_src.totloop; + r_loop_starts.append_unchecked(selected_loops_num); + selected_loops_num += poly_src.totloop; } } - *r_num_selected_polys = r_selected_poly_indices.size(); - *r_num_selected_loops = num_selected_loops; + *r_selected_polys_num = r_selected_poly_indices.size(); + *r_selected_loops_num = selected_loops_num; } /** @@ -740,21 +740,21 @@ static void compute_selected_mesh_data_from_vertex_selection_edge_face( MutableSpan<int> r_edge_map, Vector<int> &r_selected_poly_indices, Vector<int> &r_loop_starts, - int *r_num_selected_edges, - int *r_num_selected_polys, - int *r_num_selected_loops) + int *r_selected_edges_num, + int *r_selected_polys_num, + int *r_selected_loops_num) { compute_selected_edges_from_vertex_selection( - mesh, vertex_selection, invert, r_edge_map, r_num_selected_edges); + mesh, vertex_selection, invert, r_edge_map, r_selected_edges_num); compute_selected_polygons_from_vertex_selection(mesh, vertex_selection, invert, r_selected_poly_indices, r_loop_starts, - r_num_selected_polys, - r_num_selected_loops); + r_selected_polys_num, + r_selected_loops_num); } /** @@ -768,24 +768,24 @@ static void compute_selected_mesh_data_from_vertex_selection(const Mesh &mesh, MutableSpan<int> r_edge_map, Vector<int> &r_selected_poly_indices, Vector<int> &r_loop_starts, - int *r_num_selected_vertices, - int *r_num_selected_edges, - int *r_num_selected_polys, - int *r_num_selected_loops) + int *r_selected_vertices_num, + int *r_selected_edges_num, + int *r_selected_polys_num, + int *r_selected_loops_num) { compute_selected_vertices_from_vertex_selection( - vertex_selection, invert, r_vertex_map, r_num_selected_vertices); + vertex_selection, invert, r_vertex_map, r_selected_vertices_num); compute_selected_edges_from_vertex_selection( - mesh, vertex_selection, invert, r_edge_map, r_num_selected_edges); + mesh, vertex_selection, invert, r_edge_map, r_selected_edges_num); compute_selected_polygons_from_vertex_selection(mesh, vertex_selection, invert, r_selected_poly_indices, r_loop_starts, - r_num_selected_polys, - r_num_selected_loops); + r_selected_polys_num, + r_selected_loops_num); } /** @@ -799,19 +799,19 @@ static void compute_selected_mesh_data_from_edge_selection_edge_face( MutableSpan<int> r_edge_map, Vector<int> &r_selected_poly_indices, Vector<int> &r_loop_starts, - int *r_num_selected_edges, - int *r_num_selected_polys, - int *r_num_selected_loops) + int *r_selected_edges_num, + int *r_selected_polys_num, + int *r_selected_loops_num) { compute_selected_edges_from_edge_selection( - mesh, edge_selection, invert, r_edge_map, r_num_selected_edges); + mesh, edge_selection, invert, r_edge_map, r_selected_edges_num); compute_selected_polygons_from_edge_selection(mesh, edge_selection, invert, r_selected_poly_indices, r_loop_starts, - r_num_selected_polys, - r_num_selected_loops); + r_selected_polys_num, + r_selected_loops_num); } /** @@ -825,10 +825,10 @@ static void compute_selected_mesh_data_from_edge_selection(const Mesh &mesh, MutableSpan<int> r_edge_map, Vector<int> &r_selected_poly_indices, Vector<int> &r_loop_starts, - int *r_num_selected_vertices, - int *r_num_selected_edges, - int *r_num_selected_polys, - int *r_num_selected_loops) + int *r_selected_vertices_num, + int *r_selected_edges_num, + int *r_selected_polys_num, + int *r_selected_loops_num) { r_vertex_map.fill(-1); compute_selected_vertices_and_edges_from_edge_selection(mesh, @@ -836,15 +836,15 @@ static void compute_selected_mesh_data_from_edge_selection(const Mesh &mesh, invert, r_vertex_map, r_edge_map, - r_num_selected_vertices, - r_num_selected_edges); + r_selected_vertices_num, + r_selected_edges_num); compute_selected_polygons_from_edge_selection(mesh, edge_selection, invert, r_selected_poly_indices, r_loop_starts, - r_num_selected_polys, - r_num_selected_loops); + r_selected_polys_num, + r_selected_loops_num); } /** @@ -855,26 +855,26 @@ static void compute_selected_polygons_from_poly_selection(const Mesh &mesh, const bool invert, Vector<int> &r_selected_poly_indices, Vector<int> &r_loop_starts, - int *r_num_selected_polys, - int *r_num_selected_loops) + int *r_selected_polys_num, + int *r_selected_loops_num) { BLI_assert(mesh.totpoly == poly_selection.size()); r_selected_poly_indices.reserve(mesh.totpoly); r_loop_starts.reserve(mesh.totloop); - int num_selected_loops = 0; + int selected_loops_num = 0; for (const int i : IndexRange(mesh.totpoly)) { const MPoly &poly_src = mesh.mpoly[i]; /* We keep this one. */ if (poly_selection[i] != invert) { r_selected_poly_indices.append_unchecked(i); - r_loop_starts.append_unchecked(num_selected_loops); - num_selected_loops += poly_src.totloop; + r_loop_starts.append_unchecked(selected_loops_num); + selected_loops_num += poly_src.totloop; } } - *r_num_selected_polys = r_selected_poly_indices.size(); - *r_num_selected_loops = num_selected_loops; + *r_selected_polys_num = r_selected_poly_indices.size(); + *r_selected_loops_num = selected_loops_num; } /** * Checks for every polygon if it is in `poly_selection`. If it is, the edges @@ -887,9 +887,9 @@ static void compute_selected_mesh_data_from_poly_selection_edge_face( MutableSpan<int> r_edge_map, Vector<int> &r_selected_poly_indices, Vector<int> &r_loop_starts, - int *r_num_selected_edges, - int *r_num_selected_polys, - int *r_num_selected_loops) + int *r_selected_edges_num, + int *r_selected_polys_num, + int *r_selected_loops_num) { BLI_assert(mesh.totpoly == poly_selection.size()); BLI_assert(mesh.totedge == r_edge_map.size()); @@ -898,30 +898,30 @@ static void compute_selected_mesh_data_from_poly_selection_edge_face( r_selected_poly_indices.reserve(mesh.totpoly); r_loop_starts.reserve(mesh.totloop); - int num_selected_loops = 0; - int num_selected_edges = 0; + int selected_loops_num = 0; + int selected_edges_num = 0; for (const int i : IndexRange(mesh.totpoly)) { const MPoly &poly_src = mesh.mpoly[i]; /* We keep this one. */ if (poly_selection[i] != invert) { r_selected_poly_indices.append_unchecked(i); - r_loop_starts.append_unchecked(num_selected_loops); - num_selected_loops += poly_src.totloop; + r_loop_starts.append_unchecked(selected_loops_num); + selected_loops_num += poly_src.totloop; /* Add the vertices and the edges. */ Span<MLoop> loops_src(&mesh.mloop[poly_src.loopstart], poly_src.totloop); for (const MLoop &loop : loops_src) { /* Check first if it has not yet been added. */ if (r_edge_map[loop.e] == -1) { - r_edge_map[loop.e] = num_selected_edges; - num_selected_edges++; + r_edge_map[loop.e] = selected_edges_num; + selected_edges_num++; } } } } - *r_num_selected_edges = num_selected_edges; - *r_num_selected_polys = r_selected_poly_indices.size(); - *r_num_selected_loops = num_selected_loops; + *r_selected_edges_num = selected_edges_num; + *r_selected_polys_num = r_selected_poly_indices.size(); + *r_selected_loops_num = selected_loops_num; } /** @@ -935,10 +935,10 @@ static void compute_selected_mesh_data_from_poly_selection(const Mesh &mesh, MutableSpan<int> r_edge_map, Vector<int> &r_selected_poly_indices, Vector<int> &r_loop_starts, - int *r_num_selected_vertices, - int *r_num_selected_edges, - int *r_num_selected_polys, - int *r_num_selected_loops) + int *r_selected_vertices_num, + int *r_selected_edges_num, + int *r_selected_polys_num, + int *r_selected_loops_num) { BLI_assert(mesh.totpoly == poly_selection.size()); BLI_assert(mesh.totedge == r_edge_map.size()); @@ -948,36 +948,36 @@ static void compute_selected_mesh_data_from_poly_selection(const Mesh &mesh, r_selected_poly_indices.reserve(mesh.totpoly); r_loop_starts.reserve(mesh.totloop); - int num_selected_loops = 0; - int num_selected_vertices = 0; - int num_selected_edges = 0; + int selected_loops_num = 0; + int selected_verts_num = 0; + int selected_edges_num = 0; for (const int i : IndexRange(mesh.totpoly)) { const MPoly &poly_src = mesh.mpoly[i]; /* We keep this one. */ if (poly_selection[i] != invert) { r_selected_poly_indices.append_unchecked(i); - r_loop_starts.append_unchecked(num_selected_loops); - num_selected_loops += poly_src.totloop; + r_loop_starts.append_unchecked(selected_loops_num); + selected_loops_num += poly_src.totloop; /* Add the vertices and the edges. */ Span<MLoop> loops_src(&mesh.mloop[poly_src.loopstart], poly_src.totloop); for (const MLoop &loop : loops_src) { /* Check first if it has not yet been added. */ if (r_vertex_map[loop.v] == -1) { - r_vertex_map[loop.v] = num_selected_vertices; - num_selected_vertices++; + r_vertex_map[loop.v] = selected_verts_num; + selected_verts_num++; } if (r_edge_map[loop.e] == -1) { - r_edge_map[loop.e] = num_selected_edges; - num_selected_edges++; + r_edge_map[loop.e] = selected_edges_num; + selected_edges_num++; } } } } - *r_num_selected_vertices = num_selected_vertices; - *r_num_selected_edges = num_selected_edges; - *r_num_selected_polys = r_selected_poly_indices.size(); - *r_num_selected_loops = num_selected_loops; + *r_selected_vertices_num = selected_verts_num; + *r_selected_edges_num = selected_edges_num; + *r_selected_polys_num = r_selected_poly_indices.size(); + *r_selected_loops_num = selected_loops_num; } /** @@ -993,8 +993,8 @@ static void do_mesh_separation(GeometrySet &geometry_set, /* Needed in all cases. */ Vector<int> selected_poly_indices; Vector<int> new_loop_starts; - int num_selected_polys = 0; - int num_selected_loops = 0; + int selected_polys_num = 0; + int selected_loops_num = 0; const Mesh &mesh_in = *in_component.get_for_read(); Mesh *mesh_out; @@ -1007,10 +1007,10 @@ static void do_mesh_separation(GeometrySet &geometry_set, switch (mode) { case GEO_NODE_DELETE_GEOMETRY_MODE_ALL: { Array<int> vertex_map(mesh_in.totvert); - int num_selected_vertices = 0; + int selected_verts_num = 0; Array<int> edge_map(mesh_in.totedge); - int num_selected_edges = 0; + int selected_edges_num = 0; /* Fill all the maps based on the selection. */ switch (domain) { @@ -1022,10 +1022,10 @@ static void do_mesh_separation(GeometrySet &geometry_set, edge_map, selected_poly_indices, new_loop_starts, - &num_selected_vertices, - &num_selected_edges, - &num_selected_polys, - &num_selected_loops); + &selected_verts_num, + &selected_edges_num, + &selected_polys_num, + &selected_loops_num); break; case ATTR_DOMAIN_EDGE: compute_selected_mesh_data_from_edge_selection(mesh_in, @@ -1035,10 +1035,10 @@ static void do_mesh_separation(GeometrySet &geometry_set, edge_map, selected_poly_indices, new_loop_starts, - &num_selected_vertices, - &num_selected_edges, - &num_selected_polys, - &num_selected_loops); + &selected_verts_num, + &selected_edges_num, + &selected_polys_num, + &selected_loops_num); break; case ATTR_DOMAIN_FACE: compute_selected_mesh_data_from_poly_selection(mesh_in, @@ -1048,21 +1048,21 @@ static void do_mesh_separation(GeometrySet &geometry_set, edge_map, selected_poly_indices, new_loop_starts, - &num_selected_vertices, - &num_selected_edges, - &num_selected_polys, - &num_selected_loops); + &selected_verts_num, + &selected_edges_num, + &selected_polys_num, + &selected_loops_num); break; default: BLI_assert_unreachable(); break; } mesh_out = BKE_mesh_new_nomain_from_template(&mesh_in, - num_selected_vertices, - num_selected_edges, + selected_verts_num, + selected_edges_num, 0, - num_selected_loops, - num_selected_polys); + selected_loops_num, + selected_polys_num); out_component.replace(mesh_out, GeometryOwnershipType::Editable); /* Copy the selected parts of the mesh over to the new mesh. */ @@ -1084,14 +1084,14 @@ static void do_mesh_separation(GeometrySet &geometry_set, copy_face_corner_attributes(attributes, in_component, out_component, - num_selected_loops, + selected_loops_num, selected_poly_indices, mesh_in); break; } case GEO_NODE_DELETE_GEOMETRY_MODE_EDGE_FACE: { Array<int> edge_map(mesh_in.totedge); - int num_selected_edges = 0; + int selected_edges_num = 0; /* Fill all the maps based on the selection. */ switch (domain) { @@ -1102,9 +1102,9 @@ static void do_mesh_separation(GeometrySet &geometry_set, edge_map, selected_poly_indices, new_loop_starts, - &num_selected_edges, - &num_selected_polys, - &num_selected_loops); + &selected_edges_num, + &selected_polys_num, + &selected_loops_num); break; case ATTR_DOMAIN_EDGE: compute_selected_mesh_data_from_edge_selection_edge_face(mesh_in, @@ -1113,9 +1113,9 @@ static void do_mesh_separation(GeometrySet &geometry_set, edge_map, selected_poly_indices, new_loop_starts, - &num_selected_edges, - &num_selected_polys, - &num_selected_loops); + &selected_edges_num, + &selected_polys_num, + &selected_loops_num); break; case ATTR_DOMAIN_FACE: compute_selected_mesh_data_from_poly_selection_edge_face(mesh_in, @@ -1124,9 +1124,9 @@ static void do_mesh_separation(GeometrySet &geometry_set, edge_map, selected_poly_indices, new_loop_starts, - &num_selected_edges, - &num_selected_polys, - &num_selected_loops); + &selected_edges_num, + &selected_polys_num, + &selected_loops_num); break; default: BLI_assert_unreachable(); @@ -1134,10 +1134,10 @@ static void do_mesh_separation(GeometrySet &geometry_set, } mesh_out = BKE_mesh_new_nomain_from_template(&mesh_in, mesh_in.totvert, - num_selected_edges, + selected_edges_num, 0, - num_selected_loops, - num_selected_polys); + selected_loops_num, + selected_polys_num); out_component.replace(mesh_out, GeometryOwnershipType::Editable); /* Copy the selected parts of the mesh over to the new mesh. */ @@ -1158,7 +1158,7 @@ static void do_mesh_separation(GeometrySet &geometry_set, copy_face_corner_attributes(attributes, in_component, out_component, - num_selected_loops, + selected_loops_num, selected_poly_indices, mesh_in); break; @@ -1172,8 +1172,8 @@ static void do_mesh_separation(GeometrySet &geometry_set, invert, selected_poly_indices, new_loop_starts, - &num_selected_polys, - &num_selected_loops); + &selected_polys_num, + &selected_loops_num); break; case ATTR_DOMAIN_EDGE: compute_selected_polygons_from_edge_selection(mesh_in, @@ -1181,8 +1181,8 @@ static void do_mesh_separation(GeometrySet &geometry_set, invert, selected_poly_indices, new_loop_starts, - &num_selected_polys, - &num_selected_loops); + &selected_polys_num, + &selected_loops_num); break; case ATTR_DOMAIN_FACE: compute_selected_polygons_from_poly_selection(mesh_in, @@ -1190,15 +1190,15 @@ static void do_mesh_separation(GeometrySet &geometry_set, invert, selected_poly_indices, new_loop_starts, - &num_selected_polys, - &num_selected_loops); + &selected_polys_num, + &selected_loops_num); break; default: BLI_assert_unreachable(); break; } mesh_out = BKE_mesh_new_nomain_from_template( - &mesh_in, mesh_in.totvert, mesh_in.totedge, 0, num_selected_loops, num_selected_polys); + &mesh_in, mesh_in.totvert, mesh_in.totedge, 0, selected_loops_num, selected_polys_num); out_component.replace(mesh_out, GeometryOwnershipType::Editable); /* Copy the selected parts of the mesh over to the new mesh. */ @@ -1217,7 +1217,7 @@ static void do_mesh_separation(GeometrySet &geometry_set, copy_face_corner_attributes(attributes, in_component, out_component, - num_selected_loops, + selected_loops_num, selected_poly_indices, mesh_in); break; diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc index 82584f6f413..0072fbcde93 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc @@ -25,7 +25,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input<decl::Geometry>("Mesh").supported_type(GEO_COMPONENT_TYPE_MESH); b.add_input<decl::Bool>(N_("Selection")).default_value(true).supports_field().hide_value(); b.add_input<decl::Vector>(N_("Offset")).subtype(PROP_TRANSLATION).implicit_field().hide_value(); - b.add_input<decl::Float>(N_("Offset Scale")).default_value(1.0f).min(0.0f).supports_field(); + b.add_input<decl::Float>(N_("Offset Scale")).default_value(1.0f).supports_field(); b.add_input<decl::Bool>(N_("Individual")).default_value(true); b.add_output<decl::Geometry>("Mesh"); b.add_output<decl::Bool>(N_("Top")).field_source(); @@ -523,7 +523,7 @@ static void extrude_mesh_edges(MeshComponent &component, } case ATTR_DOMAIN_FACE: { /* Attribute values for new faces are a mix of the values of faces connected to the its - * original edge. */ + * original edge. */ copy_with_mixing(data.slice(new_poly_range), data.as_span(), [&](const int i) { return edge_to_poly_map[edge_selection[i]].as_span(); }); diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc b/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc index ab6f6b40d5e..6c24f86b63b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc @@ -3,15 +3,8 @@ #include "node_geometry_util.hh" #include "BKE_curves.hh" -#include "BKE_spline.hh" -namespace blender::nodes::node_geo_input_spline_length_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_output<decl::Float>(N_("Length")).field_source(); - b.add_output<decl::Int>(N_("Point Count")).field_source(); -} +namespace blender::nodes { /* -------------------------------------------------------------------- * Spline Length @@ -23,55 +16,66 @@ static VArray<float> construct_spline_length_gvarray(const CurveComponent &compo if (!component.has_curves()) { return {}; } - const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*component.get_for_read()); + const Curves &curves_id = *component.get_for_read(); + const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); - Span<SplinePtr> splines = curve->splines(); - Array<float> spline_lenghts(splines.size()); - for (const int i : splines.index_range()) { - spline_lenghts[i] = splines[i]->length(); - } + curves.ensure_evaluated_lengths(); + + VArray<bool> cyclic = curves.cyclic(); + VArray<float> lengths = VArray<float>::ForFunc( + curves.curves_num(), [&curves, cyclic = std::move(cyclic)](int64_t index) { + return curves.evaluated_length_total_for_curve(index, cyclic[index]); + }); if (domain == ATTR_DOMAIN_CURVE) { - return VArray<float>::ForContainer(std::move(spline_lenghts)); + return lengths; } + if (domain == ATTR_DOMAIN_POINT) { - VArray<float> length = VArray<float>::ForContainer(std::move(spline_lenghts)); return component.attribute_try_adapt_domain<float>( - std::move(length), ATTR_DOMAIN_CURVE, ATTR_DOMAIN_POINT); + std::move(lengths), ATTR_DOMAIN_CURVE, ATTR_DOMAIN_POINT); } return {}; } -class SplineLengthFieldInput final : public GeometryFieldInput { - public: - SplineLengthFieldInput() : GeometryFieldInput(CPPType::get<float>(), "Spline Length node") - { - category_ = Category::Generated; - } +SplineLengthFieldInput::SplineLengthFieldInput() + : GeometryFieldInput(CPPType::get<float>(), "Spline Length node") +{ + category_ = Category::Generated; +} - GVArray get_varray_for_context(const GeometryComponent &component, - const AttributeDomain domain, - IndexMask UNUSED(mask)) const final - { - if (component.type() == GEO_COMPONENT_TYPE_CURVE) { - const CurveComponent &curve_component = static_cast<const CurveComponent &>(component); - return construct_spline_length_gvarray(curve_component, domain); - } - return {}; +GVArray SplineLengthFieldInput::get_varray_for_context(const GeometryComponent &component, + const AttributeDomain domain, + IndexMask UNUSED(mask)) const +{ + if (component.type() == GEO_COMPONENT_TYPE_CURVE) { + const CurveComponent &curve_component = static_cast<const CurveComponent &>(component); + return construct_spline_length_gvarray(curve_component, domain); } + return {}; +} - uint64_t hash() const override - { - /* Some random constant hash. */ - return 3549623580; - } +uint64_t SplineLengthFieldInput::hash() const +{ + /* Some random constant hash. */ + return 3549623580; +} - bool is_equal_to(const fn::FieldNode &other) const override - { - return dynamic_cast<const SplineLengthFieldInput *>(&other) != nullptr; - } -}; +bool SplineLengthFieldInput::is_equal_to(const fn::FieldNode &other) const +{ + return dynamic_cast<const SplineLengthFieldInput *>(&other) != nullptr; +} + +} // namespace blender::nodes + +namespace blender::nodes::node_geo_input_spline_length_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output<decl::Float>(N_("Length")).field_source(); + b.add_output<decl::Int>(N_("Point Count")).field_source(); +} /* -------------------------------------------------------------------- * Spline Count diff --git a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc index 231ef547a8b..368954447c9 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc @@ -298,7 +298,7 @@ class RaycastFunction : public fn::MultiFunction { GMutableSpan result = params.uninitialized_single_output_if_required(7, "Attribute"); if (!result.is_empty()) { MeshAttributeInterpolator interp(&mesh, hit_mask, hit_positions, hit_indices); - result.type().fill_assign_indices(result.type().default_value(), result.data(), mask); + result.type().value_initialize_indices(result.data(), mask); interp.sample_data(*target_data_, domain_, get_map_mode(mapping_), result); } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc index 271dd824d27..31b9f1765a5 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc @@ -1,6 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -#include "BKE_spline.hh" +#include <atomic> + +#include "BKE_curves.hh" #include "UI_interface.h" #include "UI_resources.h" @@ -34,8 +36,40 @@ static void node_init(bNodeTree *UNUSED(tree), bNode *node) node->storage = data; } -static void set_position_in_component(const GeometryNodeCurveHandleMode mode, - CurveComponent &component, +static void update_handle_types_for_movement(int8_t &type, int8_t &other) +{ + switch (type) { + case BEZIER_HANDLE_FREE: + break; + case BEZIER_HANDLE_AUTO: + /* Converting auto handles to aligned handled instead of free handles is + * arbitrary, but expected and "standard" based on behavior in edit mode. */ + if (other == BEZIER_HANDLE_AUTO) { + /* Convert pairs of auto handles to aligned handles when moving one side. */ + type = BEZIER_HANDLE_ALIGN; + other = BEZIER_HANDLE_ALIGN; + } + else { + /* If the other handle isn't automatic, just make the handle free. */ + type = BEZIER_HANDLE_FREE; + } + break; + case BEZIER_HANDLE_VECTOR: + type = BEZIER_HANDLE_FREE; + break; + case BEZIER_HANDLE_ALIGN: + /* The handle can stay aligned if the other handle is also aligned (in which case the other + * handle should be updated to be consistent). But otherwise the handle must be made free to + * avoid conflicting with its "aligned" type. */ + if (other != BEZIER_HANDLE_ALIGN) { + type = BEZIER_HANDLE_FREE; + } + break; + } +} + +static void set_position_in_component(CurveComponent &component, + const GeometryNodeCurveHandleMode mode, const Field<bool> &selection_field, const Field<float3> &position_field, const Field<float3> &offset_field) @@ -52,83 +86,44 @@ static void set_position_in_component(const GeometryNodeCurveHandleMode mode, evaluator.add(offset_field); evaluator.evaluate(); const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); - - std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*component.get_for_read()); - - int current_point = 0; - int current_mask = 0; - for (const SplinePtr &spline : curve->splines()) { - if (spline->type() == CURVE_TYPE_BEZIER) { - BezierSpline &bezier = static_cast<BezierSpline &>(*spline); - - bezier.ensure_auto_handles(); - for (const int i : bezier.positions().index_range()) { - if (current_mask < selection.size() && selection[current_mask] == current_point) { - if (mode & GEO_NODE_CURVE_HANDLE_LEFT) { - if (bezier.handle_types_left()[i] == BEZIER_HANDLE_VECTOR) { - bezier.handle_types_left()[i] = BEZIER_HANDLE_FREE; - } - else if (bezier.handle_types_left()[i] == BEZIER_HANDLE_AUTO) { - bezier.handle_types_left()[i] = BEZIER_HANDLE_ALIGN; - } - } - else { - if (bezier.handle_types_right()[i] == BEZIER_HANDLE_VECTOR) { - bezier.handle_types_right()[i] = BEZIER_HANDLE_FREE; - } - else if (bezier.handle_types_right()[i] == BEZIER_HANDLE_AUTO) { - bezier.handle_types_right()[i] = BEZIER_HANDLE_ALIGN; - } - } - current_mask++; - } - current_point++; - } + const VArray<float3> &new_positions = evaluator.get_evaluated<float3>(0); + const VArray<float3> &new_offsets = evaluator.get_evaluated<float3>(1); + + Curves &curves_id = *component.get_for_write(); + bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); + + Span<float3> positions = curves.positions(); + + const bool use_left = mode == GEO_NODE_CURVE_HANDLE_LEFT; + MutableSpan<int8_t> handle_types = use_left ? curves.handle_types_left() : + curves.handle_types_right(); + MutableSpan<int8_t> handle_types_other = use_left ? curves.handle_types_right() : + curves.handle_types_left(); + MutableSpan<float3> handle_positions = use_left ? curves.handle_positions_left() : + curves.handle_positions_right(); + MutableSpan<float3> handle_positions_other = use_left ? curves.handle_positions_right() : + curves.handle_positions_left(); + + threading::parallel_for(selection.index_range(), 2048, [&](IndexRange range) { + for (const int i : selection.slice(range)) { + update_handle_types_for_movement(handle_types[i], handle_types_other[i]); } - else { - for ([[maybe_unused]] int i : spline->positions().index_range()) { - if (current_mask < selection.size() && selection[current_mask] == current_point) { - current_mask++; - } - current_point++; - } - } - } + }); - const VArray<float3> &positions_input = evaluator.get_evaluated<float3>(0); - const VArray<float3> &offsets_input = evaluator.get_evaluated<float3>(1); - - current_point = 0; - current_mask = 0; - for (const SplinePtr &spline : curve->splines()) { - if (spline->type() == CURVE_TYPE_BEZIER) { - BezierSpline &bezier = static_cast<BezierSpline &>(*spline); - for (const int i : bezier.positions().index_range()) { - if (current_mask < selection.size() && selection[current_mask] == current_point) { - if (mode & GEO_NODE_CURVE_HANDLE_LEFT) { - bezier.set_handle_position_left( - i, positions_input[current_point] + offsets_input[current_point]); - } - else { - bezier.set_handle_position_right( - i, positions_input[current_point] + offsets_input[current_point]); - } - current_mask++; - } - current_point++; - } - } - else { - for ([[maybe_unused]] int i : spline->positions().index_range()) { - if (current_mask < selection.size() && selection[current_mask] == current_point) { - current_mask++; - } - current_point++; - } + threading::parallel_for(selection.index_range(), 2048, [&](IndexRange range) { + for (const int i : selection.slice(range)) { + bke::curves::bezier::set_handle_position(positions[i], + HandleType(handle_types[i]), + HandleType(handle_types_other[i]), + new_positions[i] + new_offsets[i], + handle_positions[i], + handle_positions_other[i]); } - } + }); - component.replace(curve_eval_to_curves(*curve), GeometryOwnershipType::Owned); + curves.calculate_bezier_auto_handles(); + + curves.tag_positions_changed(); } static void node_geo_exec(GeoNodeExecParams params) @@ -141,24 +136,32 @@ static void node_geo_exec(GeoNodeExecParams params) Field<float3> position_field = params.extract_input<Field<float3>>("Position"); Field<float3> offset_field = params.extract_input<Field<float3>>("Offset"); - bool has_bezier = false; + std::atomic<bool> has_curves = false; + std::atomic<bool> has_bezier = false; + geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { - if (geometry_set.has_curves()) { - const std::unique_ptr<CurveEval> curve = curves_to_curve_eval( - *geometry_set.get_curves_for_read()); - has_bezier = curve->has_spline_with_type(CURVE_TYPE_BEZIER); - - set_position_in_component(mode, - geometry_set.get_component_for_write<CurveComponent>(), - selection_field, - position_field, - offset_field); + if (!geometry_set.has_curves()) { + return; + } + has_curves = true; + const CurveComponent &component = *geometry_set.get_component_for_read<CurveComponent>(); + if (!component.attribute_exists("handle_left") || + !component.attribute_exists("handle_right")) { + return; } + has_bezier = true; + + set_position_in_component(geometry_set.get_component_for_write<CurveComponent>(), + mode, + selection_field, + position_field, + offset_field); }); - if (!has_bezier) { - params.error_message_add(NodeWarningType::Info, - TIP_("The input geometry does not contain a Bezier spline")); + + if (has_curves && !has_bezier) { + params.error_message_add(NodeWarningType::Info, TIP_("Input curves do not have Bezier type")); } + params.set_output("Curve", std::move(geometry_set)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_position.cc b/source/blender/nodes/geometry/nodes/node_geo_set_position.cc index eb035aa9b6b..d2ff9753897 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_position.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_position.cc @@ -7,6 +7,8 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "BKE_curves.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_set_position_cc { @@ -62,6 +64,9 @@ static void set_computed_position_and_offset(GeometryComponent &component, break; } case GEO_COMPONENT_TYPE_CURVE: { + CurveComponent &curve_component = static_cast<CurveComponent &>(component); + Curves &curves_id = *curve_component.get_for_write(); + bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); if (component.attribute_exists("handle_right") && component.attribute_exists("handle_left")) { OutputAttribute_Typed<float3> handle_right_attribute = @@ -90,6 +95,9 @@ static void set_computed_position_and_offset(GeometryComponent &component, handle_right_attribute.save(); handle_left_attribute.save(); + + /* Automatic Bezier handles must be recalculated based on the new positions. */ + curves.calculate_bezier_auto_handles(); break; } else { diff --git a/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc index 7f0ba950490..12e306ba480 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc @@ -493,7 +493,7 @@ class NearestTransferFunction : public fn::MultiFunction { GMutableSpan dst = params.uninitialized_single_output_if_required(1, "Attribute"); if (!use_mesh_ && !use_points_) { - dst.type().fill_construct_indices(dst.type().default_value(), dst.data(), mask); + dst.type().value_initialize_indices(dst.data(), mask); return; } @@ -673,7 +673,7 @@ class IndexTransferFunction : public fn::MultiFunction { const CPPType &type = dst.type(); if (src_data_ == nullptr) { - type.fill_construct_indices(type.default_value(), dst.data(), mask); + type.value_initialize_indices(dst.data(), mask); return; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_transform.cc b/source/blender/nodes/geometry/nodes/node_geo_transform.cc index a04544e2814..cc115ee3b3f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_transform.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_transform.cc @@ -103,8 +103,8 @@ static void transform_volume(Volume &volume, const float4x4 &transform, const De memcpy(vdb_matrix.asPointer(), &scale_limited_transform, sizeof(float[4][4])); openvdb::Mat4d vdb_matrix_d{vdb_matrix}; - const int num_grids = BKE_volume_num_grids(&volume); - for (const int i : IndexRange(num_grids)) { + const int grids_num = BKE_volume_num_grids(&volume); + for (const int i : IndexRange(grids_num)) { VolumeGrid *volume_grid = BKE_volume_grid_get_for_write(&volume, i); openvdb::GridBase::Ptr grid = BKE_volume_grid_openvdb_for_write(&volume, volume_grid, false); diff --git a/source/blender/nodes/intern/geometry_nodes_eval_log.cc b/source/blender/nodes/intern/geometry_nodes_eval_log.cc index 5c8f4c52f75..13f38c3352e 100644 --- a/source/blender/nodes/intern/geometry_nodes_eval_log.cc +++ b/source/blender/nodes/intern/geometry_nodes_eval_log.cc @@ -337,6 +337,16 @@ const NodeLog *ModifierLog::find_node_by_node_editor_context(const SpaceNode &sn return tree_log->lookup_node_log(node); } +const NodeLog *ModifierLog::find_node_by_node_editor_context(const SpaceNode &snode, + const StringRef node_name) +{ + const TreeLog *tree_log = ModifierLog::find_tree_by_node_editor_context(snode); + if (tree_log == nullptr) { + return nullptr; + } + return tree_log->lookup_node_log(node_name); +} + const SocketLog *ModifierLog::find_socket_by_node_editor_context(const SpaceNode &snode, const bNode &node, const bNodeSocket &socket) diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c index 6492f528a5e..35d5cb6a994 100644 --- a/source/blender/python/bmesh/bmesh_py_ops_call.c +++ b/source/blender/python/bmesh/bmesh_py_ops_call.c @@ -233,8 +233,8 @@ static int bpy_slot_from_py(BMesh *bm, if (!Matrix_ParseAny(value, &pymat)) { return -1; } - const ushort size = pymat->num_col; - if ((size != pymat->num_row) || (!ELEM(size, 3, 4))) { + const ushort size = pymat->col_num; + if ((size != pymat->row_num) || (!ELEM(size, 3, 4))) { PyErr_Format(PyExc_TypeError, "%.200s: keyword \"%.200s\" expected a 3x3 or 4x4 matrix", opname, diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 9ceff9b84b6..46f89dd4103 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -1309,7 +1309,7 @@ static PyObject *bpy_bmesh_transform(BPy_BMElem *self, PyObject *args, PyObject if (BaseMath_ReadCallback(mat) == -1) { return NULL; } - if (mat->num_col != 4 || mat->num_row != 4) { + if (mat->col_num != 4 || mat->row_num != 4) { PyErr_SetString(PyExc_ValueError, "expected a 4x4 matrix"); return NULL; } diff --git a/source/blender/python/gpu/gpu_py_shader.c b/source/blender/python/gpu/gpu_py_shader.c index 1a53ccd6686..43b26e05327 100644 --- a/source/blender/python/gpu/gpu_py_shader.c +++ b/source/blender/python/gpu/gpu_py_shader.c @@ -381,11 +381,11 @@ static PyObject *pygpu_shader_uniform_float(BPyGPUShader *self, PyObject *args) if (BaseMath_ReadCallback(mat) == -1) { return NULL; } - if ((mat->num_row != mat->num_col) || !ELEM(mat->num_row, 3, 4)) { + if ((mat->row_num != mat->col_num) || !ELEM(mat->row_num, 3, 4)) { PyErr_SetString(PyExc_ValueError, "Expected 3x3 or 4x4 matrix"); return NULL; } - length = mat->num_row * mat->num_col; + length = mat->row_num * mat->col_num; memcpy(values, mat->matrix, sizeof(float) * length); } else { diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index ba3e6a3d74b..34ffef03e66 100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -24,7 +24,7 @@ void bpy_app_generic_callback(struct Main *main, struct PointerRNA **pointers, - const int num_pointers, + const int pointers_num, void *arg); static PyTypeObject BlenderAppCbType; @@ -305,7 +305,7 @@ static PyObject *choose_arguments(PyObject *func, PyObject *args_all, PyObject * /* the actual callback - not necessarily called from py */ void bpy_app_generic_callback(struct Main *UNUSED(main), struct PointerRNA **pointers, - const int num_pointers, + const int pointers_num, void *arg) { PyObject *cb_list = py_cb_array[POINTER_AS_INT(arg)]; @@ -320,14 +320,14 @@ void bpy_app_generic_callback(struct Main *UNUSED(main), Py_ssize_t pos; /* setup arguments */ - for (int i = 0; i < num_pointers; ++i) { + for (int i = 0; i < pointers_num; ++i) { PyTuple_SET_ITEM(args_all, i, pyrna_struct_CreatePyObject(pointers[i])); } - for (int i = num_pointers; i < num_arguments; ++i) { + for (int i = pointers_num; i < num_arguments; ++i) { PyTuple_SET_ITEM(args_all, i, Py_INCREF_RET(Py_None)); } - if (num_pointers == 0) { + if (pointers_num == 0) { PyTuple_SET_ITEM(args_single, 0, Py_INCREF_RET(Py_None)); } else { diff --git a/source/blender/python/intern/bpy_interface_run.c b/source/blender/python/intern/bpy_interface_run.c index 8db122470b8..9299bd196e2 100644 --- a/source/blender/python/intern/bpy_interface_run.c +++ b/source/blender/python/intern/bpy_interface_run.c @@ -35,22 +35,33 @@ /** \name Private Utilities * \{ */ -static void python_script_error_jump_text(Text *text) +static void python_script_error_jump_text(Text *text, const char *filepath) { - int lineno; - int offset; - python_script_error_jump(text->id.name + 2, &lineno, &offset); - if (lineno != -1) { - /* select the line with the error */ - txt_move_to(text, lineno - 1, INT_MAX, false); + int lineno, lineno_end; + int offset, offset_end; + if (python_script_error_jump(filepath, &lineno, &offset, &lineno_end, &offset_end)) { + /* Start at the end so cursor motion that looses the selection, + * leaves the cursor from the most useful place. + * Also, the end can't always be set, so don't give it priority. */ + txt_move_to(text, lineno_end - 1, offset_end, false); txt_move_to(text, lineno - 1, offset, true); } } -/* returns a dummy filename for a textblock so we can tell what file a text block comes from */ -static void bpy_text_filename_get(char *fn, const Main *bmain, size_t fn_len, const Text *text) +/** + * Generate a `filepath` from a text-block so we can tell what file a text block comes from. + */ +static void bpy_text_filepath_get(char *filepath, + const size_t filepath_maxlen, + const Main *bmain, + const Text *text) { - BLI_snprintf(fn, fn_len, "%s%c%s", ID_BLEND_PATH(bmain, &text->id), SEP, text->id.name + 2); + BLI_snprintf(filepath, + filepath_maxlen, + "%s%c%s", + ID_BLEND_PATH(bmain, &text->id), + SEP, + text->id.name + 2); } /* Very annoying! Undo #_PyModule_Clear(), see T23871. */ @@ -74,17 +85,24 @@ typedef struct { * * \note Share a function for this since setup/cleanup logic is the same. */ -static bool python_script_exec( - bContext *C, const char *fn, struct Text *text, struct ReportList *reports, const bool do_jump) +static bool python_script_exec(bContext *C, + const char *filepath, + struct Text *text, + struct ReportList *reports, + const bool do_jump) { Main *bmain_old = CTX_data_main(C); PyObject *main_mod = NULL; PyObject *py_dict = NULL, *py_result = NULL; PyGILState_STATE gilstate; - BLI_assert(fn || text); + char filepath_dummy[FILE_MAX]; + /** The `__file__` added into the name-space. */ + const char *filepath_namespace = NULL; + + BLI_assert(filepath || text); - if (fn == NULL && text == NULL) { + if (filepath == NULL && text == NULL) { return 0; } @@ -93,40 +111,41 @@ static bool python_script_exec( PyC_MainModule_Backup(&main_mod); if (text) { - char fn_dummy[FILE_MAXDIR]; - bpy_text_filename_get(fn_dummy, bmain_old, sizeof(fn_dummy), text); + bpy_text_filepath_get(filepath_dummy, sizeof(filepath_dummy), bmain_old, text); + filepath_namespace = filepath_dummy; if (text->compiled == NULL) { /* if it wasn't already compiled, do it now */ char *buf; - PyObject *fn_dummy_py; + PyObject *filepath_dummy_py; - fn_dummy_py = PyC_UnicodeFromByte(fn_dummy); + filepath_dummy_py = PyC_UnicodeFromByte(filepath_dummy); size_t buf_len_dummy; buf = txt_to_buf(text, &buf_len_dummy); - text->compiled = Py_CompileStringObject(buf, fn_dummy_py, Py_file_input, NULL, -1); + text->compiled = Py_CompileStringObject(buf, filepath_dummy_py, Py_file_input, NULL, -1); MEM_freeN(buf); - Py_DECREF(fn_dummy_py); + Py_DECREF(filepath_dummy_py); if (PyErr_Occurred()) { if (do_jump) { - python_script_error_jump_text(text); + python_script_error_jump_text(text, filepath_dummy); } BPY_text_free_code(text); } } if (text->compiled) { - py_dict = PyC_DefaultNameSpace(fn_dummy); + py_dict = PyC_DefaultNameSpace(filepath_dummy); py_result = PyEval_EvalCode(text->compiled, py_dict, py_dict); } } else { - FILE *fp = BLI_fopen(fn, "r"); + FILE *fp = BLI_fopen(filepath, "r"); + filepath_namespace = filepath; if (fp) { - py_dict = PyC_DefaultNameSpace(fn); + py_dict = PyC_DefaultNameSpace(filepath); #ifdef _WIN32 /* Previously we used PyRun_File to run directly the code on a FILE @@ -153,13 +172,13 @@ static bool python_script_exec( py_result = PyRun_String(pystring, Py_file_input, py_dict, py_dict); } #else - py_result = PyRun_File(fp, fn, Py_file_input, py_dict, py_dict); + py_result = PyRun_File(fp, filepath, Py_file_input, py_dict, py_dict); fclose(fp); #endif } else { PyErr_Format( - PyExc_IOError, "Python file \"%s\" could not be opened: %s", fn, strerror(errno)); + PyExc_IOError, "Python file \"%s\" could not be opened: %s", filepath, strerror(errno)); py_result = NULL; } } @@ -170,7 +189,7 @@ static bool python_script_exec( /* ensure text is valid before use, the script may have freed itself */ Main *bmain_new = CTX_data_main(C); if ((bmain_old == bmain_new) && (BLI_findindex(&bmain_new->texts, text) != -1)) { - python_script_error_jump_text(text); + python_script_error_jump_text(text, filepath_namespace); } } } diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c index f5bec247250..8506ec97bc3 100644 --- a/source/blender/python/intern/bpy_rna_array.c +++ b/source/blender/python/intern/bpy_rna_array.c @@ -377,15 +377,15 @@ static int validate_array(PyObject *rvalue, totdim); return -1; } - if (pymat->num_col != dimsize[0] || pymat->num_row != dimsize[1]) { + if (pymat->col_num != dimsize[0] || pymat->row_num != dimsize[1]) { PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, matrix assign dimension size mismatch, " "is %dx%d, expected be %dx%d", error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), - pymat->num_col, - pymat->num_row, + pymat->col_num, + pymat->row_num, dimsize[0], dimsize[1]); return -1; @@ -473,7 +473,7 @@ static char *copy_values(PyObject *seq, if (dim == 0) { if (MatrixObject_Check(seq)) { MatrixObject *pymat = (MatrixObject *)seq; - const size_t allocsize = pymat->num_col * pymat->num_row * sizeof(float); + const size_t allocsize = pymat->col_num * pymat->row_num * sizeof(float); /* read callback already done by validate */ /* since this is the first iteration we can assume data is allocated */ diff --git a/source/blender/python/intern/bpy_traceback.c b/source/blender/python/intern/bpy_traceback.c index 13af254c286..40478f3613c 100644 --- a/source/blender/python/intern/bpy_traceback.c +++ b/source/blender/python/intern/bpy_traceback.c @@ -24,7 +24,7 @@ static const char *traceback_filepath(PyTracebackObject *tb, PyObject **coerce) return PyBytes_AS_STRING(*coerce); } -/* copied from pythonrun.c, 3.4.0 */ +/* copied from pythonrun.c, 3.10.0 */ _Py_static_string(PyId_string, "<string>"); static int parse_syntax_error(PyObject *err, @@ -32,14 +32,18 @@ static int parse_syntax_error(PyObject *err, PyObject **filename, int *lineno, int *offset, + int *end_lineno, + int *end_offset, PyObject **text) { - long hold; + Py_ssize_t hold; PyObject *v; _Py_IDENTIFIER(msg); _Py_IDENTIFIER(filename); _Py_IDENTIFIER(lineno); _Py_IDENTIFIER(offset); + _Py_IDENTIFIER(end_lineno); + _Py_IDENTIFIER(end_offset); _Py_IDENTIFIER(text); *message = NULL; @@ -71,7 +75,7 @@ static int parse_syntax_error(PyObject *err, if (!v) { goto finally; } - hold = PyLong_AsLong(v); + hold = PyLong_AsSsize_t(v); Py_DECREF(v); if (hold < 0 && PyErr_Occurred()) { goto finally; @@ -87,7 +91,7 @@ static int parse_syntax_error(PyObject *err, Py_DECREF(v); } else { - hold = PyLong_AsLong(v); + hold = PyLong_AsSsize_t(v); Py_DECREF(v); if (hold < 0 && PyErr_Occurred()) { goto finally; @@ -95,6 +99,49 @@ static int parse_syntax_error(PyObject *err, *offset = (int)hold; } + if (Py_TYPE(err) == (PyTypeObject *)PyExc_SyntaxError) { + v = _PyObject_GetAttrId(err, &PyId_end_lineno); + if (!v) { + PyErr_Clear(); + *end_lineno = *lineno; + } + else if (v == Py_None) { + *end_lineno = *lineno; + Py_DECREF(v); + } + else { + hold = PyLong_AsSsize_t(v); + Py_DECREF(v); + if (hold < 0 && PyErr_Occurred()) { + goto finally; + } + *end_lineno = hold; + } + + v = _PyObject_GetAttrId(err, &PyId_end_offset); + if (!v) { + PyErr_Clear(); + *end_offset = -1; + } + else if (v == Py_None) { + *end_offset = -1; + Py_DECREF(v); + } + else { + hold = PyLong_AsSsize_t(v); + Py_DECREF(v); + if (hold < 0 && PyErr_Occurred()) { + goto finally; + } + *end_offset = hold; + } + } + else { + /* `SyntaxError` subclasses. */ + *end_lineno = *lineno; + *end_offset = -1; + } + v = _PyObject_GetAttrId(err, &PyId_text); if (!v) { goto finally; @@ -115,39 +162,48 @@ finally: } /* end copied function! */ -void python_script_error_jump(const char *filepath, int *lineno, int *offset) +bool python_script_error_jump( + const char *filepath, int *r_lineno, int *r_offset, int *r_lineno_end, int *r_offset_end) { + bool success = false; PyObject *exception, *value; PyTracebackObject *tb; - *lineno = -1; - *offset = 0; + *r_lineno = -1; + *r_offset = 0; + + *r_lineno_end = -1; + *r_offset_end = 0; PyErr_Fetch(&exception, &value, (PyObject **)&tb); + if (exception == NULL) { + return false; + } - if (exception && PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError)) { - /* no trace-back available when `SyntaxError`. - * python has no API's to this. reference #parse_syntax_error() from pythonrun.c */ + if (PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError)) { + /* No trace-back available when `SyntaxError`. + * Python has no API's to this. reference #parse_syntax_error() from `pythonrun.c`. */ PyErr_NormalizeException(&exception, &value, (PyObject **)&tb); - if (value) { /* should always be true */ + if (value) { /* Should always be true. */ PyObject *message; - PyObject *filename_py, *text_py; - - if (parse_syntax_error(value, &message, &filename_py, lineno, offset, &text_py)) { - const char *filename = PyUnicode_AsUTF8(filename_py); + PyObject *filepath_exc_py, *text_py; + + if (parse_syntax_error(value, + &message, + &filepath_exc_py, + r_lineno, + r_offset, + r_lineno_end, + r_offset_end, + &text_py)) { + const char *filepath_exc = PyUnicode_AsUTF8(filepath_exc_py); /* python adds a '/', prefix, so check for both */ - if ((BLI_path_cmp(filename, filepath) == 0) || - (ELEM(filename[0], '\\', '/') && BLI_path_cmp(filename + 1, filepath) == 0)) { - /* good */ - } - else { - *lineno = -1; + if ((BLI_path_cmp(filepath_exc, filepath) == 0) || + (ELEM(filepath_exc[0], '\\', '/') && BLI_path_cmp(filepath_exc + 1, filepath) == 0)) { + success = true; } } - else { - *lineno = -1; - } } PyErr_Restore(exception, value, (PyObject *)tb); /* takes away reference! */ } @@ -167,9 +223,12 @@ void python_script_error_jump(const char *filepath, int *lineno, int *offset) Py_DECREF(coerce); if (match) { - *lineno = tb->tb_lineno; + success = true; + *r_lineno = *r_lineno_end = tb->tb_lineno; /* used to break here, but better find the inner most line */ } } } + + return success; } diff --git a/source/blender/python/intern/bpy_traceback.h b/source/blender/python/intern/bpy_traceback.h index 99e032f3594..f5232eca864 100644 --- a/source/blender/python/intern/bpy_traceback.h +++ b/source/blender/python/intern/bpy_traceback.h @@ -10,7 +10,8 @@ extern "C" { #endif -void python_script_error_jump(const char *filepath, int *lineno, int *offset); +bool python_script_error_jump( + const char *filepath, int *r_lineno, int *r_offset, int *r_lineno_end, int *r_offset_end); #ifdef __cplusplus } diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c index 8ed156a7e55..1aa2cec861c 100644 --- a/source/blender/python/mathutils/mathutils.c +++ b/source/blender/python/mathutils/mathutils.c @@ -92,47 +92,46 @@ Py_hash_t mathutils_array_hash(const float *array, size_t array_len) } int mathutils_array_parse( - float *array, int array_min, int array_max, PyObject *value, const char *error_prefix) + float *array, int array_num_min, int array_num_max, PyObject *value, const char *error_prefix) { - const uint flag = array_max; - int size; + const uint flag = array_num_max; + int num; - array_max &= ~MU_ARRAY_FLAGS; + array_num_max &= ~MU_ARRAY_FLAGS; #if 1 /* approx 6x speedup for mathutils types */ - if ((size = VectorObject_Check(value) ? ((VectorObject *)value)->size : 0) || - (size = EulerObject_Check(value) ? 3 : 0) || - (size = QuaternionObject_Check(value) ? 4 : 0) || - (size = ColorObject_Check(value) ? 3 : 0)) { + if ((num = VectorObject_Check(value) ? ((VectorObject *)value)->vec_num : 0) || + (num = EulerObject_Check(value) ? 3 : 0) || (num = QuaternionObject_Check(value) ? 4 : 0) || + (num = ColorObject_Check(value) ? 3 : 0)) { if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) { return -1; } if (flag & MU_ARRAY_SPILL) { - CLAMP_MAX(size, array_max); + CLAMP_MAX(num, array_num_max); } - if (size > array_max || size < array_min) { - if (array_max == array_min) { + if (num > array_num_max || num < array_num_min) { + if (array_num_max == array_num_min) { PyErr_Format(PyExc_ValueError, - "%.200s: sequence size is %d, expected %d", + "%.200s: sequence length is %d, expected %d", error_prefix, - size, - array_max); + num, + array_num_max); } else { PyErr_Format(PyExc_ValueError, - "%.200s: sequence size is %d, expected [%d - %d]", + "%.200s: sequence length is %d, expected [%d - %d]", error_prefix, - size, - array_min, - array_max); + num, + array_num_min, + array_num_max); } return -1; } - memcpy(array, ((const BaseMathObject *)value)->data, size * sizeof(float)); + memcpy(array, ((const BaseMathObject *)value)->data, num * sizeof(float)); } else #endif @@ -145,77 +144,76 @@ int mathutils_array_parse( return -1; } - size = PySequence_Fast_GET_SIZE(value_fast); + num = PySequence_Fast_GET_SIZE(value_fast); if (flag & MU_ARRAY_SPILL) { - CLAMP_MAX(size, array_max); + CLAMP_MAX(num, array_num_max); } - if (size > array_max || size < array_min) { - if (array_max == array_min) { + if (num > array_num_max || num < array_num_min) { + if (array_num_max == array_num_min) { PyErr_Format(PyExc_ValueError, - "%.200s: sequence size is %d, expected %d", + "%.200s: sequence length is %d, expected %d", error_prefix, - size, - array_max); + num, + array_num_max); } else { PyErr_Format(PyExc_ValueError, - "%.200s: sequence size is %d, expected [%d - %d]", + "%.200s: sequence length is %d, expected [%d - %d]", error_prefix, - size, - array_min, - array_max); + num, + array_num_min, + array_num_max); } Py_DECREF(value_fast); return -1; } - size = mathutils_array_parse_fast(array, size, value_fast, error_prefix); + num = mathutils_array_parse_fast(array, num, value_fast, error_prefix); Py_DECREF(value_fast); } - if (size != -1) { + if (num != -1) { if (flag & MU_ARRAY_ZERO) { - const int size_left = array_max - size; - if (size_left) { - memset(&array[size], 0, sizeof(float) * size_left); + const int array_num_left = array_num_max - num; + if (array_num_left) { + memset(&array[num], 0, sizeof(float) * array_num_left); } } } - return size; + return num; } int mathutils_array_parse_alloc(float **array, - int array_min, + int array_num, PyObject *value, const char *error_prefix) { - int size; + int num; #if 1 /* approx 6x speedup for mathutils types */ - if ((size = VectorObject_Check(value) ? ((VectorObject *)value)->size : 0) || - (size = EulerObject_Check(value) ? 3 : 0) || - (size = QuaternionObject_Check(value) ? 4 : 0) || - (size = ColorObject_Check(value) ? 3 : 0)) { + if ((num = VectorObject_Check(value) ? ((VectorObject *)value)->vec_num : 0) || + (num = EulerObject_Check(value) ? 3 : 0) || (num = QuaternionObject_Check(value) ? 4 : 0) || + (num = ColorObject_Check(value) ? 3 : 0)) { if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) { return -1; } - if (size < array_min) { + if (num < array_num) { PyErr_Format(PyExc_ValueError, "%.200s: sequence size is %d, expected > %d", error_prefix, - size, - array_min); + num, + array_num); return -1; } - *array = PyMem_Malloc(size * sizeof(float)); - memcpy(*array, ((const BaseMathObject *)value)->data, size * sizeof(float)); - return size; + *array = PyMem_Malloc(num * sizeof(float)); + memcpy(*array, ((const BaseMathObject *)value)->data, num * sizeof(float)); + return num; } #endif @@ -230,21 +228,21 @@ int mathutils_array_parse_alloc(float **array, return -1; } - size = PySequence_Fast_GET_SIZE(value_fast); + num = PySequence_Fast_GET_SIZE(value_fast); - if (size < array_min) { + if (num < array_num) { Py_DECREF(value_fast); PyErr_Format(PyExc_ValueError, "%.200s: sequence size is %d, expected > %d", error_prefix, - size, - array_min); + num, + array_num); return -1; } - *array = PyMem_Malloc(size * sizeof(float)); + *array = PyMem_Malloc(num * sizeof(float)); - ret = mathutils_array_parse_fast(*array, size, value_fast, error_prefix); + ret = mathutils_array_parse_fast(*array, num, value_fast, error_prefix); Py_DECREF(value_fast); if (ret == -1) { @@ -261,7 +259,7 @@ int mathutils_array_parse_alloc_v(float **array, { PyObject *value_fast; const int array_dim_flag = array_dim; - int i, size; + int i, num; /* non list/tuple cases */ if (!(value_fast = PySequence_Fast(value, error_prefix))) { @@ -269,30 +267,30 @@ int mathutils_array_parse_alloc_v(float **array, return -1; } - size = PySequence_Fast_GET_SIZE(value_fast); + num = PySequence_Fast_GET_SIZE(value_fast); - if (size != 0) { + if (num != 0) { PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast); float *fp; array_dim &= ~MU_ARRAY_FLAGS; - fp = *array = PyMem_Malloc(size * array_dim * sizeof(float)); + fp = *array = PyMem_Malloc(num * array_dim * sizeof(float)); - for (i = 0; i < size; i++, fp += array_dim) { + for (i = 0; i < num; i++, fp += array_dim) { PyObject *item = value_fast_items[i]; if (mathutils_array_parse(fp, array_dim, array_dim_flag, item, error_prefix) == -1) { PyMem_Free(*array); *array = NULL; - size = -1; + num = -1; break; } } } Py_DECREF(value_fast); - return size; + return num; } int mathutils_int_array_parse(int *array, int array_dim, PyObject *value, const char *error_prefix) @@ -458,7 +456,7 @@ int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) { return -1; } - if (((MatrixObject *)value)->num_row < 3 || ((MatrixObject *)value)->num_col < 3) { + if (((MatrixObject *)value)->row_num < 3 || ((MatrixObject *)value)->col_num < 3) { PyErr_Format( PyExc_ValueError, "%.200s: matrix must have minimum 3x3 dimensions", error_prefix); return -1; diff --git a/source/blender/python/mathutils/mathutils.h b/source/blender/python/mathutils/mathutils.h index 5831489ef5b..84386e99d18 100644 --- a/source/blender/python/mathutils/mathutils.h +++ b/source/blender/python/mathutils/mathutils.h @@ -153,12 +153,12 @@ void _BaseMathObject_RaiseNotFrozenExc(const BaseMathObject *self); * \return length of `value`, -1 on error. */ int mathutils_array_parse( - float *array, int array_min, int array_max, PyObject *value, const char *error_prefix); + float *array, int array_num_min, int array_num_max, PyObject *value, const char *error_prefix); /** * \return -1 is returned on error and no allocation is made. */ int mathutils_array_parse_alloc(float **array, - int array_min, + int array_num_min, PyObject *value, const char *error_prefix); /** diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index b8eaf1486ab..76b5424711f 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -34,7 +34,7 @@ static PyObject *MatrixAccess_CreatePyObject(MatrixObject *matrix, const eMatrix static int matrix_row_vector_check(MatrixObject *mat, VectorObject *vec, int row) { - if ((vec->size != mat->num_col) || (row >= mat->num_row)) { + if ((vec->vec_num != mat->col_num) || (row >= mat->row_num)) { PyErr_SetString(PyExc_AttributeError, "Matrix(): " "owner matrix has been resized since this row vector was created"); @@ -46,7 +46,7 @@ static int matrix_row_vector_check(MatrixObject *mat, VectorObject *vec, int row static int matrix_col_vector_check(MatrixObject *mat, VectorObject *vec, int col) { - if ((vec->size != mat->num_row) || (col >= mat->num_col)) { + if ((vec->vec_num != mat->row_num) || (col >= mat->col_num)) { PyErr_SetString(PyExc_AttributeError, "Matrix(): " "owner matrix has been resized since this column vector was created"); @@ -80,7 +80,7 @@ static int mathutils_matrix_row_get(BaseMathObject *bmo, int row) return -1; } - for (col = 0; col < self->num_col; col++) { + for (col = 0; col < self->col_num; col++) { bmo->data[col] = MATRIX_ITEM(self, row, col); } @@ -99,7 +99,7 @@ static int mathutils_matrix_row_set(BaseMathObject *bmo, int row) return -1; } - for (col = 0; col < self->num_col; col++) { + for (col = 0; col < self->col_num; col++) { MATRIX_ITEM(self, row, col) = bmo->data[col]; } @@ -162,7 +162,7 @@ static int mathutils_matrix_col_check(BaseMathObject *bmo) static int mathutils_matrix_col_get(BaseMathObject *bmo, int col) { MatrixObject *self = (MatrixObject *)bmo->cb_user; - int num_row; + int row_num; int row; if (BaseMath_ReadCallback(self) == -1) { @@ -172,10 +172,10 @@ static int mathutils_matrix_col_get(BaseMathObject *bmo, int col) return -1; } - /* for 'translation' size will always be '3' even on 4x4 vec */ - num_row = min_ii(self->num_row, ((const VectorObject *)bmo)->size); + /* for 'translation' `vec_num` will always be '3' even on 4x4 vec */ + row_num = min_ii(self->row_num, ((const VectorObject *)bmo)->vec_num); - for (row = 0; row < num_row; row++) { + for (row = 0; row < row_num; row++) { bmo->data[row] = MATRIX_ITEM(self, row, col); } @@ -185,7 +185,7 @@ static int mathutils_matrix_col_get(BaseMathObject *bmo, int col) static int mathutils_matrix_col_set(BaseMathObject *bmo, int col) { MatrixObject *self = (MatrixObject *)bmo->cb_user; - int num_row; + int row_num; int row; if (BaseMath_ReadCallback_ForWrite(self) == -1) { @@ -195,10 +195,10 @@ static int mathutils_matrix_col_set(BaseMathObject *bmo, int col) return -1; } - /* for 'translation' size will always be '3' even on 4x4 vec */ - num_row = min_ii(self->num_row, ((const VectorObject *)bmo)->size); + /* for 'translation' `vec_num` will always be '3' even on 4x4 vec */ + row_num = min_ii(self->row_num, ((const VectorObject *)bmo)->vec_num); - for (row = 0; row < num_row; row++) { + for (row = 0; row < row_num; row++) { MATRIX_ITEM(self, row, col) = bmo->data[row]; } @@ -349,18 +349,18 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) /* Input is now as a sequence of rows so length of sequence * is the number of rows */ /* -1 is an error, size checks will account for this */ - const ushort num_row = PySequence_Size(arg); + const ushort row_num = PySequence_Size(arg); - if (num_row >= 2 && num_row <= 4) { + if (row_num >= 2 && row_num <= 4) { PyObject *item = PySequence_GetItem(arg, 0); /* Since each item is a row, number of items is the * same as the number of columns */ - const ushort num_col = PySequence_Size(item); + const ushort col_num = PySequence_Size(item); Py_XDECREF(item); - if (num_col >= 2 && num_col <= 4) { + if (col_num >= 2 && col_num <= 4) { /* Sane row & col size, new matrix and assign as slice. */ - PyObject *matrix = Matrix_CreatePyObject(NULL, num_col, num_row, type); + PyObject *matrix = Matrix_CreatePyObject(NULL, col_num, row_num, type); if (Matrix_ass_slice((MatrixObject *)matrix, 0, INT_MAX, arg) == 0) { return matrix; } @@ -613,7 +613,7 @@ PyDoc_STRVAR(C_Matrix_Scale_doc, static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args) { PyObject *vec = NULL; - int vec_size; + int vec_num; float tvec[3]; float factor; int matSize; @@ -646,12 +646,10 @@ static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args) return NULL; } if (vec) { - vec_size = (matSize == 2 ? 2 : 3); - if (mathutils_array_parse(tvec, - vec_size, - vec_size, - vec, - "Matrix.Scale(factor, size, axis), invalid 'axis' arg") == -1) { + vec_num = (matSize == 2 ? 2 : 3); + if (mathutils_array_parse( + tvec, vec_num, vec_num, vec, "Matrix.Scale(factor, size, axis), invalid 'axis' arg") == + -1) { return NULL; } } @@ -671,11 +669,11 @@ static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args) * normalize arbitrary axis */ float norm = 0.0f; int x; - for (x = 0; x < vec_size; x++) { + for (x = 0; x < vec_num; x++) { norm += tvec[x] * tvec[x]; } norm = sqrtf(norm); - for (x = 0; x < vec_size; x++) { + for (x = 0; x < vec_num; x++) { tvec[x] /= norm; } if (matSize == 2) { @@ -795,23 +793,23 @@ static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args) else { /* arbitrary plane */ - const int vec_size = (matSize == 2 ? 2 : 3); + const int vec_num = (matSize == 2 ? 2 : 3); float tvec[4]; if (mathutils_array_parse(tvec, - vec_size, - vec_size, + vec_num, + vec_num, axis, "Matrix.OrthoProjection(axis, size), invalid 'axis' arg") == -1) { return NULL; } /* normalize arbitrary axis */ - for (x = 0; x < vec_size; x++) { + for (x = 0; x < vec_num; x++) { norm += tvec[x] * tvec[x]; } norm = sqrtf(norm); - for (x = 0; x < vec_size; x++) { + for (x = 0; x < vec_num; x++) { tvec[x] /= norm; } if (matSize == 2) { @@ -1019,7 +1017,7 @@ static PyObject *C_Matrix_LocRotScale(PyObject *cls, PyObject *args) return NULL; } - if (mat_obj->num_col == 3 && mat_obj->num_row == 3) { + if (mat_obj->col_num == 3 && mat_obj->row_num == 3) { copy_m4_m3(mat, (const float(*)[3])mat_obj->matrix); } else { @@ -1062,20 +1060,20 @@ void matrix_as_3x3(float mat[3][3], MatrixObject *self) static void matrix_copy(MatrixObject *mat_dst, const MatrixObject *mat_src) { - BLI_assert((mat_dst->num_col == mat_src->num_col) && (mat_dst->num_row == mat_src->num_row)); + BLI_assert((mat_dst->col_num == mat_src->col_num) && (mat_dst->row_num == mat_src->row_num)); BLI_assert(mat_dst != mat_src); - memcpy(mat_dst->matrix, mat_src->matrix, sizeof(float) * (mat_dst->num_col * mat_dst->num_row)); + memcpy(mat_dst->matrix, mat_src->matrix, sizeof(float) * (mat_dst->col_num * mat_dst->row_num)); } static void matrix_unit_internal(MatrixObject *self) { - const int mat_size = sizeof(float) * (self->num_col * self->num_row); + const int mat_size = sizeof(float) * (self->col_num * self->row_num); memset(self->matrix, 0x0, mat_size); - const int col_row_max = min_ii(self->num_col, self->num_row); - const int num_row = self->num_row; + const int col_row_max = min_ii(self->col_num, self->row_num); + const int row_num = self->row_num; for (int col = 0; col < col_row_max; col++) { - self->matrix[(col * num_row) + col] = 1.0f; + self->matrix[(col * row_num) + col] = 1.0f; } } @@ -1085,8 +1083,8 @@ static void matrix_transpose_internal(float mat_dst_fl[], const MatrixObject *ma ushort col, row; uint i = 0; - for (row = 0; row < mat_src->num_row; row++) { - for (col = 0; col < mat_src->num_col; col++) { + for (row = 0; row < mat_src->row_num; row++) { + for (col = 0; col < mat_src->col_num; col++) { mat_dst_fl[i++] = MATRIX_ITEM(mat_src, row, col); } } @@ -1095,13 +1093,13 @@ static void matrix_transpose_internal(float mat_dst_fl[], const MatrixObject *ma /* assumes rowsize == colsize is checked and the read callback has run */ static float matrix_determinant_internal(const MatrixObject *self) { - if (self->num_col == 2) { + if (self->col_num == 2) { return determinant_m2(MATRIX_ITEM(self, 0, 0), MATRIX_ITEM(self, 0, 1), MATRIX_ITEM(self, 1, 0), MATRIX_ITEM(self, 1, 1)); } - if (self->num_col == 3) { + if (self->col_num == 3) { return determinant_m3(MATRIX_ITEM(self, 0, 0), MATRIX_ITEM(self, 0, 1), MATRIX_ITEM(self, 0, 2), @@ -1152,8 +1150,8 @@ static void matrix_invert_with_det_n_internal(float *mat_dst, /* divide by determinant & set values */ k = 0; - for (i = 0; i < dim; i++) { /* num_col */ - for (j = 0; j < dim; j++) { /* num_row */ + for (i = 0; i < dim; i++) { /* col_num */ + for (j = 0; j < dim; j++) { /* row_num */ mat_dst[MATRIX_ITEM_INDEX_NUMROW(dim, j, i)] = mat[k++] / det; } } @@ -1165,11 +1163,11 @@ static void matrix_invert_with_det_n_internal(float *mat_dst, static bool matrix_invert_internal(const MatrixObject *self, float *r_mat) { float det; - BLI_assert(self->num_col == self->num_row); + BLI_assert(self->col_num == self->row_num); det = matrix_determinant_internal(self); if (det != 0.0f) { - matrix_invert_with_det_n_internal(r_mat, self->matrix, det, self->num_col); + matrix_invert_with_det_n_internal(r_mat, self->matrix, det, self->col_num); return true; } @@ -1184,7 +1182,7 @@ static void matrix_invert_safe_internal(const MatrixObject *self, float *r_mat) { float det; float *in_mat = self->matrix; - BLI_assert(self->num_col == self->num_row); + BLI_assert(self->col_num == self->row_num); det = matrix_determinant_internal(self); if (det == 0.0f) { @@ -1194,7 +1192,7 @@ static void matrix_invert_safe_internal(const MatrixObject *self, float *r_mat) * and modify it in place to add diagonal epsilon. */ in_mat = r_mat; - switch (self->num_col) { + switch (self->col_num) { case 2: { float(*mat)[2] = (float(*)[2])in_mat; @@ -1248,7 +1246,7 @@ static void matrix_invert_safe_internal(const MatrixObject *self, float *r_mat) } } - matrix_invert_with_det_n_internal(r_mat, in_mat, det, self->num_col); + matrix_invert_with_det_n_internal(r_mat, in_mat, det, self->col_num); } /*-----------------------------METHODS----------------------------*/ @@ -1268,13 +1266,13 @@ static PyObject *Matrix_to_quaternion(MatrixObject *self) } /* must be 3-4 cols, 3-4 rows, square matrix */ - if ((self->num_row < 3) || (self->num_col < 3) || (self->num_row != self->num_col)) { + if ((self->row_num < 3) || (self->col_num < 3) || (self->row_num != self->col_num)) { PyErr_SetString(PyExc_ValueError, "Matrix.to_quat(): " "inappropriate matrix size - expects 3x3 or 4x4 matrix"); return NULL; } - if (self->num_row == 3) { + if (self->row_num == 3) { mat3_to_quat(quat, (float(*)[3])self->matrix); } else { @@ -1326,10 +1324,10 @@ static PyObject *Matrix_to_euler(MatrixObject *self, PyObject *args) } /* Must be 3-4 cols, 3-4 rows, square matrix. */ - if (self->num_row == 3 && self->num_col == 3) { + if (self->row_num == 3 && self->col_num == 3) { copy_m3_m3(mat, (const float(*)[3])self->matrix); } - else if (self->num_row == 4 && self->num_col == 4) { + else if (self->row_num == 4 && self->col_num == 4) { copy_m3_m4(mat, (const float(*)[4])self->matrix); } else { @@ -1401,36 +1399,36 @@ static PyObject *Matrix_resize_4x4(MatrixObject *self) unit_m4(mat); - for (col = 0; col < self->num_col; col++) { - memcpy(mat[col], MATRIX_COL_PTR(self, col), self->num_row * sizeof(float)); + for (col = 0; col < self->col_num; col++) { + memcpy(mat[col], MATRIX_COL_PTR(self, col), self->row_num * sizeof(float)); } copy_m4_m4((float(*)[4])self->matrix, (const float(*)[4])mat); - self->num_col = 4; - self->num_row = 4; + self->col_num = 4; + self->row_num = 4; Py_RETURN_NONE; } -static PyObject *Matrix_to_NxN(MatrixObject *self, const int num_col, const int num_row) +static PyObject *Matrix_to_NxN(MatrixObject *self, const int col_num, const int row_num) { - const int mat_size = sizeof(float) * (num_col * num_row); + const int mat_size = sizeof(float) * (col_num * row_num); MatrixObject *pymat = (MatrixObject *)Matrix_CreatePyObject_alloc( - PyMem_Malloc(mat_size), num_col, num_row, Py_TYPE(self)); + PyMem_Malloc(mat_size), col_num, row_num, Py_TYPE(self)); - if ((self->num_row == num_row) && (self->num_col == num_col)) { + if ((self->row_num == row_num) && (self->col_num == col_num)) { memcpy(pymat->matrix, self->matrix, mat_size); } else { - if ((self->num_col < num_col) || (self->num_row < num_row)) { + if ((self->col_num < col_num) || (self->row_num < row_num)) { matrix_unit_internal(pymat); } - const int col_len_src = min_ii(num_col, self->num_col); - const int row_len_src = min_ii(num_row, self->num_row); + const int col_len_src = min_ii(col_num, self->col_num); + const int row_len_src = min_ii(row_num, self->row_num); for (int col = 0; col < col_len_src; col++) { memcpy( - &pymat->matrix[col * num_row], MATRIX_COL_PTR(self, col), sizeof(float) * row_len_src); + &pymat->matrix[col * row_num], MATRIX_COL_PTR(self, col), sizeof(float) * row_len_src); } } return (PyObject *)pymat; @@ -1495,7 +1493,7 @@ static PyObject *Matrix_to_translation(MatrixObject *self) return NULL; } - if ((self->num_row < 3) || self->num_col < 4) { + if ((self->row_num < 3) || self->col_num < 4) { PyErr_SetString(PyExc_ValueError, "Matrix.to_translation(): " "inappropriate matrix size"); @@ -1526,7 +1524,7 @@ static PyObject *Matrix_to_scale(MatrixObject *self) } /* Must be 3-4 cols, 3-4 rows, square matrix. */ - if ((self->num_row < 3) || (self->num_col < 3)) { + if ((self->row_num < 3) || (self->col_num < 3)) { PyErr_SetString(PyExc_ValueError, "Matrix.to_scale(): " "inappropriate matrix size, 3x3 minimum size"); @@ -1546,7 +1544,7 @@ static PyObject *Matrix_to_scale(MatrixObject *self) /* re-usable checks for invert */ static bool matrix_invert_is_compat(const MatrixObject *self) { - if (self->num_col != self->num_row) { + if (self->col_num != self->row_num) { PyErr_SetString(PyExc_ValueError, "Matrix.invert(ed): " "only square matrices are supported"); @@ -1571,7 +1569,7 @@ static bool matrix_invert_args_check(const MatrixObject *self, PyObject *args, b return false; } - if ((self->num_col != fallback->num_col) || (self->num_row != fallback->num_row)) { + if ((self->col_num != fallback->col_num) || (self->row_num != fallback->row_num)) { PyErr_SetString(PyExc_TypeError, "Matrix.invert: " "matrix argument has different dimensions"); @@ -1782,7 +1780,7 @@ static PyObject *Matrix_adjugate(MatrixObject *self) return NULL; } - if (self->num_col != self->num_row) { + if (self->col_num != self->row_num) { PyErr_SetString(PyExc_ValueError, "Matrix.adjugate(d): " "only square matrices are supported"); @@ -1790,12 +1788,12 @@ static PyObject *Matrix_adjugate(MatrixObject *self) } /* calculate the classical adjoint */ - if (self->num_col <= 4) { - adjoint_matrix_n(self->matrix, self->matrix, self->num_col); + if (self->col_num <= 4) { + adjoint_matrix_n(self->matrix, self->matrix, self->col_num); } else { PyErr_Format( - PyExc_ValueError, "Matrix adjugate(d): size (%d) unsupported", (int)self->num_col); + PyExc_ValueError, "Matrix adjugate(d): size (%d) unsupported", (int)self->col_num); return NULL; } @@ -1838,7 +1836,7 @@ static PyObject *Matrix_rotate(MatrixObject *self, PyObject *value) return NULL; } - if (self->num_row != 3 || self->num_col != 3) { + if (self->row_num != 3 || self->col_num != 3) { PyErr_SetString(PyExc_ValueError, "Matrix.rotate(): " "must have 3x3 dimensions"); @@ -1870,7 +1868,7 @@ static PyObject *Matrix_decompose(MatrixObject *self) float quat[4]; float size[3]; - if (self->num_row != 4 || self->num_col != 4) { + if (self->row_num != 4 || self->col_num != 4) { PyErr_SetString(PyExc_ValueError, "Matrix.decompose(): " "inappropriate matrix size - expects 4x4 matrix"); @@ -1913,7 +1911,7 @@ static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args) return NULL; } - if (self->num_col != mat2->num_col || self->num_row != mat2->num_row) { + if (self->col_num != mat2->col_num || self->row_num != mat2->row_num) { PyErr_SetString(PyExc_ValueError, "Matrix.lerp(): " "expects both matrix objects of the same dimensions"); @@ -1925,14 +1923,14 @@ static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args) } /* TODO: different sized matrix. */ - if (self->num_col == 4 && self->num_row == 4) { + if (self->col_num == 4 && self->row_num == 4) { #ifdef MATH_STANDALONE blend_m4_m4m4((float(*)[4])mat, (float(*)[4])self->matrix, (float(*)[4])mat2->matrix, fac); #else interp_m4_m4m4((float(*)[4])mat, (float(*)[4])self->matrix, (float(*)[4])mat2->matrix, fac); #endif } - else if (self->num_col == 3 && self->num_row == 3) { + else if (self->col_num == 3 && self->row_num == 3) { #ifdef MATH_STANDALONE blend_m3_m3m3((float(*)[3])mat, (float(*)[3])self->matrix, (float(*)[3])mat2->matrix, fac); #else @@ -1946,7 +1944,7 @@ static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args) return NULL; } - return Matrix_CreatePyObject(mat, self->num_col, self->num_row, Py_TYPE(self)); + return Matrix_CreatePyObject(mat, self->col_num, self->row_num, Py_TYPE(self)); } /*---------------------------matrix.determinant() ----------------*/ @@ -1966,7 +1964,7 @@ static PyObject *Matrix_determinant(MatrixObject *self) return NULL; } - if (self->num_col != self->num_row) { + if (self->col_num != self->row_num) { PyErr_SetString(PyExc_ValueError, "Matrix.determinant(): " "only square matrices are supported"); @@ -1989,19 +1987,19 @@ static PyObject *Matrix_transpose(MatrixObject *self) return NULL; } - if (self->num_col != self->num_row) { + if (self->col_num != self->row_num) { PyErr_SetString(PyExc_ValueError, "Matrix.transpose(d): " "only square matrices are supported"); return NULL; } - if (self->num_col == 2) { + if (self->col_num == 2) { const float t = MATRIX_ITEM(self, 1, 0); MATRIX_ITEM(self, 1, 0) = MATRIX_ITEM(self, 0, 1); MATRIX_ITEM(self, 0, 1) = t; } - else if (self->num_col == 3) { + else if (self->col_num == 3) { transpose_m3((float(*)[3])self->matrix); } else { @@ -2035,17 +2033,17 @@ static PyObject *Matrix_normalize(MatrixObject *self) return NULL; } - if (self->num_col != self->num_row) { + if (self->col_num != self->row_num) { PyErr_SetString(PyExc_ValueError, "Matrix.normalize(): " "only square matrices are supported"); return NULL; } - if (self->num_col == 3) { + if (self->col_num == 3) { normalize_m3((float(*)[3])self->matrix); } - else if (self->num_col == 4) { + else if (self->col_num == 4) { normalize_m4((float(*)[4])self->matrix); } else { @@ -2083,7 +2081,7 @@ static PyObject *Matrix_zero(MatrixObject *self) return NULL; } - copy_vn_fl(self->matrix, self->num_col * self->num_row, 0.0f); + copy_vn_fl(self->matrix, self->col_num * self->row_num, 0.0f); if (BaseMath_WriteCallback(self) == -1) { return NULL; @@ -2094,12 +2092,12 @@ static PyObject *Matrix_zero(MatrixObject *self) /*---------------------------matrix.identity(() ------------------*/ static void matrix_identity_internal(MatrixObject *self) { - BLI_assert((self->num_col == self->num_row) && (self->num_row <= 4)); + BLI_assert((self->col_num == self->row_num) && (self->row_num <= 4)); - if (self->num_col == 2) { + if (self->col_num == 2) { unit_m2((float(*)[2])self->matrix); } - else if (self->num_col == 3) { + else if (self->col_num == 3) { unit_m3((float(*)[3])self->matrix); } else { @@ -2123,7 +2121,7 @@ static PyObject *Matrix_identity(MatrixObject *self) return NULL; } - if (self->num_col != self->num_row) { + if (self->col_num != self->row_num) { PyErr_SetString(PyExc_ValueError, "Matrix.identity(): " "only square matrices are supported"); @@ -2143,7 +2141,7 @@ static PyObject *Matrix_identity(MatrixObject *self) static PyObject *Matrix_copy_notest(MatrixObject *self, const float *matrix) { - return Matrix_CreatePyObject((const float *)matrix, self->num_col, self->num_row, Py_TYPE(self)); + return Matrix_CreatePyObject((const float *)matrix, self->col_num, self->row_num, Py_TYPE(self)); } PyDoc_STRVAR(Matrix_copy_doc, @@ -2180,13 +2178,13 @@ static PyObject *Matrix_repr(MatrixObject *self) return NULL; } - for (row = 0; row < self->num_row; row++) { - rows[row] = PyTuple_New(self->num_col); - for (col = 0; col < self->num_col; col++) { + for (row = 0; row < self->row_num; row++) { + rows[row] = PyTuple_New(self->col_num); + for (col = 0; col < self->col_num; col++) { PyTuple_SET_ITEM(rows[row], col, PyFloat_FromDouble(MATRIX_ITEM(self, row, col))); } } - switch (self->num_row) { + switch (self->row_num) { case 2: return PyUnicode_FromFormat( "Matrix((%R,\n" @@ -2236,9 +2234,9 @@ static PyObject *Matrix_str(MatrixObject *self) ds = BLI_dynstr_new(); /* First determine the maximum width for each column */ - for (col = 0; col < self->num_col; col++) { + for (col = 0; col < self->col_num; col++) { maxsize[col] = 0; - for (row = 0; row < self->num_row; row++) { + for (row = 0; row < self->row_num; row++) { const int size = BLI_snprintf_rlen( dummy_buf, sizeof(dummy_buf), "%.4f", MATRIX_ITEM(self, row, col)); maxsize[col] = max_ii(maxsize[col], size); @@ -2246,12 +2244,12 @@ static PyObject *Matrix_str(MatrixObject *self) } /* Now write the unicode string to be printed */ - BLI_dynstr_appendf(ds, "<Matrix %dx%d (", self->num_row, self->num_col); - for (row = 0; row < self->num_row; row++) { - for (col = 0; col < self->num_col; col++) { + BLI_dynstr_appendf(ds, "<Matrix %dx%d (", self->row_num, self->col_num); + for (row = 0; row < self->row_num; row++) { + for (col = 0; col < self->col_num; col++) { BLI_dynstr_appendf(ds, col ? ", %*.4f" : "%*.4f", maxsize[col], MATRIX_ITEM(self, row, col)); } - BLI_dynstr_append(ds, row + 1 != self->num_row ? ")\n (" : ")"); + BLI_dynstr_append(ds, row + 1 != self->row_num ? ")\n (" : ")"); } BLI_dynstr_append(ds, ">"); @@ -2272,8 +2270,8 @@ static PyObject *Matrix_richcmpr(PyObject *a, PyObject *b, int op) return NULL; } - ok = ((matA->num_row == matB->num_row) && (matA->num_col == matB->num_col) && - EXPP_VectorsAreEqual(matA->matrix, matB->matrix, (matA->num_col * matA->num_row), 1)) ? + ok = ((matA->row_num == matB->row_num) && (matA->col_num == matB->col_num) && + EXPP_VectorsAreEqual(matA->matrix, matB->matrix, (matA->col_num * matA->row_num), 1)) ? 0 : -1; } @@ -2314,7 +2312,7 @@ static Py_hash_t Matrix_hash(MatrixObject *self) matrix_transpose_internal(mat, self); - return mathutils_array_hash(mat, self->num_row * self->num_col); + return mathutils_array_hash(mat, self->row_num * self->col_num); } /*---------------------SEQUENCE PROTOCOLS------------------------ @@ -2322,7 +2320,7 @@ static Py_hash_t Matrix_hash(MatrixObject *self) * sequence length */ static int Matrix_len(MatrixObject *self) { - return self->num_row; + return self->row_num; } /*----------------------------object[]--------------------------- * sequence accessor (get) @@ -2333,14 +2331,14 @@ static PyObject *Matrix_item_row(MatrixObject *self, int row) return NULL; } - if (row < 0 || row >= self->num_row) { + if (row < 0 || row >= self->row_num) { PyErr_SetString(PyExc_IndexError, "matrix[attribute]: " "array index out of range"); return NULL; } return Vector_CreatePyObject_cb( - (PyObject *)self, self->num_col, mathutils_matrix_row_cb_index, row); + (PyObject *)self, self->col_num, mathutils_matrix_row_cb_index, row); } /* same but column access */ static PyObject *Matrix_item_col(MatrixObject *self, int col) @@ -2349,14 +2347,14 @@ static PyObject *Matrix_item_col(MatrixObject *self, int col) return NULL; } - if (col < 0 || col >= self->num_col) { + if (col < 0 || col >= self->col_num) { PyErr_SetString(PyExc_IndexError, "matrix[attribute]: " "array index out of range"); return NULL; } return Vector_CreatePyObject_cb( - (PyObject *)self, self->num_row, mathutils_matrix_col_cb_index, col); + (PyObject *)self, self->row_num, mathutils_matrix_col_cb_index, col); } /*----------------------------object[]------------------------- @@ -2370,18 +2368,18 @@ static int Matrix_ass_item_row(MatrixObject *self, int row, PyObject *value) return -1; } - if (row >= self->num_row || row < 0) { + if (row >= self->row_num || row < 0) { PyErr_SetString(PyExc_IndexError, "matrix[attribute] = x: bad row"); return -1; } if (mathutils_array_parse( - vec, self->num_col, self->num_col, value, "matrix[i] = value assignment") == -1) { + vec, self->col_num, self->col_num, value, "matrix[i] = value assignment") == -1) { return -1; } /* Since we are assigning a row we cannot memcpy */ - for (col = 0; col < self->num_col; col++) { + for (col = 0; col < self->col_num; col++) { MATRIX_ITEM(self, row, col) = vec[col]; } @@ -2396,18 +2394,18 @@ static int Matrix_ass_item_col(MatrixObject *self, int col, PyObject *value) return -1; } - if (col >= self->num_col || col < 0) { + if (col >= self->col_num || col < 0) { PyErr_SetString(PyExc_IndexError, "matrix[attribute] = x: bad col"); return -1; } if (mathutils_array_parse( - vec, self->num_row, self->num_row, value, "matrix[i] = value assignment") == -1) { + vec, self->row_num, self->row_num, value, "matrix[i] = value assignment") == -1) { return -1; } /* Since we are assigning a row we cannot memcpy */ - for (row = 0; row < self->num_row; row++) { + for (row = 0; row < self->row_num; row++) { MATRIX_ITEM(self, row, col) = vec[row]; } @@ -2427,8 +2425,8 @@ static PyObject *Matrix_slice(MatrixObject *self, int begin, int end) return NULL; } - CLAMP(begin, 0, self->num_row); - CLAMP(end, 0, self->num_row); + CLAMP(begin, 0, self->row_num); + CLAMP(end, 0, self->row_num); begin = MIN2(begin, end); tuple = PyTuple_New(end - begin); @@ -2436,7 +2434,7 @@ static PyObject *Matrix_slice(MatrixObject *self, int begin, int end) PyTuple_SET_ITEM(tuple, count - begin, Vector_CreatePyObject_cb( - (PyObject *)self, self->num_col, mathutils_matrix_row_cb_index, count)); + (PyObject *)self, self->col_num, mathutils_matrix_row_cb_index, count)); } return tuple; @@ -2451,8 +2449,8 @@ static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *va return -1; } - CLAMP(begin, 0, self->num_row); - CLAMP(end, 0, self->num_row); + CLAMP(begin, 0, self->row_num); + CLAMP(end, 0, self->row_num); begin = MIN2(begin, end); /* non list/tuple cases */ @@ -2475,7 +2473,7 @@ static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *va return -1; } - memcpy(mat, self->matrix, self->num_col * self->num_row * sizeof(float)); + memcpy(mat, self->matrix, self->col_num * self->row_num * sizeof(float)); /* parse sub items */ for (row = begin; row < end; row++) { @@ -2483,21 +2481,21 @@ static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *va PyObject *item = value_fast_items[row - begin]; if (mathutils_array_parse( - vec, self->num_col, self->num_col, item, "matrix[begin:end] = value assignment") == + vec, self->col_num, self->col_num, item, "matrix[begin:end] = value assignment") == -1) { Py_DECREF(value_fast); return -1; } - for (col = 0; col < self->num_col; col++) { - mat[col * self->num_row + row] = vec[col]; + for (col = 0; col < self->col_num; col++) { + mat[col * self->row_num + row] = vec[col]; } } Py_DECREF(value_fast); /* Parsed well - now set in matrix. */ - memcpy(self->matrix, mat, self->num_col * self->num_row * sizeof(float)); + memcpy(self->matrix, mat, self->col_num * self->row_num * sizeof(float)); (void)BaseMath_WriteCallback(self); return 0; @@ -2525,16 +2523,16 @@ static PyObject *Matrix_add(PyObject *m1, PyObject *m2) return NULL; } - if (mat1->num_col != mat2->num_col || mat1->num_row != mat2->num_row) { + if (mat1->col_num != mat2->col_num || mat1->row_num != mat2->row_num) { PyErr_SetString(PyExc_ValueError, "Matrix addition: " "matrices must have the same dimensions for this operation"); return NULL; } - add_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row); + add_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->col_num * mat1->row_num); - return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_TYPE(mat1)); + return Matrix_CreatePyObject(mat, mat1->col_num, mat1->row_num, Py_TYPE(mat1)); } /*------------------------obj - obj------------------------------ * subtraction */ @@ -2559,24 +2557,24 @@ static PyObject *Matrix_sub(PyObject *m1, PyObject *m2) return NULL; } - if (mat1->num_col != mat2->num_col || mat1->num_row != mat2->num_row) { + if (mat1->col_num != mat2->col_num || mat1->row_num != mat2->row_num) { PyErr_SetString(PyExc_ValueError, "Matrix addition: " "matrices must have the same dimensions for this operation"); return NULL; } - sub_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row); + sub_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->col_num * mat1->row_num); - return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_TYPE(mat1)); + return Matrix_CreatePyObject(mat, mat1->col_num, mat1->row_num, Py_TYPE(mat1)); } /*------------------------obj * obj------------------------------ * element-wise multiplication */ static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar) { float tmat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; - mul_vn_vn_fl(tmat, mat->matrix, mat->num_col * mat->num_row, scalar); - return Matrix_CreatePyObject(tmat, mat->num_col, mat->num_row, Py_TYPE(mat)); + mul_vn_vn_fl(tmat, mat->matrix, mat->col_num * mat->row_num, scalar); + return Matrix_CreatePyObject(tmat, mat->col_num, mat->row_num, Py_TYPE(mat)); } static PyObject *Matrix_mul(PyObject *m1, PyObject *m2) @@ -2602,16 +2600,16 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2) /* MATRIX * MATRIX */ float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; - if ((mat1->num_row != mat2->num_row) || (mat1->num_col != mat2->num_col)) { + if ((mat1->row_num != mat2->row_num) || (mat1->col_num != mat2->col_num)) { PyErr_SetString(PyExc_ValueError, "matrix1 * matrix2: matrix1 number of rows/columns " "and the matrix2 number of rows/columns must be the same"); return NULL; } - mul_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row); + mul_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->col_num * mat1->row_num); - return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1)); + return Matrix_CreatePyObject(mat, mat2->col_num, mat1->row_num, Py_TYPE(mat1)); } if (mat2) { /* FLOAT/INT * MATRIX */ @@ -2656,18 +2654,18 @@ static PyObject *Matrix_imul(PyObject *m1, PyObject *m2) if (mat1 && mat2) { /* MATRIX *= MATRIX */ - if ((mat1->num_row != mat2->num_row) || (mat1->num_col != mat2->num_col)) { + if ((mat1->row_num != mat2->row_num) || (mat1->col_num != mat2->col_num)) { PyErr_SetString(PyExc_ValueError, "matrix1 *= matrix2: matrix1 number of rows/columns " "and the matrix2 number of rows/columns must be the same"); return NULL; } - mul_vn_vn(mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row); + mul_vn_vn(mat1->matrix, mat2->matrix, mat1->col_num * mat1->row_num); } else if (mat1 && (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0)) { /* MATRIX *= FLOAT/INT */ - mul_vn_fl(mat1->matrix, mat1->num_row * mat1->num_col, scalar); + mul_vn_fl(mat1->matrix, mat1->row_num * mat1->col_num, scalar); } else { PyErr_Format(PyExc_TypeError, @@ -2686,7 +2684,7 @@ static PyObject *Matrix_imul(PyObject *m1, PyObject *m2) * matrix multiplication */ static PyObject *Matrix_matmul(PyObject *m1, PyObject *m2) { - int vec_size; + int vec_num; MatrixObject *mat1 = NULL, *mat2 = NULL; @@ -2709,24 +2707,24 @@ static PyObject *Matrix_matmul(PyObject *m1, PyObject *m2) int col, row, item; - if (mat1->num_col != mat2->num_row) { + if (mat1->col_num != mat2->row_num) { PyErr_SetString(PyExc_ValueError, "matrix1 * matrix2: matrix1 number of columns " "and the matrix2 number of rows must be the same"); return NULL; } - for (col = 0; col < mat2->num_col; col++) { - for (row = 0; row < mat1->num_row; row++) { + for (col = 0; col < mat2->col_num; col++) { + for (row = 0; row < mat1->row_num; row++) { double dot = 0.0f; - for (item = 0; item < mat1->num_col; item++) { + for (item = 0; item < mat1->col_num; item++) { dot += (double)(MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col)); } - mat[(col * mat1->num_row) + row] = (float)dot; + mat[(col * mat1->row_num) + row] = (float)dot; } } - return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1)); + return Matrix_CreatePyObject(mat, mat2->col_num, mat1->row_num, Py_TYPE(mat1)); } if (mat1) { /* MATRIX @ VECTOR */ @@ -2740,14 +2738,14 @@ static PyObject *Matrix_matmul(PyObject *m1, PyObject *m2) return NULL; } - if (mat1->num_col == 4 && vec2->size == 3) { - vec_size = 3; + if (mat1->col_num == 4 && vec2->vec_num == 3) { + vec_num = 3; } else { - vec_size = mat1->num_row; + vec_num = mat1->row_num; } - return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(m2)); + return Vector_CreatePyObject(tvec, vec_num, Py_TYPE(m2)); } } @@ -2782,27 +2780,27 @@ static PyObject *Matrix_imatmul(PyObject *m1, PyObject *m2) float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; int col, row, item; - if (mat1->num_col != mat2->num_row) { + if (mat1->col_num != mat2->row_num) { PyErr_SetString(PyExc_ValueError, "matrix1 * matrix2: matrix1 number of columns " "and the matrix2 number of rows must be the same"); return NULL; } - for (col = 0; col < mat2->num_col; col++) { - for (row = 0; row < mat1->num_row; row++) { + for (col = 0; col < mat2->col_num; col++) { + for (row = 0; row < mat1->row_num; row++) { double dot = 0.0f; - for (item = 0; item < mat1->num_col; item++) { + for (item = 0; item < mat1->col_num; item++) { dot += (double)(MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col)); } /* store in new matrix as overwriting original at this point will cause * subsequent iterations to use incorrect values */ - mat[(col * mat1->num_row) + row] = (float)dot; + mat[(col * mat1->row_num) + row] = (float)dot; } } /* copy matrix back */ - memcpy(mat1->matrix, mat, (mat1->num_row * mat1->num_col) * sizeof(float)); + memcpy(mat1->matrix, mat, (mat1->row_num * mat1->col_num) * sizeof(float)); } else { PyErr_Format(PyExc_TypeError, @@ -2841,14 +2839,14 @@ static PyObject *Matrix_subscript(MatrixObject *self, PyObject *item) return NULL; } if (i < 0) { - i += self->num_row; + i += self->row_num; } return Matrix_item_row(self, i); } if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx(item, self->num_row, &start, &stop, &step, &slicelength) < 0) { + if (PySlice_GetIndicesEx(item, self->row_num, &start, &stop, &step, &slicelength) < 0) { return NULL; } @@ -2876,14 +2874,14 @@ static int Matrix_ass_subscript(MatrixObject *self, PyObject *item, PyObject *va return -1; } if (i < 0) { - i += self->num_row; + i += self->row_num; } return Matrix_ass_item_row(self, i, value); } if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx(item, self->num_row, &start, &stop, &step, &slicelength) < 0) { + if (PySlice_GetIndicesEx(item, self->row_num, &start, &stop, &step, &slicelength) < 0) { return -1; } @@ -2955,7 +2953,7 @@ static PyObject *Matrix_translation_get(MatrixObject *self, void *UNUSED(closure } /* Must be 4x4 square matrix. */ - if (self->num_row != 4 || self->num_col != 4) { + if (self->row_num != 4 || self->col_num != 4) { PyErr_SetString(PyExc_AttributeError, "Matrix.translation: " "inappropriate matrix size, must be 4x4"); @@ -2977,7 +2975,7 @@ static int Matrix_translation_set(MatrixObject *self, PyObject *value, void *UNU } /* Must be 4x4 square matrix. */ - if (self->num_row != 4 || self->num_col != 4) { + if (self->row_num != 4 || self->col_num != 4) { PyErr_SetString(PyExc_AttributeError, "Matrix.translation: " "inappropriate matrix size, must be 4x4"); @@ -3021,7 +3019,7 @@ static PyObject *Matrix_median_scale_get(MatrixObject *self, void *UNUSED(closur } /* Must be 3-4 cols, 3-4 rows, square matrix. */ - if ((self->num_row < 3) || (self->num_col < 3)) { + if ((self->row_num < 3) || (self->col_num < 3)) { PyErr_SetString(PyExc_AttributeError, "Matrix.median_scale: " "inappropriate matrix size, 3x3 minimum"); @@ -3043,10 +3041,10 @@ static PyObject *Matrix_is_negative_get(MatrixObject *self, void *UNUSED(closure } /* Must be 3-4 cols, 3-4 rows, square matrix. */ - if (self->num_row == 4 && self->num_col == 4) { + if (self->row_num == 4 && self->col_num == 4) { return PyBool_FromLong(is_negative_m4((const float(*)[4])self->matrix)); } - if (self->num_row == 3 && self->num_col == 3) { + if (self->row_num == 3 && self->col_num == 3) { return PyBool_FromLong(is_negative_m3((const float(*)[3])self->matrix)); } @@ -3065,10 +3063,10 @@ static PyObject *Matrix_is_orthogonal_get(MatrixObject *self, void *UNUSED(closu } /* Must be 3-4 cols, 3-4 rows, square matrix. */ - if (self->num_row == 4 && self->num_col == 4) { + if (self->row_num == 4 && self->col_num == 4) { return PyBool_FromLong(is_orthonormal_m4((const float(*)[4])self->matrix)); } - if (self->num_row == 3 && self->num_col == 3) { + if (self->row_num == 3 && self->col_num == 3) { return PyBool_FromLong(is_orthonormal_m3((const float(*)[3])self->matrix)); } @@ -3088,10 +3086,10 @@ static PyObject *Matrix_is_orthogonal_axis_vectors_get(MatrixObject *self, void } /* Must be 3-4 cols, 3-4 rows, square matrix. */ - if (self->num_row == 4 && self->num_col == 4) { + if (self->row_num == 4 && self->col_num == 4) { return PyBool_FromLong(is_orthogonal_m4((const float(*)[4])self->matrix)); } - if (self->num_row == 3 && self->num_col == 3) { + if (self->row_num == 3 && self->col_num == 3) { return PyBool_FromLong(is_orthogonal_m3((const float(*)[3])self->matrix)); } @@ -3271,22 +3269,22 @@ PyTypeObject matrix_Type = { }; PyObject *Matrix_CreatePyObject(const float *mat, - const ushort num_col, - const ushort num_row, + const ushort col_num, + const ushort row_num, PyTypeObject *base_type) { MatrixObject *self; float *mat_alloc; /* matrix objects can be any 2-4row x 2-4col matrix */ - if (num_col < 2 || num_col > 4 || num_row < 2 || num_row > 4) { + if (col_num < 2 || col_num > 4 || row_num < 2 || row_num > 4) { PyErr_SetString(PyExc_RuntimeError, "Matrix(): " "row and column sizes must be between 2 and 4"); return NULL; } - mat_alloc = PyMem_Malloc(num_col * num_row * sizeof(float)); + mat_alloc = PyMem_Malloc(col_num * row_num * sizeof(float)); if (UNLIKELY(mat_alloc == NULL)) { PyErr_SetString(PyExc_MemoryError, "Matrix(): " @@ -3297,23 +3295,23 @@ PyObject *Matrix_CreatePyObject(const float *mat, self = BASE_MATH_NEW(MatrixObject, matrix_Type, base_type); if (self) { self->matrix = mat_alloc; - self->num_col = num_col; - self->num_row = num_row; + self->col_num = col_num; + self->row_num = row_num; /* init callbacks as NULL */ self->cb_user = NULL; self->cb_type = self->cb_subtype = 0; if (mat) { /* If a float array passed. */ - memcpy(self->matrix, mat, num_col * num_row * sizeof(float)); + memcpy(self->matrix, mat, col_num * row_num * sizeof(float)); } - else if (num_col == num_row) { + else if (col_num == row_num) { /* or if no arguments are passed return identity matrix for square matrices */ matrix_identity_internal(self); } else { /* otherwise zero everything */ - memset(self->matrix, 0, num_col * num_row * sizeof(float)); + memset(self->matrix, 0, col_num * row_num * sizeof(float)); } self->flag = BASE_MATH_FLAG_DEFAULT; } @@ -3325,14 +3323,14 @@ PyObject *Matrix_CreatePyObject(const float *mat, } PyObject *Matrix_CreatePyObject_wrap(float *mat, - const ushort num_col, - const ushort num_row, + const ushort col_num, + const ushort row_num, PyTypeObject *base_type) { MatrixObject *self; /* matrix objects can be any 2-4row x 2-4col matrix */ - if (num_col < 2 || num_col > 4 || num_row < 2 || num_row > 4) { + if (col_num < 2 || col_num > 4 || row_num < 2 || row_num > 4) { PyErr_SetString(PyExc_RuntimeError, "Matrix(): " "row and column sizes must be between 2 and 4"); @@ -3341,8 +3339,8 @@ PyObject *Matrix_CreatePyObject_wrap(float *mat, self = BASE_MATH_NEW(MatrixObject, matrix_Type, base_type); if (self) { - self->num_col = num_col; - self->num_row = num_row; + self->col_num = col_num; + self->row_num = row_num; /* init callbacks as NULL */ self->cb_user = NULL; @@ -3355,9 +3353,9 @@ PyObject *Matrix_CreatePyObject_wrap(float *mat, } PyObject *Matrix_CreatePyObject_cb( - PyObject *cb_user, const ushort num_col, const ushort num_row, uchar cb_type, uchar cb_subtype) + PyObject *cb_user, const ushort col_num, const ushort row_num, uchar cb_type, uchar cb_subtype) { - MatrixObject *self = (MatrixObject *)Matrix_CreatePyObject(NULL, num_col, num_row, NULL); + MatrixObject *self = (MatrixObject *)Matrix_CreatePyObject(NULL, col_num, row_num, NULL); if (self) { Py_INCREF(cb_user); self->cb_user = cb_user; @@ -3369,12 +3367,12 @@ PyObject *Matrix_CreatePyObject_cb( } PyObject *Matrix_CreatePyObject_alloc(float *mat, - const ushort num_col, - const ushort num_row, + const ushort col_num, + const ushort row_num, PyTypeObject *base_type) { MatrixObject *self; - self = (MatrixObject *)Matrix_CreatePyObject_wrap(mat, num_col, num_row, base_type); + self = (MatrixObject *)Matrix_CreatePyObject_wrap(mat, col_num, row_num, base_type); if (self) { self->flag &= ~BASE_MATH_FLAG_IS_WRAP; } @@ -3419,7 +3417,7 @@ int Matrix_Parse2x2(PyObject *o, void *p) if (!Matrix_ParseCheck(pymat)) { return 0; } - if ((pymat->num_col != 2) || (pymat->num_row != 2)) { + if ((pymat->col_num != 2) || (pymat->row_num != 2)) { PyErr_SetString(PyExc_ValueError, "matrix must be 2x2"); return 0; } @@ -3436,7 +3434,7 @@ int Matrix_Parse3x3(PyObject *o, void *p) if (!Matrix_ParseCheck(pymat)) { return 0; } - if ((pymat->num_col != 3) || (pymat->num_row != 3)) { + if ((pymat->col_num != 3) || (pymat->row_num != 3)) { PyErr_SetString(PyExc_ValueError, "matrix must be 3x3"); return 0; } @@ -3453,7 +3451,7 @@ int Matrix_Parse4x4(PyObject *o, void *p) if (!Matrix_ParseCheck(pymat)) { return 0; } - if ((pymat->num_col != 4) || (pymat->num_row != 4)) { + if ((pymat->col_num != 4) || (pymat->row_num != 4)) { PyErr_SetString(PyExc_ValueError, "matrix must be 4x4"); return 0; } @@ -3497,7 +3495,7 @@ static void MatrixAccess_dealloc(MatrixAccessObject *self) static int MatrixAccess_len(MatrixAccessObject *self) { - return (self->type == MAT_ACCESS_ROW) ? self->matrix_user->num_row : self->matrix_user->num_col; + return (self->type == MAT_ACCESS_ROW) ? self->matrix_user->row_num : self->matrix_user->col_num; } static PyObject *MatrixAccess_slice(MatrixAccessObject *self, int begin, int end) @@ -3511,11 +3509,11 @@ static PyObject *MatrixAccess_slice(MatrixAccessObject *self, int begin, int end PyObject *(*Matrix_item_new)(MatrixObject *, int); if (self->type == MAT_ACCESS_ROW) { - matrix_access_len = matrix_user->num_row; + matrix_access_len = matrix_user->row_num; Matrix_item_new = Matrix_item_row; } else { /* MAT_ACCESS_ROW */ - matrix_access_len = matrix_user->num_col; + matrix_access_len = matrix_user->col_num; Matrix_item_new = Matrix_item_col; } @@ -3546,13 +3544,13 @@ static PyObject *MatrixAccess_subscript(MatrixAccessObject *self, PyObject *item } if (self->type == MAT_ACCESS_ROW) { if (i < 0) { - i += matrix_user->num_row; + i += matrix_user->row_num; } return Matrix_item_row(matrix_user, i); } /* MAT_ACCESS_ROW */ if (i < 0) { - i += matrix_user->num_col; + i += matrix_user->col_num; } return Matrix_item_col(matrix_user, i); } @@ -3592,13 +3590,13 @@ static int MatrixAccess_ass_subscript(MatrixAccessObject *self, PyObject *item, if (self->type == MAT_ACCESS_ROW) { if (i < 0) { - i += matrix_user->num_row; + i += matrix_user->row_num; } return Matrix_ass_item_row(matrix_user, i, value); } /* MAT_ACCESS_ROW */ if (i < 0) { - i += matrix_user->num_col; + i += matrix_user->col_num; } return Matrix_ass_item_col(matrix_user, i, value); } diff --git a/source/blender/python/mathutils/mathutils_Matrix.h b/source/blender/python/mathutils/mathutils_Matrix.h index 6dd1640b3bf..bc596ce6ac8 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.h +++ b/source/blender/python/mathutils/mathutils_Matrix.h @@ -20,14 +20,14 @@ typedef unsigned short ushort; #ifdef DEBUG # define MATRIX_ITEM_ASSERT(_mat, _row, _col) \ - (BLI_assert(_row < (_mat)->num_row && _col < (_mat)->num_col)) + (BLI_assert(_row < (_mat)->row_num && _col < (_mat)->col_num)) #else # define MATRIX_ITEM_ASSERT(_mat, _row, _col) (void)0 #endif #define MATRIX_ITEM_INDEX_NUMROW(_totrow, _row, _col) (((_totrow) * (_col)) + (_row)) #define MATRIX_ITEM_INDEX(_mat, _row, _col) \ - (MATRIX_ITEM_ASSERT(_mat, _row, _col), (((_mat)->num_row * (_col)) + (_row))) + (MATRIX_ITEM_ASSERT(_mat, _row, _col), (((_mat)->row_num * (_col)) + (_row))) #define MATRIX_ITEM_PTR(_mat, _row, _col) ((_mat)->matrix + MATRIX_ITEM_INDEX(_mat, _row, _col)) #define MATRIX_ITEM(_mat, _row, _col) ((_mat)->matrix[MATRIX_ITEM_INDEX(_mat, _row, _col)]) @@ -36,8 +36,8 @@ typedef unsigned short ushort; typedef struct { BASE_MATH_MEMBERS(matrix); - ushort num_col; - ushort num_row; + ushort col_num; + ushort row_num; } MatrixObject; /* struct data contains a pointer to the actual data that the @@ -47,17 +47,17 @@ typedef struct { /* prototypes */ PyObject *Matrix_CreatePyObject(const float *mat, - ushort num_col, - ushort num_row, + ushort col_num, + ushort row_num, PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT; PyObject *Matrix_CreatePyObject_wrap(float *mat, - ushort num_col, - ushort num_row, + ushort col_num, + ushort row_num, PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); PyObject *Matrix_CreatePyObject_cb(PyObject *user, - unsigned short num_col, - unsigned short num_row, + unsigned short col_num, + unsigned short row_num, unsigned char cb_type, unsigned char cb_subtype) ATTR_WARN_UNUSED_RESULT; @@ -65,8 +65,8 @@ PyObject *Matrix_CreatePyObject_cb(PyObject *user, * \param mat: Initialized matrix value to use in-place, allocated with #PyMem_Malloc */ PyObject *Matrix_CreatePyObject_alloc(float *mat, - ushort num_col, - ushort num_row, + ushort col_num, + ushort row_num, PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT; /* PyArg_ParseTuple's "O&" formatting helpers. */ diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c index f0ba125e768..7b51154f0d0 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.c +++ b/source/blender/python/mathutils/mathutils_Quaternion.c @@ -1035,7 +1035,7 @@ static PyObject *Quaternion_matmul(PyObject *q1, PyObject *q2) VectorObject *vec2 = (VectorObject *)q2; float tvec[3]; - if (vec2->size != 3) { + if (vec2->vec_num != 3) { PyErr_SetString(PyExc_ValueError, "Vector multiplication: " "only 3D vector rotations (with quats) " diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index 080a1e7fbdd..ffeb121b3d1 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -45,7 +45,7 @@ static int row_vector_multiplication(float r_vec[MAX_DIMENSIONS], static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { float *vec = NULL; - int size = 3; /* default to a 3D vector */ + int vec_num = 3; /* default to a 3D vector */ if (kwds && PyDict_Size(kwds)) { PyErr_SetString(PyExc_TypeError, @@ -56,7 +56,7 @@ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds) switch (PyTuple_GET_SIZE(args)) { case 0: - vec = PyMem_Malloc(size * sizeof(float)); + vec = PyMem_Malloc(vec_num * sizeof(float)); if (vec == NULL) { PyErr_SetString(PyExc_MemoryError, @@ -65,10 +65,10 @@ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } - copy_vn_fl(vec, size, 0.0f); + copy_vn_fl(vec, vec_num, 0.0f); break; case 1: - if ((size = mathutils_array_parse_alloc( + if ((vec_num = mathutils_array_parse_alloc( &vec, 2, PyTuple_GET_ITEM(args, 0), "mathutils.Vector()")) == -1) { return NULL; } @@ -79,7 +79,7 @@ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds) "more than a single arg given"); return NULL; } - return Vector_CreatePyObject_alloc(vec, size, type); + return Vector_CreatePyObject_alloc(vec, vec_num, type); } static PyObject *vec__apply_to_copy(PyObject *(*vec_func)(VectorObject *), VectorObject *self) @@ -108,19 +108,19 @@ PyDoc_STRVAR(C_Vector_Fill_doc, static PyObject *C_Vector_Fill(PyObject *cls, PyObject *args) { float *vec; - int size; + int vec_num; float fill = 0.0f; - if (!PyArg_ParseTuple(args, "i|f:Vector.Fill", &size, &fill)) { + if (!PyArg_ParseTuple(args, "i|f:Vector.Fill", &vec_num, &fill)) { return NULL; } - if (size < 2) { + if (vec_num < 2) { PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid size"); return NULL; } - vec = PyMem_Malloc(size * sizeof(float)); + vec = PyMem_Malloc(vec_num * sizeof(float)); if (vec == NULL) { PyErr_SetString(PyExc_MemoryError, @@ -129,9 +129,9 @@ static PyObject *C_Vector_Fill(PyObject *cls, PyObject *args) return NULL; } - copy_vn_fl(vec, size, fill); + copy_vn_fl(vec, vec_num, fill); - return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls); + return Vector_CreatePyObject_alloc(vec, vec_num, (PyTypeObject *)cls); } PyDoc_STRVAR(C_Vector_Range_doc, @@ -148,7 +148,7 @@ PyDoc_STRVAR(C_Vector_Range_doc, static PyObject *C_Vector_Range(PyObject *cls, PyObject *args) { float *vec; - int stop, size; + int stop, vec_num; int start = 0; int step = 1; @@ -158,7 +158,7 @@ static PyObject *C_Vector_Range(PyObject *cls, PyObject *args) switch (PyTuple_GET_SIZE(args)) { case 1: - size = start; + vec_num = start; start = 0; break; case 2: @@ -169,7 +169,7 @@ static PyObject *C_Vector_Range(PyObject *cls, PyObject *args) return NULL; } - size = stop - start; + vec_num = stop - start; break; default: if (start >= stop) { @@ -179,23 +179,23 @@ static PyObject *C_Vector_Range(PyObject *cls, PyObject *args) return NULL; } - size = (stop - start); + vec_num = (stop - start); - if ((size % step) != 0) { - size += step; + if ((vec_num % step) != 0) { + vec_num += step; } - size /= step; + vec_num /= step; break; } - if (size < 2) { + if (vec_num < 2) { PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid size"); return NULL; } - vec = PyMem_Malloc(size * sizeof(float)); + vec = PyMem_Malloc(vec_num * sizeof(float)); if (vec == NULL) { PyErr_SetString(PyExc_MemoryError, @@ -204,9 +204,9 @@ static PyObject *C_Vector_Range(PyObject *cls, PyObject *args) return NULL; } - range_vn_fl(vec, size, (float)start, (float)step); + range_vn_fl(vec, vec_num, (float)start, (float)step); - return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls); + return Vector_CreatePyObject_alloc(vec, vec_num, (PyTypeObject *)cls); } PyDoc_STRVAR(C_Vector_Linspace_doc, @@ -224,21 +224,21 @@ PyDoc_STRVAR(C_Vector_Linspace_doc, static PyObject *C_Vector_Linspace(PyObject *cls, PyObject *args) { float *vec; - int size; + int vec_num; float start, end, step; - if (!PyArg_ParseTuple(args, "ffi:Vector.Linspace", &start, &end, &size)) { + if (!PyArg_ParseTuple(args, "ffi:Vector.Linspace", &start, &end, &vec_num)) { return NULL; } - if (size < 2) { + if (vec_num < 2) { PyErr_SetString(PyExc_RuntimeError, "Vector.Linspace(): invalid size"); return NULL; } - step = (end - start) / (float)(size - 1); + step = (end - start) / (float)(vec_num - 1); - vec = PyMem_Malloc(size * sizeof(float)); + vec = PyMem_Malloc(vec_num * sizeof(float)); if (vec == NULL) { PyErr_SetString(PyExc_MemoryError, @@ -247,9 +247,9 @@ static PyObject *C_Vector_Linspace(PyObject *cls, PyObject *args) return NULL; } - range_vn_fl(vec, size, start, step); + range_vn_fl(vec, vec_num, start, step); - return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls); + return Vector_CreatePyObject_alloc(vec, vec_num, (PyTypeObject *)cls); } PyDoc_STRVAR( @@ -266,20 +266,20 @@ static PyObject *C_Vector_Repeat(PyObject *cls, PyObject *args) { float *vec; float *iter_vec = NULL; - int i, size, value_size; + int i, vec_num, value_num; PyObject *value; - if (!PyArg_ParseTuple(args, "Oi:Vector.Repeat", &value, &size)) { + if (!PyArg_ParseTuple(args, "Oi:Vector.Repeat", &value, &vec_num)) { return NULL; } - if (size < 2) { - PyErr_SetString(PyExc_RuntimeError, "Vector.Repeat(): invalid size"); + if (vec_num < 2) { + PyErr_SetString(PyExc_RuntimeError, "Vector.Repeat(): invalid vec_num"); return NULL; } - if ((value_size = mathutils_array_parse_alloc( - &iter_vec, 2, value, "Vector.Repeat(vector, size), invalid 'vector' arg")) == -1) { + if ((value_num = mathutils_array_parse_alloc( + &iter_vec, 2, value, "Vector.Repeat(vector, vec_num), invalid 'vector' arg")) == -1) { return NULL; } @@ -290,7 +290,7 @@ static PyObject *C_Vector_Repeat(PyObject *cls, PyObject *args) return NULL; } - vec = PyMem_Malloc(size * sizeof(float)); + vec = PyMem_Malloc(vec_num * sizeof(float)); if (vec == NULL) { PyMem_Free(iter_vec); @@ -301,14 +301,14 @@ static PyObject *C_Vector_Repeat(PyObject *cls, PyObject *args) } i = 0; - while (i < size) { - vec[i] = iter_vec[i % value_size]; + while (i < vec_num) { + vec[i] = iter_vec[i % value_num]; i++; } PyMem_Free(iter_vec); - return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls); + return Vector_CreatePyObject_alloc(vec, vec_num, (PyTypeObject *)cls); } /*-----------------------------METHODS---------------------------- */ @@ -322,7 +322,7 @@ static PyObject *Vector_zero(VectorObject *self) return NULL; } - copy_vn_fl(self->vec, self->size, 0.0f); + copy_vn_fl(self->vec, self->vec_num, 0.0f); if (BaseMath_WriteCallback(self) == -1) { return NULL; @@ -342,12 +342,12 @@ PyDoc_STRVAR(Vector_normalize_doc, " however 4D Vectors w axis is left untouched.\n"); static PyObject *Vector_normalize(VectorObject *self) { - const int size = (self->size == 4 ? 3 : self->size); + const int vec_num = (self->vec_num == 4 ? 3 : self->vec_num); if (BaseMath_ReadCallback_ForWrite(self) == -1) { return NULL; } - normalize_vn(self->vec, size); + normalize_vn(self->vec, vec_num); (void)BaseMath_WriteCallback(self); Py_RETURN_NONE; @@ -370,7 +370,7 @@ PyDoc_STRVAR(Vector_resize_doc, " Resize the vector to have size number of elements.\n"); static PyObject *Vector_resize(VectorObject *self, PyObject *value) { - int size; + int vec_num; if (self->flag & BASE_MATH_FLAG_IS_WRAP) { PyErr_SetString(PyExc_TypeError, @@ -385,19 +385,19 @@ static PyObject *Vector_resize(VectorObject *self, PyObject *value) return NULL; } - if ((size = PyC_Long_AsI32(value)) == -1) { + if ((vec_num = PyC_Long_AsI32(value)) == -1) { PyErr_SetString(PyExc_TypeError, "Vector.resize(size): " "expected size argument to be an integer"); return NULL; } - if (size < 2) { + if (vec_num < 2) { PyErr_SetString(PyExc_RuntimeError, "Vector.resize(): invalid size"); return NULL; } - self->vec = PyMem_Realloc(self->vec, (size * sizeof(float))); + self->vec = PyMem_Realloc(self->vec, (vec_num * sizeof(float))); if (self->vec == NULL) { PyErr_SetString(PyExc_MemoryError, "Vector.resize(): " @@ -406,11 +406,11 @@ static PyObject *Vector_resize(VectorObject *self, PyObject *value) } /* If the vector has increased in length, set all new elements to 0.0f */ - if (size > self->size) { - copy_vn_fl(self->vec + self->size, size - self->size, 0.0f); + if (vec_num > self->vec_num) { + copy_vn_fl(self->vec + self->vec_num, vec_num - self->vec_num, 0.0f); } - self->size = size; + self->vec_num = vec_num; Py_RETURN_NONE; } @@ -423,19 +423,19 @@ PyDoc_STRVAR(Vector_resized_doc, " :rtype: :class:`Vector`\n"); static PyObject *Vector_resized(VectorObject *self, PyObject *value) { - int size; + int vec_num; float *vec; - if ((size = PyLong_AsLong(value)) == -1) { + if ((vec_num = PyLong_AsLong(value)) == -1) { return NULL; } - if (size < 2) { + if (vec_num < 2) { PyErr_SetString(PyExc_RuntimeError, "Vector.resized(): invalid size"); return NULL; } - vec = PyMem_Malloc(size * sizeof(float)); + vec = PyMem_Malloc(vec_num * sizeof(float)); if (vec == NULL) { PyErr_SetString(PyExc_MemoryError, @@ -444,10 +444,10 @@ static PyObject *Vector_resized(VectorObject *self, PyObject *value) return NULL; } - copy_vn_fl(vec, size, 0.0f); - memcpy(vec, self->vec, self->size * sizeof(float)); + copy_vn_fl(vec, vec_num, 0.0f); + memcpy(vec, self->vec, self->vec_num * sizeof(float)); - return Vector_CreatePyObject_alloc(vec, size, NULL); + return Vector_CreatePyObject_alloc(vec, vec_num, NULL); } PyDoc_STRVAR(Vector_resize_2d_doc, @@ -477,7 +477,7 @@ static PyObject *Vector_resize_2d(VectorObject *self) return NULL; } - self->size = 2; + self->vec_num = 2; Py_RETURN_NONE; } @@ -508,11 +508,11 @@ static PyObject *Vector_resize_3d(VectorObject *self) return NULL; } - if (self->size == 2) { + if (self->vec_num == 2) { self->vec[2] = 0.0f; } - self->size = 3; + self->vec_num = 3; Py_RETURN_NONE; } @@ -543,14 +543,14 @@ static PyObject *Vector_resize_4d(VectorObject *self) return NULL; } - if (self->size == 2) { + if (self->vec_num == 2) { self->vec[2] = 0.0f; self->vec[3] = 1.0f; } - else if (self->size == 3) { + else if (self->vec_num == 3) { self->vec[3] = 1.0f; } - self->size = 4; + self->vec_num = 4; Py_RETURN_NONE; } PyDoc_STRVAR(Vector_to_2d_doc, @@ -583,7 +583,7 @@ static PyObject *Vector_to_3d(VectorObject *self) return NULL; } - memcpy(tvec, self->vec, sizeof(float) * MIN2(self->size, 3)); + memcpy(tvec, self->vec, sizeof(float) * MIN2(self->vec_num, 3)); return Vector_CreatePyObject(tvec, 3, Py_TYPE(self)); } PyDoc_STRVAR(Vector_to_4d_doc, @@ -601,7 +601,7 @@ static PyObject *Vector_to_4d(VectorObject *self) return NULL; } - memcpy(tvec, self->vec, sizeof(float) * MIN2(self->size, 4)); + memcpy(tvec, self->vec, sizeof(float) * MIN2(self->vec_num, 4)); return Vector_CreatePyObject(tvec, 4, Py_TYPE(self)); } @@ -620,15 +620,15 @@ static PyObject *Vector_to_tuple_ex(VectorObject *self, int ndigits) PyObject *ret; int i; - ret = PyTuple_New(self->size); + ret = PyTuple_New(self->vec_num); if (ndigits >= 0) { - for (i = 0; i < self->size; i++) { + for (i = 0; i < self->vec_num; i++) { PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->vec[i], ndigits))); } } else { - for (i = 0; i < self->size; i++) { + for (i = 0; i < self->vec_num; i++) { PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->vec[i])); } } @@ -684,7 +684,7 @@ static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args) return NULL; } - if (self->size != 3) { + if (self->vec_num != 3) { PyErr_SetString(PyExc_TypeError, "Vector.to_track_quat(): " "only for 3D vectors"); @@ -795,7 +795,7 @@ static PyObject *Vector_orthogonal(VectorObject *self) { float vec[3]; - if (self->size > 3) { + if (self->vec_num > 3) { PyErr_SetString(PyExc_TypeError, "Vector.orthogonal(): " "Vector must be 3D or 2D"); @@ -806,14 +806,14 @@ static PyObject *Vector_orthogonal(VectorObject *self) return NULL; } - if (self->size == 3) { + if (self->vec_num == 3) { ortho_v3_v3(vec, self->vec); } else { ortho_v2_v2(vec, self->vec); } - return Vector_CreatePyObject(vec, self->size, Py_TYPE(self)); + return Vector_CreatePyObject(vec, self->vec_num, Py_TYPE(self)); } /** @@ -833,7 +833,7 @@ PyDoc_STRVAR(Vector_reflect_doc, " :rtype: :class:`Vector`\n"); static PyObject *Vector_reflect(VectorObject *self, PyObject *value) { - int value_size; + int value_num; float mirror[3], vec[3]; float reflect[3] = {0.0f}; float tvec[MAX_DIMENSIONS]; @@ -842,28 +842,28 @@ static PyObject *Vector_reflect(VectorObject *self, PyObject *value) return NULL; } - if ((value_size = mathutils_array_parse( + if ((value_num = mathutils_array_parse( tvec, 2, 4, value, "Vector.reflect(other), invalid 'other' arg")) == -1) { return NULL; } - if (self->size < 2 || self->size > 4) { + if (self->vec_num < 2 || self->vec_num > 4) { PyErr_SetString(PyExc_ValueError, "Vector must be 2D, 3D or 4D"); return NULL; } mirror[0] = tvec[0]; mirror[1] = tvec[1]; - mirror[2] = (value_size > 2) ? tvec[2] : 0.0f; + mirror[2] = (value_num > 2) ? tvec[2] : 0.0f; vec[0] = self->vec[0]; vec[1] = self->vec[1]; - vec[2] = (value_size > 2) ? self->vec[2] : 0.0f; + vec[2] = (value_num > 2) ? self->vec[2] : 0.0f; normalize_v3(mirror); reflect_v3_v3v3(reflect, vec, mirror); - return Vector_CreatePyObject(reflect, self->size, Py_TYPE(self)); + return Vector_CreatePyObject(reflect, self->vec_num, Py_TYPE(self)); } PyDoc_STRVAR(Vector_cross_doc, @@ -886,17 +886,18 @@ static PyObject *Vector_cross(VectorObject *self, PyObject *value) return NULL; } - if (self->size > 3) { + if (self->vec_num > 3) { PyErr_SetString(PyExc_ValueError, "Vector must be 2D or 3D"); return NULL; } if (mathutils_array_parse( - tvec, self->size, self->size, value, "Vector.cross(other), invalid 'other' arg") == -1) { + tvec, self->vec_num, self->vec_num, value, "Vector.cross(other), invalid 'other' arg") == + -1) { return NULL; } - if (self->size == 3) { + if (self->vec_num == 3) { ret = Vector_CreatePyObject(NULL, 3, Py_TYPE(self)); cross_v3_v3v3(((VectorObject *)ret)->vec, self->vec, tvec); } @@ -926,11 +927,11 @@ static PyObject *Vector_dot(VectorObject *self, PyObject *value) } if (mathutils_array_parse_alloc( - &tvec, self->size, value, "Vector.dot(other), invalid 'other' arg") == -1) { + &tvec, self->vec_num, value, "Vector.dot(other), invalid 'other' arg") == -1) { return NULL; } - ret = PyFloat_FromDouble(dot_vn_vn(self->vec, tvec, self->size)); + ret = PyFloat_FromDouble(dot_vn_vn(self->vec, tvec, self->vec_num)); PyMem_Free(tvec); return ret; } @@ -950,7 +951,7 @@ PyDoc_STRVAR( " :rtype: float\n"); static PyObject *Vector_angle(VectorObject *self, PyObject *args) { - const int size = MIN2(self->size, 3); /* 4D angle makes no sense */ + const int vec_num = MIN2(self->vec_num, 3); /* 4D angle makes no sense */ float tvec[MAX_DIMENSIONS]; PyObject *value; double dot = 0.0f, dot_self = 0.0f, dot_other = 0.0f; @@ -968,16 +969,17 @@ static PyObject *Vector_angle(VectorObject *self, PyObject *args) /* don't use clamped size, rule of thumb is vector sizes must match, * even though n this case 'w' is ignored */ if (mathutils_array_parse( - tvec, self->size, self->size, value, "Vector.angle(other), invalid 'other' arg") == -1) { + tvec, self->vec_num, self->vec_num, value, "Vector.angle(other), invalid 'other' arg") == + -1) { return NULL; } - if (self->size > 4) { + if (self->vec_num > 4) { PyErr_SetString(PyExc_ValueError, "Vector must be 2D, 3D or 4D"); return NULL; } - for (x = 0; x < size; x++) { + for (x = 0; x < vec_num; x++) { dot_self += (double)self->vec[x] * (double)self->vec[x]; dot_other += (double)tvec[x] * (double)tvec[x]; dot += (double)self->vec[x] * (double)tvec[x]; @@ -1032,7 +1034,7 @@ static PyObject *Vector_angle_signed(VectorObject *self, PyObject *args) return NULL; } - if (self->size != 2) { + if (self->vec_num != 2) { PyErr_SetString(PyExc_ValueError, "Vector must be 2D"); return NULL; } @@ -1069,7 +1071,7 @@ static PyObject *Vector_rotation_difference(VectorObject *self, PyObject *value) { float quat[4], vec_a[3], vec_b[3]; - if (self->size < 3 || self->size > 4) { + if (self->vec_num < 3 || self->vec_num > 4) { PyErr_SetString(PyExc_ValueError, "vec.difference(value): " "expects both vectors to be size 3 or 4"); @@ -1105,7 +1107,7 @@ PyDoc_STRVAR(Vector_project_doc, " :rtype: :class:`Vector`\n"); static PyObject *Vector_project(VectorObject *self, PyObject *value) { - const int size = self->size; + const int vec_num = self->vec_num; float *tvec; double dot = 0.0f, dot2 = 0.0f; int x; @@ -1115,21 +1117,21 @@ static PyObject *Vector_project(VectorObject *self, PyObject *value) } if (mathutils_array_parse_alloc( - &tvec, size, value, "Vector.project(other), invalid 'other' arg") == -1) { + &tvec, vec_num, value, "Vector.project(other), invalid 'other' arg") == -1) { return NULL; } /* get dot products */ - for (x = 0; x < size; x++) { + for (x = 0; x < vec_num; x++) { dot += (double)(self->vec[x] * tvec[x]); dot2 += (double)(tvec[x] * tvec[x]); } /* projection */ dot /= dot2; - for (x = 0; x < size; x++) { + for (x = 0; x < vec_num; x++) { tvec[x] *= (float)dot; } - return Vector_CreatePyObject_alloc(tvec, size, Py_TYPE(self)); + return Vector_CreatePyObject_alloc(tvec, vec_num, Py_TYPE(self)); } PyDoc_STRVAR(Vector_lerp_doc, @@ -1145,7 +1147,7 @@ PyDoc_STRVAR(Vector_lerp_doc, " :rtype: :class:`Vector`\n"); static PyObject *Vector_lerp(VectorObject *self, PyObject *args) { - const int size = self->size; + const int vec_num = self->vec_num; PyObject *value = NULL; float fac; float *tvec; @@ -1158,14 +1160,14 @@ static PyObject *Vector_lerp(VectorObject *self, PyObject *args) return NULL; } - if (mathutils_array_parse_alloc(&tvec, size, value, "Vector.lerp(other), invalid 'other' arg") == - -1) { + if (mathutils_array_parse_alloc( + &tvec, vec_num, value, "Vector.lerp(other), invalid 'other' arg") == -1) { return NULL; } - interp_vn_vn(tvec, self->vec, 1.0f - fac, size); + interp_vn_vn(tvec, self->vec, 1.0f - fac, vec_num); - return Vector_CreatePyObject_alloc(tvec, size, Py_TYPE(self)); + return Vector_CreatePyObject_alloc(tvec, vec_num, Py_TYPE(self)); } PyDoc_STRVAR(Vector_slerp_doc, @@ -1185,7 +1187,7 @@ PyDoc_STRVAR(Vector_slerp_doc, " :rtype: :class:`Vector`\n"); static PyObject *Vector_slerp(VectorObject *self, PyObject *args) { - const int size = self->size; + const int vec_num = self->vec_num; PyObject *value = NULL; float fac, cosom, w[2]; float self_vec[3], other_vec[3], ret_vec[3]; @@ -1201,18 +1203,18 @@ static PyObject *Vector_slerp(VectorObject *self, PyObject *args) return NULL; } - if (self->size > 3) { + if (self->vec_num > 3) { PyErr_SetString(PyExc_ValueError, "Vector must be 2D or 3D"); return NULL; } if (mathutils_array_parse( - other_vec, size, size, value, "Vector.slerp(other), invalid 'other' arg") == -1) { + other_vec, vec_num, vec_num, value, "Vector.slerp(other), invalid 'other' arg") == -1) { return NULL; } - self_len_sq = normalize_vn_vn(self_vec, self->vec, size); - other_len_sq = normalize_vn(other_vec, size); + self_len_sq = normalize_vn_vn(self_vec, self->vec, vec_num); + other_len_sq = normalize_vn(other_vec, vec_num); /* use fallbacks for zero length vectors */ if (UNLIKELY((self_len_sq < FLT_EPSILON) || (other_len_sq < FLT_EPSILON))) { @@ -1229,7 +1231,7 @@ static PyObject *Vector_slerp(VectorObject *self, PyObject *args) } /* We have sane state, execute slerp */ - cosom = (float)dot_vn_vn(self_vec, other_vec, size); + cosom = (float)dot_vn_vn(self_vec, other_vec, vec_num); /* direct opposite, can't slerp */ if (UNLIKELY(cosom < (-1.0f + FLT_EPSILON))) { @@ -1247,11 +1249,11 @@ static PyObject *Vector_slerp(VectorObject *self, PyObject *args) interp_dot_slerp(fac, cosom, w); - for (x = 0; x < size; x++) { + for (x = 0; x < vec_num; x++) { ret_vec[x] = (w[0] * self_vec[x]) + (w[1] * other_vec[x]); } - return Vector_CreatePyObject(ret_vec, size, Py_TYPE(self)); + return Vector_CreatePyObject(ret_vec, vec_num, Py_TYPE(self)); } PyDoc_STRVAR( @@ -1270,7 +1272,7 @@ static PyObject *Vector_rotate(VectorObject *self, PyObject *value) return NULL; } - if (self->size == 2) { + if (self->vec_num == 2) { /* Special case for 2D Vector with 2x2 matrix, so we avoid resizing it to a 3x3. */ float other_rmat[2][2]; MatrixObject *pymat; @@ -1311,7 +1313,7 @@ static PyObject *Vector_copy(VectorObject *self) return NULL; } - return Vector_CreatePyObject(self->vec, self->size, Py_TYPE(self)); + return Vector_CreatePyObject(self->vec, self->vec_num, Py_TYPE(self)); } static PyObject *Vector_deepcopy(VectorObject *self, PyObject *args) { @@ -1350,7 +1352,7 @@ static PyObject *Vector_str(VectorObject *self) BLI_dynstr_append(ds, "<Vector ("); - for (i = 0; i < self->size; i++) { + for (i = 0; i < self->vec_num; i++) { BLI_dynstr_appendf(ds, i ? ", %.4f" : "%.4f", self->vec[i]); } @@ -1364,21 +1366,21 @@ static PyObject *Vector_str(VectorObject *self) /* sequence length len(vector) */ static int Vector_len(VectorObject *self) { - return self->size; + return self->vec_num; } /* sequence accessor (get): vector[index] */ static PyObject *vector_item_internal(VectorObject *self, int i, const bool is_attr) { if (i < 0) { - i = self->size - i; + i = self->vec_num - i; } - if (i < 0 || i >= self->size) { + if (i < 0 || i >= self->vec_num) { if (is_attr) { PyErr_Format(PyExc_AttributeError, "Vector.%c: unavailable on %dd vector", *(((const char *)"xyzw") + i), - self->size); + self->vec_num); } else { PyErr_SetString(PyExc_IndexError, "vector[index]: out of range"); @@ -1415,15 +1417,15 @@ static int vector_ass_item_internal(VectorObject *self, int i, PyObject *value, } if (i < 0) { - i = self->size - i; + i = self->vec_num - i; } - if (i < 0 || i >= self->size) { + if (i < 0 || i >= self->vec_num) { if (is_attr) { PyErr_Format(PyExc_AttributeError, "Vector.%c = x: unavailable on %dd vector", *(((const char *)"xyzw") + i), - self->size); + self->vec_num); } else { PyErr_SetString(PyExc_IndexError, @@ -1455,11 +1457,11 @@ static PyObject *Vector_slice(VectorObject *self, int begin, int end) return NULL; } - CLAMP(begin, 0, self->size); + CLAMP(begin, 0, self->vec_num); if (end < 0) { - end = self->size + end + 1; + end = self->vec_num + end + 1; } - CLAMP(end, 0, self->size); + CLAMP(end, 0, self->vec_num); begin = MIN2(begin, end); tuple = PyTuple_New(end - begin); @@ -1472,19 +1474,19 @@ static PyObject *Vector_slice(VectorObject *self, int begin, int end) /* sequence slice (set): vector[a:b] = value */ static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *seq) { - int size = 0; + int vec_num = 0; float *vec = NULL; if (BaseMath_ReadCallback_ForWrite(self) == -1) { return -1; } - CLAMP(begin, 0, self->size); - CLAMP(end, 0, self->size); + CLAMP(begin, 0, self->vec_num); + CLAMP(end, 0, self->vec_num); begin = MIN2(begin, end); - size = (end - begin); - if (mathutils_array_parse_alloc(&vec, size, seq, "vector[begin:end] = [...]") == -1) { + vec_num = (end - begin); + if (mathutils_array_parse_alloc(&vec, vec_num, seq, "vector[begin:end] = [...]") == -1) { return -1; } @@ -1496,7 +1498,7 @@ static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *se } /* Parsed well - now set in vector. */ - memcpy(self->vec + begin, vec, size * sizeof(float)); + memcpy(self->vec + begin, vec, vec_num * sizeof(float)); PyMem_Free(vec); @@ -1530,14 +1532,14 @@ static PyObject *Vector_add(PyObject *v1, PyObject *v2) } /* VECTOR + VECTOR. */ - if (vec1->size != vec2->size) { + if (vec1->vec_num != vec2->vec_num) { PyErr_SetString(PyExc_AttributeError, "Vector addition: " "vectors must have the same dimensions for this operation"); return NULL; } - vec = PyMem_Malloc(vec1->size * sizeof(float)); + vec = PyMem_Malloc(vec1->vec_num * sizeof(float)); if (vec == NULL) { PyErr_SetString(PyExc_MemoryError, "Vector(): " @@ -1545,9 +1547,9 @@ static PyObject *Vector_add(PyObject *v1, PyObject *v2) return NULL; } - add_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size); + add_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->vec_num); - return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1)); + return Vector_CreatePyObject_alloc(vec, vec1->vec_num, Py_TYPE(v1)); } /* addition in-place: obj += obj */ @@ -1566,7 +1568,7 @@ static PyObject *Vector_iadd(PyObject *v1, PyObject *v2) vec1 = (VectorObject *)v1; vec2 = (VectorObject *)v2; - if (vec1->size != vec2->size) { + if (vec1->vec_num != vec2->vec_num) { PyErr_SetString(PyExc_AttributeError, "Vector addition: " "vectors must have the same dimensions for this operation"); @@ -1577,7 +1579,7 @@ static PyObject *Vector_iadd(PyObject *v1, PyObject *v2) return NULL; } - add_vn_vn(vec1->vec, vec2->vec, vec1->size); + add_vn_vn(vec1->vec, vec2->vec, vec1->vec_num); (void)BaseMath_WriteCallback(vec1); Py_INCREF(v1); @@ -1605,14 +1607,14 @@ static PyObject *Vector_sub(PyObject *v1, PyObject *v2) return NULL; } - if (vec1->size != vec2->size) { + if (vec1->vec_num != vec2->vec_num) { PyErr_SetString(PyExc_AttributeError, "Vector subtraction: " "vectors must have the same dimensions for this operation"); return NULL; } - vec = PyMem_Malloc(vec1->size * sizeof(float)); + vec = PyMem_Malloc(vec1->vec_num * sizeof(float)); if (vec == NULL) { PyErr_SetString(PyExc_MemoryError, "Vector(): " @@ -1620,9 +1622,9 @@ static PyObject *Vector_sub(PyObject *v1, PyObject *v2) return NULL; } - sub_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size); + sub_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->vec_num); - return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1)); + return Vector_CreatePyObject_alloc(vec, vec1->vec_num, Py_TYPE(v1)); } /* subtraction in-place: obj -= obj */ @@ -1641,7 +1643,7 @@ static PyObject *Vector_isub(PyObject *v1, PyObject *v2) vec1 = (VectorObject *)v1; vec2 = (VectorObject *)v2; - if (vec1->size != vec2->size) { + if (vec1->vec_num != vec2->vec_num) { PyErr_SetString(PyExc_AttributeError, "Vector subtraction: " "vectors must have the same dimensions for this operation"); @@ -1652,7 +1654,7 @@ static PyObject *Vector_isub(PyObject *v1, PyObject *v2) return NULL; } - sub_vn_vn(vec1->vec, vec2->vec, vec1->size); + sub_vn_vn(vec1->vec, vec2->vec, vec1->vec_num); (void)BaseMath_WriteCallback(vec1); Py_INCREF(v1); @@ -1667,8 +1669,8 @@ int column_vector_multiplication(float r_vec[MAX_DIMENSIONS], VectorObject *vec, float vec_cpy[MAX_DIMENSIONS]; int row, col, z = 0; - if (mat->num_col != vec->size) { - if (mat->num_col == 4 && vec->size == 3) { + if (mat->col_num != vec->vec_num) { + if (mat->col_num == 4 && vec->vec_num == 3) { vec_cpy[3] = 1.0f; } else { @@ -1680,13 +1682,13 @@ int column_vector_multiplication(float r_vec[MAX_DIMENSIONS], VectorObject *vec, } } - memcpy(vec_cpy, vec->vec, vec->size * sizeof(float)); + memcpy(vec_cpy, vec->vec, vec->vec_num * sizeof(float)); r_vec[3] = 1.0f; - for (row = 0; row < mat->num_row; row++) { + for (row = 0; row < mat->row_num; row++) { double dot = 0.0f; - for (col = 0; col < mat->num_col; col++) { + for (col = 0; col < mat->col_num; col++) { dot += (double)(MATRIX_ITEM(mat, row, col) * vec_cpy[col]); } r_vec[z++] = (float)dot; @@ -1697,7 +1699,7 @@ int column_vector_multiplication(float r_vec[MAX_DIMENSIONS], VectorObject *vec, static PyObject *vector_mul_float(VectorObject *vec, const float scalar) { - float *tvec = PyMem_Malloc(vec->size * sizeof(float)); + float *tvec = PyMem_Malloc(vec->vec_num * sizeof(float)); if (tvec == NULL) { PyErr_SetString(PyExc_MemoryError, "vec * float: " @@ -1705,13 +1707,13 @@ static PyObject *vector_mul_float(VectorObject *vec, const float scalar) return NULL; } - mul_vn_vn_fl(tvec, vec->vec, vec->size, scalar); - return Vector_CreatePyObject_alloc(tvec, vec->size, Py_TYPE(vec)); + mul_vn_vn_fl(tvec, vec->vec, vec->vec_num, scalar); + return Vector_CreatePyObject_alloc(tvec, vec->vec_num, Py_TYPE(vec)); } static PyObject *vector_mul_vec(VectorObject *vec1, VectorObject *vec2) { - float *tvec = PyMem_Malloc(vec1->size * sizeof(float)); + float *tvec = PyMem_Malloc(vec1->vec_num * sizeof(float)); if (tvec == NULL) { PyErr_SetString(PyExc_MemoryError, "vec * vec: " @@ -1719,8 +1721,8 @@ static PyObject *vector_mul_vec(VectorObject *vec1, VectorObject *vec2) return NULL; } - mul_vn_vnvn(tvec, vec1->vec, vec2->vec, vec1->size); - return Vector_CreatePyObject_alloc(tvec, vec1->size, Py_TYPE(vec1)); + mul_vn_vnvn(tvec, vec1->vec, vec2->vec, vec1->vec_num); + return Vector_CreatePyObject_alloc(tvec, vec1->vec_num, Py_TYPE(vec1)); } static PyObject *Vector_mul(PyObject *v1, PyObject *v2) @@ -1745,7 +1747,7 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2) /* make sure v1 is always the vector */ if (vec1 && vec2) { - if (vec1->size != vec2->size) { + if (vec1->vec_num != vec2->vec_num) { PyErr_SetString(PyExc_ValueError, "Vector multiplication: " "vectors must have the same dimensions for this operation"); @@ -1800,7 +1802,7 @@ static PyObject *Vector_imul(PyObject *v1, PyObject *v2) /* Intentionally don't support (Quaternion, Matrix) here, uses reverse order instead. */ if (vec1 && vec2) { - if (vec1->size != vec2->size) { + if (vec1->vec_num != vec2->vec_num) { PyErr_SetString(PyExc_ValueError, "Vector multiplication: " "vectors must have the same dimensions for this operation"); @@ -1808,11 +1810,11 @@ static PyObject *Vector_imul(PyObject *v1, PyObject *v2) } /* Element-wise product in-place. */ - mul_vn_vn(vec1->vec, vec2->vec, vec1->size); + mul_vn_vn(vec1->vec, vec2->vec, vec1->vec_num); } else if (vec1 && (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0)) { /* VEC *= FLOAT */ - mul_vn_fl(vec1->vec, vec1->size, scalar); + mul_vn_fl(vec1->vec, vec1->vec_num, scalar); } else { PyErr_Format(PyExc_TypeError, @@ -1831,7 +1833,7 @@ static PyObject *Vector_imul(PyObject *v1, PyObject *v2) static PyObject *Vector_matmul(PyObject *v1, PyObject *v2) { VectorObject *vec1 = NULL, *vec2 = NULL; - int vec_size; + int vec_num; if (VectorObject_Check(v1)) { vec1 = (VectorObject *)v1; @@ -1850,7 +1852,7 @@ static PyObject *Vector_matmul(PyObject *v1, PyObject *v2) /* make sure v1 is always the vector */ if (vec1 && vec2) { - if (vec1->size != vec2->size) { + if (vec1->vec_num != vec2->vec_num) { PyErr_SetString(PyExc_ValueError, "Vector multiplication: " "vectors must have the same dimensions for this operation"); @@ -1858,7 +1860,7 @@ static PyObject *Vector_matmul(PyObject *v1, PyObject *v2) } /* Dot product. */ - return PyFloat_FromDouble(dot_vn_vn(vec1->vec, vec2->vec, vec1->size)); + return PyFloat_FromDouble(dot_vn_vn(vec1->vec, vec2->vec, vec1->vec_num)); } if (vec1) { if (MatrixObject_Check(v2)) { @@ -1872,14 +1874,14 @@ static PyObject *Vector_matmul(PyObject *v1, PyObject *v2) return NULL; } - if (((MatrixObject *)v2)->num_row == 4 && vec1->size == 3) { - vec_size = 3; + if (((MatrixObject *)v2)->row_num == 4 && vec1->vec_num == 3) { + vec_num = 3; } else { - vec_size = ((MatrixObject *)v2)->num_col; + vec_num = ((MatrixObject *)v2)->col_num; } - return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(vec1)); + return Vector_CreatePyObject(tvec, vec_num, Py_TYPE(vec1)); } } @@ -1934,7 +1936,7 @@ static PyObject *Vector_div(PyObject *v1, PyObject *v2) return NULL; } - vec = PyMem_Malloc(vec1->size * sizeof(float)); + vec = PyMem_Malloc(vec1->vec_num * sizeof(float)); if (vec == NULL) { PyErr_SetString(PyExc_MemoryError, @@ -1943,9 +1945,9 @@ static PyObject *Vector_div(PyObject *v1, PyObject *v2) return NULL; } - mul_vn_vn_fl(vec, vec1->vec, vec1->size, 1.0f / scalar); + mul_vn_vn_fl(vec, vec1->vec, vec1->vec_num, 1.0f / scalar); - return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1)); + return Vector_CreatePyObject_alloc(vec, vec1->vec_num, Py_TYPE(v1)); } /* divide in-place: obj /= obj */ @@ -1973,7 +1975,7 @@ static PyObject *Vector_idiv(PyObject *v1, PyObject *v2) return NULL; } - mul_vn_fl(vec1->vec, vec1->size, 1.0f / scalar); + mul_vn_fl(vec1->vec, vec1->vec_num, 1.0f / scalar); (void)BaseMath_WriteCallback(vec1); @@ -1991,9 +1993,9 @@ static PyObject *Vector_neg(VectorObject *self) return NULL; } - tvec = PyMem_Malloc(self->size * sizeof(float)); - negate_vn_vn(tvec, self->vec, self->size); - return Vector_CreatePyObject_alloc(tvec, self->size, Py_TYPE(self)); + tvec = PyMem_Malloc(self->vec_num * sizeof(float)); + negate_vn_vn(tvec, self->vec, self->vec_num); + return Vector_CreatePyObject_alloc(tvec, self->vec_num, Py_TYPE(self)); } /*------------------------tp_richcmpr @@ -2019,7 +2021,7 @@ static PyObject *Vector_richcmpr(PyObject *objectA, PyObject *objectB, int compa return NULL; } - if (vecA->size != vecB->size) { + if (vecA->vec_num != vecB->vec_num) { if (comparison_type == Py_NE) { Py_RETURN_TRUE; } @@ -2029,15 +2031,15 @@ static PyObject *Vector_richcmpr(PyObject *objectA, PyObject *objectB, int compa switch (comparison_type) { case Py_LT: - lenA = len_squared_vn(vecA->vec, vecA->size); - lenB = len_squared_vn(vecB->vec, vecB->size); + lenA = len_squared_vn(vecA->vec, vecA->vec_num); + lenB = len_squared_vn(vecB->vec, vecB->vec_num); if (lenA < lenB) { result = 1; } break; case Py_LE: - lenA = len_squared_vn(vecA->vec, vecA->size); - lenB = len_squared_vn(vecB->vec, vecB->size); + lenA = len_squared_vn(vecA->vec, vecA->vec_num); + lenB = len_squared_vn(vecB->vec, vecB->vec_num); if (lenA < lenB) { result = 1; } @@ -2046,21 +2048,21 @@ static PyObject *Vector_richcmpr(PyObject *objectA, PyObject *objectB, int compa } break; case Py_EQ: - result = EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->size, 1); + result = EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->vec_num, 1); break; case Py_NE: - result = !EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->size, 1); + result = !EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->vec_num, 1); break; case Py_GT: - lenA = len_squared_vn(vecA->vec, vecA->size); - lenB = len_squared_vn(vecB->vec, vecB->size); + lenA = len_squared_vn(vecA->vec, vecA->vec_num); + lenB = len_squared_vn(vecB->vec, vecB->vec_num); if (lenA > lenB) { result = 1; } break; case Py_GE: - lenA = len_squared_vn(vecA->vec, vecA->size); - lenB = len_squared_vn(vecB->vec, vecB->size); + lenA = len_squared_vn(vecA->vec, vecA->vec_num); + lenB = len_squared_vn(vecB->vec, vecB->vec_num); if (lenA > lenB) { result = 1; } @@ -2089,7 +2091,7 @@ static Py_hash_t Vector_hash(VectorObject *self) return -1; } - return mathutils_array_hash(self->vec, self->size); + return mathutils_array_hash(self->vec, self->vec_num); } /*-----------------PROTCOL DECLARATIONS--------------------------*/ @@ -2115,14 +2117,14 @@ static PyObject *Vector_subscript(VectorObject *self, PyObject *item) return NULL; } if (i < 0) { - i += self->size; + i += self->vec_num; } return Vector_item(self, i); } if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx(item, self->size, &start, &stop, &step, &slicelength) < 0) { + if (PySlice_GetIndicesEx(item, self->vec_num, &start, &stop, &step, &slicelength) < 0) { return NULL; } @@ -2150,14 +2152,14 @@ static int Vector_ass_subscript(VectorObject *self, PyObject *item, PyObject *va return -1; } if (i < 0) { - i += self->size; + i += self->vec_num; } return Vector_ass_item(self, i, value); } if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx(item, self->size, &start, &stop, &step, &slicelength) < 0) { + if (PySlice_GetIndicesEx(item, self->vec_num, &start, &stop, &step, &slicelength) < 0) { return -1; } @@ -2247,7 +2249,7 @@ static PyObject *Vector_length_get(VectorObject *self, void *UNUSED(closure)) return NULL; } - return PyFloat_FromDouble(sqrt(dot_vn_vn(self->vec, self->vec, self->size))); + return PyFloat_FromDouble(sqrt(dot_vn_vn(self->vec, self->vec, self->vec_num))); } static int Vector_length_set(VectorObject *self, PyObject *value) @@ -2268,11 +2270,11 @@ static int Vector_length_set(VectorObject *self, PyObject *value) return -1; } if (param == 0.0) { - copy_vn_fl(self->vec, self->size, 0.0f); + copy_vn_fl(self->vec, self->vec_num, 0.0f); return 0; } - dot = dot_vn_vn(self->vec, self->vec, self->size); + dot = dot_vn_vn(self->vec, self->vec, self->vec_num); if (!dot) { /* can't sqrt zero */ @@ -2287,7 +2289,7 @@ static int Vector_length_set(VectorObject *self, PyObject *value) dot = dot / param; - mul_vn_fl(self->vec, self->size, 1.0 / dot); + mul_vn_fl(self->vec, self->vec_num, 1.0 / dot); (void)BaseMath_WriteCallback(self); /* checked already */ @@ -2302,7 +2304,7 @@ static PyObject *Vector_length_squared_get(VectorObject *self, void *UNUSED(clos return NULL; } - return PyFloat_FromDouble(dot_vn_vn(self->vec, self->vec, self->size)); + return PyFloat_FromDouble(dot_vn_vn(self->vec, self->vec, self->vec_num)); } /** @@ -2382,7 +2384,7 @@ static PyObject *Vector_swizzle_get(VectorObject *self, void *closure) swizzleClosure = POINTER_AS_INT(closure); while (swizzleClosure & SWIZZLE_VALID_AXIS) { axis_from = swizzleClosure & SWIZZLE_AXIS; - if (axis_from >= self->size) { + if (axis_from >= self->vec_num) { PyErr_SetString(PyExc_AttributeError, "Vector swizzle: " "specified axis not present"); @@ -2432,7 +2434,7 @@ static int Vector_swizzle_set(VectorObject *self, PyObject *value, void *closure while (swizzleClosure & SWIZZLE_VALID_AXIS) { axis_to = swizzleClosure & SWIZZLE_AXIS; - if (axis_to >= self->size) { + if (axis_to >= self->vec_num) { PyErr_SetString(PyExc_AttributeError, "Vector swizzle: " "specified axis not present"); @@ -2468,8 +2470,8 @@ static int Vector_swizzle_set(VectorObject *self, PyObject *value, void *closure /* We must first copy current vec into tvec, else some org values may be lost. * See T31760. - * Assuming self->size can't be higher than MAX_DIMENSIONS! */ - memcpy(tvec, self->vec, self->size * sizeof(float)); + * Assuming self->vec_num can't be higher than MAX_DIMENSIONS! */ + memcpy(tvec, self->vec, self->vec_num * sizeof(float)); while (swizzleClosure & SWIZZLE_VALID_AXIS) { axis_to = swizzleClosure & SWIZZLE_AXIS; @@ -2480,7 +2482,7 @@ static int Vector_swizzle_set(VectorObject *self, PyObject *value, void *closure /* We must copy back the whole tvec into vec, else some changes may be lost (e.g. xz...). * See T31760. */ - memcpy(self->vec, tvec, self->size * sizeof(float)); + memcpy(self->vec, tvec, self->vec_num * sizeof(float)); /* continue with BaseMathObject_WriteCallback at the end */ if (BaseMath_WriteCallback(self) == -1) { @@ -2898,10 +2900,10 @@ static int row_vector_multiplication(float r_vec[MAX_DIMENSIONS], MatrixObject *mat) { float vec_cpy[MAX_DIMENSIONS]; - int row, col, z = 0, vec_size = vec->size; + int row, col, z = 0, vec_num = vec->vec_num; - if (mat->num_row != vec_size) { - if (mat->num_row == 4 && vec_size == 3) { + if (mat->row_num != vec_num) { + if (mat->row_num == 4 && vec_num == 3) { vec_cpy[3] = 1.0f; } else { @@ -2916,13 +2918,13 @@ static int row_vector_multiplication(float r_vec[MAX_DIMENSIONS], return -1; } - memcpy(vec_cpy, vec->vec, vec_size * sizeof(float)); + memcpy(vec_cpy, vec->vec, vec_num * sizeof(float)); r_vec[3] = 1.0f; /* Multiplication. */ - for (col = 0; col < mat->num_col; col++) { + for (col = 0; col < mat->col_num; col++) { double dot = 0.0; - for (row = 0; row < mat->num_row; row++) { + for (row = 0; row < mat->row_num; row++) { dot += (double)(MATRIX_ITEM(mat, row, col) * vec_cpy[row]); } r_vec[z++] = (float)dot; @@ -2941,7 +2943,7 @@ static PyObject *Vector_negate(VectorObject *self) return NULL; } - negate_vn(self->vec, self->size); + negate_vn(self->vec, self->vec_num); (void)BaseMath_WriteCallback(self); /* already checked for error */ Py_RETURN_NONE; @@ -3096,17 +3098,17 @@ PyTypeObject vector_Type = { NULL, }; -PyObject *Vector_CreatePyObject(const float *vec, const int size, PyTypeObject *base_type) +PyObject *Vector_CreatePyObject(const float *vec, const int vec_num, PyTypeObject *base_type) { VectorObject *self; float *vec_alloc; - if (size < 2) { + if (vec_num < 2) { PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid size"); return NULL; } - vec_alloc = PyMem_Malloc(size * sizeof(float)); + vec_alloc = PyMem_Malloc(vec_num * sizeof(float)); if (UNLIKELY(vec_alloc == NULL)) { PyErr_SetString(PyExc_MemoryError, "Vector(): " @@ -3117,18 +3119,18 @@ PyObject *Vector_CreatePyObject(const float *vec, const int size, PyTypeObject * self = BASE_MATH_NEW(VectorObject, vector_Type, base_type); if (self) { self->vec = vec_alloc; - self->size = size; + self->vec_num = vec_num; /* init callbacks as NULL */ self->cb_user = NULL; self->cb_type = self->cb_subtype = 0; if (vec) { - memcpy(self->vec, vec, size * sizeof(float)); + memcpy(self->vec, vec, vec_num * sizeof(float)); } else { /* new empty */ - copy_vn_fl(self->vec, size, 0.0f); - if (size == 4) { /* do the homogeneous thing */ + copy_vn_fl(self->vec, vec_num, 0.0f); + if (vec_num == 4) { /* do the homogeneous thing */ self->vec[3] = 1.0f; } } @@ -3141,18 +3143,18 @@ PyObject *Vector_CreatePyObject(const float *vec, const int size, PyTypeObject * return (PyObject *)self; } -PyObject *Vector_CreatePyObject_wrap(float *vec, const int size, PyTypeObject *base_type) +PyObject *Vector_CreatePyObject_wrap(float *vec, const int vec_num, PyTypeObject *base_type) { VectorObject *self; - if (size < 2) { + if (vec_num < 2) { PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid size"); return NULL; } self = BASE_MATH_NEW(VectorObject, vector_Type, base_type); if (self) { - self->size = size; + self->vec_num = vec_num; /* init callbacks as NULL */ self->cb_user = NULL; @@ -3164,9 +3166,9 @@ PyObject *Vector_CreatePyObject_wrap(float *vec, const int size, PyTypeObject *b return (PyObject *)self; } -PyObject *Vector_CreatePyObject_cb(PyObject *cb_user, int size, uchar cb_type, uchar cb_subtype) +PyObject *Vector_CreatePyObject_cb(PyObject *cb_user, int vec_num, uchar cb_type, uchar cb_subtype) { - VectorObject *self = (VectorObject *)Vector_CreatePyObject(NULL, size, NULL); + VectorObject *self = (VectorObject *)Vector_CreatePyObject(NULL, vec_num, NULL); if (self) { Py_INCREF(cb_user); self->cb_user = cb_user; @@ -3178,10 +3180,10 @@ PyObject *Vector_CreatePyObject_cb(PyObject *cb_user, int size, uchar cb_type, u return (PyObject *)self; } -PyObject *Vector_CreatePyObject_alloc(float *vec, const int size, PyTypeObject *base_type) +PyObject *Vector_CreatePyObject_alloc(float *vec, const int vec_num, PyTypeObject *base_type) { VectorObject *self; - self = (VectorObject *)Vector_CreatePyObject_wrap(vec, size, base_type); + self = (VectorObject *)Vector_CreatePyObject_wrap(vec, vec_num, base_type); if (self) { self->flag &= ~BASE_MATH_FLAG_IS_WRAP; } diff --git a/source/blender/python/mathutils/mathutils_Vector.h b/source/blender/python/mathutils/mathutils_Vector.h index 422050c8742..3bc4e9d6b6f 100644 --- a/source/blender/python/mathutils/mathutils_Vector.h +++ b/source/blender/python/mathutils/mathutils_Vector.h @@ -14,12 +14,13 @@ extern PyTypeObject vector_Type; typedef struct { BASE_MATH_MEMBERS(vec); - int size; /* vec size 2 or more */ + /** Number of items in this vector (2 or more). */ + int vec_num; } VectorObject; /*prototypes*/ PyObject *Vector_CreatePyObject(const float *vec, - int size, + int vec_num, PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT; /** * Create a vector that wraps existing memory. @@ -27,7 +28,7 @@ PyObject *Vector_CreatePyObject(const float *vec, * \param vec: Use this vector in-place. */ PyObject *Vector_CreatePyObject_wrap(float *vec, - int size, + int vec_num, PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); /** @@ -35,13 +36,13 @@ PyObject *Vector_CreatePyObject_wrap(float *vec, * see: #Mathutils_RegisterCallback */ PyObject *Vector_CreatePyObject_cb(PyObject *user, - int size, + int vec_num, unsigned char cb_type, unsigned char subtype) ATTR_WARN_UNUSED_RESULT; /** * \param vec: Initialized vector value to use in-place, allocated with #PyMem_Malloc */ PyObject *Vector_CreatePyObject_alloc(float *vec, - int size, + int vec_num, PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c index 84ba2ce4031..1e492574903 100644 --- a/source/blender/python/mathutils/mathutils_geometry.c +++ b/source/blender/python/mathutils/mathutils_geometry.c @@ -158,24 +158,30 @@ static PyObject *M_Geometry_intersect_line_line(PyObject *UNUSED(self), PyObject PyObject *tuple; PyObject *py_lines[4]; float lines[4][3], i1[3], i2[3]; - int len; + int ix_vec_num; int result; if (!PyArg_ParseTuple(args, "OOOO:intersect_line_line", UNPACK4_EX(&, py_lines, ))) { return NULL; } - if ((((len = mathutils_array_parse( + if ((((ix_vec_num = mathutils_array_parse( lines[0], 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_lines[0], error_prefix)) != -1) && - (mathutils_array_parse( - lines[1], len, len | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_lines[1], error_prefix) != - -1) && - (mathutils_array_parse( - lines[2], len, len | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_lines[2], error_prefix) != - -1) && - (mathutils_array_parse( - lines[3], len, len | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_lines[3], error_prefix) != - -1)) == 0) { + (mathutils_array_parse(lines[1], + ix_vec_num, + ix_vec_num | MU_ARRAY_SPILL | MU_ARRAY_ZERO, + py_lines[1], + error_prefix) != -1) && + (mathutils_array_parse(lines[2], + ix_vec_num, + ix_vec_num | MU_ARRAY_SPILL | MU_ARRAY_ZERO, + py_lines[2], + error_prefix) != -1) && + (mathutils_array_parse(lines[3], + ix_vec_num, + ix_vec_num | MU_ARRAY_SPILL | MU_ARRAY_ZERO, + py_lines[3], + error_prefix) != -1)) == 0) { return NULL; } @@ -192,8 +198,9 @@ static PyObject *M_Geometry_intersect_line_line(PyObject *UNUSED(self), PyObject } tuple = PyTuple_New(2); - PyTuple_SET_ITEMS( - tuple, Vector_CreatePyObject(i1, len, NULL), Vector_CreatePyObject(i2, len, NULL)); + PyTuple_SET_ITEMS(tuple, + Vector_CreatePyObject(i1, ix_vec_num, NULL), + Vector_CreatePyObject(i2, ix_vec_num, NULL)); return tuple; } @@ -764,14 +771,14 @@ static PyObject *M_Geometry_intersect_point_line(PyObject *UNUSED(self), PyObjec float pt[3], pt_out[3], line_a[3], line_b[3]; float lambda; PyObject *ret; - int size = 2; + int pt_num = 2; if (!PyArg_ParseTuple(args, "OOO:intersect_point_line", &py_pt, &py_line_a, &py_line_b)) { return NULL; } /* accept 2d verts */ - if ((((size = mathutils_array_parse( + if ((((pt_num = mathutils_array_parse( pt, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_pt, error_prefix)) != -1) && (mathutils_array_parse( line_a, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_line_a, error_prefix) != -1) && @@ -784,7 +791,7 @@ static PyObject *M_Geometry_intersect_point_line(PyObject *UNUSED(self), PyObjec lambda = closest_to_line_v3(pt_out, pt, line_a, line_b); ret = PyTuple_New(2); - PyTuple_SET_ITEMS(ret, Vector_CreatePyObject(pt_out, size, NULL), PyFloat_FromDouble(lambda)); + PyTuple_SET_ITEMS(ret, Vector_CreatePyObject(pt_out, pt_num, NULL), PyFloat_FromDouble(lambda)); return ret; } diff --git a/source/blender/python/mathutils/mathutils_noise.c b/source/blender/python/mathutils/mathutils_noise.c index 0853c5dd3ea..e1282e90c48 100644 --- a/source/blender/python/mathutils/mathutils_noise.c +++ b/source/blender/python/mathutils/mathutils_noise.c @@ -305,23 +305,24 @@ static PyObject *M_Noise_random_unit_vector(PyObject *UNUSED(self), PyObject *ar static const char *kwlist[] = {"size", NULL}; float vec[4] = {0.0f, 0.0f, 0.0f, 0.0f}; float norm = 2.0f; - int size = 3; + int vec_num = 3; - if (!PyArg_ParseTupleAndKeywords(args, kw, "|$i:random_unit_vector", (char **)kwlist, &size)) { + if (!PyArg_ParseTupleAndKeywords( + args, kw, "|$i:random_unit_vector", (char **)kwlist, &vec_num)) { return NULL; } - if (size > 4 || size < 2) { + if (vec_num > 4 || vec_num < 2) { PyErr_SetString(PyExc_ValueError, "Vector(): invalid size"); return NULL; } while (norm == 0.0f || norm > 1.0f) { - rand_vn(vec, size); - norm = normalize_vn(vec, size); + rand_vn(vec, vec_num); + norm = normalize_vn(vec, vec_num); } - return Vector_CreatePyObject(vec, size, NULL); + return Vector_CreatePyObject(vec, vec_num, NULL); } PyDoc_STRVAR(M_Noise_random_vector_doc, @@ -337,22 +338,22 @@ static PyObject *M_Noise_random_vector(PyObject *UNUSED(self), PyObject *args, P { static const char *kwlist[] = {"size", NULL}; float *vec = NULL; - int size = 3; + int vec_num = 3; - if (!PyArg_ParseTupleAndKeywords(args, kw, "|$i:random_vector", (char **)kwlist, &size)) { + if (!PyArg_ParseTupleAndKeywords(args, kw, "|$i:random_vector", (char **)kwlist, &vec_num)) { return NULL; } - if (size < 2) { + if (vec_num < 2) { PyErr_SetString(PyExc_ValueError, "Vector(): invalid size"); return NULL; } - vec = PyMem_New(float, size); + vec = PyMem_New(float, vec_num); - rand_vn(vec, size); + rand_vn(vec, vec_num); - return Vector_CreatePyObject_alloc(vec, size, NULL); + return Vector_CreatePyObject_alloc(vec, vec_num, NULL); } PyDoc_STRVAR(M_Noise_seed_set_doc, diff --git a/source/blender/render/RE_bake.h b/source/blender/render/RE_bake.h index 6d849757166..3a4a3e6dcb9 100644 --- a/source/blender/render/RE_bake.h +++ b/source/blender/render/RE_bake.h @@ -27,16 +27,16 @@ typedef struct BakeImage { typedef struct BakeTargets { /* All images of the object. */ BakeImage *images; - int num_images; + int images_num; /* Lookup table from Material number to BakeImage. */ int *material_to_image; - int num_materials; + int materials_num; /* Pixel buffer to bake to. */ float *result; - int num_pixels; - int num_channels; + int pixels_num; + int channels_num; /* Baking to non-color data image. */ bool is_noncolor; @@ -81,7 +81,7 @@ bool RE_bake_pixels_populate_from_objects(struct Mesh *me_low, BakePixel pixel_array_to[], BakeHighPolyData highpoly[], int tot_highpoly, - size_t num_pixels, + size_t pixels_num, bool is_custom_cage, float cage_extrusion, float max_ray_distance, @@ -91,11 +91,11 @@ bool RE_bake_pixels_populate_from_objects(struct Mesh *me_low, void RE_bake_pixels_populate(struct Mesh *me, struct BakePixel *pixel_array, - size_t num_pixels, + size_t pixels_num, const struct BakeTargets *targets, const char *uv_layer); -void RE_bake_mask_fill(const BakePixel pixel_array[], size_t num_pixels, char *mask); +void RE_bake_mask_fill(const BakePixel pixel_array[], size_t pixels_num, char *mask); void RE_bake_margin(struct ImBuf *ibuf, char *mask, @@ -105,7 +105,7 @@ void RE_bake_margin(struct ImBuf *ibuf, char const *uv_layer); void RE_bake_normal_world_to_object(const BakePixel pixel_array[], - size_t num_pixels, + size_t pixels_num, int depth, float result[], struct Object *ob, @@ -115,14 +115,14 @@ void RE_bake_normal_world_to_object(const BakePixel pixel_array[], * to a tangent space normal map for a given low poly mesh. */ void RE_bake_normal_world_to_tangent(const BakePixel pixel_array[], - size_t num_pixels, + size_t pixels_num, int depth, float result[], struct Mesh *me, const eBakeNormalSwizzle normal_swizzle[3], float mat[4][4]); void RE_bake_normal_world_to_world(const BakePixel pixel_array[], - size_t num_pixels, + size_t pixels_num, int depth, float result[], const eBakeNormalSwizzle normal_swizzle[3]); diff --git a/source/blender/render/intern/bake.c b/source/blender/render/intern/bake.c index 596adafb2c9..69235fb6cb1 100644 --- a/source/blender/render/intern/bake.c +++ b/source/blender/render/intern/bake.c @@ -12,14 +12,14 @@ * The Bake API is fully implemented with Python rna functions. * The operator expects/call a function: * - * `def bake(scene, object, pass_type, object_id, pixel_array, num_pixels, depth, result)` + * `def bake(scene, object, pass_type, object_id, pixel_array, pixels_num, depth, result)` * - scene: current scene (Python object) * - object: object to render (Python object) * - pass_type: pass to render (string, e.g., "COMBINED", "AO", "NORMAL", ...) * - object_id: index of object to bake (to use with the pixel_array) * - pixel_array: list of primitive ids and barycentric coordinates to * `bake(Python object, see bake_pixel)`. - * - num_pixels: size of pixel_array, number of pixels to bake (int) + * - pixels_num: size of pixel_array, number of pixels to bake (int) * - depth: depth of pixels to return (int, assuming always 4 now) * - result: array to be populated by the engine (float array, PyLong_AsVoidPtr) * @@ -126,7 +126,7 @@ static void store_bake_pixel(void *handle, int x, int y, float u, float v) pixel->seed = i; } -void RE_bake_mask_fill(const BakePixel pixel_array[], const size_t num_pixels, char *mask) +void RE_bake_mask_fill(const BakePixel pixel_array[], const size_t pixels_num, char *mask) { size_t i; if (!mask) { @@ -134,7 +134,7 @@ void RE_bake_mask_fill(const BakePixel pixel_array[], const size_t num_pixels, c } /* only extend to pixels outside the mask area */ - for (i = 0; i < num_pixels; i++) { + for (i = 0; i < pixels_num; i++) { if (pixel_array[i].primitive_id != -1) { mask[i] = FILTER_MASK_USED; } @@ -539,7 +539,7 @@ bool RE_bake_pixels_populate_from_objects(struct Mesh *me_low, BakePixel pixel_array_to[], BakeHighPolyData highpoly[], const int tot_highpoly, - const size_t num_pixels, + const size_t pixels_num, const bool is_custom_cage, const float cage_extrusion, const float max_ray_distance, @@ -603,7 +603,7 @@ bool RE_bake_pixels_populate_from_objects(struct Mesh *me_low, } } - for (i = 0; i < num_pixels; i++) { + for (i = 0; i < pixels_num; i++) { float co[3]; float dir[3]; TriTessFace *tri_low; @@ -707,7 +707,7 @@ static void bake_differentials(BakeDataZSpan *bd, void RE_bake_pixels_populate(Mesh *me, BakePixel pixel_array[], - const size_t num_pixels, + const size_t pixels_num, const BakeTargets *targets, const char *uv_layer) { @@ -726,15 +726,15 @@ void RE_bake_pixels_populate(Mesh *me, BakeDataZSpan bd; bd.pixel_array = pixel_array; - bd.zspan = MEM_callocN(sizeof(ZSpan) * targets->num_images, "bake zspan"); + bd.zspan = MEM_callocN(sizeof(ZSpan) * targets->images_num, "bake zspan"); /* initialize all pixel arrays so we know which ones are 'blank' */ - for (int i = 0; i < num_pixels; i++) { + for (int i = 0; i < pixels_num; i++) { pixel_array[i].primitive_id = -1; pixel_array[i].object_id = 0; } - for (int i = 0; i < targets->num_images; i++) { + for (int i = 0; i < targets->images_num; i++) { zbuf_alloc_span(&bd.zspan[i], targets->images[i].width, targets->images[i].height); } @@ -772,7 +772,7 @@ void RE_bake_pixels_populate(Mesh *me, zspan_scanconvert(&bd.zspan[image_id], (void *)&bd, vec[0], vec[1], vec[2], store_bake_pixel); } - for (int i = 0; i < targets->num_images; i++) { + for (int i = 0; i < targets->images_num; i++) { zbuf_free_span(&bd.zspan[i]); } @@ -823,7 +823,7 @@ static void normal_compress(float out[3], } void RE_bake_normal_world_to_tangent(const BakePixel pixel_array[], - const size_t num_pixels, + const size_t pixels_num, const int depth, float result[], Mesh *me, @@ -838,9 +838,9 @@ void RE_bake_normal_world_to_tangent(const BakePixel pixel_array[], triangles = mesh_calc_tri_tessface(me, true, me_eval); - BLI_assert(num_pixels >= 3); + BLI_assert(pixels_num >= 3); - for (i = 0; i < num_pixels; i++) { + for (i = 0; i < pixels_num; i++) { TriTessFace *triangle; float tangents[3][3]; float normals[3][3]; @@ -948,7 +948,7 @@ void RE_bake_normal_world_to_tangent(const BakePixel pixel_array[], } void RE_bake_normal_world_to_object(const BakePixel pixel_array[], - const size_t num_pixels, + const size_t pixels_num, const int depth, float result[], struct Object *ob, @@ -959,7 +959,7 @@ void RE_bake_normal_world_to_object(const BakePixel pixel_array[], invert_m4_m4(iobmat, ob->obmat); - for (i = 0; i < num_pixels; i++) { + for (i = 0; i < pixels_num; i++) { size_t offset; float nor[3]; @@ -980,14 +980,14 @@ void RE_bake_normal_world_to_object(const BakePixel pixel_array[], } void RE_bake_normal_world_to_world(const BakePixel pixel_array[], - const size_t num_pixels, + const size_t pixels_num, const int depth, float result[], const eBakeNormalSwizzle normal_swizzle[3]) { size_t i; - for (i = 0; i < num_pixels; i++) { + for (i = 0; i < pixels_num; i++) { size_t offset; float nor[3]; diff --git a/source/blender/render/intern/engine.c b/source/blender/render/intern/engine.c index 3a7ac22dc1f..8a4b4c2a70d 100644 --- a/source/blender/render/intern/engine.c +++ b/source/blender/render/intern/engine.c @@ -827,14 +827,14 @@ bool RE_bake_engine(Render *re, type->update(engine, re->main, engine->depsgraph); } - for (int i = 0; i < targets->num_images; i++) { + for (int i = 0; i < targets->images_num; i++) { const BakeImage *image = targets->images + i; engine->bake.pixels = pixel_array + image->offset; - engine->bake.result = result + image->offset * targets->num_channels; + engine->bake.result = result + image->offset * targets->channels_num; engine->bake.width = image->width; engine->bake.height = image->height; - engine->bake.depth = targets->num_channels; + engine->bake.depth = targets->channels_num; engine->bake.object_id = object_id; type->bake( diff --git a/source/blender/render/intern/multires_bake.c b/source/blender/render/intern/multires_bake.c index c573d4feed1..33d961c027d 100644 --- a/source/blender/render/intern/multires_bake.c +++ b/source/blender/render/intern/multires_bake.c @@ -1061,23 +1061,23 @@ static void create_ao_raytree(MultiresBakeRender *bkr, MAOBakeData *ao_data) RayFace *face; CCGElem **grid_data; CCGKey key; - int num_grids, grid_size /*, face_side */, num_faces; + int grids_num, grid_size /*, face_side */, faces_num; int i; - num_grids = hidm->getNumGrids(hidm); + grids_num = hidm->getNumGrids(hidm); grid_size = hidm->getGridSize(hidm); grid_data = hidm->getGridData(hidm); hidm->getGridKey(hidm, &key); /* face_side = (grid_size << 1) - 1; */ /* UNUSED */ - num_faces = num_grids * (grid_size - 1) * (grid_size - 1); + faces_num = grids_num * (grid_size - 1) * (grid_size - 1); raytree = ao_data->raytree = RE_rayobject_create( - bkr->raytrace_structure, num_faces, bkr->octree_resolution); - face = ao_data->rayfaces = (RayFace *)MEM_callocN(num_faces * sizeof(RayFace), + bkr->raytrace_structure, faces_num, bkr->octree_resolution); + face = ao_data->rayfaces = (RayFace *)MEM_callocN(faces_num * sizeof(RayFace), "ObjectRen faces"); - for (i = 0; i < num_grids; i++) { + for (i = 0; i < grids_num; i++) { int x, y; for (x = 0; x < grid_size - 1; x++) { for (y = 0; y < grid_size - 1; y++) { diff --git a/source/blender/render/intern/render_result.c b/source/blender/render/intern/render_result.c index ea7fa961f0d..9f4aa642773 100644 --- a/source/blender/render/intern/render_result.c +++ b/source/blender/render/intern/render_result.c @@ -402,7 +402,7 @@ RenderResult *render_result_new(Render *re, render_layer_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, view, "RGBA", false); } - /* NOTE: this has to be in sync with `scene.c`. */ + /* NOTE: this has to be in sync with `scene.cc`. */ rl->layflag = SCE_LAY_FLAG_DEFAULT; rl->passflag = SCE_PASS_COMBINED; diff --git a/source/blender/render/intern/texture_pointdensity.c b/source/blender/render/intern/texture_pointdensity.c index f81b43f4bb0..bb313d4962c 100644 --- a/source/blender/render/intern/texture_pointdensity.c +++ b/source/blender/render/intern/texture_pointdensity.c @@ -843,7 +843,7 @@ void RE_point_density_minmax(struct Depsgraph *depsgraph, } else { const float radius[3] = {pd->radius, pd->radius, pd->radius}; - BoundBox *bb = BKE_object_boundbox_get(object); + const BoundBox *bb = BKE_object_boundbox_get(object); if (bb != NULL) { BLI_assert((bb->flag & BOUNDBOX_DIRTY) == 0); diff --git a/source/blender/sequencer/SEQ_animation.h b/source/blender/sequencer/SEQ_animation.h index 455e77fb4a3..f2c66393b65 100644 --- a/source/blender/sequencer/SEQ_animation.h +++ b/source/blender/sequencer/SEQ_animation.h @@ -19,6 +19,18 @@ struct Sequence; void SEQ_free_animdata(struct Scene *scene, struct Sequence *seq); void SEQ_offset_animdata(struct Scene *scene, struct Sequence *seq, int ofs); struct GSet *SEQ_fcurves_by_strip_get(const struct Sequence *seq, struct ListBase *fcurve_base); +/** + * Move all `F-curves` from `scene` to `list`. + */ +void SEQ_animation_backup_original(struct Scene *scene, struct ListBase *list); +/** + * Move all `F-curves` from `list` to `scene`. + */ +void SEQ_animation_restore_original(struct Scene *scene, struct ListBase *list); +/** + * Duplicate `F-curves` used by `seq` from `list` to `scene`. + */ +void SEQ_animation_duplicate(struct Scene *scene, struct Sequence *seq, struct ListBase *list); #ifdef __cplusplus } diff --git a/source/blender/sequencer/intern/animation.c b/source/blender/sequencer/intern/animation.c index 47453ceda2b..27f7316e042 100644 --- a/source/blender/sequencer/intern/animation.c +++ b/source/blender/sequencer/intern/animation.c @@ -104,3 +104,32 @@ void SEQ_free_animdata(Scene *scene, Sequence *seq) GSET_FOREACH_END(); BLI_gset_free(fcurves, NULL); } + +void SEQ_animation_backup_original(Scene *scene, ListBase *list) +{ + if (scene->adt == NULL || scene->adt->action == NULL || + BLI_listbase_is_empty(&scene->adt->action->curves)) { + return; + } + + BLI_movelisttolist(list, &scene->adt->action->curves); +} + +void SEQ_animation_restore_original(Scene *scene, ListBase *list) +{ + if (scene->adt == NULL || scene->adt->action == NULL || BLI_listbase_is_empty(list)) { + return; + } + + BLI_movelisttolist(&scene->adt->action->curves, list); +} + +void SEQ_animation_duplicate(Scene *scene, Sequence *seq, ListBase *list) +{ + GSet *fcurves = SEQ_fcurves_by_strip_get(seq, list); + GSET_FOREACH_BEGIN (FCurve *, fcu, fcurves) { + FCurve *fcu_cpy = BKE_fcurve_copy(fcu); + BLI_addtail(&scene->adt->action->curves, fcu_cpy); + } + GSET_FOREACH_END(); +} diff --git a/source/blender/sequencer/intern/effects.c b/source/blender/sequencer/intern/effects.c index 8f7088b0c4b..a4ab7671eb0 100644 --- a/source/blender/sequencer/intern/effects.c +++ b/source/blender/sequencer/intern/effects.c @@ -1681,7 +1681,7 @@ static void do_wipe_effect_byte(Sequence *seq, for (int i = 0; i < y; i++) { for (int j = 0; j < x; j++) { - float check = check_zone(&wipezone, x, y, seq, fac); + float check = check_zone(&wipezone, j, i, seq, fac); if (check) { if (cp1) { float rt1[4], rt2[4], tempc[4]; @@ -1742,7 +1742,7 @@ static void do_wipe_effect_float( for (int i = 0; i < y; i++) { for (int j = 0; j < x; j++) { - float check = check_zone(&wipezone, x, y, seq, fac); + float check = check_zone(&wipezone, j, i, seq, fac); if (check) { if (rt1) { rt[0] = rt1[0] * check + rt2[0] * (1 - check); diff --git a/source/blender/sequencer/intern/strip_edit.c b/source/blender/sequencer/intern/strip_edit.c index 60f3f35314e..2f76b6240cf 100644 --- a/source/blender/sequencer/intern/strip_edit.c +++ b/source/blender/sequencer/intern/strip_edit.c @@ -457,11 +457,18 @@ Sequence *SEQ_edit_strip_split(Main *bmain, return NULL; } - /* Move strips in collection from seqbase to new ListBase. */ + /* Store `F-curves`, so original ones aren't renamed. */ + ListBase fcurves_original_backup = {NULL, NULL}; + SEQ_animation_backup_original(scene, &fcurves_original_backup); + ListBase left_strips = {NULL, NULL}; SEQ_ITERATOR_FOREACH (seq, collection) { + /* Move strips in collection from seqbase to new ListBase. */ BLI_remlink(seqbase, seq); BLI_addtail(&left_strips, seq); + + /* Duplicate curves from backup, so they can be renamed along with split strips. */ + SEQ_animation_duplicate(scene, seq, &fcurves_original_backup); } SEQ_collection_free(collection); @@ -511,6 +518,8 @@ Sequence *SEQ_edit_strip_split(Main *bmain, SEQ_ensure_unique_name(seq_rename, scene); } + SEQ_animation_restore_original(scene, &fcurves_original_backup); + return return_seq; } diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 6be3d719c64..bd7504788e1 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -39,6 +39,7 @@ struct MenuType; struct PointerRNA; struct PropertyRNA; struct ScrArea; +struct SelectPick_Params; struct View3D; struct ViewLayer; struct bContext; @@ -740,14 +741,33 @@ bool WM_operator_last_properties_store(struct wmOperator *op); /* wm_operator_props.c */ void WM_operator_properties_confirm_or_exec(struct wmOperatorType *ot); + +/** Flags for #WM_operator_properties_filesel. */ +typedef enum eFileSel_Flag { + WM_FILESEL_RELPATH = 1 << 0, + WM_FILESEL_DIRECTORY = 1 << 1, + WM_FILESEL_FILENAME = 1 << 2, + WM_FILESEL_FILEPATH = 1 << 3, + WM_FILESEL_FILES = 1 << 4, + /** Show the properties sidebar by default. */ + WM_FILESEL_SHOW_PROPS = 1 << 5, +} eFileSel_Flag; +ENUM_OPERATORS(eFileSel_Flag, WM_FILESEL_SHOW_PROPS) + +/** Action for #WM_operator_properties_filesel. */ +typedef enum eFileSel_Action { + FILE_OPENFILE = 0, + FILE_SAVE = 1, +} eFileSel_Action; + /** * Default properties for file-select. */ void WM_operator_properties_filesel(struct wmOperatorType *ot, int filter, short type, - short action, - short flag, + eFileSel_Action action, + eFileSel_Flag flag, short display, short sort); /** @@ -777,6 +797,9 @@ void WM_operator_properties_gesture_straightline(struct wmOperatorType *ot, int * Use with #WM_gesture_circle_invoke */ void WM_operator_properties_gesture_circle(struct wmOperatorType *ot); +/** + * See #ED_select_pick_params_from_operator to initialize parameters defined here. + */ void WM_operator_properties_mouse_select(struct wmOperatorType *ot); void WM_operator_properties_select_all(struct wmOperatorType *ot); void WM_operator_properties_select_action(struct wmOperatorType *ot, @@ -841,16 +864,6 @@ void WM_operator_properties_checker_interval_from_op(struct wmOperator *op, bool WM_operator_properties_checker_interval_test(const struct CheckerIntervalParams *op_params, int depth); -/* flags for WM_operator_properties_filesel */ -#define WM_FILESEL_RELPATH (1 << 0) - -#define WM_FILESEL_DIRECTORY (1 << 1) -#define WM_FILESEL_FILENAME (1 << 2) -#define WM_FILESEL_FILEPATH (1 << 3) -#define WM_FILESEL_FILES (1 << 4) -/* Show the properties sidebar by default. */ -#define WM_FILESEL_SHOW_PROPS (1 << 5) - /** * Operator as a Python command (resulting string must be freed). * diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c index 00615d9d662..d7b54129caa 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c @@ -1130,7 +1130,12 @@ void WM_gizmo_group_refresh(const bContext *C, wmGizmoGroup *gzgroup) const wmGizmoGroupType *gzgt = gzgroup->type; if (gzgt->flag & WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK) { wmGizmoMap *gzmap = gzgroup->parent_gzmap; - wmGizmo *gz = wm_gizmomap_highlight_get(gzmap); + wmGizmo *gz = NULL; + /* Without the check for refresh, any highlighted gizmo will prevent hiding + * when selecting with RMB when the cursor happens to be over a gizmo. */ + if ((gzgroup->init_flag & WM_GIZMOGROUP_INIT_REFRESH) == 0) { + gz = wm_gizmomap_highlight_get(gzmap); + } if (!gz || gz->parent_gzgroup != gzgroup) { wmWindow *win = CTX_wm_window(C); ARegion *region = CTX_wm_region(C); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 60ae4eccbbe..84c40c42adc 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1297,6 +1297,23 @@ static wmOperator *wm_operator_create(wmWindowManager *wm, return op; } +/** + * This isn't very nice but needed to redraw gizmos which are hidden while tweaking, + * See #WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK for details. + */ +static void wm_region_tag_draw_on_gizmo_delay_refresh_for_tweak(wmWindow *win, bScreen *screen) +{ + ED_screen_areas_iter (win, screen, area) { + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { + if (region->gizmo_map != NULL) { + if (WM_gizmomap_tag_delay_refresh_for_tweak_check(region->gizmo_map)) { + ED_region_tag_redraw(region); + } + } + } + } +} + static void wm_region_mouse_co(bContext *C, wmEvent *event) { ARegion *region = CTX_wm_region(C); @@ -3711,6 +3728,7 @@ void wm_event_do_handlers(bContext *C) event->flag |= WM_EVENT_FORCE_DRAG_THRESHOLD; } } + const bool event_queue_check_drag_prev = win->event_queue_check_drag; /* Active screen might change during handlers, update pointer. */ screen = WM_window_get_active_screen(win); @@ -3870,6 +3888,10 @@ void wm_event_do_handlers(bContext *C) win->event_queue_check_drag_handled = false; } + if (event_queue_check_drag_prev && (win->event_queue_check_drag == false)) { + wm_region_tag_draw_on_gizmo_delay_refresh_for_tweak(win, screen); + } + /* Update previous mouse position for following events to use. */ copy_v2_v2_int(win->eventstate->prev_xy, event->xy); diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 1369ee99cd2..d398b255502 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -873,7 +873,7 @@ static void file_read_reports_finalize(BlendFileReadReport *bf_reports) RPT_WARNING, "Proxies have been removed from Blender (%d proxies were automatically converted " "to library overrides, %d proxies could not be converted and were cleared). " - "Please also consider re-saving any library .blend file with the newest Blender version.", + "Please also consider re-saving any library .blend file with the newest Blender version", bf_reports->count.proxies_to_lib_overrides_success, bf_reports->count.proxies_to_lib_overrides_failures); } diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c index dacc17c2c1e..c048b64426a 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.c +++ b/source/blender/windowmanager/intern/wm_operator_props.c @@ -58,12 +58,12 @@ static const EnumPropertyItem *wm_operator_properties_filesel_sort_items_itemf( } void WM_operator_properties_filesel(wmOperatorType *ot, - int filter, - short type, - short action, - short flag, - short display, - short sort) + const int filter, + const short type, + const eFileSel_Action action, + const eFileSel_Flag flag, + const short display, + const short sort) { PropertyRNA *prop; diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index b45c638d7b9..a3d2d38136c 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -588,7 +588,13 @@ char *WM_context_path_resolve_property_full(const bContext *C, if (data_path != NULL) { if (prop != NULL) { char *prop_str = RNA_path_property_py(ptr, prop, index); - member_id_data_path = BLI_string_join_by_sep_charN('.', member_id, data_path, prop_str); + if (prop_str[0] == '[') { + member_id_data_path = BLI_string_joinN(member_id, ".", data_path, prop_str); + } + else { + member_id_data_path = BLI_string_join_by_sep_charN( + '.', member_id, data_path, prop_str); + } MEM_freeN(prop_str); } else { @@ -600,7 +606,12 @@ char *WM_context_path_resolve_property_full(const bContext *C, else { if (prop != NULL) { char *prop_str = RNA_path_property_py(ptr, prop, index); - member_id_data_path = BLI_string_join_by_sep_charN('.', member_id, prop_str); + if (prop_str[0] == '[') { + member_id_data_path = BLI_string_joinN(member_id, prop_str); + } + else { + member_id_data_path = BLI_string_join_by_sep_charN('.', member_id, prop_str); + } MEM_freeN(prop_str); } else { diff --git a/tests/python/cycles_render_tests.py b/tests/python/cycles_render_tests.py index 598e4b6828c..10ba2ce552a 100644 --- a/tests/python/cycles_render_tests.py +++ b/tests/python/cycles_render_tests.py @@ -32,6 +32,11 @@ BLACKLIST_OPTIX = [ 'T43865.blend', ] +BLACKLIST_METAL = [ + # No MNEE for Metal currently + "underwater_caustics.blend", +] + BLACKLIST_GPU = [ # Uninvestigated differences with GPU. 'image_log.blend', @@ -116,6 +121,8 @@ def main(): blacklist += BLACKLIST_OSL if device == 'OPTIX': blacklist += BLACKLIST_OPTIX + if device == 'METAL': + blacklist += BLACKLIST_METAL from modules import render_report report = render_report.Report('Cycles', output_dir, idiff, device, blacklist) |