Image Editor Vectorscope Improvement #116974
30
AUTHORS
30
AUTHORS
|
@ -20,7 +20,9 @@
|
|||
# python ./tools/utils/authors_git_gen.py
|
||||
|
||||
# BEGIN individuals section.
|
||||
20kdc <asdd2808@gmail.com>
|
||||
Aaron Carlisle <carlisle.aaron00@gmail.com>
|
||||
Aaron Franke <arnfranke@yahoo.com>
|
||||
Adam Nydahl <Loginer>
|
||||
Adi Sage <adisage.connect@gmail.com>
|
||||
Aditya Y Jeppu <quantimoney>
|
||||
|
@ -48,6 +50,7 @@ Alexander Kuznetsov <kuzsasha@gmail.com>
|
|||
Alexander Pinzon <apinzonf@gmail.com>
|
||||
Alexander Revkov <arevkov>
|
||||
Alexander Romanov <a.romanov@blend4web.com>
|
||||
Alexander Wilms <alexanderwilms@noreply.localhost>
|
||||
Alexandr Kuznetsov <ak3636@nyu.edu>
|
||||
Aleš Jelovčan <frogstomp>
|
||||
Alfredo de Greef <eeshlo@yahoo.com>
|
||||
|
@ -63,6 +66,7 @@ Andrea Beconcini <beco>
|
|||
Andrea Weikert <elubie@gmx.net>
|
||||
Andreas Bergmeier <abergmeier>
|
||||
Andrej730 <azhilenkov@gmail.com>
|
||||
Andres Stephens <ondraise15@hotmail.com>
|
||||
Andrew Buttery <axb2035@gmail.com>
|
||||
Andrew Hale <TrumanBlending@gmail.com>
|
||||
Andrew Oates <aoates>
|
||||
|
@ -139,6 +143,7 @@ Christoph Lendenfeld <chris.lenden@gmail.com>
|
|||
Christophe Hery <chery>
|
||||
Christopher Peerman <chris_82>
|
||||
Cian Jinks <cjinks99@gmail.com>
|
||||
Clément Busschaert <clement.busschaert@gmail.com>
|
||||
Clément Foucault <foucault.clem@gmail.com>
|
||||
Cody Winchester <CodyWinch>
|
||||
Colby Klein <shakesoda>
|
||||
|
@ -150,6 +155,7 @@ Cyrax <cyrax.iiit@gmail.com>
|
|||
Cédric Paille <cedricp>
|
||||
D. O <Likkez>
|
||||
D.J. Capelis <blender@capelis.dj>
|
||||
Daiki Hashimoto <daisea3e1203@gmail.com>
|
||||
Daisuke Takahashi <noreply@blender.org>
|
||||
Dalai Felinto <dalai@blender.org>
|
||||
Damien Dh <damdhe>
|
||||
|
@ -190,6 +196,7 @@ Dontsov Valentin <@blend4web.com>
|
|||
Dorian <BD3D>
|
||||
Doug Hammond <doughammond@hamsterfight.co.uk>
|
||||
Douglas Paul <douglas.w.paul@gmail.com>
|
||||
Dyvine57 <dulana57@gmail.com>
|
||||
Ed Halley <ed@halley.cc>
|
||||
Edgar Roman Cervantes <redvant>
|
||||
Edmund Kapusniak <edmundmk>
|
||||
|
@ -206,6 +213,7 @@ Erik Abrahamsson <ecke101@gmail.com>
|
|||
Ervin Weber <ervin.weber@gmail.com>
|
||||
Erwin Coumans <blender@erwincoumans.com>
|
||||
Ethan Hall <Ethan1080>
|
||||
Eugene Kuznetsov <eugene.kuznetsov@amd.com>
|
||||
Evan Wilson <EAW>
|
||||
Fabian Schempp <fabianschempp@googlemail.com>
|
||||
Fabrício Luis <ce3po>
|
||||
|
@ -314,6 +322,7 @@ Johannes Meng <info@jmeng.de>
|
|||
John Quillan <jquillan>
|
||||
Johnny Matthews <johnny.matthews@gmail.com>
|
||||
Joilnen Leite <joilnen.leite@gmail.com>
|
||||
Jonas Holzman <jonas@holzman.fr>
|
||||
Jonathan Williamson <jonathan@cgcookie.com>
|
||||
Jorge Bernal <jbernalmartinez@gmail.com>
|
||||
Jorijn de Graaf <bonj@noreply.localhost>
|
||||
|
@ -333,10 +342,12 @@ Juanfran Matheu <jfmatheu>
|
|||
Juha Mäki-Kanto <ih5235252@gmail.com>
|
||||
Juho Vepsalainen <bebraw@gmail.com>
|
||||
Julian Eisel <julian@blender.org>
|
||||
Julian Plak <julian.plak@live.nl>
|
||||
Julian Squires <julian@cipht.net>
|
||||
Julien Kaspar <julien@blender.org>
|
||||
Jun Mizutani <jmztn@noreply.localhost>
|
||||
Jung Jaeyun <cube-c>
|
||||
Jure Triglav <juretriglav@gmail.com>
|
||||
Justin Dailey <dail8859@yahoo.com>
|
||||
Justin Jones <jjones780>
|
||||
Jörg Müller <nexyon@gmail.com>
|
||||
|
@ -352,6 +363,7 @@ Keith Boshoff <wahooney>
|
|||
Ken Hughes <khughes@pacific.edu>
|
||||
Kenneth Perry <thothonegan>
|
||||
Kent Mein <mein@cs.umn.edu>
|
||||
Kenzie <kenziemac130@noreply.localhost>
|
||||
Kester Maddock <Christopher.Maddock.1@uni.massey.ac.nz>
|
||||
Kevin Buhr <buhr>
|
||||
Kevin C. Burke <kevincburke@noreply.localhost>
|
||||
|
@ -365,7 +377,6 @@ Kris <Metricity>
|
|||
Krzysztof Recko <yetioszek@gmail.com>
|
||||
Kévin Dietrich <kevin.dietrich@mailoo.org>
|
||||
L. E. Segovia <leonardo.segovia@cs.uns.edu.ar>
|
||||
Laurynas Duburas <laurynas>
|
||||
Lawrence D'Oliveiro <from-blender@geek-central.gen.nz>
|
||||
Leha <leha>
|
||||
Leon Schittek <leon.schittek@gmx.net>
|
||||
|
@ -399,6 +410,7 @@ Manuel Castilla <manzanillawork@gmail.com>
|
|||
Marc Chehab <marcchehab@protonmail.ch>
|
||||
Marc Freixas <mfreixas@lsi.upc.edu>
|
||||
Marcelo Demian Gómez <mdemiang>
|
||||
Marcelo Mutzbauer <1xundoredo@gmail.com>
|
||||
Marco <nacioss>
|
||||
Marcos Perez <pistolario>
|
||||
Marino Toscano <marino.toscano@gmail.com>
|
||||
|
@ -455,7 +467,7 @@ Mikkel Gjoel <mikkelgjoel>
|
|||
Milan Davidović <milan.davidovic@protonmail.com>
|
||||
Milan Jaros <jar091>
|
||||
Mitchell Stokes <mogurijin@gmail.com>
|
||||
Monique Dewanchand <m.dewanchand@atmind.nl>
|
||||
Monique Dewanchand <mdewanchand@atmind.nl>
|
||||
Moritz Röhrich <ildefons>
|
||||
Morten Mikkelsen <mikkelsen7@gmail.com>
|
||||
Myles Walcott <myles_walcott>
|
||||
|
@ -484,9 +496,11 @@ Olivier Jolly <zeograd>
|
|||
Olivier Maury <omaury>
|
||||
Omar Emara <mail@OmarEmara.dev>
|
||||
Ove Murberg Henriksen <sorayasilvermoon@hotmail.com>
|
||||
Pablo Delgado Krämer <private@pablode.com>
|
||||
Pablo Dobarro <pablodp606@gmail.com>
|
||||
Pablo Vazquez <pablo@blender.org>
|
||||
Paolo Acampora <pkrime>
|
||||
Paolo Amadini <paolo.blender.dev@amadzone.org>
|
||||
Pascal Schoen <pascal.schoen@adidas-group.com>
|
||||
Patrick Bender <ichbinkeinreh>
|
||||
Patrick Busch <xylvier@noreply.localhost>
|
||||
|
@ -521,11 +535,11 @@ Pierre Risch <prisch>
|
|||
Piotr Makal <pmakal>
|
||||
Piotr Ostrowski <postrowski>
|
||||
Pratik Borhade <pratikborhade302@gmail.com>
|
||||
Prikshit singh <prikshitsingh79@gmail.com>
|
||||
Quentin Wenger <matpi@protonmail.ch>
|
||||
RUben <KUbo_0>
|
||||
Rahul Chaudhary <RC12>
|
||||
Raimund Klink <raimund58@noreply.localhost>
|
||||
Rajesh Advani <rajeshja>
|
||||
Ralf Hölzemer <r.hoelzemer@googlemail.com>
|
||||
Ramil Roosileht <Limarest>
|
||||
Rateeb Riyasat <bmollusc>
|
||||
|
@ -591,6 +605,7 @@ Sonny Campbell <sonny.campbell@unity3d.com>
|
|||
Sriharsha Kotcharlakot <k.venkatsriharsha@gmail.com>
|
||||
Stanislav Blinov <radcapricorn>
|
||||
Stefan Gartner <stefang@aon.at>
|
||||
Stefan Heinz <stefanh@noreply.localhost>
|
||||
Stefan Werner <stefan.werner@intel.com>
|
||||
Stefano Bonicatti <smjert>
|
||||
Stephan Seitz <theHamsta>
|
||||
|
@ -599,7 +614,7 @@ Stephen Seo <seodisparate>
|
|||
Stephen Swaney <sswaney@centurytel.net>
|
||||
Stuart Broadfoot <gbroadfoot@hotmail.com>
|
||||
Sukhitha Prabhath Jayathilake <pr.jayathilake@gmail.com>
|
||||
Sun Kim <persun@noreply.localhost>
|
||||
Sun Kim <perplexing.sun@gmail.com>
|
||||
Sv. Lockal <lockalsash@gmail.com>
|
||||
Sybren A. Stüvel <sybren@blender.org>
|
||||
Szymon Ulatowski <szulat>
|
||||
|
@ -649,7 +664,7 @@ Vitor Boschi <vitorboschi@gmail.com>
|
|||
Vuk Gardašević <lijenstina>
|
||||
Wael El Oraiby <wael.eloraiby@gmail.com>
|
||||
Walid Shouman <eng.walidshouman@gmail.com>
|
||||
Wannes Malfait <Wannes>
|
||||
Wannes Malfait <wannes.malfait@gmail.com>
|
||||
Wayde Moss <wbmoss_dev@yahoo.com>
|
||||
Weikang Qiu <qiuweikang1999@gmail.com>
|
||||
Weizhen Huang <weizhen@blender.org>
|
||||
|
@ -674,19 +689,23 @@ Yonatan Maor <yon.maor@gmail.com>
|
|||
Yuki Hashimoto <hzuika>
|
||||
Yuki Shirakawa <shirakawa>
|
||||
Yuntoko <yuntokon@gmail.com>
|
||||
Z-Map <blendfan@gmail.com>
|
||||
Zev Eisenberg <ZevEisenberg>
|
||||
Zijun Zhou <eary@noreply.localhost>
|
||||
andreas atteneder <atti>
|
||||
ariva00 <ariva00.it@gmail.com>
|
||||
b-init <b-init>
|
||||
bird_d <bird_d>
|
||||
brunoT <drehuwann@gmail.com>
|
||||
cgtinker <Denys.Hsu@gmail.com>
|
||||
coyo_t <constachugga@gmail.com>
|
||||
dupoxy <dupoxy@noreply.localhost>
|
||||
fiord <hyoga_quasar@yahoo.co.jp>
|
||||
himisa <himisa@noreply.localhost>
|
||||
jim man <jimman2003>
|
||||
jon denning <gfxcoder@gmail.com>
|
||||
kiki <charles@skeletalstudios.com>
|
||||
laurynas <laduem@gmail.com>
|
||||
listout <listout@protonmail.com>
|
||||
lolloz98 <lorenzocarpaneto@yahoo.it>
|
||||
luzpaz <luzpaz>
|
||||
|
@ -697,6 +716,7 @@ nBurn <nbwashburn@gmail.com>
|
|||
nutti <nutti.metro@gmail.com>
|
||||
ok_what <ip1149a@gmail.com>
|
||||
persun <perplexing.sun@gmail.com>
|
||||
rajveermalviya <rajveer0malviya@gmail.com>
|
||||
swann <slumber>
|
||||
unclezeiv <davide.vercelli@gmail.com>
|
||||
yves <valfeur>
|
||||
|
|
|
@ -1234,10 +1234,10 @@ if(WITH_PYTHON)
|
|||
# Do this before main 'platform_*' checks,
|
||||
# because UNIX will search for the old Python paths which may not exist.
|
||||
# giving errors about missing paths before this case is met.
|
||||
if(DEFINED PYTHON_VERSION AND "${PYTHON_VERSION}" VERSION_LESS "3.10")
|
||||
if(DEFINED PYTHON_VERSION AND "${PYTHON_VERSION}" VERSION_LESS "3.11")
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"At least Python 3.10 is required to build, but found Python ${PYTHON_VERSION}"
|
||||
"At least Python 3.11 is required to build, but found Python ${PYTHON_VERSION}"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
|
27
GNUmakefile
27
GNUmakefile
|
@ -199,11 +199,6 @@ ifndef DEPS_INSTALL_DIR
|
|||
endif
|
||||
endif
|
||||
|
||||
# Allow to use alternative binary (pypy3, etc)
|
||||
ifndef PYTHON
|
||||
PYTHON:=python3
|
||||
endif
|
||||
|
||||
# Set the LIBDIR, an empty string when not found.
|
||||
LIBDIR:=$(wildcard ../lib/${OS_NCASE}_${CPU})
|
||||
ifeq (, $(LIBDIR))
|
||||
|
@ -215,15 +210,15 @@ endif
|
|||
|
||||
# Find the newest Python version bundled in `LIBDIR`.
|
||||
PY_LIB_VERSION:=3.15
|
||||
ifeq (, $(wildcard $(LIBDIR)/python/lib/python$(PY_LIB_VERSION)))
|
||||
ifeq (, $(wildcard $(LIBDIR)/python/bin/python$(PY_LIB_VERSION)))
|
||||
PY_LIB_VERSION:=3.14
|
||||
ifeq (, $(wildcard $(LIBDIR)/python/lib/python$(PY_LIB_VERSION)))
|
||||
ifeq (, $(wildcard $(LIBDIR)/python/bin/python$(PY_LIB_VERSION)))
|
||||
PY_LIB_VERSION:=3.13
|
||||
ifeq (, $(wildcard $(LIBDIR)/python/lib/python$(PY_LIB_VERSION)))
|
||||
ifeq (, $(wildcard $(LIBDIR)/python/bin/python$(PY_LIB_VERSION)))
|
||||
PY_LIB_VERSION:=3.12
|
||||
ifeq (, $(wildcard $(LIBDIR)/python/lib/python$(PY_LIB_VERSION)))
|
||||
ifeq (, $(wildcard $(LIBDIR)/python/bin/python$(PY_LIB_VERSION)))
|
||||
PY_LIB_VERSION:=3.11
|
||||
ifeq (, $(wildcard $(LIBDIR)/python/lib/python$(PY_LIB_VERSION)))
|
||||
ifeq (, $(wildcard $(LIBDIR)/python/bin/python$(PY_LIB_VERSION)))
|
||||
PY_LIB_VERSION:=3.10
|
||||
endif
|
||||
endif
|
||||
|
@ -231,11 +226,13 @@ ifeq (, $(wildcard $(LIBDIR)/python/lib/python$(PY_LIB_VERSION)))
|
|||
endif
|
||||
endif
|
||||
|
||||
# For macOS python3 is not installed by default, so fallback to python binary
|
||||
# in libraries, or python 2 for running make update to get it.
|
||||
ifeq ($(OS_NCASE),darwin)
|
||||
ifeq (, $(shell command -v $(PYTHON)))
|
||||
PYTHON:=$(LIBDIR)/python/bin/python$(PY_LIB_VERSION)
|
||||
# Allow to use alternative binary (pypy3, etc)
|
||||
ifndef PYTHON
|
||||
# If not overriden, first try using Python from LIBDIR.
|
||||
PYTHON:=$(LIBDIR)/python/bin/python$(PY_LIB_VERSION)
|
||||
ifeq (, $(PYTHON))
|
||||
# If not available, use system python3 or python command.
|
||||
PYTHON:=python3
|
||||
ifeq (, $(shell command -v $(PYTHON)))
|
||||
PYTHON:=python
|
||||
endif
|
||||
|
|
|
@ -34,9 +34,9 @@ add_dependencies(
|
|||
if(BUILD_MODE STREQUAL Release AND WIN32)
|
||||
ExternalProject_Add_Step(external_freetype after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/freetype ${HARVEST_TARGET}/freetype
|
||||
# harfbuzz *NEEDS* to find freetype.lib and will not be conviced to take alternative names so just give it
|
||||
# what it wants.
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/freetype/lib/freetype2st.lib ${LIBDIR}/freetype/lib/freetype.lib
|
||||
# harfbuzz *NEEDS* to find freetype.lib and will not be conviced to take alternative names so just give it
|
||||
# what it wants.
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/freetype/lib/freetype2st.lib ${LIBDIR}/freetype/lib/freetype.lib
|
||||
|
||||
DEPENDEES install
|
||||
)
|
||||
|
|
|
@ -8,8 +8,8 @@ if(BUILD_MODE STREQUAL Release)
|
|||
-DALSOFT_NO_CONFIG_UTIL=ON
|
||||
-DALSOFT_EXAMPLES=OFF
|
||||
-DALSOFT_TESTS=OFF
|
||||
-DALSOFT_CONFIG=OFF
|
||||
-DALSOFT_HRTF_DEFS=OFF
|
||||
-DALSOFT_INSTALL_CONFIG=OFF
|
||||
-DALSOFT_INSTALL_HRTF_DATA=OFF
|
||||
-DALSOFT_INSTALL=ON
|
||||
-DALSOFT_BACKEND_SNDIO=OFF
|
||||
)
|
||||
|
|
|
@ -18,9 +18,9 @@ set(ZLIB_FILE zlib-${ZLIB_VERSION}.tar.gz)
|
|||
set(ZLIB_CPE "cpe:2.3:a:zlib:zlib:${ZLIB_VERSION}:*:*:*:*:*:*:*")
|
||||
set(ZLIB_HOMEPAGE https://zlib.net)
|
||||
|
||||
set(OPENAL_VERSION 1.21.1)
|
||||
set(OPENAL_URI http://openal-soft.org/openal-releases/openal-soft-${OPENAL_VERSION}.tar.bz2)
|
||||
set(OPENAL_HASH a936806ebd8de417b0ffd8cf3f48f456)
|
||||
set(OPENAL_VERSION 1.23.1)
|
||||
set(OPENAL_URI https://github.com/kcat/openal-soft/releases/download/${OPENAL_VERSION}/openal-soft-${OPENAL_VERSION}.tar.bz2)
|
||||
set(OPENAL_HASH 58a73698288d2787451b61f8f4431513)
|
||||
set(OPENAL_HASH_TYPE MD5)
|
||||
set(OPENAL_FILE openal-soft-${OPENAL_VERSION}.tar.bz2)
|
||||
set(OPENAL_HOMEPAGE https://openal-soft.org/)
|
||||
|
|
|
@ -24,7 +24,7 @@ if(WIN32)
|
|||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/zlib/include/ ${HARVEST_TARGET}/zlib/include/
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${LIBDIR}/zlib/bin/zlib.dll
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${LIBDIR}/zlib/lib/zlib.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/zlib/lib/zlibstatic${LIBEXT} ${LIBDIR}/zlib/lib/zlib${LIBEXT}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/zlib/lib/zlibstatic${LIBEXT} ${LIBDIR}/zlib/lib/zlib${LIBEXT}
|
||||
DEPENDEES install
|
||||
)
|
||||
endif()
|
||||
|
|
|
@ -174,9 +174,9 @@ if(OPENEXR_VERSION VERSION_GREATER_EQUAL "3.0.0")
|
|||
endif()
|
||||
|
||||
if(OPENEXR_VERSION VERSION_GREATER_EQUAL "3.0.0")
|
||||
set(IMATH_LIBRARIES ${IMATH_LIBRARY})
|
||||
set(IMATH_LIBRARIES ${IMATH_LIBRARY})
|
||||
else()
|
||||
set(IMATH_LIBRARIES ${OPENEXR_IMATH_LIBRARY})
|
||||
set(IMATH_LIBRARIES ${OPENEXR_IMATH_LIBRARY})
|
||||
endif()
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set OPENEXR_FOUND to TRUE if
|
||||
|
|
|
@ -555,11 +555,15 @@ endif()
|
|||
|
||||
set(_PYTHON_VERSION "3.11")
|
||||
string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${_PYTHON_VERSION})
|
||||
if(NOT EXISTS ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS})
|
||||
set(_PYTHON_VERSION "3.10")
|
||||
string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${_PYTHON_VERSION})
|
||||
|
||||
# Enable for a short time when bumping to the next Python version.
|
||||
if(FALSE)
|
||||
if(NOT EXISTS ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS})
|
||||
message(FATAL_ERROR "Missing python libraries! Neither 3.11 nor 3.10 are found in ${LIBDIR}/python")
|
||||
set(_PYTHON_VERSION "3.12")
|
||||
string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${_PYTHON_VERSION})
|
||||
if(NOT EXISTS ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS})
|
||||
message(FATAL_ERROR "Missing python libraries! Neither 3.12 nor 3.11 are found in ${LIBDIR}/python")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
|
|
@ -158,12 +158,13 @@ def build_info(
|
|||
del args_orig
|
||||
|
||||
# join args incase they are not.
|
||||
args = ' '.join(args)
|
||||
args = args.replace(" -isystem", " -I")
|
||||
args = args.replace(" -D ", " -D")
|
||||
args = args.replace(" -I ", " -I")
|
||||
args_str = " ".join(args)
|
||||
args_str = args_str.replace(" -isystem", " -I")
|
||||
args_str = args_str.replace(" -D ", " -D")
|
||||
args_str = args_str.replace(" -I ", " -I")
|
||||
|
||||
args = shlex.split(args)
|
||||
args = shlex.split(args_str)
|
||||
del args_str
|
||||
# end
|
||||
|
||||
# remove compiler
|
||||
|
|
|
@ -26,14 +26,9 @@ function(blender_test_set_envvars testname envvars_list)
|
|||
|
||||
if(NOT CMAKE_BUILD_TYPE MATCHES "Release")
|
||||
if(WITH_COMPILER_ASAN)
|
||||
# Don't fail tests on leaks since these often happen in external libraries that we can't fix.
|
||||
# FIXME This is a 'nuke solution', no xSAN errors will ever fail tests. Needs more refined handling,
|
||||
# see https://projects.blender.org/blender/blender/pulls/116635 .
|
||||
set(_lsan_options "LSAN_OPTIONS=exitcode=0")
|
||||
set(_lsan_options "LSAN_OPTIONS=print_suppressions=false:suppressions=${CMAKE_SOURCE_DIR}/tools/config/analysis/lsan.supp")
|
||||
# FIXME That `allocator_may_return_null=true` ASAN option is only needed for the `guardedalloc` test,
|
||||
# would be nice to allow tests definition to pass extra envvars better.
|
||||
# NOTE: This is needed for Mac builds currently, on Linux the `exitcode=0` option passed above to LSAN
|
||||
# also seems to silence reports from ASAN.
|
||||
set(_asan_options "ASAN_OPTIONS=allocator_may_return_null=true")
|
||||
if(DEFINED ENV{LSAN_OPTIONS})
|
||||
set(_lsan_options "${_lsan_options}:$ENV{LSAN_OPTIONS}")
|
||||
|
@ -54,7 +49,10 @@ macro(blender_src_gtest_ex)
|
|||
set(options)
|
||||
set(oneValueArgs NAME)
|
||||
set(multiValueArgs SRC EXTRA_LIBS COMMAND_ARGS)
|
||||
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
|
||||
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
unset(options)
|
||||
unset(oneValueArgs)
|
||||
unset(multiValueArgs)
|
||||
|
||||
set(TARGET_NAME ${ARG_NAME}_test)
|
||||
get_property(_current_include_directories
|
||||
|
@ -259,7 +257,10 @@ function(blender_add_test_executable_impl
|
|||
)
|
||||
|
||||
set(oneValueArgs ADD_CTESTS DISCOVER_TESTS)
|
||||
set(multiValueArgs)
|
||||
cmake_parse_arguments(ARGS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
unset(oneValueArgs)
|
||||
unset(multiValueArgs)
|
||||
|
||||
add_cc_flags_custom_test(${name} PARENT_SCOPE)
|
||||
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
"""
|
||||
Get the property associated with a hovered button.
|
||||
Returns a tuple of the datablock, data path to the property, and array index.
|
||||
Returns a tuple of the data-block, data path to the property, and array index.
|
||||
|
||||
.. note::
|
||||
|
||||
When the property doesn't have an associated :class:`bpy.types.ID` non-ID data may be returned.
|
||||
This may occur when accessing windowing data, for example, operator properties.
|
||||
"""
|
||||
|
||||
# Example inserting keyframe for the hovered property.
|
||||
|
|
|
@ -1217,7 +1217,7 @@ context_type_map = {
|
|||
"particle_settings": ("ParticleSettings", False),
|
||||
"particle_system": ("ParticleSystem", False),
|
||||
"particle_system_editable": ("ParticleSystem", False),
|
||||
"property": ("(:class:`bpy.types.ID`, :class:`string`, :class:`int`)", False),
|
||||
"property": ("(:class:`bpy.types.AnyType`, :class:`string`, :class:`int`)", False),
|
||||
"pointcloud": ("PointCloud", False),
|
||||
"pose_bone": ("PoseBone", False),
|
||||
"pose_object": ("Object", False),
|
||||
|
@ -1247,6 +1247,7 @@ context_type_map = {
|
|||
"soft_body": ("SoftBodyModifier", False),
|
||||
"speaker": ("Speaker", False),
|
||||
"texture": ("Texture", False),
|
||||
"texture_node": ("Node", False),
|
||||
"texture_slot": ("TextureSlot", False),
|
||||
"texture_user": ("ID", False),
|
||||
"texture_user_property": ("Property", False),
|
||||
|
|
|
@ -16,7 +16,7 @@ from bpy.props import (
|
|||
)
|
||||
from bpy.app.translations import (
|
||||
contexts as i18n_contexts,
|
||||
pgettext_iface as iface_
|
||||
pgettext_rpt as rpt_
|
||||
)
|
||||
|
||||
from math import pi
|
||||
|
@ -1602,50 +1602,62 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
|||
|
||||
if not found_device:
|
||||
col = box.column(align=True)
|
||||
col.label(text="No compatible GPUs found for Cycles", icon='INFO')
|
||||
col.label(text=rpt_("No compatible GPUs found for Cycles"), icon='INFO', translate=False)
|
||||
|
||||
if device_type == 'CUDA':
|
||||
compute_capability = "3.0"
|
||||
col.label(text=iface_("Requires NVIDIA GPU with compute capability %s") % compute_capability,
|
||||
col.label(text=rpt_("Requires NVIDIA GPU with compute capability %s") % compute_capability,
|
||||
icon='BLANK1', translate=False)
|
||||
elif device_type == 'OPTIX':
|
||||
compute_capability = "5.0"
|
||||
driver_version = "470"
|
||||
col.label(text=iface_("Requires NVIDIA GPU with compute capability %s") % compute_capability,
|
||||
col.label(text=rpt_("Requires NVIDIA GPU with compute capability %s") % compute_capability,
|
||||
icon='BLANK1', translate=False)
|
||||
col.label(text=iface_("and NVIDIA driver version %s or newer") % driver_version,
|
||||
col.label(text=rpt_("and NVIDIA driver version %s or newer") % driver_version,
|
||||
icon='BLANK1', translate=False)
|
||||
elif device_type == 'HIP':
|
||||
import sys
|
||||
if sys.platform[:3] == "win":
|
||||
driver_version = "21.Q4"
|
||||
col.label(text="Requires AMD GPU with Vega or RDNA architecture", icon='BLANK1')
|
||||
col.label(text=iface_("and AMD Radeon Pro %s driver or newer") % driver_version,
|
||||
col.label(
|
||||
text=rpt_("Requires AMD GPU with Vega or RDNA architecture"),
|
||||
icon='BLANK1',
|
||||
translate=False)
|
||||
col.label(text=rpt_("and AMD Radeon Pro %s driver or newer") % driver_version,
|
||||
icon='BLANK1', translate=False)
|
||||
elif sys.platform.startswith("linux"):
|
||||
driver_version = "22.10"
|
||||
col.label(text="Requires AMD GPU with Vega or RDNA architecture", icon='BLANK1')
|
||||
col.label(text=iface_("and AMD driver version %s or newer") % driver_version, icon='BLANK1',
|
||||
col.label(
|
||||
text=rpt_("Requires AMD GPU with Vega or RDNA architecture"),
|
||||
icon='BLANK1',
|
||||
translate=False)
|
||||
col.label(text=rpt_("and AMD driver version %s or newer") % driver_version, icon='BLANK1',
|
||||
translate=False)
|
||||
elif device_type == 'ONEAPI':
|
||||
import sys
|
||||
if sys.platform.startswith("win"):
|
||||
driver_version = "XX.X.101.4824"
|
||||
col.label(text="Requires Intel GPU with Xe-HPG architecture", icon='BLANK1')
|
||||
col.label(text=iface_("and Windows driver version %s or newer") % driver_version,
|
||||
col.label(text=rpt_("Requires Intel GPU with Xe-HPG architecture"), icon='BLANK1', translate=False)
|
||||
col.label(text=rpt_("and Windows driver version %s or newer") % driver_version,
|
||||
icon='BLANK1', translate=False)
|
||||
elif sys.platform.startswith("linux"):
|
||||
driver_version = "XX.XX.25812.14"
|
||||
col.label(text="Requires Intel GPU with Xe-HPG architecture and", icon='BLANK1')
|
||||
col.label(text=" - intel-level-zero-gpu or intel-compute-runtime version", icon='BLANK1')
|
||||
col.label(text=iface_(" %s or newer") % driver_version, icon='BLANK1', translate=False)
|
||||
col.label(text=" - oneAPI Level-Zero Loader", icon='BLANK1')
|
||||
col.label(
|
||||
text=rpt_("Requires Intel GPU with Xe-HPG architecture and"),
|
||||
icon='BLANK1',
|
||||
translate=False)
|
||||
col.label(
|
||||
text=rpt_(" - intel-level-zero-gpu or intel-compute-runtime version"),
|
||||
icon='BLANK1',
|
||||
translate=False)
|
||||
col.label(text=rpt_(" %s or newer") % driver_version, icon='BLANK1', translate=False)
|
||||
col.label(text=rpt_(" - oneAPI Level-Zero Loader"), icon='BLANK1', translate=False)
|
||||
elif device_type == 'METAL':
|
||||
silicon_mac_version = "12.2"
|
||||
amd_mac_version = "12.3"
|
||||
col.label(text=iface_("Requires Apple Silicon with macOS %s or newer") % silicon_mac_version,
|
||||
col.label(text=rpt_("Requires Apple Silicon with macOS %s or newer") % silicon_mac_version,
|
||||
icon='BLANK1', translate=False)
|
||||
col.label(text=iface_("or AMD with macOS %s or newer") % amd_mac_version, icon='BLANK1',
|
||||
col.label(text=rpt_("or AMD with macOS %s or newer") % amd_mac_version, icon='BLANK1',
|
||||
translate=False)
|
||||
return
|
||||
|
||||
|
|
|
@ -90,40 +90,44 @@ def get_device_type(context):
|
|||
return context.preferences.addons[__package__].preferences.compute_device_type
|
||||
|
||||
|
||||
def backend_has_active_gpu(context):
|
||||
return context.preferences.addons[__package__].preferences.has_active_device()
|
||||
|
||||
|
||||
def use_cpu(context):
|
||||
cscene = context.scene.cycles
|
||||
|
||||
return (get_device_type(context) == 'NONE' or cscene.device == 'CPU')
|
||||
return (get_device_type(context) == 'NONE' or cscene.device == 'CPU' or not backend_has_active_gpu(context))
|
||||
|
||||
|
||||
def use_metal(context):
|
||||
cscene = context.scene.cycles
|
||||
|
||||
return (get_device_type(context) == 'METAL' and cscene.device == 'GPU')
|
||||
return (get_device_type(context) == 'METAL' and cscene.device == 'GPU' and backend_has_active_gpu(context))
|
||||
|
||||
|
||||
def use_cuda(context):
|
||||
cscene = context.scene.cycles
|
||||
|
||||
return (get_device_type(context) == 'CUDA' and cscene.device == 'GPU')
|
||||
return (get_device_type(context) == 'CUDA' and cscene.device == 'GPU' and backend_has_active_gpu(context))
|
||||
|
||||
|
||||
def use_hip(context):
|
||||
cscene = context.scene.cycles
|
||||
|
||||
return (get_device_type(context) == 'HIP' and cscene.device == 'GPU')
|
||||
return (get_device_type(context) == 'HIP' and cscene.device == 'GPU' and backend_has_active_gpu(context))
|
||||
|
||||
|
||||
def use_optix(context):
|
||||
cscene = context.scene.cycles
|
||||
|
||||
return (get_device_type(context) == 'OPTIX' and cscene.device == 'GPU')
|
||||
return (get_device_type(context) == 'OPTIX' and cscene.device == 'GPU' and backend_has_active_gpu(context))
|
||||
|
||||
|
||||
def use_oneapi(context):
|
||||
cscene = context.scene.cycles
|
||||
|
||||
return (get_device_type(context) == 'ONEAPI' and cscene.device == 'GPU')
|
||||
return (get_device_type(context) == 'ONEAPI' and cscene.device == 'GPU' and backend_has_active_gpu(context))
|
||||
|
||||
|
||||
def use_multi_device(context):
|
||||
|
@ -137,7 +141,7 @@ def show_device_active(context):
|
|||
cscene = context.scene.cycles
|
||||
if cscene.device != 'GPU':
|
||||
return True
|
||||
return context.preferences.addons[__package__].preferences.has_active_device()
|
||||
return backend_has_active_gpu(context)
|
||||
|
||||
|
||||
def get_effective_preview_denoiser(context):
|
||||
|
@ -2441,10 +2445,11 @@ def draw_device(self, context):
|
|||
|
||||
from . import engine
|
||||
if engine.with_osl() and (
|
||||
use_cpu(context) or
|
||||
(use_optix(context) and (engine.osl_version()[1] >= 13 or engine.osl_version()[0] > 1))
|
||||
):
|
||||
col.prop(cscene, "shading_system")
|
||||
use_cpu(context) or (
|
||||
use_optix(context) and (
|
||||
engine.osl_version()[1] >= 13 or engine.osl_version()[0] > 1))):
|
||||
osl_col = layout.column()
|
||||
osl_col.prop(cscene, "shading_system")
|
||||
|
||||
|
||||
def draw_pause(self, context):
|
||||
|
|
|
@ -683,12 +683,15 @@ static void fill_generic_attribute(const int num_curves,
|
|||
}
|
||||
}
|
||||
|
||||
static void attr_create_motion(Hair *hair,
|
||||
const blender::Span<blender::float3> src,
|
||||
const float motion_scale)
|
||||
static void attr_create_motion_from_velocity(Hair *hair,
|
||||
const blender::Span<blender::float3> src,
|
||||
const float motion_scale)
|
||||
{
|
||||
const int num_curve_keys = hair->get_curve_keys().size();
|
||||
|
||||
/* Override motion steps to fixed number. */
|
||||
hair->set_motion_steps(3);
|
||||
|
||||
/* Find or add attribute */
|
||||
float3 *P = &hair->get_curve_keys()[0];
|
||||
Attribute *attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
||||
|
@ -732,7 +735,7 @@ static void attr_create_generic(Scene *scene,
|
|||
if (need_motion && name == u_velocity) {
|
||||
const blender::VArraySpan b_attr = *b_attributes.lookup<blender::float3>(
|
||||
id, blender::bke::AttrDomain::Point);
|
||||
attr_create_motion(hair, b_attr, motion_scale);
|
||||
attr_create_motion_from_velocity(hair, b_attr, motion_scale);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -237,12 +237,15 @@ static void mikk_compute_tangents(
|
|||
}
|
||||
}
|
||||
|
||||
static void attr_create_motion(Mesh *mesh,
|
||||
const blender::Span<blender::float3> b_attr,
|
||||
const float motion_scale)
|
||||
static void attr_create_motion_from_velocity(Mesh *mesh,
|
||||
const blender::Span<blender::float3> b_attr,
|
||||
const float motion_scale)
|
||||
{
|
||||
const int numverts = mesh->get_verts().size();
|
||||
|
||||
/* Override motion steps to fixed number. */
|
||||
mesh->set_motion_steps(3);
|
||||
|
||||
/* Find or add attribute */
|
||||
float3 *P = &mesh->get_verts()[0];
|
||||
Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
||||
|
@ -289,7 +292,7 @@ static void attr_create_generic(Scene *scene,
|
|||
if (need_motion && name == u_velocity) {
|
||||
const blender::VArraySpan b_attribute = *b_attributes.lookup<blender::float3>(
|
||||
id, blender::bke::AttrDomain::Point);
|
||||
attr_create_motion(mesh, b_attribute, motion_scale);
|
||||
attr_create_motion_from_velocity(mesh, b_attribute, motion_scale);
|
||||
}
|
||||
|
||||
if (!(mesh->need_attribute(scene, name) ||
|
||||
|
|
|
@ -133,7 +133,12 @@ void BlenderSync::sync_object_motion_init(BL::Object &b_parent, BL::Object &b_ob
|
|||
}
|
||||
|
||||
geom->set_use_motion_blur(use_motion_blur);
|
||||
geom->set_motion_steps(motion_steps);
|
||||
|
||||
if (!geom->has_motion_blur()) {
|
||||
/* Only set motion steps if geometry doesn't already have
|
||||
* motion blur from a velocity attribute. */
|
||||
geom->set_motion_steps(motion_steps);
|
||||
}
|
||||
|
||||
motion.resize(motion_steps, transform_empty());
|
||||
|
||||
|
|
|
@ -18,16 +18,19 @@
|
|||
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_attribute_math.hh"
|
||||
#include "BKE_pointcloud.h"
|
||||
#include "BKE_pointcloud.hh"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
static void attr_create_motion(PointCloud *pointcloud,
|
||||
const blender::Span<blender::float3> b_attribute,
|
||||
const float motion_scale)
|
||||
static void attr_create_motion_from_velocity(PointCloud *pointcloud,
|
||||
const blender::Span<blender::float3> b_attribute,
|
||||
const float motion_scale)
|
||||
{
|
||||
const int num_points = pointcloud->get_points().size();
|
||||
|
||||
/* Override motion steps to fixed number. */
|
||||
pointcloud->set_motion_steps(3);
|
||||
|
||||
/* Find or add attribute */
|
||||
float3 *P = pointcloud->get_points().data();
|
||||
float *radius = pointcloud->get_radius().data();
|
||||
|
@ -69,7 +72,7 @@ static void copy_attributes(PointCloud *pointcloud,
|
|||
|
||||
if (need_motion && name == u_velocity) {
|
||||
const blender::VArraySpan b_attr = *b_attributes.lookup<blender::float3>(id);
|
||||
attr_create_motion(pointcloud, b_attr, motion_scale);
|
||||
attr_create_motion_from_velocity(pointcloud, b_attr, motion_scale);
|
||||
}
|
||||
|
||||
if (attributes.find(name)) {
|
||||
|
|
|
@ -231,7 +231,6 @@ class BlenderVolumeLoader : public VDBImageLoader {
|
|||
if (b_volume_grid.name() == grid_name) {
|
||||
const auto *volume_grid = static_cast<const blender::bke::VolumeGridData *>(
|
||||
b_volume_grid.ptr.data);
|
||||
tree_access_token = volume_grid->tree_access_token();
|
||||
grid = volume_grid->grid_ptr(tree_access_token);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -159,12 +159,6 @@ void device_hip_info(vector<DeviceInfo> &devices)
|
|||
info.has_nanovdb = true;
|
||||
info.has_light_tree = true;
|
||||
info.has_mnee = true;
|
||||
info.denoisers = 0;
|
||||
# if defined(WITH_OPENIMAGEDENOISE)
|
||||
if (OIDNDenoiserGPU::is_device_supported(info)) {
|
||||
info.denoisers |= DENOISER_OPENIMAGEDENOISE;
|
||||
}
|
||||
# endif
|
||||
|
||||
info.has_gpu_queue = true;
|
||||
/* Check if the device has P2P access to any other device in the system. */
|
||||
|
@ -188,6 +182,13 @@ void device_hip_info(vector<DeviceInfo> &devices)
|
|||
(unsigned int)pci_location[1],
|
||||
(unsigned int)pci_location[2]);
|
||||
|
||||
info.denoisers = 0;
|
||||
# if defined(WITH_OPENIMAGEDENOISE)
|
||||
if (OIDNDenoiserGPU::is_device_supported(info)) {
|
||||
info.denoisers |= DENOISER_OPENIMAGEDENOISE;
|
||||
}
|
||||
# endif
|
||||
|
||||
/* If device has a kernel timeout and no compute preemption, we assume
|
||||
* it is connected to a display and will freeze the display while doing
|
||||
* computations. */
|
||||
|
|
|
@ -495,12 +495,13 @@ ccl_device_forceinline int integrate_surface_bsdf_bssrdf_bounce(
|
|||
INTEGRATOR_STATE_WRITE(state, path, mis_origin_n) = sc->N;
|
||||
INTEGRATOR_STATE_WRITE(state, path, min_ray_pdf) = fminf(
|
||||
unguided_bsdf_pdf, INTEGRATOR_STATE(state, path, min_ray_pdf));
|
||||
}
|
||||
|
||||
#ifdef __LIGHT_LINKING__
|
||||
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_LINKING) {
|
||||
INTEGRATOR_STATE_WRITE(state, path, mis_ray_object) = sd->object;
|
||||
}
|
||||
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_LINKING) {
|
||||
INTEGRATOR_STATE_WRITE(state, path, mis_ray_object) = sd->object;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
path_state_next(kg, state, label, sd->flag);
|
||||
|
||||
|
|
|
@ -425,7 +425,7 @@ struct GWL_Cursor {
|
|||
* The size of the cursor (when looking up a cursor theme).
|
||||
* This must be scaled by the maximum output scale when passing to wl_cursor_theme_load.
|
||||
* See #update_cursor_scale.
|
||||
* */
|
||||
*/
|
||||
int theme_size = 0;
|
||||
int custom_scale = 1;
|
||||
};
|
||||
|
@ -1327,7 +1327,7 @@ struct GWL_Display {
|
|||
};
|
||||
|
||||
/**
|
||||
* Free the #GWL_Display and it's related members.
|
||||
* Free the #GWL_Display and its related members.
|
||||
*
|
||||
* \note This may run on a partially initialized struct,
|
||||
* so it can't be assumed all members are set.
|
||||
|
@ -2086,6 +2086,13 @@ static int memfd_create_sealed(const char *name)
|
|||
#endif /* !HAVE_MEMFD_CREATE */
|
||||
}
|
||||
|
||||
#if defined(WITH_GHOST_WAYLAND_LIBDECOR) && defined(WITH_VULKAN_BACKEND)
|
||||
int memfd_create_sealed_for_vulkan_hack(const char *name)
|
||||
{
|
||||
return memfd_create_sealed(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
enum {
|
||||
GWL_IOR_READ = 1 << 0,
|
||||
GWL_IOR_WRITE = 1 << 1,
|
||||
|
|
|
@ -88,6 +88,13 @@ bool ghost_wl_dynload_libraries_init();
|
|||
void ghost_wl_dynload_libraries_exit();
|
||||
#endif
|
||||
|
||||
#if defined(WITH_GHOST_WAYLAND_LIBDECOR) && defined(WITH_VULKAN_BACKEND)
|
||||
/**
|
||||
* Needed for temporary buffer creation.
|
||||
*/
|
||||
int memfd_create_sealed_for_vulkan_hack(const char *name);
|
||||
#endif
|
||||
|
||||
struct GWL_Output {
|
||||
|
||||
/** Wayland core types. */
|
||||
|
|
|
@ -107,7 +107,6 @@ GHOST_SystemX11::GHOST_SystemX11()
|
|||
: GHOST_System(),
|
||||
m_xkb_descr(nullptr),
|
||||
m_start_time(0),
|
||||
m_start_time_monotonic(0),
|
||||
m_keyboard_vector{0},
|
||||
#ifdef WITH_X11_XINPUT
|
||||
m_last_key_time(0),
|
||||
|
@ -176,22 +175,12 @@ GHOST_SystemX11::GHOST_SystemX11()
|
|||
m_last_release_keycode = 0;
|
||||
m_last_release_time = 0;
|
||||
|
||||
/* Compute the initial times. */
|
||||
{
|
||||
timeval tv;
|
||||
if (gettimeofday(&tv, nullptr) != 0) {
|
||||
GHOST_ASSERT(false, "Could not instantiate timer!");
|
||||
}
|
||||
/* Taking care not to overflow the `tv.tv_sec * 1000`. */
|
||||
m_start_time = uint64_t(tv.tv_sec) * 1000 + tv.tv_usec / 1000;
|
||||
}
|
||||
|
||||
{
|
||||
timespec ts = {0, 0};
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
|
||||
GHOST_ASSERT(false, "Could not instantiate monotonic timer!");
|
||||
}
|
||||
m_start_time_monotonic = (uint64_t(ts.tv_sec) * 1000) + uint64_t(ts.tv_nsec / 1000000);
|
||||
m_start_time = (uint64_t(ts.tv_sec) * 1000) + uint64_t(ts.tv_nsec / 1000000);
|
||||
}
|
||||
|
||||
/* Use detectable auto-repeat, mac and windows also do this. */
|
||||
|
@ -283,24 +272,73 @@ GHOST_TSuccess GHOST_SystemX11::init()
|
|||
|
||||
uint64_t GHOST_SystemX11::getMilliSeconds() const
|
||||
{
|
||||
timeval tv;
|
||||
if (gettimeofday(&tv, nullptr) != 0) {
|
||||
GHOST_ASSERT(false, "Could not compute time!");
|
||||
timespec ts = {0, 0};
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
|
||||
GHOST_ASSERT(false, "Could not instantiate monotonic timer!");
|
||||
}
|
||||
|
||||
/* Taking care not to overflow the tv.tv_sec * 1000 */
|
||||
return uint64_t(tv.tv_sec) * 1000 + tv.tv_usec / 1000 - m_start_time;
|
||||
const uint64_t time = (uint64_t(ts.tv_sec) * 1000) + uint64_t(ts.tv_nsec / 1000000);
|
||||
GHOST_ASSERT(m_start_time <= time, "Monotonic time unexpectedly went backwards!");
|
||||
return time - m_start_time;
|
||||
}
|
||||
|
||||
uint64_t GHOST_SystemX11::ms_from_input_time(const Time timestamp) const
|
||||
uint64_t GHOST_SystemX11::ms_from_input_time(Time timestamp) const
|
||||
{
|
||||
GHOST_ASSERT(timestamp >= m_start_time_monotonic, "Invalid time-stamp");
|
||||
/* NOTE(@ideasman42): Return a time compatible with `getMilliSeconds()`,
|
||||
* this is needed as X11 time-stamps use monotonic time.
|
||||
* The X11 implementation *could* use any basis, in practice though we are supporting
|
||||
* XORG/LIBINPUT which uses time-stamps based on the monotonic time,
|
||||
* Needed to resolve failure to detect double-clicking, see: #40009. */
|
||||
return uint64_t(timestamp) - m_start_time_monotonic;
|
||||
|
||||
/* Accumulate time rollover (as well as store the initial delta from `m_start_time`). */
|
||||
static uint64_t timestamp_offset = 0;
|
||||
|
||||
/* The last event time (to detect rollover). */
|
||||
static uint32_t timestamp_prev = 0;
|
||||
/* Causes the X11 time-stamp to be zero based. */
|
||||
static uint32_t timestamp_start = 0;
|
||||
|
||||
static bool is_time_init = false;
|
||||
|
||||
#if 0
|
||||
/* Force rollover after 2 seconds (for testing). */
|
||||
{
|
||||
const uint32_t timestamp_wrap_ms = 2000;
|
||||
static uint32_t timestamp_offset_fake = 0;
|
||||
if (!is_time_init) {
|
||||
timestamp_offset_fake = UINT32_MAX - (timestamp + timestamp_wrap_ms);
|
||||
}
|
||||
timestamp = uint32_t(timestamp + timestamp_offset_fake);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!is_time_init) {
|
||||
/* Store the initial delta in the rollover. */
|
||||
const uint64_t current_time = getMilliSeconds();
|
||||
timestamp_offset = current_time;
|
||||
timestamp_start = timestamp;
|
||||
}
|
||||
|
||||
/* Always remove the start time.
|
||||
* This changes the point where `uint32_t` rolls over, but that's OK. */
|
||||
timestamp = uint32_t(timestamp) - timestamp_start;
|
||||
|
||||
if (!is_time_init) {
|
||||
is_time_init = true;
|
||||
timestamp_prev = timestamp;
|
||||
}
|
||||
|
||||
if (UNLIKELY(timestamp < timestamp_prev)) {
|
||||
/* Only rollover if this is within a reasonable range. */
|
||||
if (UNLIKELY(timestamp_prev - timestamp > UINT32_MAX / 2)) {
|
||||
timestamp_offset += uint64_t(UINT32_MAX) + 1;
|
||||
}
|
||||
}
|
||||
timestamp_prev = timestamp;
|
||||
|
||||
uint64_t timestamp_final = (uint64_t(timestamp) + timestamp_offset);
|
||||
|
||||
return timestamp_final;
|
||||
}
|
||||
|
||||
uint8_t GHOST_SystemX11::getNumDisplays() const
|
||||
|
|
|
@ -348,10 +348,8 @@ class GHOST_SystemX11 : public GHOST_System {
|
|||
/** The vector of windows that need to be updated. */
|
||||
std::vector<GHOST_WindowX11 *> m_dirty_windows;
|
||||
|
||||
/** Start time at initialization. */
|
||||
/** Start time at initialization (using `CLOCK_MONOTONIC`). */
|
||||
uint64_t m_start_time;
|
||||
/** Start time at initialization (using `CLOCK_MONOTONIC`). */
|
||||
uint64_t m_start_time_monotonic;
|
||||
|
||||
/** A vector of keyboard key masks. */
|
||||
char m_keyboard_vector[32];
|
||||
|
|
|
@ -38,6 +38,10 @@
|
|||
# include <wayland_dynload_libdecor.h>
|
||||
# endif
|
||||
# include <libdecor.h>
|
||||
|
||||
# ifdef WITH_VULKAN_BACKEND
|
||||
# include <unistd.h> /* For `ftruncate`. */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Generated by `wayland-scanner`. */
|
||||
|
@ -1769,11 +1773,47 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
|||
|
||||
/* NOTE: LIBDECOR requires the window to be created & configured before the state can be set.
|
||||
* Workaround this by using the underlying `xdg_toplevel` */
|
||||
|
||||
# ifdef WITH_VULKAN_BACKEND
|
||||
/* A dummy buffer is needed for VULKAN & LIBDECOR,
|
||||
* otherwise `decor.initial_configure_seen` and startup locks up. */
|
||||
wl_buffer *dummy_buffer = nullptr;
|
||||
if (window_->ghost_context_type == GHOST_kDrawingContextTypeVulkan) {
|
||||
const uint32_t format = WL_SHM_FORMAT_ARGB8888;
|
||||
const int format_size = 4;
|
||||
const int buffer_size = (window_->frame.size[0] * window_->frame.size[1]) * format_size;
|
||||
const int fd = memfd_create_sealed_for_vulkan_hack("ghost-wl-dummy-buffer");
|
||||
ftruncate(fd, buffer_size);
|
||||
wl_shm *shm = system_->wl_shm_get();
|
||||
wl_shm_pool *pool = wl_shm_create_pool(shm, fd, buffer_size);
|
||||
dummy_buffer = wl_shm_pool_create_buffer(pool,
|
||||
0,
|
||||
window_->frame.size[0],
|
||||
window_->frame.size[1],
|
||||
window_->frame.size[0] * format_size,
|
||||
format);
|
||||
wl_shm_pool_destroy(pool);
|
||||
|
||||
wl_surface_attach(window_->wl.surface, dummy_buffer, 0, 0);
|
||||
wl_surface_damage(window_->wl.surface, 0, 0, window_->frame.size[0], window_->frame.size[1]);
|
||||
wl_surface_commit(window_->wl.surface);
|
||||
::close(fd);
|
||||
}
|
||||
# endif /* WITH_GHOST_WAYLAND_LIBDECOR */
|
||||
|
||||
while (!decor.initial_configure_seen) {
|
||||
wl_display_flush(system->wl_display_get());
|
||||
wl_display_dispatch(system->wl_display_get());
|
||||
}
|
||||
|
||||
# ifdef WITH_VULKAN_BACKEND
|
||||
if (window_->ghost_context_type == GHOST_kDrawingContextTypeVulkan) {
|
||||
wl_surface_attach(window_->wl.surface, nullptr, 0, 0);
|
||||
wl_surface_commit(window_->wl.surface);
|
||||
wl_buffer_destroy(dummy_buffer);
|
||||
}
|
||||
# endif /* WITH_GHOST_WAYLAND_LIBDECOR */
|
||||
|
||||
xdg_toplevel *toplevel = libdecor_frame_get_xdg_toplevel(decor.frame);
|
||||
gwl_window_state_set_for_xdg(toplevel, state, gwl_window_state_get(window_));
|
||||
}
|
||||
|
|
|
@ -593,7 +593,7 @@ MANTA::~MANTA()
|
|||
* with some differences:
|
||||
* - Doesn't touch `sys.modules`, use #manta_python_main_module_activate instead.
|
||||
* - Returns the module instead of the modules `dict`.
|
||||
* */
|
||||
*/
|
||||
static PyObject *manta_python_main_module_create(const char *filename)
|
||||
{
|
||||
PyObject *builtins = PyEval_GetBuiltins();
|
||||
|
|
|
@ -46,8 +46,8 @@
|
|||
id="namedview34335"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.4142136"
|
||||
inkscape:cx="229.45615"
|
||||
inkscape:cy="319.96582"
|
||||
inkscape:cx="268.34702"
|
||||
inkscape:cy="242.89117"
|
||||
inkscape:window-x="1912"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
|
@ -19237,6 +19237,47 @@
|
|||
fill="#ffffff"
|
||||
id="path5-2" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(189.03819,-63.105705)"
|
||||
id="g37415-7"
|
||||
inkscape:label="DA-14"
|
||||
style="display:inline;enable-background:new">
|
||||
<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;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new"
|
||||
d="m 286,622 c -2.7555,0 -5,2.2445 -5,5 0,2.7555 2.2445,5 5,5 2.7555,0 5,-2.2445 5,-5 0,-2.7555 -2.2445,-5 -5,-5 z"
|
||||
id="circle13982-8"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="sssss" />
|
||||
<rect
|
||||
style="display:inline;fill:none;stroke-width:1.627;enable-background:new"
|
||||
id="rect37443-8-9"
|
||||
width="18"
|
||||
height="18"
|
||||
x="276.99994"
|
||||
y="-636"
|
||||
transform="scale(1,-1)"
|
||||
inkscape:label="frame" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(189.03819,-63.105705)"
|
||||
id="g37418-6"
|
||||
inkscape:label="DA-13"
|
||||
style="display:inline;enable-background:new">
|
||||
<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 265,622 c -2.7555,0 -5,2.2445 -5,5 0,2.7555 2.2445,5 5,5 2.7555,0 5,-2.2445 5,-5 0,-2.7555 -2.2445,-5 -5,-5 z m 0,1 c 2.21506,0 4,1.78494 4,4 0,2.21506 -1.78494,4 -4,4 -2.21506,0 -4,-1.78494 -4,-4 0,-2.21506 1.78494,-4 4,-4 z"
|
||||
id="path13966-3"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
style="display:inline;fill:none;stroke-width:1.627;enable-background:new"
|
||||
id="rect21004-5-8-0-9-3"
|
||||
width="18"
|
||||
height="18"
|
||||
x="255.99994"
|
||||
y="-636"
|
||||
transform="scale(1,-1)"
|
||||
inkscape:label="frame" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
|
|
Before Width: | Height: | Size: 2.6 MiB After Width: | Height: | Size: 2.6 MiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -573,6 +573,7 @@ def dump_py_messages_from_files(msgs, reports, files, settings):
|
|||
("pgettext", ("_",)),
|
||||
("pgettext_iface", ("iface_",)),
|
||||
("pgettext_tip", ("tip_",)),
|
||||
("pgettext_rpt", ("rpt_",)),
|
||||
("pgettext_data", ("data_",)),
|
||||
)
|
||||
pgettext_variants_args = {"msgid": (0, {"msgctxt": 1})}
|
||||
|
|
|
@ -243,14 +243,15 @@ _ctxt_re = _ctxt_re_gen("")
|
|||
_msg_re = r"(?P<msg_raw>" + _str_whole_re.format(_="_msg") + r")"
|
||||
PYGETTEXT_KEYWORDS = (() +
|
||||
tuple((r"{}\(\s*" + _msg_re + r"\s*\)").format(it)
|
||||
for it in ("IFACE_", "TIP_", "DATA_", "N_")) +
|
||||
for it in ("IFACE_", "TIP_", "RPT_", "DATA_", "N_")) +
|
||||
|
||||
tuple((r"{}\(\s*" + _ctxt_re + r"\s*,\s*" + _msg_re + r"\s*\)").format(it)
|
||||
for it in ("CTX_IFACE_", "CTX_TIP_", "CTX_DATA_", "CTX_N_")) +
|
||||
for it in ("CTX_IFACE_", "CTX_TIP_", "CTX_RPT_", "CTX_DATA_", "CTX_N_")) +
|
||||
|
||||
tuple(("{}\\((?:[^\"',]+,){{1,2}}\\s*" + _msg_re + r"\s*(?:\)|,)").format(it)
|
||||
for it in ("BKE_report", "BKE_reportf", "BKE_reports_prepend", "BKE_reports_prependf",
|
||||
"CTX_wm_operator_poll_msg_set", "WM_report", "WM_reportf")) +
|
||||
"CTX_wm_operator_poll_msg_set", "WM_report", "WM_reportf",
|
||||
"UI_but_disable")) +
|
||||
|
||||
# bmesh operator errors
|
||||
tuple(("{}\\((?:[^\"',]+,){{3}}\\s*" + _msg_re + r"\s*\)").format(it)
|
||||
|
|
|
@ -4586,6 +4586,8 @@ def km_grease_pencil_paint(_params):
|
|||
|
||||
# Show/hide
|
||||
*_template_items_hide_reveal_actions("grease_pencil.layer_hide", "grease_pencil.layer_reveal"),
|
||||
|
||||
("paint.sample_color", {"type": 'X', "value": 'PRESS', "shift": True}, None),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
@ -6077,6 +6079,7 @@ def km_edit_curves(params):
|
|||
("curves.set_selection_domain", {"type": 'TWO', "value": 'PRESS'}, {"properties": [("domain", 'CURVE')]}),
|
||||
("curves.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
|
||||
*_template_items_select_actions(params, "curves.select_all"),
|
||||
("curves.extrude_move", {"type": 'E', "value": 'PRESS'}, None),
|
||||
("curves.select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None),
|
||||
("curves.delete", {"type": 'X', "value": 'PRESS'}, None),
|
||||
("curves.delete", {"type": 'DEL', "value": 'PRESS'}, None),
|
||||
|
|
|
@ -14,7 +14,7 @@ from bpy.props import (
|
|||
StringProperty,
|
||||
)
|
||||
from bpy.app.translations import (
|
||||
pgettext_tip as tip_,
|
||||
pgettext_rpt as rpt_,
|
||||
contexts as i18n_contexts,
|
||||
)
|
||||
|
||||
|
@ -114,7 +114,7 @@ class ANIM_OT_keying_set_export(Operator):
|
|||
if not found:
|
||||
self.report(
|
||||
{'WARN'},
|
||||
tip_("Could not find material or light using Shader Node Tree - %s") %
|
||||
rpt_("Could not find material or light using Shader Node Tree - %s") %
|
||||
(ksp.id))
|
||||
elif ksp.id.bl_rna.identifier.startswith("CompositorNodeTree"):
|
||||
# Find compositor node-tree using this node tree.
|
||||
|
@ -123,7 +123,7 @@ class ANIM_OT_keying_set_export(Operator):
|
|||
id_bpy_path = "bpy.data.scenes[\"%s\"].node_tree" % (scene.name)
|
||||
break
|
||||
else:
|
||||
self.report({'WARN'}, tip_("Could not find scene using Compositor Node Tree - %s") % (ksp.id))
|
||||
self.report({'WARN'}, rpt_("Could not find scene using Compositor Node Tree - %s") % (ksp.id))
|
||||
elif ksp.id.bl_rna.name == "Key":
|
||||
# "keys" conflicts with a Python keyword, hence the simple solution won't work
|
||||
id_bpy_path = "bpy.data.shape_keys[\"%s\"]" % (ksp.id.name)
|
||||
|
@ -358,7 +358,7 @@ class ClearUselessActions(Operator):
|
|||
action.user_clear()
|
||||
removed += 1
|
||||
|
||||
self.report({'INFO'}, tip_("Removed %d empty and/or fake-user only Actions")
|
||||
self.report({'INFO'}, rpt_("Removed %d empty and/or fake-user only Actions")
|
||||
% removed)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
@ -443,7 +443,7 @@ class UpdateAnimatedTransformConstraint(Operator):
|
|||
print(log)
|
||||
text = bpy.data.texts.new("UpdateAnimatedTransformConstraint Report")
|
||||
text.from_string(log)
|
||||
self.report({'INFO'}, tip_("Complete report available on '%s' text datablock") % text.name)
|
||||
self.report({'INFO'}, rpt_("Complete report available on '%s' text datablock") % text.name)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import bpy
|
|||
from bpy.types import Operator
|
||||
from bpy.app.translations import (
|
||||
pgettext_data as data_,
|
||||
pgettext_tip as tip_,
|
||||
pgettext_rpt as rpt_,
|
||||
)
|
||||
|
||||
|
||||
|
@ -125,7 +125,7 @@ class ASSET_OT_open_containing_blend_file(Operator):
|
|||
return {'RUNNING_MODAL'}
|
||||
|
||||
if returncode:
|
||||
self.report({'WARNING'}, tip_("Blender sub-process exited with error code %d") % returncode)
|
||||
self.report({'WARNING'}, rpt_("Blender sub-process exited with error code %d") % returncode)
|
||||
|
||||
if bpy.ops.asset.library_refresh.poll():
|
||||
bpy.ops.asset.library_refresh()
|
||||
|
|
|
@ -9,7 +9,7 @@ from mathutils import (
|
|||
Vector,
|
||||
Matrix,
|
||||
)
|
||||
from bpy.app.translations import pgettext_tip as tip_
|
||||
from bpy.app.translations import pgettext_rpt as rpt_
|
||||
|
||||
|
||||
def CLIP_spaces_walk(context, all_screens, tarea, tspace, callback, *args):
|
||||
|
@ -197,7 +197,7 @@ class CLIP_OT_filter_tracks(Operator):
|
|||
|
||||
def execute(self, context):
|
||||
num_tracks = self._filter_values(context, self.track_threshold)
|
||||
self.report({'INFO'}, tip_("Identified %d problematic tracks") % num_tracks)
|
||||
self.report({'INFO'}, rpt_("Identified %d problematic tracks") % num_tracks)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ from bpy.props import (
|
|||
CollectionProperty,
|
||||
StringProperty,
|
||||
)
|
||||
from bpy.app.translations import pgettext_tip as tip_
|
||||
from bpy.app.translations import pgettext_rpt as rpt_
|
||||
|
||||
# ########## Datablock previews... ##########
|
||||
|
||||
|
@ -126,7 +126,7 @@ class WM_OT_previews_batch_generate(Operator):
|
|||
if not self.use_backups:
|
||||
cmd.append("--no_backups")
|
||||
if subprocess.call(cmd):
|
||||
self.report({'ERROR'}, tip_("Previews generation process failed for file '%s'!") % blen_path)
|
||||
self.report({'ERROR'}, rpt_("Previews generation process failed for file '%s'!") % blen_path)
|
||||
context.window_manager.progress_end()
|
||||
return {'CANCELLED'}
|
||||
context.window_manager.progress_update(i + 1)
|
||||
|
@ -237,7 +237,7 @@ class WM_OT_previews_batch_clear(Operator):
|
|||
if not self.use_backups:
|
||||
cmd.append("--no_backups")
|
||||
if subprocess.call(cmd):
|
||||
self.report({'ERROR'}, tip_("Previews clear process failed for file '%s'!") % blen_path)
|
||||
self.report({'ERROR'}, rpt_("Previews clear process failed for file '%s'!") % blen_path)
|
||||
context.window_manager.progress_end()
|
||||
return {'CANCELLED'}
|
||||
context.window_manager.progress_update(i + 1)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
import bpy
|
||||
from bpy.types import Operator
|
||||
from bpy.props import StringProperty
|
||||
from bpy.app.translations import pgettext_tip as tip_
|
||||
from bpy.app.translations import pgettext_rpt as rpt_
|
||||
|
||||
|
||||
class EditExternally(Operator):
|
||||
|
@ -55,7 +55,7 @@ class EditExternally(Operator):
|
|||
|
||||
if not os.path.exists(filepath) or not os.path.isfile(filepath):
|
||||
self.report({'ERROR'},
|
||||
tip_("Image path %r not found, image may be packed or "
|
||||
rpt_("Image path %r not found, image may be packed or "
|
||||
"unsaved") % filepath)
|
||||
return {'CANCELLED'}
|
||||
|
||||
|
@ -182,7 +182,7 @@ class ProjectApply(Operator):
|
|||
image_name = ProjectEdit._proj_hack[0] # TODO, deal with this nicer
|
||||
image = bpy.data.images.get((image_name, None))
|
||||
if image is None:
|
||||
self.report({'ERROR'}, tip_("Could not find image '%s'") % image_name)
|
||||
self.report({'ERROR'}, rpt_("Could not find image '%s'") % image_name)
|
||||
return {'CANCELLED'}
|
||||
|
||||
image.reload()
|
||||
|
|
|
@ -9,7 +9,7 @@ from bpy.props import (
|
|||
EnumProperty,
|
||||
IntProperty,
|
||||
)
|
||||
from bpy.app.translations import pgettext_tip as tip_
|
||||
from bpy.app.translations import pgettext_rpt as rpt_
|
||||
|
||||
|
||||
class MeshMirrorUV(Operator):
|
||||
|
@ -169,18 +169,18 @@ class MeshMirrorUV(Operator):
|
|||
|
||||
if total_duplicates and total_no_active_UV:
|
||||
self.report({'WARNING'},
|
||||
tip_("%d mesh(es) with no active UV layer, "
|
||||
rpt_("%d mesh(es) with no active UV layer, "
|
||||
"%d duplicates found in %d mesh(es), mirror may be incomplete")
|
||||
% (total_no_active_UV,
|
||||
total_duplicates,
|
||||
meshes_with_duplicates))
|
||||
elif total_no_active_UV:
|
||||
self.report({'WARNING'},
|
||||
tip_("%d mesh(es) with no active UV layer")
|
||||
rpt_("%d mesh(es) with no active UV layer")
|
||||
% (total_no_active_UV,))
|
||||
elif total_duplicates:
|
||||
self.report({'WARNING'},
|
||||
tip_("%d duplicates found in %d mesh(es), mirror may be incomplete")
|
||||
rpt_("%d duplicates found in %d mesh(es), mirror may be incomplete")
|
||||
% (total_duplicates, meshes_with_duplicates))
|
||||
|
||||
return {'FINISHED'}
|
||||
|
|
|
@ -20,7 +20,10 @@ from mathutils import (
|
|||
Vector,
|
||||
)
|
||||
|
||||
from bpy.app.translations import pgettext_tip as tip_
|
||||
from bpy.app.translations import (
|
||||
pgettext_tip as tip_,
|
||||
pgettext_rpt as rpt_,
|
||||
)
|
||||
|
||||
|
||||
class NodeSetting(PropertyGroup):
|
||||
|
@ -94,7 +97,7 @@ class NodeAddOperator:
|
|||
except AttributeError as ex:
|
||||
self.report(
|
||||
{'ERROR_INVALID_INPUT'},
|
||||
tip_("Node has no attribute %s") % setting.name)
|
||||
rpt_("Node has no attribute %s") % setting.name)
|
||||
print(str(ex))
|
||||
# Continue despite invalid attribute
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ from bpy.props import (
|
|||
IntProperty,
|
||||
StringProperty,
|
||||
)
|
||||
from bpy.app.translations import pgettext_tip as tip_
|
||||
from bpy.app.translations import pgettext_rpt as rpt_
|
||||
|
||||
|
||||
class SelectPattern(Operator):
|
||||
|
@ -367,12 +367,12 @@ class ShapeTransfer(Operator):
|
|||
for ob_other in objects:
|
||||
if ob_other.type != 'MESH':
|
||||
self.report({'WARNING'},
|
||||
tip_("Skipping '%s', not a mesh") % ob_other.name)
|
||||
rpt_("Skipping '%s', not a mesh") % ob_other.name)
|
||||
continue
|
||||
me_other = ob_other.data
|
||||
if len(me_other.vertices) != len(me.vertices):
|
||||
self.report({'WARNING'},
|
||||
tip_("Skipping '%s', vertex count differs") % ob_other.name)
|
||||
rpt_("Skipping '%s', vertex count differs") % ob_other.name)
|
||||
continue
|
||||
|
||||
target_normals = me_nos(me_other.vertices)
|
||||
|
@ -511,7 +511,7 @@ class JoinUVs(Operator):
|
|||
|
||||
if not mesh.uv_layers:
|
||||
self.report({'WARNING'},
|
||||
tip_("Object: %s, Mesh: '%s' has no UVs")
|
||||
rpt_("Object: %s, Mesh: '%s' has no UVs")
|
||||
% (obj.name, mesh.name))
|
||||
else:
|
||||
nbr_loops = len(mesh.loops)
|
||||
|
@ -535,7 +535,7 @@ class JoinUVs(Operator):
|
|||
|
||||
if len(mesh_other.loops) != nbr_loops:
|
||||
self.report({'WARNING'},
|
||||
tip_("Object: %s, Mesh: "
|
||||
rpt_("Object: %s, Mesh: "
|
||||
"'%s' has %d loops (for %d faces),"
|
||||
" expected %d\n")
|
||||
% (obj_other.name,
|
||||
|
@ -552,7 +552,7 @@ class JoinUVs(Operator):
|
|||
uv_other = mesh_other.uv_layers.active
|
||||
if not uv_other:
|
||||
self.report({'ERROR'},
|
||||
tip_("Could not add "
|
||||
rpt_("Could not add "
|
||||
"a new UV map to object "
|
||||
"'%s' (Mesh '%s')\n")
|
||||
% (obj_other.name,
|
||||
|
@ -795,7 +795,7 @@ class TransformsToDeltasAnim(Operator):
|
|||
adt = obj.animation_data
|
||||
if (adt is None) or (adt.action is None):
|
||||
self.report({'WARNING'},
|
||||
tip_("No animation data to convert on object: %r")
|
||||
rpt_("No animation data to convert on object: %r")
|
||||
% obj.name)
|
||||
continue
|
||||
|
||||
|
@ -822,7 +822,7 @@ class TransformsToDeltasAnim(Operator):
|
|||
if fcu.array_index in existingFCurves[dpath]:
|
||||
# conflict
|
||||
self.report({'ERROR'},
|
||||
tip_("Object '%r' already has '%r' F-Curve(s). "
|
||||
rpt_("Object '%r' already has '%r' F-Curve(s). "
|
||||
"Remove these before trying again") %
|
||||
(obj.name, dpath))
|
||||
return {'CANCELLED'}
|
||||
|
|
|
@ -12,7 +12,7 @@ from bpy.props import (
|
|||
IntProperty,
|
||||
)
|
||||
from bpy.app.translations import (
|
||||
pgettext_tip as tip_,
|
||||
pgettext_rpt as rpt_,
|
||||
pgettext_data as data_,
|
||||
)
|
||||
|
||||
|
@ -282,7 +282,7 @@ class QuickExplode(ObjectModeOperator, Operator):
|
|||
for obj in mesh_objects:
|
||||
if obj.particle_systems:
|
||||
self.report({'ERROR'},
|
||||
tip_("Object %r already has a "
|
||||
rpt_("Object %r already has a "
|
||||
"particle system") % obj.name)
|
||||
|
||||
return {'CANCELLED'}
|
||||
|
|
|
@ -13,7 +13,7 @@ from bpy.props import (
|
|||
StringProperty,
|
||||
)
|
||||
from bpy.app.translations import (
|
||||
pgettext_tip as tip_,
|
||||
pgettext_rpt as rpt_,
|
||||
pgettext_data as data_,
|
||||
)
|
||||
|
||||
|
@ -191,7 +191,7 @@ class AddPresetBase:
|
|||
else:
|
||||
os.remove(filepath)
|
||||
except BaseException as ex:
|
||||
self.report({'ERROR'}, tip_("Unable to remove preset: %r") % ex)
|
||||
self.report({'ERROR'}, rpt_("Unable to remove preset: %r") % ex)
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return {'CANCELLED'}
|
||||
|
@ -241,7 +241,7 @@ class ExecutePreset(Operator):
|
|||
ext = splitext(filepath)[1].lower()
|
||||
|
||||
if ext not in {".py", ".xml"}:
|
||||
self.report({'ERROR'}, tip_("Unknown file type: %r") % ext)
|
||||
self.report({'ERROR'}, rpt_("Unknown file type: %r") % ext)
|
||||
return {'CANCELLED'}
|
||||
|
||||
if hasattr(preset_class, "reset_cb"):
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import bpy
|
||||
from bpy.types import Operator
|
||||
from bpy.app.translations import pgettext_tip as tip_
|
||||
from bpy.app.translations import pgettext_rpt as rpt_
|
||||
|
||||
|
||||
def guess_player_path(preset):
|
||||
|
@ -119,7 +119,7 @@ class PlayRenderedAnim(Operator):
|
|||
file = rd.frame_path(frame=scene.frame_start, preview=scene.use_preview_range, view=view_suffix)
|
||||
file = bpy.path.abspath(file) # expand '//'
|
||||
if not os.path.exists(file):
|
||||
err_msg = tip_("File %r not found") % file
|
||||
err_msg = rpt_("File %r not found") % file
|
||||
self.report({'WARNING'}, err_msg)
|
||||
path_valid = False
|
||||
|
||||
|
@ -127,7 +127,7 @@ class PlayRenderedAnim(Operator):
|
|||
if scene.use_preview_range and not path_valid:
|
||||
file = rd.frame_path(frame=scene.frame_start, preview=False, view=view_suffix)
|
||||
file = bpy.path.abspath(file) # expand '//'
|
||||
err_msg = tip_("File %r not found") % file
|
||||
err_msg = rpt_("File %r not found") % file
|
||||
if not os.path.exists(file):
|
||||
self.report({'WARNING'}, err_msg)
|
||||
|
||||
|
@ -195,7 +195,7 @@ class PlayRenderedAnim(Operator):
|
|||
try:
|
||||
subprocess.Popen(cmd)
|
||||
except BaseException as ex:
|
||||
err_msg = tip_("Couldn't run external animation player with command %r\n%s") % (cmd, ex)
|
||||
err_msg = rpt_("Couldn't run external animation player with command %r\n%s") % (cmd, ex)
|
||||
self.report(
|
||||
{'ERROR'},
|
||||
err_msg,
|
||||
|
|
|
@ -10,7 +10,7 @@ from bpy.props import (
|
|||
FloatProperty,
|
||||
IntProperty,
|
||||
)
|
||||
from bpy.app.translations import pgettext_tip as tip_
|
||||
from bpy.app.translations import pgettext_rpt as rpt_
|
||||
|
||||
|
||||
class SequencerCrossfadeSounds(Operator):
|
||||
|
@ -236,7 +236,7 @@ class SequencerFadesAdd(Operator):
|
|||
sequence.invalidate_cache('COMPOSITE')
|
||||
|
||||
sequence_string = "sequence" if len(faded_sequences) == 1 else "sequences"
|
||||
self.report({'INFO'}, tip_("Added fade animation to %d %s") % (len(faded_sequences), sequence_string))
|
||||
self.report({'INFO'}, rpt_("Added fade animation to %d %s") % (len(faded_sequences), sequence_string))
|
||||
return {'FINISHED'}
|
||||
|
||||
def calculate_fade_duration(self, context, sequence):
|
||||
|
|
|
@ -16,7 +16,7 @@ from bpy.props import (
|
|||
)
|
||||
from bpy.app.translations import (
|
||||
pgettext_iface as iface_,
|
||||
pgettext_tip as tip_,
|
||||
pgettext_tip as rpt_,
|
||||
)
|
||||
|
||||
|
||||
|
@ -229,7 +229,7 @@ class PREFERENCES_OT_keyconfig_import(Operator):
|
|||
else:
|
||||
shutil.move(self.filepath, path)
|
||||
except BaseException as ex:
|
||||
self.report({'ERROR'}, tip_("Installing keymap failed: %s") % ex)
|
||||
self.report({'ERROR'}, rpt_("Installing keymap failed: %s") % ex)
|
||||
return {'CANCELLED'}
|
||||
|
||||
# sneaky way to check we're actually running the code.
|
||||
|
@ -455,7 +455,7 @@ class PREFERENCES_OT_addon_enable(Operator):
|
|||
if info_ver > bpy.app.version:
|
||||
self.report(
|
||||
{'WARNING'},
|
||||
tip_("This script was written Blender "
|
||||
rpt_("This script was written Blender "
|
||||
"version %d.%d.%d and might not "
|
||||
"function (correctly), "
|
||||
"though it is enabled")
|
||||
|
@ -543,7 +543,7 @@ class PREFERENCES_OT_theme_install(Operator):
|
|||
|
||||
if not self.overwrite:
|
||||
if os.path.exists(path_dest):
|
||||
self.report({'WARNING'}, tip_("File already installed to %r\n") % path_dest)
|
||||
self.report({'WARNING'}, rpt_("File already installed to %r\n") % path_dest)
|
||||
return {'CANCELLED'}
|
||||
|
||||
try:
|
||||
|
@ -657,7 +657,7 @@ class PREFERENCES_OT_addon_install(Operator):
|
|||
pyfile_dir = os.path.dirname(pyfile)
|
||||
for addon_path in addon_utils.paths():
|
||||
if os.path.samefile(pyfile_dir, addon_path):
|
||||
self.report({'ERROR'}, tip_("Source file is in the add-on search path: %r") % addon_path)
|
||||
self.report({'ERROR'}, rpt_("Source file is in the add-on search path: %r") % addon_path)
|
||||
return {'CANCELLED'}
|
||||
del addon_path
|
||||
del pyfile_dir
|
||||
|
@ -681,7 +681,7 @@ class PREFERENCES_OT_addon_install(Operator):
|
|||
for f in file_to_extract_root:
|
||||
path_dest = os.path.join(path_addons, os.path.basename(f))
|
||||
if os.path.exists(path_dest):
|
||||
self.report({'WARNING'}, tip_("File already installed to %r\n") % path_dest)
|
||||
self.report({'WARNING'}, rpt_("File already installed to %r\n") % path_dest)
|
||||
return {'CANCELLED'}
|
||||
|
||||
try: # extract the file to "addons"
|
||||
|
@ -696,7 +696,7 @@ class PREFERENCES_OT_addon_install(Operator):
|
|||
if self.overwrite:
|
||||
_module_filesystem_remove(path_addons, os.path.basename(pyfile))
|
||||
elif os.path.exists(path_dest):
|
||||
self.report({'WARNING'}, tip_("File already installed to %r\n") % path_dest)
|
||||
self.report({'WARNING'}, rpt_("File already installed to %r\n") % path_dest)
|
||||
return {'CANCELLED'}
|
||||
|
||||
# if not compressed file just copy into the addon path
|
||||
|
@ -731,7 +731,7 @@ class PREFERENCES_OT_addon_install(Operator):
|
|||
|
||||
# print message
|
||||
msg = (
|
||||
tip_("Modules Installed (%s) from %r into %r") %
|
||||
rpt_("Modules Installed (%s) from %r into %r") %
|
||||
(", ".join(sorted(addons_new)), pyfile, path_addons)
|
||||
)
|
||||
print(msg)
|
||||
|
@ -776,7 +776,7 @@ class PREFERENCES_OT_addon_remove(Operator):
|
|||
|
||||
path, isdir = PREFERENCES_OT_addon_remove.path_from_addon(self.module)
|
||||
if path is None:
|
||||
self.report({'WARNING'}, tip_("Add-on path %r could not be found") % path)
|
||||
self.report({'WARNING'}, rpt_("Add-on path %r could not be found") % path)
|
||||
return {'CANCELLED'}
|
||||
|
||||
# in case its enabled
|
||||
|
@ -926,7 +926,7 @@ class PREFERENCES_OT_app_template_install(Operator):
|
|||
for f in file_to_extract_root:
|
||||
path_dest = os.path.join(path_app_templates, os.path.basename(f))
|
||||
if os.path.exists(path_dest):
|
||||
self.report({'WARNING'}, tip_("File already installed to %r\n") % path_dest)
|
||||
self.report({'WARNING'}, rpt_("File already installed to %r\n") % path_dest)
|
||||
return {'CANCELLED'}
|
||||
|
||||
try: # extract the file to "bl_app_templates_user"
|
||||
|
@ -937,7 +937,7 @@ class PREFERENCES_OT_app_template_install(Operator):
|
|||
|
||||
else:
|
||||
# Only support installing zip-files.
|
||||
self.report({'WARNING'}, tip_("Expected a zip-file %r\n") % filepath)
|
||||
self.report({'WARNING'}, rpt_("Expected a zip-file %r\n") % filepath)
|
||||
return {'CANCELLED'}
|
||||
|
||||
app_templates_new = set(os.listdir(path_app_templates)) - app_templates_old
|
||||
|
@ -947,7 +947,7 @@ class PREFERENCES_OT_app_template_install(Operator):
|
|||
|
||||
# print message
|
||||
msg = (
|
||||
tip_("Template Installed (%s) from %r into %r") %
|
||||
rpt_("Template Installed (%s) from %r into %r") %
|
||||
(", ".join(sorted(app_templates_new)), filepath, path_app_templates)
|
||||
)
|
||||
print(msg)
|
||||
|
@ -1011,7 +1011,7 @@ class PREFERENCES_OT_studiolight_install(Operator):
|
|||
|
||||
# print message
|
||||
msg = (
|
||||
tip_("StudioLight Installed %r into %r") %
|
||||
rpt_("StudioLight Installed %r into %r") %
|
||||
(", ".join(e.name for e in self.files), path_studiolights)
|
||||
)
|
||||
print(msg)
|
||||
|
@ -1069,7 +1069,7 @@ class PREFERENCES_OT_studiolight_new(Operator):
|
|||
|
||||
# print message
|
||||
msg = (
|
||||
tip_("StudioLight Installed %r into %r") %
|
||||
rpt_("StudioLight Installed %r into %r") %
|
||||
(self.filename, str(path_studiolights))
|
||||
)
|
||||
print(msg)
|
||||
|
|
|
@ -32,45 +32,56 @@ def extend(obj, EXTEND_MODE, use_uv_selection):
|
|||
return STATUS_ERR_NOT_SELECTED # Active face is not selected.
|
||||
if len(f_act.verts) != 4:
|
||||
return STATUS_ERR_NOT_QUAD # Active face is not a quad
|
||||
if not bm.loops.layers.uv:
|
||||
uv_act = bm.loops.layers.uv.active # Always use the active UV layer.
|
||||
if uv_act is None:
|
||||
return STATUS_ERR_MISSING_UV_LAYER # Object's mesh doesn't have any UV layers.
|
||||
|
||||
uv_act = bm.loops.layers.uv.active # Always use the active UV layer.
|
||||
|
||||
# Construct a set of selected quads.
|
||||
faces = {f for f in bm.faces if len(f.verts) == 4 and f.select}
|
||||
if use_uv_selection:
|
||||
# Filter `faces` to extract only UV selected quads.
|
||||
faces = {f for f in faces if is_face_uv_selected(f, uv_act, False)}
|
||||
faces = [
|
||||
f for f in bm.faces
|
||||
if f.select and len(f.verts) == 4 and is_face_uv_selected(f, uv_act, False)
|
||||
]
|
||||
else:
|
||||
faces = [
|
||||
f for f in bm.faces
|
||||
if f.select and len(f.verts) == 4
|
||||
]
|
||||
|
||||
if not faces:
|
||||
return STATUS_ERR_NO_FACES_SELECTED
|
||||
|
||||
def walk_face():
|
||||
from collections import deque
|
||||
# Our own local walker.
|
||||
|
||||
def walk_face_init(faces, f_act):
|
||||
# First tag all faces True (so we don't UV-map them).
|
||||
for f in bm.faces:
|
||||
f.tag = f not in faces
|
||||
f.tag = True
|
||||
# Then tag faces argument False.
|
||||
for f in faces:
|
||||
f.tag = False
|
||||
# Tag the active face True since we begin there.
|
||||
f_act.tag = True
|
||||
|
||||
faces_deque = deque()
|
||||
faces_deque.append(f_act)
|
||||
f_act.tag = True # Queued.
|
||||
def walk_face(f):
|
||||
# All faces in this list must be tagged.
|
||||
f.tag = True
|
||||
faces_a = [f]
|
||||
faces_b = []
|
||||
|
||||
while faces_deque: # Breadth first search.
|
||||
f = faces_deque.popleft()
|
||||
for l in f.loops:
|
||||
l_edge = l.edge
|
||||
if l_edge.seam:
|
||||
continue # Don't walk across seams.
|
||||
if not l_edge.is_manifold:
|
||||
continue # Don't walk across non-manifold.
|
||||
l_other = l.link_loop_radial_next # Manifold implies uniqueness.
|
||||
f_other = l_other.face
|
||||
if f_other.tag:
|
||||
continue # Either queued, visited, not selected, or not quad.
|
||||
yield (f, l, f_other)
|
||||
faces_deque.append(f_other)
|
||||
f_other.tag = True # Queued.
|
||||
while faces_a:
|
||||
for f in faces_a:
|
||||
for l in f.loops:
|
||||
l_edge = l.edge
|
||||
if (l_edge.is_manifold is True) and (l_edge.seam is False):
|
||||
l_other = l.link_loop_radial_next
|
||||
f_other = l_other.face
|
||||
if not f_other.tag:
|
||||
yield (f, l, f_other)
|
||||
f_other.tag = True
|
||||
faces_b.append(f_other)
|
||||
# Swap.
|
||||
faces_a, faces_b = faces_b, faces_a
|
||||
faces_b.clear()
|
||||
|
||||
def walk_edgeloop(l):
|
||||
"""
|
||||
|
@ -95,22 +106,13 @@ def extend(obj, EXTEND_MODE, use_uv_selection):
|
|||
else:
|
||||
break
|
||||
|
||||
uv_updates = []
|
||||
|
||||
def record_and_assign_uv(dest, source):
|
||||
from mathutils import Vector
|
||||
|
||||
if dest[uv_act].uv == source:
|
||||
return # Already placed correctly, probably a nearby quad.
|
||||
dest_uv_copy = Vector(dest[uv_act].uv) # Make a copy to prevent aliasing.
|
||||
uv_updates.append([dest.vert, dest_uv_copy, source]) # Record changes.
|
||||
dest[uv_act].uv = source # Assign updated UV.
|
||||
|
||||
def extrapolate_uv(fac, l_a_outer, l_a_inner, l_b_outer, l_b_inner):
|
||||
l_a_inner_uv = l_a_inner[uv_act].uv
|
||||
l_a_outer_uv = l_a_outer[uv_act].uv
|
||||
record_and_assign_uv(l_b_inner, l_a_inner_uv)
|
||||
record_and_assign_uv(l_b_outer, l_a_inner_uv * (1 + fac) - l_a_outer_uv * fac)
|
||||
def extrapolate_uv(
|
||||
fac,
|
||||
l_a_outer, l_a_inner,
|
||||
l_b_outer, l_b_inner,
|
||||
):
|
||||
l_b_inner[:] = l_a_inner
|
||||
l_b_outer[:] = l_a_inner + ((l_a_inner - l_a_outer) * fac)
|
||||
|
||||
def apply_uv(_f_prev, l_prev, _f_next):
|
||||
l_a = [None, None, None, None]
|
||||
|
@ -149,6 +151,9 @@ def extend(obj, EXTEND_MODE, use_uv_selection):
|
|||
l_b[2] = l_b[1].link_loop_next
|
||||
l_b[3] = l_b[2].link_loop_next
|
||||
|
||||
l_a_uv = [l[uv_act].uv for l in l_a]
|
||||
l_b_uv = [l[uv_act].uv for l in l_b]
|
||||
|
||||
if EXTEND_MODE == 'LENGTH_AVERAGE':
|
||||
d1 = edge_lengths[l_a[1].edge.index][0]
|
||||
d2 = edge_lengths[l_b[2].edge.index][0]
|
||||
|
@ -169,8 +174,13 @@ def extend(obj, EXTEND_MODE, use_uv_selection):
|
|||
else:
|
||||
fac = 1.0
|
||||
|
||||
extrapolate_uv(fac, l_a[3], l_a[0], l_b[3], l_b[0])
|
||||
extrapolate_uv(fac, l_a[2], l_a[1], l_b[2], l_b[1])
|
||||
extrapolate_uv(fac,
|
||||
l_a_uv[3], l_a_uv[0],
|
||||
l_b_uv[3], l_b_uv[0])
|
||||
|
||||
extrapolate_uv(fac,
|
||||
l_a_uv[2], l_a_uv[1],
|
||||
l_b_uv[2], l_b_uv[1])
|
||||
|
||||
# -------------------------------------------
|
||||
# Calculate average length per loop if needed.
|
||||
|
@ -202,16 +212,12 @@ def extend(obj, EXTEND_MODE, use_uv_selection):
|
|||
|
||||
edge_length_store[0] = edge_length_accum / edge_length_total
|
||||
|
||||
for f_triple in walk_face():
|
||||
apply_uv(*f_triple)
|
||||
# done with average length
|
||||
# ------------------------
|
||||
|
||||
# Propagate UV changes across boundary of selection.
|
||||
for (v, original_uv, source) in uv_updates:
|
||||
# Visit all loops associated with our vertex.
|
||||
for loop in v.link_loops:
|
||||
# If the loop's UV matches the original, assign the new UV.
|
||||
if loop[uv_act].uv == original_uv:
|
||||
loop[uv_act].uv = source
|
||||
walk_face_init(faces, f_act)
|
||||
for f_triple in walk_face(f_act):
|
||||
apply_uv(*f_triple)
|
||||
|
||||
bmesh.update_edit_mesh(me, loop_triangles=False)
|
||||
return STATUS_OK
|
||||
|
|
|
@ -113,9 +113,15 @@ class prettyface:
|
|||
|
||||
# ngons work different, we store projected result
|
||||
# in UVs to avoid having to re-project later.
|
||||
for i, co in enumerate(cos_2d):
|
||||
self.uv[i][:] = ((co.x - xmin) / xspan,
|
||||
(co.y - ymin) / yspan)
|
||||
if xspan < 0.0000001 or yspan < 0.0000001:
|
||||
for i in range(len(cos_2d)):
|
||||
self.uv[i][:] = (0.0, 0.0)
|
||||
else:
|
||||
for i, co in enumerate(cos_2d):
|
||||
self.uv[i][:] = (
|
||||
(co.x - xmin) / xspan,
|
||||
(co.y - ymin) / yspan,
|
||||
)
|
||||
|
||||
self.children = []
|
||||
|
||||
|
@ -296,28 +302,52 @@ def lightmap_uvpack(
|
|||
tri_lengths = [trylens(f) for f in face_sel if f.loop_total == 3]
|
||||
del trylens
|
||||
|
||||
def trilensdiff(t1, t2):
|
||||
return (abs(t1[1][t1[2][0]] - t2[1][t2[2][0]]) +
|
||||
abs(t1[1][t1[2][1]] - t2[1][t2[2][1]]) +
|
||||
abs(t1[1][t1[2][2]] - t2[1][t2[2][2]]))
|
||||
# To add triangles into the light-map pack triangles are grouped in pairs to fill rectangular areas.
|
||||
# In the following for each triangle we add the sorted triangle edge lengths (3d point) into a KD-Tree
|
||||
# then iterate over all triangles and search for pairs of triangles by looking for the closest
|
||||
# sorted triangle point.
|
||||
# Additionally clusters of similar/equal triangles are parsed by searching for ranges in a second step.
|
||||
kd = mathutils.kdtree.KDTree(len(tri_lengths))
|
||||
for i, (f, lens, o) in enumerate(tri_lengths):
|
||||
vector = (lens[o[0]], lens[o[1]], lens[o[2]])
|
||||
kd.insert(vector, i)
|
||||
kd.balance()
|
||||
|
||||
while tri_lengths:
|
||||
tri1 = tri_lengths.pop()
|
||||
added_ids = [False] * len(tri_lengths)
|
||||
pairs_added = 0
|
||||
tri_equality_threshold = 0.00001 # Add multiple pairs at once that are within this threshold.
|
||||
for i in range(len(tri_lengths)):
|
||||
if added_ids[i]:
|
||||
continue
|
||||
tri1 = tri_lengths[i]
|
||||
f1, lens1, lo1 = tri1
|
||||
|
||||
if not tri_lengths:
|
||||
sorted_l = (lens1[lo1[0]], lens1[lo1[1]], lens1[lo1[2]])
|
||||
added_ids[i] = True
|
||||
vec, nearest, dist = kd.find(sorted_l, filter=lambda idx: not added_ids[idx])
|
||||
if not nearest or nearest < 0:
|
||||
pretty_faces.append(prettyface((tri1, None)))
|
||||
break
|
||||
tri2 = tri_lengths[nearest]
|
||||
pretty_faces.append(prettyface((tri1, tri2)))
|
||||
pairs_added = pairs_added + 1
|
||||
added_ids[nearest] = True
|
||||
|
||||
best_tri_index = -1
|
||||
best_tri_diff = 100000000.0
|
||||
# Look in threshold proximity to add all similar/equal triangles in one go.
|
||||
# This code is not necessary but acts as a shortcut (~9% performance improvement).
|
||||
if dist < tri_equality_threshold:
|
||||
cluster_tri_ids = [
|
||||
idx for _, idx, _ in kd.find_range(sorted_l, tri_equality_threshold)
|
||||
if not added_ids[idx]
|
||||
]
|
||||
|
||||
for i, tri2 in enumerate(tri_lengths):
|
||||
diff = trilensdiff(tri1, tri2)
|
||||
if diff < best_tri_diff:
|
||||
best_tri_index = i
|
||||
best_tri_diff = diff
|
||||
|
||||
pretty_faces.append(prettyface((tri1, tri_lengths.pop(best_tri_index))))
|
||||
if len(cluster_tri_ids) > 1:
|
||||
for ci in range(0, len(cluster_tri_ids) - (len(cluster_tri_ids) % 2), 2):
|
||||
pretty_faces.append(
|
||||
prettyface((tri_lengths[cluster_tri_ids[ci]], tri_lengths[cluster_tri_ids[ci + 1]]))
|
||||
)
|
||||
added_ids[cluster_tri_ids[ci]] = added_ids[cluster_tri_ids[ci + 1]] = True
|
||||
pairs_added = pairs_added + 1
|
||||
|
||||
# Get the min, max and total areas
|
||||
max_area = 0.0
|
||||
|
|
|
@ -23,6 +23,7 @@ from bpy.props import (
|
|||
from bpy.app.translations import (
|
||||
pgettext_iface as iface_,
|
||||
pgettext_tip as tip_,
|
||||
pgettext_rpt as rpt_,
|
||||
contexts as i18n_contexts,
|
||||
)
|
||||
|
||||
|
@ -778,7 +779,7 @@ class WM_OT_operator_pie_enum(Operator):
|
|||
try:
|
||||
op_rna = op.get_rna_type()
|
||||
except KeyError:
|
||||
self.report({'ERROR'}, tip_("Operator not found: bpy.ops.%s") % data_path)
|
||||
self.report({'ERROR'}, rpt_("Operator not found: bpy.ops.%s") % data_path)
|
||||
return {'CANCELLED'}
|
||||
|
||||
def draw_cb(self, context):
|
||||
|
@ -878,7 +879,7 @@ class WM_OT_context_collection_boolean_set(Operator):
|
|||
elif value_orig is False:
|
||||
pass
|
||||
else:
|
||||
self.report({'WARNING'}, tip_("Non boolean value found: %s[ ].%s") %
|
||||
self.report({'WARNING'}, rpt_("Non boolean value found: %s[ ].%s") %
|
||||
(data_path_iter, data_path_item))
|
||||
return {'CANCELLED'}
|
||||
|
||||
|
@ -981,7 +982,7 @@ class WM_OT_context_modal_mouse(Operator):
|
|||
(item, ) = self._values.keys()
|
||||
header_text = header_text % eval("item.%s" % self.data_path_item)
|
||||
else:
|
||||
header_text = (self.header_text % delta) + tip_(" (delta)")
|
||||
header_text = (self.header_text % delta) + rpt_(" (delta)")
|
||||
context.area.header_text_set(header_text)
|
||||
|
||||
elif 'LEFTMOUSE' == event_type:
|
||||
|
@ -1001,7 +1002,7 @@ class WM_OT_context_modal_mouse(Operator):
|
|||
self._values_store(context)
|
||||
|
||||
if not self._values:
|
||||
self.report({'WARNING'}, tip_("Nothing to operate on: %s[ ].%s") %
|
||||
self.report({'WARNING'}, rpt_("Nothing to operate on: %s[ ].%s") %
|
||||
(self.data_path_iter, self.data_path_item))
|
||||
|
||||
return {'CANCELLED'}
|
||||
|
@ -1168,7 +1169,7 @@ class WM_OT_path_open(Operator):
|
|||
filepath = os.path.normpath(filepath)
|
||||
|
||||
if not os.path.exists(filepath):
|
||||
self.report({'ERROR'}, tip_("File '%s' not found") % filepath)
|
||||
self.report({'ERROR'}, rpt_("File '%s' not found") % filepath)
|
||||
return {'CANCELLED'}
|
||||
|
||||
if sys.platform[:3] == "win":
|
||||
|
@ -1239,7 +1240,7 @@ def _wm_doc_get_id(doc_id, *, do_url=True, url_prefix="", report=None):
|
|||
|
||||
if rna_class is None:
|
||||
if report is not None:
|
||||
report({'ERROR'}, tip_("Type \"%s\" can not be found") % class_name)
|
||||
report({'ERROR'}, rpt_("Type \"%s\" can not be found") % class_name)
|
||||
return None
|
||||
|
||||
# Detect if this is a inherited member and use that name instead.
|
||||
|
@ -1334,7 +1335,7 @@ class WM_OT_doc_view_manual(Operator):
|
|||
if url is None:
|
||||
self.report(
|
||||
{'WARNING'},
|
||||
tip_("No reference available %r, "
|
||||
rpt_("No reference available %r, "
|
||||
"Update info in 'rna_manual_reference.py' "
|
||||
"or callback to bpy.utils.manual_map()") %
|
||||
self.doc_id
|
||||
|
@ -2317,7 +2318,7 @@ class WM_OT_tool_set_by_id(Operator):
|
|||
tool_settings.workspace_tool_type = 'FALLBACK'
|
||||
return {'FINISHED'}
|
||||
else:
|
||||
self.report({'WARNING'}, tip_("Tool %r not found for space %r") % (self.name, space_type))
|
||||
self.report({'WARNING'}, rpt_("Tool %r not found for space %r") % (self.name, space_type))
|
||||
return {'CANCELLED'}
|
||||
|
||||
|
||||
|
@ -3188,7 +3189,7 @@ class WM_OT_batch_rename(Operator):
|
|||
change_len += 1
|
||||
total_len += 1
|
||||
|
||||
self.report({'INFO'}, tip_("Renamed %d of %d %s") % (change_len, total_len, descr))
|
||||
self.report({'INFO'}, rpt_("Renamed %d of %d %s") % (change_len, total_len, descr))
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
|
|
@ -215,6 +215,7 @@ class NODE_MT_geometry_node_GEO_GEOMETRY_OPERATIONS(Menu):
|
|||
node_add_menu.add_node_type(layout, "GeometryNodeDeleteGeometry")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeDuplicateElements")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMergeByDistance")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSortElements")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeTransform")
|
||||
layout.separator()
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSeparateComponents")
|
||||
|
|
|
@ -158,11 +158,18 @@ class ARMATURE_MT_collection_tree_context_menu(Menu):
|
|||
layout = self.layout
|
||||
arm = context.armature
|
||||
|
||||
props = layout.operator(
|
||||
active_bcoll_is_locked = arm.collections.active and not arm.collections.active.is_editable
|
||||
|
||||
# The poll function doesn't have access to the parent index property, so
|
||||
# it cannot disable this operator depending on whether the parent is
|
||||
# editable or not. That means this menu has to do the disabling for it.
|
||||
sub = layout.column()
|
||||
sub.enabled = not active_bcoll_is_locked
|
||||
props = sub.operator(
|
||||
"armature.collection_add", text="Add Child Collection"
|
||||
)
|
||||
props.parent_index = arm.collections.active_index
|
||||
layout.operator("armature.collection_remove")
|
||||
sub.operator("armature.collection_remove")
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
@ -171,8 +178,13 @@ class ARMATURE_MT_collection_tree_context_menu(Menu):
|
|||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("armature.collection_assign", text="Assign Selected Bones")
|
||||
layout.operator("armature.collection_unassign", text="Remove Selected Bones")
|
||||
# These operators can be used to assign to a named collection as well, and
|
||||
# don't necessarily always use the active bone collection. That means that
|
||||
# they have the same limitation as described above.
|
||||
sub = layout.column()
|
||||
sub.enabled = not active_bcoll_is_locked
|
||||
sub.operator("armature.collection_assign", text="Assign Selected Bones")
|
||||
sub.operator("armature.collection_unassign", text="Remove Selected Bones")
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
|
|
@ -112,6 +112,10 @@ class CURVES_UL_attributes(UIList):
|
|||
for idx, item in enumerate(attributes):
|
||||
flags[idx] = 0 if item.is_internal else flags[idx]
|
||||
|
||||
# Reorder by name.
|
||||
if self.use_filter_sort_alpha:
|
||||
indices = bpy.types.UI_UL_list.sort_items_by_name(attributes, "name")
|
||||
|
||||
return flags, indices
|
||||
|
||||
def draw_item(self, _context, layout, _data, attribute, _icon, _active_data, _active_propname, _index):
|
||||
|
|
|
@ -8,7 +8,7 @@ from rna_prop_ui import PropertyPanel
|
|||
|
||||
from bpy.app.translations import (
|
||||
pgettext_iface as iface_,
|
||||
pgettext_tip as tip_,
|
||||
pgettext_tip as rpt_,
|
||||
)
|
||||
|
||||
|
||||
|
@ -495,6 +495,10 @@ class MESH_UL_attributes(UIList):
|
|||
for idx, item in enumerate(attributes):
|
||||
flags[idx] = 0 if item.is_internal else flags[idx]
|
||||
|
||||
# Reorder by name.
|
||||
if self.use_filter_sort_alpha:
|
||||
indices = bpy.types.UI_UL_list.sort_items_by_name(attributes, "name")
|
||||
|
||||
return flags, indices
|
||||
|
||||
def draw_item(self, _context, layout, _data, attribute, _icon, _active_data, _active_propname, _index):
|
||||
|
@ -577,7 +581,7 @@ def draw_attribute_warnings(context, layout):
|
|||
if not colliding_names:
|
||||
return
|
||||
|
||||
layout.label(text=tip_("Name collisions: ") + ", ".join(set(colliding_names)),
|
||||
layout.label(text=rpt_("Name collisions: ") + ", ".join(set(colliding_names)),
|
||||
icon='ERROR', translate=False)
|
||||
|
||||
|
||||
|
@ -609,6 +613,10 @@ class ColorAttributesListBase():
|
|||
)
|
||||
flags[idx] = 0 if skip else flags[idx]
|
||||
|
||||
# Reorder by name.
|
||||
if self.use_filter_sort_alpha:
|
||||
indices = bpy.types.UI_UL_list.sort_items_by_name(attributes, "name")
|
||||
|
||||
return flags, indices
|
||||
|
||||
|
||||
|
|
|
@ -89,6 +89,10 @@ class POINTCLOUD_UL_attributes(UIList):
|
|||
for idx, item in enumerate(attributes):
|
||||
flags[idx] = 0 if item.is_internal else flags[idx]
|
||||
|
||||
# Reorder by name.
|
||||
if self.use_filter_sort_alpha:
|
||||
indices = bpy.types.UI_UL_list.sort_items_by_name(attributes, "name")
|
||||
|
||||
return flags, indices
|
||||
|
||||
def draw_item(self, _context, layout, _data, attribute, _icon, _active_data, _active_propname, _index):
|
||||
|
|
|
@ -27,6 +27,15 @@ class GPENCIL_MT_material_context_menu(Menu):
|
|||
layout.operator("grease_pencil.material_unlock_all", icon='UNLOCKED', text="Unlock All")
|
||||
layout.operator("grease_pencil.material_lock_unselected", text="Lock Unselected")
|
||||
layout.operator("grease_pencil.material_lock_unused", text="Lock Unused")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator(
|
||||
"grease_pencil.material_copy_to_object",
|
||||
text="Copy Material to Selected").only_active = True
|
||||
layout.operator("grease_pencil.material_copy_to_object",
|
||||
text="Copy All Materials to Selected").only_active = False
|
||||
|
||||
else:
|
||||
layout.operator("gpencil.material_reveal", icon='RESTRICT_VIEW_OFF', text="Show All")
|
||||
layout.operator("gpencil.material_hide", icon='RESTRICT_VIEW_ON', text="Hide Others").unselected = True
|
||||
|
|
|
@ -8,7 +8,7 @@ from bl_ui.utils import PresetPanel
|
|||
|
||||
from bpy.app.translations import (
|
||||
contexts as i18n_contexts,
|
||||
pgettext_tip as tip_,
|
||||
pgettext_iface as iface_,
|
||||
)
|
||||
|
||||
|
||||
|
@ -75,10 +75,10 @@ class RENDER_PT_format(RenderOutputButtonsPanel, Panel):
|
|||
custom_framerate = (fps_rate not in {23.98, 24, 25, 29.97, 30, 50, 59.94, 60, 120, 240})
|
||||
|
||||
if custom_framerate is True:
|
||||
fps_label_text = tip_("Custom (%.4g fps)") % fps_rate
|
||||
fps_label_text = iface_("Custom (%.4g fps)") % fps_rate
|
||||
show_framerate = True
|
||||
else:
|
||||
fps_label_text = tip_("%.4g fps") % fps_rate
|
||||
fps_label_text = iface_("%.4g fps") % fps_rate
|
||||
show_framerate = (preset_label == "Custom")
|
||||
|
||||
RENDER_PT_format._frame_rate_args_prev = args
|
||||
|
|
|
@ -8,6 +8,7 @@ from rna_prop_ui import PropertyPanel
|
|||
from bpy.app.translations import (
|
||||
contexts as i18n_contexts,
|
||||
pgettext_iface as iface_,
|
||||
pgettext_rpt as rpt_,
|
||||
)
|
||||
from bl_ui.utils import PresetPanel
|
||||
|
||||
|
@ -221,7 +222,7 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
|
|||
row.template_ID(psys, "settings", new="particle.new")
|
||||
|
||||
if part.is_fluid:
|
||||
layout.label(text=iface_("%d fluid particles for this frame") % part.count, translate=False)
|
||||
layout.label(text=rpt_("%d fluid particles for this frame") % part.count, translate=False)
|
||||
return
|
||||
|
||||
row = layout.row()
|
||||
|
@ -432,10 +433,10 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel):
|
|||
label = "ERROR"
|
||||
icon = 'ERROR'
|
||||
box.label(text=label, icon=icon)
|
||||
box.label(text=iface_("Iterations: %d .. %d (avg. %d)") %
|
||||
box.label(text=rpt_("Iterations: %d .. %d (avg. %d)") %
|
||||
(result.min_iterations, result.max_iterations, result.avg_iterations),
|
||||
translate=False)
|
||||
box.label(text=iface_("Error: %.5f .. %.5f (avg. %.5f)")
|
||||
box.label(text=rpt_("Error: %.5f .. %.5f (avg. %.5f)")
|
||||
% (result.min_error, result.max_error, result.avg_error),
|
||||
translate=False)
|
||||
|
||||
|
|
|
@ -1055,51 +1055,6 @@ class PHYSICS_PT_particles(PhysicButtonsPanel, Panel):
|
|||
split.operator("fluid.free_particles", text="Free Particles")
|
||||
|
||||
|
||||
class PHYSICS_PT_viscosity(PhysicButtonsPanel, Panel):
|
||||
bl_label = "Viscosity"
|
||||
bl_parent_id = "PHYSICS_PT_liquid"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
COMPAT_ENGINES = {
|
||||
'BLENDER_RENDER',
|
||||
'BLENDER_EEVEE',
|
||||
'BLENDER_EEVEE_NEXT',
|
||||
'BLENDER_WORKBENCH',
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
# Fluid viscosity only enabled for liquids
|
||||
if not PhysicButtonsPanel.poll_liquid_domain(context):
|
||||
return False
|
||||
|
||||
return (context.engine in cls.COMPAT_ENGINES)
|
||||
|
||||
def draw_header(self, context):
|
||||
md = context.fluid.domain_settings
|
||||
domain = context.fluid.domain_settings
|
||||
is_baking_any = domain.is_cache_baking_any
|
||||
has_baked_any = domain.has_cache_baked_any
|
||||
self.layout.enabled = not is_baking_any and not has_baked_any
|
||||
self.layout.prop(md, "use_viscosity", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
|
||||
domain = context.fluid.domain_settings
|
||||
layout.active = domain.use_viscosity
|
||||
|
||||
is_baking_any = domain.is_cache_baking_any
|
||||
has_baked_any = domain.has_cache_baked_any
|
||||
has_baked_data = domain.has_cache_baked_data
|
||||
|
||||
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
|
||||
flow.enabled = not is_baking_any and not has_baked_any and not has_baked_data
|
||||
|
||||
col = flow.column(align=True)
|
||||
col.prop(domain, "viscosity_value", text="Strength")
|
||||
|
||||
|
||||
class PHYSICS_PT_diffusion(PhysicButtonsPanel, Panel):
|
||||
bl_label = "Diffusion"
|
||||
bl_parent_id = "PHYSICS_PT_liquid"
|
||||
|
@ -1152,6 +1107,51 @@ class PHYSICS_PT_diffusion(PhysicButtonsPanel, Panel):
|
|||
col.prop(domain, "surface_tension", text="Surface Tension")
|
||||
|
||||
|
||||
class PHYSICS_PT_viscosity(PhysicButtonsPanel, Panel):
|
||||
bl_label = "High Viscosity Solver"
|
||||
bl_parent_id = "PHYSICS_PT_diffusion"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
COMPAT_ENGINES = {
|
||||
'BLENDER_RENDER',
|
||||
'BLENDER_EEVEE',
|
||||
'BLENDER_EEVEE_NEXT',
|
||||
'BLENDER_WORKBENCH',
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
# Fluid viscosity only enabled for liquids
|
||||
if not PhysicButtonsPanel.poll_liquid_domain(context):
|
||||
return False
|
||||
|
||||
return (context.engine in cls.COMPAT_ENGINES)
|
||||
|
||||
def draw_header(self, context):
|
||||
md = context.fluid.domain_settings
|
||||
domain = context.fluid.domain_settings
|
||||
is_baking_any = domain.is_cache_baking_any
|
||||
has_baked_any = domain.has_cache_baked_any
|
||||
self.layout.enabled = not is_baking_any and not has_baked_any
|
||||
self.layout.prop(md, "use_viscosity", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
|
||||
domain = context.fluid.domain_settings
|
||||
layout.active = domain.use_viscosity
|
||||
|
||||
is_baking_any = domain.is_cache_baking_any
|
||||
has_baked_any = domain.has_cache_baked_any
|
||||
has_baked_data = domain.has_cache_baked_data
|
||||
|
||||
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
|
||||
flow.enabled = not is_baking_any and not has_baked_any and not has_baked_data
|
||||
|
||||
col = flow.column(align=True)
|
||||
col.prop(domain, "viscosity_value", text="Strength")
|
||||
|
||||
|
||||
class PHYSICS_PT_guide(PhysicButtonsPanel, Panel):
|
||||
bl_label = "Guides"
|
||||
bl_parent_id = "PHYSICS_PT_fluid"
|
||||
|
@ -1625,8 +1625,8 @@ classes = (
|
|||
PHYSICS_PT_noise,
|
||||
PHYSICS_PT_fire,
|
||||
PHYSICS_PT_liquid,
|
||||
PHYSICS_PT_viscosity,
|
||||
PHYSICS_PT_diffusion,
|
||||
PHYSICS_PT_viscosity,
|
||||
PHYSICS_PT_particles,
|
||||
PHYSICS_PT_mesh,
|
||||
PHYSICS_PT_guide,
|
||||
|
|
|
@ -10,6 +10,7 @@ from bl_ui.space_view3d import (
|
|||
VIEW3D_PT_shading_options,
|
||||
)
|
||||
from bl_ui.utils import PresetPanel
|
||||
from bpy.app.translations import pgettext_rpt as rpt_
|
||||
|
||||
|
||||
class RenderButtonsPanel:
|
||||
|
@ -829,7 +830,7 @@ class RENDER_PT_eevee_indirect_lighting(RenderButtonsPanel, Panel):
|
|||
|
||||
cache_info = scene.eevee.gi_cache_info
|
||||
if cache_info:
|
||||
col.label(text=cache_info)
|
||||
col.label(text=rpt_(cache_info), translate=False)
|
||||
|
||||
col.prop(props, "gi_auto_bake")
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import bpy
|
|||
from bpy.types import Panel, Header, Menu, UIList
|
||||
from bpy.app.translations import (
|
||||
pgettext_iface as iface_,
|
||||
pgettext_rpt as rpt_,
|
||||
contexts as i18n_contexts,
|
||||
)
|
||||
from bl_ui.utils import PresetPanel
|
||||
|
@ -170,7 +171,7 @@ class CLIP_HT_header(Header):
|
|||
r = active_object.reconstruction
|
||||
|
||||
if r.is_valid and sc.view == 'CLIP':
|
||||
layout.label(text=iface_("Solve error: %.2f px") %
|
||||
layout.label(text=rpt_("Solve error: %.2f px") %
|
||||
(r.average_error),
|
||||
translate=False)
|
||||
|
||||
|
@ -769,7 +770,7 @@ class CLIP_PT_track(CLIP_PT_tracking_panel, Panel):
|
|||
layout.prop(act_track, "weight_stab")
|
||||
|
||||
if act_track.has_bundle:
|
||||
label_text = iface_("Average Error: %.2f px") % (act_track.average_error)
|
||||
label_text = rpt_("Average Error: %.2f px") % (act_track.average_error)
|
||||
layout.label(text=label_text, translate=False)
|
||||
|
||||
layout.use_property_split = False
|
||||
|
|
|
@ -11,6 +11,7 @@ from bpy.types import (
|
|||
from bpy.app.translations import (
|
||||
contexts as i18n_contexts,
|
||||
pgettext_iface as iface_,
|
||||
pgettext_rpt as rpt_,
|
||||
)
|
||||
from bl_ui.properties_grease_pencil_common import (
|
||||
AnnotationDataPanel,
|
||||
|
@ -1225,7 +1226,7 @@ class SEQUENCER_MT_context_menu(Menu):
|
|||
layout.operator("sequencer.retiming_segment_speed_set")
|
||||
layout.separator()
|
||||
|
||||
layout.operator("sequencer.retiming_key_remove")
|
||||
layout.operator("sequencer.delete", text="Delete Retiming Keys")
|
||||
|
||||
def draw(self, context):
|
||||
ed = context.scene.sequence_editor
|
||||
|
@ -1905,7 +1906,7 @@ class SEQUENCER_PT_mask(SequencerButtonsPanel, Panel):
|
|||
if mask:
|
||||
sta = mask.frame_start
|
||||
end = mask.frame_end
|
||||
layout.label(text=iface_("Original frame range: %d-%d (%d)") % (sta, end, end - sta + 1), translate=False)
|
||||
layout.label(text=rpt_("Original frame range: %d-%d (%d)") % (sta, end, end - sta + 1), translate=False)
|
||||
|
||||
|
||||
class SEQUENCER_PT_time(SequencerButtonsPanel, Panel):
|
||||
|
|
|
@ -1307,6 +1307,7 @@ class _defs_edit_curves:
|
|||
props = tool.operator_properties("curves.draw")
|
||||
col = layout.column(align=True)
|
||||
col.prop(props, "is_curve_2d", text="Curve 2D")
|
||||
col.prop(props, "bezier_as_nurbs", text="As NURBS")
|
||||
|
||||
return dict(
|
||||
idname="builtin.draw",
|
||||
|
|
|
@ -11,7 +11,7 @@ from bpy.types import (
|
|||
from bpy.app.translations import (
|
||||
contexts as i18n_contexts,
|
||||
pgettext_iface as iface_,
|
||||
pgettext_tip as tip_,
|
||||
pgettext_rpt as rpt_,
|
||||
)
|
||||
from bl_ui.utils import PresetPanel
|
||||
|
||||
|
@ -260,6 +260,7 @@ class USERPREF_PT_interface_translation(InterfacePanel, CenterAlignMixIn, Panel)
|
|||
col.active = (bpy.app.translations.locale != "en_US")
|
||||
col.prop(view, "use_translate_tooltips", text="Tooltips")
|
||||
col.prop(view, "use_translate_interface", text="Interface")
|
||||
col.prop(view, "use_translate_reports", text="Reports")
|
||||
col.prop(view, "use_translate_new_dataname", text="New Data")
|
||||
|
||||
|
||||
|
@ -2239,11 +2240,11 @@ class USERPREF_PT_addons(AddOnPanel, Panel):
|
|||
if info["description"]:
|
||||
split = colsub.row().split(factor=0.15)
|
||||
split.label(text="Description:")
|
||||
split.label(text=tip_(info["description"]))
|
||||
split.label(text=iface_(info["description"]))
|
||||
if info["location"]:
|
||||
split = colsub.row().split(factor=0.15)
|
||||
split.label(text="Location:")
|
||||
split.label(text=tip_(info["location"]))
|
||||
split.label(text=iface_(info["location"]))
|
||||
if mod:
|
||||
split = colsub.row().split(factor=0.15)
|
||||
split.label(text="File:")
|
||||
|
@ -2259,7 +2260,7 @@ class USERPREF_PT_addons(AddOnPanel, Panel):
|
|||
if info["warning"]:
|
||||
split = colsub.row().split(factor=0.15)
|
||||
split.label(text="Warning:")
|
||||
split.label(text=" " + info["warning"], icon='ERROR')
|
||||
split.label(text=" " + iface_(info["warning"]), icon='ERROR')
|
||||
|
||||
user_addon = USERPREF_PT_addons.is_user_addon(mod, user_addon_paths)
|
||||
if info["doc_url"] or info.get("tracker_url"):
|
||||
|
@ -2370,7 +2371,7 @@ class StudioLightPanelMixin:
|
|||
layout.label(text=self.get_error_message())
|
||||
|
||||
def get_error_message(self):
|
||||
return tip_("No custom %s configured") % self.bl_label
|
||||
return rpt_("No custom %s configured") % self.bl_label
|
||||
|
||||
def draw_studio_light(self, layout, studio_light):
|
||||
box = layout.box()
|
||||
|
@ -2398,7 +2399,7 @@ class USERPREF_PT_studiolight_matcaps(StudioLightPanel, StudioLightPanelMixin, P
|
|||
layout.separator()
|
||||
|
||||
def get_error_message(self):
|
||||
return tip_("No custom MatCaps configured")
|
||||
return rpt_("No custom MatCaps configured")
|
||||
|
||||
|
||||
class USERPREF_PT_studiolight_world(StudioLightPanel, StudioLightPanelMixin, Panel):
|
||||
|
@ -2411,7 +2412,7 @@ class USERPREF_PT_studiolight_world(StudioLightPanel, StudioLightPanelMixin, Pan
|
|||
layout.separator()
|
||||
|
||||
def get_error_message(self):
|
||||
return tip_("No custom HDRIs configured")
|
||||
return rpt_("No custom HDRIs configured")
|
||||
|
||||
|
||||
class USERPREF_PT_studiolight_lights(StudioLightPanel, StudioLightPanelMixin, Panel):
|
||||
|
@ -2426,7 +2427,7 @@ class USERPREF_PT_studiolight_lights(StudioLightPanel, StudioLightPanelMixin, Pa
|
|||
layout.separator()
|
||||
|
||||
def get_error_message(self):
|
||||
return tip_("No custom Studio Lights configured")
|
||||
return rpt_("No custom Studio Lights configured")
|
||||
|
||||
|
||||
class USERPREF_PT_studiolight_light_editor(StudioLightPanel, Panel):
|
||||
|
|
|
@ -24,7 +24,7 @@ from bl_ui.space_toolsystem_common import (
|
|||
)
|
||||
from bpy.app.translations import (
|
||||
pgettext_iface as iface_,
|
||||
pgettext_tip as tip_,
|
||||
pgettext_rpt as rpt_,
|
||||
contexts as i18n_contexts,
|
||||
)
|
||||
|
||||
|
@ -2180,6 +2180,10 @@ class VIEW3D_MT_paint_grease_pencil(Menu):
|
|||
|
||||
layout.menu("VIEW3D_MT_edit_greasepencil_showhide")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("paint.sample_color")
|
||||
|
||||
|
||||
class VIEW3D_MT_paint_gpencil(Menu):
|
||||
bl_label = "Paint"
|
||||
|
@ -2861,16 +2865,16 @@ class VIEW3D_MT_object_context_menu(Menu):
|
|||
props.data_path_item = "data.lens"
|
||||
props.input_scale = 0.1
|
||||
if obj.data.lens_unit == 'MILLIMETERS':
|
||||
props.header_text = tip_("Camera Focal Length: %.1fmm")
|
||||
props.header_text = rpt_("Camera Focal Length: %.1fmm")
|
||||
else:
|
||||
props.header_text = tip_("Camera Focal Length: %.1f\u00B0")
|
||||
props.header_text = rpt_("Camera Focal Length: %.1f\u00B0")
|
||||
|
||||
else:
|
||||
props = layout.operator("wm.context_modal_mouse", text="Camera Lens Scale")
|
||||
props.data_path_iter = "selected_editable_objects"
|
||||
props.data_path_item = "data.ortho_scale"
|
||||
props.input_scale = 0.01
|
||||
props.header_text = tip_("Camera Lens Scale: %.3f")
|
||||
props.header_text = rpt_("Camera Lens Scale: %.3f")
|
||||
|
||||
if not obj.data.dof.focus_object:
|
||||
if view and view.camera == obj and view.region_3d.view_perspective == 'CAMERA':
|
||||
|
@ -2880,7 +2884,7 @@ class VIEW3D_MT_object_context_menu(Menu):
|
|||
props.data_path_iter = "selected_editable_objects"
|
||||
props.data_path_item = "data.dof.focus_distance"
|
||||
props.input_scale = 0.02
|
||||
props.header_text = tip_("Focus Distance: %.3f")
|
||||
props.header_text = rpt_("Focus Distance: %.3f")
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
@ -2891,13 +2895,13 @@ class VIEW3D_MT_object_context_menu(Menu):
|
|||
props.data_path_iter = "selected_editable_objects"
|
||||
props.data_path_item = "data.extrude"
|
||||
props.input_scale = 0.01
|
||||
props.header_text = tip_("Extrude: %.3f")
|
||||
props.header_text = rpt_("Extrude: %.3f")
|
||||
|
||||
props = layout.operator("wm.context_modal_mouse", text="Adjust Offset")
|
||||
props.data_path_iter = "selected_editable_objects"
|
||||
props.data_path_item = "data.offset"
|
||||
props.input_scale = 0.01
|
||||
props.header_text = tip_("Offset: %.3f")
|
||||
props.header_text = rpt_("Offset: %.3f")
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
@ -2908,7 +2912,7 @@ class VIEW3D_MT_object_context_menu(Menu):
|
|||
props.data_path_iter = "selected_editable_objects"
|
||||
props.data_path_item = "empty_display_size"
|
||||
props.input_scale = 0.01
|
||||
props.header_text = tip_("Empty Display Size: %.3f")
|
||||
props.header_text = rpt_("Empty Display Size: %.3f")
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
@ -2926,36 +2930,36 @@ class VIEW3D_MT_object_context_menu(Menu):
|
|||
props.data_path_iter = "selected_editable_objects"
|
||||
props.data_path_item = "data.energy"
|
||||
props.input_scale = 1.0
|
||||
props.header_text = tip_("Light Power: %.3f")
|
||||
props.header_text = rpt_("Light Power: %.3f")
|
||||
|
||||
if light.type == 'AREA':
|
||||
if light.shape in {'RECTANGLE', 'ELLIPSE'}:
|
||||
props = layout.operator("wm.context_modal_mouse", text="Adjust Area Light X Size")
|
||||
props.data_path_iter = "selected_editable_objects"
|
||||
props.data_path_item = "data.size"
|
||||
props.header_text = tip_("Light Size X: %.3f")
|
||||
props.header_text = rpt_("Light Size X: %.3f")
|
||||
|
||||
props = layout.operator("wm.context_modal_mouse", text="Adjust Area Light Y Size")
|
||||
props.data_path_iter = "selected_editable_objects"
|
||||
props.data_path_item = "data.size_y"
|
||||
props.header_text = tip_("Light Size Y: %.3f")
|
||||
props.header_text = rpt_("Light Size Y: %.3f")
|
||||
else:
|
||||
props = layout.operator("wm.context_modal_mouse", text="Adjust Area Light Size")
|
||||
props.data_path_iter = "selected_editable_objects"
|
||||
props.data_path_item = "data.size"
|
||||
props.header_text = tip_("Light Size: %.3f")
|
||||
props.header_text = rpt_("Light Size: %.3f")
|
||||
|
||||
elif light.type in {'SPOT', 'POINT'}:
|
||||
props = layout.operator("wm.context_modal_mouse", text="Adjust Light Radius")
|
||||
props.data_path_iter = "selected_editable_objects"
|
||||
props.data_path_item = "data.shadow_soft_size"
|
||||
props.header_text = tip_("Light Radius: %.3f")
|
||||
props.header_text = rpt_("Light Radius: %.3f")
|
||||
|
||||
elif light.type == 'SUN':
|
||||
props = layout.operator("wm.context_modal_mouse", text="Adjust Sun Light Angle")
|
||||
props.data_path_iter = "selected_editable_objects"
|
||||
props.data_path_item = "data.angle"
|
||||
props.header_text = tip_("Light Angle: %.3f")
|
||||
props.header_text = rpt_("Light Angle: %.3f")
|
||||
|
||||
if light.type == 'SPOT':
|
||||
layout.separator()
|
||||
|
@ -2964,13 +2968,13 @@ class VIEW3D_MT_object_context_menu(Menu):
|
|||
props.data_path_iter = "selected_editable_objects"
|
||||
props.data_path_item = "data.spot_size"
|
||||
props.input_scale = 0.01
|
||||
props.header_text = tip_("Spot Size: %.2f")
|
||||
props.header_text = rpt_("Spot Size: %.2f")
|
||||
|
||||
props = layout.operator("wm.context_modal_mouse", text="Adjust Spot Light Blend")
|
||||
props.data_path_iter = "selected_editable_objects"
|
||||
props.data_path_item = "data.spot_blend"
|
||||
props.input_scale = -0.01
|
||||
props.header_text = tip_("Spot Blend: %.2f")
|
||||
props.header_text = rpt_("Spot Blend: %.2f")
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
@ -5821,10 +5825,13 @@ class VIEW3D_MT_edit_greasepencil_stroke(Menu):
|
|||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
layout.operator("grease_pencil.stroke_subdivide", text="Subdivide")
|
||||
layout.operator("grease_pencil.stroke_subdivide_smooth", text="Subdivide and Smooth")
|
||||
layout.operator("grease_pencil.stroke_simplify", text="Simplify")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.menu("VIEW3D_MT_grease_pencil_assign_material")
|
||||
layout.operator("grease_pencil.set_active_material")
|
||||
|
||||
layout.separator()
|
||||
|
@ -8133,6 +8140,27 @@ class VIEW3D_MT_greasepencil_material_active(Menu):
|
|||
layout.operator("grease_pencil.set_material", text=mat.name, icon_value=icon).slot = mat.name
|
||||
|
||||
|
||||
class VIEW3D_MT_grease_pencil_assign_material(Menu):
|
||||
bl_label = "Assign Material"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
ob = context.active_object
|
||||
mat_active = ob.active_material
|
||||
|
||||
if len(ob.material_slots) == 0:
|
||||
row = layout.row()
|
||||
row.label(text="No Materials")
|
||||
row.enabled = False
|
||||
return
|
||||
|
||||
for slot in ob.material_slots:
|
||||
mat = slot.material
|
||||
if mat:
|
||||
layout.operator("grease_pencil.stroke_material_set", text=mat.name,
|
||||
icon='LAYER_ACTIVE' if mat == mat_active else 'BLANK1').material = mat.name
|
||||
|
||||
|
||||
class VIEW3D_MT_greasepencil_edit_context_menu(Menu):
|
||||
bl_label = ""
|
||||
|
||||
|
@ -8152,6 +8180,8 @@ class VIEW3D_MT_greasepencil_edit_context_menu(Menu):
|
|||
col.label(text="Point", icon='GP_SELECT_POINTS')
|
||||
|
||||
# Main Strokes Operators
|
||||
col.operator("grease_pencil.stroke_subdivide", text="Subdivide")
|
||||
col.operator("grease_pencil.stroke_subdivide_smooth", text="Subdivide and Smooth")
|
||||
col.operator("grease_pencil.stroke_simplify", text="Simplify")
|
||||
|
||||
col.separator()
|
||||
|
@ -8178,6 +8208,8 @@ class VIEW3D_MT_greasepencil_edit_context_menu(Menu):
|
|||
col.label(text="Stroke", icon='GP_SELECT_STROKES')
|
||||
|
||||
# Main Strokes Operators
|
||||
col.operator("grease_pencil.stroke_subdivide", text="Subdivide")
|
||||
col.operator("grease_pencil.stroke_subdivide_smooth", text="Subdivide and Smooth")
|
||||
col.operator("grease_pencil.stroke_simplify", text="Simplify")
|
||||
|
||||
col.separator()
|
||||
|
@ -8188,6 +8220,11 @@ class VIEW3D_MT_greasepencil_edit_context_menu(Menu):
|
|||
|
||||
col.separator()
|
||||
|
||||
col.menu("VIEW3D_MT_grease_pencil_assign_material")
|
||||
col.operator("grease_pencil.set_active_material", text="Set as Active Material")
|
||||
|
||||
col.separator()
|
||||
|
||||
col.menu("VIEW3D_MT_mirror")
|
||||
|
||||
|
||||
|
@ -8884,6 +8921,7 @@ classes = (
|
|||
VIEW3D_MT_gpencil_autoweights,
|
||||
VIEW3D_MT_gpencil_edit_context_menu,
|
||||
VIEW3D_MT_greasepencil_edit_context_menu,
|
||||
VIEW3D_MT_grease_pencil_assign_material,
|
||||
VIEW3D_MT_edit_greasepencil,
|
||||
VIEW3D_MT_edit_greasepencil_delete,
|
||||
VIEW3D_MT_edit_greasepencil_stroke,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Example of a group that edits a single property
|
||||
# using the predefined gizmo arrow.
|
||||
#
|
||||
# Usage: Select a light in the 3D view and drag the arrow at it's rear
|
||||
# to change it's energy value.
|
||||
# Usage: Select a light in the 3D view and drag the arrow at its rear
|
||||
# to change its energy value.
|
||||
#
|
||||
import bpy
|
||||
from bpy.types import (
|
||||
|
|
|
@ -49,8 +49,11 @@ BoneCollection *ANIM_bonecoll_new(const char *name) ATTR_WARN_UNUSED_RESULT;
|
|||
* of a bArmature. Normally bone collections are owned (and thus managed) by the armature.
|
||||
*
|
||||
* \see ANIM_armature_bonecoll_remove
|
||||
*
|
||||
* \param do_id_user_count whether to update user counts for IDs referenced from IDProperties of
|
||||
* the bone collection. Needs to be false when freeing a CoW copy, true otherwise.
|
||||
*/
|
||||
void ANIM_bonecoll_free(BoneCollection *bcoll);
|
||||
void ANIM_bonecoll_free(BoneCollection *bcoll, bool do_id_user_count = true);
|
||||
|
||||
/**
|
||||
* Recalculate the armature & bone runtime data.
|
||||
|
@ -68,7 +71,7 @@ void ANIM_armature_runtime_free(bArmature *armature);
|
|||
/**
|
||||
* Add a new bone collection to the given armature.
|
||||
*
|
||||
* \param parent_index Index into the Armature's `collections_array`. -1 adds it
|
||||
* \param parent_index: Index into the Armature's `collections_array`. -1 adds it
|
||||
* as a root (i.e. parentless) collection.
|
||||
*
|
||||
* The Armature owns the returned pointer.
|
||||
|
@ -364,14 +367,14 @@ bool bonecoll_has_children(const BoneCollection *bcoll);
|
|||
/**
|
||||
* Move a bone collection from one parent to another.
|
||||
*
|
||||
* \param from_bcoll_index index of the bone collection to move.
|
||||
* \param to_child_num gap index of where to insert the collection; 0 to make it
|
||||
* \param from_bcoll_index: Index of the bone collection to move.
|
||||
* \param to_child_num: Gap index of where to insert the collection; 0 to make it
|
||||
* the first child, and parent->child_count to make it the last child. -1 also
|
||||
* works as an indicator for the last child, as that makes it possible to call
|
||||
* this function without requiring the caller to find the BoneCollection* of the
|
||||
* parent.
|
||||
* \param from_parent_index index of its current parent (-1 if it is a root collection).
|
||||
* \param to_parent_index index of the new parent (-1 if it is to become a root collection).
|
||||
* \param from_parent_index: Index of its current parent (-1 if it is a root collection).
|
||||
* \param to_parent_index: Index of the new parent (-1 if it is to become a root collection).
|
||||
* \return the collection's new index in the collections_array.
|
||||
*/
|
||||
int armature_bonecoll_move_to_parent(bArmature *armature,
|
||||
|
|
|
@ -73,13 +73,13 @@ BoneCollection *ANIM_bonecoll_new(const char *name)
|
|||
return bcoll;
|
||||
}
|
||||
|
||||
void ANIM_bonecoll_free(BoneCollection *bcoll)
|
||||
void ANIM_bonecoll_free(BoneCollection *bcoll, const bool do_id_user_count)
|
||||
{
|
||||
BLI_assert_msg(BLI_listbase_is_empty(&bcoll->bones),
|
||||
"bone collection still has bones assigned to it, will cause dangling pointers in "
|
||||
"bone runtime data");
|
||||
if (bcoll->prop) {
|
||||
IDP_FreeProperty(bcoll->prop);
|
||||
IDP_FreeProperty_ex(bcoll->prop, do_id_user_count);
|
||||
}
|
||||
MEM_delete(bcoll);
|
||||
}
|
||||
|
@ -1157,6 +1157,9 @@ bool armature_bonecoll_is_descendant_of(const bArmature *armature,
|
|||
const int potential_parent_index,
|
||||
const int potential_descendant_index)
|
||||
{
|
||||
BLI_assert_msg(potential_descendant_index >= 0,
|
||||
"Potential descendant has to exist for this function call to make sense.");
|
||||
|
||||
if (armature_bonecoll_is_child_of(armature, potential_parent_index, potential_descendant_index))
|
||||
{
|
||||
/* Found a direct child. */
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace blender::animrig::internal {
|
|||
* Updating those, as well as any references to the rotated element, is the
|
||||
* responsibility of the caller.
|
||||
*
|
||||
* \param direction must be either -1 or 1.
|
||||
* \param direction: Must be either -1 or 1.
|
||||
*/
|
||||
void bonecolls_rotate_block(bArmature *armature, int start_index, int count, int direction);
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include "DEG_depsgraph.hh"
|
||||
#include "DEG_depsgraph_query.hh"
|
||||
#include "DNA_anim_types.h"
|
||||
#include "ED_keyframing.hh"
|
||||
#include "MEM_guardedalloc.h"
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_path.hh"
|
||||
|
@ -69,21 +68,21 @@ void update_autoflags_fcurve_direct(FCurve *fcu, PropertyRNA *prop)
|
|||
}
|
||||
|
||||
/** Used to make curves newly added to a cyclic Action cycle with the correct period. */
|
||||
static void make_new_fcurve_cyclic(const bAction *act, FCurve *fcu)
|
||||
static void make_new_fcurve_cyclic(FCurve *fcu, const blender::float2 &action_range)
|
||||
{
|
||||
/* The curve must contain one (newly-added) keyframe. */
|
||||
if (fcu->totvert != 1 || !fcu->bezt) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float period = act->frame_end - act->frame_start;
|
||||
const float period = action_range[1] - action_range[0];
|
||||
|
||||
if (period < 0.1f) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Move the keyframe into the range. */
|
||||
const float frame_offset = fcu->bezt[0].vec[1][0] - act->frame_start;
|
||||
const float frame_offset = fcu->bezt[0].vec[1][0] - action_range[0];
|
||||
const float fix = floorf(frame_offset / period) * period;
|
||||
|
||||
fcu->bezt[0].vec[0][0] -= fix;
|
||||
|
@ -376,7 +375,7 @@ bool insert_keyframe_direct(ReportList *reports,
|
|||
PointerRNA tmp_ptr;
|
||||
|
||||
if (RNA_path_resolve_property(&ptr, fcu->rna_path, &tmp_ptr, &prop) == false) {
|
||||
const char *idname = (ptr.owner_id) ? ptr.owner_id->name : TIP_("<No ID pointer>");
|
||||
const char *idname = (ptr.owner_id) ? ptr.owner_id->name : RPT_("<No ID pointer>");
|
||||
|
||||
BKE_reportf(reports,
|
||||
RPT_ERROR,
|
||||
|
@ -471,7 +470,7 @@ static bool insert_keyframe_fcurve_value(Main *bmain,
|
|||
const bool is_cyclic_action = (flag & INSERTKEY_CYCLE_AWARE) && BKE_action_is_cyclic(act);
|
||||
|
||||
if (is_cyclic_action && fcu->totvert == 1) {
|
||||
make_new_fcurve_cyclic(act, fcu);
|
||||
make_new_fcurve_cyclic(fcu, {act->frame_start, act->frame_end});
|
||||
}
|
||||
|
||||
/* Update F-Curve flags to ensure proper behavior for property type. */
|
||||
|
@ -495,7 +494,7 @@ static bool insert_keyframe_fcurve_value(Main *bmain,
|
|||
|
||||
/* If the curve is new, make it cyclic if appropriate. */
|
||||
if (is_cyclic_action && is_new_curve) {
|
||||
make_new_fcurve_cyclic(act, fcu);
|
||||
make_new_fcurve_cyclic(fcu, {act->frame_start, act->frame_end});
|
||||
}
|
||||
|
||||
return success;
|
||||
|
@ -530,7 +529,7 @@ int insert_keyframe(Main *bmain,
|
|||
reports,
|
||||
RPT_ERROR,
|
||||
"Could not insert keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
|
||||
(id) ? id->name : TIP_("<Missing ID block>"),
|
||||
(id) ? id->name : RPT_("<Missing ID block>"),
|
||||
rna_path);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -304,6 +304,10 @@ bool autokeyframe_property(bContext *C,
|
|||
return changed;
|
||||
}
|
||||
|
||||
if (driven) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (special) {
|
||||
/* NLA Strip property. */
|
||||
if (is_autokey_on(scene)) {
|
||||
|
@ -321,25 +325,6 @@ bool autokeyframe_property(bContext *C,
|
|||
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, nullptr);
|
||||
}
|
||||
}
|
||||
else if (driven) {
|
||||
/* Driver - Try to insert keyframe using the driver's input as the frame,
|
||||
* making it easier to set up corrective drivers.
|
||||
*/
|
||||
if (is_autokey_on(scene)) {
|
||||
ReportList *reports = CTX_wm_reports(C);
|
||||
ToolSettings *ts = scene->toolsettings;
|
||||
|
||||
changed = insert_keyframe_direct(reports,
|
||||
*ptr,
|
||||
prop,
|
||||
fcu,
|
||||
&anim_eval_context,
|
||||
eBezTriple_KeyframeType(ts->keyframe_type),
|
||||
nullptr,
|
||||
INSERTKEY_DRIVER);
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, nullptr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ID *id = ptr->owner_id;
|
||||
Main *bmain = CTX_data_main(C);
|
||||
|
|
|
@ -29,7 +29,7 @@ extern "C" {
|
|||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 9
|
||||
#define BLENDER_FILE_SUBVERSION 10
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and cancel loading the file, showing a warning to
|
||||
|
|
|
@ -218,8 +218,16 @@ bool BKE_collection_object_cyclic_check(struct Main *bmain,
|
|||
|
||||
struct ListBase BKE_collection_object_cache_get(struct Collection *collection);
|
||||
ListBase BKE_collection_object_cache_instanced_get(struct Collection *collection);
|
||||
/** Free the object cache of given `collection` and all of its ancestors (recursively). */
|
||||
void BKE_collection_object_cache_free(struct Collection *collection);
|
||||
/** Free the object cache of given `collection` and all of its ancestors (recursively).
|
||||
*
|
||||
* \param bmain: The Main database owning the collection. May be `nullptr`, only used if doing
|
||||
* depsgraph tagging.
|
||||
* \param id_create_flag: Flags controlling ID creation, used here to enable or
|
||||
* not depsgraph tagging of affected IDs (e.g. #LIB_ID_CREATE_NO_DEG_TAG would prevent depsgraph
|
||||
* tagging). */
|
||||
void BKE_collection_object_cache_free(const struct Main *bmain,
|
||||
struct Collection *collection,
|
||||
const int id_create_flag);
|
||||
/**
|
||||
* Free the object cache of all collections in given `bmain`, including master collections of
|
||||
* scenes.
|
||||
|
@ -261,7 +269,9 @@ bool BKE_collection_child_add(struct Main *bmain,
|
|||
struct Collection *parent,
|
||||
struct Collection *child);
|
||||
|
||||
bool BKE_collection_child_add_no_sync(struct Collection *parent, struct Collection *child);
|
||||
bool BKE_collection_child_add_no_sync(struct Main *bmain,
|
||||
struct Collection *parent,
|
||||
struct Collection *child);
|
||||
|
||||
bool BKE_collection_child_remove(struct Main *bmain,
|
||||
struct Collection *parent,
|
||||
|
|
|
@ -166,7 +166,7 @@ class CurvesGeometry : public ::CurvesGeometry {
|
|||
/**
|
||||
* Mutable access to curve types. Call #tag_topology_changed and #update_curve_types after
|
||||
* changing any type. Consider using the other methods to change types below.
|
||||
* */
|
||||
*/
|
||||
MutableSpan<int8_t> curve_types_for_write();
|
||||
/** Set all curve types to the value and call #update_curve_types. */
|
||||
void fill_curve_types(CurveType type);
|
||||
|
|
|
@ -136,7 +136,7 @@ float driver_get_variable_value(const struct AnimationEvalContext *anim_eval_con
|
|||
struct DriverVar *dvar);
|
||||
|
||||
typedef enum eDriverVariablePropertyResult {
|
||||
/** The property reference has been succesfully resolved and can be accessed. */
|
||||
/** The property reference has been successfully resolved and can be accessed. */
|
||||
DRIVER_VAR_PROPERTY_SUCCESS,
|
||||
/** Evaluation should use the fallback value. */
|
||||
DRIVER_VAR_PROPERTY_FALLBACK,
|
||||
|
|
|
@ -447,6 +447,7 @@ class MeshComponent : public GeometryComponent {
|
|||
|
||||
public:
|
||||
MeshComponent();
|
||||
MeshComponent(Mesh *mesh, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
|
||||
~MeshComponent();
|
||||
GeometryComponentPtr copy() const override;
|
||||
|
||||
|
@ -501,6 +502,8 @@ class PointCloudComponent : public GeometryComponent {
|
|||
|
||||
public:
|
||||
PointCloudComponent();
|
||||
PointCloudComponent(PointCloud *pointcloud,
|
||||
GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
|
||||
~PointCloudComponent();
|
||||
GeometryComponentPtr copy() const override;
|
||||
|
||||
|
@ -561,6 +564,7 @@ class CurveComponent : public GeometryComponent {
|
|||
|
||||
public:
|
||||
CurveComponent();
|
||||
CurveComponent(Curves *curve, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
|
||||
~CurveComponent();
|
||||
GeometryComponentPtr copy() const override;
|
||||
|
||||
|
@ -602,6 +606,8 @@ class InstancesComponent : public GeometryComponent {
|
|||
|
||||
public:
|
||||
InstancesComponent();
|
||||
InstancesComponent(Instances *instances,
|
||||
GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
|
||||
~InstancesComponent();
|
||||
GeometryComponentPtr copy() const override;
|
||||
|
||||
|
|
|
@ -818,7 +818,6 @@ void BKE_grease_pencil_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
|
|||
void BKE_grease_pencil_duplicate_drawing_array(const GreasePencil *grease_pencil_src,
|
||||
GreasePencil *grease_pencil_dst);
|
||||
|
||||
int BKE_grease_pencil_object_material_index_get(Object *ob, Material *ma);
|
||||
int BKE_grease_pencil_object_material_index_get_by_name(Object *ob, const char *name);
|
||||
Material *BKE_grease_pencil_object_material_new(Main *bmain,
|
||||
Object *ob,
|
||||
|
|
|
@ -114,6 +114,9 @@ bool BKE_object_material_slot_add(struct Main *bmain, struct Object *ob);
|
|||
bool BKE_object_material_slot_remove(struct Main *bmain, struct Object *ob);
|
||||
bool BKE_object_material_slot_used(struct Object *object, short actcol);
|
||||
|
||||
int BKE_object_material_index_get(Object *ob, Material *ma);
|
||||
int BKE_object_material_ensure(Main *bmain, Object *ob, Material *material);
|
||||
|
||||
struct Material *BKE_gpencil_material(struct Object *ob, short act);
|
||||
struct MaterialGPencilStyle *BKE_gpencil_material_settings(struct Object *ob, short act);
|
||||
|
||||
|
|
|
@ -364,7 +364,7 @@ bool BKE_mesh_has_custom_loop_normals(struct Mesh *mesh);
|
|||
|
||||
/**
|
||||
* Higher level functions hiding most of the code needed around call to
|
||||
* #normals_loop_custom_set().
|
||||
* #normals_corner_custom_set().
|
||||
*
|
||||
* \param r_custom_loop_normals: is not const, since code will replace zero_v3 normals there
|
||||
* with automatically computed vectors.
|
||||
|
@ -372,7 +372,7 @@ bool BKE_mesh_has_custom_loop_normals(struct Mesh *mesh);
|
|||
void BKE_mesh_set_custom_normals(struct Mesh *mesh, float (*r_custom_loop_normals)[3]);
|
||||
/**
|
||||
* Higher level functions hiding most of the code needed around call to
|
||||
* #normals_loop_custom_set_from_verts().
|
||||
* #normals_corner_custom_set_from_verts().
|
||||
*
|
||||
* \param r_custom_vert_normals: is not const, since code will replace zero_v3 normals there
|
||||
* with automatically computed vectors.
|
||||
|
|
|
@ -157,13 +157,12 @@ struct CornerNormalSpaceArray {
|
|||
bool create_corners_by_space = false;
|
||||
};
|
||||
|
||||
short2 lnor_space_custom_normal_to_data(const CornerNormalSpace &lnor_space,
|
||||
const float3 &custom_lnor);
|
||||
short2 corner_space_custom_normal_to_data(const CornerNormalSpace &lnor_space,
|
||||
const float3 &custom_lnor);
|
||||
|
||||
/**
|
||||
* Compute split normals, i.e. vertex normals associated with each face (hence 'loop normals').
|
||||
* Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry
|
||||
* (splitting edges).
|
||||
* Compute split normals, i.e. vertex normals associated with each face. Used to visualize sharp
|
||||
* edges (or non-smooth faces) without actually modifying the geometry (splitting edges).
|
||||
*
|
||||
* \param sharp_edges: Optional array of sharp edge tags, used to split the evaluated normals on
|
||||
* each side of the edge.
|
||||
|
@ -172,54 +171,54 @@ short2 lnor_space_custom_normal_to_data(const CornerNormalSpace &lnor_space,
|
|||
* \param r_lnors_spacearr: Optional return data filled with information about the custom
|
||||
* normals spaces for each grouped fan of face corners.
|
||||
*/
|
||||
void normals_calc_loop(Span<float3> vert_positions,
|
||||
Span<int2> edges,
|
||||
OffsetIndices<int> faces,
|
||||
Span<int> corner_verts,
|
||||
Span<int> corner_edges,
|
||||
Span<int> loop_to_face_map,
|
||||
Span<float3> vert_normals,
|
||||
Span<float3> face_normals,
|
||||
Span<bool> sharp_edges,
|
||||
Span<bool> sharp_faces,
|
||||
const short2 *clnors_data,
|
||||
CornerNormalSpaceArray *r_lnors_spacearr,
|
||||
MutableSpan<float3> r_loop_normals);
|
||||
void normals_calc_corners(Span<float3> vert_positions,
|
||||
Span<int2> edges,
|
||||
OffsetIndices<int> faces,
|
||||
Span<int> corner_verts,
|
||||
Span<int> corner_edges,
|
||||
Span<int> corner_to_face_map,
|
||||
Span<float3> vert_normals,
|
||||
Span<float3> face_normals,
|
||||
Span<bool> sharp_edges,
|
||||
Span<bool> sharp_faces,
|
||||
const short2 *clnors_data,
|
||||
CornerNormalSpaceArray *r_lnors_spacearr,
|
||||
MutableSpan<float3> r_corner_normals);
|
||||
|
||||
/**
|
||||
* \param sharp_faces: Optional array used to mark specific faces for sharp shading.
|
||||
*/
|
||||
void normals_loop_custom_set(Span<float3> vert_positions,
|
||||
Span<int2> edges,
|
||||
OffsetIndices<int> faces,
|
||||
Span<int> corner_verts,
|
||||
Span<int> corner_edges,
|
||||
Span<float3> vert_normals,
|
||||
Span<float3> face_normals,
|
||||
Span<bool> sharp_faces,
|
||||
MutableSpan<bool> sharp_edges,
|
||||
MutableSpan<float3> r_custom_loop_normals,
|
||||
MutableSpan<short2> r_clnors_data);
|
||||
void normals_corner_custom_set(Span<float3> vert_positions,
|
||||
Span<int2> edges,
|
||||
OffsetIndices<int> faces,
|
||||
Span<int> corner_verts,
|
||||
Span<int> corner_edges,
|
||||
Span<float3> vert_normals,
|
||||
Span<float3> face_normals,
|
||||
Span<bool> sharp_faces,
|
||||
MutableSpan<bool> sharp_edges,
|
||||
MutableSpan<float3> r_custom_corner_normals,
|
||||
MutableSpan<short2> r_clnors_data);
|
||||
|
||||
/**
|
||||
* \param sharp_faces: Optional array used to mark specific faces for sharp shading.
|
||||
*/
|
||||
void normals_loop_custom_set_from_verts(Span<float3> vert_positions,
|
||||
Span<int2> edges,
|
||||
OffsetIndices<int> faces,
|
||||
Span<int> corner_verts,
|
||||
Span<int> corner_edges,
|
||||
Span<float3> vert_normals,
|
||||
Span<float3> face_normals,
|
||||
Span<bool> sharp_faces,
|
||||
MutableSpan<bool> sharp_edges,
|
||||
MutableSpan<float3> r_custom_vert_normals,
|
||||
MutableSpan<short2> r_clnors_data);
|
||||
void normals_corner_custom_set_from_verts(Span<float3> vert_positions,
|
||||
Span<int2> edges,
|
||||
OffsetIndices<int> faces,
|
||||
Span<int> corner_verts,
|
||||
Span<int> corner_edges,
|
||||
Span<float3> vert_normals,
|
||||
Span<float3> face_normals,
|
||||
Span<bool> sharp_faces,
|
||||
MutableSpan<bool> sharp_edges,
|
||||
MutableSpan<float3> r_custom_vert_normals,
|
||||
MutableSpan<short2> r_clnors_data);
|
||||
|
||||
/**
|
||||
* Define sharp edges as needed to mimic 'autosmooth' from angle threshold.
|
||||
*
|
||||
* Used when defining an empty custom loop normals data layer,
|
||||
* Used when defining an empty custom corner normals data layer,
|
||||
* to keep same shading as with auto-smooth!
|
||||
*
|
||||
* \param sharp_faces: Optional array used to mark specific faces for sharp shading.
|
||||
|
@ -228,7 +227,7 @@ void edges_sharp_from_angle_set(OffsetIndices<int> faces,
|
|||
Span<int> corner_verts,
|
||||
Span<int> corner_edges,
|
||||
Span<float3> face_normals,
|
||||
Span<int> loop_to_face,
|
||||
Span<int> corner_to_face,
|
||||
Span<bool> sharp_faces,
|
||||
const float split_angle,
|
||||
MutableSpan<bool> sharp_edges);
|
||||
|
|
|
@ -274,7 +274,7 @@ int *BKE_mesh_calc_smoothgroups(int edges_num,
|
|||
|
||||
namespace blender::bke::mesh {
|
||||
|
||||
Array<int> build_loop_to_face_map(OffsetIndices<int> faces);
|
||||
Array<int> build_corner_to_face_map(OffsetIndices<int> faces);
|
||||
|
||||
GroupedSpan<int> build_vert_to_edge_map(Span<int2> edges,
|
||||
int verts_num,
|
||||
|
@ -292,15 +292,15 @@ GroupedSpan<int> build_vert_to_face_map(OffsetIndices<int> faces,
|
|||
Array<int> &r_indices);
|
||||
|
||||
Array<int> build_vert_to_corner_indices(Span<int> corner_verts, OffsetIndices<int> offsets);
|
||||
GroupedSpan<int> build_vert_to_loop_map(Span<int> corner_verts,
|
||||
int verts_num,
|
||||
Array<int> &r_offsets,
|
||||
Array<int> &r_indices);
|
||||
GroupedSpan<int> build_vert_to_corner_map(Span<int> corner_verts,
|
||||
int verts_num,
|
||||
Array<int> &r_offsets,
|
||||
Array<int> &r_indices);
|
||||
|
||||
GroupedSpan<int> build_edge_to_loop_map(Span<int> corner_edges,
|
||||
int edges_num,
|
||||
Array<int> &r_offsets,
|
||||
Array<int> &r_indices);
|
||||
GroupedSpan<int> build_edge_to_corner_map(Span<int> corner_edges,
|
||||
int edges_num,
|
||||
Array<int> &r_offsets,
|
||||
Array<int> &r_indices);
|
||||
|
||||
GroupedSpan<int> build_edge_to_face_map(OffsetIndices<int> faces,
|
||||
Span<int> corner_edges,
|
||||
|
|
|
@ -68,6 +68,22 @@ enum class ModifierTypeType {
|
|||
enum ModifierTypeFlag {
|
||||
eModifierTypeFlag_AcceptsMesh = (1 << 0),
|
||||
eModifierTypeFlag_AcceptsCVs = (1 << 1),
|
||||
/**
|
||||
* Modifiers that enable this flag can have the modifiers "On Cage" option toggled,
|
||||
* see: #eModifierMode_OnCage, where the output of the modifier can be selected directly.
|
||||
* In some cases the cage geometry use read to tool code as well (loop-cut & knife are examples).
|
||||
*
|
||||
* When set, geometry from the resulting mesh can be mapped back to the original indices
|
||||
* via #CD_ORIGINDEX.
|
||||
*
|
||||
* While many modifiers using this flag preserve the order of geometry arrays,
|
||||
* this isn't always the case, this flag doesn't imply #ModifierTypeType::OnlyDeform.
|
||||
* Geometry from the original mesh may be removed from the resulting mesh or new geometry
|
||||
* may be added (where the #CD_ORIGINDEX value will be #ORIGINDEX_NONE).
|
||||
*
|
||||
* Modifiers that create entirely new geometry from the input should not enable this flag
|
||||
* because none of the geometry will be selectable when "On Cage" is enabled.
|
||||
*/
|
||||
eModifierTypeFlag_SupportsMapping = (1 << 2),
|
||||
eModifierTypeFlag_SupportsEditmode = (1 << 3),
|
||||
|
||||
|
|
|
@ -1327,6 +1327,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
|
|||
#define GEO_NODE_BAKE 2120
|
||||
#define GEO_NODE_GET_NAMED_GRID 2121
|
||||
#define GEO_NODE_STORE_NAMED_GRID 2122
|
||||
#define GEO_NODE_SORT_ELEMENTS 2123
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
|
||||
#include "BLI_vector.hh"
|
||||
|
@ -33,11 +35,17 @@ class bNodeTreeZone {
|
|||
Vector<bNodeTreeZone *> child_zones;
|
||||
/** Direct children nodes excluding nodes that belong to child zones. */
|
||||
Vector<const bNode *> child_nodes;
|
||||
/** Links that enter the zone through the zone border. */
|
||||
/**
|
||||
* Links that enter the zone through the zone border and carry information. This excludes muted
|
||||
* and unavailable links as well as links that are dangling because they are only connected to a
|
||||
* reroute.
|
||||
*/
|
||||
Vector<const bNodeLink *> border_links;
|
||||
|
||||
bool contains_node_recursively(const bNode &node) const;
|
||||
bool contains_zone_recursively(const bNodeTreeZone &other_zone) const;
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &stream, const bNodeTreeZone &zone);
|
||||
};
|
||||
|
||||
class bNodeTreeZones {
|
||||
|
@ -68,6 +76,8 @@ class bNodeTreeZones {
|
|||
* nested zone. For nodes that are at the root level, the returned list is empty.
|
||||
*/
|
||||
Vector<const bNodeTreeZone *> get_zone_stack_for_node(const int32_t node_id) const;
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &stream, const bNodeTreeZones &zones);
|
||||
};
|
||||
|
||||
const bNodeTreeZones *get_tree_zones(const bNodeTree &tree);
|
||||
|
|
|
@ -87,7 +87,14 @@ struct ObjectRuntime {
|
|||
*/
|
||||
Mesh *mesh_deform_eval = nullptr;
|
||||
|
||||
/* Evaluated mesh cage in edit mode. */
|
||||
/**
|
||||
* Evaluated mesh cage in edit mode.
|
||||
*
|
||||
* \note When the mesh's `runtime->deformed_only` is true, the meshes vertex positions
|
||||
* and other geometry arrays will be aligned the edit-mesh. Otherwise the #CD_ORIGINDEX
|
||||
* custom-data should be used to map the cage geometry back to the original indices, see
|
||||
* #eModifierTypeFlag_SupportsMapping.
|
||||
*/
|
||||
Mesh *editmesh_eval_cage = nullptr;
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,20 +9,13 @@
|
|||
* \brief General operations for point clouds.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
# include <mutex>
|
||||
#include <mutex>
|
||||
|
||||
# include "BLI_bounds_types.hh"
|
||||
# include "BLI_math_vector_types.hh"
|
||||
# include "BLI_shared_cache.hh"
|
||||
#include "BLI_bounds_types.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_shared_cache.hh"
|
||||
|
||||
# include "DNA_pointcloud_types.h"
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "DNA_pointcloud_types.h"
|
||||
|
||||
struct Depsgraph;
|
||||
struct Main;
|
||||
|
@ -34,7 +27,6 @@ struct Scene;
|
|||
extern const char *POINTCLOUD_ATTR_POSITION;
|
||||
extern const char *POINTCLOUD_ATTR_RADIUS;
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace blender::bke {
|
||||
|
||||
struct PointCloudRuntime {
|
||||
|
@ -50,8 +42,6 @@ struct PointCloudRuntime {
|
|||
|
||||
} // namespace blender::bke
|
||||
|
||||
#endif
|
||||
|
||||
void *BKE_pointcloud_add(struct Main *bmain, const char *name);
|
||||
void *BKE_pointcloud_add_default(struct Main *bmain, const char *name);
|
||||
struct PointCloud *BKE_pointcloud_new_nomain(int totpoint);
|
||||
|
@ -79,7 +69,3 @@ void BKE_pointcloud_batch_cache_free(struct PointCloud *pointcloud);
|
|||
|
||||
extern void (*BKE_pointcloud_batch_cache_dirty_tag_cb)(struct PointCloud *pointcloud, int mode);
|
||||
extern void (*BKE_pointcloud_batch_cache_free_cb)(struct PointCloud *pointcloud);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -27,6 +27,7 @@ struct BlendWriter;
|
|||
struct Header;
|
||||
struct ID;
|
||||
struct IDRemapper;
|
||||
struct LayoutPanelState;
|
||||
struct LibraryForeachIDData;
|
||||
struct ListBase;
|
||||
struct Menu;
|
||||
|
@ -606,6 +607,14 @@ void BKE_screen_area_free(ScrArea *area);
|
|||
void BKE_region_callback_free_gizmomap_set(void (*callback)(wmGizmoMap *));
|
||||
void BKE_region_callback_refresh_tag_gizmomap_set(void (*callback)(wmGizmoMap *));
|
||||
|
||||
/**
|
||||
* Get the layout panel state for the given idname. If it does not exist yet, initialize a new
|
||||
* panel state with the given default value.
|
||||
*/
|
||||
LayoutPanelState *BKE_panel_layout_panel_state_ensure(Panel *panel,
|
||||
const char *idname,
|
||||
bool default_closed);
|
||||
|
||||
/**
|
||||
* Find a region of type \a region_type in provided \a regionbase.
|
||||
*
|
||||
|
|
|
@ -48,7 +48,7 @@ extern void sbFreeSimulation(struct SoftBody *sb);
|
|||
|
||||
/**
|
||||
* Do one simulation step, reading and writing vertex locs from given array.
|
||||
* */
|
||||
*/
|
||||
extern void sbObjectStep(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Object *ob,
|
||||
|
|
|
@ -37,7 +37,7 @@ enum eSubdivFVarLinearInterpolation {
|
|||
};
|
||||
|
||||
struct SubdivSettings {
|
||||
/* Simple subdivision corresponds to "Simple" option in the interface. When it's enabled the
|
||||
/* Simple subdivision corresponds to "Simple" option in the interface. When it's enabled, the
|
||||
* subdivided mesh is not "smoothed": new vertices are added uniformly on the existing surface.
|
||||
*
|
||||
* On an OpenSubdiv implementation level this translates to a subdivision scheme:
|
||||
|
|
|
@ -29,7 +29,7 @@ struct EditFontSelBox {
|
|||
|
||||
/**
|
||||
* Edit data for #Curve (a text curve, with an #Object::type of `OB_FONT`).
|
||||
* */
|
||||
*/
|
||||
struct EditFont {
|
||||
/** Array of UTF32 code-points. */
|
||||
char32_t *textbuf;
|
||||
|
|
|
@ -139,12 +139,6 @@ class VolumeGridData : public ImplicitSharingMixin {
|
|||
|
||||
~VolumeGridData();
|
||||
|
||||
/**
|
||||
* Get an access token for the underlying tree. This is necessary to be able to detect whether
|
||||
* the grid is currently unused so that it can be safely unloaded.
|
||||
*/
|
||||
VolumeTreeAccessToken tree_access_token() const;
|
||||
|
||||
/**
|
||||
* Create a copy of the volume grid. This should generally only be done when the current grid is
|
||||
* shared and one owner wants to modify it.
|
||||
|
@ -158,22 +152,20 @@ class VolumeGridData : public ImplicitSharingMixin {
|
|||
* Get the underlying OpenVDB grid for read-only access. This may load the tree lazily if it's
|
||||
* not loaded already.
|
||||
*/
|
||||
const openvdb::GridBase &grid(const VolumeTreeAccessToken &tree_access_token) const;
|
||||
const openvdb::GridBase &grid(VolumeTreeAccessToken &r_token) const;
|
||||
/**
|
||||
* Get the underlying OpenVDB grid for read and write access. This may load the tree lazily if
|
||||
* it's not loaded already. It may also make a copy of the tree if it's currently shared.
|
||||
*/
|
||||
openvdb::GridBase &grid_for_write(const VolumeTreeAccessToken &tree_access_token);
|
||||
openvdb::GridBase &grid_for_write(VolumeTreeAccessToken &r_token);
|
||||
|
||||
/**
|
||||
* Same as #grid and #grid_for_write but returns the grid as a `shared_ptr` so that it can be
|
||||
* used with APIs that only support grids wrapped into one. This method is not supposed to
|
||||
* actually transfer ownership of the grid.
|
||||
*/
|
||||
std::shared_ptr<const openvdb::GridBase> grid_ptr(
|
||||
const VolumeTreeAccessToken &tree_access_token) const;
|
||||
std::shared_ptr<openvdb::GridBase> grid_ptr_for_write(
|
||||
const VolumeTreeAccessToken &tree_access_token);
|
||||
std::shared_ptr<const openvdb::GridBase> grid_ptr(VolumeTreeAccessToken &r_token) const;
|
||||
std::shared_ptr<openvdb::GridBase> grid_ptr_for_write(VolumeTreeAccessToken &r_token);
|
||||
|
||||
/**
|
||||
* Get the name of the grid that's stored in the grid meta-data.
|
||||
|
@ -319,8 +311,8 @@ template<typename T> class VolumeGrid : public GVolumeGrid {
|
|||
/**
|
||||
* Wraps the same methods on #VolumeGridData but casts to the correct OpenVDB type.
|
||||
*/
|
||||
const OpenvdbGridType<T> &grid(const VolumeTreeAccessToken &tree_access_token) const;
|
||||
OpenvdbGridType<T> &grid_for_write(const VolumeTreeAccessToken &tree_access_token);
|
||||
const OpenvdbGridType<T> &grid(VolumeTreeAccessToken &r_token) const;
|
||||
OpenvdbGridType<T> &grid_for_write(VolumeTreeAccessToken &r_token);
|
||||
|
||||
private:
|
||||
void assert_correct_type() const;
|
||||
|
@ -381,18 +373,15 @@ inline VolumeGrid<T>::VolumeGrid(std::shared_ptr<OpenvdbGridType<T>> grid)
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
inline const OpenvdbGridType<T> &VolumeGrid<T>::grid(
|
||||
const VolumeTreeAccessToken &tree_access_token) const
|
||||
inline const OpenvdbGridType<T> &VolumeGrid<T>::grid(VolumeTreeAccessToken &r_token) const
|
||||
{
|
||||
return static_cast<const OpenvdbGridType<T> &>(data_->grid(tree_access_token));
|
||||
return static_cast<const OpenvdbGridType<T> &>(data_->grid(r_token));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline OpenvdbGridType<T> &VolumeGrid<T>::grid_for_write(
|
||||
const VolumeTreeAccessToken &tree_access_token)
|
||||
inline OpenvdbGridType<T> &VolumeGrid<T>::grid_for_write(VolumeTreeAccessToken &r_token)
|
||||
{
|
||||
return static_cast<OpenvdbGridType<T> &>(
|
||||
this->get_for_write().grid_for_write(tree_access_token));
|
||||
return static_cast<OpenvdbGridType<T> &>(this->get_for_write().grid_for_write(r_token));
|
||||
}
|
||||
|
||||
template<typename T> inline void VolumeGrid<T>::assert_correct_type() const
|
||||
|
|
|
@ -475,7 +475,7 @@ set(SRC
|
|||
BKE_pbvh_api.hh
|
||||
BKE_pbvh_pixels.hh
|
||||
BKE_pointcache.h
|
||||
BKE_pointcloud.h
|
||||
BKE_pointcloud.hh
|
||||
BKE_pose_backup.h
|
||||
BKE_preferences.h
|
||||
BKE_preview_image.hh
|
||||
|
|
|
@ -3235,7 +3235,7 @@ static void animsys_create_action_track_strip(const AnimData *adt,
|
|||
/* Must set NLASTRIP_FLAG_USR_INFLUENCE, or else the default setting overrides, and influence
|
||||
* doesn't work.
|
||||
*/
|
||||
r_action_strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
|
||||
r_action_strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE | NLASTRIP_FLAG_NO_TIME_MAP;
|
||||
|
||||
const bool tweaking = (adt->flag & ADT_NLA_EDIT_ON) != 0;
|
||||
const bool soloing = (adt->flag & ADT_NLA_SOLO_TRACK) != 0;
|
||||
|
|
|
@ -137,7 +137,7 @@ bMotionPath *animviz_verify_motionpaths(ReportList *reports,
|
|||
(pchan) ? pchan->name : ob->id.name,
|
||||
avs->path_sf,
|
||||
avs->path_ef,
|
||||
(avs->path_sf == avs->path_ef) ? TIP_(", cannot have single-frame paths") : "");
|
||||
(avs->path_sf == avs->path_ef) ? RPT_(", cannot have single-frame paths") : "");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -95,16 +95,19 @@ static void armature_init_data(ID *id)
|
|||
*
|
||||
* Note: this function's use case is narrow in scope, intended only for use in
|
||||
* `armature_copy_data()` below. You probably don't want to use this otherwise.
|
||||
*
|
||||
* \param lib_id_flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
|
||||
*/
|
||||
static void copy_bone_collection(bArmature *armature_dst,
|
||||
BoneCollection *&bcoll_dst,
|
||||
const BoneCollection *bcoll_src)
|
||||
const BoneCollection *bcoll_src,
|
||||
const int lib_id_flag)
|
||||
{
|
||||
bcoll_dst = static_cast<BoneCollection *>(MEM_dupallocN(bcoll_src));
|
||||
|
||||
/* ID properties. */
|
||||
if (bcoll_dst->prop) {
|
||||
bcoll_dst->prop = IDP_CopyProperty(bcoll_dst->prop);
|
||||
bcoll_dst->prop = IDP_CopyProperty_ex(bcoll_dst->prop, lib_id_flag);
|
||||
}
|
||||
|
||||
/* Bone references. */
|
||||
|
@ -169,8 +172,10 @@ static void armature_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, c
|
|||
MEM_dupallocN(armature_src->collection_array));
|
||||
armature_dst->collection_array_num = armature_src->collection_array_num;
|
||||
for (int i = 0; i < armature_src->collection_array_num; i++) {
|
||||
copy_bone_collection(
|
||||
armature_dst, armature_dst->collection_array[i], armature_src->collection_array[i]);
|
||||
copy_bone_collection(armature_dst,
|
||||
armature_dst->collection_array[i],
|
||||
armature_src->collection_array[i],
|
||||
flag);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -193,7 +198,7 @@ static void armature_free_data(ID *id)
|
|||
if (armature->collection_array) {
|
||||
for (BoneCollection *bcoll : armature->collections_span()) {
|
||||
BLI_freelistN(&bcoll->bones);
|
||||
ANIM_bonecoll_free(bcoll);
|
||||
ANIM_bonecoll_free(bcoll, false);
|
||||
}
|
||||
MEM_freeN(armature->collection_array);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include "BKE_editmesh.hh"
|
||||
#include "BKE_grease_pencil.hh"
|
||||
#include "BKE_mesh.hh"
|
||||
#include "BKE_pointcloud.h"
|
||||
#include "BKE_pointcloud.hh"
|
||||
#include "BKE_report.h"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
|
|
|
@ -936,29 +936,6 @@ void gather_attributes(const AttributeAccessor src_attributes,
|
|||
});
|
||||
}
|
||||
|
||||
static bool indices_are_range(const Span<int> indices, const IndexRange range)
|
||||
{
|
||||
if (indices.size() != range.size()) {
|
||||
return false;
|
||||
}
|
||||
return threading::parallel_reduce(
|
||||
range,
|
||||
4096,
|
||||
true,
|
||||
[&](const IndexRange range, const bool init) {
|
||||
if (!init) {
|
||||
return false;
|
||||
}
|
||||
for (const int i : range) {
|
||||
if (indices[i] != i) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
std::logical_and());
|
||||
}
|
||||
|
||||
void gather_attributes(const AttributeAccessor src_attributes,
|
||||
const AttrDomain domain,
|
||||
const AnonymousAttributePropagationInfo &propagation_info,
|
||||
|
@ -966,7 +943,7 @@ void gather_attributes(const AttributeAccessor src_attributes,
|
|||
const Span<int> indices,
|
||||
MutableAttributeAccessor dst_attributes)
|
||||
{
|
||||
if (indices_are_range(indices, IndexRange(src_attributes.domain_size(domain)))) {
|
||||
if (array_utils::indices_are_range(indices, IndexRange(src_attributes.domain_size(domain)))) {
|
||||
copy_attributes(src_attributes, domain, propagation_info, skip, dst_attributes);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "BKE_instances.hh"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_mesh.hh"
|
||||
#include "BKE_pointcloud.h"
|
||||
#include "BKE_pointcloud.hh"
|
||||
|
||||
#include "BLI_endian_defines.h"
|
||||
#include "BLI_endian_switch.h"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue