Compare commits

..

29 Commits

Author SHA1 Message Date
ad3d5b5ff6 Merge branch 'master' into eevee-gpencil 2021-06-06 16:02:56 +02:00
2471986440 Merge branch 'master' into eevee-gpencil 2021-06-05 22:19:26 +02:00
7672e32137 Merge branch 'master' into eevee-gpencil 2021-06-05 12:50:24 +02:00
82cc3b5cc2 Merge branch 'master' into eevee-gpencil 2021-06-04 19:15:23 +02:00
786aa4b518 Merge branch 'master' into eevee-gpencil 2021-05-26 12:43:49 +02:00
0330805ec7 Merge branch 'master' into eevee-gpencil 2021-05-21 15:49:44 +02:00
e4ed986b97 Merge branch 'master' into eevee-gpencil 2021-05-10 10:30:41 +02:00
4350b18d85 Merge branch 'master' into eevee-gpencil 2021-04-25 18:51:16 +02:00
37ad0a95cf Merge branch 'master' into eevee-gpencil 2021-04-19 16:37:11 +02:00
c49681b43b Merge branch 'master' into eevee-gpencil 2021-04-17 15:45:23 +02:00
35640a8d60 Merge branch 'master' into eevee-gpencil 2021-04-14 15:44:39 +02:00
fcd2e920b4 Merge branch 'master' into eevee-gpencil 2021-04-12 13:35:14 +02:00
f3d010df11 Merge branch 'master' into eevee-gpencil 2021-04-09 10:44:42 +02:00
cf9a23d9a2 Merge branch 'master' into eevee-gpencil 2021-04-07 16:25:09 +02:00
a0981ce0ff Merge branch 'master' into eevee-gpencil 2021-04-01 17:40:54 +02:00
f97b9e99bc Merge branch 'master' into eevee-gpencil 2021-03-30 10:00:33 +02:00
90516f1af4 Merge branch 'master' into eevee-gpencil 2021-03-29 18:33:52 +02:00
76de19a1d4 Merge branch 'master' into eevee-gpencil 2021-03-27 15:04:34 +01:00
1605a19bc4 Merge branch 'master' into eevee-gpencil 2021-03-24 16:19:16 +01:00
64ab5f77a2 Merge branch 'master' into eevee-gpencil 2021-03-23 15:51:34 +01:00
d94e3814c5 EEVEE: Enable GPencil Material Cast Shadows by default 2021-03-21 10:43:03 +01:00
a98fd628ca Merge branch 'master' into eevee-gpencil 2021-03-21 10:28:45 +01:00
52ec2269af Merge branch 'master' into eevee-gpencil 2021-03-19 18:21:17 +01:00
65700fc064 EEVEE: Add Shadow option as GPencil Layer level
Now there are tow options to enable the shadows, at material level and layer level.

Also, renamed `show_shadows` to `use_cast_shadows`
2021-03-19 16:19:56 +01:00
3163e8988c Merge branch 'master' into eevee-gpencil 2021-03-19 15:39:29 +01:00
8df9002ad4 EEVEE: Add simplify fill option for shadows 2021-03-18 18:30:03 +01:00
b5cfd81519 Merge branch 'master' into eevee-gpencil 2021-03-18 17:26:29 +01:00
88395ad654 EEVEE: Add a parameter to disable shadows by material
The new option is in the Options panels, but it can be moved in the future.
2021-03-18 17:18:53 +01:00
1fd04e0dec EEVEE: Add basic support of GPencil objects
This only adds support for shadows. The feature is experimental and the
code is rough. Needs more work.
2021-03-18 16:05:32 +01:00
1343 changed files with 14735 additions and 27692 deletions

View File

@@ -265,5 +265,4 @@ ForEachMacros:
- VECTOR_SET_SLOT_PROBING_BEGIN
StatementMacros:
- PyObject_HEAD
- PyObject_VAR_HEAD

View File

@@ -836,7 +836,7 @@ if(WITH_PYTHON)
# 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.9")
message(FATAL_ERROR "At least Python 3.9 is required to build, but found Python ${PYTHON_VERSION}")
message(FATAL_ERROR "At least Python 3.9 is required to build")
endif()
file(GLOB RESULT "${CMAKE_SOURCE_DIR}/release/scripts/addons")

View File

@@ -79,7 +79,6 @@ if(WIN32)
# Normal collection of build artifacts
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb_debug.lib ${HARVEST_TARGET}/tbb/lib/tbb_debug.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/bin/tbb_debug.dll ${HARVEST_TARGET}/tbb/bin/tbb_debug.dll
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc_debug.lib ${HARVEST_TARGET}/tbb/lib/tbbmalloc_debug.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc_proxy_debug.lib ${HARVEST_TARGET}/tbb/lib/tbbmalloc_proxy_debug.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/bin/tbbmalloc_debug.dll ${HARVEST_TARGET}/tbb/bin/tbbmalloc_debug.dll
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/bin/tbbmalloc_proxy_debug.dll ${HARVEST_TARGET}/tbb/bin/tbbmalloc_proxy_debug.dll

View File

@@ -432,9 +432,9 @@ set(USD_HASH 1dd1e2092d085ed393c1f7c450a4155a)
set(USD_HASH_TYPE MD5)
set(USD_FILE usd-v${USD_VERSION}.tar.gz)
set(OIDN_VERSION 1.4.0)
set(OIDN_VERSION 1.3.0)
set(OIDN_URI https://github.com/OpenImageDenoise/oidn/releases/download/v${OIDN_VERSION}/oidn-${OIDN_VERSION}.src.tar.gz)
set(OIDN_HASH 421824019becc5b664a22a2b98332bc5)
set(OIDN_HASH 301a5a0958d375a942014df0679b9270)
set(OIDN_HASH_TYPE MD5)
set(OIDN_FILE oidn-${OIDN_VERSION}.src.tar.gz)

View File

@@ -553,10 +553,10 @@ EMBREE_FORCE_BUILD=false
EMBREE_FORCE_REBUILD=false
EMBREE_SKIP=false
OIDN_VERSION="1.4.0"
OIDN_VERSION_SHORT="1.4"
OIDN_VERSION_MIN="1.4.0"
OIDN_VERSION_MAX="1.5"
OIDN_VERSION="1.3.0"
OIDN_VERSION_SHORT="1.3"
OIDN_VERSION_MIN="1.3.0"
OIDN_VERSION_MAX="1.4"
OIDN_FORCE_BUILD=false
OIDN_FORCE_REBUILD=false
OIDN_SKIP=false
@@ -565,7 +565,7 @@ ISPC_VERSION="1.14.1"
FFMPEG_VERSION="4.4"
FFMPEG_VERSION_SHORT="4.4"
FFMPEG_VERSION_MIN="3.0"
FFMPEG_VERSION_MIN="4.4"
FFMPEG_VERSION_MAX="5.0"
FFMPEG_FORCE_BUILD=false
FFMPEG_FORCE_REBUILD=false

View File

@@ -1,3 +1,33 @@
diff -Naur oidn-1.3.0/cmake/FindTBB.cmake external_openimagedenoise/cmake/FindTBB.cmake
--- oidn-1.3.0/cmake/FindTBB.cmake 2021-02-04 16:20:26 -0700
+++ external_openimagedenoise/cmake/FindTBB.cmake 2021-02-12 09:35:53 -0700
@@ -332,20 +332,22 @@
${TBB_ROOT}/lib/${TBB_ARCH}/${TBB_VCVER}
${TBB_ROOT}/lib
)
-
# On Windows, also search the DLL so that the client may install it.
file(GLOB DLL_NAMES
${TBB_ROOT}/bin/${TBB_ARCH}/${TBB_VCVER}/${LIB_NAME}.dll
${TBB_ROOT}/bin/${LIB_NAME}.dll
+ ${TBB_ROOT}/lib/${LIB_NAME}.dll
${TBB_ROOT}/redist/${TBB_ARCH}/${TBB_VCVER}/${LIB_NAME}.dll
${TBB_ROOT}/redist/${TBB_ARCH}/${TBB_VCVER}/${LIB_NAME_GLOB1}.dll
${TBB_ROOT}/redist/${TBB_ARCH}/${TBB_VCVER}/${LIB_NAME_GLOB2}.dll
${TBB_ROOT}/../redist/${TBB_ARCH}/tbb/${TBB_VCVER}/${LIB_NAME}.dll
${TBB_ROOT}/../redist/${TBB_ARCH}_win/tbb/${TBB_VCVER}/${LIB_NAME}.dll
)
- list(GET DLL_NAMES 0 DLL_NAME)
- get_filename_component(${BIN_DIR_VAR} "${DLL_NAME}" DIRECTORY)
- set(${DLL_VAR} "${DLL_NAME}" CACHE PATH "${COMPONENT_NAME} ${BUILD_CONFIG} dll path")
+ if (DLL_NAMES)
+ list(GET DLL_NAMES 0 DLL_NAME)
+ get_filename_component(${BIN_DIR_VAR} "${DLL_NAME}" DIRECTORY)
+ set(${DLL_VAR} "${DLL_NAME}" CACHE PATH "${COMPONENT_NAME} ${BUILD_CONFIG} dll path")
+ endif()
elseif(APPLE)
set(LIB_PATHS ${TBB_ROOT}/lib)
else()
--- external_openimagedenoise/cmake/oidn_ispc.cmake 2021-02-15 17:29:34.000000000 +0100
+++ external_openimagedenoise/cmake/oidn_ispc.cmake2 2021-02-15 17:29:28.000000000 +0100
@@ -98,7 +98,7 @@

View File

