WIP: Brush assets project #106303

Draft
Julian Eisel wants to merge 351 commits from brush-assets-project into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
363 changed files with 2653 additions and 846 deletions
Showing only changes of commit ea5b3310f9 - Show all commits

View File

@ -9,13 +9,13 @@ body:
attributes:
value: |
### Instructions
First time reporting? See [tips](https://wiki.blender.org/wiki/Process/Bug_Reports).
First time reporting? See [tips](https://developer.blender.org/docs/handbook/bug_reports/making_good_bug_reports/).
* Use **Help > Report a Bug** in Blender to fill system information and exact Blender version.
* Test [daily builds](https://builder.blender.org/) to verify if the issue is already fixed.
* Test [previous versions](https://download.blender.org/release/) to find an older working version.
* For feature requests, feedback, questions or build issues, see [communication channels](https://wiki.blender.org/wiki/Communication/Contact#User_Feedback_and_Requests).
* Security vulnerabilities should be [reported privately](https://wiki.blender.org/wiki/Process/Vulnerability_Reports).
* For feature requests, feedback, questions or build issues, see [communication channels](https://developer.blender.org/docs/handbook/communication/user_feedback/).
* Security vulnerabilities should be [reported privately](https://developer.blender.org/docs/handbook/bug_reports/vulnerability_reports/).
* If there are multiple bugs, make multiple bug reports.
- type: textarea

View File

@ -6,7 +6,7 @@ body:
value: |
### Instructions
Guides to [contributing code](https://wiki.blender.org/index.php/Dev:Doc/Process/Contributing_Code) and effective [code review](https://wiki.blender.org/index.php/Dev:Doc/Tools/Code_Review).
Guides to [contributing code](https://developer.blender.org/docs/handbook/contributing/) and effective [code review](https://developer.blender.org/docs/handbook/contributing/pull_requests/).
By submitting code here, you agree that the code is (compatible with) GNU GPL v2 or later.

View File

@ -1,4 +1,4 @@
This repository is only used as a mirror. Blender development happens on projects.blender.org.
To get started with contributing code, please see:
https://wiki.blender.org/wiki/Process/Contributing_Code
https://developer.blender.org/docs/handbook/contributing/

2
.github/stale.yml vendored
View File

@ -18,4 +18,4 @@ closeComment: >
used as a mirror. Blender development happens on projects.blender.org.
To get started contributing code, please read:
https://wiki.blender.org/wiki/Process/Contributing_Code
https://developer.blender.org/docs/handbook/contributing/

View File

@ -110,7 +110,7 @@ enable_testing()
# -----------------------------------------------------------------------------
# Test Compiler Support
#
# Keep in sync with: https://wiki.blender.org/wiki/Building_Blender
# Keep in sync with: https://developer.blender.org/docs/handbook/building_blender/
if(CMAKE_COMPILER_IS_GNUCC)
if("${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "11.0.0")

View File

@ -76,7 +76,7 @@ Documentation Checking
* check_wiki_file_structure:
Check the WIKI documentation for the source-tree's file structure
matches Blender's source-code.
See: https://wiki.blender.org/wiki/Source/File_Structure
See: https://developer.blender.org/docs/features/code_layout/
Spell Checkers
This runs the spell checker from the developer tools repositor.

View File

@ -23,10 +23,10 @@ Project Pages
Development
-----------
- [Build Instructions](https://wiki.blender.org/wiki/Building_Blender)
- [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://wiki.blender.org)
- [Developer Documentation](https://developer.blender.org/docs/)
License

View File

@ -1714,7 +1714,7 @@ def argparse_create():
"NOTE: To build with system package libraries instead of the precompiled ones when both are available,\n"
"the `WITH_LIBS_PRECOMPILED` option must be disabled in CMake.\n"
"\n"
"See https://wiki.blender.org/wiki/Building_Blender for more details.\n"
"See https://developer.blender.org/docs/handbook/building_blender/ for more details.\n"
"\n"
)

View File

@ -4,7 +4,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# This script is part of the official build environment, see wiki page for details.
# https://wiki.blender.org/wiki/Building_Blender/Other/Rocky8ReleaseEnvironment
# https://developer.blender.org/docs/handbook/release_process/build/rocky_8/
set -e

View File

@ -7,7 +7,7 @@
# assumes you have dependencies installed already
# See this page for more info:
# https://wiki.blender.org/wiki/Building_Blender/Linux/Generic_Distro/CMake
# https://developer.blender.org/docs/handbook/building_blender/linux/
# grab blender
mkdir ~/blender-git

View File

@ -12,7 +12,7 @@
*
* \subsection implinks Important Links
* - <a href="https://developer.blender.org">developer.blender.org</a> with bug tracker.
* - <a href="https://wiki.blender.org">Development documents</a> on our wiki.
* - <a href="https://developer.blender.org/docs/">Development documentation</a>.
*
* \subsection blother Other
* For more information on using Blender browse to https://www.blender.org

View File

@ -23,8 +23,8 @@ Then, call ``bpy.app.translations.register(__name__, your_dict)`` in your ``regi
The ``Manage UI translations`` add-on has several functions to help you collect strings to translate, and
generate the needed python code (the translation dictionary), as well as optional intermediary po files
if you want some... See
`How to Translate Blender <https://wiki.blender.org/wiki/Process/Translate_Blender>`_ and
`Using i18n in Blender Code <https://wiki.blender.org/wiki/Source/Interface/Internationalization>`_
`How to Translate Blender <https://developer.blender.org/docs/handbook/translating/translator_guide/>`_ and
`Using i18n in Blender Code <https://developer.blender.org/docs/handbook/translating/developer_guide/>`_
for more info.
Module References
@ -35,7 +35,7 @@ Module References
import bpy
# This block can be automatically generated by UI translations addon, which also handles conversion with PO format.
# See also https://wiki.blender.org/wiki/Process/Translate_Blender#Translating_non-official_addons
# See also https://developer.blender.org/docs/handbook/translating/translator_guide/#translating-non-official-add-ons
# It can (should) also be put in a different, specific py file.
# ##### BEGIN AUTOGENERATED I18N SECTION #####

View File

@ -14,7 +14,7 @@ The features exposed closely follow the C API,
giving Python access to the functions used by Blender's own mesh editing tools.
For an overview of BMesh data types and how they reference each other see:
`BMesh Design Document <https://wiki.blender.org/index.php/Dev:Source/Modeling/BMesh/Design>`__.
`BMesh Design Document <https://developer.blender.org/docs/features/objects/mesh/bmesh/>`__.
.. note::

View File

@ -13,7 +13,7 @@ allowing ``import bpy`` to be added to any Python script, providing access to Bl
- A pre-compiled ``bpy`` module is
`available via PIP <https://pypi.org/project/bpy/>`__.
- Or you may compile this yourself using the
`build instructions <https://wiki.blender.org/w/index.php?title=Building_Blender/Other/BlenderAsPyModule>`__.
`build instructions <https://developer.blender.org/docs/handbook/building_blender/python_module/>`__.
Use Cases

View File

@ -91,7 +91,7 @@ They are only loaded on startup if selected from the user preferences.
The only difference between add-ons and built-in Python modules is that add-ons must contain a ``bl_info`` variable
which Blender uses to read metadata such as name, author, category and project link.
The User Preferences add-on listing uses ``bl_info`` to display information about each add-on.
`See Add-ons <https://wiki.blender.org/index.php/Dev:Py/Scripts/Guidelines/Addons>`__
`See Add-ons <https://developer.blender.org/docs/handbook/addons/guidelines/>`__
for details on the ``bl_info`` dictionary.

View File

@ -295,7 +295,7 @@ Advantages include:
This is marked advanced because to run Blender as a Python module requires a special build option.
For instructions on building see
`Building Blender as a Python module <https://wiki.blender.org/wiki/Building_Blender/Other/BlenderAsPyModule>`__.
`Building Blender as a Python module <https://developer.blender.org/docs/handbook/building_blender/python_module/>`__.
Python Safety (Build Option)

View File

@ -302,8 +302,8 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id)
break;
case 0x256F: /* 3Dconnexion. */
switch (product_id) {
case 0xC62E: /* Plugged in. */
case 0xC62F: /* Wireless. */
case 0xC62E: /* SpaceMouse Wireless (cabled). */
case 0xC62F: /* SpaceMouse Wireless Receiver. */
case 0xC658: /* Wireless (3DConnexion Universal Wireless Receiver in WIN32), see #82412. */
{
device_type_ = NDOF_SpaceMouseWireless;
@ -311,8 +311,11 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id)
hid_map_ = ndof_HID_map_Modern3Dx;
break;
}
case 0xC631: /* Plugged in. */
case 0xC632: /* Wireless. */
case 0xC631: /* SpaceMouse Pro Wireless (cabled). */
case 0xC632: /* SpaceMouse Pro Wireless Receiver. */
case 0xC638: /* SpaceMouse Pro Wireless BT (cabled), see #116393.
* 3Dconnexion docs describe this as "Wireless BT", but it is cabled. */
case 0xC652: /* Universal Receiver. */
{
device_type_ = NDOF_SpaceMouseProWireless;
hid_map_button_num_ = 27; /* 15 physical buttons, but HID codes range from 0 to 26. */

View File

@ -26,7 +26,7 @@
<url type="faq">https://www.blender.org/support/faq/</url>
<url type="help">https://www.blender.org/support/</url>
<url type="donation">https://fund.blender.org/</url>
<url type="translate">https://wiki.blender.org/wiki/Process/Translate_Blender</url>
<url type="translate">https://developer.blender.org/docs/handbook/translating/translator_guide/</url>
<url type="vcs-browser">https://projects.blender.org/blender/blender</url>
<url type="contribute">https://www.blender.org/get-involved/</url>
<screenshots>

View File

@ -43,7 +43,7 @@
<p class="p4">
The Blender Foundation and online developer community is proud to present Blender
@BLENDER_VERSION@.
<a href="https://wiki.blender.org/wiki/Reference/Release_Notes/@BLENDER_VERSION@">
<a href="https://developer.blender.org/docs/release_notes/@BLENDER_VERSION@">
<span class="s1">More information about this release</span>
</a>.
</p>
@ -95,8 +95,8 @@
<span class="s4">www.blender.org</span>
</a><br>
Release Notes
<a href="https://wiki.blender.org/wiki/Reference/Release_Notes/@BLENDER_VERSION@">
<span class="s4">wiki.blender.org/wiki/Reference/Release_Notes/@BLENDER_VERSION@</span>
<a href="https://developer.blender.org/docs/release_notes/@BLENDER_VERSION@">
<span class="s4">https://developer.blender.org/docs/release_notes/@BLENDER_VERSION@</span>
</a><br>
Tutorials
<a href="https://www.blender.org/support/tutorials/">

View File

@ -612,7 +612,10 @@ class _ext_global:
# Store a map of `preferences.filepaths.extension_repos` -> `module_id`.
# Only needed to detect renaming between `bpy.app.handlers.extension_repos_update_{pre & post}` events.
idmap = {}
#
# The first dictionary is for enabled repositories, the second for disabled repositories
# which can be ignored in most cases and is only needed for a module rename.
idmap_pair = {}, {}
# The base package created by `JunctionModuleHandle`.
module_handle = None
@ -624,12 +627,14 @@ _ext_base_pkg_idname = "bl_ext"
def _extension_preferences_idmap():
repos_idmap = {}
repos_idmap_disabled = {}
if _preferences.experimental.use_extension_repos:
for repo in _preferences.filepaths.extension_repos:
if not repo.enabled:
continue
repos_idmap[repo.as_pointer()] = repo.module
return repos_idmap
if repo.enabled:
repos_idmap[repo.as_pointer()] = repo.module
else:
repos_idmap_disabled[repo.as_pointer()] = repo.module
return repos_idmap, repos_idmap_disabled
def _extension_dirpath_from_preferences():
@ -654,24 +659,161 @@ def _extension_dirpath_from_handle():
repos_info[module_id] = dirpath
return repos_info
# Ensure the add-ons follow changes to repositories, enabling, disabling and module renaming.
def _initialize_extension_repos_post_addons_prepare(
module_handle,
*,
submodules_del,
submodules_add,
submodules_rename_module,
submodules_del_disabled,
submodules_rename_module_disabled,
):
addons_to_enable = []
if not (
submodules_del or
submodules_add or
submodules_rename_module or
submodules_del_disabled or
submodules_rename_module_disabled
):
return addons_to_enable
# All preferences info.
# Map: `repo_id -> {submodule_id -> addon, ...}`.
addon_userdef_info = {}
module_prefix = _ext_base_pkg_idname + "."
for addon in _preferences.addons:
module = addon.module
if not module.startswith(module_prefix):
continue
module_id, submodule_id = module[len(module_prefix):].partition(".")[0::2]
try:
addon_userdef_info[module_id][submodule_id] = addon
except KeyError:
addon_userdef_info[module_id] = {submodule_id: addon}
# All run-time info.
# Map: `module_id -> {submodule_id -> module, ...}`.
addon_runtime_info = {}
for module_id, repo_module in module_handle.submodule_items():
extensions_info = {}
for submodule_id in dir(repo_module):
if submodule_id.startswith("_"):
continue
mod = getattr(repo_module, submodule_id)
# Filter out non add-on, non-modules.
if not hasattr(mod, "__addon_enabled__"):
continue
extensions_info[submodule_id] = mod
addon_runtime_info[module_id] = extensions_info
del extensions_info
# Apply changes to add-ons.
if submodules_add:
# Re-enable add-ons that exist in the user preferences,
# this lets the add-ons state be restored when toggling a repository.
for module_id, _dirpath in submodules_add:
repo_userdef = addon_userdef_info.get(module_id, {})
repo_runtime = addon_runtime_info.get(module_id, {})
for submodule_id, addon in repo_userdef.items():
module_name_next = "%s.%s.%s" % (_ext_base_pkg_idname, module_id, submodule_id)
# Only default & persistent add-ons are kept for re-activation.
default_set = True
persistent = True
addons_to_enable.append((module_name_next, addon, default_set, persistent))
for module_id_prev, module_id_next in submodules_rename_module:
repo_userdef = addon_userdef_info.get(module_id_prev, {})
repo_runtime = addon_runtime_info.get(module_id_prev, {})
for submodule_id, mod in repo_runtime.items():
if not getattr(mod, "__addon_enabled__", False):
continue
module_name_prev = "%s.%s.%s" % (_ext_base_pkg_idname, module_id_prev, submodule_id)
module_name_next = "%s.%s.%s" % (_ext_base_pkg_idname, module_id_next, submodule_id)
disable(module_name_prev, default_set=False)
addon = repo_userdef.get(submodule_id)
default_set = addon is not None
persistent = getattr(mod, "__addon_persistent__", False)
addons_to_enable.append((module_name_next, addon, default_set, persistent))
for module_id_prev, module_id_next in submodules_rename_module_disabled:
repo_userdef = addon_userdef_info.get(module_id_prev, {})
repo_runtime = addon_runtime_info.get(module_id_prev, {})
for submodule_id, addon in repo_userdef.items():
mod = repo_runtime.get(submodule_id)
if mod is not None and getattr(mod, "__addon_enabled__", False):
continue
# Either there is no run-time data or the module wasn't enabled.
# Rename the add-on without enabling it so the next time it's enabled it's preferences are kept.
module_name_next = "%s.%s.%s" % (_ext_base_pkg_idname, module_id_next, submodule_id)
addon.module = module_name_next
if submodules_del:
repo_module_map = {repo.module: repo for repo in _preferences.filepaths.extension_repos}
for module_id in submodules_del:
repo_userdef = addon_userdef_info.get(module_id, {})
repo_runtime = addon_runtime_info.get(module_id, {})
repo = repo_module_map.get(module_id)
default_set = True
if repo and not repo.enabled:
# The repository exists but has been disabled, keep the add-on preferences
# because the user may want to re-enable the repository temporarily.
default_set = False
for submodule_id, mod in repo_runtime.items():
module_name_prev = "%s.%s.%s" % (_ext_base_pkg_idname, module_id, submodule_id)
disable(module_name_prev, default_set=default_set)
del repo
del repo_module_map
if submodules_del_disabled:
for module_id_prev in submodules_del_disabled:
repo_userdef = addon_userdef_info.get(module_id_prev, {})
for submodule_id in repo_userdef.keys():
module_name_prev = "%s.%s.%s" % (_ext_base_pkg_idname, module_id_prev, submodule_id)
disable(module_name_prev, default_set=True)
return addons_to_enable
# Enable add-ons after the modules have been manipulated.
def _initialize_extension_repos_post_addons_restore(addons_to_enable):
if not addons_to_enable:
return
for (module_name_next, addon, default_set, persistent) in addons_to_enable:
# Ensure the preferences are kept.
if addon is not None:
addon.module = module_name_next
enable(module_name_next, default_set=default_set, persistent=persistent)
# Needed for module rename.
modules._is_first = True
# Use `bpy.app.handlers.extension_repos_update_{pre/post}` to track changes to extension repositories
# and sync the changes to the Python module.
@_bpy.app.handlers.persistent
def _initialize_extension_repos_pre(*_):
_ext_global.idmap = _extension_preferences_idmap()
_ext_global.idmap_pair = _extension_preferences_idmap()
@_bpy.app.handlers.persistent
def _initialize_extension_repos_post(*_):
def _initialize_extension_repos_post(*_, is_first=False):
do_addons = not is_first
# Map `module_id` -> `dirpath`.
repos_info_prev = _extension_dirpath_from_handle()
repos_info_next = _extension_dirpath_from_preferences()
# Map `repo.as_pointer()` -> `module_id`.
repos_idmap_prev = _ext_global.idmap
repos_idmap_next = _extension_preferences_idmap()
repos_idmap_prev, repos_idmap_prev_disabled = _ext_global.idmap_pair
repos_idmap_next, repos_idmap_next_disabled = _extension_preferences_idmap()
# Map `module_id` -> `repo.as_pointer()`.
repos_idmap_next_reverse = {value: key for key, value in repos_idmap_next.items()}
@ -690,10 +832,6 @@ def _initialize_extension_repos_post(*_):
if module_id_prev not in repos_info_prev:
del repos_idmap_prev[repo_id_prev]
# NOTE(@ideasman42): supporting renaming at all is something we might limit to extensions
# which have no add-ons loaded as supporting renaming add-ons in-place seems error prone as the add-on
# may define internal variables based on the full package path.
submodules_add = [] # List of module names to add: `(module_id, dirpath)`.
submodules_del = [] # List of module names to remove: `module_id`.
submodules_rename_module = [] # List of module names: `(module_id_src, module_id_dst)`.
@ -732,7 +870,38 @@ def _initialize_extension_repos_post(*_):
if (module_id not in repos_info_next) and (module_id not in renamed_prev):
submodules_del.append(module_id)
# Apply changes to the `_ext_base_pkg_idname` named module so it matches extension data from the preferences.
if do_addons:
submodules_del_disabled = [] # A version of `submodules_del` for disabled repositories.
submodules_rename_module_disabled = [] # A version of `submodules_rename_module` for disabled repositories.
# Detect deleted modules.
for repo_id_prev, module_id_prev in repos_idmap_prev_disabled.items():
if (
(repo_id_prev not in repos_idmap_next_disabled) and
(repo_id_prev not in repos_idmap_next)
):
submodules_del_disabled.append(module_id_prev)
# Detect rename of disabled modules.
for repo_id_next, module_id_next in repos_idmap_next_disabled.items():
module_id_prev = repos_idmap_prev_disabled.get(repo_id_next)
if module_id_prev is None:
continue
# Detect rename.
if module_id_next != module_id_prev:
submodules_rename_module_disabled.append((module_id_prev, module_id_next))
addons_to_enable = _initialize_extension_repos_post_addons_prepare(
_ext_global.module_handle,
submodules_del=submodules_del,
submodules_add=submodules_add,
submodules_rename_module=submodules_rename_module,
submodules_del_disabled=submodules_del_disabled,
submodules_rename_module_disabled=submodules_rename_module_disabled,
)
del submodules_del_disabled, submodules_rename_module_disabled
# Apply changes to the `_ext_base_pkg_idname` named module so it matches extension data from the preferences.
module_handle = _ext_global.module_handle
for module_id in submodules_del:
module_handle.unregister_submodule(module_id)
@ -743,7 +912,11 @@ def _initialize_extension_repos_post(*_):
for module_id, dirpath in submodules_rename_dirpath:
module_handle.rename_directory(module_id, dirpath)
_ext_global.idmap.clear()
_ext_global.idmap_pair[0].clear()
_ext_global.idmap_pair[1].clear()
if do_addons:
_initialize_extension_repos_post_addons_restore(addons_to_enable)
# Force refreshing if directory paths change.
if submodules_del or submodules_add or submodules_rename_dirpath:
@ -759,7 +932,7 @@ def _initialize_extensions_repos_once():
# Setup repositories for the first time.
# Intentionally don't call `_initialize_extension_repos_pre` as this is the first time,
# the previous state is not useful to read.
_initialize_extension_repos_post()
_initialize_extension_repos_post(is_first=True)
# Internal handlers intended for Blender's own handling of repositories.
_bpy.app.handlers._extension_repos_update_pre.append(_initialize_extension_repos_pre)

View File

@ -6,7 +6,7 @@
# XXX: This script is meant to be used from inside Blender!
# You should not directly use this script, rather use update_msg.py!
import datetime
import time
import os
import re
import sys
@ -1011,10 +1011,9 @@ def dump_addon_bl_info(msgs, reports, module, settings):
def dump_messages(do_messages, do_checks, settings):
bl_ver = "Blender " + bpy.app.version_string
bl_hash = bpy.app.build_hash
bl_date = datetime.datetime.strptime(bpy.app.build_date.decode() + "T" + bpy.app.build_time.decode(),
"%Y-%m-%dT%H:%M:%S")
pot = utils.I18nMessages.gen_empty_messages(settings.PARSER_TEMPLATE_ID, bl_ver, bl_hash, bl_date, bl_date.year,
settings=settings)
bl_time = time.strptime(f"{bpy.app.build_date.decode()} {bpy.app.build_time.decode()} UTC", "%Y-%m-%d %H:%M:%S %Z")
pot = utils.I18nMessages.gen_empty_messages(
settings.PARSER_TEMPLATE_ID, bl_ver, bl_hash, bl_time, settings=settings)
msgs = pot.msgs
# Enable all wanted addons.
@ -1113,13 +1112,12 @@ def dump_addon_messages(module_name, do_checks, settings):
addon_info = addon_utils.module_bl_info(addon)
ver = addon_info["name"] + " " + ".".join(str(v) for v in addon_info["version"])
rev = 0
date = datetime.datetime.now()
pot = utils.I18nMessages.gen_empty_messages(settings.PARSER_TEMPLATE_ID, ver, rev, date, date.year,
settings=settings)
curr_time = time.gmtime()
pot = utils.I18nMessages.gen_empty_messages(settings.PARSER_TEMPLATE_ID, ver, rev, curr_time, settings=settings)
msgs = pot.msgs
minus_pot = utils.I18nMessages.gen_empty_messages(settings.PARSER_TEMPLATE_ID, ver, rev, date, date.year,
settings=settings)
minus_pot = utils.I18nMessages.gen_empty_messages(
settings.PARSER_TEMPLATE_ID, ver, rev, curr_time, settings=settings)
minus_msgs = minus_pot.msgs
check_ctxt = _gen_check_ctxt(settings) if do_checks else None

View File

@ -9,7 +9,7 @@ import os
import re
import struct
import tempfile
# import time
import time
from bl_i18n_utils import (
settings,
@ -478,13 +478,17 @@ class I18nMessages:
return getattr(collections, "OrderedDict", dict)()
@classmethod
def gen_empty_messages(cls, uid, blender_ver, blender_hash, time, year, default_copyright=True, settings=settings):
def gen_empty_messages(cls, uid, blender_ver, blender_hash, bl_time, default_copyright=True, settings=settings):
"""Generate an empty I18nMessages object (only header is present!)."""
fmt = settings.PO_HEADER_MSGSTR
msgstr = fmt.format(blender_ver=str(blender_ver), blender_hash=blender_hash, time=str(time), uid=str(uid))
msgstr = fmt.format(
blender_ver=str(blender_ver),
blender_hash=blender_hash,
time=time.strftime("%Y-%m-%d %H:%M%z", bl_time),
uid=str(uid))
comment = ""
if default_copyright:
comment = settings.PO_HEADER_COMMENT_COPYRIGHT.format(year=str(year))
comment = settings.PO_HEADER_COMMENT_COPYRIGHT.format(year=str(time.gmtime().tm_year))
comment = comment + settings.PO_HEADER_COMMENT
msgs = cls(uid=uid, settings=settings)

View File

@ -425,8 +425,8 @@ def do_previews(do_objects, do_collections, do_scenes, do_data_intern):
try:
bpy.ops.wm.save_mainfile()
except BaseException as ex:
# Might fail in some odd cases, like e.g. in regression files we have glsl/ram_glsl.blend which
# references an inexistent texture... Better not break in this case, just spit error to console.
# Might fail in some odd cases, like e.g. in regression files we have `glsl/ram_glsl.blend` which
# references an nonexistent texture. Better not break in this case, just spit error to console.
print("ERROR:", ex)
else:
print("*NOT* Saving %s, because some error(s) happened while deleting temp render data..." % bpy.data.filepath)

View File

@ -124,6 +124,27 @@ class JunctionModuleHandle:
delattr(self._module, submodule_name)
del sys.modules[name_full]
# Remove all sub-modules, to prevent them being reused in the future.
#
# While it might not seem like a problem to keep these around it means if a module
# with the same name is registered later, importing sub-modules uses the cached values
# from `sys.modules` and does *not* assign the module to the name-space of the new `submodule`.
# This isn't exactly a bug, it's often assumed that inspecting a module
# is a way to find its sub-modules, using `dir(submodule)` for example.
# For more technical example `sys.modules["foo.bar"] == sys.modules["foo"].bar`
# which can fail with and attribute error unless the modules are cleared here.
#
# An alternative solution could be re-attach sub-modules to the modules name-space when its re-registered.
# This has some advantages since the module doesn't have to be re-imported however it has the down
# side that stale data would be kept in `sys.modules` unnecessarily in many cases.
name_full_prefix = name_full + "."
submodule_name_list = [
submodule_name for submodule_name in sys.modules.keys()
if submodule_name.startswith(name_full_prefix)
]
for submodule_name in submodule_name_list:
del sys.modules[submodule_name]
def rename_submodule(self, submodule_name_src: str, submodule_name_dst: str) -> None:
name_full_prev = self._module_name + "." + submodule_name_src
name_full_next = self._module_name + "." + submodule_name_dst

View File

@ -11,6 +11,7 @@ __all__ = (
"object_add_grid_scale",
"object_add_grid_scale_apply_operator",
"world_to_camera_view",
"object_verify_active_shape_key_is_editable",
)
@ -263,3 +264,26 @@ def world_to_camera_view(scene, obj, coord):
y = (co_local.y - min_y) / (max_y - min_y)
return Vector((x, y, z))
def object_report_if_active_shape_key_is_locked(obj, operator):
"""
Checks if the active shape key of the specified object is locked, and reports an error if so.
If the object has no shape keys, there is nothing to lock, and the function returns False.
:arg obj: Object to check.
:type obj: :class:`bpy.types.Object`
:arg operator: Currently running operator to report the error through. Use None to suppress emitting the message.
:type operator: :class:`bpy.types.Operator`
:return: True if the shape key was locked.
"""
key = obj.active_shape_key
if key and key.lock_shape:
if operator:
operator.report({'ERROR'}, "The active shape key of %s is locked" % obj.name)
return True
return False

View File

@ -21,6 +21,11 @@ class VIEW3D_OT_edit_mesh_extrude_individual_move(Operator):
return (obj is not None and obj.mode == 'EDIT')
def execute(self, context):
from bpy_extras.object_utils import object_report_if_active_shape_key_is_locked
if object_report_if_active_shape_key_is_locked(context.object, self):
return {'CANCELLED'}
mesh = context.object.data
select_mode = context.tool_settings.mesh_select_mode
@ -83,7 +88,12 @@ class VIEW3D_OT_edit_mesh_extrude_move(Operator):
return (obj is not None and obj.mode == 'EDIT')
@staticmethod
def extrude_region(context, use_vert_normals, dissolve_and_intersect):
def extrude_region(operator, context, use_vert_normals, dissolve_and_intersect):
from bpy_extras.object_utils import object_report_if_active_shape_key_is_locked
if object_report_if_active_shape_key_is_locked(context.object, operator):
return {'CANCELLED'}
mesh = context.object.data
totface = mesh.total_face_sel
@ -146,7 +156,7 @@ class VIEW3D_OT_edit_mesh_extrude_move(Operator):
def execute(self, context):
return VIEW3D_OT_edit_mesh_extrude_move.extrude_region(
context, False, self.dissolve_and_intersect)
self, context, False, self.dissolve_and_intersect)
def invoke(self, context, _event):
return self.execute(context)
@ -163,7 +173,7 @@ class VIEW3D_OT_edit_mesh_extrude_shrink_fatten(Operator):
return (obj is not None and obj.mode == 'EDIT')
def execute(self, context):
return VIEW3D_OT_edit_mesh_extrude_move.extrude_region(context, True, False)
return VIEW3D_OT_edit_mesh_extrude_move.extrude_region(self, context, True, False)
def invoke(self, context, _event):
return self.execute(context)
@ -179,7 +189,11 @@ class VIEW3D_OT_edit_mesh_extrude_manifold_normal(Operator):
obj = context.active_object
return (obj is not None and obj.mode == 'EDIT')
def execute(self, _context):
def execute(self, context):
from bpy_extras.object_utils import object_report_if_active_shape_key_is_locked
if object_report_if_active_shape_key_is_locked(context.object, self):
return {'CANCELLED'}
bpy.ops.mesh.extrude_manifold(
'INVOKE_REGION_WIN',
MESH_OT_extrude_region={

View File

@ -3228,7 +3228,7 @@ class WM_MT_splash_quick_setup(Menu):
)
col.operator(
"wm.url_open", text="See What's New...", icon='URL',
).url = "https://wiki.blender.org/wiki/Reference/Release_Notes/4.0"
).url = "https://developer.blender.org/docs/release_notes/%d.%d" % bpy.app.version[:2]
col.separator(factor=2.0)
if can_import:

View File

@ -104,6 +104,13 @@ _modules_loaded = [_namespace[name] for name in _modules]
del _namespace
# Bypass the caching mechanism in the "Format" panel to make sure it is properly translated on language update.
@bpy.app.handlers.persistent
def translation_update(_):
from .properties_output import RENDER_PT_format
RENDER_PT_format._frame_rate_args_prev = None
def register():
from bpy.utils import register_class
for mod in _modules_loaded:
@ -166,6 +173,8 @@ def register():
)
del items
bpy.app.handlers.translation_update_post.append(translation_update)
# done...
@ -176,6 +185,11 @@ def unregister():
if cls.is_registered:
unregister_class(cls)
try:
bpy.app.handlers.translation_update_post.remove(translation_update)
except ValueError:
pass
# Define a default UIList, when a list does not need any custom drawing...
# Keep in sync with its #defined name in UI_interface.hh

View File

@ -73,6 +73,9 @@ class MESH_MT_shape_key_context_menu(Menu):
props.all = True
props.apply_mix = True
layout.separator()
layout.operator("object.shape_key_lock", icon='LOCKED', text="Lock All").action = 'LOCK'
layout.operator("object.shape_key_lock", icon='UNLOCKED', text="Unlock All").action = 'UNLOCK'
layout.separator()
layout.operator("object.shape_key_move", icon='TRIA_UP_BAR', text="Move to Top").type = 'TOP'
layout.operator("object.shape_key_move", icon='TRIA_DOWN_BAR', text="Move to Bottom").type = 'BOTTOM'
@ -132,6 +135,7 @@ class MESH_UL_shape_keys(UIList):
else:
row.label(text="")
row.prop(key_block, "mute", text="", emboss=False)
row.prop(key_block, "lock_shape", text="", emboss=False)
elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)

View File

@ -71,14 +71,16 @@ class OBJECT_MT_modifier_add(ModifierAddMenu, Menu):
if geometry_nodes_supported:
self.operator_modifier_add(layout, 'NODES')
layout.separator()
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE', 'GREASEPENCIL'}:
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
layout.menu("OBJECT_MT_modifier_add_edit")
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'VOLUME'}:
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'VOLUME', 'GREASEPENCIL'}:
layout.menu("OBJECT_MT_modifier_add_generate")
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE', 'VOLUME'}:
layout.menu("OBJECT_MT_modifier_add_deform")
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
layout.menu("OBJECT_MT_modifier_add_physics")
if ob_type in {'GREASEPENCIL'}:
layout.menu("OBJECT_MT_modifier_add_color")
if geometry_nodes_supported:
layout.menu_contents("OBJECT_MT_modifier_add_root_catalogs")
@ -105,8 +107,6 @@ class OBJECT_MT_modifier_add_edit(ModifierAddMenu, Menu):
self.operator_modifier_add(layout, 'VERTEX_WEIGHT_EDIT')
self.operator_modifier_add(layout, 'VERTEX_WEIGHT_MIX')
self.operator_modifier_add(layout, 'VERTEX_WEIGHT_PROXIMITY')
if ob_type == 'GREASEPENCIL':
self.operator_modifier_add(layout, 'GREASE_PENCIL_OPACITY')
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)
@ -149,6 +149,8 @@ class OBJECT_MT_modifier_add_generate(ModifierAddMenu, Menu):
self.operator_modifier_add(layout, 'WELD')
if ob_type == 'MESH':
self.operator_modifier_add(layout, 'WIREFRAME')
if ob_type == 'GREASEPENCIL':
self.operator_modifier_add(layout, 'GREASEPENCIL_SUBDIV')
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)
@ -209,6 +211,18 @@ class OBJECT_MT_modifier_add_physics(ModifierAddMenu, Menu):
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)
class OBJECT_MT_modifier_add_color(ModifierAddMenu, Menu):
bl_label = "Color"
bl_options = {'SEARCH_ON_KEY_PRESS'}
def draw(self, context):
layout = self.layout
ob_type = context.object.type
if ob_type == 'GREASEPENCIL':
self.operator_modifier_add(layout, 'GREASE_PENCIL_OPACITY')
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)
class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
bl_label = "Modifiers"
@ -247,6 +261,7 @@ classes = (
OBJECT_MT_modifier_add_generate,
OBJECT_MT_modifier_add_deform,
OBJECT_MT_modifier_add_physics,
OBJECT_MT_modifier_add_color,
DATA_PT_gpencil_modifiers,
AddModifierMenu,
)

View File

@ -248,7 +248,7 @@ class TIME_PT_playback(TimelinePanelButtons, Panel):
layout.prop(scene, "sync_mode", text="Sync")
col = layout.column(heading="Audio")
col.prop(scene, "use_audio_scrub", text="Scrubbing")
col.prop(scene, "use_audio", text="Mute")
col.prop(scene, "use_audio")
col = layout.column(heading="Playback")
col.prop(scene, "lock_frame_selection_to_range", text="Limit to Frame Range")

View File

@ -708,7 +708,7 @@ class TOPBAR_MT_help(Menu):
"wm.url_open",
text="Developer Documentation",
icon='URL',
).url = "https://wiki.blender.org/wiki/Main_Page"
).url = "https://developer.blender.org/docs/"
layout.operator("wm.url_open", text="Developer Community").url = "https://devtalk.blender.org"
layout.operator("wm.url_open_preset", text="Python API Reference").type = 'API'
layout.operator("wm.operator_cheat_sheet", icon='TEXT')

View File

@ -109,7 +109,10 @@ class USERPREF_MT_save_load(Menu):
if prefs.use_preferences_save:
layout.operator("wm.save_userpref", text="Save Preferences")
sub_revert = layout.column(align=True)
sub_revert.active = prefs.is_dirty
# NOTE: regarding `factory_startup`. To correctly show the active state of this menu item,
# the user preferences themselves would need to have a `factory_startup` state.
# Since showing an active menu item whenever factory-startup is used is not such a problem, leave this as-is.
sub_revert.active = prefs.is_dirty or bpy.app.factory_startup
sub_revert.operator("wm.read_userpref", text="Revert to Saved Preferences")
layout.operator_context = 'INVOKE_AREA'

View File

@ -5286,6 +5286,7 @@ class VIEW3D_MT_edit_font(Menu):
layout.separator()
layout.operator("FONT_OT_text_insert_unicode")
layout.menu("VIEW3D_MT_edit_font_chars")
layout.separator()

View File

@ -30,6 +30,10 @@ bAction *id_action_ensure(Main *bmain, ID *id);
*/
void animdata_fcurve_delete(bAnimContext *ac, AnimData *adt, FCurve *fcu);
/** Iterate the FCurves of the given bAnimContext and validate the RNA path. Sets the flag
* FCURVE_DISABLED if the path can't be resolved. */
void reevaluate_fcurve_errors(bAnimContext *ac);
/**
* Unlink the action from animdata if it's empty.
*

View File

@ -0,0 +1,25 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup animrig
*
* \brief Functions to work with drivers.
*/
#include "RNA_types.hh"
struct AnimationEvalContext;
struct FCurve;
namespace blender::animrig {
/** Evaluates the driver on the frame given in `anim_eval_context` and returns the value. Returns 0
* if the RNA path can't be resolved. */
float evaluate_driver_from_rna_pointer(const AnimationEvalContext *anim_eval_context,
PointerRNA *ptr,
PropertyRNA *prop,
const FCurve *fcu);
} // namespace blender::animrig

View File

@ -24,6 +24,7 @@ set(SRC
intern/animdata.cc
intern/bone_collections.cc
intern/bonecolor.cc
intern/driver.cc
intern/fcurve.cc
intern/keyframing.cc
intern/keyframing_auto.cc
@ -34,6 +35,7 @@ set(SRC
ANIM_armature_iter.hh
ANIM_bone_collections.hh
ANIM_bonecolor.hh
ANIM_driver.hh
ANIM_fcurve.hh
ANIM_keyframing.hh
ANIM_rna.hh

View File

@ -17,6 +17,8 @@
#include "DEG_depsgraph_build.hh"
#include "DNA_anim_types.h"
#include "ED_anim_api.hh"
#include "RNA_access.hh"
#include "RNA_path.hh"
namespace blender::animrig {
@ -135,4 +137,35 @@ bool animdata_remove_empty_action(AnimData *adt)
/** \} */
void reevaluate_fcurve_errors(bAnimContext *ac)
{
/* Need to take off the flag before filtering, else the filter code would skip the FCurves, which
* have not yet been validated. */
const bool filtering_enabled = ac->ads->filterflag & ADS_FILTER_ONLY_ERRORS;
if (filtering_enabled) {
ac->ads->filterflag &= ~ADS_FILTER_ONLY_ERRORS;
}
ListBase anim_data = {nullptr, nullptr};
const eAnimFilter_Flags filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FCURVESONLY;
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, eAnimCont_Types(ac->datatype));
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
FCurve *fcu = (FCurve *)ale->key_data;
PointerRNA ptr;
PropertyRNA *prop;
PointerRNA id_ptr = RNA_id_pointer_create(ale->id);
if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
fcu->flag &= ~FCURVE_DISABLED;
}
else {
fcu->flag |= FCURVE_DISABLED;
}
}
ANIM_animdata_freelist(&anim_data);
if (filtering_enabled) {
ac->ads->filterflag |= ADS_FILTER_ONLY_ERRORS;
}
}
} // namespace blender::animrig

View File

@ -0,0 +1,29 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup animrig
*/
#include "ANIM_driver.hh"
#include "BKE_animsys.h"
#include "BKE_fcurve_driver.h"
#include "DNA_anim_types.h"
#include "RNA_access.hh"
namespace blender::animrig {
float evaluate_driver_from_rna_pointer(const AnimationEvalContext *anim_eval_context,
PointerRNA *ptr,
PropertyRNA *prop,
const FCurve *fcu)
{
PathResolvedRNA anim_rna;
if (!RNA_path_resolved_create(ptr, prop, fcu->array_index, &anim_rna)) {
return 0.0f;
}
return evaluate_driver(&anim_rna, fcu->driver, fcu->driver, anim_eval_context);
}
} // namespace blender::animrig

View File

@ -21,7 +21,6 @@
#include "BKE_anim_data.h"
#include "BKE_animsys.h"
#include "BKE_fcurve.h"
#include "BKE_fcurve_driver.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.hh"
#include "BKE_nla.h"
@ -279,12 +278,12 @@ static bool new_key_needed(FCurve *fcu, const float frame, const float value)
return true;
}
static AnimationEvalContext nla_time_remap(const AnimationEvalContext *anim_eval_context,
PointerRNA *id_ptr,
AnimData *adt,
bAction *act,
ListBase *nla_cache,
NlaKeyframingContext **r_nla_context)
static float nla_time_remap(const AnimationEvalContext *anim_eval_context,
PointerRNA *id_ptr,
AnimData *adt,
bAction *act,
ListBase *nla_cache,
NlaKeyframingContext **r_nla_context)
{
if (adt && adt->action == act) {
*r_nla_context = BKE_animsys_get_nla_keyframing_context(
@ -292,28 +291,11 @@ static AnimationEvalContext nla_time_remap(const AnimationEvalContext *anim_eval
const float remapped_frame = BKE_nla_tweakedit_remap(
adt, anim_eval_context->eval_time, NLATIME_CONVERT_UNMAP);
return BKE_animsys_eval_context_construct_at(anim_eval_context, remapped_frame);
return remapped_frame;
}
*r_nla_context = nullptr;
return *anim_eval_context;
}
/* Adjust frame on which to add keyframe, to make it easier to add corrective drivers. */
static float remap_driver_frame(const AnimationEvalContext *anim_eval_context,
PointerRNA *ptr,
PropertyRNA *prop,
const FCurve *fcu)
{
float cfra = anim_eval_context->eval_time;
PathResolvedRNA anim_rna;
if (RNA_path_resolved_create(ptr, prop, fcu->array_index, &anim_rna)) {
cfra = evaluate_driver(&anim_rna, fcu->driver, fcu->driver, anim_eval_context);
}
else {
cfra = 0.0f;
}
return cfra;
return anim_eval_context->eval_time;
}
/* Insert the specified keyframe value into a single F-Curve. */
@ -418,11 +400,7 @@ bool insert_keyframe_direct(ReportList *reports,
return false;
}
float cfra = anim_eval_context->eval_time;
if ((flag & INSERTKEY_DRIVER) && (fcu->driver)) {
cfra = remap_driver_frame(anim_eval_context, &ptr, prop, fcu);
}
const float cfra = anim_eval_context->eval_time;
const bool success = insert_keyframe_value(fcu, cfra, current_value, keytype, flag);
if (!success) {
@ -445,7 +423,7 @@ static bool insert_keyframe_fcurve_value(Main *bmain,
const char group[],
const char rna_path[],
int array_index,
const AnimationEvalContext *anim_eval_context,
const float fcurve_frame,
float curval,
eBezTriple_KeyframeType keytype,
eInsertKeyFlags flag)
@ -476,12 +454,7 @@ static bool insert_keyframe_fcurve_value(Main *bmain,
/* Update F-Curve flags to ensure proper behavior for property type. */
update_autoflags_fcurve_direct(fcu, prop);
float cfra = anim_eval_context->eval_time;
if ((flag & INSERTKEY_DRIVER) && (fcu->driver)) {
cfra = remap_driver_frame(anim_eval_context, ptr, prop, fcu);
}
const bool success = insert_keyframe_value(fcu, cfra, curval, keytype, flag);
const bool success = insert_keyframe_value(fcu, fcurve_frame, curval, keytype, flag);
if (!success) {
BKE_reportf(reports,
@ -552,7 +525,7 @@ int insert_keyframe(Main *bmain,
NlaKeyframingContext *nla_context = nullptr;
ListBase nla_cache = {nullptr, nullptr};
AnimData *adt = BKE_animdata_from_id(id);
const AnimationEvalContext remapped_context = nla_time_remap(
const float nla_mapped_frame = nla_time_remap(
anim_eval_context, &id_ptr, adt, act, &nla_cache, &nla_context);
bool force_all;
@ -587,7 +560,7 @@ int insert_keyframe(Main *bmain,
group,
rna_path,
array_index,
&remapped_context,
nla_mapped_frame,
values[array_index],
keytype,
flag))
@ -615,7 +588,7 @@ int insert_keyframe(Main *bmain,
group,
rna_path,
array_index,
&remapped_context,
nla_mapped_frame,
values[array_index],
keytype,
flag);
@ -638,7 +611,7 @@ int insert_keyframe(Main *bmain,
group,
rna_path,
array_index,
&remapped_context,
nla_mapped_frame,
values[array_index],
keytype,
flag);
@ -658,7 +631,7 @@ int insert_keyframe(Main *bmain,
group,
rna_path,
array_index,
&remapped_context,
nla_mapped_frame,
values[array_index],
keytype,
flag);

View File

@ -29,7 +29,7 @@ namespace blender::asset_system {
* - Only slashes are used as path component separators.
* - All paths are absolute, so there is no need for a leading slash.
*
* See https://wiki.blender.org/wiki/Source/Architecture/Asset_System/Catalogs
* See https://developer.blender.org/docs/features/asset_system/backend/asset_catalogs/
*
* Paths are stored as byte sequences, and assumed to be UTF-8.
*/

View File

@ -7,7 +7,7 @@
*
* \brief Information to uniquely identify and locate an asset.
*
* https://wiki.blender.org/wiki/Source/Architecture/Asset_System/Back_End#Asset_Identifier
* https://developer.blender.org/docs/features/asset_system/backend/#asset-identifier
*/
#pragma once

View File

@ -8,7 +8,7 @@
* \brief Main runtime representation of an asset.
*
* Abstraction to reference an asset, with necessary data for display & interaction.
* https://wiki.blender.org/wiki/Source/Architecture/Asset_System/Back_End#Asset_Representation
* https://developer.blender.org/docs/features/asset_system/backend/#asset-representation
*/
#pragma once

View File

@ -30,7 +30,7 @@
* TODO Currently disabled because UI data depends on asset library data, so we have to make sure
* it's freed in the right order (UI first). Pre-load handlers don't give us this order.
* Should be addressed with a proper ownership model for the asset system:
* https://wiki.blender.org/wiki/Source/Architecture/Asset_System/Back_End#Ownership_Model
* https://developer.blender.org/docs/features/asset_system/backend/#ownership-model
*/
// #define WITH_DESTROY_VIA_LOAD_HANDLER

View File

@ -88,7 +88,7 @@ struct KS_Path *BKE_keyingset_find_path(struct KeyingSet *ks,
/* Copy all KeyingSets in the given list */
void BKE_keyingsets_copy(struct ListBase *newlist, const struct ListBase *list);
/** Process the ID pointers inside a scene's keyingsets, in see `BKE_lib_query.h` for details. */
/** Process the ID pointers inside a scene's keyingsets, in see `BKE_lib_query.hh` for details. */
void BKE_keyingsets_foreach_id(struct LibraryForeachIDData *data,
const struct ListBase *keyingsets);

View File

@ -29,13 +29,15 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 11
#define BLENDER_FILE_SUBVERSION 12
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and cancel loading the file, showing a warning to
* the user.
*
* See https://wiki.blender.org/wiki/Process/Compatibility_Handling for details. */
* See
* https://developer.blender.org/docs/handbook/guidelines/compatibility_handling_for_blend_files/
* for details. */
#define BLENDER_FILE_MIN_VERSION 306
#define BLENDER_FILE_MIN_SUBVERSION 13

View File

@ -109,6 +109,7 @@ typedef enum {
BKE_CB_EVT_COMPOSITE_CANCEL,
BKE_CB_EVT_ANIMATION_PLAYBACK_PRE,
BKE_CB_EVT_ANIMATION_PLAYBACK_POST,
BKE_CB_EVT_TRANSLATION_UPDATE_POST,
BKE_CB_EVT_EXTENSION_REPOS_UPDATE_PRE,
BKE_CB_EVT_EXTENSION_REPOS_UPDATE_POST,
BKE_CB_EVT_TOT,

View File

@ -180,7 +180,7 @@ void BKE_constraints_copy_ex(struct ListBase *dst,
* Run the given callback on all ID-blocks in list of constraints.
*
* \param flag: the `IDWALK_` flags controlling the behavior of the foreach_id code, see
* `BKE_lib_query.h`
* `BKE_lib_query.hh`
*/
void BKE_constraints_id_loop(struct ListBase *list,
ConstraintIDFunc func,

View File

@ -55,7 +55,7 @@ typedef struct IDCacheKey {
unsigned int id_session_uuid;
/* Value uniquely identifying the cache within its ID.
* Typically the offset of its member in the data-block struct, but can be anything. */
size_t offset_in_ID;
size_t identifier;
} IDCacheKey;
uint BKE_idtype_cache_key_hash(const void *key_v);

View File

@ -88,9 +88,9 @@ struct KeyBlock *BKE_keyblock_add(struct Key *key, const char *name);
*/
struct KeyBlock *BKE_keyblock_add_ctime(struct Key *key, const char *name, bool do_force);
/**
* Get the appropriate #KeyBlock given an index.
* Get the appropriate #KeyBlock given an index (0 refers to the basis key). Key may be null.
*/
struct KeyBlock *BKE_keyblock_from_key(struct Key *key, int index);
struct KeyBlock *BKE_keyblock_find_by_index(struct Key *key, int index);
/**
* Get the appropriate #KeyBlock given a name to search for.
*/

View File

@ -21,10 +21,6 @@
#include "BLI_sys_types.h"
#ifdef __cplusplus
extern "C" {
#endif
struct ID;
struct IDProperty;
struct Main;
@ -119,23 +115,23 @@ enum {
IDWALK_RET_STOP_RECURSION = 1 << 1,
};
typedef struct LibraryIDLinkCallbackData {
struct LibraryIDLinkCallbackData {
void *user_data;
/** Main database used to call `BKE_library_foreach_ID_link()`. */
struct Main *bmain;
Main *bmain;
/**
* 'Real' ID, the one that might be in bmain, only differs from self_id when the later is an
* embedded one.
*/
struct ID *owner_id;
ID *owner_id;
/**
* ID from which the current ID pointer is being processed. It may be an embedded ID like master
* collection or root node tree.
*/
struct ID *self_id;
struct ID **id_pointer;
ID *self_id;
ID **id_pointer;
int cb_flag;
} LibraryIDLinkCallbackData;
};
/**
* Call a callback for each ID link which the given ID uses.
@ -211,12 +207,10 @@ typedef struct LibraryForeachIDData LibraryForeachIDData;
* Check whether current iteration over ID usages should be stopped or not.
* \return true if the iteration should be stopped, false otherwise.
*/
bool BKE_lib_query_foreachid_iter_stop(const struct LibraryForeachIDData *data);
void BKE_lib_query_foreachid_process(struct LibraryForeachIDData *data,
struct ID **id_pp,
int cb_flag);
int BKE_lib_query_foreachid_process_flags_get(const struct LibraryForeachIDData *data);
int BKE_lib_query_foreachid_process_callback_flag_override(struct LibraryForeachIDData *data,
bool BKE_lib_query_foreachid_iter_stop(const LibraryForeachIDData *data);
void BKE_lib_query_foreachid_process(LibraryForeachIDData *data, ID **id_pp, int cb_flag);
int BKE_lib_query_foreachid_process_flags_get(const LibraryForeachIDData *data);
int BKE_lib_query_foreachid_process_callback_flag_override(LibraryForeachIDData *data,
int cb_flag,
bool do_replace);
@ -268,18 +262,18 @@ int BKE_lib_query_foreachid_process_callback_flag_override(struct LibraryForeach
* Those require specific care, since they are technically sub-data of their owner, yet in some
* cases they still behave as regular IDs.
*/
void BKE_library_foreach_ID_embedded(struct LibraryForeachIDData *data, struct ID **id_pp);
void BKE_lib_query_idpropertiesForeachIDLink_callback(struct IDProperty *id_prop, void *user_data);
void BKE_library_foreach_ID_embedded(LibraryForeachIDData *data, ID **id_pp);
void BKE_lib_query_idpropertiesForeachIDLink_callback(IDProperty *id_prop, void *user_data);
/**
* Loop over all of the ID's this data-block links to.
*/
void BKE_library_foreach_ID_link(
struct Main *bmain, struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag);
Main *bmain, ID *id, LibraryIDLinkCallback callback, void *user_data, int flag);
/**
* Re-usable function, use when replacing ID's.
*/
void BKE_library_update_ID_link_user(struct ID *id_dst, struct ID *id_src, int cb_flag);
void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, int cb_flag);
/**
* Return the number of times given \a id_user uses/references \a id_used.
@ -291,7 +285,7 @@ void BKE_library_update_ID_link_user(struct ID *id_dst, struct ID *id_src, int c
* \param id_used: the ID which is supposed to be used (referenced) by \a id_user.
* \return the number of direct usages/references of \a id_used by \a id_user.
*/
int BKE_library_ID_use_ID(struct ID *id_user, struct ID *id_used);
int BKE_library_ID_use_ID(ID *id_user, ID *id_used);
/**
* Say whether given \a owner_id may use (in any way) a data-block of \a id_type_used.
@ -299,26 +293,26 @@ int BKE_library_ID_use_ID(struct ID *id_user, struct ID *id_used);
* This is a 'simplified' abstract version of #BKE_library_foreach_ID_link() above,
* quite useful to reduce useless iterations in some cases.
*/
bool BKE_library_id_can_use_idtype(struct ID *owner_id, short id_type_used);
bool BKE_library_id_can_use_idtype(ID *owner_id, short id_type_used);
/**
* Given the owner_id return the type of id_types it can use as a filter_id.
*/
uint64_t BKE_library_id_can_use_filter_id(const struct ID *owner_id, const bool include_ui);
uint64_t BKE_library_id_can_use_filter_id(const ID *owner_id, const bool include_ui);
/**
* Check whether given ID is used locally (i.e. by another non-linked ID).
*/
bool BKE_library_ID_is_locally_used(struct Main *bmain, void *idv);
bool BKE_library_ID_is_locally_used(Main *bmain, void *idv);
/**
* Check whether given ID is used indirectly (i.e. by another linked ID).
*/
bool BKE_library_ID_is_indirectly_used(struct Main *bmain, void *idv);
bool BKE_library_ID_is_indirectly_used(Main *bmain, void *idv);
/**
* Combine #BKE_library_ID_is_locally_used() and #BKE_library_ID_is_indirectly_used()
* in a single call.
*/
void BKE_library_ID_test_usages(struct Main *bmain,
void BKE_library_ID_test_usages(Main *bmain,
void *idv,
bool *r_is_used_local,
bool *r_is_used_linked);
@ -338,7 +332,7 @@ void BKE_library_ID_test_usages(struct Main *bmain,
* Number of tagged-as-unused IDs is then set for each type, and as total in
* #INDEX_ID_NULL item.
*/
void BKE_lib_query_unused_ids_tag(struct Main *bmain,
void BKE_lib_query_unused_ids_tag(Main *bmain,
int tag,
bool do_local_ids,
bool do_linked_ids,
@ -354,7 +348,7 @@ void BKE_lib_query_unused_ids_tag(struct Main *bmain,
* \param do_init_tag: if \a true, all linked data are checked, if \a false,
* only linked data-blocks already tagged with #LIB_TAG_DOIT are checked.
*/
void BKE_library_unused_linked_data_set_tag(struct Main *bmain, bool do_init_tag);
void BKE_library_unused_linked_data_set_tag(Main *bmain, bool do_init_tag);
/**
* Untag linked data blocks used by other untagged linked data-blocks.
* Used to detect data-blocks that we can forcefully make local
@ -363,8 +357,4 @@ void BKE_library_unused_linked_data_set_tag(struct Main *bmain, bool do_init_tag
* after this function has ran caller knows data-blocks still tagged can directly be made local,
* since they are only used by other data-blocks that will also be made fully local.
*/
void BKE_library_indirectly_used_data_tag_clear(struct Main *bmain);
#ifdef __cplusplus
}
#endif
void BKE_library_indirectly_used_data_tag_clear(Main *bmain);

View File

@ -58,7 +58,7 @@ struct MainIDRelationsEntryItem {
/* Session uuid of the `id_pointer`. */
uint session_uuid;
int usage_flag; /* Using IDWALK_ enums, defined in BKE_lib_query.h */
int usage_flag; /* Using IDWALK_ enums, defined in BKE_lib_query.hh */
};
struct MainIDRelationsEntry {

View File

@ -21,6 +21,10 @@ using index_mask::IndexMask;
#include "BKE_mesh_types.hh"
namespace blender::bke {
enum class AttrDomain : int8_t;
class AttributeIDRef;
namespace mesh {
/* -------------------------------------------------------------------- */
/** \name Polygon Data Evaluation
@ -334,4 +338,10 @@ void mesh_select_edge_flush(Mesh &mesh);
/** Make vertex and edge visibility consistent with faces. */
void mesh_select_face_flush(Mesh &mesh);
/** Set the default name when adding a color attribute if there is no default yet. */
void mesh_ensure_default_color_attribute_on_add(Mesh &mesh,
const AttributeIDRef &id,
AttrDomain domain,
eCustomDataType data_type);
} // namespace blender::bke

View File

@ -7,6 +7,7 @@
* \ingroup bke
*/
#include "BLI_compiler_attrs.h"
#include "BLI_function_ref.hh"
#include "BLI_math_matrix_types.hh"
#include "BLI_span.hh"
@ -33,6 +34,7 @@ struct ModifierData;
struct Object;
struct Scene;
struct StructRNA;
struct IDCacheKey;
enum class ModifierTypeType {
/* Should not be used, only for None modifier type */
@ -122,7 +124,7 @@ enum ModifierTypeFlag {
/** Accepts #GreasePencil data input. */
eModifierTypeFlag_AcceptsGreasePencil = (1 << 12),
};
ENUM_OPERATORS(ModifierTypeFlag, eModifierTypeFlag_AcceptsBMesh)
ENUM_OPERATORS(ModifierTypeFlag, eModifierTypeFlag_AcceptsGreasePencil)
using IDWalkFunc = void (*)(void *user_data, Object *ob, ID **idpoin, int cb_flag);
using TexWalkFunc = void (*)(void *user_data, Object *ob, ModifierData *md, const char *propname);
@ -381,6 +383,14 @@ struct ModifierTypeInfo {
* not been written (e.g. runtime data) can be reset.
*/
void (*blend_read)(BlendDataReader *reader, ModifierData *md);
/**
* Iterate over all cache pointers of given modifier. Also see #IDTypeInfo::foreach_cache.
*/
void (*foreach_cache)(
Object *object,
ModifierData *md,
blender::FunctionRef<void(const IDCacheKey &cache_key, void **cache_p, uint flags)> fn);
};
/* Used to set a modifier's panel type. */

View File

@ -420,7 +420,7 @@ set(SRC
BKE_layer.h
BKE_lib_id.hh
BKE_lib_override.hh
BKE_lib_query.h
BKE_lib_query.hh
BKE_lib_remap.hh
BKE_library.hh
BKE_light.h

View File

@ -357,9 +357,9 @@ static float (*get_orco_coords(Object *ob, BMEditMesh *em, int layer, int *free)
if (!em) {
ClothModifierData *clmd = (ClothModifierData *)BKE_modifiers_findby_type(
ob, eModifierType_Cloth);
if (clmd) {
KeyBlock *kb = BKE_keyblock_from_key(BKE_key_from_object(ob),
clmd->sim_parms->shapekey_rest);
if (clmd && clmd->sim_parms->shapekey_rest) {
KeyBlock *kb = BKE_keyblock_find_by_index(BKE_key_from_object(ob),
clmd->sim_parms->shapekey_rest);
if (kb && kb->data) {
return (float(*)[3])kb->data;

View File

@ -46,7 +46,7 @@
#include "BKE_idprop.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_main.hh"
#include "BKE_object.hh"
#include "BKE_object_types.hh"

View File

@ -18,7 +18,7 @@
#include "BKE_global.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_main.hh"
#include "BKE_nla.h"
#include "BKE_node.h"

View File

@ -42,7 +42,7 @@
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_main.hh"
#include "BKE_material.h"
#include "BKE_nla.h"

View File

@ -45,7 +45,7 @@
#include "BKE_idprop.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_main.hh"
#include "BKE_object.hh"
#include "BKE_object_types.hh"
@ -1898,7 +1898,7 @@ static void find_bbone_segment_index_curved(const bPoseChannel *pchan,
* reduce the gradient slope to the ideal value (the one you get for points directly on
* the curve), using heuristic blend strength falloff coefficients based on the distances
* to the boundary plane before and after mapping. See PR #110758 for more details, or
* https://wiki.blender.org/wiki/Source/Animation/B-Bone_Vertex_Mapping#Curved_Mapping */
* https://developer.blender.org/docs/features/animation/b-bone_vertex_mapping/#curved-mapping */
const float segment_scale = pchan->runtime.bbone_arc_length_reciprocal;
for (int i = stack_top; i >= 0; --i) {

View File

@ -11,15 +11,6 @@
namespace blender::bke::bake {
static const CPPType &get_socket_cpp_type(const eNodeSocketDatatype socket_type)
{
const char *socket_idname = nodeStaticSocketType(socket_type, 0);
const bNodeSocketType *typeinfo = nodeSocketTypeFind(socket_idname);
BLI_assert(typeinfo);
BLI_assert(typeinfo->geometry_nodes_cpp_type);
return *typeinfo->geometry_nodes_cpp_type;
}
Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<void *> socket_values,
const BakeSocketConfig &config)
{
@ -201,6 +192,14 @@ static void rename_attributes(const Span<GeometrySet *> geometries,
}
}
static void default_initialize_socket_value(const eNodeSocketDatatype socket_type, void *r_value)
{
const char *socket_idname = nodeStaticSocketType(socket_type, 0);
const bNodeSocketType *typeinfo = nodeSocketTypeFind(socket_idname);
typeinfo->geometry_nodes_cpp_type->copy_construct(typeinfo->geometry_nodes_default_cpp_value,
r_value);
}
void move_bake_items_to_socket_values(
const Span<BakeItem *> bake_items,
const BakeSocketConfig &config,
@ -214,11 +213,10 @@ void move_bake_items_to_socket_values(
for (const int i : bake_items.index_range()) {
const eNodeSocketDatatype socket_type = config.types[i];
const CPPType &type = get_socket_cpp_type(socket_type);
BakeItem *bake_item = bake_items[i];
void *r_socket_value = r_socket_values[i];
if (bake_item == nullptr) {
type.value_initialize(r_socket_value);
default_initialize_socket_value(socket_type, r_socket_value);
continue;
}
if (!copy_bake_item_to_socket_value(
@ -228,7 +226,7 @@ void move_bake_items_to_socket_values(
attribute_map,
r_socket_value))
{
type.value_initialize(r_socket_value);
default_initialize_socket_value(socket_type, r_socket_value);
continue;
}
if (socket_type == SOCK_GEOMETRY) {
@ -253,11 +251,10 @@ void copy_bake_items_to_socket_values(
for (const int i : bake_items.index_range()) {
const eNodeSocketDatatype socket_type = config.types[i];
const CPPType &type = get_socket_cpp_type(socket_type);
const BakeItem *bake_item = bake_items[i];
void *r_socket_value = r_socket_values[i];
if (bake_item == nullptr) {
type.value_initialize(r_socket_value);
default_initialize_socket_value(socket_type, r_socket_value);
continue;
}
if (!copy_bake_item_to_socket_value(
@ -267,7 +264,7 @@ void copy_bake_items_to_socket_values(
attribute_map,
r_socket_value))
{
type.value_initialize(r_socket_value);
default_initialize_socket_value(socket_type, r_socket_value);
continue;
}
if (socket_type == SOCK_GEOMETRY) {

View File

@ -45,7 +45,7 @@
#include "BKE_layer.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_override.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_lib_remap.hh"
#include "BKE_main.hh"
#include "BKE_main_idmap.hh"

View File

@ -40,7 +40,7 @@
#include "BKE_layer.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_override.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_lib_remap.hh"
#include "BKE_main.hh"
#include "BKE_main_namemap.hh"

View File

@ -36,7 +36,7 @@
#include "BKE_idprop.hh"
#include "BKE_idtype.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_lib_remap.hh"
#include "BKE_main.hh"
#include "BKE_material.h"

View File

@ -35,7 +35,7 @@
#include "BKE_idtype.h"
#include "BKE_layer.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_main.hh"
#include "BKE_object.hh"
#include "BKE_scene.h"

View File

@ -26,7 +26,7 @@
#include "BKE_idtype.h"
#include "BKE_layer.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_lib_remap.hh"
#include "BKE_main.hh"
#include "BKE_object.hh"

View File

@ -59,7 +59,7 @@
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_mesh.hh"
#include "BKE_mesh_runtime.hh"
#include "BKE_movieclip.h"

View File

@ -47,7 +47,7 @@
#include "BKE_idtype.h"
#include "BKE_key.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_main.hh"
#include "BKE_object.hh"
#include "BKE_object_types.hh"

View File

@ -34,7 +34,7 @@
#include "BKE_global.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_lib_remap.hh"
#include "BKE_main.hh"
#include "BKE_modifier.hh"

View File

@ -34,7 +34,7 @@
#include "BKE_fcurve_driver.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_nla.h"
#include "BLO_read_write.hh"

View File

@ -46,7 +46,7 @@
#include "BKE_idtype.h"
#include "BKE_image.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_main.hh"
#include "BKE_material.h"
#include "BKE_paint.hh"

View File

@ -36,7 +36,7 @@
#include "BKE_gpencil_modifier_legacy.h"
#include "BKE_lattice.hh"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_material.h"
#include "BKE_modifier.hh"
#include "BKE_object.hh"

View File

@ -16,7 +16,7 @@
#include "BKE_grease_pencil.hh"
#include "BKE_idtype.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_material.h"
#include "BKE_modifier.hh"
#include "BKE_object.hh"

View File

@ -80,7 +80,7 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
SpanAttributeWriter<float> stroke_hardnesses = attributes.lookup_or_add_for_write_span<float>(
"hardness", AttrDomain::Curve);
SpanAttributeWriter<float> stroke_point_aspect_ratios =
attributes.lookup_or_add_for_write_span<float>("point_aspect_ratio", AttrDomain::Curve);
attributes.lookup_or_add_for_write_span<float>("aspect_ratio", AttrDomain::Curve);
SpanAttributeWriter<float2> stroke_fill_translations =
attributes.lookup_or_add_for_write_span<float2>("fill_translation", AttrDomain::Curve);
SpanAttributeWriter<float> stroke_fill_rotations =

View File

@ -33,7 +33,7 @@ uint BKE_idtype_cache_key_hash(const void *key_v)
{
const IDCacheKey *key = static_cast<const IDCacheKey *>(key_v);
size_t hash = BLI_ghashutil_uinthash(key->id_session_uuid);
hash = BLI_ghashutil_combine_hash(hash, BLI_ghashutil_uinthash(uint(key->offset_in_ID)));
hash = BLI_ghashutil_combine_hash(hash, BLI_ghashutil_uinthash(uint(key->identifier)));
return uint(hash);
}
@ -42,7 +42,7 @@ bool BKE_idtype_cache_key_cmp(const void *key_a_v, const void *key_b_v)
const IDCacheKey *key_a = static_cast<const IDCacheKey *>(key_a_v);
const IDCacheKey *key_b = static_cast<const IDCacheKey *>(key_b_v);
return (key_a->id_session_uuid != key_b->id_session_uuid) ||
(key_a->offset_in_ID != key_b->offset_in_ID);
(key_a->identifier != key_b->identifier);
}
static IDTypeInfo *id_types[INDEX_ID_MAX] = {nullptr};

View File

@ -237,12 +237,12 @@ static void image_foreach_cache(ID *id,
Image *image = (Image *)id;
IDCacheKey key;
key.id_session_uuid = id->session_uuid;
key.offset_in_ID = offsetof(Image, cache);
key.identifier = offsetof(Image, cache);
function_callback(id, &key, (void **)&image->cache, 0, user_data);
key.offset_in_ID = offsetof(Image, anims.first);
key.identifier = offsetof(Image, anims.first);
function_callback(id, &key, (void **)&image->anims.first, 0, user_data);
key.offset_in_ID = offsetof(Image, anims.last);
key.identifier = offsetof(Image, anims.last);
function_callback(id, &key, (void **)&image->anims.last, 0, user_data);
auto gputexture_offset = [image](int target, int eye) {
@ -258,16 +258,16 @@ static void image_foreach_cache(ID *id,
if (texture == nullptr) {
continue;
}
key.offset_in_ID = gputexture_offset(a, eye);
key.identifier = gputexture_offset(a, eye);
function_callback(id, &key, (void **)&image->gputexture[a][eye], 0, user_data);
}
}
key.offset_in_ID = offsetof(Image, rr);
key.identifier = offsetof(Image, rr);
function_callback(id, &key, (void **)&image->rr, 0, user_data);
LISTBASE_FOREACH (RenderSlot *, slot, &image->renderslots) {
key.offset_in_ID = size_t(BLI_ghashutil_strhash_p(slot->name));
key.identifier = size_t(BLI_ghashutil_strhash_p(slot->name));
function_callback(id, &key, (void **)&slot->render, 0, user_data);
}
}

View File

@ -52,7 +52,7 @@
#include "BKE_ipo.h"
#include "BKE_key.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_main.hh"
#include "BKE_nla.h"
@ -443,7 +443,7 @@ static char *shapekey_adrcodes_to_paths(ID *id, int adrcode, int * /*r_array_ind
else {
/* Find the name of the ShapeKey (i.e. KeyBlock) to look for */
Key *key = (Key *)id;
KeyBlock *kb = BKE_keyblock_from_key(key, adrcode);
KeyBlock *kb = BKE_keyblock_find_by_index(key, adrcode);
/* setting that we alter is the "value" (i.e. keyblock.curval) */
if (kb) {

View File

@ -43,7 +43,7 @@
#include "BKE_key.h"
#include "BKE_lattice.hh"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_main.hh"
#include "BKE_mesh.hh"
#include "BKE_scene.h"
@ -1897,12 +1897,7 @@ KeyBlock *BKE_keyblock_from_object(Object *ob)
{
Key *key = BKE_key_from_object(ob);
if (key) {
KeyBlock *kb = static_cast<KeyBlock *>(BLI_findlink(&key->block, ob->shapenr - 1));
return kb;
}
return nullptr;
return BKE_keyblock_find_by_index(key, ob->shapenr - 1);
}
KeyBlock *BKE_keyblock_from_object_reference(Object *ob)
@ -1916,21 +1911,13 @@ KeyBlock *BKE_keyblock_from_object_reference(Object *ob)
return nullptr;
}
KeyBlock *BKE_keyblock_from_key(Key *key, int index)
KeyBlock *BKE_keyblock_find_by_index(Key *key, int index)
{
if (key) {
KeyBlock *kb = static_cast<KeyBlock *>(key->block.first);
for (int i = 1; i < key->totkey; i++) {
kb = kb->next;
if (index == i) {
return kb;
}
}
if (!key) {
return nullptr;
}
return nullptr;
return static_cast<KeyBlock *>(BLI_findlink(&key->block, index));
}
KeyBlock *BKE_keyblock_find_name(Key *key, const char name[])

View File

@ -39,7 +39,7 @@
#include "BKE_idtype.h"
#include "BKE_lattice.hh"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_main.hh"
#include "BKE_modifier.hh"
#include "BKE_object.hh"

View File

@ -52,7 +52,7 @@
#include "BKE_key.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_override.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_lib_remap.hh"
#include "BKE_main.hh"
#include "BKE_main_namemap.hh"

View File

@ -36,7 +36,7 @@
#include "BKE_layer.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_override.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_lib_remap.hh"
#include "BKE_main.hh"
#include "BKE_main_namemap.hh"

View File

@ -19,7 +19,7 @@
#include "BKE_idprop.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_main.hh"
#include "BKE_node.h"

View File

@ -22,7 +22,7 @@
#include "BKE_curve.hh"
#include "BKE_layer.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_lib_remap.hh"
#include "BKE_main.hh"
#include "BKE_material.h"

View File

@ -24,7 +24,7 @@
#include "BKE_bpath.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_library.hh"
#include "BKE_main.hh"
#include "BKE_main_namemap.hh"

View File

@ -28,7 +28,7 @@
#include "BKE_icons.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_light.h"
#include "BKE_main.hh"
#include "BKE_node.h"

View File

@ -20,7 +20,7 @@
#include "BKE_anim_data.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_lightprobe.h"
#include "BKE_main.hh"

View File

@ -31,7 +31,7 @@
#include "BKE_freestyle.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_linestyle.h"
#include "BKE_main.hh"
#include "BKE_node.hh"

View File

@ -28,7 +28,7 @@
#include "BKE_global.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_lib_remap.hh"
#include "BKE_main.hh"
#include "BKE_main_idmap.hh"

View File

@ -35,7 +35,7 @@
#include "BKE_anim_data.h"
#include "BKE_image.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_main.hh"
#include "BKE_mask.h"
#include "BKE_movieclip.h"

View File

@ -56,7 +56,7 @@
#include "BKE_idtype.h"
#include "BKE_image.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_main.hh"
#include "BKE_material.h"
#include "BKE_mesh.hh"

View File

@ -47,7 +47,7 @@
#include "BKE_lattice.hh"
#include "BKE_layer.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_material.h"
#include "BKE_mball.h"
#include "BKE_mball_tessellate.h"

View File

@ -51,7 +51,7 @@
#include "BKE_idtype.h"
#include "BKE_key.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_main.hh"
#include "BKE_material.h"
#include "BKE_mesh.hh"
@ -645,6 +645,25 @@ MutableSpan<MDeformVert> Mesh::deform_verts_for_write()
namespace blender::bke {
void mesh_ensure_default_color_attribute_on_add(Mesh &mesh,
const AttributeIDRef &id,
AttrDomain domain,
eCustomDataType data_type)
{
if (id.is_anonymous()) {
return;
}
if (!(CD_TYPE_AS_MASK(data_type) & CD_MASK_COLOR_ALL) ||
!(ATTR_DOMAIN_AS_MASK(domain) & ATTR_DOMAIN_MASK_COLOR))
{
return;
}
if (mesh.default_color_attribute) {
return;
}
mesh.default_color_attribute = BLI_strdupn(id.name().data(), id.name().size());
}
static void mesh_ensure_cdlayers_primary(Mesh &mesh)
{
MutableAttributeAccessor attributes = mesh.attributes_for_write();

View File

@ -35,7 +35,7 @@
#include "BKE_geometry_set_instances.hh"
#include "BKE_key.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_main.hh"
#include "BKE_material.h"
#include "BKE_mball.h"

View File

@ -16,7 +16,7 @@
#include "DNA_object_types.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_mesh.hh"
#include "BKE_mesh_fair.hh"
#include "BKE_mesh_mapping.hh"

View File

@ -17,7 +17,7 @@
#include "BKE_attribute.hh"
#include "BKE_deform.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_mesh.hh"
#include "BKE_mesh_mirror.hh"
#include "BKE_modifier.hh"

View File

@ -55,7 +55,7 @@
#include "BKE_idtype.h"
#include "BKE_key.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_mesh.hh"
#include "BKE_mesh_wrapper.hh"
#include "BKE_multires.hh"

View File

@ -51,7 +51,7 @@
#include "BKE_idtype.h"
#include "BKE_image.h" /* openanim */
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_main.hh"
#include "BKE_movieclip.h"
#include "BKE_node.h"
@ -142,10 +142,10 @@ static void movie_clip_foreach_cache(ID *id,
MovieClip *movie_clip = (MovieClip *)id;
IDCacheKey key{};
key.id_session_uuid = id->session_uuid;
key.offset_in_ID = offsetof(MovieClip, cache);
key.identifier = offsetof(MovieClip, cache);
function_callback(id, &key, (void **)&movie_clip->cache, 0, user_data);
key.offset_in_ID = offsetof(MovieClip, tracking.camera.intrinsics);
key.identifier = offsetof(MovieClip, tracking.camera.intrinsics);
function_callback(id, &key, (void **)&movie_clip->tracking.camera.intrinsics, 0, user_data);
}

View File

@ -34,7 +34,7 @@
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_main.hh"
#include "BKE_nla.h"
#include "BKE_sound.h"

View File

@ -63,7 +63,7 @@
#include "BKE_idtype.h"
#include "BKE_image_format.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_main.hh"
#include "BKE_node.hh"
#include "BKE_node_runtime.hh"
@ -400,7 +400,7 @@ static void node_foreach_cache(ID *id,
bNodeTree *nodetree = reinterpret_cast<bNodeTree *>(id);
IDCacheKey key = {0};
key.id_session_uuid = id->session_uuid;
key.offset_in_ID = offsetof(bNodeTree, previews);
key.identifier = offsetof(bNodeTree, previews);
/* TODO: see also `direct_link_nodetree()` in `readfile.cc`. */
#if 0
@ -410,7 +410,7 @@ static void node_foreach_cache(ID *id,
if (nodetree->type == NTREE_COMPOSIT) {
for (bNode *node : nodetree->all_nodes()) {
if (node->type == CMP_NODE_MOVIEDISTORTION) {
key.offset_in_ID = size_t(BLI_ghashutil_strhash_p(node->name));
key.identifier = size_t(BLI_ghashutil_strhash_p(node->name));
function_callback(id, &key, static_cast<void **>(&node->storage), 0, user_data);
}
}
@ -2529,6 +2529,7 @@ bNode *nodeAddNode(const bContext *C, bNodeTree *ntree, const char *idname)
node->runtime = MEM_new<bNodeRuntime>(__func__);
BLI_addtail(&ntree->nodes, node);
nodeUniqueID(ntree, node);
node->ui_order = ntree->all_nodes().size();
STRNCPY(node->idname, idname);
blender::bke::node_set_typeinfo(C, ntree, node, nodeTypeFind(idname));

View File

@ -4,7 +4,7 @@
#include "BKE_idprop.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_query.hh"
#include "BKE_node.hh"
#include "BKE_node_tree_interface.hh"

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