apply patches
This commit is contained in:
parent
887c739ed6
commit
c88ad44057
13
GNUmakefile
13
GNUmakefile
|
@ -22,6 +22,7 @@ Blender Convenience Targets
|
|||
* developer: Enable faster builds, error checking and tests, recommended for developers.
|
||||
* ninja: Use ninja build tool for faster builds.
|
||||
* ccache: Use ccache for faster rebuilds.
|
||||
* tornavis-lite: Build lite adding mechanical blender deps.
|
||||
|
||||
Note: when passing in multiple targets their order is not important.
|
||||
So for a fast build you can for e.g. run 'make lite ccache ninja'.
|
||||
|
@ -126,6 +127,9 @@ Utilities
|
|||
* update_code:
|
||||
Updates git and all submodules but not svn.
|
||||
|
||||
* tornavis-apply:
|
||||
Applies mechanical Blender patches.
|
||||
|
||||
* format:
|
||||
Format source code using clang-format & autopep8 (uses PATHS if passed in). For example::
|
||||
|
||||
|
@ -276,6 +280,11 @@ ifneq "$(findstring lite, $(MAKECMDGOALS))" ""
|
|||
BUILD_DIR:=$(BUILD_DIR)_lite
|
||||
CMAKE_CONFIG_ARGS:=-C"$(BLENDER_DIR)/build_files/cmake/config/blender_lite.cmake" $(CMAKE_CONFIG_ARGS)
|
||||
endif
|
||||
ifneq "$(findstring mbleder-lite, $(MAKECMDGOALS))" ""
|
||||
BUILD_DIR:=$(BUILD_DIR)_lite
|
||||
CMAKE_CONFIG_ARGS:=-C"$(BLENDER_DIR)/build_files/cmake/config/blender_lite.cmake" $(CMAKE_CONFIG_ARGS)
|
||||
CMAKE_CONFIG_ARGS:=-DWITH_BOOST=YES $(CMAKE_CONFIG_ARGS)
|
||||
endif
|
||||
ifneq "$(findstring release, $(MAKECMDGOALS))" ""
|
||||
BUILD_DIR:=$(BUILD_DIR)_release
|
||||
CMAKE_CONFIG_ARGS:=-C"$(BLENDER_DIR)/build_files/cmake/config/blender_release.cmake" $(CMAKE_CONFIG_ARGS)
|
||||
|
@ -407,6 +416,7 @@ bpy: all
|
|||
developer: all
|
||||
ninja: all
|
||||
ccache: all
|
||||
tornavis-lite: all
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Build dependencies
|
||||
|
@ -590,6 +600,9 @@ format: .FORCE
|
|||
@$(PYTHON) tools/utils_maintenance/autopep8_format_paths.py --autopep8-command="$(AUTOPEP8)" $(PATHS)
|
||||
|
||||
|
||||
tornavis-apply: .FORCE
|
||||
@$(PYTHON) ./build_files/utils/apply_tornavis_patches.py
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Documentation
|
||||
#
|
||||
|
|
21
README.md
21
README.md
|
@ -4,35 +4,24 @@ linking to external resources instead of including content in-line.
|
|||
See 'release/text/readme.html' for the end user read-me.
|
||||
-->
|
||||
|
||||
Blender
|
||||
![Tornavis logo](https://www.tornavis.org/tornavis.png)
|
||||
=======
|
||||
|
||||
Blender is the free and open source 3D creation suite.
|
||||
It supports the entirety of the 3D pipeline-modeling, rigging, animation, simulation, rendering, compositing,
|
||||
motion tracking and video editing.
|
||||
|
||||
![Blender screenshot](https://code.blender.org/wp-content/uploads/2018/12/springrg.jpg "Blender screenshot")
|
||||
Tornavis Project (aka mblender) aims to give mechanical engineering and design tools to a really awesome piece of software.
|
||||
|
||||
Project Pages
|
||||
-------------
|
||||
|
||||
- [Main Website](http://www.blender.org)
|
||||
- [Reference Manual](https://docs.blender.org/manual/en/latest/index.html)
|
||||
- [User Community](https://www.blender.org/community/)
|
||||
- [Website](https://www.tornavis.org)
|
||||
|
||||
Development
|
||||
-----------
|
||||
|
||||
- [Build Instructions](https://developer.blender.org/docs/handbook/building_blender/)
|
||||
- [Code Review & Bug Tracker](https://projects.blender.org)
|
||||
- [Developer Forum](https://devtalk.blender.org)
|
||||
- [Developer Documentation](https://developer.blender.org/docs/)
|
||||
|
||||
Project is currently on development, on **early** early stages.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Blender as a whole is licensed under the GNU General Public License, Version 3.
|
||||
Individual files may have a different, but compatible license.
|
||||
Tornavis inherits Blender License.
|
||||
|
||||
See [blender.org/about/license](https://www.blender.org/about/license) for details.
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Mechanical Blender
|
||||
|
||||
"""
|
||||
"make mblender" for applying mblender patches on current source.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
import os
|
||||
|
||||
import make_utils
|
||||
from make_utils import call
|
||||
|
||||
MB_0001 = "https://www.tornavis.org/mblender_patches/patches/mb-0001-operator-repeat.patch"
|
||||
MB_0002 = "https://www.tornavis.org/mblender_patches/patches/mb-0002-readme-file.patch"
|
||||
MB_0003 = "https://www.tornavis.org/mblender_patches/patches/mb-0003-mblender-make-target-windows.patch"
|
||||
MB_0004 = "https://www.tornavis.org/mblender_patches/patches/mb-0004-mblender-make-target-linux.patch"
|
||||
MB_0005 = "https://www.tornavis.org/mblender_patches/patches/mb-0005-splash-changes.patch"
|
||||
MB_0006 = "https://www.tornavis.org/mblender_patches/patches/mb-0006-allow-no-modal-transform.patch"
|
||||
MB_0007 = "https://www.tornavis.org/mblender_patches/patches/mb-0007-transform-flags.patch"
|
||||
MB_0008 = "https://www.tornavis.org/mblender_patches/patches/mb-0008-mblender-core.patch"
|
||||
MB_0009 = "https://www.tornavis.org/mblender_patches/patches/mb-0009-addon-menu-references.patch"
|
||||
MB_0010 = "https://www.tornavis.org/mblender_patches/patches/mb-0010-url-presets.patch"
|
||||
MB_0011 = "https://www.tornavis.org/mblender_patches/patches/mb-0011-operator-handlers.patch"
|
||||
MB_0012 = "https://www.tornavis.org/mblender_patches/patches/mb-0012-custom-splash.patch"
|
||||
MB_0013 = "https://www.tornavis.org/mblender_patches/patches/mb-0013-blender-top-bar.patch"
|
||||
MB_0013_BIN = "https://www.tornavis.org/mblender_patches/patches/mb-0013-blender-top-bar.tar"
|
||||
MB_0014 = "https://www.tornavis.org/mblender_patches/patches/mb-0014-bpy-images.patch"
|
||||
MB_0015 = "https://www.tornavis.org/mblender_patches/patches/mb-0015-image-ui.patch"
|
||||
MB_0016 = "https://www.tornavis.org/mblender_patches/patches/mb-0016-create-object-with-custom-orientation.patch"
|
||||
|
||||
|
||||
def parse_arguments() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--git-command", default="git")
|
||||
parser.add_argument("--wget-command", default="wget")
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
args = parse_arguments()
|
||||
git_command = args.git_command
|
||||
wget_command = args.wget_command
|
||||
|
||||
tmp_file = "/tmp/mblender.patch"
|
||||
tmp_file2 = "/tmp/mblender.tar"
|
||||
|
||||
if make_utils.command_missing(git_command):
|
||||
sys.stderr.write("git not found, can't checkout test files\n")
|
||||
sys.exit(1)
|
||||
|
||||
if make_utils.command_missing(wget_command):
|
||||
sys.stderr.write("wget not found, used for downloading patches\n")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
call([wget_command, MB_0001, "-O", tmp_file])
|
||||
call([git_command, "apply", tmp_file])
|
||||
|
||||
call([wget_command, MB_0002, "-O", tmp_file])
|
||||
call([git_command, "apply", tmp_file])
|
||||
|
||||
call([wget_command, MB_0003, "-O", tmp_file])
|
||||
call([git_command, "apply", tmp_file])
|
||||
|
||||
# MB-0004 Already applied
|
||||
|
||||
call([wget_command, MB_0005, "-O", tmp_file])
|
||||
call([git_command, "apply", tmp_file])
|
||||
|
||||
call([wget_command, MB_0006, "-O", tmp_file])
|
||||
call([git_command, "apply", tmp_file])
|
||||
|
||||
call([wget_command, MB_0007, "-O", tmp_file])
|
||||
call([git_command, "apply", tmp_file])
|
||||
|
||||
call([wget_command, MB_0008, "-O", tmp_file])
|
||||
call([git_command, "apply", tmp_file])
|
||||
|
||||
call([wget_command, MB_0009, "-O", tmp_file])
|
||||
call([git_command, "apply", tmp_file])
|
||||
|
||||
call([wget_command, MB_0010, "-O", tmp_file])
|
||||
call([git_command, "apply", tmp_file])
|
||||
|
||||
call([wget_command, MB_0011, "-O", tmp_file])
|
||||
call([git_command, "apply", tmp_file])
|
||||
|
||||
call([wget_command, MB_0012, "-O", tmp_file])
|
||||
call([git_command, "apply", tmp_file])
|
||||
|
||||
call([wget_command, MB_0013, "-O", tmp_file])
|
||||
call([git_command, "apply", tmp_file])
|
||||
|
||||
call([wget_command, MB_0013_BIN, "-O", tmp_file2])
|
||||
call(["cmake","-E","tar", "xf", tmp_file2])
|
||||
|
||||
call([wget_command, MB_0014, "-O", tmp_file])
|
||||
call([git_command, "apply", tmp_file])
|
||||
|
||||
call([wget_command, MB_0015, "-O", tmp_file])
|
||||
call([git_command, "apply", tmp_file])
|
||||
|
||||
call([wget_command, MB_0016, "-O", tmp_file])
|
||||
call([git_command, "apply", tmp_file])
|
|
@ -0,0 +1,116 @@
|
|||
if "%GIT%" == "" (
|
||||
echo Git not found, cannot apply patches.
|
||||
goto ERR
|
||||
)
|
||||
|
||||
if "%CURL%" == "" (
|
||||
echo Curl not found, cannot download patches
|
||||
goto ERR
|
||||
)
|
||||
|
||||
set MB_0001=https://www.tornavis.org/mblender_patches/patches/mb-0001-operator-repeat.patch
|
||||
set MB_0002=https://www.tornavis.org/mblender_patches/patches/mb-0002-readme-file.patch
|
||||
set MB_0003=https://www.tornavis.org/mblender_patches/patches/mb-0003-mblender-make-target-windows.patch
|
||||
set MB_0004=https://www.tornavis.org/mblender_patches/patches/mb-0004-mblender-make-target-linux.patch
|
||||
set MB_0005=https://www.tornavis.org/mblender_patches/patches/mb-0005-splash-changes.patch
|
||||
set MB_0006=https://www.tornavis.org/mblender_patches/patches/mb-0006-allow-no-modal-transform.patch
|
||||
set MB_0007=https://www.tornavis.org/mblender_patches/patches/mb-0007-transform-flags.patch
|
||||
set MB_0008=https://www.tornavis.org/mblender_patches/patches/mb-0008-mblender-core.patch
|
||||
set MB_0009=https://www.tornavis.org/mblender_patches/patches/mb-0009-addon-menu-references.patch
|
||||
set MB_0010=https://www.tornavis.org/mblender_patches/patches/mb-0010-url-presets.patch
|
||||
set MB_0011=https://www.tornavis.org/mblender_patches/patches/mb-0011-operator-handlers.patch
|
||||
set MB_0012=https://www.tornavis.org/mblender_patches/patches/mb-0012-custom-splash.patch
|
||||
set MB_0013=https://www.tornavis.org/mblender_patches/patches/mb-0013-blender-top-bar.patch
|
||||
set MB_0013_BIN=https://www.tornavis.org/mblender_patches/patches/mb-0013-blender-top-bar.tar
|
||||
set MB_0014=https://www.tornavis.org/mblender_patches/patches/mb-0014-bpy-images.patch
|
||||
set MB_0015=https://www.tornavis.org/mblender_patches/patches/mb-0015-image-ui.patch
|
||||
set MB_0016=https://www.tornavis.org/mblender_patches/patches/mb-0016-create-object-with-custom-orientation.patch
|
||||
set MB_0017=https://www.tornavis.org/mblender_patches/patches/mb-0017-transform-orientation-origin.patch
|
||||
set MB_0018=https://www.tornavis.org/mblender_patches/patches/mb-0018-ucs.patch
|
||||
|
||||
echo [APPLY] %MB_0001%
|
||||
"%CURL%" "%MB_0001%" --ssl-no-revoke | "%GIT%" apply
|
||||
if errorlevel 1 goto ERR
|
||||
|
||||
echo [APPLY] %MB_0002%
|
||||
"%CURL%" "%MB_0002%" --ssl-no-revoke | "%GIT%" apply
|
||||
if errorlevel 1 goto ERR
|
||||
|
||||
REM MB-0003 already applied
|
||||
|
||||
echo [APPLY] "%MB_0004%
|
||||
"%CURL%" "%MB_0004%" --ssl-no-revoke | "%GIT%" apply
|
||||
if errorlevel 1 goto ERR
|
||||
|
||||
echo [APPLY]"%MB_0005%
|
||||
"%CURL%" "%MB_0005%" --ssl-no-revoke | "%GIT%" apply
|
||||
if errorlevel 1 goto ERR
|
||||
|
||||
echo [APPLY] "%MB_0006%
|
||||
"%CURL%" "%MB_0006%" --ssl-no-revoke | "%GIT%" apply
|
||||
if errorlevel 1 goto ERR
|
||||
|
||||
echo [APPLY] "%MB_0007%
|
||||
"%CURL%" "%MB_0007%" --ssl-no-revoke | "%GIT%" apply
|
||||
if errorlevel 1 goto ERR
|
||||
|
||||
echo [APPLY] "%MB_0008%
|
||||
"%CURL%" "%MB_0008%" --ssl-no-revoke | "%GIT%" apply
|
||||
if errorlevel 1 goto ERR
|
||||
|
||||
echo [APPLY] "%MB_0009%
|
||||
"%CURL%" "%MB_0009%" --ssl-no-revoke | "%GIT%" apply
|
||||
if errorlevel 1 goto ERR
|
||||
|
||||
echo [APPLY] "%MB_0010%
|
||||
"%CURL%" "%MB_0010%" --ssl-no-revoke | "%GIT%" apply
|
||||
if errorlevel 1 goto ERR
|
||||
|
||||
echo [APPLY] "%MB_0011%
|
||||
"%CURL%" "%MB_0011%" --ssl-no-revoke | "%GIT%" apply
|
||||
if errorlevel 1 goto ERR
|
||||
|
||||
echo [APPLY] "%MB_0012%
|
||||
"%CURL%" "%MB_0012%" --ssl-no-revoke | "%GIT%" apply
|
||||
if errorlevel 1 goto ERR
|
||||
|
||||
echo [APPLY] "%MB_0013%
|
||||
"%CURL%" "%MB_0013%" --ssl-no-revoke | "%GIT%" apply
|
||||
if errorlevel 1 goto ERR
|
||||
|
||||
echo [BINARY] %MB_0013_BIN%
|
||||
"%CURL%" "%MB_0013_BIN%" --ssl-no-revoke -o data.tar
|
||||
if errorlevel 1 goto ERR
|
||||
"%CMAKE%" -E tar xf data.tar
|
||||
if errorlevel 1 goto ERR
|
||||
del data.tar
|
||||
if errorlevel 1 goto ERR
|
||||
|
||||
echo [APPLY] "%MB_0014%
|
||||
"%CURL%" "%MB_0014%" --ssl-no-revoke | "%GIT%" apply
|
||||
if errorlevel 1 goto ERR
|
||||
|
||||
echo [APPLY] "%MB_0015%
|
||||
"%CURL%" "%MB_0015%" --ssl-no-revoke | "%GIT%" apply
|
||||
if errorlevel 1 goto ERR
|
||||
|
||||
echo [APPLY] "%MB_0016%
|
||||
"%CURL%" "%MB_0016%" --ssl-no-revoke | "%GIT%" apply
|
||||
if errorlevel 1 goto ERR
|
||||
|
||||
echo [APPLY] "%MB_0017%
|
||||
"%CURL%" "%MB_0017%" --ssl-no-revoke | "%GIT%" apply
|
||||
if errorlevel 1 goto ERR
|
||||
|
||||
echo [APPLY] "%MB_0018%
|
||||
"%CURL%" "%MB_0018%" --ssl-no-revoke | "%GIT%" apply
|
||||
if errorlevel 1 goto ERR
|
||||
|
||||
echo [OK] Now build blender as usually.
|
||||
|
||||
:EOF
|
||||
exit /b 0
|
||||
|
||||
:ERR
|
||||
echo [ERROR] Something went wrong!
|
||||
exit /b 1
|
|
@ -3,6 +3,7 @@ for %%X in (svn.exe) do (set SVN=%%~$PATH:X)
|
|||
for %%X in (cmake.exe) do (set CMAKE=%%~$PATH:X)
|
||||
for %%X in (ctest.exe) do (set CTEST=%%~$PATH:X)
|
||||
for %%X in (git.exe) do (set GIT=%%~$PATH:X)
|
||||
for %%X in (curl.exe) do (set CURL=%%~$PATH:X)
|
||||
REM For python, default on 310 but if that does not exist also check
|
||||
REM the 311, 312 and finally 39 folders to see if those are there, it checks
|
||||
REM this far ahead to ensure good lib folder compatibility in the future
|
||||
|
|
|
@ -113,6 +113,13 @@ if NOT "%1" == "" (
|
|||
) else if "%1" == "svnfix" (
|
||||
set SVN_FIX=1
|
||||
goto EOF
|
||||
) else if "%1" == "tornavis-apply" (
|
||||
set MB_PATCHES=1
|
||||
goto EOF
|
||||
) else if "%1" == "tornavis-lite" (
|
||||
set TARGET=Lite
|
||||
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -C"%BLENDER_DIR%\build_files\cmake\config\blender_lite.cmake"
|
||||
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DWITH_BOOST=On
|
||||
) else (
|
||||
echo Command "%1" unknown, aborting!
|
||||
goto ERR
|
||||
|
|
|
@ -6,6 +6,7 @@ echo - lite
|
|||
echo - headless
|
||||
echo - cycles
|
||||
echo - bpy
|
||||
echo - tornavis-lite ^(lite adding tornavis deps^)
|
||||
echo.
|
||||
echo Utilities ^(not associated with building^)
|
||||
echo - clean ^(Target must be set^)
|
||||
|
@ -15,6 +16,7 @@ echo - nobuild ^(only generate project files^)
|
|||
echo - showhash ^(Show git hashes of source tree^)
|
||||
echo - test ^(Run automated tests with ctest^)
|
||||
echo - format [path] ^(Format the source using clang-format, path is optional, requires python 3.x to be available^)
|
||||
echo - tornavis-apply ^(Apply all tornavis' patches^)
|
||||
echo.
|
||||
echo Configuration options
|
||||
echo - verbose ^(enable diagnostic output during configuration^)
|
||||
|
|
5
make.bat
5
make.bat
|
@ -16,6 +16,11 @@ if errorlevel 1 goto EOF
|
|||
call "%BLENDER_DIR%\build_files\windows\find_dependencies.cmd"
|
||||
if errorlevel 1 goto EOF
|
||||
|
||||
if "%MB_PATCHES%" == "1" (
|
||||
call "%BLENDER_DIR%\build_files\windows\apply_tornavis_patches.cmd"
|
||||
goto EOF
|
||||
)
|
||||
|
||||
REM if it is one of the convenience targets and BLENDER_BIN is set
|
||||
REM skip compiler detection
|
||||
if "%ICONS%%ICONS_GEOM%%DOC_PY%" == "1" (
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Binary data like icons or images related to mechanical blender
|
Binary file not shown.
After Width: | Height: | Size: 6.8 KiB |
|
@ -13,8 +13,27 @@ _op_as_string = _ops_module.as_string
|
|||
_op_get_rna_type = _ops_module.get_rna_type
|
||||
_op_get_bl_options = _ops_module.get_bl_options
|
||||
|
||||
_op_handlers = _ops_module.handlers
|
||||
|
||||
_ModuleType = type(_ops_module)
|
||||
|
||||
class handler_action:
|
||||
def __init__(self, mod, append_func, remove_func):
|
||||
self._mod = mod
|
||||
self._append_func = append_func
|
||||
self._remove_func = remove_func
|
||||
|
||||
def append(self,cb, owner = None, args = None, poll = None):
|
||||
#is there a way to remove self from console show?
|
||||
self._append_func(owner=owner, op = self._mod.idname(), cb=cb, args=args, poll = poll)
|
||||
|
||||
def remove(self, cb = None, owner = None):
|
||||
self._remove_func(owner=owner, op = self._mod.idname(), cb=cb, args=None, poll = None)
|
||||
|
||||
|
||||
def remove_handlers(owner = None, cb = None):
|
||||
_op_handlers.remove(owner = owner, cb = cb, op = None, args = None, poll = None)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Callable Operator Wrapper
|
||||
|
@ -26,7 +45,14 @@ class _BPyOpsSubModOp:
|
|||
eg. bpy.ops.object.somefunc
|
||||
"""
|
||||
|
||||
__slots__ = ("_module", "_func")
|
||||
__slots__ = ("_module", "_func", "handlers")
|
||||
|
||||
class _handlers:
|
||||
def __init__(self, mod):
|
||||
self.invoke_pre = handler_action(mod, _op_handlers.pre_invoke, _op_handlers.pre_invoke_remove)
|
||||
self.invoke_post = handler_action(mod, _op_handlers.post_invoke, _op_handlers.post_invoke_remove)
|
||||
self.modal = handler_action(mod, _op_handlers.modal, _op_handlers.modal_remove)
|
||||
self.modal_end = handler_action(mod, _op_handlers.modal_end, _op_handlers.modal_end_remove)
|
||||
|
||||
def _get_doc(self):
|
||||
idname = self.idname()
|
||||
|
@ -77,6 +103,7 @@ class _BPyOpsSubModOp:
|
|||
def __init__(self, module, func):
|
||||
self._module = module
|
||||
self._func = func
|
||||
self.handlers = self._handlers(self)
|
||||
|
||||
def poll(self, *args):
|
||||
C_exec, _C_undo = _BPyOpsSubModOp._parse_args(args)
|
||||
|
@ -178,4 +205,6 @@ def __dir__():
|
|||
else:
|
||||
submodules.add(id_split[0])
|
||||
|
||||
submodules.add("remove_handlers")
|
||||
|
||||
return list(submodules)
|
||||
|
|
|
@ -66,7 +66,7 @@ _preferences = _bpy.context.preferences
|
|||
_is_factory_startup = _bpy.app.factory_startup
|
||||
|
||||
# Directories added to the start of `sys.path` for all of Blender's "scripts" directories.
|
||||
_script_module_dirs = "startup", "modules"
|
||||
_script_module_dirs = "startup", "modules","tornavis"
|
||||
|
||||
# Base scripts, this points to the directory containing: "modules" & "startup" (see `_script_module_dirs`).
|
||||
# In Blender's code-base this is `./scripts`.
|
||||
|
@ -308,6 +308,10 @@ def load_scripts(*, reload_scripts=False, refresh_scripts=False, extensions=True
|
|||
for mod in modules_from_path(path, loaded_modules):
|
||||
test_register(mod)
|
||||
|
||||
if path_subdir == "tornavis":
|
||||
for mod in modules_from_path(path, loaded_modules):
|
||||
test_register(mod)
|
||||
|
||||
if reload_scripts:
|
||||
# Update key-maps for key-map items referencing operators defined in "startup".
|
||||
# Without this, key-map items wont be set properly, see: #113309.
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
# SPDX-FileCopyrightText: 2015-2023 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
"""
|
||||
This module contains utility functions to handle custom images.
|
||||
"""
|
||||
|
||||
__all__ = (
|
||||
"load",
|
||||
"release"
|
||||
"list",
|
||||
)
|
||||
|
||||
from _bpy import _utils_images
|
||||
|
||||
|
||||
list = []
|
||||
|
||||
|
||||
def load(name, path):
|
||||
r = _utils_images.load(name, path)
|
||||
if r != None:
|
||||
data = {'id' : r , 'name' : name, 'path' : path}
|
||||
list.append(data)
|
||||
return data;
|
||||
else:
|
||||
return None;
|
||||
|
||||
load.__doc__ = _utils_images.load.__doc__;
|
||||
|
||||
def release(image_id):
|
||||
r = _utils_images.release(image_id)
|
||||
if r == True:
|
||||
for data in list:
|
||||
if data.get('id') == image_id:
|
||||
list.remove(data)
|
||||
|
||||
return r;
|
||||
release.__doc__ = _utils_images.release.__doc__
|
||||
|
||||
import atexit
|
||||
|
||||
def exit_clear():
|
||||
while len(list):
|
||||
release(list[0].get('id'))
|
||||
|
||||
atexit.register(exit_clear)
|
||||
del atexit, exit_clear
|
|
@ -987,6 +987,11 @@ class AddonPreferences(StructRNA, metaclass=RNAMeta):
|
|||
__slots__ = ()
|
||||
|
||||
|
||||
class ReferencedDrawFunc:
|
||||
def __init__(self, func):
|
||||
self.func = func
|
||||
self.used = False
|
||||
|
||||
class _GenericUI:
|
||||
__slots__ = ()
|
||||
|
||||
|
@ -1007,6 +1012,13 @@ class _GenericUI:
|
|||
else:
|
||||
owner_names = None
|
||||
|
||||
if (hasattr(cls, "reference_debug") and cls.reference_debug):
|
||||
print ("---")
|
||||
# Reset drawn flag, to be able shown error if not used
|
||||
for label in cls.referenced_post:
|
||||
for ref in cls.referenced_post[label]:
|
||||
ref.used = False
|
||||
|
||||
for func in draw_ls._draw_funcs:
|
||||
|
||||
# Begin 'owner_id' filter.
|
||||
|
@ -1030,11 +1042,38 @@ class _GenericUI:
|
|||
|
||||
self.layout.operator_context = operator_context_default
|
||||
|
||||
for label in cls.referenced_post:
|
||||
for ref in cls.referenced_post[label]:
|
||||
if ref.used == False:
|
||||
print("ERR: ", label, " referenced not drawn in", self.__class__.__name__)
|
||||
|
||||
draw_funcs = draw_ls._draw_funcs = [cls.draw]
|
||||
cls.draw = draw_ls
|
||||
|
||||
cls.referenced_pre = {}
|
||||
cls.referenced_post = {}
|
||||
|
||||
return draw_funcs
|
||||
|
||||
def draw_referenced_pre(cls, label):
|
||||
if (hasattr(cls, "reference_debug") and cls.reference_debug):
|
||||
print (label)
|
||||
|
||||
cls._dyn_ui_initialize()
|
||||
if label in cls.referenced_pre:
|
||||
for ref in cls.referenced_pre[label]:
|
||||
#need to get the context
|
||||
ref.used = True
|
||||
ref.func(cls, None)
|
||||
|
||||
def draw_referenced_post(cls, label):
|
||||
cls._dyn_ui_initialize()
|
||||
if label in cls.referenced_post:
|
||||
for ref in cls.referenced_post[label]:
|
||||
#need to get the context
|
||||
ref.used = True
|
||||
ref.func(cls, None)
|
||||
|
||||
@staticmethod
|
||||
def _dyn_owner_apply(draw_func):
|
||||
from _bpy import _bl_owner_id_get
|
||||
|
@ -1047,24 +1086,36 @@ class _GenericUI:
|
|||
return bool(getattr(cls.draw, "_draw_funcs", None))
|
||||
|
||||
@classmethod
|
||||
def append(cls, draw_func):
|
||||
def append(cls, draw_func, label_referenced = None):
|
||||
"""
|
||||
Append a draw function to this menu,
|
||||
takes the same arguments as the menus draw function
|
||||
"""
|
||||
draw_funcs = cls._dyn_ui_initialize()
|
||||
cls._dyn_owner_apply(draw_func)
|
||||
draw_funcs.append(draw_func)
|
||||
|
||||
if label_referenced != None:
|
||||
if not (label_referenced in cls.referenced_post):
|
||||
cls.referenced_post[label_referenced] = []
|
||||
cls.referenced_post[label_referenced].append(ReferencedDrawFunc(draw_func))
|
||||
else:
|
||||
draw_funcs.append(draw_func)
|
||||
|
||||
@classmethod
|
||||
def prepend(cls, draw_func):
|
||||
def prepend(cls, draw_func, label_referenced = None):
|
||||
"""
|
||||
Prepend a draw function to this menu, takes the same arguments as
|
||||
the menus draw function
|
||||
"""
|
||||
draw_funcs = cls._dyn_ui_initialize()
|
||||
cls._dyn_owner_apply(draw_func)
|
||||
draw_funcs.insert(0, draw_func)
|
||||
|
||||
if label_referenced != None:
|
||||
if not (label_referenced in cls.referenced_pre):
|
||||
cls.referenced_pre[label_referenced] = []
|
||||
cls.referenced_pre[label_referenced].append(ReferencedDrawFunc(draw_func))
|
||||
else:
|
||||
draw_funcs.insert(0, draw_func)
|
||||
|
||||
@classmethod
|
||||
def remove(cls, draw_func):
|
||||
|
|
|
@ -3334,6 +3334,7 @@ class WM_MT_splash(Menu):
|
|||
|
||||
col2.operator("wm.url_open_preset", text="Donate", icon='FUND').type = 'FUND'
|
||||
col2.operator("wm.url_open_preset", text="What's New", icon='URL').type = 'RELEASE_NOTES'
|
||||
col2.operator("wm.url_open_preset", text="Tornavis project's Website", icon='URL').type = 'TORNAVIS'
|
||||
|
||||
layout.separator()
|
||||
layout.separator()
|
||||
|
|
|
@ -659,8 +659,12 @@ class VIEW3D_HT_header(Header):
|
|||
# Orientation
|
||||
if object_mode in {'OBJECT', 'EDIT', 'EDIT_GPENCIL'} or has_pose_mode:
|
||||
orient_slot = scene.transform_orientation_slots[0]
|
||||
row = layout.row(align=True)
|
||||
view = context.space_data
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(view, "ucs", text="UCS")
|
||||
|
||||
row = layout.row(align=True)
|
||||
sub = row.row()
|
||||
sub.ui_units_x = 4
|
||||
sub.prop_with_popover(
|
||||
|
@ -7624,7 +7628,10 @@ class VIEW3D_PT_transform_orientations(Panel):
|
|||
row = layout.row(align=False)
|
||||
row.prop(orientation, "name", text="", icon='OBJECT_ORIGIN')
|
||||
row.operator("transform.delete_orientation", text="", icon='X', emboss=False)
|
||||
|
||||
row = layout.row()
|
||||
row.label(text="Origin:")
|
||||
row = layout.row()
|
||||
row.prop(orientation, "origin", text="", icon='OBJECT_ORIGIN')
|
||||
|
||||
class VIEW3D_PT_gpencil_origin(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
import bpy
|
||||
import bpy.utils.images
|
||||
import os
|
||||
|
||||
img = None
|
||||
|
||||
class WM_MT_splash_about_mblender(bpy.types.Menu):
|
||||
bl_label = "About Tornavis"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.operator_context = 'EXEC_DEFAULT'
|
||||
|
||||
split = layout.split(factor=0.6)
|
||||
split.template_image_ui(image_value = img['id'], scale= 1)
|
||||
|
||||
layout.row().label(text="Tornavis - A project for giving CAD development to Blender")
|
||||
|
||||
row = layout.row()
|
||||
row.emboss = 'PULLDOWN_MENU'
|
||||
col = row.column()
|
||||
col.operator("wm.url_open", text="Patreon", icon='FUND').url = "https://www.patreon.com/tornavis"
|
||||
col.operator("wm.url_open", text="Credits", icon='URL').url = "https://tornavis.org/#credits"
|
||||
col.operator("wm.url_open", text="License", icon='URL').url = "https://tornavis.org/#license"
|
||||
col.operator("wm.url_open_preset", text="Tornavis Website", icon='URL').type = 'TORNAVIS'
|
||||
|
||||
def draw_mblender_about_menu(self, context):
|
||||
self.layout.operator("wm.splash_custom", text=WM_MT_splash_about_mblender.bl_label).menutype='WM_MT_splash_about_mblender'
|
||||
|
||||
def draw_blender_doc_menu(self, context):
|
||||
self.layout.operator("wm.url_open_preset", text="Tornavis Project's documentation", icon='URL').type = 'TORNAVIS_DOC'
|
||||
|
||||
def register():
|
||||
global img
|
||||
|
||||
bpy.types.TOPBAR_MT_blender.append(draw_mblender_about_menu, label_referenced = "About Blender")
|
||||
bpy.types.TOPBAR_MT_help.append(draw_blender_doc_menu, label_referenced = "Manual")
|
||||
bpy.utils.register_class(WM_MT_splash_about_mblender)
|
||||
|
||||
path = os.path.join(bpy.utils.system_resource('DATAFILES', path="tornavis"), 'tornavis_logo.png')
|
||||
img = bpy.utils.images.load('tornavis-logo', path)
|
||||
|
||||
def unregister():
|
||||
global img
|
||||
bpy.utils.unregister_class(AboutMBlenderOperator)
|
||||
bpy.utils.unregister_class(WM_MT_splash_about_mblender)
|
||||
bpy.utils.images.release(img['id'])
|
|
@ -0,0 +1,17 @@
|
|||
import bpy
|
||||
|
||||
def register ():
|
||||
# bpy.ops.wm.url_open_preset(type="TORNAVIS")
|
||||
|
||||
bpy.types.WM_OT_url_open_preset.preset_items.append(
|
||||
(('TORNAVIS', "Tornavis.org", "Tornavis project official web-site"),
|
||||
"https://www.tornavis.org")
|
||||
)
|
||||
bpy.types.WM_OT_url_open_preset.preset_items.append(
|
||||
(('TORNAVIS_DOC', "Tornavis Doc", "Tornavis project documentation"),
|
||||
"https://www.tornavis.org/#documentation")
|
||||
)
|
||||
|
||||
def unregister():
|
||||
pass
|
||||
|
|
@ -159,6 +159,7 @@ add_subdirectory(functions)
|
|||
add_subdirectory(makesdna)
|
||||
add_subdirectory(makesrna)
|
||||
add_subdirectory(compositor)
|
||||
add_subdirectory(tornavis)
|
||||
|
||||
if(WITH_BLENDER_THUMBNAILER)
|
||||
add_subdirectory(blendthumb)
|
||||
|
|
|
@ -69,6 +69,7 @@ struct View3D;
|
|||
struct ViewLayer;
|
||||
struct wmGizmoGroup;
|
||||
struct wmMsgBus;
|
||||
struct wmOpHandlers;
|
||||
struct wmWindow;
|
||||
struct wmWindowManager;
|
||||
struct WorkSpace;
|
||||
|
@ -191,6 +192,7 @@ void *CTX_wm_region_data(const bContext *C);
|
|||
ARegion *CTX_wm_menu(const bContext *C);
|
||||
wmGizmoGroup *CTX_wm_gizmo_group(const bContext *C);
|
||||
wmMsgBus *CTX_wm_message_bus(const bContext *C);
|
||||
wmOpHandlers *CTX_wm_op_handlers(const bContext *C);
|
||||
ReportList *CTX_wm_reports(const bContext *C);
|
||||
|
||||
View3D *CTX_wm_view3d(const bContext *C);
|
||||
|
|
|
@ -763,6 +763,11 @@ wmMsgBus *CTX_wm_message_bus(const bContext *C)
|
|||
return C->wm.manager ? C->wm.manager->message_bus : nullptr;
|
||||
}
|
||||
|
||||
struct wmOpHandlers *CTX_wm_op_handlers(const bContext *C)
|
||||
{
|
||||
return C->wm.manager ? C->wm.manager->op_handlers : nullptr;
|
||||
}
|
||||
|
||||
ReportList *CTX_wm_reports(const bContext *C)
|
||||
{
|
||||
if (C->wm.manager) {
|
||||
|
|
|
@ -104,10 +104,13 @@ void OVERLAY_grid_init(OVERLAY_Data *vedata)
|
|||
|
||||
float viewinv[4][4], wininv[4][4];
|
||||
float viewmat[4][4], winmat[4][4];
|
||||
float ucsmat[4][4], ucsinv[4][4];
|
||||
DRW_view_winmat_get(nullptr, winmat, false);
|
||||
DRW_view_winmat_get(nullptr, wininv, true);
|
||||
DRW_view_viewmat_get(nullptr, viewmat, false);
|
||||
DRW_view_viewmat_get(nullptr, viewinv, true);
|
||||
DRW_view_ucsmat_get(nullptr, ucsmat, false);
|
||||
DRW_view_ucsmat_get(nullptr, ucsinv, true);
|
||||
|
||||
/* If perspective view or non-axis aligned view. */
|
||||
if (winmat[3][3] == 0.0f || rv3d->view == RV3D_VIEW_USER) {
|
||||
|
@ -142,8 +145,8 @@ void OVERLAY_grid_init(OVERLAY_Data *vedata)
|
|||
zpos_flag = SHOW_AXIS_Z;
|
||||
|
||||
float zvec[3], campos[3];
|
||||
negate_v3_v3(zvec, viewinv[2]);
|
||||
copy_v3_v3(campos, viewinv[3]);
|
||||
negate_v3_v3(zvec, ucsinv[2]);
|
||||
copy_v3_v3(campos, ucsinv[3]);
|
||||
|
||||
/* z axis : chose the most facing plane */
|
||||
if (fabsf(zvec[0]) < fabsf(zvec[1])) {
|
||||
|
@ -205,7 +208,7 @@ void OVERLAY_grid_init(OVERLAY_Data *vedata)
|
|||
* component, which may not be correct if the user is "shrunk" or "enlarged" by zooming in or
|
||||
* out. Therefore, we need to compensate the values here. */
|
||||
/* Assumption is uniform scaling (all column vectors are of same length). */
|
||||
float viewinvscale = len_v3(viewinv[0]);
|
||||
float viewinvscale = len_v3(ucsinv[0]);
|
||||
grid->distance *= viewinvscale;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,5 +44,5 @@ void main()
|
|||
local_pos.z = clamp(local_pos.z, -1.0, 0.0);
|
||||
}
|
||||
|
||||
gl_Position = drw_view.winmat * (drw_view.viewmat * vec4(real_pos, 1.0));
|
||||
gl_Position = drw_view.winmat * (drw_view.ucsmat * vec4(real_pos, 1.0));
|
||||
}
|
||||
|
|
|
@ -694,6 +694,16 @@ bool DRW_pass_is_empty(DRWPass *pass);
|
|||
|
||||
/* Views. */
|
||||
|
||||
/**
|
||||
* Create a view with culling.
|
||||
*/
|
||||
DRWView *DRW_view_create(const float viewmat[4][4],
|
||||
const float winmat[4][4],
|
||||
const float (*culling_viewmat)[4],
|
||||
const float (*culling_winmat)[4],
|
||||
DRWCallVisibilityFn *visibility_fn);
|
||||
|
||||
|
||||
/**
|
||||
* Create a view with culling.
|
||||
*/
|
||||
|
@ -717,6 +727,10 @@ void DRW_view_update(DRWView *view,
|
|||
const float winmat[4][4],
|
||||
const float (*culling_viewmat)[4],
|
||||
const float (*culling_winmat)[4]);
|
||||
/**
|
||||
* Update ucs matrix
|
||||
*/
|
||||
void DRW_view_ucs_update(DRWView *view, const float ucsmat[4][4]);
|
||||
/**
|
||||
* Update matrices of a view created with #DRW_view_create_sub.
|
||||
*/
|
||||
|
@ -751,6 +765,7 @@ void DRW_view_clip_planes_set(DRWView *view, float (*planes)[4], int plane_len);
|
|||
|
||||
void DRW_view_winmat_get(const DRWView *view, float mat[4][4], bool inverse);
|
||||
void DRW_view_viewmat_get(const DRWView *view, float mat[4][4], bool inverse);
|
||||
void DRW_view_ucsmat_get(const DRWView *view, float mat[4][4], bool inverse);
|
||||
void DRW_view_persmat_get(const DRWView *view, float mat[4][4], bool inverse);
|
||||
|
||||
/**
|
||||
|
|
|
@ -581,6 +581,7 @@ static void drw_manager_init(DRWManager *dst, GPUViewport *viewport, const int s
|
|||
if (rv3d != nullptr) {
|
||||
dst->pixsize = rv3d->pixsize;
|
||||
dst->view_default = DRW_view_create(rv3d->viewmat, rv3d->winmat, nullptr, nullptr, nullptr);
|
||||
DRW_view_ucs_update(dst->view_default, rv3d->ucsmat);
|
||||
|
||||
if (dst->draw_ctx.sh_cfg == GPU_SHADER_CFG_CLIPPED) {
|
||||
int plane_len = (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXCLIP) ? 4 : 6;
|
||||
|
|
|
@ -2294,6 +2294,11 @@ void DRW_view_update(DRWView *view,
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
void DRW_view_ucs_update(DRWView *view, const float ucsmat[4][4]) {
|
||||
copy_m4_m4(view->storage.ucsmat.ptr(), ucsmat);
|
||||
}
|
||||
|
||||
const DRWView *DRW_view_default_get()
|
||||
{
|
||||
return DST.view_default;
|
||||
|
@ -2368,6 +2373,20 @@ void DRW_view_viewmat_get(const DRWView *view, float mat[4][4], bool inverse)
|
|||
copy_m4_m4(mat, (inverse) ? storage->viewinv.ptr() : storage->viewmat.ptr());
|
||||
}
|
||||
|
||||
void DRW_view_ucsmat_get(const DRWView *view, float mat[4][4], bool inverse)
|
||||
{
|
||||
view = (view) ? view : DST.view_default;
|
||||
const ViewMatrices *storage = &view->storage;
|
||||
copy_m4_m4(mat, storage->ucsmat.ptr());
|
||||
if (inverse) {
|
||||
float tmp[4][4];
|
||||
invert_m4_m4(tmp, mat);
|
||||
copy_m4_m4(mat, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DRW_view_winmat_get(const DRWView *view, float mat[4][4], bool inverse)
|
||||
{
|
||||
view = (view) ? view : DST.view_default;
|
||||
|
|
|
@ -125,6 +125,7 @@ struct ViewMatrices {
|
|||
float4x4 viewinv;
|
||||
float4x4 winmat;
|
||||
float4x4 wininv;
|
||||
float4x4 ucsmat;
|
||||
};
|
||||
BLI_STATIC_ASSERT_ALIGN(ViewMatrices, 16)
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ bool calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], floa
|
|||
void BIF_clearTransformOrientation(bContext *C);
|
||||
void BIF_removeTransformOrientation(bContext *C, TransformOrientation *target);
|
||||
void BIF_removeTransformOrientationIndex(bContext *C, int index);
|
||||
bool BIF_createTransformOrientation(bContext *C,
|
||||
TransformOrientation* BIF_createTransformOrientation(bContext *C,
|
||||
ReportList *reports,
|
||||
const char *name,
|
||||
bool use_view,
|
||||
|
|
|
@ -57,6 +57,8 @@ struct wmOperator;
|
|||
struct wmWindow;
|
||||
struct wmWindowManager;
|
||||
|
||||
struct TransformOrientation;
|
||||
|
||||
/* for derivedmesh drawing callbacks, for view3d_select, .... */
|
||||
struct ViewContext {
|
||||
bContext *C;
|
||||
|
@ -1048,6 +1050,15 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph,
|
|||
const rcti *rect,
|
||||
bool offscreen);
|
||||
bool ED_view3d_quat_from_axis_view(char view, char view_axis_roll, float r_quat[4]);
|
||||
|
||||
bool ED_view3d_quat_from_axis_view_transform(
|
||||
Scene *scene, View3D *v3d, const char view, const char view_axis_roll, float r_quat[4]);
|
||||
|
||||
bool ED_view3d_quat_from_axis_view_ucs(TransformOrientation *ts,
|
||||
char viewnum,
|
||||
char view_axis_roll,
|
||||
float quat[4]);
|
||||
|
||||
bool ED_view3d_quat_to_axis_view(const float viewquat[4],
|
||||
float epsilon,
|
||||
char *r_view,
|
||||
|
@ -1067,6 +1078,9 @@ char ED_view3d_lock_view_from_index(int index);
|
|||
char ED_view3d_axis_view_opposite(char view);
|
||||
bool ED_view3d_lock(RegionView3D *rv3d);
|
||||
|
||||
bool ED_view3d_lock_ucs(TransformOrientation *ts, struct RegionView3D *rv3d);
|
||||
|
||||
|
||||
void ED_view3d_datamask(const Scene *scene,
|
||||
ViewLayer *view_layer,
|
||||
const View3D *v3d,
|
||||
|
|
|
@ -2236,6 +2236,9 @@ void UI_menutype_draw(bContext *C, MenuType *mt, uiLayout *layout);
|
|||
*/
|
||||
void UI_paneltype_draw(bContext *C, PanelType *pt, uiLayout *layout);
|
||||
|
||||
void *uiLayoutGetParentObject(uiLayout *layout);
|
||||
struct ExtensionRNA *uiLayoutGetParentRnaExt(uiLayout *layout);
|
||||
|
||||
/* Only for convenience. */
|
||||
void uiLayoutSetContextFromBut(uiLayout *layout, uiBut *but);
|
||||
|
||||
|
@ -2457,6 +2460,9 @@ void uiTemplatePreview(uiLayout *layout,
|
|||
MTex *slot,
|
||||
const char *preview_id);
|
||||
void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname, bool expand);
|
||||
|
||||
void uiTemplateImageUI(uiLayout *layout, int image_id, float image_scale);
|
||||
|
||||
/**
|
||||
* \param icon_scale: Scale of the icon, 1x == button height.
|
||||
*/
|
||||
|
|
|
@ -168,6 +168,10 @@ struct uiLayout {
|
|||
eUIEmbossType emboss;
|
||||
/** for fixed width or height to avoid UI size changes */
|
||||
float units[2];
|
||||
|
||||
ExtensionRNA *parent_rna_ext;
|
||||
void *parent_object;
|
||||
|
||||
};
|
||||
|
||||
struct uiLayoutItemFlow {
|
||||
|
@ -6042,6 +6046,20 @@ bContextStore *uiLayoutGetContextStore(uiLayout *layout)
|
|||
return layout->context;
|
||||
}
|
||||
|
||||
void *uiLayoutGetParentObject(uiLayout * layout)
|
||||
{
|
||||
return layout->parent_object;
|
||||
}
|
||||
|
||||
ExtensionRNA *uiLayoutGetParentRnaExt(uiLayout *layout)
|
||||
{
|
||||
// rna ext is set on menu draw, layout maybe a sublayout
|
||||
while (layout && layout->parent_rna_ext == NULL) {
|
||||
layout = layout->parent;
|
||||
}
|
||||
return layout ? layout->parent_rna_ext : NULL;
|
||||
}
|
||||
|
||||
void uiLayoutContextCopy(uiLayout *layout, const bContextStore *context)
|
||||
{
|
||||
uiBlock *block = layout->root->block;
|
||||
|
@ -6136,6 +6154,9 @@ void UI_menutype_draw(bContext *C, MenuType *mt, uiLayout *layout)
|
|||
menu.layout = layout;
|
||||
menu.type = mt;
|
||||
|
||||
layout->parent_rna_ext = &mt->rna_ext;
|
||||
layout->parent_object = (void*) &menu;
|
||||
|
||||
if (G.debug & G_DEBUG_WM) {
|
||||
printf("%s: opening menu \"%s\"\n", __func__, mt->idname);
|
||||
}
|
||||
|
@ -6158,6 +6179,10 @@ void UI_menutype_draw(bContext *C, MenuType *mt, uiLayout *layout)
|
|||
if (layout->context) {
|
||||
CTX_store_set(C, nullptr);
|
||||
}
|
||||
|
||||
layout->parent_rna_ext = NULL;
|
||||
layout->parent_object = NULL;
|
||||
|
||||
}
|
||||
|
||||
static bool ui_layout_has_panel_label(const uiLayout *layout, const PanelType *pt)
|
||||
|
|
|
@ -84,6 +84,9 @@
|
|||
#include "ED_render.hh"
|
||||
#include "ED_screen.hh"
|
||||
#include "ED_undo.hh"
|
||||
#include "ED_datafiles.h"
|
||||
|
||||
#include "IMB_imbuf.hh"
|
||||
|
||||
#include "IMB_imbuf.hh"
|
||||
#include "IMB_imbuf_types.hh"
|
||||
|
@ -104,6 +107,8 @@
|
|||
#include "UI_view2d.hh"
|
||||
#include "interface_intern.hh"
|
||||
|
||||
#include "BPY_extern.h"
|
||||
|
||||
/* we may want to make this optional, disable for now. */
|
||||
// #define USE_OP_RESET_BUT
|
||||
|
||||
|
@ -3380,6 +3385,28 @@ void uiTemplatePreview(uiLayout *layout,
|
|||
|
||||
/** \} */
|
||||
|
||||
void uiTemplateImageUI(uiLayout* layout, int image_id,float image_scale) {
|
||||
|
||||
ImBuf *ibuf = IMB_dupImBuf((ImBuf *) BPY_utils_images_get(image_id));
|
||||
|
||||
if (ibuf) {
|
||||
int width = ibuf->x * image_scale;
|
||||
int height = (width * ibuf->y) / ibuf->x;
|
||||
|
||||
IMB_premultiply_alpha(ibuf);
|
||||
IMB_scaleImBuf(ibuf, width, height);
|
||||
|
||||
bTheme *btheme = UI_GetTheme();
|
||||
uchar *color = btheme->tui.wcol_menu_back.text_sel;
|
||||
//color = btheme->tui.wcol_box.inner;
|
||||
|
||||
uiBlock *block = uiLayoutAbsoluteBlock(layout);
|
||||
|
||||
uiBut *but = uiDefButImage(block, ibuf, 0, U.widget_unit, width, height, color);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name ColorRamp Template
|
||||
* \{ */
|
||||
|
|
|
@ -20,6 +20,7 @@ set(INC
|
|||
../../shader_fx
|
||||
../../windowmanager
|
||||
../../../../extern/fmtlib/include
|
||||
../transform
|
||||
|
||||
# RNA_prototypes.h
|
||||
${CMAKE_BINARY_DIR}/source/blender/makesrna
|
||||
|
|
|
@ -90,6 +90,7 @@
|
|||
#include "BKE_speaker.h"
|
||||
#include "BKE_vfont.hh"
|
||||
#include "BKE_volume.hh"
|
||||
#include "BKE_scene.h"
|
||||
|
||||
#include "DEG_depsgraph.hh"
|
||||
#include "DEG_depsgraph_build.hh"
|
||||
|
@ -127,6 +128,8 @@
|
|||
|
||||
#include "object_intern.h"
|
||||
|
||||
#include "transform_orientations.hh"
|
||||
|
||||
using blender::float3;
|
||||
using blender::float4x4;
|
||||
using blender::Vector;
|
||||
|
@ -348,15 +351,35 @@ float ED_object_new_primitive_matrix(bContext *C,
|
|||
View3D *v3d = CTX_wm_view3d(C);
|
||||
float mat[3][3], rmat[3][3], cmat[3][3], imat[3][3];
|
||||
|
||||
float ts_mat[3][3];
|
||||
char ts_name[MAX_NAME];
|
||||
//int orientation_index = v3d->twmode - V3D_MANIP_CUSTOM;
|
||||
TransformOrientation *custom_orientation = nullptr;
|
||||
if (scene->orientation_slots->type >= V3D_ORIENT_CUSTOM &&
|
||||
scene->orientation_slots->index_custom != -1)
|
||||
{
|
||||
custom_orientation = BKE_scene_transform_orientation_find(
|
||||
scene, scene->orientation_slots->index_custom);
|
||||
}
|
||||
|
||||
unit_m4(r_primmat);
|
||||
|
||||
eul_to_mat3(rmat, rot);
|
||||
invert_m3(rmat);
|
||||
|
||||
if (custom_orientation) {
|
||||
applyTransformOrientation(custom_orientation, ts_mat, ts_name);
|
||||
invert_m3(ts_mat);
|
||||
mul_m3_m3m3(mat, rmat, ts_mat);
|
||||
copy_m3_m3(rmat, mat);
|
||||
}
|
||||
|
||||
|
||||
/* inverse transform for initial rotation and object */
|
||||
copy_m3_m4(mat, obedit->object_to_world);
|
||||
mul_m3_m3m3(cmat, rmat, mat);
|
||||
invert_m3_m3(imat, cmat);
|
||||
|
||||
copy_m4_m3(r_primmat, imat);
|
||||
|
||||
/* center */
|
||||
|
|
|
@ -4025,9 +4025,10 @@ static void view3d_localview_update_rv3d(RegionView3D *rv3d)
|
|||
}
|
||||
|
||||
static void region_quadview_init_rv3d(
|
||||
ScrArea *area, ARegion *region, const char viewlock, const char view, const char persp)
|
||||
ScrArea *area, Scene *scene, ARegion *region, const char viewlock, const char view, const char persp)
|
||||
{
|
||||
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
|
||||
View3D *v3d = static_cast<View3D *>(area->spacedata.first);
|
||||
|
||||
if (persp == RV3D_CAMOB) {
|
||||
ED_view3d_lastview_store(rv3d);
|
||||
|
@ -4039,7 +4040,27 @@ static void region_quadview_init_rv3d(
|
|||
rv3d->view_axis_roll = RV3D_VIEW_AXIS_ROLL_0;
|
||||
rv3d->persp = persp;
|
||||
|
||||
ED_view3d_lock(rv3d);
|
||||
if (v3d->ucs) {
|
||||
TransformOrientation *custom_orientation = nullptr;
|
||||
if (scene->orientation_slots->type >= V3D_ORIENT_CUSTOM &&
|
||||
scene->orientation_slots->index_custom != -1)
|
||||
{
|
||||
custom_orientation = BKE_scene_transform_orientation_find(
|
||||
scene, scene->orientation_slots->index_custom);
|
||||
}
|
||||
|
||||
if (custom_orientation) {
|
||||
ED_view3d_lock_ucs(custom_orientation, rv3d);
|
||||
}
|
||||
else {
|
||||
// Invalid ucs
|
||||
ED_view3d_lock(rv3d);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Global
|
||||
ED_view3d_lock(rv3d);
|
||||
}
|
||||
view3d_localview_update_rv3d(rv3d);
|
||||
if ((viewlock & RV3D_BOXCLIP) && (persp == RV3D_ORTHO)) {
|
||||
ED_view3d_quadview_update(area, region, true);
|
||||
|
@ -4108,6 +4129,7 @@ static int region_quadview_exec(bContext *C, wmOperator *op)
|
|||
else {
|
||||
/* Enter quad-view */
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
region->alignment = RGN_ALIGN_QSPLIT;
|
||||
|
||||
|
@ -4132,14 +4154,20 @@ static int region_quadview_exec(bContext *C, wmOperator *op)
|
|||
(rv3d->viewlock_quad & ~RV3D_VIEWLOCK_INIT) :
|
||||
RV3D_LOCK_ROTATION;
|
||||
|
||||
region_quadview_init_rv3d(
|
||||
area, region, viewlock, ED_view3d_lock_view_from_index(index_qsplit++), RV3D_ORTHO);
|
||||
region_quadview_init_rv3d(area,
|
||||
scene,
|
||||
(region = region->next),
|
||||
viewlock,
|
||||
ED_view3d_lock_view_from_index(index_qsplit++),
|
||||
RV3D_ORTHO);
|
||||
region_quadview_init_rv3d(area,
|
||||
scene,
|
||||
(region = region->next),
|
||||
viewlock,
|
||||
ED_view3d_lock_view_from_index(index_qsplit++),
|
||||
RV3D_ORTHO);
|
||||
region_quadview_init_rv3d(area,
|
||||
scene,
|
||||
(region = region->next),
|
||||
viewlock,
|
||||
ED_view3d_lock_view_from_index(index_qsplit++),
|
||||
|
|
|
@ -134,6 +134,40 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph,
|
|||
/* NOTE: calls BKE_object_where_is_calc for camera... */
|
||||
view3d_viewmatrix_set(depsgraph, scene, v3d, rv3d, rect ? rect_scale : nullptr);
|
||||
}
|
||||
|
||||
if (v3d->ucs > 0) {
|
||||
TransformOrientation *custom_orientation = nullptr;
|
||||
if (scene->orientation_slots->type >= V3D_ORIENT_CUSTOM &&
|
||||
+scene->orientation_slots->index_custom != -1)
|
||||
{
|
||||
custom_orientation = BKE_scene_transform_orientation_find(
|
||||
+scene, scene->orientation_slots->index_custom);
|
||||
}
|
||||
|
||||
if (custom_orientation) {
|
||||
float m[4][4] = {{0}}, mt[4][4];
|
||||
unit_m4(m);
|
||||
unit_m4(mt); // Translation matrix
|
||||
|
||||
copy_m4_m3(m, custom_orientation->mat);
|
||||
translate_m4(mt,
|
||||
custom_orientation->origin[0],
|
||||
custom_orientation->origin[1],
|
||||
custom_orientation->origin[2]);
|
||||
|
||||
mul_m4_series(rv3d->ucsmat, rv3d->viewmat, mt, m);
|
||||
}
|
||||
else {
|
||||
// Invalid
|
||||
v3d->ucs = 0;
|
||||
copy_m4_m4(rv3d->ucsmat, rv3d->viewmat);
|
||||
}
|
||||
}
|
||||
else {
|
||||
copy_m4_m4(rv3d->ucsmat, rv3d->viewmat);
|
||||
}
|
||||
|
||||
|
||||
/* update utility matrices */
|
||||
mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
|
||||
invert_m4_m4(rv3d->persinv, rv3d->persmat);
|
||||
|
|
|
@ -164,7 +164,8 @@ static int view_axis_exec(bContext *C, wmOperator *op)
|
|||
/* Use this to test if we started out with a camera */
|
||||
const int nextperspo = (rv3d->persp == RV3D_CAMOB) ? rv3d->lpersp : perspo;
|
||||
float quat[4];
|
||||
ED_view3d_quat_from_axis_view(viewnum, view_axis_roll, quat);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ED_view3d_quat_from_axis_view_transform(scene, v3d, viewnum, view_axis_roll, quat);
|
||||
axis_set_view(
|
||||
C, v3d, region, quat, viewnum, view_axis_roll, nextperspo, align_quat, smooth_viewtx);
|
||||
|
||||
|
|
|
@ -1425,6 +1425,33 @@ static float view3d_quat_axis[6][4][4] = {
|
|||
|
||||
};
|
||||
|
||||
bool ED_view3d_quat_from_axis_view_transform(Scene *scene, View3D *v3d, const char view,
|
||||
const char view_axis_roll,
|
||||
float r_quat[4])
|
||||
{
|
||||
if (v3d->ucs) {
|
||||
TransformOrientation *custom_orientation = nullptr;
|
||||
if (scene->orientation_slots->type >= V3D_ORIENT_CUSTOM &&
|
||||
scene->orientation_slots->index_custom != -1)
|
||||
{
|
||||
custom_orientation = BKE_scene_transform_orientation_find(
|
||||
scene, scene->orientation_slots->index_custom);
|
||||
}
|
||||
|
||||
if (custom_orientation) {
|
||||
return ED_view3d_quat_from_axis_view_ucs(custom_orientation,view, view_axis_roll, r_quat);
|
||||
}
|
||||
else {
|
||||
// Invalid ucs
|
||||
return ED_view3d_quat_from_axis_view(view,view_axis_roll, r_quat);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return ED_view3d_quat_from_axis_view(view, view_axis_roll, r_quat);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ED_view3d_quat_from_axis_view(const char view, const char view_axis_roll, float r_quat[4])
|
||||
{
|
||||
BLI_assert(view_axis_roll <= RV3D_VIEW_AXIS_ROLL_270);
|
||||
|
@ -1435,6 +1462,43 @@ bool ED_view3d_quat_from_axis_view(const char view, const char view_axis_roll, f
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ED_view3d_quat_from_axis_view_ucs(TransformOrientation *ts,
|
||||
char view,
|
||||
char view_axis_roll, float quat[4])
|
||||
{
|
||||
float m[3][3];
|
||||
float eul[3];
|
||||
|
||||
copy_m3_m3(m, ts->mat);
|
||||
mat3_to_eul(eul, m);
|
||||
|
||||
switch (view) {
|
||||
case RV3D_VIEW_TOP:
|
||||
// XY
|
||||
invert_m3(m);
|
||||
mat3_to_quat(quat, m);
|
||||
break;
|
||||
case RV3D_VIEW_FRONT:
|
||||
// ZX
|
||||
rotate_eul(eul, 'X', M_PI / 2.0f);
|
||||
eul_to_mat3(m, eul);
|
||||
invert_m3(m);
|
||||
mat3_to_quat(quat, m);
|
||||
break;
|
||||
case RV3D_VIEW_RIGHT:
|
||||
// ZY
|
||||
rotate_eul(eul, 'Z', M_PI / 2.0f);
|
||||
rotate_eul(eul, 'X', M_PI / 2.0f);
|
||||
eul_to_mat3(m, eul);
|
||||
invert_m3(m);
|
||||
mat3_to_quat(quat, m);
|
||||
break;
|
||||
default:
|
||||
ED_view3d_quat_from_axis_view(view, view_axis_roll, quat);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ED_view3d_quat_to_axis_view(const float quat[4],
|
||||
const float epsilon,
|
||||
char *r_view,
|
||||
|
@ -1538,6 +1602,12 @@ bool ED_view3d_lock(RegionView3D *rv3d)
|
|||
return ED_view3d_quat_from_axis_view(rv3d->view, rv3d->view_axis_roll, rv3d->viewquat);
|
||||
}
|
||||
|
||||
bool ED_view3d_lock_ucs(TransformOrientation *ts, RegionView3D *rv3d)
|
||||
{
|
||||
ED_view3d_quat_from_axis_view_ucs(ts, rv3d->view, rv3d->view_axis_roll, rv3d->viewquat);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -713,6 +713,8 @@ static bool transform_modal_item_poll(const wmOperator *op, int value)
|
|||
}
|
||||
case TFM_MODAL_PASSTHROUGH_NAVIGATE:
|
||||
return t->vod != nullptr;
|
||||
case TFM_MODAL_NO_MODAL_TRANSFORM:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -768,6 +770,7 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
|
|||
{TFM_MODAL_AUTOCONSTRAINTPLANE, "AUTOCONSTRAINPLANE", 0, "Automatic Constraint Plane", ""},
|
||||
{TFM_MODAL_PRECISION, "PRECISION", 0, "Precision Mode", ""},
|
||||
{TFM_MODAL_PASSTHROUGH_NAVIGATE, "PASSTHROUGH_NAVIGATE", 0, "Navigate", ""},
|
||||
{TFM_MODAL_NO_MODAL_TRANSFORM, "NO_MODAL_TRANSFORM", 0, "Allow movements around the scene",""},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
|
@ -967,12 +970,74 @@ static bool transform_event_modal_constraint(TransInfo *t, short modal_type)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void switchTransformNoModal(TransInfo *t, const wmEvent *event) {
|
||||
t->flag ^= T_TRANSFORM_NO_MODAL;
|
||||
|
||||
{
|
||||
// Enable/Disable modal events allowing to be processed as non-modal events
|
||||
wmKeyMapItem *kmi;
|
||||
for (kmi =(wmKeyMapItem*) t->keymap->items.first; kmi; kmi = kmi->next)
|
||||
{
|
||||
if (ELEM(kmi->type, LEFTMOUSE, RIGHTMOUSE, MIDDLEMOUSE, WHEELDOWNMOUSE, WHEELUPMOUSE)) {
|
||||
if ((t->flag & T_TRANSFORM_NO_MODAL) == 0) {
|
||||
kmi->flag &= ~KMI_INACTIVE;
|
||||
}
|
||||
else {
|
||||
kmi->flag |= KMI_INACTIVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((t->flag & T_TRANSFORM_NO_MODAL) == 0) {
|
||||
// Transform Restart
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int transformEvent(TransInfo *t, const wmEvent *event)
|
||||
{
|
||||
bool handled = false;
|
||||
bool is_navigating = t->vod ? ((RegionView3D *)t->region->regiondata)->rflag & RV3D_NAVIGATING :
|
||||
false;
|
||||
|
||||
if (t->flag & T_TRANSFORM_NO_MODAL) {
|
||||
if (ELEM(event->val, KM_PRESS, KM_RELEASE) &&
|
||||
ELEM(event->type, LEFTMOUSE, RIGHTMOUSE, MIDDLEMOUSE))
|
||||
{
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
else if (ELEM(event->type,
|
||||
BUTTON4MOUSE,
|
||||
BUTTON5MOUSE,
|
||||
BUTTON6MOUSE,
|
||||
BUTTON7MOUSE,
|
||||
MOUSEPAN,
|
||||
MOUSEZOOM,
|
||||
MOUSEROTATE,
|
||||
WHEELINMOUSE,
|
||||
WHEELOUTMOUSE,
|
||||
WHEELUPMOUSE,
|
||||
WHEELDOWNMOUSE))
|
||||
{
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
else if (event->type == EVT_MODAL_MAP) {
|
||||
switch (event->val) {
|
||||
case TFM_MODAL_CANCEL:
|
||||
t->state = TRANS_CANCEL;
|
||||
break;
|
||||
case TFM_MODAL_CONFIRM:
|
||||
t->state = TRANS_CONFIRM;
|
||||
break;
|
||||
case TFM_MODAL_NO_MODAL_TRANSFORM:
|
||||
t->redraw |= TREDRAW_HARD; // Redraw the Header
|
||||
switchTransformNoModal(t, event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Handle modal numinput events first, if already activated. */
|
||||
if (!is_navigating && ((event->val == KM_PRESS) || (event->type == EVT_MODAL_MAP)) &&
|
||||
hasNumInput(&t->num) && handleNumInput(t->context, &(t->num), event))
|
||||
|
@ -1013,6 +1078,11 @@ int transformEvent(TransInfo *t, const wmEvent *event)
|
|||
handled = true;
|
||||
}
|
||||
break;
|
||||
case TFM_MODAL_NO_MODAL_TRANSFORM:
|
||||
switchTransformNoModal(t, event);
|
||||
handled = true;
|
||||
t->redraw |= TREDRAW_HARD;
|
||||
break;
|
||||
case TFM_MODAL_TRANSLATE:
|
||||
case TFM_MODAL_ROTATE:
|
||||
case TFM_MODAL_RESIZE:
|
||||
|
@ -1311,6 +1381,10 @@ int transformEvent(TransInfo *t, const wmEvent *event)
|
|||
/* Else do non-mapped events. */
|
||||
else if (event->val == KM_PRESS) {
|
||||
switch (event->type) {
|
||||
case EVT_MKEY :
|
||||
t->flag |= T_TRANSFORM_MULTIPLE;
|
||||
handled = true;
|
||||
break;
|
||||
case EVT_CKEY:
|
||||
if (event->flag & WM_EVENT_IS_REPEAT) {
|
||||
break;
|
||||
|
@ -1838,6 +1912,12 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
|
|||
RNA_property_boolean_set(
|
||||
op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT_SLIDE) != 0);
|
||||
}
|
||||
|
||||
if ((prop = RNA_struct_find_property(op->ptr, "transform_multiple"))) {
|
||||
RNA_boolean_set(op->ptr, "transform_multiple", (t->flag & T_TRANSFORM_MULTIPLE) != 0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void initSnapSpatial(TransInfo *t, float r_snap[3], float *r_snap_precision)
|
||||
|
@ -1934,6 +2014,12 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
|
|||
|
||||
initTransInfo(C, t, op, event);
|
||||
|
||||
if (prop = RNA_struct_find_property(op->ptr, "transform_multiple")) {
|
||||
if (RNA_boolean_get(op->ptr, "transform_multiple")) {
|
||||
t->flag |= T_TRANSFORM_MULTIPLE;
|
||||
}
|
||||
}
|
||||
|
||||
if (t->spacetype == SPACE_VIEW3D) {
|
||||
t->draw_handle_view = ED_region_draw_cb_activate(
|
||||
t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
|
||||
|
@ -2055,6 +2141,12 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
|
|||
calculatePropRatio(t);
|
||||
calculateCenter(t);
|
||||
|
||||
if (t->spacetype == SPACE_VIEW3D) {
|
||||
float p[3] = {0, 0, 0};
|
||||
ED_view3d_win_to_3d_int((View3D*) t->view, t->region, p, event->mval, t->iloc);
|
||||
}
|
||||
|
||||
|
||||
if (event) {
|
||||
/* Initialize accurate transform to settings requested by keymap. */
|
||||
bool use_accurate = false;
|
||||
|
@ -2165,7 +2257,7 @@ void transformApply(bContext *C, TransInfo *t)
|
|||
|
||||
int transformEnd(bContext *C, TransInfo *t)
|
||||
{
|
||||
int exit_code = OPERATOR_RUNNING_MODAL;
|
||||
int exit_code = (t->flag & T_TRANSFORM_NO_MODAL) ? OPERATOR_HANDLED : OPERATOR_RUNNING_MODAL;
|
||||
|
||||
t->context = C;
|
||||
|
||||
|
@ -2185,6 +2277,10 @@ int transformEnd(bContext *C, TransInfo *t)
|
|||
exit_code = OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
if (t->state == TRANS_CONFIRM && (t->flag & T_TRANSFORM_MULTIPLE)) {
|
||||
exit_code |= OPERATOR_REPEAT;
|
||||
}
|
||||
|
||||
/* aftertrans does insert keyframes, and clears base flags; doesn't read transdata */
|
||||
special_aftertrans_update(C, t);
|
||||
|
||||
|
|
|
@ -150,6 +150,12 @@ enum eTFlag {
|
|||
|
||||
/** Special flag for when the transform code is called after keys have been duplicated. */
|
||||
T_DUPLICATED_KEYFRAMES = 1 << 26,
|
||||
|
||||
/* Used on MB-0001-operator-repeat */
|
||||
T_TRANSFORM_MULTIPLE = 1 << 27,
|
||||
|
||||
/* Used on MB-0006-allow-no-modal-transform*/
|
||||
T_TRANSFORM_NO_MODAL = 1 << 28,
|
||||
};
|
||||
ENUM_OPERATORS(eTFlag, T_DUPLICATED_KEYFRAMES);
|
||||
|
||||
|
@ -285,6 +291,7 @@ enum {
|
|||
TFM_MODAL_EDIT_SNAP_SOURCE_OFF = 35,
|
||||
|
||||
TFM_MODAL_PASSTHROUGH_NAVIGATE = 36,
|
||||
TFM_MODAL_NO_MODAL_TRANSFORM = 37,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
@ -561,6 +568,8 @@ struct TransInfo {
|
|||
/** Mouse side of the current frame, 'L', 'R' or 'B' */
|
||||
char frame_side;
|
||||
|
||||
float iloc[3]; /* Initial location */
|
||||
|
||||
/** copy from #RegionView3D, prevents feedback. */
|
||||
float viewmat[4][4];
|
||||
/** and to make sure we don't have to. */
|
||||
|
|
|
@ -258,6 +258,8 @@ static int create_orientation_exec(bContext *C, wmOperator *op)
|
|||
const bool use_view = RNA_boolean_get(op->ptr, "use_view");
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const bool set_ucs = RNA_boolean_get(op->ptr, "set_ucs");
|
||||
TransformOrientation *ts;
|
||||
|
||||
RNA_string_get(op->ptr, "name", name);
|
||||
|
||||
|
@ -268,7 +270,9 @@ static int create_orientation_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (!BIF_createTransformOrientation(C, op->reports, name, use_view, use, overwrite)) {
|
||||
|
||||
ts = BIF_createTransformOrientation(C, op->reports, name, use_view, use, overwrite);
|
||||
if (ts == nullptr) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Unable to create orientation");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
@ -279,6 +283,16 @@ static int create_orientation_exec(bContext *C, wmOperator *op)
|
|||
WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
|
||||
}
|
||||
|
||||
if (set_ucs) {
|
||||
if (scene) {
|
||||
// 0 = Global
|
||||
v3d->ucs = BLI_findindex(&scene->transform_spaces, ts) + 1;
|
||||
}
|
||||
else {
|
||||
BKE_report(op->reports, RPT_ERROR, "Cannot set ucs!");
|
||||
}
|
||||
}
|
||||
|
||||
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, nullptr);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
|
@ -305,6 +319,8 @@ static void TRANSFORM_OT_create_orientation(wmOperatorType *ot)
|
|||
"Use View",
|
||||
"Use the current view instead of the active object to create the new orientation");
|
||||
|
||||
RNA_def_boolean(ot->srna, "set_ucs", false, "Set as UCS", "Select as ucs after its creation");
|
||||
|
||||
WM_operatortype_props_advanced_begin(ot);
|
||||
|
||||
RNA_def_boolean(
|
||||
|
@ -464,7 +480,7 @@ static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
|
||||
exit_code |= transformEnd(C, t);
|
||||
|
||||
if ((exit_code & OPERATOR_RUNNING_MODAL) == 0) {
|
||||
if ((exit_code & (OPERATOR_CANCELLED | OPERATOR_FINISHED))) {
|
||||
transformops_exit(C, op);
|
||||
exit_code &= ~OPERATOR_PASS_THROUGH; /* Preventively remove pass-through. */
|
||||
}
|
||||
|
@ -817,6 +833,8 @@ void Transform_Properties(wmOperatorType *ot, int flags)
|
|||
"Forces the use of Auto Merge and Split");
|
||||
RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
}
|
||||
|
||||
RNA_def_boolean(ot->srna, "transform_multiple", 0, "Multiple", "Apply Multiple times");
|
||||
}
|
||||
|
||||
static void TRANSFORM_OT_translate(wmOperatorType *ot)
|
||||
|
|
|
@ -97,6 +97,7 @@ static TransformOrientation *createViewSpace(bContext *C,
|
|||
{
|
||||
RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
||||
float mat[3][3];
|
||||
float origin[3] = {0};
|
||||
|
||||
if (!rv3d) {
|
||||
return nullptr;
|
||||
|
@ -116,7 +117,7 @@ static TransformOrientation *createViewSpace(bContext *C,
|
|||
}
|
||||
}
|
||||
|
||||
return addMatrixSpace(C, mat, name, overwrite);
|
||||
return addMatrixSpace(C, mat, origin, name, overwrite);
|
||||
}
|
||||
|
||||
static TransformOrientation *createObjectSpace(bContext *C,
|
||||
|
@ -127,6 +128,7 @@ static TransformOrientation *createObjectSpace(bContext *C,
|
|||
Base *base = CTX_data_active_base(C);
|
||||
Object *ob;
|
||||
float mat[3][3];
|
||||
float origin[3];
|
||||
|
||||
if (base == nullptr) {
|
||||
return nullptr;
|
||||
|
@ -135,6 +137,7 @@ static TransformOrientation *createObjectSpace(bContext *C,
|
|||
ob = base->object;
|
||||
|
||||
copy_m3_m4(mat, ob->object_to_world);
|
||||
copy_v3_v3(origin, ob->loc);
|
||||
normalize_m3(mat);
|
||||
|
||||
/* use object name if no name is given */
|
||||
|
@ -142,7 +145,7 @@ static TransformOrientation *createObjectSpace(bContext *C,
|
|||
name = ob->id.name + 2;
|
||||
}
|
||||
|
||||
return addMatrixSpace(C, mat, name, overwrite);
|
||||
return addMatrixSpace(C, mat, origin, name, overwrite);
|
||||
}
|
||||
|
||||
static TransformOrientation *createBoneSpace(bContext *C,
|
||||
|
@ -152,8 +155,9 @@ static TransformOrientation *createBoneSpace(bContext *C,
|
|||
{
|
||||
float mat[3][3];
|
||||
float normal[3], plane[3];
|
||||
float origin[3];
|
||||
|
||||
getTransformOrientation(C, normal, plane);
|
||||
getTransformOrientation(C, normal, plane, origin);
|
||||
|
||||
if (createSpaceNormalTangent(mat, normal, plane) == 0) {
|
||||
BKE_reports_prepend(reports, "Cannot use zero-length bone");
|
||||
|
@ -164,7 +168,7 @@ static TransformOrientation *createBoneSpace(bContext *C,
|
|||
name = "Bone";
|
||||
}
|
||||
|
||||
return addMatrixSpace(C, mat, name, overwrite);
|
||||
return addMatrixSpace(C, mat, origin, name, overwrite);
|
||||
}
|
||||
|
||||
static TransformOrientation *createCurveSpace(bContext *C,
|
||||
|
@ -174,8 +178,9 @@ static TransformOrientation *createCurveSpace(bContext *C,
|
|||
{
|
||||
float mat[3][3];
|
||||
float normal[3], plane[3];
|
||||
float origin[3];
|
||||
|
||||
getTransformOrientation(C, normal, plane);
|
||||
getTransformOrientation(C, normal, plane, origin);
|
||||
|
||||
if (createSpaceNormalTangent(mat, normal, plane) == 0) {
|
||||
BKE_reports_prepend(reports, "Cannot use zero-length curve");
|
||||
|
@ -186,7 +191,7 @@ static TransformOrientation *createCurveSpace(bContext *C,
|
|||
name = "Curve";
|
||||
}
|
||||
|
||||
return addMatrixSpace(C, mat, name, overwrite);
|
||||
return addMatrixSpace(C, mat, origin, name, overwrite);
|
||||
}
|
||||
|
||||
static TransformOrientation *createMeshSpace(bContext *C,
|
||||
|
@ -197,8 +202,9 @@ static TransformOrientation *createMeshSpace(bContext *C,
|
|||
float mat[3][3];
|
||||
float normal[3], plane[3];
|
||||
int type;
|
||||
float origin[3];
|
||||
|
||||
type = getTransformOrientation(C, normal, plane);
|
||||
type = getTransformOrientation(C, normal, plane, origin);
|
||||
|
||||
switch (type) {
|
||||
case ORIENTATION_VERT:
|
||||
|
@ -235,7 +241,7 @@ static TransformOrientation *createMeshSpace(bContext *C,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return addMatrixSpace(C, mat, name, overwrite);
|
||||
return addMatrixSpace(C, mat, origin, name, overwrite);
|
||||
}
|
||||
|
||||
static bool test_rotmode_euler(short rotmode)
|
||||
|
@ -431,7 +437,7 @@ bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const floa
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BIF_createTransformOrientation(bContext *C,
|
||||
TransformOrientation* BIF_createTransformOrientation(bContext *C,
|
||||
ReportList *reports,
|
||||
const char *name,
|
||||
const bool use_view,
|
||||
|
@ -468,11 +474,12 @@ bool BIF_createTransformOrientation(bContext *C,
|
|||
if (activate && ts != nullptr) {
|
||||
BIF_selectTransformOrientation(C, ts);
|
||||
}
|
||||
return (ts != nullptr);
|
||||
return (ts);
|
||||
}
|
||||
|
||||
TransformOrientation *addMatrixSpace(bContext *C,
|
||||
float mat[3][3],
|
||||
float origin[3],
|
||||
const char *name,
|
||||
const bool overwrite)
|
||||
{
|
||||
|
@ -500,6 +507,7 @@ TransformOrientation *addMatrixSpace(bContext *C,
|
|||
|
||||
/* copy matrix into transform space */
|
||||
copy_m3_m3(ts->mat, mat);
|
||||
copy_v3_v3(ts->origin, origin);
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
@ -898,6 +906,7 @@ int getTransformOrientation_ex(const Scene *scene,
|
|||
Object *obedit,
|
||||
float normal[3],
|
||||
float plane[3],
|
||||
float origin[3],
|
||||
const short around)
|
||||
{
|
||||
int result = ORIENTATION_NONE;
|
||||
|
@ -905,6 +914,7 @@ int getTransformOrientation_ex(const Scene *scene,
|
|||
|
||||
zero_v3(normal);
|
||||
zero_v3(plane);
|
||||
zero_v3(origin);
|
||||
|
||||
if (obedit) {
|
||||
float imat[3][3], mat[3][3];
|
||||
|
@ -1129,6 +1139,24 @@ int getTransformOrientation_ex(const Scene *scene,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (em->bm->totvertsel > 1) {
|
||||
BMIter iter;
|
||||
BMVert *v;
|
||||
int i = 0;
|
||||
|
||||
zero_v3(origin);
|
||||
|
||||
BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
|
||||
if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
|
||||
add_v3_v3(origin, v->co);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
mul_v3_fl(origin, 1.0f / i);
|
||||
mul_m4_v3(ob->object_to_world, origin);
|
||||
}
|
||||
|
||||
/* not needed but this matches 2.68 and older behavior */
|
||||
negate_v3(plane);
|
||||
|
||||
|
@ -1425,7 +1453,7 @@ int getTransformOrientation_ex(const Scene *scene,
|
|||
return result;
|
||||
}
|
||||
|
||||
int getTransformOrientation(const bContext *C, float normal[3], float plane[3])
|
||||
int getTransformOrientation(const bContext *C, float normal[3], float plane[3], float origin[3])
|
||||
{
|
||||
Object *obact = CTX_data_active_object(C);
|
||||
Object *obedit = CTX_data_edit_object(C);
|
||||
|
@ -1437,7 +1465,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3])
|
|||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
|
||||
return getTransformOrientation_ex(scene, view_layer, v3d, obact, obedit, normal, plane, around);
|
||||
return getTransformOrientation_ex(scene, view_layer, v3d, obact, obedit, normal, plane, origin, around);
|
||||
}
|
||||
|
||||
void ED_getTransformOrientationMatrix(const Scene *scene,
|
||||
|
@ -1450,10 +1478,11 @@ void ED_getTransformOrientationMatrix(const Scene *scene,
|
|||
{
|
||||
float normal[3] = {0.0, 0.0, 0.0};
|
||||
float plane[3] = {0.0, 0.0, 0.0};
|
||||
float origin[3] = {0.0, 0.0, 0.0};
|
||||
|
||||
int type;
|
||||
|
||||
type = getTransformOrientation_ex(scene, view_layer, v3d, ob, obedit, normal, plane, around);
|
||||
type = getTransformOrientation_ex(scene, view_layer, v3d, ob, obedit, normal, plane, origin, around);
|
||||
|
||||
/* Fallback, when the plane can't be calculated. */
|
||||
if (ORIENTATION_USE_PLANE(type) && is_zero_v3(plane)) {
|
||||
|
|
|
@ -47,6 +47,7 @@ bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const floa
|
|||
|
||||
TransformOrientation *addMatrixSpace(bContext *C,
|
||||
float mat[3][3],
|
||||
float origin[3],
|
||||
const char *name,
|
||||
bool overwrite);
|
||||
void applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3], char r_name[64]);
|
||||
|
@ -67,5 +68,6 @@ int getTransformOrientation_ex(const Scene *scene,
|
|||
Object *obedit,
|
||||
float normal[3],
|
||||
float plane[3],
|
||||
float origin[3],
|
||||
short around);
|
||||
int getTransformOrientation(const bContext *C, float normal[3], float plane[3]);
|
||||
int getTransformOrientation(const bContext *C, float normal[3], float plane[3], float origin [3]);
|
||||
|
|
|
@ -321,7 +321,7 @@ typedef struct TransformOrientation {
|
|||
/** MAX_NAME. */
|
||||
char name[64];
|
||||
float mat[3][3];
|
||||
char _pad[4];
|
||||
float origin[3];
|
||||
} TransformOrientation;
|
||||
|
||||
/** Some preview UI data need to be saved in file. */
|
||||
|
|
|
@ -39,6 +39,8 @@ typedef struct RegionView3D {
|
|||
/** Offset/scale for camera GLSL texture-coordinates. */
|
||||
float viewcamtexcofac[4];
|
||||
|
||||
float ucsmat[4][4];
|
||||
|
||||
/** viewmat/persmat multiplied with object matrix, while drawing and selection. */
|
||||
float viewmatob[4][4];
|
||||
float persmatob[4][4];
|
||||
|
@ -358,6 +360,10 @@ typedef struct View3D {
|
|||
|
||||
/** Runtime evaluation data (keep last). */
|
||||
View3D_Runtime runtime;
|
||||
|
||||
int ucs;
|
||||
char _pad5[4];
|
||||
|
||||
} View3D;
|
||||
|
||||
/** #View3D::stereo3d_flag */
|
||||
|
|
|
@ -213,6 +213,8 @@ typedef struct wmWindowManager {
|
|||
|
||||
struct wmMsgBus *message_bus;
|
||||
|
||||
struct wmOpHandlers *op_handlers;
|
||||
|
||||
// #ifdef WITH_XR_OPENXR
|
||||
wmXrData xr;
|
||||
// #endif
|
||||
|
@ -646,10 +648,12 @@ enum {
|
|||
* \note this isn't great design (using operators to trigger UI) avoid where possible.
|
||||
*/
|
||||
OPERATOR_INTERFACE = (1 << 5),
|
||||
/* Create a new operator based on current */
|
||||
OPERATOR_REPEAT = (1 << 6),
|
||||
};
|
||||
#define OPERATOR_FLAGS_ALL \
|
||||
(OPERATOR_RUNNING_MODAL | OPERATOR_CANCELLED | OPERATOR_FINISHED | OPERATOR_PASS_THROUGH | \
|
||||
OPERATOR_HANDLED | OPERATOR_INTERFACE | 0)
|
||||
OPERATOR_HANDLED | OPERATOR_INTERFACE | OPERATOR_REPEAT | 0)
|
||||
|
||||
/* sanity checks for debug mode only */
|
||||
#define OPERATOR_RETVAL_CHECK(ret) \
|
||||
|
|
|
@ -2937,6 +2937,12 @@ static void rna_def_transform_orientation(BlenderRNA *brna)
|
|||
RNA_def_struct_name_property(srna, prop);
|
||||
RNA_def_property_ui_text(prop, "Name", "Name of the custom transform orientation");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TRANSFORM, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "origin", PROP_FLOAT, PROP_XYZ);
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_ui_text(prop, "Origin", "Origin of the custom transform orientation");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
|
||||
}
|
||||
|
||||
static void rna_def_transform_orientation_slot(BlenderRNA *brna)
|
||||
|
|
|
@ -536,6 +536,10 @@ static const EnumPropertyItem rna_enum_curve_display_handle_items[] = {
|
|||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
const EnumPropertyItem ucs_items[] = {
|
||||
{0, "global", 0, "Global", "Use global as system coordinates"}, {0, NULL, 0, NULL, NULL}};
|
||||
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
# include "AS_asset_representation.hh"
|
||||
|
@ -1549,6 +1553,44 @@ static void rna_SpaceView3D_use_local_collections_update(bContext *C, PointerRNA
|
|||
}
|
||||
}
|
||||
|
||||
const EnumPropertyItem *rna_ucs_itemf(bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
bool *r_free)
|
||||
{
|
||||
Scene *scene = NULL;
|
||||
ListBase *transform_spaces;
|
||||
TransformOrientation *ts = NULL;
|
||||
EnumPropertyItem tmp = {0, "", 0, "", ""};
|
||||
EnumPropertyItem *item = NULL;
|
||||
int i = 1, totitem = 0;
|
||||
|
||||
RNA_enum_items_add(&item, &totitem, ucs_items);
|
||||
|
||||
scene = CTX_data_scene(C);
|
||||
|
||||
if (scene) {
|
||||
transform_spaces = &scene->transform_spaces;
|
||||
ts = (TransformOrientation*) transform_spaces->first;
|
||||
}
|
||||
|
||||
if (ts) {
|
||||
RNA_enum_item_add_separator(&item, &totitem);
|
||||
|
||||
for (; ts; ts = ts->next) {
|
||||
tmp.identifier = ts->name;
|
||||
tmp.name = ts->name;
|
||||
tmp.value = i++;
|
||||
RNA_enum_item_add(&item, &totitem, &tmp);
|
||||
}
|
||||
}
|
||||
|
||||
RNA_enum_item_end(&item, &totitem);
|
||||
*r_free = true;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
static const EnumPropertyItem *rna_SpaceView3D_stereo3d_camera_itemf(bContext *C,
|
||||
PointerRNA * /*ptr*/,
|
||||
PropertyRNA * /*prop*/,
|
||||
|
@ -5285,6 +5327,14 @@ static void rna_def_space_view3d(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(
|
||||
prop, "Overlay Settings", "Settings for display of overlays in the 3D viewport");
|
||||
|
||||
|
||||
prop = RNA_def_property(srna, "ucs", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "ucs");
|
||||
RNA_def_property_enum_items(prop, ucs_items);
|
||||
RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_ucs_itemf");
|
||||
RNA_def_property_ui_text(prop, "UCS", "User Coordinate System");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
|
||||
rna_def_space_view3d_shading(brna);
|
||||
rna_def_space_view3d_overlay(brna);
|
||||
|
||||
|
|
|
@ -990,7 +990,7 @@ static StructRNA *rna_Menu_register(Main *bmain,
|
|||
const char *error_prefix = "Registering menu class:";
|
||||
MenuType *mt, dummy_mt = {nullptr};
|
||||
Menu dummy_menu = {nullptr};
|
||||
bool have_function[2];
|
||||
bool have_function[4];
|
||||
size_t over_alloc = 0; /* Warning, if this becomes a mess, we better do another allocation. */
|
||||
size_t description_size = 0;
|
||||
char _menu_descr[RNA_DYN_DESCR_MAX];
|
||||
|
@ -2194,6 +2194,19 @@ static void rna_def_menu(BlenderRNA *brna)
|
|||
parm = RNA_def_pointer(func, "context", "Context", "", "");
|
||||
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
|
||||
|
||||
/* draw referenced */
|
||||
func = RNA_def_function(srna, "draw_referenced_pre", nullptr);
|
||||
RNA_def_function_ui_description(func, "Draw UI elements into the menu UI layout before reference");
|
||||
RNA_def_function_flag(func, FUNC_REGISTER);
|
||||
parm = RNA_def_string(func, "label", nullptr, 0, "", "draw reference menu label");
|
||||
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
|
||||
|
||||
func = RNA_def_function(srna, "draw_referenced_post", nullptr);
|
||||
RNA_def_function_ui_description(func, "Draw UI elements into the menu UI layout after reference");
|
||||
RNA_def_function_flag(func, FUNC_REGISTER);
|
||||
parm = RNA_def_string(func, "label", nullptr, 0, "", "draw reference menu label");
|
||||
RNA_def_parameter_flags(parm,PropertyFlag(0), PARM_REQUIRED);
|
||||
|
||||
RNA_define_verify_sdna(false); /* not in sdna */
|
||||
|
||||
prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BLI_string.h"
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "RNA_define.hh"
|
||||
|
@ -326,6 +327,63 @@ static void rna_uiItemPointerR(uiLayout *layout,
|
|||
layout, ptr, prop, searchptr, searchprop, name, icon, results_are_suggestions);
|
||||
}
|
||||
|
||||
static void rna_call_draw_referenced(uiLayout *layout, const char *name, FunctionRNA *func)
|
||||
{
|
||||
if (*name == '\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
char *label = (char*) MEM_callocN(255, __func__); // Error defined as not dinamic []
|
||||
BLI_strncpy(label, name, 255);
|
||||
|
||||
|
||||
// Remove ... added in some menus, like Open...
|
||||
size_t label_len = BLI_strnlen(name, 255);
|
||||
if (label_len > 4) {
|
||||
char *end = label + label_len;
|
||||
if (*(end - 1) == '.' && *(end - 2) == '.' && *(end - 3) == '.') {
|
||||
*(end - 3) = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ExtensionRNA *ext_rna = uiLayoutGetParentRnaExt(layout);
|
||||
if (ext_rna) {
|
||||
PointerRNA ptr = RNA_pointer_create(NULL, ext_rna->srna, uiLayoutGetParentObject(layout));
|
||||
ParameterList list;
|
||||
RNA_parameter_list_create(&list, &ptr, func);
|
||||
// Do not know how the get the context, is lost on python RNA call.
|
||||
// RNA_parameter_set_lookup(&list, "context", &C);
|
||||
// rna_ext->call((bContext *)C, &ptr, func, &list);
|
||||
RNA_parameter_set_lookup(&list, "label", &label);
|
||||
ext_rna->call(NULL, &ptr, func, &list);
|
||||
RNA_parameter_list_free(&list);
|
||||
}
|
||||
|
||||
MEM_freeN(label);
|
||||
}
|
||||
|
||||
static void rna_call_draw_referenced_pre(uiLayout *layout, const char *name)
|
||||
{
|
||||
|
||||
extern FunctionRNA rna_Menu_draw_referenced_pre_func;
|
||||
FunctionRNA *func;
|
||||
func = &rna_Menu_draw_referenced_pre_func; /* RNA_struct_find_function(&ptr,
|
||||
"draw_referenced_pre") */
|
||||
rna_call_draw_referenced(layout, name, func);
|
||||
}
|
||||
|
||||
static void rna_call_draw_referenced_post(uiLayout *layout, const char *name)
|
||||
{
|
||||
extern FunctionRNA rna_Menu_draw_referenced_post_func;
|
||||
|
||||
FunctionRNA *func;
|
||||
func = &rna_Menu_draw_referenced_post_func; /* RNA_struct_find_function(&ptr, "draw_referenced_post") */
|
||||
|
||||
rna_call_draw_referenced(layout, name, func);
|
||||
}
|
||||
|
||||
|
||||
static PointerRNA rna_uiItemO(uiLayout *layout,
|
||||
const char *opname,
|
||||
const char *name,
|
||||
|
@ -337,6 +395,11 @@ static PointerRNA rna_uiItemO(uiLayout *layout,
|
|||
int icon_value)
|
||||
{
|
||||
wmOperatorType *ot;
|
||||
char original_name[255] = {0};
|
||||
|
||||
if (name) {
|
||||
BLI_strncpy(original_name, name, 255);
|
||||
}
|
||||
|
||||
ot = WM_operatortype_find(opname, false); /* print error next */
|
||||
if (!ot || !ot->srna) {
|
||||
|
@ -344,6 +407,13 @@ static PointerRNA rna_uiItemO(uiLayout *layout,
|
|||
return PointerRNA_NULL;
|
||||
}
|
||||
|
||||
if (name && *name != '\0') {
|
||||
BLI_strncpy(original_name, name, 255);
|
||||
}
|
||||
else {
|
||||
BLI_strncpy(original_name, ot->name, 255);
|
||||
}
|
||||
|
||||
/* Get translated name (label). */
|
||||
name = rna_translate_ui_text(name, text_ctxt, ot->srna, nullptr, translate);
|
||||
|
||||
|
@ -358,10 +428,15 @@ static PointerRNA rna_uiItemO(uiLayout *layout,
|
|||
flag |= UI_ITEM_O_DEPRESS;
|
||||
}
|
||||
|
||||
rna_call_draw_referenced_pre(layout, original_name);
|
||||
|
||||
PointerRNA opptr;
|
||||
uiItemFullO_ptr(
|
||||
layout, ot, name, icon, nullptr, uiLayoutGetOperatorContext(layout), flag, &opptr);
|
||||
return opptr;
|
||||
|
||||
rna_call_draw_referenced_post(layout, original_name);
|
||||
|
||||
return opptr;
|
||||
}
|
||||
|
||||
static PointerRNA rna_uiItemOMenuHold(uiLayout *layout,
|
||||
|
@ -405,8 +480,17 @@ static void rna_uiItemsEnumO(uiLayout *layout,
|
|||
const char *propname,
|
||||
const bool icon_only)
|
||||
{
|
||||
|
||||
wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
|
||||
|
||||
/** Calling only once per operator **/
|
||||
rna_call_draw_referenced_pre(layout, ot->name);
|
||||
|
||||
eUI_Item_Flag flag = icon_only ? UI_ITEM_R_ICON_ONLY : UI_ITEM_NONE;
|
||||
uiItemsFullEnumO(layout, opname, propname, nullptr, uiLayoutGetOperatorContext(layout), flag);
|
||||
|
||||
rna_call_draw_referenced_post(layout, ot->name);
|
||||
|
||||
}
|
||||
|
||||
static PointerRNA rna_uiItemMenuEnumO(uiLayout *layout,
|
||||
|
@ -420,6 +504,12 @@ static PointerRNA rna_uiItemMenuEnumO(uiLayout *layout,
|
|||
{
|
||||
wmOperatorType *ot = WM_operatortype_find(opname, false); /* print error next */
|
||||
|
||||
char original_name[255] = {0};
|
||||
|
||||
if (name) {
|
||||
BLI_strncpy(original_name, name, 255);
|
||||
}
|
||||
|
||||
if (!ot || !ot->srna) {
|
||||
RNA_warning("%s '%s'", ot ? "unknown operator" : "operator missing srna", opname);
|
||||
return PointerRNA_NULL;
|
||||
|
@ -428,8 +518,13 @@ static PointerRNA rna_uiItemMenuEnumO(uiLayout *layout,
|
|||
/* Get translated name (label). */
|
||||
name = rna_translate_ui_text(name, text_ctxt, ot->srna, nullptr, translate);
|
||||
|
||||
rna_call_draw_referenced_pre(layout, original_name);
|
||||
|
||||
PointerRNA opptr;
|
||||
uiItemMenuEnumFullO_ptr(layout, C, ot, propname, name, icon, &opptr);
|
||||
|
||||
rna_call_draw_referenced_post(layout, original_name);
|
||||
|
||||
return opptr;
|
||||
}
|
||||
|
||||
|
@ -465,12 +560,33 @@ static void rna_uiItemM(uiLayout *layout,
|
|||
icon = icon_value;
|
||||
}
|
||||
|
||||
MenuType *mt = WM_menutype_find(menuname, false);
|
||||
if (mt == NULL) {
|
||||
RNA_warning("not found %s", menuname);
|
||||
return;
|
||||
}
|
||||
|
||||
rna_call_draw_referenced_pre(layout, mt->label);
|
||||
|
||||
uiItemM(layout, menuname, name, icon);
|
||||
|
||||
rna_call_draw_referenced_post(layout, mt->label);
|
||||
}
|
||||
|
||||
static void rna_uiItemM_contents(uiLayout *layout, const char *menuname)
|
||||
{
|
||||
|
||||
MenuType *mt = WM_menutype_find(menuname, false);
|
||||
if (mt == NULL) {
|
||||
RNA_warning("not found %s", menuname);
|
||||
return;
|
||||
}
|
||||
|
||||
rna_call_draw_referenced_pre(layout, mt->label);
|
||||
|
||||
uiItemMContents(layout, menuname);
|
||||
|
||||
rna_call_draw_referenced_post(layout, mt->label);
|
||||
}
|
||||
|
||||
static void rna_uiItemPopoverPanel(uiLayout *layout,
|
||||
|
@ -1751,6 +1867,21 @@ void RNA_api_ui_layout(StructRNA *srna)
|
|||
1.0f,
|
||||
100.0f);
|
||||
|
||||
|
||||
func = RNA_def_function(srna, "template_image_ui", "uiTemplateImageUI");
|
||||
RNA_def_function_ui_description(func, "A image on UI");
|
||||
parm = RNA_def_int(func, "image_value", 0, 0, INT_MAX, "image to display", "", 0, INT_MAX);
|
||||
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
|
||||
RNA_def_float(func,
|
||||
"scale",
|
||||
1.0f,
|
||||
1.0f,
|
||||
100.0f,
|
||||
"Scale",
|
||||
"Scale the icon size (by the button size)",
|
||||
1.0f,
|
||||
100.0f);
|
||||
|
||||
func = RNA_def_function(srna, "template_icon_view", "uiTemplateIconView");
|
||||
RNA_def_function_ui_description(func, "Enum. Large widget showing Icon previews");
|
||||
api_ui_item_rna_common(func);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
/* Empty file */
|
|
@ -133,6 +133,8 @@ bool BPY_string_is_keyword(const char *str);
|
|||
void BPY_callback_screen_free(struct ARegionType *art);
|
||||
void BPY_callback_wm_free(struct wmWindowManager *wm);
|
||||
|
||||
void* BPY_utils_images_get(int image_id);
|
||||
|
||||
/* I18n for addons */
|
||||
#ifdef WITH_INTERNATIONAL
|
||||
const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid);
|
||||
|
|
|
@ -15,6 +15,7 @@ set(INC
|
|||
../../windowmanager
|
||||
../../../../intern/mantaflow/extern
|
||||
../../../../intern/opencolorio
|
||||
../../tornavis
|
||||
# RNA_prototypes.h
|
||||
${CMAKE_BINARY_DIR}/source/blender/makesrna
|
||||
)
|
||||
|
@ -39,6 +40,7 @@ set(SRC
|
|||
bpy_app_timers.cc
|
||||
bpy_app_translations.cc
|
||||
bpy_app_usd.cc
|
||||
bpy_app_tornavis.cc
|
||||
bpy_capi_utils.cc
|
||||
bpy_driver.cc
|
||||
bpy_gizmo_wrap.cc
|
||||
|
@ -68,6 +70,7 @@ set(SRC
|
|||
bpy_rna_ui.cc
|
||||
bpy_traceback.cc
|
||||
bpy_utils_previews.cc
|
||||
bpy_utils_images.cc
|
||||
bpy_utils_units.cc
|
||||
stubs.cc
|
||||
|
||||
|
@ -86,6 +89,7 @@ set(SRC
|
|||
bpy_app_timers.h
|
||||
bpy_app_translations.h
|
||||
bpy_app_usd.h
|
||||
bpy_app_tornavis.h
|
||||
bpy_capi_utils.h
|
||||
bpy_driver.h
|
||||
bpy_gizmo_wrap.h
|
||||
|
@ -110,6 +114,7 @@ set(SRC
|
|||
bpy_rna_ui.h
|
||||
bpy_traceback.h
|
||||
bpy_utils_previews.h
|
||||
bpy_utils_images.h
|
||||
bpy_utils_units.h
|
||||
../BPY_extern.h
|
||||
../BPY_extern_clog.h
|
||||
|
@ -128,6 +133,7 @@ set(LIB
|
|||
PRIVATE bf::intern::guardedalloc
|
||||
PRIVATE bf::animrig
|
||||
bf_python_gpu
|
||||
tornavis
|
||||
|
||||
${PYTHON_LINKFLAGS}
|
||||
${PYTHON_LIBRARIES}
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "bpy_rna_id_collection.h"
|
||||
#include "bpy_rna_types_capi.h"
|
||||
#include "bpy_utils_previews.h"
|
||||
#include "bpy_utils_images.h"
|
||||
#include "bpy_utils_units.h"
|
||||
|
||||
#include "../generic/py_capi_utils.h"
|
||||
|
@ -686,6 +687,7 @@ void BPy_init_modules(bContext *C)
|
|||
PyModule_AddObject(mod, "app", BPY_app_struct());
|
||||
PyModule_AddObject(mod, "_utils_units", BPY_utils_units());
|
||||
PyModule_AddObject(mod, "_utils_previews", BPY_utils_previews_module());
|
||||
PyModule_AddObject(mod, "_utils_images", BPY_utils_images_module());
|
||||
PyModule_AddObject(mod, "msgbus", BPY_msgbus_module());
|
||||
|
||||
PointerRNA ctx_ptr = RNA_pointer_create(nullptr, &RNA_Context, C);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "bpy_app_openvdb.h"
|
||||
#include "bpy_app_sdl.h"
|
||||
#include "bpy_app_usd.h"
|
||||
#include "bpy_app_tornavis.h"
|
||||
|
||||
#include "bpy_app_translations.h"
|
||||
|
||||
|
@ -116,6 +117,7 @@ static PyStructSequence_Field app_info_fields[] = {
|
|||
{"build_options", "A set containing most important enabled optional build features"},
|
||||
{"handlers", "Application handler callbacks"},
|
||||
{"translations", "Application and addons internationalization API"},
|
||||
{"tornavis", "Tornavis options"},
|
||||
|
||||
/* Modules (not struct sequence). */
|
||||
{"icons", "Manage custom icons"},
|
||||
|
@ -200,6 +202,7 @@ static PyObject *make_app_info()
|
|||
SetObjItem(BPY_app_build_options_struct());
|
||||
SetObjItem(BPY_app_handlers_struct());
|
||||
SetObjItem(BPY_app_translations_struct());
|
||||
SetObjItem(BPY_app_tornavis_struct());
|
||||
|
||||
/* modules */
|
||||
SetObjItem(BPY_app_icons_module());
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup pythonintern
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "bpy_app_tornavis.h"
|
||||
|
||||
#include "MB_tornavis.h"
|
||||
|
||||
static PyTypeObject BlenderAppTornavisType;
|
||||
|
||||
static PyStructSequence_Field app_tornavis_info_fields[] = {
|
||||
{"patches", nullptr},
|
||||
{nullptr},
|
||||
};
|
||||
|
||||
static PyStructSequence_Desc app_tornavis_info_desc = {
|
||||
"bpy.app.tornavis", /* name */
|
||||
"This module contains options about tornavis project", /* doc */
|
||||
app_tornavis_info_fields, /* fields */
|
||||
ARRAY_SIZE(app_tornavis_info_fields) - 1,
|
||||
};
|
||||
|
||||
static PyObject *make_tornavis_info()
|
||||
{
|
||||
PyObject *tornavis_info;
|
||||
PyObject *list;
|
||||
int pos=0;
|
||||
char *patch = nullptr;
|
||||
|
||||
tornavis_info = PyStructSequence_New(&BlenderAppTornavisType);
|
||||
if (tornavis_info == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
list = PyList_New(0);
|
||||
|
||||
PyStructSequence_SET_ITEM(tornavis_info, pos++, list);
|
||||
|
||||
|
||||
for (int i =0 ; (patch = MB_patch_get(i)); i++) {
|
||||
PyList_Append(list, PyUnicode_FromString(patch));
|
||||
}
|
||||
|
||||
|
||||
return tornavis_info;
|
||||
}
|
||||
|
||||
PyObject *BPY_app_tornavis_struct()
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
PyStructSequence_InitType(&BlenderAppTornavisType, &app_tornavis_info_desc);
|
||||
|
||||
ret = make_tornavis_info();
|
||||
|
||||
/* prevent user from creating new instances */
|
||||
BlenderAppTornavisType.tp_init = nullptr;
|
||||
BlenderAppTornavisType.tp_new = nullptr;
|
||||
/* Without this we can't do `set(sys.modules)` #29635. */
|
||||
BlenderAppTornavisType.tp_hash = (hashfunc)_Py_HashPointer;
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup pythonintern
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
PyObject *BPY_app_tornavis_struct(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -36,6 +36,7 @@
|
|||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "WM_api.hh"
|
||||
#include "WM_op_handlers.h"
|
||||
#include "WM_types.hh"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
@ -461,11 +462,493 @@ static PyModuleDef bpy_ops_module = {
|
|||
/*m_free*/ nullptr,
|
||||
};
|
||||
|
||||
static int bpy_op_handler_check(void *py_data, void* owner, void *callback)
|
||||
{
|
||||
PyObject *py_owner = PyTuple_GET_ITEM(py_data, 0);
|
||||
PyObject *py_callback = PyTuple_GET_ITEM(py_data, 2);
|
||||
if (owner != NULL && callback != NULL) {
|
||||
return (py_owner == owner && py_callback == callback);
|
||||
}
|
||||
else if (owner != NULL)
|
||||
{
|
||||
return (py_owner == owner);
|
||||
}
|
||||
else { //callback != NULL
|
||||
return (py_callback == callback);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @Properties Rna Properties that has been used to set the operator
|
||||
*/
|
||||
static PyObject *bpy_op_get_operator_params(PointerRNA *properties)
|
||||
{
|
||||
const char *arg_name = NULL;
|
||||
PyObject *py_dict = PyDict_New();
|
||||
PyObject *data;
|
||||
RNA_STRUCT_BEGIN (properties, prop) {
|
||||
arg_name = RNA_property_identifier(prop);
|
||||
data = NULL;
|
||||
if (STREQ(arg_name, "rna_type")) {
|
||||
continue;
|
||||
}
|
||||
switch (RNA_property_type(prop)) {
|
||||
case PROP_BOOLEAN: {
|
||||
bool val = RNA_property_boolean_get(properties, prop);
|
||||
// from Py Docs, Py_False and Py_truee needs to be treated just like any other object with
|
||||
// respect to reference counts.
|
||||
data = val ? Py_False : Py_True;
|
||||
break;
|
||||
}
|
||||
case PROP_INT: {
|
||||
const int prop_array_length = RNA_property_array_length(properties, prop);
|
||||
if (prop_array_length == 0) {
|
||||
int val = RNA_property_int_get(properties, prop);
|
||||
data = PyLong_FromLong(val);
|
||||
}
|
||||
else {
|
||||
int *values = (int*) MEM_callocN(sizeof(int) * prop_array_length, __func__);
|
||||
RNA_property_int_get_array(properties, prop, values);
|
||||
data = PyTuple_New(prop_array_length);
|
||||
for (int i = 0; i < prop_array_length; i++) {
|
||||
PyObject *py_val = PyLong_FromLong(*(values + i));
|
||||
PyTuple_SET_ITEM(data, i, py_val);
|
||||
}
|
||||
MEM_freeN(values);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PROP_FLOAT: {
|
||||
const int prop_array_length = RNA_property_array_length(properties, prop);
|
||||
if (prop_array_length == 0) {
|
||||
float val;
|
||||
val = RNA_property_float_get(properties, prop);
|
||||
data = PyFloat_FromDouble(val);
|
||||
}
|
||||
else {
|
||||
float *values = (float*) MEM_callocN(sizeof(float) * prop_array_length, __func__);
|
||||
RNA_property_float_get_array(properties, prop, values);
|
||||
data = PyTuple_New(prop_array_length);
|
||||
for (int i = 0; i < prop_array_length; i++) {
|
||||
PyObject *py_val = PyFloat_FromDouble(*(values + i));
|
||||
PyTuple_SET_ITEM(data, i, py_val);
|
||||
}
|
||||
MEM_freeN(values);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PROP_STRING: {
|
||||
char buff[256];
|
||||
char *value = RNA_property_string_get_alloc(properties, prop, buff, sizeof(buff), NULL);
|
||||
data = PyUnicode_FromString(value);
|
||||
if (value != buff) {
|
||||
MEM_freeN(value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PROP_ENUM: {
|
||||
int val = RNA_property_enum_get(properties, prop);
|
||||
data = PyLong_FromLong(val);
|
||||
break;
|
||||
}
|
||||
case PROP_POINTER: {
|
||||
data = PyUnicode_FromString("POINTER");
|
||||
break;
|
||||
}
|
||||
case PROP_COLLECTION: {
|
||||
data = PyUnicode_FromString("COLLECTION");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BLI_assert(false);
|
||||
}
|
||||
if (data != NULL) {
|
||||
PyDict_SetItemString(py_dict, arg_name, data);
|
||||
}
|
||||
}
|
||||
RNA_STRUCT_END;
|
||||
return py_dict;
|
||||
}
|
||||
|
||||
|
||||
static bool bpy_op_callback_get_return_value(PyObject *callback, PyObject *py_ret)
|
||||
{
|
||||
bool ret = true; // Do not interrump on error
|
||||
if (py_ret == NULL) {
|
||||
PyC_Err_PrintWithFunc(callback);
|
||||
}
|
||||
else {
|
||||
if (py_ret == Py_None) {
|
||||
// pass
|
||||
}
|
||||
else if (py_ret == Py_True) {
|
||||
// pass
|
||||
}
|
||||
else if (py_ret == Py_False){
|
||||
ret = false;
|
||||
} else {
|
||||
PyErr_SetString(PyExc_ValueError, "the return value must be None or boolean");
|
||||
PyC_Err_PrintWithFunc(callback);
|
||||
}
|
||||
Py_DECREF(py_ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *bpy_op_get_callback_call(PyObject *callback,
|
||||
bContext *C, const wmEvent *event, int *operator_ret, PyObject *params, PyObject *callback_args)
|
||||
{
|
||||
PointerRNA ctx_ptr;
|
||||
PointerRNA event_ptr;
|
||||
|
||||
PyObject *bpy_ctx;
|
||||
PyObject *bpy_event;
|
||||
PyObject *py_ret;
|
||||
|
||||
ctx_ptr = RNA_pointer_create(nullptr, &RNA_Context, C);
|
||||
bpy_ctx = pyrna_struct_CreatePyObject(&ctx_ptr);
|
||||
|
||||
if (event != NULL) {
|
||||
event_ptr = RNA_pointer_create(NULL, &RNA_Event, (void*) event);
|
||||
bpy_event = pyrna_struct_CreatePyObject(&event_ptr);
|
||||
}
|
||||
else {
|
||||
bpy_event = Py_None;
|
||||
}
|
||||
|
||||
int s = (operator_ret == NULL) ? 3 : 4;
|
||||
int c = (callback_args == Py_None) ? s : PyTuple_GET_SIZE(callback_args) + s;
|
||||
PyObject *func_args = PyTuple_New(c);
|
||||
|
||||
PyTuple_SET_ITEM(func_args, 0, bpy_ctx);
|
||||
PyTuple_SET_ITEM(func_args, 1, bpy_event);
|
||||
PyTuple_SET_ITEM(func_args, 2, params);
|
||||
|
||||
if (operator_ret != NULL) {
|
||||
PyObject *op_ret = pyrna_enum_bitfield_to_py(rna_enum_operator_return_items, *operator_ret);
|
||||
PyTuple_SET_ITEM(func_args, 3, op_ret);
|
||||
}
|
||||
|
||||
for (int i = s; i < c; i++) {
|
||||
PyTuple_SET_ITEM(func_args, i, PyTuple_GET_ITEM(callback_args, i - s));
|
||||
}
|
||||
|
||||
py_ret = PyObject_CallObject(callback, func_args);
|
||||
Py_DECREF(func_args);
|
||||
return py_ret;
|
||||
}
|
||||
|
||||
|
||||
static bool bpy_op_handler_poll(struct bContext *C,
|
||||
const wmEvent *event, void *py_data,
|
||||
PointerRNA *properties)
|
||||
{
|
||||
bool ret = true;
|
||||
PyGILState_STATE gilstate; // this is because is not thread safe
|
||||
bpy_context_set(C, &gilstate);
|
||||
{
|
||||
PyObject *callback_args = PyTuple_GET_ITEM(py_data, 3);
|
||||
PyObject *py_poll = PyTuple_GET_ITEM(py_data, 4);
|
||||
|
||||
// Properties get null on modall poll, params are not bypassed to Py poll function
|
||||
PyObject *params = (properties == NULL) ? Py_None : bpy_op_get_operator_params(properties);
|
||||
if (py_poll != Py_None) {
|
||||
PyObject *py_ret = bpy_op_get_callback_call(py_poll, C, event, NULL, params, callback_args);
|
||||
|
||||
if (py_ret == NULL) {
|
||||
// Error
|
||||
PyErr_Print();
|
||||
return false;
|
||||
}
|
||||
else if (py_ret == Py_True) {
|
||||
ret = true;
|
||||
Py_DECREF(py_ret);
|
||||
}
|
||||
else if (py_ret == Py_False) {
|
||||
ret = false;
|
||||
Py_DECREF(py_ret);
|
||||
}
|
||||
else {
|
||||
ret = false;
|
||||
Py_DECREF(py_ret);
|
||||
PyErr_SetString(PyExc_ValueError, "the return value must be boolean");
|
||||
PyC_Err_PrintWithFunc(py_poll);
|
||||
}
|
||||
}
|
||||
// Py_DECREF(params);
|
||||
}
|
||||
bpy_context_clear(C, &gilstate);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool bpy_op_handler_modal (bContext *C, const wmEvent *event, void *py_data, PointerRNA *properties, int operator_ret)
|
||||
{
|
||||
// this is because is not thread safe
|
||||
bool ret = true;
|
||||
PyGILState_STATE gilstate;
|
||||
bpy_context_set(C, &gilstate);
|
||||
{
|
||||
PyObject *callback = PyTuple_GET_ITEM(py_data, 2);
|
||||
PyObject *callback_args = PyTuple_GET_ITEM(py_data, 3);
|
||||
PyObject *py_ret = bpy_op_get_callback_call(callback, C, event, &operator_ret, Py_None, callback_args);
|
||||
ret = bpy_op_callback_get_return_value(callback, py_ret);
|
||||
}
|
||||
bpy_context_clear(C, &gilstate);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static bool bpy_op_handler_invoke(bContext *C,
|
||||
const wmEvent *event,
|
||||
void *py_data,
|
||||
PointerRNA *properties,
|
||||
int operator_ret)
|
||||
{
|
||||
bool ret = true;
|
||||
// this is because is not thread safe
|
||||
PyGILState_STATE gilstate;
|
||||
bpy_context_set(C, &gilstate);
|
||||
{
|
||||
PyObject *callback = PyTuple_GET_ITEM(py_data, 2);
|
||||
PyObject *callback_args = PyTuple_GET_ITEM(py_data, 3);
|
||||
PyObject *params = bpy_op_get_operator_params(properties);
|
||||
PyObject *py_ret = bpy_op_get_callback_call(callback, C, event, operator_ret ? &operator_ret : NULL , params, callback_args);
|
||||
ret = bpy_op_callback_get_return_value(callback, py_ret);
|
||||
}
|
||||
bpy_context_clear(C, &gilstate);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *bpy_op_handler_proc(
|
||||
PyObject *args,
|
||||
PyObject *kw)
|
||||
{
|
||||
const char *error_prefix = "op_handler_proc";
|
||||
|
||||
PyObject *py_op = NULL;
|
||||
PyObject *py_owner = NULL; // Object who creates the handler
|
||||
PyObject *callback = NULL, *py_poll = NULL;
|
||||
PyObject *callback_args = NULL;
|
||||
|
||||
|
||||
if (PyTuple_GET_SIZE(args) != 0) {
|
||||
PyErr_Format(PyExc_TypeError, "%s: only keyword arguments are supported", error_prefix);
|
||||
}
|
||||
|
||||
// see https://docs.python.org/3/c-api/arg.html
|
||||
static const char *_keywords[] = {"owner", "op", "cb", "args", "poll", NULL};
|
||||
static _PyArg_Parser _parser = {"OOOOO|:handler_proc", _keywords, 0};
|
||||
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &py_owner, &py_op, &callback, &callback_args, &py_poll)) {
|
||||
PyErr_SetString(
|
||||
PyExc_TypeError, "Cannot set arguments, or types does not match");
|
||||
}
|
||||
|
||||
if (callback != Py_None && !PyFunction_Check(callback)) {
|
||||
// Callback may be none on remove
|
||||
PyErr_Format(
|
||||
PyExc_TypeError, "callback expects a function, found %.200s", Py_TYPE(callback)->tp_name);
|
||||
}
|
||||
|
||||
if (py_poll != Py_None && !PyFunction_Check(py_poll)) {
|
||||
// Callback may be none on remove
|
||||
PyErr_Format(
|
||||
PyExc_TypeError, "poll expects a function, found %.200s", Py_TYPE(callback)->tp_name);
|
||||
}
|
||||
|
||||
if (py_op != Py_None && !PyUnicode_Check(py_op)) {
|
||||
PyErr_Format(
|
||||
PyExc_TypeError, "op expects an astring, found %.200s", Py_TYPE(py_op)->tp_name);
|
||||
}
|
||||
|
||||
if (PyErr_Occurred() != NULL) {
|
||||
PyErr_Print();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
PyObject *py_data = PyTuple_New(5);
|
||||
PyTuple_SET_ITEMS(py_data,
|
||||
Py_INCREF_RET(py_owner), // 0
|
||||
Py_INCREF_RET(py_op), // 1
|
||||
Py_INCREF_RET(callback), // 2
|
||||
Py_INCREF_RET(callback_args), // 3
|
||||
Py_INCREF_RET(py_poll)); // 4
|
||||
|
||||
return Py_INCREF_RET(py_data);
|
||||
}
|
||||
|
||||
static PyObject *op_handler_append(int handler_id , PyObject *args, PyObject *kw)
|
||||
{
|
||||
bContext *C = BPY_context_get();
|
||||
struct wmOpHandlers *op_handlers = CTX_wm_op_handlers(C);
|
||||
|
||||
PyObject *py_data = bpy_op_handler_proc(args, kw);
|
||||
|
||||
bool (*func)(bContext * C,const wmEvent * event, void *, PointerRNA *, int) = nullptr;
|
||||
|
||||
switch (handler_id) {
|
||||
case HANDLER_TYPE_PRE_INVOKE:
|
||||
case HANDLER_TYPE_POST_INVOKE:
|
||||
func = bpy_op_handler_invoke;
|
||||
break;
|
||||
case HANDLER_TYPE_MODAL:
|
||||
case HANDLER_TYPE_MODAL_END:
|
||||
func = bpy_op_handler_modal;
|
||||
break;
|
||||
}
|
||||
|
||||
if (py_data != NULL) {
|
||||
PyObject *py_owner = PyTuple_GET_ITEM(py_data, 0);
|
||||
PyObject *py_op = PyTuple_GET_ITEM(py_data, 1);
|
||||
PyObject *py_callback = PyTuple_GET_ITEM(py_data, 2);
|
||||
PyObject *py_poll = PyTuple_GET_ITEM(py_data, 4);
|
||||
if (py_op == Py_None) {
|
||||
PyErr_Format(PyExc_TypeError, "missing operator");
|
||||
}
|
||||
else if (py_callback == Py_None) {
|
||||
PyErr_Format(PyExc_TypeError, "callback expects a function");
|
||||
} else {
|
||||
WM_op_handlers_append(op_handlers,
|
||||
handler_id,
|
||||
py_owner,
|
||||
PyUnicode_AsUTF8(py_op),
|
||||
func,
|
||||
bpy_op_handler_check,
|
||||
py_poll == Py_None ? NULL : bpy_op_handler_poll,
|
||||
py_data);
|
||||
}
|
||||
}
|
||||
|
||||
if (PyErr_Occurred() != NULL) {
|
||||
PyErr_Print();
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *op_handler_remove(int handler_id, PyObject *args, PyObject *kw)
|
||||
{
|
||||
bContext *C = BPY_context_get();
|
||||
struct wmOpHandlers *op_handlers = CTX_wm_op_handlers(C);
|
||||
|
||||
PyObject *py_data = bpy_op_handler_proc(args, kw);
|
||||
|
||||
if (py_data != NULL) {
|
||||
PyObject *py_owner = PyTuple_GET_ITEM(py_data, 0);
|
||||
PyObject *py_op = PyTuple_GET_ITEM(py_data, 1);
|
||||
PyObject *py_cb = PyTuple_GET_ITEM(py_data, 2);
|
||||
if (py_owner == Py_None && py_cb == Py_None) {
|
||||
PyErr_Format(PyExc_TypeError, "missing owner or callback");
|
||||
} else {
|
||||
if (WM_op_handlers_remove(op_handlers,
|
||||
handler_id,
|
||||
(py_op == Py_None ? NULL : PyUnicode_AsUTF8(py_op)),
|
||||
(py_cb == Py_None ? NULL : py_cb),
|
||||
(py_owner == Py_None ? NULL : py_owner)) == 0) {
|
||||
PyErr_Format(PyExc_NameError, "data not found on %s", PyUnicode_AsUTF8(py_op));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (PyErr_Occurred() != NULL) {
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *op_handler_append_pre_invoke(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
return op_handler_append(HANDLER_TYPE_PRE_INVOKE, args, kw);
|
||||
}
|
||||
|
||||
static PyObject *op_handler_append_post_invoke(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
return op_handler_append(HANDLER_TYPE_POST_INVOKE, args, kw);
|
||||
}
|
||||
|
||||
static PyObject *op_handler_append_modal(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
return op_handler_append(HANDLER_TYPE_MODAL, args, kw);
|
||||
}
|
||||
|
||||
static PyObject *op_handler_append_modal_end(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
return op_handler_append(HANDLER_TYPE_MODAL_END, args, kw);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static PyObject *op_handler_remove_pre_invoke(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
return op_handler_remove(HANDLER_TYPE_PRE_INVOKE, args, kw);
|
||||
}
|
||||
|
||||
static PyObject *op_handler_remove_post_invoke(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
return op_handler_remove(HANDLER_TYPE_POST_INVOKE, args, kw);
|
||||
}
|
||||
|
||||
static PyObject *op_handler_remove_modal(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
return op_handler_remove(HANDLER_TYPE_MODAL, args, kw);
|
||||
}
|
||||
|
||||
static PyObject *op_handler_remove_modal_end(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
return op_handler_remove(HANDLER_TYPE_MODAL_END, args, kw);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *op_handlers_remove(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
return op_handler_remove(HANDLER_TYPE_ALL, args, kw);
|
||||
}
|
||||
|
||||
|
||||
static struct PyMethodDef bpy_ops_handlers_methods[] = {
|
||||
{"pre_invoke", (PyCFunction)op_handler_append_pre_invoke, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{"post_invoke", (PyCFunction)op_handler_append_post_invoke, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{"modal", (PyCFunction)op_handler_append_modal, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{"modal_end", (PyCFunction)op_handler_append_modal_end, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{"pre_invoke_remove", (PyCFunction)op_handler_remove_pre_invoke, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{"post_invoke_remove", (PyCFunction)op_handler_remove_post_invoke, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{"modal_remove",(PyCFunction)op_handler_remove_post_invoke, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{"modal_end_remove", (PyCFunction)op_handler_remove_modal_end, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{"remove", (PyCFunction)op_handlers_remove, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{NULL, NULL, 0, NULL},
|
||||
};
|
||||
|
||||
static struct PyModuleDef bpy_ops_handlers = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_bpy.ops.handlers",
|
||||
NULL,
|
||||
-1, /* multiple "initialization" just copies the module dict. */
|
||||
bpy_ops_handlers_methods,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
|
||||
PyObject *BPY_operator_module()
|
||||
{
|
||||
PyObject *submodule;
|
||||
|
||||
submodule = PyModule_Create(&bpy_ops_module);
|
||||
|
||||
PyObject *handlers = PyModule_Create(&bpy_ops_handlers);
|
||||
|
||||
Py_INCREF(handlers);
|
||||
if (PyModule_AddObject(submodule, "handlers", handlers) < 0) {
|
||||
Py_DECREF(submodule);
|
||||
Py_DECREF(handlers);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return submodule;
|
||||
}
|
||||
|
|
|
@ -1303,6 +1303,25 @@ static int pyrna_prop_to_enum_bitfield(
|
|||
return ret;
|
||||
}
|
||||
|
||||
PyObject *pyrna_enum_bitfield_to_py(const EnumPropertyItem *items, int value)
|
||||
{
|
||||
PyObject *ret = PySet_New(NULL);
|
||||
const char *identifier[RNA_ENUM_BITFLAG_SIZE + 1];
|
||||
|
||||
if (RNA_enum_bitflag_identifiers(items, value, identifier)) {
|
||||
PyObject *item;
|
||||
int index;
|
||||
for (index = 0; identifier[index]; index++) {
|
||||
item = PyUnicode_FromString(identifier[index]);
|
||||
PySet_Add(ret, item);
|
||||
Py_DECREF(item);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val)
|
||||
{
|
||||
PyObject *item, *ret = nullptr;
|
||||
|
|
|
@ -189,6 +189,8 @@ PyObject *pyrna_id_CreatePyObject(struct ID *id);
|
|||
bool pyrna_id_FromPyObject(PyObject *obj, struct ID **id);
|
||||
bool pyrna_id_CheckPyObject(PyObject *obj);
|
||||
|
||||
PyObject *pyrna_enum_bitfield_to_py(const struct EnumPropertyItem *items, int value);
|
||||
|
||||
/* operators also need this to set args */
|
||||
int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, bool all_args, const char *error_prefix);
|
||||
PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop);
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup pythonintern
|
||||
*
|
||||
* This file defines a singleton py object accessed via 'bpy.utils.images',
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
#include <structmember.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_prototypes.h"
|
||||
#include "RNA_types.hh"
|
||||
|
||||
#include "BPY_extern.h"
|
||||
#include "bpy_rna.h"
|
||||
#include "bpy_utils_images.h"
|
||||
|
||||
#include "../generic/py_capi_utils.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "IMB_imbuf.hh"
|
||||
|
||||
#include "../generic/python_utildefines.h"
|
||||
|
||||
|
||||
struct bpy_image_data{
|
||||
bpy_image_data *prev;
|
||||
bpy_image_data *next;
|
||||
|
||||
int id;
|
||||
ImBuf *ibuf;
|
||||
std::string name;
|
||||
std::string path;
|
||||
};
|
||||
|
||||
int bpy_images_last_id = 0;
|
||||
ListBase bpy_images_list;
|
||||
|
||||
|
||||
bpy_image_data* BPY_utils_images_get_data(int image_id) {
|
||||
return (bpy_image_data *)BLI_listbase_bytes_find(
|
||||
&bpy_images_list, &image_id, sizeof(int), sizeof(bpy_image_data *) * 2);
|
||||
}
|
||||
|
||||
void* BPY_utils_images_get(int image_id)
|
||||
{
|
||||
bpy_image_data *el = BPY_utils_images_get_data(image_id);
|
||||
return (el != nullptr) ? el->ibuf : nullptr;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(bpy_utils_images_load_doc,
|
||||
".. method:: load(name, filepath)\n"
|
||||
"\n"
|
||||
" Generate a new preview from given file path.\n"
|
||||
"\n"
|
||||
" :arg name: The name identifying the image.\n"
|
||||
" :type name: string\n"
|
||||
" :arg filepath: The file path to the image.\n"
|
||||
" :type filepath: string or bytes\n"
|
||||
" :return: image id.\n"
|
||||
" :rtype: long`\n");
|
||||
static PyObject *bpy_utils_images_load(PyObject * /*self*/, PyObject *args)
|
||||
{
|
||||
char *name = NULL;
|
||||
PyC_UnicodeAsBytesAndSize_Data filepath_data = {nullptr};
|
||||
|
||||
if (!PyArg_ParseTuple(args,
|
||||
"s" /* `name` */
|
||||
"O&" /* `filepath` */
|
||||
":load",
|
||||
&name,
|
||||
PyC_ParseUnicodeAsBytesAndSize,
|
||||
&filepath_data,
|
||||
0))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!filepath_data.value || !name) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
ImBuf *ibuf = IMB_loadiffname(filepath_data.value, 0, nullptr);
|
||||
|
||||
if (ibuf) {
|
||||
bpy_image_data *data = MEM_new<bpy_image_data>(__func__);
|
||||
data->id = ++bpy_images_last_id;
|
||||
data->ibuf = ibuf;
|
||||
data->name = name;
|
||||
data->path = filepath_data.value;
|
||||
|
||||
BLI_addtail(&bpy_images_list, data);
|
||||
|
||||
return PyLong_FromLong(data->id);
|
||||
}
|
||||
else {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(bpy_utils_images_release_doc,
|
||||
".. method:: release(image_id)\n"
|
||||
"\n"
|
||||
" Release (free) a previously added image.\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" :arg image_id: The id identifying the image.\n"
|
||||
" :type name: long\n"
|
||||
" :return: true if release.\n"
|
||||
" :rtype: bool`\n");
|
||||
static PyObject *bpy_utils_images_release(PyObject * /*self*/, PyObject *args)
|
||||
{
|
||||
int image_id = -1;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i:release", &image_id)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bpy_image_data *el = BPY_utils_images_get_data(image_id);
|
||||
|
||||
if (el != nullptr) {
|
||||
BLI_remlink(&bpy_images_list, el);
|
||||
IMB_freeImBuf(el->ibuf);
|
||||
MEM_freeN(el);
|
||||
Py_RETURN_TRUE;
|
||||
}
|
||||
else {
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static PyMethodDef bpy_utils_images_methods[] = {
|
||||
/* Can't use METH_KEYWORDS alone, see http://bugs.python.org/issue11587 */
|
||||
{"load", (PyCFunction)bpy_utils_images_load, METH_VARARGS, bpy_utils_images_load_doc},
|
||||
{"release",(PyCFunction)bpy_utils_images_release,METH_VARARGS, bpy_utils_images_release_doc},
|
||||
{nullptr, nullptr, 0, nullptr},
|
||||
};
|
||||
|
||||
PyDoc_STRVAR(
|
||||
bpy_utils_images_doc,
|
||||
"This object contains basic static methods to handle cached (non-ID) previews in Blender\n"
|
||||
"(low-level API, not exposed to final users).");
|
||||
static PyModuleDef bpy_utils_images_module = {
|
||||
/*m_base*/ PyModuleDef_HEAD_INIT,
|
||||
/*m_name*/ "bpy._utils_images",
|
||||
/*m_doc*/ bpy_utils_images_doc,
|
||||
/*m_size*/ 0,
|
||||
/*m_methods*/ bpy_utils_images_methods,
|
||||
/*m_slots*/ nullptr,
|
||||
/*m_traverse*/ nullptr,
|
||||
/*m_clear*/ nullptr,
|
||||
/*m_free*/ nullptr,
|
||||
};
|
||||
|
||||
PyObject *BPY_utils_images_module()
|
||||
{
|
||||
PyObject *submodule;
|
||||
|
||||
submodule = PyModule_Create(&bpy_utils_images_module);
|
||||
|
||||
return submodule;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup pythonintern
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
PyObject *BPY_utils_images_module(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,45 @@
|
|||
#
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
set(INC
|
||||
.
|
||||
../blenlib
|
||||
)
|
||||
|
||||
set(LIB
|
||||
PRIVATE bf::blenlib
|
||||
)
|
||||
|
||||
|
||||
if(WITH_BOOST)
|
||||
list(APPEND INC_SYS
|
||||
${BOOST_INCLUDE_DIR}
|
||||
)
|
||||
else()
|
||||
message (FATAL_ERROR "tornavis requires WITH_BOOST")
|
||||
endif()
|
||||
|
||||
# Auto fill source files, so patches will not touch that file
|
||||
file(GLOB sources "MB_*")
|
||||
foreach(source ${sources})
|
||||
get_filename_component(name ${source} NAME)
|
||||
list(APPEND SRC "${name}")
|
||||
endforeach()
|
||||
|
||||
# Generate a Definition for each found patch
|
||||
file(GLOB patches "patches/*")
|
||||
foreach(patch ${patches})
|
||||
get_filename_component(def ${patch} NAME_WE)
|
||||
get_filename_component(name ${patch} NAME)
|
||||
if (${name} MATCHES "^MB_[0-9][0-9][0-9][0-9]\.h$" )
|
||||
add_definitions(-D${def})
|
||||
list(APPEND SRC "patches/${name}")
|
||||
else()
|
||||
message (FATAL_ERROR "invalid patch file ${name}")
|
||||
endif ()
|
||||
endforeach()
|
||||
|
||||
|
||||
blender_add_lib(tornavis "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
|
@ -0,0 +1,149 @@
|
|||
#ifndef MB_BLENDER_PATCHES_H
|
||||
#define MB_BLENDER_PATCHES_H
|
||||
|
||||
#ifdef MB_0001
|
||||
#include "patches/MB_0001.h"
|
||||
#define MB_0001_APPLIED 1
|
||||
#else
|
||||
#define MB_0001_APPLIED 0
|
||||
#endif
|
||||
|
||||
#ifdef MB_0002
|
||||
#include "patches/MB_0002.h"
|
||||
#define MB_0002_APPLIED 1
|
||||
#else
|
||||
#define MB_0002_APPLIED 0
|
||||
#endif
|
||||
|
||||
#ifdef MB_0003
|
||||
#include "patches/MB_0003.h"
|
||||
#define MB_0003_APPLIED 1
|
||||
#else
|
||||
# define MB_0003_APPLIED 0
|
||||
#endif
|
||||
|
||||
#ifdef MB_0004
|
||||
#include "patches/MB_0004.h"
|
||||
#define MB_0004_APPLIED 1
|
||||
#else
|
||||
# define MB_0004_APPLIED 0
|
||||
#endif
|
||||
|
||||
#ifdef MB_0005
|
||||
#include "patches/MB_0005.h"
|
||||
#define MB_0005_APPLIED 1
|
||||
#else
|
||||
# define MB_0005_APPLIED 0
|
||||
#endif
|
||||
|
||||
#ifdef MB_0006
|
||||
#include "patches/MB_0006.h"
|
||||
#define MB_0006_APPLIED 1
|
||||
#else
|
||||
#define MB_0006_APPLIED 0
|
||||
#endif
|
||||
|
||||
#ifdef MB_0007
|
||||
#include "patches/MB_0007.h"
|
||||
#define MB_0007_APPLIED 1
|
||||
#else
|
||||
#define MB_0007_APPLIED 0
|
||||
#endif
|
||||
|
||||
#ifdef MB_0008
|
||||
#include "patches/MB_0008.h"
|
||||
#define MB_0008_APPLIED 1
|
||||
#else
|
||||
#define MB_0008_APPLIED 0
|
||||
#endif
|
||||
|
||||
#ifdef MB_0009
|
||||
#include "patches/MB_0009.h"
|
||||
#define MB_0009_APPLIED 1
|
||||
#else
|
||||
#define MB_0009_APPLIED 0
|
||||
#endif
|
||||
|
||||
#ifdef MB_0010
|
||||
#include "patches/MB_0010.h"
|
||||
#define MB_0010_APPLIED 1
|
||||
#else
|
||||
#define MB_0010_APPLIED 0
|
||||
#endif
|
||||
|
||||
#ifdef MB_0011
|
||||
#include "patches/MB_0011.h"
|
||||
#define MB_0011_APPLIED 1
|
||||
#else
|
||||
#define MB_0011_APPLIED 0
|
||||
#endif
|
||||
|
||||
#ifdef MB_0012
|
||||
#include "patches/MB_0012.h"
|
||||
#define MB_0012_APPLIED 1
|
||||
#else
|
||||
#define MB_0012_APPLIED 0
|
||||
#endif
|
||||
|
||||
#ifdef MB_0013
|
||||
#include "patches/MB_0013.h"
|
||||
#define MB_0013_APPLIED 1
|
||||
#else
|
||||
#define MB_0013_APPLIED 0
|
||||
#endif
|
||||
|
||||
#ifdef MB_0014
|
||||
#include "patches/MB_0014.h"
|
||||
#define MB_0014_APPLIED 1
|
||||
#else
|
||||
#define MB_0014_APPLIED 0
|
||||
#endif
|
||||
|
||||
#ifdef MB_0015
|
||||
#include "patches/MB_0015.h"
|
||||
#define MB_0015_APPLIED 1
|
||||
#else
|
||||
#define MB_0015_APPLIED 0
|
||||
#endif
|
||||
|
||||
#ifdef MB_0016
|
||||
#include "patches/MB_0016.h"
|
||||
#define MB_0016_APPLIED 1
|
||||
#else
|
||||
#define MB_0016_APPLIED 0
|
||||
#endif
|
||||
|
||||
#ifdef MB_0017
|
||||
#include "patches/MB_0017.h"
|
||||
#define MB_0017_APPLIED 1
|
||||
#else
|
||||
#define MB_0017_APPLIED 0
|
||||
#endif
|
||||
|
||||
#ifdef MB_0018
|
||||
#include "patches/MB_0018.h"
|
||||
#define MB_0018_APPLIED 1
|
||||
#else
|
||||
#define MB_0018_APPLIED 0
|
||||
#endif
|
||||
|
||||
#ifdef MB_0019
|
||||
#include "patches/MB_0019.h"
|
||||
#define MB_0019_APPLIED 1
|
||||
#else
|
||||
#define MB_0019_APPLIED 0
|
||||
#endif
|
||||
|
||||
#ifdef MB_0020
|
||||
#include "patches/MB_0020.h"
|
||||
#define MB_0020_APPLIED 1
|
||||
#else
|
||||
#define MB_0020_APPLIED 0
|
||||
#endif
|
||||
|
||||
#ifndef MB_0021
|
||||
#define MAX_MB_PATCHES 21
|
||||
#endif
|
||||
|
||||
|
||||
#endif // !MB_BLENDER_PATCHES_H
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
#include "MB_patches.h"
|
||||
|
||||
#include <boost/preprocessor/if.hpp>
|
||||
|
||||
#include <BLI_assert.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
char patches[MAX_MB_PATCHES][8] = {0};
|
||||
|
||||
void MB_patches_discover()
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
BOOST_PP_IF(MB_0001_APPLIED, strcpy(patches[i++], "MB_0001"), );
|
||||
BOOST_PP_IF(MB_0002_APPLIED, strcpy(patches[i++], "MB_0002"), );
|
||||
BOOST_PP_IF(MB_0003_APPLIED, strcpy(patches[i++], "MB_0003"), );
|
||||
BOOST_PP_IF(MB_0004_APPLIED, strcpy(patches[i++], "MB_0004"), );
|
||||
BOOST_PP_IF(MB_0005_APPLIED, strcpy(patches[i++], "MB_0005"), );
|
||||
BOOST_PP_IF(MB_0006_APPLIED, strcpy(patches[i++], "MB_0006"), );
|
||||
BOOST_PP_IF(MB_0007_APPLIED, strcpy(patches[i++], "MB_0007"), );
|
||||
BOOST_PP_IF(MB_0008_APPLIED, strcpy(patches[i++], "MB_0008"), );
|
||||
BOOST_PP_IF(MB_0009_APPLIED, strcpy(patches[i++], "MB_0009"), );
|
||||
BOOST_PP_IF(MB_0010_APPLIED, strcpy(patches[i++], "MB_0010"), );
|
||||
BOOST_PP_IF(MB_0011_APPLIED, strcpy(patches[i++], "MB_0011"), );
|
||||
BOOST_PP_IF(MB_0012_APPLIED, strcpy(patches[i++], "MB_0012"), );
|
||||
BOOST_PP_IF(MB_0013_APPLIED, strcpy(patches[i++], "MB_0013"), );
|
||||
BOOST_PP_IF(MB_0014_APPLIED, strcpy(patches[i++], "MB_0014"), );
|
||||
BOOST_PP_IF(MB_0015_APPLIED, strcpy(patches[i++], "MB_0015"), );
|
||||
BOOST_PP_IF(MB_0016_APPLIED, strcpy(patches[i++], "MB_0016"), );
|
||||
BOOST_PP_IF(MB_0017_APPLIED, strcpy(patches[i++], "MB_0017"), );
|
||||
BOOST_PP_IF(MB_0018_APPLIED, strcpy(patches[i++], "MB_0018"), );
|
||||
BOOST_PP_IF(MB_0019_APPLIED, strcpy(patches[i++], "MB_0019"), );
|
||||
BOOST_PP_IF(MB_0020_APPLIED, strcpy(patches[i++], "MB_0020"), );
|
||||
|
||||
// Not necessary becuase initialitzed to {0}
|
||||
strcpy(patches[i++], "\0");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void MB_init(void) {
|
||||
MB_patches_discover();
|
||||
}
|
||||
|
||||
char* MB_patch_get(int pos) {
|
||||
BLI_assert(pos < MAX_MB_PATCHES);
|
||||
return *patches[pos] == '\0' ? nullptr : patches[pos];
|
||||
}
|
||||
|
||||
void MB_print_info()
|
||||
{
|
||||
printf("%s", "Tornavis Info\n");
|
||||
printf("%s", "---------------------\n");
|
||||
for (int i = 0; i < MAX_MB_PATCHES; i++) {
|
||||
if (*patches[i] == '\0') {
|
||||
break;
|
||||
}
|
||||
printf("Applied Patch %s\n", patches[i]);
|
||||
}
|
||||
printf("%s", "---------------------\n");
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MB_BLENDER_H
|
||||
#define MB_BLENDER_H
|
||||
|
||||
void MB_init(void);
|
||||
void MB_patches_discover(void);
|
||||
char* MB_patch_get(int pos);
|
||||
void MB_print_info(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1 @@
|
|||
/* Empty File */
|
|
@ -0,0 +1 @@
|
|||
/* Empty File */
|
|
@ -0,0 +1 @@
|
|||
/* Empty File */
|
|
@ -0,0 +1 @@
|
|||
/* Empty File */
|
|
@ -0,0 +1 @@
|
|||
/* Empty File */
|
|
@ -0,0 +1 @@
|
|||
/* Empty File */
|
|
@ -0,0 +1 @@
|
|||
/* Empty File */
|
|
@ -0,0 +1 @@
|
|||
/* Empty file */
|
|
@ -0,0 +1 @@
|
|||
/* Empty File */
|
|
@ -0,0 +1 @@
|
|||
/* Empty File */
|
|
@ -0,0 +1 @@
|
|||
/* Empty file */
|
|
@ -0,0 +1 @@
|
|||
/* Empty File */
|
|
@ -0,0 +1 @@
|
|||
/* Empty File */
|
|
@ -0,0 +1 @@
|
|||
/* Empty File */
|
|
@ -0,0 +1 @@
|
|||
/* Empty File */
|
|
@ -0,0 +1 @@
|
|||
/* Empty file */
|
|
@ -70,10 +70,12 @@ set(SRC
|
|||
message_bus/intern/wm_message_bus.cc
|
||||
message_bus/intern/wm_message_bus_rna.cc
|
||||
message_bus/intern/wm_message_bus_static.cc
|
||||
op_handlers/intern/wm_op_handlers.cc
|
||||
|
||||
WM_api.hh
|
||||
WM_keymap.hh
|
||||
WM_message.hh
|
||||
WM_op_handlers.h
|
||||
WM_toolsystem.hh
|
||||
WM_types.hh
|
||||
wm.hh
|
||||
|
@ -93,6 +95,8 @@ set(SRC
|
|||
gizmo/intern/wm_gizmo_intern.hh
|
||||
message_bus/intern/wm_message_bus_intern.hh
|
||||
message_bus/wm_message_bus.hh
|
||||
op_handlers/wm_op_handlers.h
|
||||
op_handlers/intern/wm_op_handlers_intern.h
|
||||
)
|
||||
|
||||
set(LIB
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
struct wmOpHandlers;
|
||||
|
||||
#include "op_handlers/wm_op_handlers.h"
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "WM_api.hh"
|
||||
#include "WM_message.hh"
|
||||
#include "WM_op_handlers.h"
|
||||
#include "WM_types.hh"
|
||||
#include "wm.hh"
|
||||
#include "wm_draw.hh"
|
||||
|
@ -217,6 +218,7 @@ static void window_manager_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
wm->undo_stack = nullptr;
|
||||
|
||||
wm->message_bus = nullptr;
|
||||
wm->op_handlers = nullptr;
|
||||
|
||||
wm->xr.runtime = nullptr;
|
||||
|
||||
|
@ -474,6 +476,10 @@ void WM_check(bContext *C)
|
|||
wm->message_bus = WM_msgbus_create();
|
||||
}
|
||||
|
||||
if (wm->op_handlers == NULL) {
|
||||
wm->op_handlers = WM_op_handlers_create();
|
||||
}
|
||||
|
||||
if (!G.background) {
|
||||
/* Case: file-read. */
|
||||
if ((wm->init_flag & WM_INIT_FLAG_WINDOW) == 0) {
|
||||
|
@ -574,6 +580,11 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm)
|
|||
WM_msgbus_destroy(wm->message_bus);
|
||||
}
|
||||
|
||||
if (wm->op_handlers != nullptr) {
|
||||
WM_op_handlers_destroy(wm->op_handlers);
|
||||
}
|
||||
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
BPY_callback_wm_free(wm);
|
||||
#endif
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
|
||||
#include "WM_api.hh"
|
||||
#include "WM_message.hh"
|
||||
#include "WM_op_handlers.h"
|
||||
#include "WM_toolsystem.hh"
|
||||
#include "WM_types.hh"
|
||||
|
||||
|
@ -1512,6 +1513,12 @@ static int wm_operator_invoke(bContext *C,
|
|||
return WM_operator_poll(C, ot);
|
||||
}
|
||||
|
||||
// Ensure any change is processed by poll
|
||||
if (WM_op_handlers_operator_pre_invoke(C, event, CTX_wm_op_handlers(C), ot, properties) ==
|
||||
false) {
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
if (WM_operator_poll(C, ot)) {
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
const intptr_t undo_id_prev = wm_operator_undo_active_id(wm);
|
||||
|
@ -1552,6 +1559,8 @@ static int wm_operator_invoke(bContext *C,
|
|||
retval = op->type->invoke(C, op, &event_temp);
|
||||
OPERATOR_RETVAL_CHECK(retval);
|
||||
|
||||
WM_op_handlers_operator_post_invoke(C, event, CTX_wm_op_handlers(C), ot, op->ptr, retval);
|
||||
|
||||
if (op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) {
|
||||
wm->op_undo_depth--;
|
||||
}
|
||||
|
@ -1564,6 +1573,8 @@ static int wm_operator_invoke(bContext *C,
|
|||
retval = op->type->exec(C, op);
|
||||
OPERATOR_RETVAL_CHECK(retval);
|
||||
|
||||
WM_op_handlers_operator_post_invoke(C, event, CTX_wm_op_handlers(C), ot, op->ptr, retval);
|
||||
|
||||
if (op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) {
|
||||
wm->op_undo_depth--;
|
||||
}
|
||||
|
@ -2478,9 +2489,20 @@ static eHandlerActionFlag wm_handler_operator_call(bContext *C,
|
|||
wm->op_undo_depth++;
|
||||
}
|
||||
|
||||
/* Warning, after this call all context data and 'event' may be freed. see check below. */
|
||||
retval = ot->modal(C, op, event);
|
||||
OPERATOR_RETVAL_CHECK(retval);
|
||||
if ( (WM_get_op_handlers(CTX_wm_op_handlers(C), ot->idname) != NULL) && !ot->poll(C)) {
|
||||
// Py Handler, changing poll conditions
|
||||
retval = OPERATOR_CANCELLED;
|
||||
}
|
||||
else {
|
||||
|
||||
/* Warning, after this call all context data and 'event' may be freed. see check below. */
|
||||
retval = ot->modal(C, op, event);
|
||||
OPERATOR_RETVAL_CHECK(retval);
|
||||
|
||||
if (WM_op_handlers_operator_modal(C, event, CTX_wm_op_handlers(C), ot, retval) == false) {
|
||||
retval = OPERATOR_CANCELLED;
|
||||
}
|
||||
}
|
||||
|
||||
if (ot->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) {
|
||||
wm->op_undo_depth--;
|
||||
|
@ -2494,7 +2516,10 @@ static eHandlerActionFlag wm_handler_operator_call(bContext *C,
|
|||
wm_event_modalkeymap_end(event, &event_backup);
|
||||
|
||||
if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) {
|
||||
wm_operator_reports(C, op, retval, false);
|
||||
|
||||
WM_op_handlers_operator_modal_end(C, nullptr, CTX_wm_op_handlers(C), ot, retval);
|
||||
|
||||
wm_operator_reports(C, op, retval, false);
|
||||
|
||||
wmOperator *op_test = handler->op->opm ? handler->op->opm : handler->op;
|
||||
if (op_test->type->modalkeymap) {
|
||||
|
@ -2526,6 +2551,9 @@ static eHandlerActionFlag wm_handler_operator_call(bContext *C,
|
|||
CTX_wm_area_set(C, area);
|
||||
CTX_wm_region_set(C, region);
|
||||
}
|
||||
else if (retval & OPERATOR_REPEAT) {
|
||||
wm_operator_invoke(C, ot, event, properties, NULL, false, true);
|
||||
}
|
||||
else {
|
||||
/* This special cases is for areas and regions that get removed. */
|
||||
CTX_wm_area_set(C, nullptr);
|
||||
|
|
|
@ -4113,6 +4113,7 @@ void wm_operatortypes_register()
|
|||
WM_operatortype_append(WM_OT_operator_defaults);
|
||||
WM_operatortype_append(WM_OT_splash);
|
||||
WM_operatortype_append(WM_OT_splash_about);
|
||||
WM_operatortype_append(WM_OT_splash_custom);
|
||||
WM_operatortype_append(WM_OT_search_menu);
|
||||
WM_operatortype_append(WM_OT_search_operator);
|
||||
WM_operatortype_append(WM_OT_search_single_menu);
|
||||
|
|
|
@ -49,6 +49,9 @@
|
|||
#include "WM_api.hh"
|
||||
#include "WM_types.hh"
|
||||
|
||||
#include "RNA_define.hh"
|
||||
#include "RNA_access.hh"
|
||||
|
||||
#include "wm.hh"
|
||||
|
||||
static void wm_block_close(bContext *C, void *arg_block, void * /*arg*/)
|
||||
|
@ -200,6 +203,10 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *region, void * /*ar
|
|||
BKE_blender_version_string(),
|
||||
splash_width - 8.0 * UI_SCALE_FAC,
|
||||
splash_height - 13.0 * UI_SCALE_FAC);
|
||||
wm_block_splash_add_label(block,
|
||||
"Tornavis Project",
|
||||
splash_width - 8.0 * UI_SCALE_FAC,
|
||||
splash_height - ((13.0 + 10) * UI_SCALE_FAC));
|
||||
}
|
||||
|
||||
const int layout_margin_x = UI_SCALE_FAC * 26;
|
||||
|
@ -336,3 +343,66 @@ void WM_OT_splash_about(wmOperatorType *ot)
|
|||
ot->invoke = wm_about_invoke;
|
||||
ot->poll = WM_operator_winactive;
|
||||
}
|
||||
|
||||
static uiBlock *wm_block_create_custom_splash(bContext *C, ARegion *region, void *arg) {
|
||||
|
||||
char *menutype_str = (char*) arg;
|
||||
|
||||
const uiStyle *style = UI_style_get_dpi();
|
||||
const int text_points_max = MAX2(style->widget.points, style->widgetlabel.points);
|
||||
const int dialog_width = text_points_max * 42 * UI_SCALE_FAC;
|
||||
|
||||
uiBlock *block = UI_block_begin(C, region, "about", UI_EMBOSS);
|
||||
|
||||
UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP);
|
||||
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
|
||||
|
||||
uiLayout *layout = UI_block_layout(
|
||||
block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, dialog_width, 0, 0, style);
|
||||
|
||||
uiLayout *col = uiLayoutColumn(layout, true);
|
||||
|
||||
MenuType *mt = WM_menutype_find(menutype_str, true);
|
||||
if (mt) {
|
||||
UI_menutype_draw(C, mt, col);
|
||||
} else {
|
||||
CLOG_ERROR(WM_LOG_OPERATORS, "cannot find WM menutype '%s'", menutype_str);
|
||||
}
|
||||
|
||||
UI_block_bounds_set_centered(block, 22 * UI_SCALE_FAC);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
static int wm_about_custom_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
char *menutype_str = MEM_cnew_array<char>(100, __func__);
|
||||
*menutype_str = '\0';
|
||||
|
||||
if (RNA_struct_property_is_set(op->ptr, "menutype")) {
|
||||
RNA_string_get(op->ptr, "menutype", menutype_str);
|
||||
}
|
||||
|
||||
UI_popup_block_invoke(C, wm_block_create_custom_splash, menutype_str, MEM_freeN);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int wm_about_custom_invoke(bContext *C, wmOperator *op , const wmEvent * /*event*/) {
|
||||
return op->type->exec(C, op);
|
||||
}
|
||||
|
||||
void WM_OT_splash_custom(wmOperatorType *ot)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
prop = RNA_def_string(ot->srna, "menutype", "MT_", 100, "", "MenuType class name");
|
||||
|
||||
ot->name = "Custom Splash";
|
||||
ot->idname = "WM_OT_splash_custom";
|
||||
ot->description = "Open a splash window with some custom information";
|
||||
|
||||
ot->exec = wm_about_custom_exec;
|
||||
ot->invoke = wm_about_custom_invoke;
|
||||
ot->poll = WM_operator_winactive;
|
||||
|
||||
}
|
||||
|
|
|
@ -525,6 +525,7 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win)
|
|||
|
||||
str += " - Blender ";
|
||||
str += BKE_blender_version_string_compact();
|
||||
str += " - Tornavis";
|
||||
|
||||
GHOST_SetTitle(handle, str.c_str());
|
||||
|
||||
|
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_windowmanager_types.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "WM_types.hh"
|
||||
|
||||
#include "op_handlers/intern/wm_op_handlers_intern.h"
|
||||
#include "op_handlers/wm_op_handlers.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/** \name Public API
|
||||
* \{ */
|
||||
|
||||
|
||||
|
||||
struct wmOpHandlers *WM_op_handlers_create(void)
|
||||
{
|
||||
|
||||
struct wmOpHandlers *op_handlers = (wmOpHandlers*) MEM_callocN(sizeof(*op_handlers), __func__);
|
||||
return op_handlers;
|
||||
}
|
||||
|
||||
void WM_op_handlers_destroy(struct wmOpHandlers *op_handlers)
|
||||
{
|
||||
LISTBASE_FOREACH (wmOpHandlerData *, opHandlers, &op_handlers->handlers ) {
|
||||
BLI_freelistN(&opHandlers->pre_invoke);
|
||||
BLI_freelistN(&opHandlers->post_invoke);
|
||||
BLI_freelistN(&opHandlers->modal);
|
||||
BLI_freelistN(&opHandlers->modal_end);
|
||||
}
|
||||
BLI_freelistN(&op_handlers->handlers);
|
||||
MEM_freeN(op_handlers);
|
||||
op_handlers = NULL;
|
||||
}
|
||||
|
||||
ListBase *WM_op_handlers_get_handler_list(wmOpHandlerData *opHandlers, int id)
|
||||
{
|
||||
ListBase *list = NULL;
|
||||
switch (id) {
|
||||
case HANDLER_TYPE_PRE_INVOKE:
|
||||
list = &opHandlers->pre_invoke;
|
||||
break;
|
||||
case HANDLER_TYPE_POST_INVOKE:
|
||||
list = &opHandlers->post_invoke;
|
||||
break;
|
||||
case HANDLER_TYPE_MODAL:
|
||||
list = &opHandlers->modal;
|
||||
break;
|
||||
case HANDLER_TYPE_MODAL_END:
|
||||
list = &opHandlers->modal_end;
|
||||
break;
|
||||
default:
|
||||
BLI_assert(false);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
wmOpHandlerData *WM_get_op_handlers(struct wmOpHandlers *op_handlers, const char *op_name)
|
||||
{
|
||||
return (wmOpHandlerData*) BLI_findstring(&op_handlers->handlers, op_name, offsetof(wmOpHandlerData, id_name));
|
||||
}
|
||||
|
||||
|
||||
void WM_op_handlers_append(struct wmOpHandlers *op_handlers,
|
||||
int id,
|
||||
void *py_handle,
|
||||
const char *op_name,
|
||||
bool (*cb)(struct bContext *, const struct wmEvent *event, void *, PointerRNA *properties, int),
|
||||
int (*check)(void *, void*, void*),
|
||||
bool (*poll)(struct bContext *, const struct wmEvent *event, void *, PointerRNA *properties),
|
||||
void *py_data)
|
||||
{
|
||||
wmOpHandlerData *opHandlers = WM_get_op_handlers(op_handlers, op_name);
|
||||
wmHandlerData *data = (wmHandlerData *)MEM_mallocN(sizeof(wmHandlerData), "wmHandlerData");
|
||||
|
||||
if (opHandlers == NULL) {
|
||||
// Create
|
||||
opHandlers = (wmOpHandlerData *) MEM_callocN(sizeof(wmOpHandlerData), "wmOpHandlerData");
|
||||
BLI_strncpy(opHandlers->id_name, op_name, OP_MAX_TYPENAME);
|
||||
BLI_addtail(&op_handlers->handlers, opHandlers);
|
||||
}
|
||||
|
||||
data->py_handle = py_handle;
|
||||
data->id_name = opHandlers->id_name;
|
||||
data->cb = cb;
|
||||
data->check = check;
|
||||
data->poll = poll;
|
||||
data->py_data = py_data;
|
||||
|
||||
ListBase *list = WM_op_handlers_get_handler_list(opHandlers, id);
|
||||
BLI_addtail(list, data);
|
||||
}
|
||||
|
||||
int WM_op_handlers_remove_all(struct wmOpHandlers *op_handlers, void *cb, void *owner)
|
||||
{
|
||||
int ret = 0;
|
||||
LISTBASE_FOREACH (wmOpHandlerData *, opHandlers, &op_handlers->handlers) {
|
||||
ret += WM_op_handlers_remove(op_handlers, HANDLER_TYPE_PRE_INVOKE, opHandlers->id_name, cb, owner);
|
||||
ret += WM_op_handlers_remove(op_handlers, HANDLER_TYPE_POST_INVOKE, opHandlers->id_name, cb, owner);
|
||||
ret += WM_op_handlers_remove(op_handlers, HANDLER_TYPE_MODAL, opHandlers->id_name, cb, owner);
|
||||
ret += WM_op_handlers_remove(op_handlers, HANDLER_TYPE_MODAL_END, opHandlers->id_name, cb, owner);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int WM_op_handlers_remove(
|
||||
struct wmOpHandlers *op_handlers, int id, const char *op_name, void *cb, void *owner)
|
||||
{
|
||||
int ret = 0;
|
||||
if (id == HANDLER_TYPE_ALL) {
|
||||
ret = WM_op_handlers_remove_all(op_handlers, cb, owner);
|
||||
}
|
||||
else {
|
||||
wmOpHandlerData *opHandlers = WM_get_op_handlers(op_handlers, op_name);
|
||||
|
||||
if (opHandlers != NULL) {
|
||||
ListBase *list = WM_op_handlers_get_handler_list(opHandlers, id);
|
||||
wmHandlerData *next;
|
||||
for (wmHandlerData *data = (wmHandlerData*) list->first; data; data = next) {
|
||||
next = data->next;
|
||||
if (data->check(data->py_data, owner, cb)) {
|
||||
BLI_freelinkN(list, data);
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool WM_op_handlers_operator_exec(struct bContext *C,
|
||||
const wmEvent *event,
|
||||
ListBase *list,
|
||||
struct wmOperatorType *ot,
|
||||
struct PointerRNA *properties,
|
||||
int retval)
|
||||
{
|
||||
bool ret = true;
|
||||
LISTBASE_FOREACH (wmHandlerData *, data, list) {
|
||||
if (data->poll == nullptr || data->poll(C, event, data->py_data, properties)) {
|
||||
ret = ret && data->cb(C, event, data->py_data, properties, retval);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// Previous to invoke
|
||||
bool WM_op_handlers_operator_pre_invoke(struct bContext *C,
|
||||
const wmEvent *event,
|
||||
struct wmOpHandlers *op_handlers,
|
||||
struct wmOperatorType *ot,
|
||||
PointerRNA *properties)
|
||||
{
|
||||
bool ret = true;
|
||||
if (op_handlers != NULL) {
|
||||
wmOpHandlerData *opHandlers = WM_get_op_handlers(op_handlers, ot->idname);
|
||||
if (opHandlers != NULL) {
|
||||
ListBase *list = WM_op_handlers_get_handler_list(opHandlers, HANDLER_TYPE_PRE_INVOKE);
|
||||
ret = ret && WM_op_handlers_operator_exec(C, event, list, ot, properties, 0);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// Post To invoke
|
||||
void WM_op_handlers_operator_post_invoke(struct bContext *C,
|
||||
const wmEvent *event,
|
||||
struct wmOpHandlers *op_handlers,
|
||||
struct wmOperatorType *ot,
|
||||
struct PointerRNA *properties,
|
||||
int retval)
|
||||
{
|
||||
if (op_handlers != NULL) {
|
||||
wmOpHandlerData *opHandlers = WM_get_op_handlers(op_handlers, ot->idname);
|
||||
if (opHandlers != NULL) {
|
||||
ListBase *list = WM_op_handlers_get_handler_list(opHandlers, HANDLER_TYPE_POST_INVOKE);
|
||||
WM_op_handlers_operator_exec(C, event, list, ot, properties, retval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool WM_op_handlers_operator_modal(struct bContext *C,
|
||||
const wmEvent *event,
|
||||
struct wmOpHandlers *op_handlers,
|
||||
struct wmOperatorType *ot,
|
||||
int retval
|
||||
)
|
||||
{
|
||||
bool ret = true;
|
||||
if (op_handlers != NULL) {
|
||||
wmOpHandlerData *opHandlers = WM_get_op_handlers(op_handlers, ot->idname);
|
||||
if (opHandlers != NULL) {
|
||||
ListBase *list = WM_op_handlers_get_handler_list(opHandlers, HANDLER_TYPE_MODAL);
|
||||
ret = ret && WM_op_handlers_operator_exec(C, event, list, ot, NULL, retval);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void WM_op_handlers_operator_modal_end(struct bContext *C,
|
||||
const wmEvent *event,
|
||||
struct wmOpHandlers *op_handlers,
|
||||
struct wmOperatorType *ot,
|
||||
int retval)
|
||||
{
|
||||
if (op_handlers != NULL) {
|
||||
wmOpHandlerData *opHandlers = WM_get_op_handlers(op_handlers, ot->idname);
|
||||
if (opHandlers != NULL) {
|
||||
ListBase *list = WM_op_handlers_get_handler_list(opHandlers, HANDLER_TYPE_MODAL_END);
|
||||
WM_op_handlers_operator_exec(C, event, list, ot, NULL, retval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** \} */
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../wm_op_handlers.h"
|
||||
|
||||
|
||||
typedef struct wmHandlerData {
|
||||
struct wmHandlerData *next, *prev;
|
||||
char *id_name; // Pointer to wmOpHandlerData.id_name
|
||||
void *py_handle;
|
||||
void *py_data;
|
||||
bool (*cb)(struct bContext *, const wmEvent *event, void *, PointerRNA *properties, int); // callback
|
||||
int (*check)(void *, void*, void*);
|
||||
bool (*poll)(struct bContext *, const wmEvent *event, void *, PointerRNA *properties);
|
||||
} wmHandlerData;
|
||||
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "RNA_types.hh"
|
||||
|
||||
#define HANDLER_TYPE_ALL 0
|
||||
#define HANDLER_TYPE_PRE_INVOKE 1
|
||||
#define HANDLER_TYPE_POST_INVOKE 2
|
||||
#define HANDLER_TYPE_MODAL 3
|
||||
#define HANDLER_TYPE_MODAL_END 4
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct wmOpHandlers {
|
||||
/** Handlers in order of being added. */
|
||||
ListBase handlers;
|
||||
};
|
||||
|
||||
|
||||
typedef struct wmOpHandlerData {
|
||||
struct wmOpHandlerData *next, *prev;
|
||||
char id_name[OP_MAX_TYPENAME];
|
||||
/** Handlers in order of being added. */
|
||||
ListBase pre_invoke;
|
||||
ListBase post_invoke;
|
||||
ListBase modal;
|
||||
ListBase modal_end;
|
||||
} wmOpHandlerData;
|
||||
|
||||
|
||||
struct wmOpHandlers *WM_op_handlers_create(void);
|
||||
void WM_op_handlers_destroy(struct wmOpHandlers *opHandlers);
|
||||
|
||||
wmOpHandlerData *WM_get_op_handlers(struct wmOpHandlers *op_handlers, const char *op_name);
|
||||
|
||||
void WM_op_handlers_append(struct wmOpHandlers *op_handlers, int id,
|
||||
void *handle,
|
||||
const char *op_name,
|
||||
bool (*cb)(struct bContext *, const struct wmEvent *event, void *, PointerRNA *properties, int),
|
||||
int (*check)(void *, void*, void *),
|
||||
bool (*poll)(struct bContext *, const struct wmEvent *event, void *, PointerRNA *properties),
|
||||
void *py_data);
|
||||
|
||||
int WM_op_handlers_remove(struct wmOpHandlers *op_handlers,
|
||||
int id,
|
||||
const char *op_name,
|
||||
void *cb,
|
||||
void *owner);
|
||||
|
||||
|
||||
bool WM_op_handlers_operator_pre_invoke(struct bContext *C,
|
||||
const struct wmEvent *event,
|
||||
struct wmOpHandlers *op_handlers,
|
||||
struct wmOperatorType *ot,
|
||||
PointerRNA *properties);
|
||||
void WM_op_handlers_operator_post_invoke(struct bContext *C,
|
||||
const struct wmEvent *event,
|
||||
struct wmOpHandlers *op_handlers,
|
||||
struct wmOperatorType *ot,
|
||||
PointerRNA *properties, int retval);
|
||||
|
||||
|
||||
bool WM_op_handlers_operator_modal(struct bContext *C,
|
||||
const struct wmEvent *event,
|
||||
struct wmOpHandlers *op_handlers,
|
||||
struct wmOperatorType *ot, int retval);
|
||||
|
||||
|
||||
void WM_op_handlers_operator_modal_end(struct bContext *C,
|
||||
const struct wmEvent *event,
|
||||
struct wmOpHandlers *op_handlers,
|
||||
struct wmOperatorType *ot,
|
||||
int retval);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -98,6 +98,7 @@ void wm_autosave_delete();
|
|||
|
||||
void WM_OT_splash(wmOperatorType *ot);
|
||||
void WM_OT_splash_about(wmOperatorType *ot);
|
||||
void WM_OT_splash_custom(wmOperatorType *ot);
|
||||
|
||||
/* `wm_stereo.cc` */
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ set(INC
|
|||
../blender/makesrna
|
||||
../blender/render
|
||||
../blender/windowmanager
|
||||
../blender/tornavis
|
||||
)
|
||||
|
||||
set(LIB
|
||||
|
@ -21,6 +22,7 @@ set(LIB
|
|||
PRIVATE bf::intern::clog
|
||||
PRIVATE bf::intern::guardedalloc
|
||||
bf_windowmanager
|
||||
tornavis
|
||||
)
|
||||
|
||||
if(HAVE_FEENABLEEXCEPT)
|
||||
|
@ -477,6 +479,13 @@ install(
|
|||
DESTINATION ${TARGETDIR_VER}/datafiles
|
||||
)
|
||||
|
||||
#tornavis
|
||||
install(
|
||||
DIRECTORY ${CMAKE_SOURCE_DIR}/release/datafiles/tornavis
|
||||
DESTINATION ${TARGETDIR_VER}/datafiles
|
||||
)
|
||||
|
||||
|
||||
# localization
|
||||
if(WITH_INTERNATIONAL)
|
||||
set(_locale_dir "${CMAKE_SOURCE_DIR}/locale")
|
||||
|
|
|
@ -51,6 +51,8 @@
|
|||
#include "BKE_vfont.hh"
|
||||
#include "BKE_volume.hh"
|
||||
|
||||
#include "MB_tornavis.h"
|
||||
|
||||
#ifndef WITH_PYTHON_MODULE
|
||||
# include "BLI_args.h"
|
||||
#endif
|
||||
|
@ -467,6 +469,8 @@ int main(int argc,
|
|||
/* After parsing number of threads argument. */
|
||||
BLI_task_scheduler_init();
|
||||
|
||||
MB_init();
|
||||
|
||||
#ifndef WITH_PYTHON_MODULE
|
||||
/* The settings pass includes:
|
||||
* - Background-mode assignment (#Global.background), checked by other subsystems
|
||||
|
|
|
@ -47,6 +47,8 @@
|
|||
|
||||
# include "GPU_context.h"
|
||||
|
||||
# include "MB_tornavis.h"
|
||||
|
||||
# ifdef WITH_FFMPEG
|
||||
# include "IMB_imbuf.hh"
|
||||
# endif
|
||||
|
@ -1479,6 +1481,16 @@ static int arg_handle_start_with_console(int /*argc*/, const char ** /*argv*/, v
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const char arg_handle_tornavis_info_doc[] =
|
||||
"\n\t"
|
||||
"Shows Tornavis project info on loading.";
|
||||
static int arg_handle_tornavis_info(int /*argc*/, const char ** /*argv*/, void * /*data*/)
|
||||
{
|
||||
MB_print_info();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char arg_handle_register_extension_doc[] =
|
||||
"\n\t"
|
||||
"Register blend-file extension for current user, then exit (Windows only).";
|
||||
|
@ -2523,6 +2535,8 @@ void main_args_setup(bContext *C, bArgs *ba, bool all)
|
|||
|
||||
BLI_args_add(ba, nullptr, "--open-last", CB(arg_handle_load_last_file), C);
|
||||
|
||||
BLI_args_add(ba, nullptr, "--tornavis-info", CB(arg_handle_tornavis_info), nullptr);
|
||||
|
||||
# undef CB
|
||||
# undef CB_EX
|
||||
# undef CB_ALL
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
names = []
|
Loading…
Reference in New Issue