@@ -20,24 +20,8 @@ if(NOT CLANG_ROOT_DIR AND NOT $ENV{CLANG_ROOT_DIR} STREQUAL "")
set(CLANG_ROOT_DIR $ENV{CLANG_ROOT_DIR})
endif()
if(NOT LLVM_ROOT_DIR)
if(DEFINED LLVM_VERSION)
message(running llvm-config-${LLVM_VERSION})
find_program(LLVM_CONFIG llvm-config-${LLVM_VERSION})
endif()
if(NOT LLVM_CONFIG)
find_program(LLVM_CONFIG llvm-config)
endif()
execute_process(COMMAND ${LLVM_CONFIG} --prefix
OUTPUT_VARIABLE LLVM_ROOT_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
set(LLVM_ROOT_DIR ${LLVM_ROOT_DIR} CACHE PATH "Path to the LLVM installation")
endif()
set(_CLANG_SEARCH_DIRS
${CLANG_ROOT_DIR}
${LLVM_ROOT_DIR}
/opt/lib/clang
)

View File

@@ -472,7 +472,8 @@ if(NOT GFLAGS_FOUND)
gflags_report_not_found(
"Could not find gflags include directory, set GFLAGS_INCLUDE_DIR "
"to directory containing gflags/gflags.h")
endif()
endif(NOT GFLAGS_INCLUDE_DIR OR
NOT EXISTS ${GFLAGS_INCLUDE_DIR})
find_library(GFLAGS_LIBRARY NAMES gflags
PATHS ${GFLAGS_LIBRARY_DIR_HINTS}
@@ -483,7 +484,8 @@ if(NOT GFLAGS_FOUND)
gflags_report_not_found(
"Could not find gflags library, set GFLAGS_LIBRARY "
"to full path to libgflags.")
endif()
endif(NOT GFLAGS_LIBRARY OR
NOT EXISTS ${GFLAGS_LIBRARY})
# gflags typically requires a threading library (which is OS dependent), note
# that this defines the CMAKE_THREAD_LIBS_INIT variable. If we are able to
@@ -558,7 +560,8 @@ if(NOT GFLAGS_FOUND)
gflags_report_not_found(
"Caller defined GFLAGS_INCLUDE_DIR:"
" ${GFLAGS_INCLUDE_DIR} does not contain gflags/gflags.h header.")
endif()
endif(GFLAGS_INCLUDE_DIR AND
NOT EXISTS ${GFLAGS_INCLUDE_DIR}/gflags/gflags.h)
# TODO: This regex for gflags library is pretty primitive, we use lowercase
# for comparison to handle Windows using CamelCase library names, could
# this check be better?
@@ -568,7 +571,8 @@ if(NOT GFLAGS_FOUND)
gflags_report_not_found(
"Caller defined GFLAGS_LIBRARY: "
"${GFLAGS_LIBRARY} does not match gflags.")
endif()
endif(GFLAGS_LIBRARY AND
NOT "${LOWERCASE_GFLAGS_LIBRARY}" MATCHES ".*gflags[^/]*")
gflags_reset_find_library_prefix()

View File

@@ -40,7 +40,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(NanoVDB DEFAULT_MSG
IF(NANOVDB_FOUND)
SET(NANOVDB_INCLUDE_DIRS ${NANOVDB_INCLUDE_DIR})
ENDIF()
ENDIF(NANOVDB_FOUND)
MARK_AS_ADVANCED(
NANOVDB_INCLUDE_DIR

View File

@@ -46,7 +46,7 @@ SET(_opencollada_FIND_COMPONENTS
)
# Fedora openCOLLADA package links these statically
# note that order is important here or it won't link
# note that order is important here ot it wont link
SET(_opencollada_FIND_STATIC_COMPONENTS
buffer
ftoa

View File

@@ -44,7 +44,7 @@ SET(PYTHON_LINKFLAGS "-Xlinker -export-dynamic" CACHE STRING "Linker flags for p
MARK_AS_ADVANCED(PYTHON_LINKFLAGS)
# if the user passes these defines as args, we don't want to overwrite
# if the user passes these defines as args, we dont want to overwrite
SET(_IS_INC_DEF OFF)
SET(_IS_INC_CONF_DEF OFF)
SET(_IS_LIB_DEF OFF)
@@ -143,7 +143,7 @@ IF((NOT _IS_INC_DEF) OR (NOT _IS_INC_CONF_DEF) OR (NOT _IS_LIB_DEF) OR (NOT _IS_
SET(_PYTHON_ABI_FLAGS "${_CURRENT_ABI_FLAGS}")
break()
ELSE()
# ensure we don't find values from 2 different ABI versions
# ensure we dont find values from 2 different ABI versions
IF(NOT _IS_INC_DEF)
UNSET(PYTHON_INCLUDE_DIR CACHE)
ENDIF()

View File

@@ -40,7 +40,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(sse2neon DEFAULT_MSG
IF(SSE2NEON_FOUND)
SET(SSE2NEON_INCLUDE_DIRS ${SSE2NEON_INCLUDE_DIR})
ENDIF()
ENDIF(SSE2NEON_FOUND)
MARK_AS_ADVANCED(
SSE2NEON_INCLUDE_DIR

View File

@@ -305,7 +305,7 @@ def file_check_arg_sizes(tu):
for i, node_child in enumerate(children):
children = list(node_child.get_children())
# skip if we don't have an index...
# skip if we dont have an index...
size_def = args_size_definition.get(i, -1)
if size_def == -1:
@@ -354,7 +354,7 @@ def file_check_arg_sizes(tu):
filepath # always the same but useful when running threaded
))
# we don't really care what we are looking at, just scan entire file for
# we dont really care what we are looking at, just scan entire file for
# function calls.
def recursive_func_call_check(node):

View File

@@ -694,7 +694,7 @@ macro(message_first_run)
endmacro()
# when we have warnings as errors applied globally this
# needs to be removed for some external libs which we don't maintain.
# needs to be removed for some external libs which we dont maintain.
# utility macro
macro(remove_cc_flag
@@ -794,7 +794,7 @@ macro(remove_extra_strict_flags)
endmacro()
# note, we can only append flags on a single file so we need to negate the options.
# at the moment we can't shut up ffmpeg deprecations, so use this, but will
# at the moment we cant shut up ffmpeg deprecations, so use this, but will
# probably add more removals here.
macro(remove_strict_c_flags_file
filenames)
@@ -963,6 +963,14 @@ macro(blender_project_hack_post)
unset(_reset_standard_cflags_rel)
unset(_reset_standard_cxxflags_rel)
# ------------------------------------------------------------------
# workaround for omission in cmake 2.8.4's GNU.cmake, fixed in 2.8.5
if(CMAKE_COMPILER_IS_GNUCC)
if(NOT DARWIN)
set(CMAKE_INCLUDE_SYSTEM_FLAG_C "-isystem ")
endif()
endif()
endmacro()
# pair of macros to allow libraries to be specify files to install, but to

View File

@@ -388,10 +388,6 @@ endif()
if(WITH_TBB)
find_package(TBB)
if(NOT TBB_FOUND)
message(WARNING "TBB not found, disabling WITH_TBB")
set(WITH_TBB OFF)
endif()
endif()
if(WITH_POTRACE)

View File

@@ -457,10 +457,6 @@ endif()
if(WITH_TBB)
find_package_wrapper(TBB)
if(NOT TBB_FOUND)
message(WARNING "TBB not found, disabling WITH_TBB")
set(WITH_TBB OFF)
endif()
endif()
if(WITH_XR_OPENXR)

View File

@@ -261,10 +261,8 @@ if(NOT DEFINED LIBDIR)
else()
message(FATAL_ERROR "32 bit compiler detected, blender no longer provides pre-build libraries for 32 bit windows, please set the LIBDIR cmake variable to your own library folder")
endif()
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.29.30130)
message(STATUS "Visual Studio 2022 detected.")
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc15)
elseif(MSVC_VERSION GREATER 1919)
# Can be 1910..1912
if(MSVC_VERSION GREATER 1919)
message(STATUS "Visual Studio 2019 detected.")
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc15)
elseif(MSVC_VERSION GREATER 1909)
@@ -550,6 +548,7 @@ if(WITH_OPENIMAGEIO)
set(OPENIMAGEIO_LIBRARIES ${OIIO_OPTIMIZED} ${OIIO_DEBUG})
set(OPENIMAGEIO_DEFINITIONS "-DUSE_TBB=0")
set(OPENCOLORIO_DEFINITIONS "-DDOpenColorIO_SKIP_IMPORTS")
set(OPENIMAGEIO_IDIFF "${OPENIMAGEIO}/bin/idiff.exe")
add_definitions(-DOIIO_STATIC_DEFINE)
add_definitions(-DOIIO_NO_SSE=1)
@@ -595,7 +594,7 @@ if(WITH_OPENCOLORIO)
debug ${OPENCOLORIO_LIBPATH}/libexpatdMD.lib
debug ${OPENCOLORIO_LIBPATH}/pystring_d.lib
)
set(OPENCOLORIO_DEFINITIONS "-DOpenColorIO_SKIP_IMPORTS")
set(OPENCOLORIO_DEFINITIONS)
endif()
if(WITH_OPENVDB)
@@ -680,7 +679,6 @@ if(WITH_TBB)
set(TBB_INCLUDE_DIR ${LIBDIR}/tbb/include)
set(TBB_INCLUDE_DIRS ${TBB_INCLUDE_DIR})
if(WITH_TBB_MALLOC_PROXY)
set(TBB_MALLOC_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbbmalloc.lib debug ${LIBDIR}/tbb/lib/tbbmalloc_debug.lib)
add_definitions(-DWITH_TBB_MALLOC)
endif()
endif()

View File

@@ -6,9 +6,6 @@ if %ERRORLEVEL% EQU 0 goto DetectionComplete
call "%~dp0\detect_msvc2019.cmd"
if %ERRORLEVEL% EQU 0 goto DetectionComplete
call "%~dp0\detect_msvc2022.cmd"
if %ERRORLEVEL% EQU 0 goto DetectionComplete
echo Compiler Detection failed. Use verbose switch for more information.
exit /b 1

View File

@@ -1,6 +1,5 @@
if "%BUILD_VS_YEAR%"=="2017" set BUILD_VS_LIBDIRPOST=vc15
if "%BUILD_VS_YEAR%"=="2019" set BUILD_VS_LIBDIRPOST=vc15
if "%BUILD_VS_YEAR%"=="2022" set BUILD_VS_LIBDIRPOST=vc15
set BUILD_VS_SVNDIR=win64_%BUILD_VS_LIBDIRPOST%
set BUILD_VS_LIBDIR="%BLENDER_DIR%..\lib\%BUILD_VS_SVNDIR%"

View File

@@ -19,10 +19,10 @@ if "%WITH_PYDEBUG%"=="1" (
set PYDEBUG_CMAKE_ARGS=-DWINDOWS_PYTHON_DEBUG=On
)
if "%BUILD_VS_YEAR%"=="2017" (
set BUILD_GENERATOR_POST=%WINDOWS_ARCH%
) else (
if "%BUILD_VS_YEAR%"=="2019" (
set BUILD_PLATFORM_SELECT=-A %MSBUILD_PLATFORM%
) else (
set BUILD_GENERATOR_POST=%WINDOWS_ARCH%
)
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -G "Visual Studio %BUILD_VS_VER% %BUILD_VS_YEAR%%BUILD_GENERATOR_POST%" %BUILD_PLATFORM_SELECT% %TESTS_CMAKE_ARGS% %CLANG_CMAKE_ARGS% %ASAN_CMAKE_ARGS% %PYDEBUG_CMAKE_ARGS%

View File

@@ -1,3 +0,0 @@
set BUILD_VS_VER=17
set BUILD_VS_YEAR=2022
call "%~dp0\detect_msvc_vswhere.cmd"

View File

@@ -66,14 +66,6 @@ if NOT "%1" == "" (
) else if "%1" == "2019b" (
set BUILD_VS_YEAR=2019
set VSWHERE_ARGS=-products Microsoft.VisualStudio.Product.BuildTools
) else if "%1" == "2022" (
set BUILD_VS_YEAR=2022
) else if "%1" == "2022pre" (
set BUILD_VS_YEAR=2022
set VSWHERE_ARGS=-prerelease
) else if "%1" == "2022b" (
set BUILD_VS_YEAR=2022
set VSWHERE_ARGS=-products Microsoft.VisualStudio.Product.BuildTools
) else if "%1" == "packagename" (
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DCPACK_OVERRIDE_PACKAGENAME="%2"
shift /1

View File

@@ -1,4 +1,4 @@
# Doxyfile 1.9.1
# Doxyfile 1.8.16
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
@@ -38,7 +38,7 @@ PROJECT_NAME = Blender
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = V3.0
PROJECT_NUMBER = "V3.0"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@@ -227,14 +227,6 @@ QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
# By default Python docstrings are displayed as preformatted text and doxygen's
# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
# doxygen's special commands can be used and the contents of the docstring
# documentation blocks is shown as doxygen documentation.
# The default value is: YES.
PYTHON_DOCSTRING = YES
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
# documentation from any documented member that it re-implements.
# The default value is: YES.
@@ -271,6 +263,12 @@ TAB_SIZE = 4
ALIASES =
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"
# will allow you to use the command class in the itcl::class meaning.
TCL_SUBST =
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
# instance, some of the names that are used will be different. The list of all
@@ -311,22 +309,19 @@ OPTIMIZE_OUTPUT_SLICE = NO
# parses. With this tag you can assign which parser to use for a given
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL,
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
# tries to guess whether the code is fixed or free formatted code, this is the
# default for Fortran type files). For instance to make doxygen treat .inc files
# as Fortran files (default is PHP), and .f files as C (default is Fortran),
# use: inc=Fortran f=C.
# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
# .inc files as Fortran files (default is PHP), and .f files as C (default is
# Fortran), use: inc=Fortran f=C.
#
# Note: For files without extension you can use no_extension as a placeholder.
#
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen. When specifying no_extension you should add
# * to the FILE_PATTERNS.
#
# Note see also the list of default file extension mappings.
# the files are not read by doxygen.
EXTENSION_MAPPING =
@@ -460,19 +455,6 @@ TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 3
# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use
# during processing. When set to 0 doxygen will based this on the number of
# cores available in the system. You can set it explicitly to a value larger
# than 0 to get more control over the balance between CPU load and processing
# speed. At this moment only the input processing can be done using multiple
# threads. Since this is still an experimental feature the default is set to 1,
# which efficively disables parallel processing. Please report any issues you
# encounter. Generating dot graphs in parallel is controlled by the
# DOT_NUM_THREADS setting.
# Minimum value: 0, maximum value: 32, default value: 1.
NUM_PROC_THREADS = 1
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
@@ -536,13 +518,6 @@ EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
# If this flag is set to YES, the name of an unnamed parameter in a declaration
# will be determined by the corresponding definition. By default unnamed
# parameters remain unnamed in the output.
# The default value is: YES.
RESOLVE_UNNAMED_PARAMS = YES
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
# undocumented members inside documented classes or files. If set to NO these
# members will be included in the various overviews, but no documentation
@@ -560,8 +535,8 @@ HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
# declarations. If set to NO, these declarations will be included in the
# documentation.
# (class|struct|union) declarations. If set to NO, these declarations will be
# included in the documentation.
# The default value is: NO.
HIDE_FRIEND_COMPOUNDS = NO
@@ -580,18 +555,11 @@ HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = YES
# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
# able to match the capabilities of the underlying filesystem. In case the
# filesystem is case sensitive (i.e. it supports files in the same directory
# whose names only differ in casing), the option must be set to YES to properly
# deal with such files in case they appear in the input. For filesystems that
# are not case sensitive the option should be be set to NO to properly deal with
# output files written for symbols that only differ in casing, such as for two
# classes, one named CLASS and the other named Class, and to also support
# references to files without having to specify the exact matching casing. On
# Windows (including Cygwin) and MacOS, users should typically set this option
# to NO, whereas on Linux or other Unix flavors it should typically be set to
# YES.
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
# names in lower-case letters. If set to YES, upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# (including Cygwin) ands Mac users are advised to set this option to NO.
# The default value is: system dependent.
CASE_SENSE_NAMES = YES
@@ -830,10 +798,7 @@ WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
# at the end of the doxygen process doxygen will return with a non-zero status.
# Possible values are: NO, YES and FAIL_ON_WARNINGS.
# a warning is encountered.
# The default value is: NO.
WARN_AS_ERROR = NO
@@ -875,8 +840,8 @@ INPUT = doxygen.main.h \
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
# documentation (see:
# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
# possible encodings.
# The default value is: UTF-8.
INPUT_ENCODING = UTF-8
@@ -889,15 +854,11 @@ INPUT_ENCODING = UTF-8
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# read by doxygen.
#
# Note the list of default checked file patterns might differ from the list of
# default file extension mappings.
#
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl,
# *.ucf, *.qsf and *.ice.
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
FILE_PATTERNS =
@@ -1125,6 +1086,13 @@ VERBATIM_HEADERS = YES
ALPHABETICAL_INDEX = YES
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
# which the alphabetical index list will be split.
# Minimum value: 1, maximum value: 20, default value: 5.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
COLS_IN_ALPHA_INDEX = 5
# In case all classes in a project start with a common prefix, all classes will
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
# can be used to specify a prefix (or a list of prefixes) that should be ignored
@@ -1263,9 +1231,9 @@ HTML_TIMESTAMP = YES
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
# documentation will contain a main index with vertical navigation menus that
# are dynamically created via JavaScript. If disabled, the navigation index will
# are dynamically created via Javascript. If disabled, the navigation index will
# consists of multiple levels of tabs that are statically embedded in every HTML
# page. Disable this option to support browsers that do not have JavaScript,
# page. Disable this option to support browsers that do not have Javascript,
# like the Qt help browser.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
@@ -1295,11 +1263,10 @@ HTML_INDEX_NUM_ENTRIES = 100
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
# generated that can be used as input for Apple's Xcode 3 integrated development
# environment (see:
# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
# create a documentation set, doxygen will generate a Makefile in the HTML
# output directory. Running make will produce the docset in that directory and
# running make install will install the docset in
# environment (see: https://developer.apple.com/xcode/), introduced with OSX
# 10.5 (Leopard). To create a documentation set, doxygen will generate a
# Makefile in the HTML output directory. Running make will produce the docset in
# that directory and running make install will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
# genXcode/_index.html for more information.
@@ -1341,8 +1308,8 @@ DOCSET_PUBLISHER_NAME = Publisher
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
# (see:
# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows.
# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
# Windows.
#
# The HTML Help Workshop contains a compiler that can convert all HTML output
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
@@ -1372,7 +1339,7 @@ CHM_FILE = blender.chm
HHC_LOCATION = "C:/Program Files (x86)/HTML Help Workshop/hhc.exe"
# The GENERATE_CHI flag controls if a separate .chi index file is generated
# (YES) or that it should be included in the main .chm file (NO).
# (YES) or that it should be included in the master .chm file (NO).
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
@@ -1417,8 +1384,7 @@ QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
# (see:
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES.
@@ -1426,8 +1392,8 @@ QHP_NAMESPACE = org.doxygen.Project
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
# Help Project output. For more information please see Qt Help Project / Virtual
# Folders (see:
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
# folders).
# The default value is: doc.
# This tag requires that the tag GENERATE_QHP is set to YES.
@@ -1435,16 +1401,16 @@ QHP_VIRTUAL_FOLDER = doc
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
# filter to add. For more information please see Qt Help Project / Custom
# Filters (see:
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
# Filters (see:
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS =
@@ -1456,9 +1422,9 @@ QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
# The QHG_LOCATION tag can be used to specify the location (absolute path
# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
# run qhelpgenerator on the generated .qhp file.
# The QHG_LOCATION tag can be used to specify the location of Qt's
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
# generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHG_LOCATION =
@@ -1535,17 +1501,6 @@ TREEVIEW_WIDTH = 246
EXT_LINKS_IN_WINDOW = NO
# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
# the HTML output. These images will generally look nicer at scaled resolutions.
# Possible values are: png (the default) and svg (looks nicer but requires the
# pdf2svg or inkscape tool).
# The default value is: png.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FORMULA_FORMAT = png
# Use this tag to change the font size of LaTeX formulas included as images in
# the HTML documentation. When you change the font size after a successful
# doxygen run you need to manually remove any form_*.png images from the HTML
@@ -1566,14 +1521,8 @@ FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
# to create new LaTeX commands to be used in formulas as building blocks. See
# the section "Including formulas" for details.
FORMULA_MACROFILE =
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
# https://www.mathjax.org) which uses client side JavaScript for the rendering
# https://www.mathjax.org) which uses client side Javascript for the rendering
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path
@@ -1585,7 +1534,7 @@ USE_MATHJAX = NO
# When MathJax is enabled you can set the default output format to be used for
# the MathJax output. See the MathJax site (see:
# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details.
# http://docs.mathjax.org/en/latest/output.html) for more details.
# Possible values are: HTML-CSS (which is slower, but has the best
# compatibility), NativeMML (i.e. MathML) and SVG.
# The default value is: HTML-CSS.
@@ -1601,7 +1550,7 @@ MATHJAX_FORMAT = HTML-CSS
# Content Delivery Network so you can quickly see the result without installing
# MathJax. However, it is strongly recommended to install a local copy of
# MathJax from https://www.mathjax.org before deployment.
# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2.
# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH = http://www.mathjax.org/mathjax
@@ -1615,8 +1564,7 @@ MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site
# (see:
# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
@@ -1644,7 +1592,7 @@ MATHJAX_CODEFILE =
SEARCHENGINE = NO
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a web server instead of a web client using JavaScript. There
# implemented using a web server instead of a web client using Javascript. There
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
# setting. When disabled, doxygen will generate a PHP script for searching and
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
@@ -1663,8 +1611,7 @@ SERVER_BASED_SEARCH = NO
#
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see:
# https://xapian.org/).
# Xapian (see: https://xapian.org/).
#
# See the section "External Indexing and Searching" for details.
# The default value is: NO.
@@ -1677,9 +1624,8 @@ EXTERNAL_SEARCH = NO
#
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see:
# https://xapian.org/). See the section "External Indexing and Searching" for
# details.
# Xapian (see: https://xapian.org/). See the section "External Indexing and
# Searching" for details.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHENGINE_URL =
@@ -1843,11 +1789,9 @@ LATEX_EXTRA_FILES =
PDF_HYPERLINKS = NO
# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
# files. Set this option to YES, to get a higher quality PDF documentation.
#
# See also section LATEX_CMD_NAME for selecting the engine.
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
# the PDF file directly from the LaTeX files. Set this option to YES, to get a
# higher quality PDF documentation.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
@@ -2182,8 +2126,7 @@ INCLUDE_FILE_PATTERNS =
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED = BUILD_DATE \
DOXYGEN=1
PREDEFINED = BUILD_DATE
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
@@ -2360,31 +2303,9 @@ UML_LOOK = YES
# but if the number exceeds 15, the total amount of fields shown is limited to
# 10.
# Minimum value: 0, maximum value: 100, default value: 10.
# This tag requires that the tag UML_LOOK is set to YES.
UML_LIMIT_NUM_FIELDS = 10
# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
# tag is set to YES, doxygen will add type and arguments for attributes and
# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
# will not generate fields with class member information in the UML graphs. The
# class diagrams will look similar to the default class diagrams but using UML
# notation for the relationships.
# Possible values are: NO, YES and NONE.
# The default value is: NO.
# This tag requires that the tag UML_LOOK is set to YES.
DOT_UML_DETAILS = NO
# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
# to display on a single line. If the actual line length exceeds this threshold
# significantly it will wrapped across multiple lines. Some heuristics are apply
# to avoid ugly line breaks.
# Minimum value: 0, maximum value: 1000, default value: 17.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_WRAP_THRESHOLD = 17
UML_LIMIT_NUM_FIELDS = 10
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
# collaboration graphs will show the relations between templates and their
@@ -2575,11 +2496,9 @@ DOT_MULTI_TARGETS = YES
GENERATE_LEGEND = YES
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
# files that are used to generate the various graphs.
#
# Note: This setting is not only used for dot files but also for msc and
# plantuml temporary files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_CLEANUP = YES

View File

@@ -29,7 +29,7 @@ with offscreen.bind():
amount = 10
for i in range(-amount, amount + 1):
x_pos = i / amount
draw_circle_2d((x_pos, 0.0), (1, 1, 1, 1), 0.5, segments=200)
draw_circle_2d((x_pos, 0.0), (1, 1, 1, 1), 0.5, 200)
# Drawing the generated texture in 3D space

View File

@@ -34,9 +34,7 @@ with offscreen.bind():
for i in range(RING_AMOUNT):
draw_circle_2d(
(random.uniform(-1, 1), random.uniform(-1, 1)),
(1, 1, 1, 1), random.uniform(0.1, 1),
segments=20,
)
(1, 1, 1, 1), random.uniform(0.1, 1), 20)
buffer = fb.read_color(0, 0, WIDTH, HEIGHT, 4, 0, 'UBYTE')

View File

@@ -1,13 +1,2 @@
sphinx==3.5.4
# Sphinx dependencies that are important
Jinja2==2.11.3
Pygments==2.9.0
docutils==0.16
snowballstemmer==2.1.0
babel==2.9.1
requests==2.25.1
# Only needed to match the theme used for the official documentation.
# Without this theme, the default theme will be used.
Sphinx==3.5.3
sphinx_rtd_theme==0.5.2

View File

@@ -1,3 +1,3 @@
#define MANTA_GIT_VERSION "commit 8fbebe02459b7f72575872c20961f7cb757db408"
#define MANTA_GIT_VERSION "commit 9c505cd22e289b98c9aa717efba8ef3201c7e458"

View File

@@ -71,19 +71,6 @@ class ParticleBase;
for (int j = bnd; j < (grid).getSizeY() - bnd; ++j) \
for (int i = bnd; i < (grid).getSizeX() - bnd; ++i)
#define FOR_NEIGHBORS_BND(grid, radius, bnd) \
for (int zj = ((grid).is3D() ? std::max(bnd, k - radius) : 0); \
zj <= ((grid).is3D() ? std::min(k + radius, (grid).getSizeZ() - 1 - bnd) : 0); \
zj++) \
for (int yj = std::max(bnd, j - radius); \
yj <= std::min(j + radius, (grid).getSizeY() - 1 - bnd); \
yj++) \
for (int xj = std::max(bnd, i - radius); \
xj <= std::min(i + radius, (grid).getSizeX() - 1 - bnd); \
xj++)
#define FOR_NEIGHBORS(grid, radius) FOR_NEIGHBORS_BND(grid, radius, 0)
//! Basic data structure for kernel data, initialized based on kernel type (e.g. single, idx, etc).
struct KernelBase {
int maxX, maxY, maxZ, minZ, maxT, minT;

View File

@@ -822,13 +822,17 @@ struct ComputeUnionLevelsetPindex : public KernelBase {
{
const Vec3 gridPos = Vec3(i, j, k) + Vec3(0.5); // shifted by half cell
Real phiv = radius * 1.0; // outside
const int r = int(radius) + 1;
FOR_NEIGHBORS(phi, r)
{
int r = int(radius) + 1;
int rZ = phi.is3D() ? r : 0;
for (int zj = k - rZ; zj <= k + rZ; zj++)
for (int yj = j - r; yj <= j + r; yj++)
for (int xj = i - r; xj <= i + r; xj++) {
if (!phi.isInBounds(Vec3i(xj, yj, zj)))
continue;
// note, for the particle indices in indexSys the access is periodic (ie, dont skip for eg
// inBounds(sx,10,10)
// note, for the particle indices in indexSys the access is periodic (ie, dont skip for
// eg inBounds(sx,10,10)
IndexInt isysIdxS = index.index(xj, yj, zj);
IndexInt pStart = index(isysIdxS), pEnd = 0;
if (phi.isInBounds(isysIdxS + 1))
@@ -1022,14 +1026,18 @@ struct ComputeAveragedLevelsetWeight : public KernelBase {
// loop over neighborhood, similar to ComputeUnionLevelsetPindex
const Real sradiusInv = 1. / (4. * radius * radius);
const int r = int(radius) + 1;
int r = int(1. * radius) + 1;
int rZ = phi.is3D() ? r : 0;
// accumulators
Real wacc = 0.;
Vec3 pacc = Vec3(0.);
Real racc = 0.;
FOR_NEIGHBORS(phi, r)
{
for (int zj = k - rZ; zj <= k + rZ; zj++)
for (int yj = j - r; yj <= j + r; yj++)
for (int xj = i - r; xj <= i + r; xj++) {
if (!phi.isInBounds(Vec3i(xj, yj, zj)))
continue;
IndexInt isysIdxS = index.index(xj, yj, zj);
IndexInt pStart = index(isysIdxS), pEnd = 0;

View File

@@ -2287,9 +2287,10 @@ struct knFlipComputePotentialTrappedAir : public KernelBase {
const Vec3 &vj = scaleFromManta * v.getCentered(x, y, z);
const Vec3 xij = xi - xj;
const Vec3 vij = vi - vj;
Real h = !pot.is3D() ? 1.414 * radius :
1.732 * radius; // estimate sqrt(2)*radius resp. sqrt(3)*radius
// for h, due to squared resp. cubic neighbor area
Real h = !pot.is3D() ?
1.414 * radius :
1.732 * radius; // estimate sqrt(2)*radius resp. sqrt(3)*radius for h, due
// to squared resp. cubic neighbor area
vdiff += norm(vij) * (1 - dot(getNormalized(vij), getNormalized(xij))) *
(1 - norm(xij) / h);
}

View File

@@ -132,7 +132,7 @@ def init():
_workaround_buggy_drivers()
path = os.path.dirname(__file__)
user_path = os.path.dirname(os.path.abspath(bpy.utils.user_resource('CONFIG', path='')))
user_path = os.path.dirname(os.path.abspath(bpy.utils.user_resource('CONFIG', '')))
_cycles.init(path, user_path, bpy.app.background)
_parse_command_line()

View File

@@ -34,17 +34,12 @@ void BlenderSync::sync_light(BL::Object &b_parent,
bool *use_portal)
{
/* test if we need to sync */
Light *light;
ObjectKey key(b_parent, persistent_id, b_ob_instance, false);
BL::Light b_light(b_ob.data());
Light *light = light_map.find(key);
/* Check if the transform was modified, in case a linked collection is moved we do not get a
* specific depsgraph update (T88515). This also mimics the behavior for Objects. */
const bool tfm_updated = (light && light->get_tfm() != tfm);
/* Update if either object or light data changed. */
if (!light_map.add_or_update(&light, b_ob, b_parent, key) && !tfm_updated) {
if (!light_map.add_or_update(&light, b_ob, b_parent, key)) {
Shader *shader;
if (!shader_map.add_or_update(&shader, b_light)) {
if (light->get_is_portal())

View File

@@ -289,10 +289,11 @@ static PyObject *render_func(PyObject * /*self*/, PyObject *args)
RNA_pointer_create(NULL, &RNA_Depsgraph, (ID *)PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr);
BL::Depsgraph b_depsgraph(depsgraphptr);
/* Allow Blender to execute other Python scripts. */
/* Allow Blender to execute other Python scripts, and isolate TBB tasks so we
* don't get deadlocks with Blender threads accessing shared data like images. */
python_thread_state_save(&session->python_thread_state);
session->render(b_depsgraph);
tbb::this_task_arena::isolate([&] { session->render(b_depsgraph); });
python_thread_state_restore(&session->python_thread_state);
@@ -329,7 +330,8 @@ static PyObject *bake_func(PyObject * /*self*/, PyObject *args)
python_thread_state_save(&session->python_thread_state);
session->bake(b_depsgraph, b_object, pass_type, pass_filter, width, height);
tbb::this_task_arena::isolate(
[&] { session->bake(b_depsgraph, b_object, pass_type, pass_filter, width, height); });
python_thread_state_restore(&session->python_thread_state);
@@ -375,7 +377,7 @@ static PyObject *reset_func(PyObject * /*self*/, PyObject *args)
python_thread_state_save(&session->python_thread_state);
session->reset_session(b_data, b_depsgraph);
tbb::this_task_arena::isolate([&] { session->reset_session(b_data, b_depsgraph); });
python_thread_state_restore(&session->python_thread_state);
@@ -397,7 +399,7 @@ static PyObject *sync_func(PyObject * /*self*/, PyObject *args)
python_thread_state_save(&session->python_thread_state);
session->synchronize(b_depsgraph);
tbb::this_task_arena::isolate([&] { session->synchronize(b_depsgraph); });
python_thread_state_restore(&session->python_thread_state);

View File

@@ -1196,18 +1196,16 @@ class OptiXDevice : public CUDADevice {
const CUDAContextScope scope(cuContext);
const bool use_fast_trace_bvh = (bvh->params.bvh_type == SceneParams::BVH_STATIC);
// Compute memory usage
OptixAccelBufferSizes sizes = {};
OptixAccelBuildOptions options = {};
options.operation = operation;
if (use_fast_trace_bvh) {
VLOG(2) << "Using fast to trace OptiX BVH";
if (background) {
// Prefer best performance and lowest memory consumption in background
options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_TRACE | OPTIX_BUILD_FLAG_ALLOW_COMPACTION;
}
else {
VLOG(2) << "Using fast to update OptiX BVH";
// Prefer fast updates in viewport
options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_BUILD | OPTIX_BUILD_FLAG_ALLOW_UPDATE;
}
@@ -1255,16 +1253,15 @@ class OptiXDevice : public CUDADevice {
out_data.device_pointer,
sizes.outputSizeInBytes,
&out_handle,
use_fast_trace_bvh ? &compacted_size_prop : NULL,
use_fast_trace_bvh ? 1 : 0));
background ? &compacted_size_prop : NULL,
background ? 1 : 0));
bvh->traversable_handle = static_cast<uint64_t>(out_handle);
// Wait for all operations to finish
check_result_cuda_ret(cuStreamSynchronize(NULL));
// Compact acceleration structure to save memory (only if using fast trace as the
// OPTIX_BUILD_FLAG_ALLOW_COMPACTION flag is only set in this case).
if (use_fast_trace_bvh) {
// Compact acceleration structure to save memory (do not do this in viewport for faster builds)
if (background) {
uint64_t compacted_size = sizes.outputSizeInBytes;
check_result_cuda_ret(
cuMemcpyDtoH(&compacted_size, compacted_size_prop.result, sizeof(compacted_size)));
@@ -1309,8 +1306,6 @@ class OptiXDevice : public CUDADevice {
return;
}
const bool use_fast_trace_bvh = (bvh->params.bvh_type == SceneParams::BVH_STATIC);
free_bvh_memory_delayed();
BVHOptiX *const bvh_optix = static_cast<BVHOptiX *>(bvh);
@@ -1320,10 +1315,10 @@ class OptiXDevice : public CUDADevice {
if (!bvh->params.top_level) {
assert(bvh->objects.size() == 1 && bvh->geometry.size() == 1);
// Refit is only possible in viewport for now (because AS is built with
// OPTIX_BUILD_FLAG_ALLOW_UPDATE only there, see above)
OptixBuildOperation operation = OPTIX_BUILD_OPERATION_BUILD;
/* Refit is only possible when using fast to trace BVH (because AS is built with
* OPTIX_BUILD_FLAG_ALLOW_UPDATE only there, see above). */
if (refit && !use_fast_trace_bvh) {
if (refit && !background) {
assert(bvh_optix->traversable_handle != 0);
operation = OPTIX_BUILD_OPERATION_UPDATE;
}

View File

@@ -65,7 +65,7 @@ class DenoiseParams {
/* Viewport start sample. */
int start_sample;
/** Native Denoiser. */
/** Native Denoiser **/
/* Pixel radius for neighboring pixels to take into account. */
int radius;
@@ -81,7 +81,7 @@ class DenoiseParams {
/* Clamp the input to the range of +-1e8. Should be enough for any legitimate data. */
bool clamp_input;
/** OIDN/Optix Denoiser. */
/** OIDN/Optix Denoiser **/
/* Passes handed over to the OIDN/OptiX denoiser (default to color + albedo). */
DenoiserInput input_passes;

View File

@@ -116,7 +116,7 @@ CCL_NAMESPACE_BEGIN
# endif
# endif /* __SHADOW_RECORD_ALL__ */
/* Record all intersections - Volume BVH traversal. */
/* Record all intersections - Volume BVH traversal */
# if defined(__VOLUME_RECORD_ALL__)
# define BVH_FUNCTION_NAME bvh_intersect_volume_all

View File

@@ -22,7 +22,7 @@
CCL_NAMESPACE_BEGIN
/* Normal on triangle. */
/* normal on triangle */
ccl_device_inline float3 triangle_normal(KernelGlobals *kg, ShaderData *sd)
{
/* load triangle vertices */
@@ -40,7 +40,7 @@ ccl_device_inline float3 triangle_normal(KernelGlobals *kg, ShaderData *sd)
}
}
/* Point and normal on triangle. */
/* point and normal on triangle */
ccl_device_inline void triangle_point_normal(
KernelGlobals *kg, int object, int prim, float u, float v, float3 *P, float3 *Ng, int *shader)
{

View File

@@ -35,7 +35,7 @@
CCL_NAMESPACE_BEGIN
/* Spherical coordinates <-> Cartesian direction. */
/* Spherical coordinates <-> Cartesian direction */
ccl_device float2 direction_to_spherical(float3 dir)
{

View File

@@ -220,13 +220,11 @@ ccl_device void svm_node_hair_info(
stack_store_float(stack, out_offset, data);
break;
}
# if 0
case NODE_INFO_CURVE_FADE: {
/*case NODE_INFO_CURVE_FADE: {
data = sd->curve_transparency;
stack_store_float(stack, out_offset, data);
break;
}
# endif
}*/
case NODE_INFO_CURVE_TANGENT_NORMAL: {
data3 = curve_tangent_normal(kg, sd);
stack_store_float3(stack, out_offset, data3);

View File

@@ -333,7 +333,7 @@ static M44d get_interpolated_matrix_for_time(const MatrixSampleMap &samples, chr
chrono_t t = (time - prev_time) / (next_time - prev_time);
/* Ensure rotation around the shortest angle. */
/* ensure rotation around the shortest angle */
if ((prev_rotation ^ next_rotation) < 0) {
next_rotation = -next_rotation;
}

View File

@@ -736,14 +736,13 @@ static void process_uvs(CachedData &cache,
const IV2fGeomParam::Sample &sample,
double time)
{
if (scope != kFacevaryingScope && scope != kVaryingScope && scope != kVertexScope) {
if (scope != kFacevaryingScope) {
return;
}
const array<int> *uv_loops = cache.uv_loops.data_for_time_no_check(time).get_data_or_null();
/* It's ok to not have loop indices, as long as the scope is not face-varying. */
if (!uv_loops && scope == kFacevaryingScope) {
if (!uv_loops) {
return;
}
@@ -767,28 +766,10 @@ static void process_uvs(CachedData &cache,
const uint32_t *indices = sample.getIndices()->get();
const V2f *values = sample.getVals()->get();
if (scope == kFacevaryingScope) {
for (const int uv_loop_index : *uv_loops) {
const uint32_t index = indices[uv_loop_index];
*data_float2++ = make_float2(values[index][0], values[index][1]);
}
}
else if (scope == kVaryingScope || scope == kVertexScope) {
if (triangles) {
for (size_t i = 0; i < triangles->size(); i++) {
const int3 t = (*triangles)[i];
*data_float2++ = make_float2(values[t.x][0], values[t.x][1]);
*data_float2++ = make_float2(values[t.y][0], values[t.y][1]);
*data_float2++ = make_float2(values[t.z][0], values[t.z][1]);
}
}
else if (corners) {
for (size_t i = 0; i < corners->size(); i++) {
const int c = (*corners)[i];
*data_float2++ = make_float2(values[c][0], values[c][1]);
}
}
}
attribute.data.add_data(data, time);
}

View File

@@ -4425,12 +4425,12 @@ void HairInfoNode::compile(SVMCompiler &compiler)
if (!out->links.empty()) {
compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_TANGENT_NORMAL, compiler.stack_assign(out));
}
#if 0
out = output("Fade");
/*out = output("Fade");
if(!out->links.empty()) {
compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_FADE, compiler.stack_assign(out));
}
#endif
}*/
out = output("Random");
if (!out->links.empty()) {
int attr = compiler.attribute(ATTR_STD_CURVE_RANDOM);

View File

@@ -1252,7 +1252,7 @@ bool Session::update_progressive_refine(bool cancel)
double current_time = time_dt();
if (current_time - last_update_time < params.progressive_update_timeout) {
/* If last sample was processed, we need to write buffers anyway. */
/* if last sample was processed, we need to write buffers anyway */
if (!write && sample != 1)
return false;
}

View File

@@ -15,7 +15,7 @@
if(WITH_GTESTS)
Include(GTestTesting)
# Otherwise we get warnings here that we can't fix in external projects
# Otherwise we get warnings here that we cant fix in external projects
remove_strict_flags()
endif()

View File

@@ -223,14 +223,12 @@ ccl_device_inline ssef fastpow24(const ssef &arg)
ssef x = fastpow<0x3F4CCCCD, 0x4F55A7FB>(arg); // error max = 0.17 avg = 0.0018 |avg| = 0.05
ssef arg2 = arg * arg;
ssef arg4 = arg2 * arg2;
/* error max = 0.018 avg = 0.0031 |avg| = 0.0031 */
x = improve_5throot_solution(x, arg4);
/* error max = 0.00021 avg = 1.6e-05 |avg| = 1.6e-05 */
x = improve_5throot_solution(x, arg4);
/* error max = 6.1e-07 avg = 5.2e-08 |avg| = 1.1e-07 */
x = improve_5throot_solution(x, arg4);
x = improve_5throot_solution(x,
arg4); /* error max = 0.018 avg = 0.0031 |avg| = 0.0031 */
x = improve_5throot_solution(x,
arg4); /* error max = 0.00021 avg = 1.6e-05 |avg| = 1.6e-05 */
x = improve_5throot_solution(x,
arg4); /* error max = 6.1e-07 avg = 5.2e-08 |avg| = 1.1e-07 */
return x * (x * x);
}

View File

@@ -282,8 +282,8 @@ static CPUCapabilities &system_cpu_capabilities()
/* actual opcode for xgetbv */
__asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(xcr_feature_mask), "=d"(edx) : "c"(0));
# elif defined(_MSC_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)
/* Minimum VS2010 SP1 compiler is required. */
xcr_feature_mask = (uint32_t)_xgetbv(_XCR_XFEATURE_ENABLED_MASK);
xcr_feature_mask = (uint32_t)_xgetbv(
_XCR_XFEATURE_ENABLED_MASK); /* min VS2010 SP1 compiler is required */
# else
xcr_feature_mask = 0;
# endif

View File

@@ -88,7 +88,7 @@ class TaskScheduler {
/* Approximate number of threads that will work on task, which may be lower
* or higher than the actual number of threads. Use as little as possible and
* leave splitting up tasks to the scheduler. */
* leave splitting up tasks to the scheduler.. */
static int num_threads();
protected:

View File

@@ -93,21 +93,40 @@ void my_guess_pkt_duration(AVFormatContext *s, AVStream *st, AVPacket *pkt)
#endif
FFMPEG_INLINE
int64_t timestamp_from_pts_or_dts(int64_t pts, int64_t dts)
void my_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
{
/* Some videos do not have any pts values, use dts instead in those cases if
* possible. Usually when this happens dts can act as pts because as all frames
* should then be presented in their decoded in order. IE pts == dts. */
if (pts == AV_NOPTS_VALUE) {
return dts;
int i;
for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
st->cur_dts = av_rescale(timestamp,
st->time_base.den * (int64_t)ref_st->time_base.num,
st->time_base.num * (int64_t)ref_st->time_base.den);
}
return pts;
}
FFMPEG_INLINE
int64_t av_get_pts_from_frame(AVFrame *picture)
void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
{
return timestamp_from_pts_or_dts(picture->pts, picture->pkt_dts);
my_update_cur_dts(s, ref_st, timestamp);
}
FFMPEG_INLINE
int64_t av_get_pts_from_frame(AVFormatContext *avctx, AVFrame *picture)
{
int64_t pts;
pts = picture->pts;
if (pts == AV_NOPTS_VALUE) {
pts = picture->pkt_dts;
}
if (pts == AV_NOPTS_VALUE) {
pts = 0;
}
(void)avctx;
return pts;
}
/* -------------------------------------------------------------------- */

View File

@@ -370,7 +370,6 @@ elseif(WIN32)
intern/GHOST_DropTargetWin32.cpp
intern/GHOST_SystemWin32.cpp
intern/GHOST_WindowWin32.cpp
intern/GHOST_Wintab.cpp
intern/GHOST_ContextD3D.h
intern/GHOST_DisplayManagerWin32.h
@@ -378,7 +377,6 @@ elseif(WIN32)
intern/GHOST_SystemWin32.h
intern/GHOST_TaskbarWin32.h
intern/GHOST_WindowWin32.h
intern/GHOST_Wintab.h
)
if(NOT WITH_GL_EGL)
@@ -483,17 +481,10 @@ if(WITH_XR_OPENXR)
shlwapi
)
elseif(UNIX AND NOT APPLE)
list(APPEND XR_PLATFORM_DEFINES -DXR_OS_LINUX)
if (WITH_GHOST_WAYLAND)
list(APPEND XR_PLATFORM_DEFINES -DXR_USE_PLATFORM_WAYLAND)
endif()
if (WITH_GHOST_X11)
if (WITH_GL_EGL)
list(APPEND XR_PLATFORM_DEFINES -DXR_USE_PLATFORM_EGL)
else()
list(APPEND XR_PLATFORM_DEFINES -DXR_USE_PLATFORM_XLIB)
endif()
endif()
list(APPEND XR_PLATFORM_DEFINES
-DXR_OS_LINUX
-DXR_USE_PLATFORM_XLIB
)
endif()
add_definitions(-DWITH_XR_OPENXR ${XR_PLATFORM_DEFINES})

View File

@@ -105,9 +105,7 @@ typedef enum {
typedef enum {
GHOST_kTabletAutomatic = 0,
/* Show as Windows Ink to users to match "Use Windows Ink" in tablet utilities,
* but we use the dependent Windows Pointer API. */
GHOST_kTabletWinPointer,
GHOST_kTabletNative,
GHOST_kTabletWintab,
} GHOST_TTabletAPI;
@@ -170,7 +168,7 @@ typedef enum {
GHOST_kButtonMaskRight,
GHOST_kButtonMaskButton4,
GHOST_kButtonMaskButton5,
/* Trackballs and programmable buttons. */
/* Trackballs and programmable buttons */
GHOST_kButtonMaskButton6,
GHOST_kButtonMaskButton7,
GHOST_kButtonNumMasks
@@ -179,15 +177,15 @@ typedef enum {
typedef enum {
GHOST_kEventUnknown = 0,
GHOST_kEventCursorMove, /* Mouse move event. */
GHOST_kEventButtonDown, /* Mouse button event. */
GHOST_kEventButtonUp, /* Mouse button event. */
GHOST_kEventWheel, /* Mouse wheel event. */
GHOST_kEventTrackpad, /* Trackpad event. */
GHOST_kEventCursorMove, /// Mouse move event
GHOST_kEventButtonDown, /// Mouse button event
GHOST_kEventButtonUp, /// Mouse button event
GHOST_kEventWheel, /// Mouse wheel event
GHOST_kEventTrackpad, /// Trackpad event
#ifdef WITH_INPUT_NDOF
GHOST_kEventNDOFMotion, /* N degree of freedom device motion event. */
GHOST_kEventNDOFButton, /* N degree of freedom device button event. */
GHOST_kEventNDOFMotion, /// N degree of freedom device motion event
GHOST_kEventNDOFButton, /// N degree of freedom device button event
#endif
GHOST_kEventKeyDown,
@@ -209,8 +207,8 @@ typedef enum {
GHOST_kEventDraggingExited,
GHOST_kEventDraggingDropDone,
GHOST_kEventOpenMainFile, /* Needed for Cocoa to open double-clicked .blend file at startup. */
GHOST_kEventNativeResolutionChange, /* Needed for Cocoa when window moves to other display. */
GHOST_kEventOpenMainFile, // Needed for Cocoa to open double-clicked .blend file at startup
GHOST_kEventNativeResolutionChange, // Needed for Cocoa when window moves to other display
GHOST_kEventTimer,
@@ -283,7 +281,7 @@ typedef enum {
GHOST_kKeyPeriod = '.',
GHOST_kKeySlash = '/',
/* Number keys. */
// Number keys
GHOST_kKey0 = '0',
GHOST_kKey1,
GHOST_kKey2,
@@ -298,7 +296,7 @@ typedef enum {
GHOST_kKeySemicolon = ';',
GHOST_kKeyEqual = '=',
/* Character keys. */
// Character keys
GHOST_kKeyA = 'A',
GHOST_kKeyB,
GHOST_kKeyC,
@@ -337,8 +335,8 @@ typedef enum {
GHOST_kKeyRightControl,
GHOST_kKeyLeftAlt,
GHOST_kKeyRightAlt,
GHOST_kKeyOS, /* Command key on Apple, Windows key(s) on Windows. */
GHOST_kKeyGrLess, /* German PC only! */
GHOST_kKeyOS, // Command key on Apple, Windows key(s) on Windows
GHOST_kKeyGrLess, // German PC only!
GHOST_kKeyApp, /* Also known as menu key. */
GHOST_kKeyCapsLock,
@@ -360,7 +358,7 @@ typedef enum {
GHOST_kKeyUpPage,
GHOST_kKeyDownPage,
/* Numpad keys. */
// Numpad keys
GHOST_kKeyNumpad0,
GHOST_kKeyNumpad1,
GHOST_kKeyNumpad2,
@@ -378,7 +376,7 @@ typedef enum {
GHOST_kKeyNumpadAsterisk,
GHOST_kKeyNumpadSlash,
/* Function keys. */
// Function keys
GHOST_kKeyF1,
GHOST_kKeyF2,
GHOST_kKeyF3,
@@ -404,7 +402,7 @@ typedef enum {
GHOST_kKeyF23,
GHOST_kKeyF24,
/* Multimedia keypad buttons. */
// Multimedia keypad buttons
GHOST_kKeyMediaPlay,
GHOST_kKeyMediaStop,
GHOST_kKeyMediaFirst,
@@ -481,9 +479,9 @@ typedef struct {
typedef enum {
GHOST_kDragnDropTypeUnknown = 0,
GHOST_kDragnDropTypeFilenames, /* Array of strings representing file names (full path). */
GHOST_kDragnDropTypeString, /* Unformatted text UTF-8 string. */
GHOST_kDragnDropTypeBitmap /* Bitmap image data. */
GHOST_kDragnDropTypeFilenames, /*Array of strings representing file names (full path) */
GHOST_kDragnDropTypeString, /* Unformatted text UTF-8 string */
GHOST_kDragnDropTypeBitmap /*Bitmap image data */
} GHOST_TDragnDropTypes;
typedef struct {
@@ -529,23 +527,18 @@ typedef enum {
#ifdef WITH_INPUT_NDOF
typedef struct {
/** N-degree of freedom device data v3 [GSoC 2010] */
/* Each component normally ranges from -1 to +1, but can exceed that.
* These use blender standard view coordinates,
* with positive rotations being CCW about the axis. */
/* translation: */
float tx, ty, tz;
/* rotation:
* - `axis = (rx,ry,rz).normalized`
* - `amount = (rx,ry,rz).magnitude` [in revolutions, 1.0 = 360 deg]. */
float rx, ry, rz;
/** Time since previous NDOF Motion event */
float dt;
/** Starting, #GHOST_kInProgress or #GHOST_kFinishing (for modal handlers) */
GHOST_TProgress progress;
// Each component normally ranges from -1 to +1, but can exceed that.
// These use blender standard view coordinates, with positive rotations being CCW about the axis.
float tx, ty, tz; // translation
float rx, ry, rz; // rotation:
// axis = (rx,ry,rz).normalized
// amount = (rx,ry,rz).magnitude [in revolutions, 1.0 = 360 deg]
float dt; // time since previous NDOF Motion event
GHOST_TProgress progress; // Starting, InProgress or Finishing (for modal handlers)
} GHOST_TEventNDOFMotionData;
typedef enum { GHOST_kPress, GHOST_kRelease } GHOST_TButtonAction;
/* Good for mouse or other buttons too, hmmm? */
// good for mouse or other buttons too, hmmm?
typedef struct {
GHOST_TButtonAction action;
@@ -568,7 +561,7 @@ typedef struct {
*/
/** The ascii code for the key event ('\0' if none). */
char ascii;
/** The unicode character. if the length is 6, not NULL terminated if all 6 are set. */
/** The unicode character. if the length is 6, not NULL terminated if all 6 are set */
char utf8_buf[6];
/** Generated by auto-repeat. */
@@ -601,8 +594,7 @@ typedef void *GHOST_TEmbedderWindowID;
#endif // _WIN32
#ifndef _WIN32
/* I can't use "Window" from `X11/Xlib.h`
* because it conflicts with Window defined in `winlay.h`. */
// I can't use "Window" from "<X11/Xlib.h>" because it conflits with Window defined in winlay.h
typedef int GHOST_TEmbedderWindowID;
#endif // _WIN32
@@ -650,10 +642,8 @@ typedef void *(*GHOST_XrGraphicsContextBindFn)(void);
typedef void (*GHOST_XrGraphicsContextUnbindFn)(GHOST_ContextHandle graphics_context);
typedef void (*GHOST_XrDrawViewFn)(const struct GHOST_XrDrawViewInfo *draw_view, void *customdata);
/**
* An array of #GHOST_TXrGraphicsBinding items defining the candidate bindings to use.
* The first available candidate will be chosen, so order defines priority.
*/
/* An array of GHOST_TXrGraphicsBinding items defining the candidate bindings to use. The first
* available candidate will be chosen, so order defines priority. */
typedef const GHOST_TXrGraphicsBinding *GHOST_XrGraphicsBindingCandidates;
typedef struct {
@@ -694,7 +684,7 @@ typedef struct GHOST_XrDrawViewInfo {
float angle_up, angle_down;
} fov;
/** Set if the buffer should be submitted with a SRGB transfer applied. */
/** Set if the buffer should be submitted with a srgb transfer applied. */
char expects_srgb_buffer;
} GHOST_XrDrawViewInfo;
@@ -744,7 +734,7 @@ typedef struct GHOST_XrActionSpaceInfo {
typedef struct GHOST_XrActionBindingInfo {
const char *action_name;
GHOST_TUns32 count_interaction_paths;
/** Interaction path: User (sub-action) path + component path. */
/** Interaction path: User (subaction) path + component path. */
const char **interaction_paths;
} GHOST_XrActionBindingInfo;

View File

@@ -149,9 +149,6 @@ static bool egl_chk(bool result, const char *file = NULL, int line = 0, const ch
static_cast<unsigned int>(error),
code ? code : "<Unknown>",
msg ? msg : "<Unknown>");
(void)(file);
(void)(line);
(void)(text);
#endif
}
@@ -202,8 +199,7 @@ template<typename T> T &choose_api(EGLenum api, T &a, T &b, T &c)
}
}
GHOST_ContextEGL::GHOST_ContextEGL(const GHOST_System *const system,
bool stereoVisual,
GHOST_ContextEGL::GHOST_ContextEGL(bool stereoVisual,
EGLNativeWindowType nativeWindow,
EGLNativeDisplayType nativeDisplay,
EGLint contextProfileMask,
@@ -213,7 +209,6 @@ GHOST_ContextEGL::GHOST_ContextEGL(const GHOST_System *const system,
EGLint contextResetNotificationStrategy,
EGLenum api)
: GHOST_Context(stereoVisual),
m_system(system),
m_nativeDisplay(nativeDisplay),
m_nativeWindow(nativeWindow),
m_contextProfileMask(contextProfileMask),
@@ -290,21 +285,6 @@ GHOST_TSuccess GHOST_ContextEGL::getSwapInterval(int &intervalOut)
return GHOST_kSuccess;
}
EGLDisplay GHOST_ContextEGL::getDisplay() const
{
return m_display;
}
EGLConfig GHOST_ContextEGL::getConfig() const
{
return m_config;
}
EGLContext GHOST_ContextEGL::getContext() const
{
return m_context;
}
GHOST_TSuccess GHOST_ContextEGL::activateDrawingContext()
{
if (m_display) {
@@ -476,7 +456,9 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
attrib_list.push_back(EGL_NONE);
if (!EGL_CHK(::eglChooseConfig(m_display, &(attrib_list[0]), &m_config, 1, &num_config)))
EGLConfig config;
if (!EGL_CHK(::eglChooseConfig(m_display, &(attrib_list[0]), &config, 1, &num_config)))
goto error;
// A common error is to assume that ChooseConfig worked because it returned EGL_TRUE
@@ -484,7 +466,7 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
goto error;
if (m_nativeWindow != 0) {
m_surface = ::eglCreateWindowSurface(m_display, m_config, m_nativeWindow, NULL);
m_surface = ::eglCreateWindowSurface(m_display, config, m_nativeWindow, NULL);
}
else {
static const EGLint pb_attrib_list[] = {
@@ -494,7 +476,7 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
1,
EGL_NONE,
};
m_surface = ::eglCreatePbufferSurface(m_display, m_config, pb_attrib_list);
m_surface = ::eglCreatePbufferSurface(m_display, config, pb_attrib_list);
}
if (!EGL_CHK(m_surface != EGL_NO_SURFACE))
@@ -595,7 +577,7 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
attrib_list.push_back(EGL_NONE);
m_context = ::eglCreateContext(m_display, m_config, m_sharedContext, &(attrib_list[0]));
m_context = ::eglCreateContext(m_display, config, m_sharedContext, &(attrib_list[0]));
if (!EGL_CHK(m_context != EGL_NO_CONTEXT))
goto error;

View File

@@ -24,7 +24,6 @@
#pragma once
#include "GHOST_Context.h"
#include "GHOST_System.h"
#include <GL/eglew.h>
@@ -37,15 +36,11 @@
#endif
class GHOST_ContextEGL : public GHOST_Context {
/* XR code needs low level graphics data to send to OpenXR. */
friend class GHOST_XrGraphicsBindingOpenGL;
public:
/**
* Constructor.
*/
GHOST_ContextEGL(const GHOST_System *const system,
bool stereoVisual,
GHOST_ContextEGL(bool stereoVisual,
EGLNativeWindowType nativeWindow,
EGLNativeDisplayType nativeDisplay,
EGLint contextProfileMask,
@@ -105,17 +100,9 @@ class GHOST_ContextEGL : public GHOST_Context {
*/
GHOST_TSuccess getSwapInterval(int &intervalOut);
EGLDisplay getDisplay() const;
EGLConfig getConfig() const;
EGLContext getContext() const;
private:
bool initContextEGLEW();
const GHOST_System *const m_system;
EGLNativeDisplayType m_nativeDisplay;
EGLNativeWindowType m_nativeWindow;
@@ -130,7 +117,6 @@ class GHOST_ContextEGL : public GHOST_Context {
EGLContext m_context;
EGLSurface m_surface;
EGLDisplay m_display;
EGLConfig m_config;
EGLint m_swap_interval;

View File

@@ -160,7 +160,7 @@ GHOST_TSuccess GHOST_DisplayManagerSDL::setCurrentDisplaySetting(
else {
/* this is a problem for the BGE player :S, perhaps SDL2 will resolve at some point.
* we really need SDL_SetDisplayModeForDisplay() to become an API func! - campbell */
printf("no windows available, can't fullscreen\n");
printf("no windows available, cant fullscreen\n");
/* do not fail, we will try again later when the window is created - wander */
return GHOST_kSuccess;

View File

@@ -31,17 +31,10 @@ class GHOST_IXrGraphicsBinding {
public:
union {
#if defined(WITH_GHOST_X11)
# if defined(WITH_GL_EGL)
XrGraphicsBindingEGLMNDX egl;
# else
XrGraphicsBindingOpenGLXlibKHR glx;
# endif
#elif defined(WIN32)
XrGraphicsBindingOpenGLWin32KHR wgl;
XrGraphicsBindingD3D11KHR d3d11;
#endif
#if defined(WITH_GHOST_WAYLAND)
XrGraphicsBindingOpenGLWaylandKHR wl;
#endif
} oxr_binding;

View File

@@ -239,7 +239,7 @@ class GHOST_System : public GHOST_ISystem {
* Set which tablet API to use. Only affects Windows, other platforms have a single API.
* \param api: Enum indicating which API to use.
*/
virtual void setTabletAPI(GHOST_TTabletAPI api);
void setTabletAPI(GHOST_TTabletAPI api);
GHOST_TTabletAPI getTabletAPI(void);
#ifdef WITH_INPUT_NDOF

View File

@@ -32,7 +32,11 @@
#include "GHOST_WindowCocoa.h"
#include "GHOST_WindowManager.h"
#if defined(WITH_GL_EGL)
# include "GHOST_ContextEGL.h"
#else
# include "GHOST_ContextCGL.h"
#endif
#ifdef WITH_INPUT_NDOF
# include "GHOST_NDOFManagerCocoa.h"
@@ -549,12 +553,10 @@ GHOST_TSuccess GHOST_SystemCocoa::init()
// ProcessSerialNumber psn;
// Carbon stuff to move window & menu to foreground
#if 0
if (!GetCurrentProcess(&psn)) {
/*if (!GetCurrentProcess(&psn)) {
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
SetFrontProcess(&psn);
}
#endif
}*/
@autoreleasepool {
[NSApplication sharedApplication]; // initializes NSApp

View File

@@ -376,7 +376,7 @@ void GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
bounds.wrapPoint(x_new, y_new, 8, window->getCursorGrabAxis());
window->getCursorGrabAccum(x_accum, y_accum);
// can't use setCursorPosition because the mouse may have no focus!
// cant use setCursorPosition because the mouse may have no focus!
if (x_new != x_root || y_new != y_root) {
if (1) { //xme.time > m_last_warp) {
/* when wrapping we don't need to add an event because the

View File

@@ -1590,28 +1590,7 @@ GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings /*g
d->os_surfaces.push_back(os_surface);
d->os_egl_windows.push_back(os_egl_window);
GHOST_Context *context;
for (int minor = 6; minor >= 0; --minor) {
context = new GHOST_ContextEGL(this,
false,
EGLNativeWindowType(os_egl_window),
EGLNativeDisplayType(d->display),
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
4,
minor,
GHOST_OPENGL_EGL_CONTEXT_FLAGS,
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
EGL_OPENGL_API);
if (context->initializeDrawingContext())
return context;
else
delete context;
}
context = new GHOST_ContextEGL(this,
false,
GHOST_Context *context = new GHOST_ContextEGL(false,
EGLNativeWindowType(os_egl_window),
EGLNativeDisplayType(d->display),
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,

View File

@@ -50,7 +50,11 @@
#include "GHOST_WindowManager.h"
#include "GHOST_WindowWin32.h"
#if defined(WITH_GL_EGL)
# include "GHOST_ContextEGL.h"
#else
# include "GHOST_ContextWGL.h"
#endif
#ifdef WITH_INPUT_NDOF
# include "GHOST_NDOFManagerWin32.h"
@@ -135,6 +139,7 @@ static void initRawInput()
#undef DEVICE_COUNT
}
typedef HRESULT(API *GHOST_WIN32_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
typedef BOOL(API *GHOST_WIN32_EnableNonClientDpiScaling)(HWND);
GHOST_SystemWin32::GHOST_SystemWin32()
@@ -862,151 +867,15 @@ GHOST_EventButton *GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type,
{
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
GHOST_TabletData td = window->getTabletData();
/* Move mouse to button event position. */
if (window->getTabletData().Active != GHOST_kTabletModeNone) {
/* Tablet should be handling in between mouse moves, only move to event position. */
DWORD msgPos = ::GetMessagePos();
int msgPosX = GET_X_LPARAM(msgPos);
int msgPosY = GET_Y_LPARAM(msgPos);
system->pushEvent(new GHOST_EventCursor(
::GetMessageTime(), GHOST_kEventCursorMove, window, msgPosX, msgPosY, td));
}
window->updateMouseCapture(type == GHOST_kEventButtonDown ? MousePressed : MouseReleased);
return new GHOST_EventButton(system->getMilliSeconds(), type, window, mask, td);
}
void GHOST_SystemWin32::processWintabEvent(GHOST_WindowWin32 *window)
{
GHOST_Wintab *wt = window->getWintab();
if (!wt) {
return;
}
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
std::vector<GHOST_WintabInfoWin32> wintabInfo;
wt->getInput(wintabInfo);
/* Wintab provided coordinates are untrusted until a Wintab and Win32 button down event match.
* This is checked on every button down event, and revoked if there is a mismatch. This can
* happen when Wintab incorrectly scales cursor position or is in mouse mode.
*
* If Wintab was never trusted while processing this Win32 event, a fallback Ghost cursor move
* event is created at the position of the Win32 WT_PACKET event. */
bool mouseMoveHandled;
bool useWintabPos;
mouseMoveHandled = useWintabPos = wt->trustCoordinates();
for (GHOST_WintabInfoWin32 &info : wintabInfo) {
switch (info.type) {
case GHOST_kEventCursorMove: {
if (!useWintabPos) {
continue;
}
wt->mapWintabToSysCoordinates(info.x, info.y, info.x, info.y);
system->pushEvent(new GHOST_EventCursor(
info.time, GHOST_kEventCursorMove, window, info.x, info.y, info.tabletData));
break;
}
case GHOST_kEventButtonDown: {
UINT message;
switch (info.button) {
case GHOST_kButtonMaskLeft:
message = WM_LBUTTONDOWN;
break;
case GHOST_kButtonMaskRight:
message = WM_RBUTTONDOWN;
break;
case GHOST_kButtonMaskMiddle:
message = WM_MBUTTONDOWN;
break;
default:
continue;
}
/* Wintab buttons are modal, but the API does not inform us what mode a pressed button is
* in. Only issue button events if we can steal an equivalent Win32 button event from the
* event queue. */
MSG msg;
if (PeekMessage(&msg, window->getHWND(), message, message, PM_NOYIELD) &&
msg.message != WM_QUIT) {
/* Test for Win32/Wintab button down match. */
useWintabPos = wt->testCoordinates(msg.pt.x, msg.pt.y, info.x, info.y);
if (!useWintabPos) {
continue;
}
/* Steal the Win32 event which was previously peeked. */
PeekMessage(&msg, window->getHWND(), message, message, PM_REMOVE | PM_NOYIELD);
/* Move cursor to button location, to prevent incorrect cursor position when
* transitioning from unsynchronized Win32 to Wintab cursor control. */
wt->mapWintabToSysCoordinates(info.x, info.y, info.x, info.y);
system->pushEvent(new GHOST_EventCursor(
info.time, GHOST_kEventCursorMove, window, info.x, info.y, info.tabletData));
if (type == GHOST_kEventButtonDown) {
window->updateMouseCapture(MousePressed);
system->pushEvent(
new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData));
mouseMoveHandled = true;
break;
}
}
case GHOST_kEventButtonUp: {
if (!useWintabPos) {
continue;
}
UINT message;
switch (info.button) {
case GHOST_kButtonMaskLeft:
message = WM_LBUTTONUP;
break;
case GHOST_kButtonMaskRight:
message = WM_RBUTTONUP;
break;
case GHOST_kButtonMaskMiddle:
message = WM_MBUTTONUP;
break;
default:
continue;
}
/* Wintab buttons are modal, but the API does not inform us what mode a pressed button is
* in. Only issue button events if we can steal an equivalent Win32 button event from the
* event queue. */
MSG msg;
if (PeekMessage(&msg, window->getHWND(), message, message, PM_REMOVE | PM_NOYIELD) &&
msg.message != WM_QUIT) {
else if (type == GHOST_kEventButtonUp) {
window->updateMouseCapture(MouseReleased);
system->pushEvent(
new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData));
}
break;
}
default:
break;
}
}
/* Fallback cursor movement if Wintab position were never trusted while processing this event. */
if (!mouseMoveHandled) {
DWORD pos = GetMessagePos();
int x = GET_X_LPARAM(pos);
int y = GET_Y_LPARAM(pos);
/* TODO supply tablet data */
system->pushEvent(new GHOST_EventCursor(
system->getMilliSeconds(), GHOST_kEventCursorMove, window, x, y, GHOST_TABLET_DATA_NONE));
}
return new GHOST_EventButton(
system->getMilliSeconds(), type, window, mask, window->getTabletData());
}
void GHOST_SystemWin32::processPointerEvent(
@@ -1014,7 +883,7 @@ void GHOST_SystemWin32::processPointerEvent(
{
/* Pointer events might fire when changing windows for a device which is set to use Wintab, even
* when when Wintab is left enabled but set to the bottom of Wintab overlap order. */
if (!window->usingTabletAPI(GHOST_kTabletWinPointer)) {
if (!window->useTabletAPI(GHOST_kTabletNative)) {
return;
}
@@ -1025,21 +894,20 @@ void GHOST_SystemWin32::processPointerEvent(
return;
}
switch (type) {
case WM_POINTERUPDATE:
/* Coalesced pointer events are reverse chronological order, reorder chronologically.
* Only contiguous move events are coalesced. */
for (GHOST_TUns32 i = pointerInfo.size(); i-- > 0;) {
system->pushEvent(new GHOST_EventCursor(pointerInfo[i].time,
GHOST_kEventCursorMove,
window,
pointerInfo[i].pixelLocation.x,
pointerInfo[i].pixelLocation.y,
pointerInfo[i].tabletData));
if (!pointerInfo[0].isPrimary) {
eventHandled = true;
return; // For multi-touch displays we ignore these events
}
/* Leave event unhandled so that system cursor is moved. */
switch (type) {
case WM_POINTERENTER:
window->m_tabletInRange = true;
system->pushEvent(new GHOST_EventCursor(pointerInfo[0].time,
GHOST_kEventCursorMove,
window,
pointerInfo[0].pixelLocation.x,
pointerInfo[0].pixelLocation.y,
pointerInfo[0].tabletData));
break;
case WM_POINTERDOWN:
/* Move cursor to point of contact because GHOST_EventButton does not include position. */
@@ -1055,10 +923,18 @@ void GHOST_SystemWin32::processPointerEvent(
pointerInfo[0].buttonMask,
pointerInfo[0].tabletData));
window->updateMouseCapture(MousePressed);
/* Mark event handled so that mouse button events are not generated. */
eventHandled = true;
break;
case WM_POINTERUPDATE:
/* Coalesced pointer events are reverse chronological order, reorder chronologically.
* Only contiguous move events are coalesced. */
for (GHOST_TUns32 i = pointerInfo.size(); i-- > 0;) {
system->pushEvent(new GHOST_EventCursor(pointerInfo[i].time,
GHOST_kEventCursorMove,
window,
pointerInfo[i].pixelLocation.x,
pointerInfo[i].pixelLocation.y,
pointerInfo[i].tabletData));
}
break;
case WM_POINTERUP:
system->pushEvent(new GHOST_EventButton(pointerInfo[0].time,
@@ -1067,14 +943,16 @@ void GHOST_SystemWin32::processPointerEvent(
pointerInfo[0].buttonMask,
pointerInfo[0].tabletData));
window->updateMouseCapture(MouseReleased);
/* Mark event handled so that mouse button events are not generated. */
eventHandled = true;
break;
case WM_POINTERLEAVE:
window->m_tabletInRange = false;
break;
default:
break;
}
eventHandled = true;
system->setCursorPosition(pointerInfo[0].pixelLocation.x, pointerInfo[0].pixelLocation.y);
}
GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *window)
@@ -1082,14 +960,18 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
GHOST_TInt32 x_screen, y_screen;
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
if (window->getTabletData().Active != GHOST_kTabletModeNone) {
/* While pen devices are in range, cursor movement is handled by tablet input processing. */
if (window->m_tabletInRange) {
if (window->useTabletAPI(GHOST_kTabletNative)) {
/* Tablet input handled in WM_POINTER* events. WM_MOUSEMOVE events in response to tablet
* input aren't normally generated when using WM_POINTER events, but manually moving the
* system cursor as we do in WM_POINTER handling does. */
return NULL;
}
}
system->getCursorPosition(x_screen, y_screen);
if (window->getCursorGrabModeIsWarp()) {
if (window->getCursorGrabModeIsWarp() && !window->m_tabletInRange) {
GHOST_TInt32 x_new = x_screen;
GHOST_TInt32 y_new = y_screen;
GHOST_TInt32 x_accum, y_accum;
@@ -1101,7 +983,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
}
/* Could also clamp to screen bounds wrap with a window outside the view will fail atm.
* Use inset in case the window is at screen bounds. */
* Use offset of 8 in case the window is at screen bounds. */
bounds.wrapPoint(x_new, y_new, 2, window->getCursorGrabAxis());
window->getCursorGrabAccum(x_accum, y_accum);
@@ -1117,7 +999,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
window,
x_screen + x_accum,
y_screen + y_accum,
GHOST_TABLET_DATA_NONE);
window->getTabletData());
}
}
else {
@@ -1126,7 +1008,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
window,
x_screen,
y_screen,
GHOST_TABLET_DATA_NONE);
window->getTabletData());
}
return NULL;
}
@@ -1236,23 +1118,6 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RA
return event;
}
GHOST_Event *GHOST_SystemWin32::processWindowSizeEvent(GHOST_WindowWin32 *window)
{
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
GHOST_Event *sizeEvent = new GHOST_Event(
system->getMilliSeconds(), GHOST_kEventWindowSize, window);
/* We get WM_SIZE before we fully init. Do not dispatch before we are continuously resizing. */
if (window->m_inLiveResize) {
system->pushEvent(sizeEvent);
system->dispatchEvents();
return NULL;
}
else {
return sizeEvent;
}
}
GHOST_Event *GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type,
GHOST_WindowWin32 *window)
{
@@ -1260,6 +1125,7 @@ GHOST_Event *GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type,
if (type == GHOST_kEventWindowActivate) {
system->getWindowManager()->setActiveWindow(window);
window->bringTabletContextToFront();
}
return new GHOST_Event(system->getMilliSeconds(), type, window);
@@ -1287,31 +1153,6 @@ GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType,
system->getMilliSeconds(), eventType, draggedObjectType, window, mouseX, mouseY, data));
}
void GHOST_SystemWin32::setTabletAPI(GHOST_TTabletAPI api)
{
GHOST_System::setTabletAPI(api);
/* If API is set to WinPointer (Windows Ink), unload Wintab so that trouble drivers don't disable
* Windows Ink. Load Wintab when API is Automatic because decision logic relies on knowing
* whether a Wintab device is present. */
const bool loadWintab = GHOST_kTabletWinPointer != api;
GHOST_WindowManager *wm = getWindowManager();
for (GHOST_IWindow *win : wm->getWindows()) {
GHOST_WindowWin32 *windowWin32 = (GHOST_WindowWin32 *)win;
if (loadWintab) {
windowWin32->loadWintab(GHOST_kWindowStateMinimized != windowWin32->getState());
if (windowWin32->usingTabletAPI(GHOST_kTabletWintab)) {
windowWin32->resetPointerPenInfo();
}
}
else {
windowWin32->closeWintab();
}
}
}
void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO *minmax)
{
minmax->ptMinTrackSize.x = 320;
@@ -1546,100 +1387,33 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
case SC_KEYMENU:
eventHandled = true;
break;
case SC_RESTORE: {
case SC_RESTORE:
::ShowWindow(hwnd, SW_RESTORE);
window->setState(window->getState());
GHOST_Wintab *wt = window->getWintab();
if (wt) {
wt->enable();
}
eventHandled = true;
break;
}
case SC_MAXIMIZE: {
GHOST_Wintab *wt = window->getWintab();
if (wt) {
wt->enable();
}
/* Don't report event as handled so that default handling occurs. */
break;
}
case SC_MINIMIZE: {
GHOST_Wintab *wt = window->getWintab();
if (wt) {
wt->disable();
}
/* Don't report event as handled so that default handling occurs. */
break;
}
}
break;
////////////////////////////////////////////////////////////////////////
// Wintab events, processed
////////////////////////////////////////////////////////////////////////
case WT_CSRCHANGE: {
GHOST_Wintab *wt = window->getWintab();
if (wt) {
wt->updateCursorInfo();
}
eventHandled = true;
break;
}
case WT_PROXIMITY: {
GHOST_Wintab *wt = window->getWintab();
if (wt) {
bool inRange = LOWORD(lParam);
if (inRange) {
/* Some devices don't emit WT_CSRCHANGE events, so update cursor info here. */
wt->updateCursorInfo();
}
else {
wt->leaveRange();
}
}
eventHandled = true;
break;
}
case WT_INFOCHANGE: {
GHOST_Wintab *wt = window->getWintab();
if (wt) {
wt->processInfoChange(lParam);
if (window->usingTabletAPI(GHOST_kTabletWintab)) {
window->resetPointerPenInfo();
}
}
eventHandled = true;
break;
}
case WT_PACKET:
processWintabEvent(window);
eventHandled = true;
window->processWin32TabletEvent(wParam, lParam);
break;
case WT_CSRCHANGE:
case WT_PROXIMITY:
window->processWin32TabletInitEvent();
break;
////////////////////////////////////////////////////////////////////////
// Pointer events, processed
////////////////////////////////////////////////////////////////////////
case WM_POINTERUPDATE:
case WM_POINTERENTER:
case WM_POINTERDOWN:
case WM_POINTERUPDATE:
case WM_POINTERUP:
case WM_POINTERLEAVE:
processPointerEvent(msg, window, wParam, lParam, eventHandled);
break;
case WM_POINTERLEAVE: {
GHOST_TUns32 pointerId = GET_POINTERID_WPARAM(wParam);
POINTER_INFO pointerInfo;
if (!GetPointerInfo(pointerId, &pointerInfo)) {
break;
}
/* Reset pointer pen info if pen device has left tracking range. */
if (pointerInfo.pointerType == PT_PEN && !IS_POINTER_INRANGE_WPARAM(wParam)) {
window->resetPointerPenInfo();
eventHandled = true;
}
break;
}
////////////////////////////////////////////////////////////////////////
// Mouse events, processed
////////////////////////////////////////////////////////////////////////
@@ -1678,20 +1452,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
}
break;
case WM_MOUSEMOVE:
if (!window->m_mousePresent) {
TRACKMOUSEEVENT tme = {sizeof(tme)};
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = hwnd;
TrackMouseEvent(&tme);
window->m_mousePresent = true;
GHOST_Wintab *wt = window->getWintab();
if (wt) {
wt->gainFocus();
}
}
event = processCursorEvent(window);
break;
case WM_MOUSEWHEEL: {
/* The WM_MOUSEWHEEL message is sent to the focus window
@@ -1701,7 +1462,14 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
* since DefWindowProc propagates it up the parent chain
* until it finds a window that processes it.
*/
processWheelEvent(window, wParam, lParam);
/* Get the window under the mouse and send event to its queue. */
POINT mouse_pos = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
HWND mouse_hwnd = ChildWindowFromPoint(HWND_DESKTOP, mouse_pos);
GHOST_WindowWin32 *mouse_window = (GHOST_WindowWin32 *)::GetWindowLongPtr(mouse_hwnd,
GWLP_USERDATA);
processWheelEvent(mouse_window ? mouse_window : window, wParam, lParam);
eventHandled = true;
#ifdef BROKEN_PEEK_TOUCHPAD
PostMessage(hwnd, WM_USER, 0, 0);
@@ -1726,17 +1494,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
window->loadCursor(true, GHOST_kStandardCursorDefault);
}
break;
case WM_MOUSELEAVE: {
window->m_mousePresent = false;
if (window->getTabletData().Active == GHOST_kTabletModeNone) {
processCursorEvent(window);
}
GHOST_Wintab *wt = window->getWintab();
if (wt) {
wt->loseFocus();
}
break;
}
////////////////////////////////////////////////////////////////////////
// Mouse events, ignored
////////////////////////////////////////////////////////////////////////
@@ -1784,7 +1542,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
* will not be dispatched to OUR active window if we minimize one of OUR windows. */
if (LOWORD(wParam) == WA_INACTIVE)
window->lostMouseCapture();
window->processWin32TabletActivateEvent(GET_WM_ACTIVATE_STATE(wParam, lParam));
lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
break;
}
@@ -1826,8 +1584,6 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
/* Let DefWindowProc handle it. */
break;
case WM_SIZING:
event = processWindowSizeEvent(window);
break;
case WM_SIZE:
/* The WM_SIZE message is sent to a window after its size has changed.
* The WM_SIZE and WM_MOVE messages are not sent if an application handles the
@@ -1835,7 +1591,15 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
* to perform any move or size change processing during the WM_WINDOWPOSCHANGED
* message without calling DefWindowProc.
*/
event = processWindowSizeEvent(window);
/* we get first WM_SIZE before we fully init.
* So, do not dispatch before we continuously resizing. */
if (window->m_inLiveResize) {
system->pushEvent(processWindowEvent(GHOST_kEventWindowSize, window));
system->dispatchEvents();
}
else {
event = processWindowEvent(GHOST_kEventWindowSize, window);
}
break;
case WM_CAPTURECHANGED:
window->lostMouseCapture();
@@ -1886,21 +1650,6 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
SWP_NOZORDER | SWP_NOACTIVATE);
}
break;
case WM_DISPLAYCHANGE: {
GHOST_Wintab *wt = window->getWintab();
if (wt) {
wt->remapCoordinates();
}
break;
}
case WM_KILLFOCUS:
/* The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard
* focus. We want to prevent this if a window is still active and it loses focus to
* nowhere. */
if (!wParam && hwnd == ::GetActiveWindow()) {
::SetFocus(hwnd);
}
break;
////////////////////////////////////////////////////////////////////////
// Window events, ignored
////////////////////////////////////////////////////////////////////////
@@ -1937,6 +1686,12 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
* object associated with the window.
*/
break;
case WM_KILLFOCUS:
/* The WM_KILLFOCUS message is sent to a window immediately before it loses the
* keyboard focus. We want to prevent this if a window is still active and it loses
* focus to nowhere. */
if (!wParam && hwnd == ::GetActiveWindow())
::SetFocus(hwnd);
case WM_SHOWWINDOW:
/* The WM_SHOWWINDOW message is sent to a window when the window is
* about to be hidden or shown. */

View File

@@ -265,16 +265,6 @@ class GHOST_SystemWin32 : public GHOST_System {
int mouseY,
void *data);
/***************************************************************************************
** Modify tablet API
***************************************************************************************/
/**
* Set which tablet API to use.
* \param api: Enum indicating which API to use.
*/
void setTabletAPI(GHOST_TTabletAPI api) override;
protected:
/**
* Initializes the system.
@@ -318,12 +308,6 @@ class GHOST_SystemWin32 : public GHOST_System {
GHOST_WindowWin32 *window,
GHOST_TButtonMask mask);
/**
* Creates tablet events from Wintab events.
* \param window: The window receiving the event (the active window).
*/
static void processWintabEvent(GHOST_WindowWin32 *window);
/**
* Creates tablet events from pointer events.
* \param type: The type of pointer event.
@@ -367,13 +351,6 @@ class GHOST_SystemWin32 : public GHOST_System {
*/
GHOST_TKey processSpecialKey(short vKey, short scanCode) const;
/**
* Creates a window size event.
* \param window: The window receiving the event (the active window).
* \return The event created.
*/
static GHOST_Event *processWindowSizeEvent(GHOST_WindowWin32 *window);
/**
* Creates a window event.
* \param type: The type of event to create.

View File

@@ -441,8 +441,7 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti
for (int minor = 5; minor >= 0; --minor) {
#if defined(WITH_GL_EGL)
context = new GHOST_ContextEGL(this,
false,
context = new GHOST_ContextEGL(false,
EGLNativeWindowType(nullptr),
EGLNativeDisplayType(m_display),
profile_mask,
@@ -472,8 +471,7 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti
}
#if defined(WITH_GL_EGL)
context = new GHOST_ContextEGL(this,
false,
context = new GHOST_ContextEGL(false,
EGLNativeWindowType(nullptr),
EGLNativeDisplayType(m_display),
profile_mask,
@@ -591,7 +589,9 @@ static void SleepTillEvent(Display *display, GHOST_TInt64 maxSleep)
}
}
/* This function borrowed from Qt's X11 support qclipboard_x11.cpp */
/* This function borrowed from Qt's X11 support
* qclipboard_x11.cpp
* */
struct init_timestamp_data {
Time timestamp;
};
@@ -2563,7 +2563,7 @@ static bool is_filler_char(char c)
return isspace(c) || c == '_' || c == '-' || c == ';' || c == ':';
}
/* These C functions are copied from Wine 3.12's `wintab.c` */
/* These C functions are copied from Wine 3.12's wintab.c */
static bool match_token(const char *haystack, const char *needle)
{
const char *h, *n;
@@ -2675,8 +2675,8 @@ void GHOST_SystemX11::refreshXInputDevices()
xtablet.PressureLevels = xvi->axes[2].max_value;
if (xvi->num_axes > 3) {
/* This is assuming that the tablet has the same tilt resolution in both
* positive and negative directions. It would be rather weird if it didn't. */
/* this is assuming that the tablet has the same tilt resolution in both
* positive and negative directions. It would be rather weird if it didn't.. */
xtablet.XtiltLevels = xvi->axes[3].max_value;
xtablet.YtiltLevels = xvi->axes[4].max_value;
}

View File

@@ -22,7 +22,11 @@
#include "GHOST_Debug.h"
#include "GHOST_SystemCocoa.h"
#if defined(WITH_GL_EGL)
# include "GHOST_ContextEGL.h"
#else
# include "GHOST_ContextCGL.h"
#endif
#include <Cocoa/Cocoa.h>
#include <Metal/Metal.h>

View File

@@ -556,7 +556,7 @@ static SDL_Cursor *sdl_ghost_CreateCursor(
return cursor;
}
/* TODO, this is currently never freed but it won't leak either. */
/* TODO, this is currently never freed but it wont leak either. */
static SDL_Cursor *getStandardCursorShape(GHOST_TStandardCursor shape)
{
if (sdl_std_cursor_array[0] == NULL) {

View File

@@ -532,25 +532,7 @@ GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType
context = new GHOST_ContextNone(m_wantStereoVisual);
break;
case GHOST_kDrawingContextTypeOpenGL:
for (int minor = 6; minor >= 0; --minor) {
context = new GHOST_ContextEGL(this->m_system,
m_wantStereoVisual,
EGLNativeWindowType(w->egl_window),
EGLNativeDisplayType(m_system->display()),
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
4,
minor,
GHOST_OPENGL_EGL_CONTEXT_FLAGS,
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
EGL_OPENGL_API);
if (context->initializeDrawingContext())
return context;
else
delete context;
}
context = new GHOST_ContextEGL(this->m_system,
m_wantStereoVisual,
context = new GHOST_ContextEGL(m_wantStereoVisual,
EGLNativeWindowType(w->egl_window),
EGLNativeDisplayType(m_system->display()),
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
@@ -559,6 +541,7 @@ GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType
GHOST_OPENGL_EGL_CONTEXT_FLAGS,
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
EGL_OPENGL_API);
break;
}
return (context->initializeDrawingContext() == GHOST_kSuccess) ? context : nullptr;

View File

@@ -21,6 +21,8 @@
* \ingroup GHOST
*/
#define _USE_MATH_DEFINES
#include "GHOST_WindowWin32.h"
#include "GHOST_ContextD3D.h"
#include "GHOST_ContextNone.h"
@@ -30,8 +32,11 @@
#include "utf_winfunc.h"
#include "utfconv.h"
#if defined(WITH_GL_EGL)
# include "GHOST_ContextEGL.h"
#else
# include "GHOST_ContextWGL.h"
#endif
#ifdef WIN32_COMPOSITING
# include <Dwmapi.h>
#endif
@@ -67,7 +72,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
bool is_debug,
bool dialog)
: GHOST_Window(width, height, state, wantStereoVisual, false),
m_mousePresent(false),
m_tabletInRange(false),
m_inLiveResize(false),
m_system(system),
m_hDC(0),
@@ -77,8 +82,6 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_nPressedButtons(0),
m_customCursor(0),
m_wantAlphaBackground(alphaBackground),
m_wintab(NULL),
m_lastPointerTabletData(GHOST_TABLET_DATA_NONE),
m_normal_state(GHOST_kWindowStateNormal),
m_user32(NULL),
m_parentWindowHwnd(parentwindow ? parentwindow->m_hWnd : HWND_DESKTOP),
@@ -87,6 +90,10 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0);
RECT win_rect = {left, top, (long)(left + width), (long)(top + height)};
// Initialize tablet variables
memset(&m_wintab, 0, sizeof(m_wintab));
m_tabletData = GHOST_TABLET_DATA_NONE;
DWORD style = parentwindow ?
WS_POPUPWINDOW | WS_CAPTION | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX :
WS_OVERLAPPEDWINDOW;
@@ -211,10 +218,65 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
}
// Initialize Wintab
if (system->getTabletAPI() != GHOST_kTabletWinPointer) {
loadWintab(GHOST_kWindowStateMinimized != state);
m_wintab.handle = ::LoadLibrary("Wintab32.dll");
if (m_wintab.handle && m_system->getTabletAPI() != GHOST_kTabletNative) {
// Get API functions
m_wintab.info = (GHOST_WIN32_WTInfo)::GetProcAddress(m_wintab.handle, "WTInfoA");
m_wintab.open = (GHOST_WIN32_WTOpen)::GetProcAddress(m_wintab.handle, "WTOpenA");
m_wintab.close = (GHOST_WIN32_WTClose)::GetProcAddress(m_wintab.handle, "WTClose");
m_wintab.packet = (GHOST_WIN32_WTPacket)::GetProcAddress(m_wintab.handle, "WTPacket");
m_wintab.enable = (GHOST_WIN32_WTEnable)::GetProcAddress(m_wintab.handle, "WTEnable");
m_wintab.overlap = (GHOST_WIN32_WTOverlap)::GetProcAddress(m_wintab.handle, "WTOverlap");
// Let's see if we can initialize tablet here.
// Check if WinTab available by getting system context info.
LOGCONTEXT lc = {0};
lc.lcOptions |= CXO_SYSTEM;
if (m_wintab.open && m_wintab.info && m_wintab.info(WTI_DEFSYSCTX, 0, &lc)) {
// Now init the tablet
/* The maximum tablet size, pressure and orientation (tilt) */
AXIS TabletX, TabletY, Pressure, Orientation[3];
// Open a Wintab context
// Open the context
lc.lcPktData = PACKETDATA;
lc.lcPktMode = PACKETMODE;
lc.lcOptions |= CXO_MESSAGES;
lc.lcMoveMask = PACKETDATA;
/* Set the entire tablet as active */
m_wintab.info(WTI_DEVICES, DVC_X, &TabletX);
m_wintab.info(WTI_DEVICES, DVC_Y, &TabletY);
/* get the max pressure, to divide into a float */
BOOL pressureSupport = m_wintab.info(WTI_DEVICES, DVC_NPRESSURE, &Pressure);
if (pressureSupport)
m_wintab.maxPressure = Pressure.axMax;
else
m_wintab.maxPressure = 0;
/* get the max tilt axes, to divide into floats */
BOOL tiltSupport = m_wintab.info(WTI_DEVICES, DVC_ORIENTATION, &Orientation);
if (tiltSupport) {
/* does the tablet support azimuth ([0]) and altitude ([1]) */
if (Orientation[0].axResolution && Orientation[1].axResolution) {
/* all this assumes the minimum is 0 */
m_wintab.maxAzimuth = Orientation[0].axMax;
m_wintab.maxAltitude = Orientation[1].axMax;
}
else { /* No so don't do tilt stuff. */
m_wintab.maxAzimuth = m_wintab.maxAltitude = 0;
}
}
// The Wintab spec says we must open the context disabled if we are using cursor masks.
m_wintab.tablet = m_wintab.open(m_hWnd, &lc, FALSE);
if (m_wintab.enable && m_wintab.tablet) {
m_wintab.enable(m_wintab.tablet, TRUE);
}
}
}
CoCreateInstance(
CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID *)&m_Bar);
}
@@ -227,7 +289,14 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
m_Bar = NULL;
}
closeWintab();
if (m_wintab.handle) {
if (m_wintab.close && m_wintab.tablet) {
m_wintab.close(m_wintab.tablet);
}
FreeLibrary(m_wintab.handle);
memset(&m_wintab, 0, sizeof(m_wintab));
}
if (m_user32) {
FreeLibrary(m_user32);
@@ -844,16 +913,20 @@ GHOST_TSuccess GHOST_WindowWin32::hasCursorShape(GHOST_TStandardCursor cursorSha
GHOST_TSuccess GHOST_WindowWin32::getPointerInfo(
std::vector<GHOST_PointerInfoWin32> &outPointerInfo, WPARAM wParam, LPARAM lParam)
{
GHOST_TInt32 pointerId = GET_POINTERID_WPARAM(wParam);
GHOST_TInt32 isPrimary = IS_POINTER_PRIMARY_WPARAM(wParam);
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem();
GHOST_TUns32 outCount = 0;
if (!(GetPointerPenInfoHistory(pointerId, &outCount, NULL))) {
if (!useTabletAPI(GHOST_kTabletNative)) {
return GHOST_kFailure;
}
std::vector<POINTER_PEN_INFO> pointerPenInfo(outCount);
GHOST_TInt32 pointerId = GET_POINTERID_WPARAM(wParam);
GHOST_TInt32 isPrimary = IS_POINTER_PRIMARY_WPARAM(wParam);
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem();
GHOST_TUns32 outCount;
if (!(GetPointerInfoHistory(pointerId, &outCount, NULL))) {
return GHOST_kFailure;
}
auto pointerPenInfo = std::vector<POINTER_PEN_INFO>(outCount);
outPointerInfo.resize(outCount);
if (!(GetPointerPenInfoHistory(pointerId, &outCount, pointerPenInfo.data()))) {
@@ -915,77 +988,148 @@ GHOST_TSuccess GHOST_WindowWin32::getPointerInfo(
}
}
if (!outPointerInfo.empty()) {
m_lastPointerTabletData = outPointerInfo.back().tabletData;
}
return GHOST_kSuccess;
}
void GHOST_WindowWin32::resetPointerPenInfo()
void GHOST_WindowWin32::processWin32TabletActivateEvent(WORD state)
{
m_lastPointerTabletData = GHOST_TABLET_DATA_NONE;
if (!useTabletAPI(GHOST_kTabletWintab)) {
return;
}
GHOST_Wintab *GHOST_WindowWin32::getWintab() const
{
return m_wintab;
}
if (m_wintab.enable && m_wintab.tablet) {
m_wintab.enable(m_wintab.tablet, state);
void GHOST_WindowWin32::loadWintab(bool enable)
{
if (!m_wintab) {
if (m_wintab = GHOST_Wintab::loadWintab(m_hWnd)) {
if (enable) {
m_wintab->enable();
/* Focus Wintab if cursor is inside this window. This ensures Wintab is enabled when the
* tablet is used to change the Tablet API. */
GHOST_TInt32 x, y;
if (m_system->getCursorPosition(x, y)) {
GHOST_Rect rect;
getClientBounds(rect);
if (rect.isInside(x, y)) {
m_wintab->gainFocus();
}
}
}
if (m_wintab.overlap && state) {
m_wintab.overlap(m_wintab.tablet, TRUE);
}
}
}
void GHOST_WindowWin32::closeWintab()
{
delete m_wintab;
m_wintab = NULL;
}
bool GHOST_WindowWin32::usingTabletAPI(GHOST_TTabletAPI api) const
bool GHOST_WindowWin32::useTabletAPI(GHOST_TTabletAPI api) const
{
if (m_system->getTabletAPI() == api) {
return true;
}
else if (m_system->getTabletAPI() == GHOST_kTabletAutomatic) {
if (m_wintab && m_wintab->devicesPresent()) {
if (m_wintab.tablet)
return api == GHOST_kTabletWintab;
}
else {
return api == GHOST_kTabletWinPointer;
}
else
return api == GHOST_kTabletNative;
}
else {
return false;
}
}
GHOST_TabletData GHOST_WindowWin32::getTabletData()
void GHOST_WindowWin32::processWin32TabletInitEvent()
{
if (usingTabletAPI(GHOST_kTabletWintab)) {
return m_wintab ? m_wintab->getLastTabletData() : GHOST_TABLET_DATA_NONE;
if (!useTabletAPI(GHOST_kTabletWintab)) {
return;
}
// Let's see if we can initialize tablet here
if (m_wintab.info && m_wintab.tablet) {
AXIS Pressure, Orientation[3]; /* The maximum tablet size */
BOOL pressureSupport = m_wintab.info(WTI_DEVICES, DVC_NPRESSURE, &Pressure);
if (pressureSupport)
m_wintab.maxPressure = Pressure.axMax;
else
m_wintab.maxPressure = 0;
BOOL tiltSupport = m_wintab.info(WTI_DEVICES, DVC_ORIENTATION, &Orientation);
if (tiltSupport) {
/* does the tablet support azimuth ([0]) and altitude ([1]) */
if (Orientation[0].axResolution && Orientation[1].axResolution) {
m_wintab.maxAzimuth = Orientation[0].axMax;
m_wintab.maxAltitude = Orientation[1].axMax;
}
else { /* No so don't do tilt stuff. */
m_wintab.maxAzimuth = m_wintab.maxAltitude = 0;
}
}
}
m_tabletData.Active = GHOST_kTabletModeNone;
}
void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam)
{
if (!useTabletAPI(GHOST_kTabletWintab)) {
return;
}
if (m_wintab.packet && m_wintab.tablet) {
PACKET pkt;
if (m_wintab.packet((HCTX)lParam, wParam, &pkt)) {
switch (pkt.pkCursor % 3) { /* % 3 for multiple devices ("DualTrack") */
case 0:
m_tabletData.Active = GHOST_kTabletModeNone; /* puck - not yet supported */
break;
case 1:
m_tabletData.Active = GHOST_kTabletModeStylus; /* stylus */
break;
case 2:
m_tabletData.Active = GHOST_kTabletModeEraser; /* eraser */
break;
}
if (m_wintab.maxPressure > 0) {
m_tabletData.Pressure = (float)pkt.pkNormalPressure / (float)m_wintab.maxPressure;
}
else {
return m_lastPointerTabletData;
m_tabletData.Pressure = 1.0f;
}
if ((m_wintab.maxAzimuth > 0) && (m_wintab.maxAltitude > 0)) {
ORIENTATION ort = pkt.pkOrientation;
float vecLen;
float altRad, azmRad; /* in radians */
/*
* from the wintab spec:
* orAzimuth Specifies the clockwise rotation of the
* cursor about the z axis through a full circular range.
*
* orAltitude Specifies the angle with the x-y plane
* through a signed, semicircular range. Positive values
* specify an angle upward toward the positive z axis;
* negative values specify an angle downward toward the negative z axis.
*
* wintab.h defines .orAltitude as a UINT but documents .orAltitude
* as positive for upward angles and negative for downward angles.
* WACOM uses negative altitude values to show that the pen is inverted;
* therefore we cast .orAltitude as an (int) and then use the absolute value.
*/
/* convert raw fixed point data to radians */
altRad = (float)((fabs((float)ort.orAltitude) / (float)m_wintab.maxAltitude) * M_PI / 2.0);
azmRad = (float)(((float)ort.orAzimuth / (float)m_wintab.maxAzimuth) * M_PI * 2.0);
/* find length of the stylus' projected vector on the XY plane */
vecLen = cos(altRad);
/* from there calculate X and Y components based on azimuth */
m_tabletData.Xtilt = sin(azmRad) * vecLen;
m_tabletData.Ytilt = (float)(sin(M_PI / 2.0 - azmRad) * vecLen);
}
else {
m_tabletData.Xtilt = 0.0f;
m_tabletData.Ytilt = 0.0f;
}
}
}
}
void GHOST_WindowWin32::bringTabletContextToFront()
{
if (!useTabletAPI(GHOST_kTabletWintab)) {
return;
}
if (m_wintab.overlap && m_wintab.tablet) {
m_wintab.overlap(m_wintab.tablet, TRUE);
}
}

View File

@@ -30,18 +30,34 @@
#include "GHOST_TaskbarWin32.h"
#include "GHOST_Window.h"
#include "GHOST_Wintab.h"
#ifdef WITH_INPUT_IME
# include "GHOST_ImeWin32.h"
#endif
#include <vector>
#include <wintab.h>
// PACKETDATA and PACKETMODE modify structs in pktdef.h, so make sure they come first
#define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR)
#define PACKETMODE PK_BUTTONS
#include <pktdef.h>
class GHOST_SystemWin32;
class GHOST_DropTargetWin32;
// typedefs for WinTab functions to allow dynamic loading
typedef UINT(API *GHOST_WIN32_WTInfo)(UINT, UINT, LPVOID);
typedef HCTX(API *GHOST_WIN32_WTOpen)(HWND, LPLOGCONTEXTA, BOOL);
typedef BOOL(API *GHOST_WIN32_WTClose)(HCTX);
typedef BOOL(API *GHOST_WIN32_WTPacket)(HCTX, UINT, LPVOID);
typedef BOOL(API *GHOST_WIN32_WTEnable)(HCTX, BOOL);
typedef BOOL(API *GHOST_WIN32_WTOverlap)(HCTX, BOOL);
// typedefs for user32 functions to allow dynamic loading of Windows 10 DPI scaling functions
typedef UINT(API *GHOST_WIN32_GetDpiForWindow)(HWND);
#ifndef USER_DEFAULT_SCREEN_DPI
# define USER_DEFAULT_SCREEN_DPI 96
#endif // USER_DEFAULT_SCREEN_DPI
struct GHOST_PointerInfoWin32 {
GHOST_TInt32 pointerId;
@@ -49,6 +65,7 @@ struct GHOST_PointerInfoWin32 {
GHOST_TButtonMask buttonMask;
POINT pixelLocation;
GHOST_TUns64 time;
GHOST_TabletData tabletData;
};
@@ -242,11 +259,16 @@ class GHOST_WindowWin32 : public GHOST_Window {
HCURSOR getStandardCursor(GHOST_TStandardCursor shape) const;
void loadCursor(bool visible, GHOST_TStandardCursor cursorShape) const;
const GHOST_TabletData &getTabletData()
{
return m_tabletData;
}
/**
* Query whether given tablet API should be used.
* \param api: Tablet API to test.
*/
bool usingTabletAPI(GHOST_TTabletAPI api) const;
bool useTabletAPI(GHOST_TTabletAPI api) const;
/**
* Translate WM_POINTER events into GHOST_PointerInfoWin32 structs.
@@ -259,34 +281,10 @@ class GHOST_WindowWin32 : public GHOST_Window {
WPARAM wParam,
LPARAM lParam);
/**
* Resets pointer pen tablet state.
*/
void resetPointerPenInfo();
/**
* Retrieves pointer to Wintab if Wintab is the set Tablet API.
* \return Pointer to Wintab member.
*/
GHOST_Wintab *getWintab() const;
/**
* Loads Wintab context for the window.
* \param enable: True if Wintab should be enabled after loading. Wintab should not be enabled if
* the window is minimized.
*/
void loadWintab(bool enable);
/**
* Closes Wintab for the window.
*/
void closeWintab();
/**
* Get the most recent Windows Pointer tablet data.
* \return Most recent pointer tablet data.
*/
GHOST_TabletData getTabletData();
void processWin32TabletActivateEvent(WORD state);
void processWin32TabletInitEvent();
void processWin32TabletEvent(WPARAM wParam, LPARAM lParam);
void bringTabletContextToFront();
GHOST_TSuccess beginFullScreen() const
{
@@ -300,10 +298,10 @@ class GHOST_WindowWin32 : public GHOST_Window {
GHOST_TUns16 getDPIHint() override;
/** True if the mouse is either over or captured by the window. */
bool m_mousePresent;
/** Whether a tablet stylus is being tracked. */
bool m_tabletInRange;
/** True if the window currently resizing. */
/** if the window currently resizing */
bool m_inLiveResize;
#ifdef WITH_INPUT_IME
@@ -387,11 +385,27 @@ class GHOST_WindowWin32 : public GHOST_Window {
static const wchar_t *s_windowClassName;
static const int s_maxTitleLength;
/** Pointer to Wintab manager if Wintab is loaded. */
GHOST_Wintab *m_wintab;
/** Tablet data for GHOST */
GHOST_TabletData m_tabletData;
/** Most recent tablet data. */
GHOST_TabletData m_lastPointerTabletData;
/* Wintab API */
struct {
/** `WinTab.dll` handle. */
HMODULE handle = NULL;
/** API functions */
GHOST_WIN32_WTInfo info;
GHOST_WIN32_WTOpen open;
GHOST_WIN32_WTClose close;
GHOST_WIN32_WTPacket packet;
GHOST_WIN32_WTEnable enable;
GHOST_WIN32_WTOverlap overlap;
/** Stores the Tablet context if detected Tablet features using `WinTab.dll` */
HCTX tablet;
LONG maxPressure;
LONG maxAzimuth, maxAltitude;
} m_wintab;
GHOST_TWindowState m_normal_state;

View File

@@ -1325,7 +1325,6 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type
for (int minor = 5; minor >= 0; --minor) {
#ifdef WITH_GL_EGL
context = new GHOST_ContextEGL(
this->m_system,
m_wantStereoVisual,
EGLNativeWindowType(m_window),
EGLNativeDisplayType(m_display),
@@ -1356,8 +1355,7 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type
}
#ifdef WITH_GL_EGL
context = new GHOST_ContextEGL(this->m_system,
m_wantStereoVisual,
context = new GHOST_ContextEGL(m_wantStereoVisual,
EGLNativeWindowType(m_window),
EGLNativeDisplayType(m_display),
profile_mask,

View File

@@ -1,491 +0,0 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/** \file
* \ingroup GHOST
*/
#define _USE_MATH_DEFINES
#include "GHOST_Wintab.h"
GHOST_Wintab *GHOST_Wintab::loadWintab(HWND hwnd)
{
/* Load Wintab library if available. */
auto handle = unique_hmodule(::LoadLibrary("Wintab32.dll"), &::FreeLibrary);
if (!handle) {
return nullptr;
}
/* Get Wintab functions. */
auto info = (GHOST_WIN32_WTInfo)::GetProcAddress(handle.get(), "WTInfoA");
if (!info) {
return nullptr;
}
auto open = (GHOST_WIN32_WTOpen)::GetProcAddress(handle.get(), "WTOpenA");
if (!open) {
return nullptr;
}
auto get = (GHOST_WIN32_WTGet)::GetProcAddress(handle.get(), "WTGetA");
if (!get) {
return nullptr;
}
auto set = (GHOST_WIN32_WTSet)::GetProcAddress(handle.get(), "WTSetA");
if (!set) {
return nullptr;
}
auto close = (GHOST_WIN32_WTClose)::GetProcAddress(handle.get(), "WTClose");
if (!close) {
return nullptr;
}
auto packetsGet = (GHOST_WIN32_WTPacketsGet)::GetProcAddress(handle.get(), "WTPacketsGet");
if (!packetsGet) {
return nullptr;
}
auto queueSizeGet = (GHOST_WIN32_WTQueueSizeGet)::GetProcAddress(handle.get(), "WTQueueSizeGet");
if (!queueSizeGet) {
return nullptr;
}
auto queueSizeSet = (GHOST_WIN32_WTQueueSizeSet)::GetProcAddress(handle.get(), "WTQueueSizeSet");
if (!queueSizeSet) {
return nullptr;
}
auto enable = (GHOST_WIN32_WTEnable)::GetProcAddress(handle.get(), "WTEnable");
if (!enable) {
return nullptr;
}
auto overlap = (GHOST_WIN32_WTOverlap)::GetProcAddress(handle.get(), "WTOverlap");
if (!overlap) {
return nullptr;
}
/* Build Wintab context. */
LOGCONTEXT lc = {0};
if (!info(WTI_DEFSYSCTX, 0, &lc)) {
return nullptr;
}
Coord tablet, system;
extractCoordinates(lc, tablet, system);
modifyContext(lc);
/* The Wintab spec says we must open the context disabled if we are using cursor masks. */
auto hctx = unique_hctx(open(hwnd, &lc, FALSE), close);
if (!hctx) {
return nullptr;
}
/* Wintab provides no way to determine the maximum queue size aside from checking if attempts
* to change the queue size are successful. */
const int maxQueue = 500;
int queueSize = queueSizeGet(hctx.get());
while (queueSize < maxQueue) {
int testSize = min(queueSize + 16, maxQueue);
if (queueSizeSet(hctx.get(), testSize)) {
queueSize = testSize;
}
else {
/* From Windows Wintab Documentation for WTQueueSizeSet:
* "If the return value is zero, the context has no queue because the function deletes the
* original queue before attempting to create a new one. The application must continue
* calling the function with a smaller queue size until the function returns a non - zero
* value."
*
* In our case we start with a known valid queue size and in the event of failure roll
* back to the last valid queue size. The Wintab spec dates back to 16 bit Windows, thus
* assumes memory recently deallocated may not be available, which is no longer a practical
* concern. */
if (!queueSizeSet(hctx.get(), queueSize)) {
/* If a previously valid queue size is no longer valid, there is likely something wrong in
* the Wintab implementation and we should not use it. */
return nullptr;
}
break;
}
}
return new GHOST_Wintab(hwnd,
std::move(handle),
info,
get,
set,
packetsGet,
enable,
overlap,
std::move(hctx),
tablet,
system,
queueSize);
}
void GHOST_Wintab::modifyContext(LOGCONTEXT &lc)
{
lc.lcPktData = PACKETDATA;
lc.lcPktMode = PACKETMODE;
lc.lcMoveMask = PACKETDATA;
lc.lcOptions |= CXO_CSRMESSAGES | CXO_MESSAGES;
/* Tablet scaling is handled manually because some drivers don't handle HIDPI or multi-display
* correctly; reset tablet scale factors to un-scaled tablet coordinates. */
lc.lcOutOrgX = lc.lcInOrgX;
lc.lcOutOrgY = lc.lcInOrgY;
lc.lcOutExtX = lc.lcInExtX;
lc.lcOutExtY = lc.lcInExtY;
}
void GHOST_Wintab::extractCoordinates(LOGCONTEXT &lc, Coord &tablet, Coord &system)
{
tablet.x.org = lc.lcInOrgX;
tablet.x.ext = lc.lcInExtX;
tablet.y.org = lc.lcInOrgY;
tablet.y.ext = lc.lcInExtY;
system.x.org = lc.lcSysOrgX;
system.x.ext = lc.lcSysExtX;
system.y.org = lc.lcSysOrgY;
/* Wintab maps y origin to the tablet's bottom; invert y to match Windows y origin mapping to the
* screen top. */
system.y.ext = -lc.lcSysExtY;
}
GHOST_Wintab::GHOST_Wintab(HWND hwnd,
unique_hmodule handle,
GHOST_WIN32_WTInfo info,
GHOST_WIN32_WTGet get,
GHOST_WIN32_WTSet set,
GHOST_WIN32_WTPacketsGet packetsGet,
GHOST_WIN32_WTEnable enable,
GHOST_WIN32_WTOverlap overlap,
unique_hctx hctx,
Coord tablet,
Coord system,
int queueSize)
: m_handle{std::move(handle)},
m_fpInfo{info},
m_fpGet{get},
m_fpSet{set},
m_fpPacketsGet{packetsGet},
m_fpEnable{enable},
m_fpOverlap{overlap},
m_context{std::move(hctx)},
m_tabletCoord{tablet},
m_systemCoord{system},
m_pkts{queueSize}
{
m_fpInfo(WTI_INTERFACE, IFC_NDEVICES, &m_numDevices);
updateCursorInfo();
}
void GHOST_Wintab::enable()
{
m_fpEnable(m_context.get(), true);
m_enabled = true;
}
void GHOST_Wintab::disable()
{
if (m_focused) {
loseFocus();
}
m_fpEnable(m_context.get(), false);
m_enabled = false;
}
void GHOST_Wintab::gainFocus()
{
m_fpOverlap(m_context.get(), true);
m_focused = true;
}
void GHOST_Wintab::loseFocus()
{
if (m_lastTabletData.Active != GHOST_kTabletModeNone) {
leaveRange();
}
/* Mouse mode of tablet or display layout may change when Wintab or Window is inactive. Don't
* trust for mouse movement until re-verified. */
m_coordTrusted = false;
m_fpOverlap(m_context.get(), false);
m_focused = false;
}
void GHOST_Wintab::leaveRange()
{
/* Button state can't be tracked while out of range, reset it. */
m_buttons = 0;
/* Set to none to indicate tablet is inactive. */
m_lastTabletData = GHOST_TABLET_DATA_NONE;
/* Clear the packet queue. */
m_fpPacketsGet(m_context.get(), m_pkts.size(), m_pkts.data());
}
void GHOST_Wintab::remapCoordinates()
{
LOGCONTEXT lc = {0};
if (m_fpInfo(WTI_DEFSYSCTX, 0, &lc)) {
extractCoordinates(lc, m_tabletCoord, m_systemCoord);
modifyContext(lc);
m_fpSet(m_context.get(), &lc);
}
}
void GHOST_Wintab::updateCursorInfo()
{
AXIS Pressure, Orientation[3];
BOOL pressureSupport = m_fpInfo(WTI_DEVICES, DVC_NPRESSURE, &Pressure);
m_maxPressure = pressureSupport ? Pressure.axMax : 0;
BOOL tiltSupport = m_fpInfo(WTI_DEVICES, DVC_ORIENTATION, &Orientation);
/* Check if tablet supports azimuth [0] and altitude [1], encoded in axResolution. */
if (tiltSupport && Orientation[0].axResolution && Orientation[1].axResolution) {
m_maxAzimuth = Orientation[0].axMax;
m_maxAltitude = Orientation[1].axMax;
}
else {
m_maxAzimuth = m_maxAltitude = 0;
}
}
void GHOST_Wintab::processInfoChange(LPARAM lParam)
{
/* Update number of connected Wintab digitizers. */
if (LOWORD(lParam) == WTI_INTERFACE && HIWORD(lParam) == IFC_NDEVICES) {
m_fpInfo(WTI_INTERFACE, IFC_NDEVICES, &m_numDevices);
}
}
bool GHOST_Wintab::devicesPresent()
{
return m_numDevices > 0;
}
GHOST_TabletData GHOST_Wintab::getLastTabletData()
{
return m_lastTabletData;
}
void GHOST_Wintab::getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo)
{
const int numPackets = m_fpPacketsGet(m_context.get(), m_pkts.size(), m_pkts.data());
outWintabInfo.resize(numPackets);
size_t outExtent = 0;
for (int i = 0; i < numPackets; i++) {
PACKET pkt = m_pkts[i];
GHOST_WintabInfoWin32 &out = outWintabInfo[i + outExtent];
out.tabletData = GHOST_TABLET_DATA_NONE;
/* % 3 for multiple devices ("DualTrack"). */
switch (pkt.pkCursor % 3) {
case 0:
/* Puck - processed as mouse. */
out.tabletData.Active = GHOST_kTabletModeNone;
break;
case 1:
out.tabletData.Active = GHOST_kTabletModeStylus;
break;
case 2:
out.tabletData.Active = GHOST_kTabletModeEraser;
break;
}
out.x = pkt.pkX;
out.y = pkt.pkY;
if (m_maxPressure > 0) {
out.tabletData.Pressure = (float)pkt.pkNormalPressure / (float)m_maxPressure;
}
if ((m_maxAzimuth > 0) && (m_maxAltitude > 0)) {
ORIENTATION ort = pkt.pkOrientation;
float vecLen;
float altRad, azmRad; /* In radians. */
/*
* From the wintab spec:
* orAzimuth: Specifies the clockwise rotation of the cursor about the z axis through a
* full circular range.
* orAltitude: Specifies the angle with the x-y plane through a signed, semicircular range.
* Positive values specify an angle upward toward the positive z axis; negative values
* specify an angle downward toward the negative z axis.
*
* wintab.h defines orAltitude as a UINT but documents orAltitude as positive for upward
* angles and negative for downward angles. WACOM uses negative altitude values to show that
* the pen is inverted; therefore we cast orAltitude as an (int) and then use the absolute
* value.
*/
/* Convert raw fixed point data to radians. */
altRad = (float)((fabs((float)ort.orAltitude) / (float)m_maxAltitude) * M_PI / 2.0);
azmRad = (float)(((float)ort.orAzimuth / (float)m_maxAzimuth) * M_PI * 2.0);
/* Find length of the stylus' projected vector on the XY plane. */
vecLen = cos(altRad);
/* From there calculate X and Y components based on azimuth. */
out.tabletData.Xtilt = sin(azmRad) * vecLen;
out.tabletData.Ytilt = (float)(sin(M_PI / 2.0 - azmRad) * vecLen);
}
out.time = pkt.pkTime;
/* Some Wintab libraries don't handle relative button input, so we track button presses
* manually. */
out.button = GHOST_kButtonMaskNone;
out.type = GHOST_kEventCursorMove;
DWORD buttonsChanged = m_buttons ^ pkt.pkButtons;
WORD buttonIndex = 0;
GHOST_WintabInfoWin32 buttonRef = out;
int buttons = 0;
while (buttonsChanged) {
if (buttonsChanged & 1) {
/* Find the index for the changed button from the button map. */
GHOST_TButtonMask button = mapWintabToGhostButton(pkt.pkCursor, buttonIndex);
if (button != GHOST_kButtonMaskNone) {
/* Extend output if multiple buttons are pressed. We don't extend input until we confirm
* a Wintab buttons maps to a system button. */
if (buttons > 0) {
outWintabInfo.resize(outWintabInfo.size() + 1);
outExtent++;
GHOST_WintabInfoWin32 &out = outWintabInfo[i + outExtent];
out = buttonRef;
}
buttons++;
out.button = button;
if (buttonsChanged & pkt.pkButtons) {
out.type = GHOST_kEventButtonDown;
}
else {
out.type = GHOST_kEventButtonUp;
}
}
m_buttons ^= 1 << buttonIndex;
}
buttonsChanged >>= 1;
buttonIndex++;
}
}
if (!outWintabInfo.empty()) {
m_lastTabletData = outWintabInfo.back().tabletData;
}
}
GHOST_TButtonMask GHOST_Wintab::mapWintabToGhostButton(UINT cursor, WORD physicalButton)
{
const WORD numButtons = 32;
BYTE logicalButtons[numButtons] = {0};
BYTE systemButtons[numButtons] = {0};
if (!m_fpInfo(WTI_CURSORS + cursor, CSR_BUTTONMAP, &logicalButtons) ||
!m_fpInfo(WTI_CURSORS + cursor, CSR_SYSBTNMAP, &systemButtons)) {
return GHOST_kButtonMaskNone;
}
if (physicalButton >= numButtons) {
return GHOST_kButtonMaskNone;
}
BYTE lb = logicalButtons[physicalButton];
if (lb >= numButtons) {
return GHOST_kButtonMaskNone;
}
switch (systemButtons[lb]) {
case SBN_LCLICK:
return GHOST_kButtonMaskLeft;
case SBN_RCLICK:
return GHOST_kButtonMaskRight;
case SBN_MCLICK:
return GHOST_kButtonMaskMiddle;
default:
return GHOST_kButtonMaskNone;
}
}
void GHOST_Wintab::mapWintabToSysCoordinates(int x_in, int y_in, int &x_out, int &y_out)
{
/* Maps from range [in.org, in.org + abs(in.ext)] to [out.org, out.org + abs(out.ext)], in
* reverse if in.ext and out.ext have differing sign. */
auto remap = [](int inPoint, Range in, Range out) -> int {
int absInExt = abs(in.ext);
int absOutExt = abs(out.ext);
/* Translate input from range [in.org, in.org + absInExt] to [0, absInExt] */
int inMagnitude = inPoint - in.org;
/* If signs of extents differ, reverse input over range. */
if ((in.ext < 0) != (out.ext < 0)) {
inMagnitude = absInExt - inMagnitude;
}
/* Scale from [0, absInExt] to [0, absOutExt]. */
int outMagnitude = inMagnitude * absOutExt / absInExt;
/* Translate from range [0, absOutExt] to [out.org, out.org + absOutExt]. */
int outPoint = outMagnitude + out.org;
return outPoint;
};
x_out = remap(x_in, m_tabletCoord.x, m_systemCoord.x);
y_out = remap(y_in, m_tabletCoord.y, m_systemCoord.y);
}
bool GHOST_Wintab::trustCoordinates()
{
return m_coordTrusted;
}
bool GHOST_Wintab::testCoordinates(int sysX, int sysY, int wtX, int wtY)
{
mapWintabToSysCoordinates(wtX, wtY, wtX, wtY);
/* Allow off by one pixel tolerance in case of rounding error. */
if (abs(sysX - wtX) <= 1 && abs(sysY - wtY) <= 1) {
m_coordTrusted = true;
return true;
}
else {
m_coordTrusted = false;
return false;
}
}

View File

@@ -1,250 +0,0 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/** \file
* \ingroup GHOST
* Declaration of GHOST_WintabWin32 class.
*/
/* Wacom's Wintab documentation is periodically offline, moved, and increasingly hidden away. You
* can find a (painstakingly) archived copy of the documentation at
* https://web.archive.org/web/20201122230125/https://developer-docs-legacy.wacom.com/display/DevDocs/Windows+Wintab+Documentation
*/
#pragma once
#include <memory>
#include <vector>
#include <wtypes.h>
#include "GHOST_Types.h"
#include <wintab.h>
/* PACKETDATA and PACKETMODE modify structs in pktdef.h, so make sure they come first. */
#define PACKETDATA \
(PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_X | PK_Y | PK_TIME)
#define PACKETMODE 0
#include <pktdef.h>
/* Typedefs for Wintab functions to allow dynamic loading. */
typedef UINT(API *GHOST_WIN32_WTInfo)(UINT, UINT, LPVOID);
typedef BOOL(API *GHOST_WIN32_WTGet)(HCTX, LPLOGCONTEXTA);
typedef BOOL(API *GHOST_WIN32_WTSet)(HCTX, LPLOGCONTEXTA);
typedef HCTX(API *GHOST_WIN32_WTOpen)(HWND, LPLOGCONTEXTA, BOOL);
typedef BOOL(API *GHOST_WIN32_WTClose)(HCTX);
typedef int(API *GHOST_WIN32_WTPacketsGet)(HCTX, int, LPVOID);
typedef int(API *GHOST_WIN32_WTQueueSizeGet)(HCTX);
typedef BOOL(API *GHOST_WIN32_WTQueueSizeSet)(HCTX, int);
typedef BOOL(API *GHOST_WIN32_WTEnable)(HCTX, BOOL);
typedef BOOL(API *GHOST_WIN32_WTOverlap)(HCTX, BOOL);
/* Typedefs for Wintab and Windows resource management. */
typedef std::unique_ptr<std::remove_pointer_t<HMODULE>, decltype(&::FreeLibrary)> unique_hmodule;
typedef std::unique_ptr<std::remove_pointer_t<HCTX>, GHOST_WIN32_WTClose> unique_hctx;
struct GHOST_WintabInfoWin32 {
GHOST_TInt32 x, y;
GHOST_TEventType type;
GHOST_TButtonMask button;
GHOST_TUns64 time;
GHOST_TabletData tabletData;
};
class GHOST_Wintab {
public:
/**
* Loads Wintab if available.
* \param hwnd: Window to attach Wintab context to.
*/
static GHOST_Wintab *loadWintab(HWND hwnd);
/**
* Enables Wintab context.
*/
void enable();
/**
* Disables the Wintab context and unwinds Wintab state.
*/
void disable();
/**
* Brings Wintab context to the top of the overlap order.
*/
void gainFocus();
/**
* Puts Wintab context at bottom of overlap order and unwinds Wintab state.
*/
void loseFocus();
/**
* Clean up when Wintab leaves tracking range.
*/
void leaveRange();
/**
* Handle Wintab coordinate changes when DisplayChange events occur.
*/
void remapCoordinates();
/**
* Maps Wintab to Win32 display coordinates.
* \param x_in: The tablet x coordinate.
* \param y_in: The tablet y coordinate.
* \param x_out: Output for the Win32 mapped x coordinate.
* \param y_out: Output for the Win32 mapped y coordinate.
*/
void mapWintabToSysCoordinates(int x_in, int y_in, int &x_out, int &y_out);
/**
* Updates cached Wintab properties for current cursor.
*/
void updateCursorInfo();
/**
* Handle Wintab info changes such as change in number of connected tablets.
* \param lParam: LPARAM of the event.
*/
void processInfoChange(LPARAM lParam);
/**
* Whether Wintab devices are present.
* \return True if Wintab devices are present.
*/
bool devicesPresent();
/**
* Translate Wintab packets into GHOST_WintabInfoWin32 structs.
* \param outWintabInfo: Storage to return resulting GHOST_WintabInfoWin32 data.
*/
void getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo);
/**
* Whether Wintab coordinates should be trusted.
* \return True if Wintab coordinates should be trusted.
*/
bool trustCoordinates();
/**
* Tests whether Wintab coordinates can be trusted by comparing Win32 and Wintab reported cursor
* position.
* \param sysX: System cursor x position.
* \param sysY: System cursor y position.
* \param wtX: Wintab cursor x position.
* \param wtY: Wintab cursor y position.
* \return True if Win32 and Wintab cursor positions match within tolerance.
*
* Note: Only test coordinates on button press, not release. This prevents issues when async
* mismatch causes mouse movement to replay and snap back, which is only an issue while drawing.
*/
bool testCoordinates(int sysX, int sysY, int wtX, int wtY);
/**
* Retrieve the most recent tablet data, or none if pen is not in range.
* \return Most recent tablet data, or none if pen is not in range.
*/
GHOST_TabletData getLastTabletData();
private:
/** Wintab DLL handle. */
unique_hmodule m_handle;
/** Wintab API functions. */
GHOST_WIN32_WTInfo m_fpInfo = nullptr;
GHOST_WIN32_WTGet m_fpGet = nullptr;
GHOST_WIN32_WTSet m_fpSet = nullptr;
GHOST_WIN32_WTPacketsGet m_fpPacketsGet = nullptr;
GHOST_WIN32_WTEnable m_fpEnable = nullptr;
GHOST_WIN32_WTOverlap m_fpOverlap = nullptr;
/** Stores the Wintab tablet context. */
unique_hctx m_context;
/** Whether the context is enabled. */
bool m_enabled = false;
/** Whether the context has focus and is at the top of overlap order. */
bool m_focused = false;
/** Pressed button map. */
GHOST_TUns8 m_buttons = 0;
/** Range of a coordinate space. */
struct Range {
/** Origin of range. */
int org = 0;
/** Extent of range. */
int ext = 1;
};
/** 2D Coordinate space. */
struct Coord {
/** Range of x. */
Range x = {};
/** Range of y. */
Range y = {};
};
/** Whether Wintab coordinates are trusted. */
bool m_coordTrusted = false;
/** Tablet input range. */
Coord m_tabletCoord = {};
/** System output range. */
Coord m_systemCoord = {};
int m_maxPressure = 0;
int m_maxAzimuth = 0;
int m_maxAltitude = 0;
/** Number of connected Wintab devices. */
UINT m_numDevices = 0;
/** Reusable buffer to read in Wintab packets. */
std::vector<PACKET> m_pkts;
/** Most recently received tablet data, or none if pen is not in range. */
GHOST_TabletData m_lastTabletData = GHOST_TABLET_DATA_NONE;
GHOST_Wintab(HWND hwnd,
unique_hmodule handle,
GHOST_WIN32_WTInfo info,
GHOST_WIN32_WTGet get,
GHOST_WIN32_WTSet set,
GHOST_WIN32_WTPacketsGet packetsGet,
GHOST_WIN32_WTEnable enable,
GHOST_WIN32_WTOverlap overlap,
unique_hctx hctx,
Coord tablet,
Coord system,
int queueSize);
/**
* Convert Wintab system mapped (mouse) buttons into Ghost button mask.
* \param cursor: The Wintab cursor associated to the button.
* \param physicalButton: The physical button ID to inspect.
* \return The system mapped button.
*/
GHOST_TButtonMask mapWintabToGhostButton(UINT cursor, WORD physicalButton);
/**
* Applies common modifications to Wintab context.
* \param lc: Wintab context to modify.
*/
static void modifyContext(LOGCONTEXT &lc);
/**
* Extracts tablet and system coordinates from Wintab context.
* \param lc: Wintab context to extract coordinates from.
* \param tablet: Tablet coordinates.
* \param system: System coordinates.
*/
static void extractCoordinates(LOGCONTEXT &lc, Coord &tablet, Coord &system);
};

View File

@@ -392,10 +392,9 @@ GHOST_XrActionSet::GHOST_XrActionSet(XrInstance instance, const GHOST_XrActionSe
{
XrActionSetCreateInfo action_set_info{XR_TYPE_ACTION_SET_CREATE_INFO};
strcpy(action_set_info.actionSetName, info.name);
/* Just use same name for localized. This can be changed in the future if necessary. */
strcpy(action_set_info.localizedActionSetName, info.name);
strcpy(action_set_info.localizedActionSetName,
info.name); /* Just use same name for localized. This can be changed in the future if
necessary. */
action_set_info.priority = 0; /* Use same (default) priority for all action sets. */
CHECK_XR(xrCreateActionSet(instance, &action_set_info, &m_action_set),

View File

@@ -420,11 +420,6 @@ void GHOST_XrContext::getExtensionsToEnable(
r_ext_names.push_back(gpu_binding);
}
#if defined(WITH_GHOST_X11) && defined(WITH_GL_EGL)
assert(openxr_extension_is_available(m_oxr->extensions, XR_MNDX_EGL_ENABLE_EXTENSION_NAME));
r_ext_names.push_back(XR_MNDX_EGL_ENABLE_EXTENSION_NAME);
#endif
for (const std::string_view &ext : try_ext) {
if (openxr_extension_is_available(m_oxr->extensions, ext)) {
r_ext_names.push_back(ext.data());

View File

@@ -22,15 +22,7 @@
#include <list>
#include <sstream>
#if defined(WITH_GL_EGL)
# include "GHOST_ContextEGL.h"
#if defined(WITH_GHOST_X11)
# include "GHOST_SystemX11.h"
# endif
# if defined(WITH_GHOST_WAYLAND)
# include "GHOST_SystemWayland.h"
# endif
#elif defined(WITH_GHOST_X11)
# include "GHOST_ContextGLX.h"
#elif defined(WIN32)
# include "GHOST_ContextD3D.h"
@@ -74,9 +66,7 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding {
XrSystemId system_id,
std::string *r_requirement_info) const override
{
#if defined(WITH_GL_EGL)
GHOST_ContextEGL &ctx_gl = static_cast<GHOST_ContextEGL &>(ghost_ctx);
#elif defined(WITH_GHOST_X11)
#if defined(WITH_GHOST_X11)
GHOST_ContextGLX &ctx_gl = static_cast<GHOST_ContextGLX &>(ghost_ctx);
#else
GHOST_ContextWGL &ctx_gl = static_cast<GHOST_ContextWGL &>(ghost_ctx);
@@ -116,17 +106,6 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding {
void initFromGhostContext(GHOST_Context &ghost_ctx) override
{
#if defined(WITH_GHOST_X11)
# if defined(WITH_GL_EGL)
GHOST_ContextEGL &ctx_egl = static_cast<GHOST_ContextEGL &>(ghost_ctx);
if (dynamic_cast<const GHOST_SystemX11 *const>(ctx_egl.m_system)) {
oxr_binding.egl.type = XR_TYPE_GRAPHICS_BINDING_EGL_MNDX;
oxr_binding.egl.getProcAddress = eglGetProcAddress;
oxr_binding.egl.display = ctx_egl.getDisplay();
oxr_binding.egl.config = ctx_egl.getConfig();
oxr_binding.egl.context = ctx_egl.getContext();
}
# else
GHOST_ContextGLX &ctx_glx = static_cast<GHOST_ContextGLX &>(ghost_ctx);
XVisualInfo *visual_info = glXGetVisualFromFBConfig(ctx_glx.m_display, ctx_glx.m_fbconfig);
@@ -138,7 +117,6 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding {
oxr_binding.glx.visualid = visual_info->visualid;
XFree(visual_info);
# endif
#elif defined(WIN32)
GHOST_ContextWGL &ctx_wgl = static_cast<GHOST_ContextWGL &>(ghost_ctx);
@@ -147,14 +125,6 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding {
oxr_binding.wgl.hGLRC = ctx_wgl.m_hGLRC;
#endif
#if defined(WITH_GHOST_WAYLAND)
GHOST_ContextEGL &ctx_wl_egl = static_cast<GHOST_ContextEGL &>(ghost_ctx);
if (dynamic_cast<const GHOST_SystemWayland *const>(ctx_wl_egl.m_system)) {
oxr_binding.wl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR;
oxr_binding.wl.display = (struct wl_display *)ctx_wl_egl.m_nativeDisplay;
}
#endif
/* Generate a frame-buffer to use for blitting into the texture. */
glGenFramebuffers(1, &m_fbo);
}

View File

@@ -74,11 +74,10 @@ class GHOST_XrSession {
const GHOST_XrActionProfileInfo *infos);
bool attachActionSets();
/**
* Action functions to be called post-session start.
* \param action_set_name: When `nullptr`, all attached action sets will be synced.
*/
bool syncActions(const char *action_set_name = nullptr);
/** Action functions to be called post-session start. */
bool syncActions(
const char *action_set_name = nullptr); /* If action_set_name is nullptr, all attached
* action sets will be synced. */
bool applyHapticAction(const char *action_set_name,
const char *action_name,
const GHOST_TInt64 &duration,

View File

@@ -42,14 +42,8 @@
# include <d3d12.h>
#endif
#ifdef WITH_GHOST_X11
# ifdef WITH_GL_EGL
/* TODO: Why do we have to create this typedef manually? */
typedef void (*(*PFNEGLGETPROCADDRESSPROC)(const char *procname))(void);
# include <GL/eglew.h>
# else
# include <GL/glxew.h>
#endif
#endif
#include <openxr/openxr.h>
#include <openxr/openxr_platform.h>

View File

@@ -103,7 +103,7 @@ int main(int argc, char *argv[])
/* ----------------------------------------------------------------- */
/* Round two, do a normal allocation, and corrupt some blocks. */
/* ----------------------------------------------------------------- */
/* Switch off, because it will complain about some things. */
/* switch off, because it will complain about some things. */
MEM_set_error_callback(NULL);
for (i = 0; i < NUM_BLOCKS; i++) {

View File

@@ -89,7 +89,7 @@ bool IK_QJacobianSolver::Setup(IK_QSegment *root, std::list<IK_QTask *> &tasks)
if (num_dof == 0)
return false;
// compute task ids and assign weights to task
// compute task id's and assing weights to task
int primary_size = 0, primary = 0;
int secondary_size = 0, secondary = 0;
double primary_weight = 0.0, secondary_weight = 0.0;
@@ -237,7 +237,7 @@ void IK_QJacobianSolver::ConstrainPoleVector(IK_QSegment *root, std::list<IK_QTa
bool IK_QJacobianSolver::UpdateAngles(double &norm)
{
// assign each segment a unique id for the jacobian
// assing each segment a unique id for the jacobian
std::vector<IK_QSegment *>::iterator seg;
IK_QSegment *qseg, *minseg = NULL;
double minabsdelta = 1e10, absdelta;

View File

@@ -77,7 +77,7 @@ class scoped_array {
void reset(T* new_array) {
if (sizeof(T)) {
delete[] array_;
delete array_;
}
array_ = new_array;
}

View File

@@ -378,7 +378,7 @@ void PrintArray(const Array3Df& array);
* (if automatic_range_detection = true)
* \note and TODO this automatic detection only works when the image contains
* at least one pixel of both bounds.
*/
**/
void FloatArrayToScaledByteArray(const Array3Df& float_array,
Array3Du* byte_array,
bool automatic_range_detection = false);

View File

@@ -425,15 +425,14 @@ tbool genTangSpace(const SMikkTSpaceContext *pContext, const float fAngularThres
index = 0;
for (f = 0; f < iNrFaces; f++) {
const int verts = pContext->m_pInterface->m_getNumVerticesOfFace(pContext, f);
if (verts != 3 && verts != 4) {
if (verts != 3 && verts != 4)
continue;
}
// I've decided to let degenerate triangles and group-with-anythings
// vary between left/right hand coordinate systems at the vertices.
// All healthy triangles on the other hand are built to always be either or.
#if 0
// force the coordinate system orientation to be uniform for every face.
/*// force the coordinate system orientation to be uniform for every face.
// (this is already the case for good triangles but not for
// degenerate ones and those with bGroupWithAnything==true)
bool bOrient = psTspace[index].bOrient;
@@ -448,8 +447,7 @@ tbool genTangSpace(const SMikkTSpaceContext *pContext, const float fAngularThres
else ++i;
}
if (!bNotFound) bOrient = psTspace[index+i].bOrient;
}
#endif
}*/
// set data
for (i = 0; i < verts; i++) {

View File

@@ -48,7 +48,6 @@ if(WITH_OPENCOLORIO)
)
add_definitions(${GL_DEFINITIONS})
add_definitions(${OPENCOLORIO_DEFINITIONS})
list(APPEND INC_SYS
${OPENCOLORIO_INCLUDE_DIRS}
@@ -68,6 +67,9 @@ if(WITH_OPENCOLORIO)
list(APPEND INC_SYS
${BOOST_INCLUDE_DIR}
)
add_definitions(
-DOpenColorIO_STATIC
)
list(APPEND LIB
${BOOST_LIBRARIES}
)

View File

@@ -112,7 +112,7 @@ void MeshTopology::getEdgeVertexIndices(int edge_index, int *v1, int *v2) const
if (edge_index >= edges_.size()) {
*v1 = -1;
*v2 = -1;
*v1 = -1;
return;
}

View File

@@ -31,13 +31,9 @@ typedef struct plConvexHull__ {
plConvexHull plConvexHullCompute(float (*coords)[3], int count);
void plConvexHullDelete(plConvexHull hull);
int plConvexHullNumVertices(plConvexHull hull);
int plConvexHullNumLoops(plConvexHull hull);
int plConvexHullNumFaces(plConvexHull hull);
void plConvexHullGetVertex(plConvexHull hull, int n, float coords[3], int *original_index);
void plConvexHullGetLoop(plConvexHull hull, int n, int *v_from, int *v_to);
int plConvexHullGetReversedLoopIndex(plConvexHull hull, int n);
int plConvexHullGetFaceSize(plConvexHull hull, int n);
void plConvexHullGetFaceLoops(plConvexHull hull, int n, int *loops);
void plConvexHullGetFaceVertices(plConvexHull hull, int n, int *vertices);
#ifdef __cplusplus

View File

@@ -39,12 +39,6 @@ int plConvexHullNumVertices(plConvexHull hull)
return computer->vertices.size();
}
int plConvexHullNumLoops(plConvexHull hull)
{
btConvexHullComputer *computer(reinterpret_cast<btConvexHullComputer *>(hull));
return computer->edges.size();
}
int plConvexHullNumFaces(plConvexHull hull)
{
btConvexHullComputer *computer(reinterpret_cast<btConvexHullComputer *>(hull));
@@ -61,19 +55,6 @@ void plConvexHullGetVertex(plConvexHull hull, int n, float coords[3], int *origi
(*original_index) = computer->original_vertex_index[n];
}
void plConvexHullGetLoop(plConvexHull hull, int n, int *v_from, int *v_to)
{
btConvexHullComputer *computer(reinterpret_cast<btConvexHullComputer *>(hull));
(*v_from) = computer->edges[n].getSourceVertex();
(*v_to) = computer->edges[n].getTargetVertex();
}
int plConvexHullGetReversedLoopIndex(plConvexHull hull, int n)
{
btConvexHullComputer *computer(reinterpret_cast<btConvexHullComputer *>(hull));
return computer->edges[n].getReverseEdge() - &computer->edges[0];
}
int plConvexHullGetFaceSize(plConvexHull hull, int n)
{
btConvexHullComputer *computer(reinterpret_cast<btConvexHullComputer *>(hull));
@@ -88,19 +69,6 @@ int plConvexHullGetFaceSize(plConvexHull hull, int n)
return count;
}
void plConvexHullGetFaceLoops(plConvexHull hull, int n, int *loops)
{
btConvexHullComputer *computer(reinterpret_cast<btConvexHullComputer *>(hull));
const btConvexHullComputer::Edge *e_orig, *e;
int count;
for (e_orig = &computer->edges[computer->faces[n]], e = e_orig, count = 0;
count == 0 || e != e_orig;
e = e->getNextEdgeOfFace(), count++) {
loops[count] = e - &computer->edges[0];
}
}
void plConvexHullGetFaceVertices(plConvexHull hull, int n, int *vertices)
{
btConvexHullComputer *computer(reinterpret_cast<btConvexHullComputer *>(hull));

View File

@@ -49,16 +49,16 @@ def _initialize():
def paths():
# RELEASE SCRIPTS: official scripts distributed in Blender releases
addon_paths = _bpy.utils.script_paths(subdir="addons")
addon_paths = _bpy.utils.script_paths("addons")
# CONTRIB SCRIPTS: good for testing but not official scripts yet
# if folder addons_contrib/ exists, scripts in there will be loaded too
addon_paths += _bpy.utils.script_paths(subdir="addons_contrib")
addon_paths += _bpy.utils.script_paths("addons_contrib")
return addon_paths
def modules_refresh(*, module_cache=addons_fake_modules):
def modules_refresh(module_cache=addons_fake_modules):
global error_encoding
import os
@@ -203,9 +203,9 @@ def modules_refresh(*, module_cache=addons_fake_modules):
del modules_stale
def modules(*, module_cache=addons_fake_modules, refresh=True):
def modules(module_cache=addons_fake_modules, *, refresh=True):
if refresh or ((module_cache is addons_fake_modules) and modules._is_first):
modules_refresh(module_cache=module_cache)
modules_refresh(module_cache)
modules._is_first = False
mod_list = list(module_cache.values())
@@ -358,8 +358,7 @@ def enable(module_name, *, default_set=False, persistent=False, handle_error=Non
except Exception as ex:
# if the addon doesn't exist, don't print full traceback
if type(ex) is ImportError and ex.name == module_name:
print("addon not loaded:", repr(module_name))
print("cause:", str(ex))
print("addon not found:", repr(module_name))
else:
handle_error(ex)
@@ -513,7 +512,7 @@ def _blender_manual_url_prefix():
return "https://docs.blender.org/manual/en/" + manual_version
def module_bl_info(mod, *, info_basis=None):
def module_bl_info(mod, info_basis=None):
if info_basis is None:
info_basis = {
"name": "",

View File

@@ -134,7 +134,7 @@ def _disable(template_id, *, handle_error=None):
print("\tapp_template_utils.disable", template_id)
def import_from_path(path, *, ignore_not_found=False):
def import_from_path(path, ignore_not_found=False):
import os
from importlib import import_module
base_module, template_id = path.rsplit(os.sep, 2)[-2:]
@@ -148,9 +148,9 @@ def import_from_path(path, *, ignore_not_found=False):
raise ex
def import_from_id(template_id, *, ignore_not_found=False):
def import_from_id(template_id, ignore_not_found=False):
import os
path = next(iter(_bpy.utils.app_template_paths(path=template_id)), None)
path = next(iter(_bpy.utils.app_template_paths(template_id)), None)
if path is None:
if ignore_not_found:
return None
@@ -163,7 +163,7 @@ def import_from_id(template_id, *, ignore_not_found=False):
return import_from_path(path, ignore_not_found=ignore_not_found)
def activate(*, template_id=None):
def activate(template_id=None):
template_id_prev = _app_template["id"]
# not needed but may as well avoids redundant
@@ -190,4 +190,4 @@ def reset(*, reload_scripts=False):
# TODO reload_scripts
activate(template_id=template_id)
activate(template_id)

View File

@@ -1572,7 +1572,7 @@ class I18n:
if not os.path.isfile(dst):
print("WARNING: trying to write as python code into {}, which is not a file! Aborting.".format(dst))
return
prev, txt, nxt, _has_trans = self._parser_check_file(dst)
prev, txt, nxt, has_trans = self._parser_check_file(dst)
if prev is None and nxt is None:
print("WARNING: Looks like given python file {} has no auto-generated translations yet, will be added "
"at the end of the file, you can move that section later if needed...".format(dst))

View File

@@ -71,7 +71,7 @@ def rtl_process_po(args, settings):
po.write(kind="PO", dest=args.dst)
def language_menu(_args, settings):
def language_menu(args, settings):
# 'DEFAULT' and en_US are always valid, fully-translated "languages"!
stats = {"DEFAULT": 1.0, "en_US": 1.0}

View File

@@ -84,10 +84,10 @@ def protect_format_seq(msg):
# LRM = "\u200E"
# RLM = "\u200F"
LRE = "\u202A"
# RLE = "\u202B"
RLE = "\u202B"
PDF = "\u202C"
LRO = "\u202D"
# RLO = "\u202E"
RLO = "\u202E"
# uctrl = {LRE, RLE, PDF, LRO, RLO}
# Most likely incomplete, but seems to cover current needs.
format_codes = set("tslfd")

View File

@@ -26,7 +26,7 @@ __all__ = (
)
def generate(context, space_type, *, use_fallback_keys=True, use_reset=True):
def generate(context, space_type, use_fallback_keys=True, use_reset=True):
"""
Keymap for popup toolbar, currently generated each time.
"""

View File

@@ -17,7 +17,7 @@
# ##### END GPL LICENSE BLOCK #####
def keyconfig_data_oskey_from_ctrl(keyconfig_data_src, *, filter_fn=None):
def keyconfig_data_oskey_from_ctrl(keyconfig_data_src, filter_fn=None):
keyconfig_data_dst = []
for km_name, km_parms, km_items_data_src in keyconfig_data_src:
km_items_data_dst = km_items_data_src.copy()
@@ -61,4 +61,4 @@ def keyconfig_data_oskey_from_ctrl_for_macos(keyconfig_data_src):
return False
return True
return keyconfig_data_oskey_from_ctrl(keyconfig_data_src, filter_fn=filter_fn)
return keyconfig_data_oskey_from_ctrl(keyconfig_data_src, filter_fn)

View File

@@ -19,7 +19,7 @@
# <pep8-80 compliant>
def url_prefill_from_blender(*, addon_info=None):
def url_prefill_from_blender(addon_info=None):
import bpy
import gpu
import struct

View File

@@ -56,7 +56,7 @@ def _getattr_bytes(var, attr):
return var.path_resolve(attr, False).as_bytes()
def abspath(path, *, start=None, library=None):
def abspath(path, start=None, library=None):
"""
Returns the absolute path relative to the current blend file
using the "//" prefix.
@@ -92,7 +92,7 @@ def abspath(path, *, start=None, library=None):
return path
def relpath(path, *, start=None):
def relpath(path, start=None):
"""
Returns the path relative to the current blend file using the "//" prefix.
@@ -134,7 +134,7 @@ def is_subdir(path, directory):
return False
def clean_name(name, *, replace="_"):
def clean_name(name, replace="_"):
"""
Returns a name with characters replaced that
may cause problems under various circumstances,
@@ -311,7 +311,7 @@ def resolve_ncase(path):
return ncase_path if found else path
def ensure_ext(filepath, ext, *, case_sensitive=False):
def ensure_ext(filepath, ext, case_sensitive=False):
"""
Return the path with the extension added if it is not already set.
@@ -332,7 +332,7 @@ def ensure_ext(filepath, ext, *, case_sensitive=False):
return filepath + ext
def module_names(path, *, recursive=False):
def module_names(path, recursive=False):
"""
Return a list of modules which can be imported from *path*.
@@ -361,7 +361,7 @@ def module_names(path, *, recursive=False):
if isfile(fullpath):
modules.append((filename, fullpath))
if recursive:
for mod_name, mod_path in module_names(directory, recursive=True):
for mod_name, mod_path in module_names(directory, True):
modules.append(("%s.%s" % (filename, mod_name),
mod_path,
))

View File

@@ -81,7 +81,7 @@ _script_module_dirs = "startup", "modules"
_is_factory_startup = _bpy.app.factory_startup
def execfile(filepath, *, mod=None):
def execfile(filepath, mod=None):
"""
Execute a file path as a Python script.
@@ -193,7 +193,7 @@ _global_loaded_modules = [] # store loaded module names for reloading.
import bpy_types as _bpy_types # keep for comparisons, never ever reload this.
def load_scripts(*, reload_scripts=False, refresh_scripts=False):
def load_scripts(reload_scripts=False, refresh_scripts=False):
"""
Load scripts and run each modules register function.
@@ -357,7 +357,7 @@ def script_path_pref():
return _os.path.normpath(path) if path else None
def script_paths(*, subdir=None, user_pref=True, check_all=False, use_user=True):
def script_paths(subdir=None, user_pref=True, check_all=False, use_user=True):
"""
Returns a list of valid script paths.
@@ -446,16 +446,16 @@ def refresh_script_paths():
_sys_path_ensure_append(path)
def app_template_paths(*, path=None):
def app_template_paths(subdir=None):
"""
Returns valid application template paths.
:arg path: Optional subdir.
:type path: string
:arg subdir: Optional subdir.
:type subdir: string
:return: app template paths.
:rtype: generator
"""
subdir_args = (path,) if path is not None else ()
subdir_args = (subdir,) if subdir is not None else ()
# Note: keep in sync with: Blender's 'BKE_appdir_app_template_any'.
# Uses 'BLENDER_USER_SCRIPTS', 'BLENDER_SYSTEM_SCRIPTS'
# ... in this case 'system' accounts for 'local' too.
@@ -463,9 +463,9 @@ def app_template_paths(*, path=None):
(_user_resource, "bl_app_templates_user"),
(system_resource, "bl_app_templates_system"),
):
path_test = resource_fn('SCRIPTS', path=_os.path.join("startup", module_name, *subdir_args))
if path_test and _os.path.isdir(path_test):
yield path_test
path = resource_fn('SCRIPTS', _os.path.join("startup", module_name, *subdir_args))
if path and _os.path.isdir(path):
yield path
def preset_paths(subdir):
@@ -478,7 +478,7 @@ def preset_paths(subdir):
:rtype: list
"""
dirs = []
for path in script_paths(subdir="presets", check_all=True):
for path in script_paths("presets", check_all=True):
directory = _os.path.join(path, subdir)
if not directory.startswith(path):
raise Exception("invalid subdir given %r" % subdir)
@@ -532,7 +532,7 @@ def is_path_builtin(path):
return False
def smpte_from_seconds(time, *, fps=None, fps_base=None):
def smpte_from_seconds(time, fps=None, fps_base=None):
"""
Returns an SMPTE formatted string from the *time*:
``HH:MM:SS:FF``.
@@ -552,7 +552,7 @@ def smpte_from_seconds(time, *, fps=None, fps_base=None):
)
def smpte_from_frame(frame, *, fps=None, fps_base=None):
def smpte_from_frame(frame, fps=None, fps_base=None):
"""
Returns an SMPTE formatted string from the *frame*:
``HH:MM:SS:FF``.
@@ -585,7 +585,7 @@ def smpte_from_frame(frame, *, fps=None, fps_base=None):
))
def time_from_frame(frame, *, fps=None, fps_base=None):
def time_from_frame(frame, fps=None, fps_base=None):
"""
Returns the time from a frame number .
@@ -610,7 +610,7 @@ def time_from_frame(frame, *, fps=None, fps_base=None):
return timedelta(0, frame / fps)
def time_to_frame(time, *, fps=None, fps_base=None):
def time_to_frame(time, fps=None, fps_base=None):
"""
Returns a float frame number from a time given in seconds or
as a datetime.timedelta object.
@@ -639,7 +639,7 @@ def time_to_frame(time, *, fps=None, fps_base=None):
return time * fps
def preset_find(name, preset_path, *, display_name=False, ext=".py"):
def preset_find(name, preset_path, display_name=False, ext=".py"):
if not name:
return None
@@ -676,7 +676,7 @@ def keyconfig_init():
keyconfig_set(filepath)
def keyconfig_set(filepath, *, report=None):
def keyconfig_set(filepath, report=None):
from os.path import basename, splitext
if _bpy.app.debug_python:
@@ -712,14 +712,14 @@ def keyconfig_set(filepath, *, report=None):
return True
def user_resource(resource_type, *, path="", create=False):
def user_resource(resource_type, path="", create=False):
"""
Return a user resource path (normally from the users home directory).
:arg type: Resource type in ['DATAFILES', 'CONFIG', 'SCRIPTS', 'AUTOSAVE'].
:type type: string
:arg path: Optional subdirectory.
:type path: string
:arg subdir: Optional subdirectory.
:type subdir: string
:arg create: Treat the path as a directory and create
it if its not existing.
:type create: boolean
@@ -727,7 +727,7 @@ def user_resource(resource_type, *, path="", create=False):
:rtype: string
"""
target_path = _user_resource(resource_type, path=path)
target_path = _user_resource(resource_type, path)
if create:
# should always be true.

View File

@@ -156,9 +156,10 @@ def bake_action_iter(
# Note: BBONE_PROPS is a list so we can preserve the ordering
BBONE_PROPS = [
'bbone_curveinx', 'bbone_curveoutx',
'bbone_curveinz', 'bbone_curveoutz',
'bbone_curveiny', 'bbone_curveouty',
'bbone_rollin', 'bbone_rollout',
'bbone_scalein', 'bbone_scaleout',
'bbone_scaleinx', 'bbone_scaleoutx',
'bbone_scaleiny', 'bbone_scaleouty',
'bbone_easein', 'bbone_easeout'
]

View File

@@ -447,7 +447,7 @@ def path_reference(
"""
import os
is_relative = filepath.startswith("//")
filepath_abs = bpy.path.abspath(filepath, start=base_src, library=library)
filepath_abs = bpy.path.abspath(filepath, base_src, library)
filepath_abs = os.path.normpath(filepath_abs)
if mode in {'ABSOLUTE', 'RELATIVE', 'STRIP'}:

View File

@@ -64,7 +64,7 @@ def region_2d_to_vector_3d(region, rv3d, coord):
return view_vector
def region_2d_to_origin_3d(region, rv3d, coord, *, clamp=None):
def region_2d_to_origin_3d(region, rv3d, coord, clamp=None):
"""
Return the 3d view origin from the region relative 2d coords.
@@ -167,7 +167,7 @@ def region_2d_to_location_3d(region, rv3d, coord, depth_location):
)[0]
def location_3d_to_region_2d(region, rv3d, coord, *, default=None):
def location_3d_to_region_2d(region, rv3d, coord, default=None):
"""
Return the *region* relative 2d location of a 3d position.

View File

@@ -150,11 +150,7 @@ class Object(bpy_types.ID):
class WindowManager(bpy_types.ID):
__slots__ = ()
def popup_menu(
self, draw_func, *,
title="",
icon='NONE',
):
def popup_menu(self, draw_func, title="", icon='NONE'):
import bpy
popup = self.popmenu_begin__internal(title, icon=icon)
@@ -180,11 +176,7 @@ class WindowManager(bpy_types.ID):
finally:
self.popover_end__internal(popup, keymap=keymap)
def popup_menu_pie(
self, event, draw_func, *,
title="",
icon='NONE',
):
def popup_menu_pie(self, event, draw_func, title="", icon='NONE'):
import bpy
pie = self.piemenu_begin__internal(title, icon=icon, event=event)
@@ -400,7 +392,7 @@ class EditBone(StructRNA, _GenericBone, metaclass=StructMetaPropGroup):
self.tail = self.head + vec
self.roll = other.roll
def transform(self, matrix, *, scale=True, roll=True):
def transform(self, matrix, scale=True, roll=True):
"""
Transform the the bones head, tail, roll and envelope
(when the matrix has a scale component).
@@ -568,17 +560,9 @@ class Text(bpy_types.ID):
self.write(string)
def as_module(self):
import bpy
from os.path import splitext, join
from os.path import splitext
from types import ModuleType
name = self.name
mod = ModuleType(splitext(name)[0])
# This is a fake file-path, set this since some scripts check `__file__`,
# error messages may include this as well.
# NOTE: the file path may be a blank string if the file hasn't been saved.
mod.__dict__.update({
"__file__": join(bpy.data.filepath, name),
})
mod = ModuleType(splitext(self.name)[0])
# TODO: We could use Text.compiled (C struct member)
# if this is called often it will be much faster.
exec(self.as_string(), mod.__dict__)
@@ -747,7 +731,7 @@ class Operator(StructRNA, metaclass=RNAMeta):
return delattr(properties, attr)
return super().__delattr__(attr)
def as_keywords(self, *, ignore=()):
def as_keywords(self, ignore=()):
"""Return a copy of the properties as a dictionary"""
ignore = ignore + ("rna_type",)
return {attr: getattr(self, attr)

View File

@@ -86,7 +86,7 @@ def get_doc(obj):
return result and RE_EMPTY_LINE.sub('', result.rstrip()) or ''
def get_argspec(func, *, strip_self=True, doc=None, source=None):
def get_argspec(func, strip_self=True, doc=None, source=None):
"""Get argument specifications.
:param strip_self: strip `self` from argspec

Some files were not shown because too many files have changed in this diff Show More