UI: Region polling support #105088
|
@ -870,6 +870,26 @@ an issue but, due to internal implementation details, currently are:
|
|||
thus breaking any current iteration over ``Collection.all_objects``.
|
||||
|
||||
|
||||
.. rubric:: Do not:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# `all_objects` is an iterator. Using it directly while performing operations on its members that will update
|
||||
# the memory accessed by the `all_objects` iterator will lead to invalid memory accesses and crashes.
|
||||
for object in bpy.data.collections["Collection"].all_objects:
|
||||
object.hide_viewport = True
|
||||
|
||||
|
||||
.. rubric:: Do:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# `all_objects[:]` is an independent list generated from the iterator. As long as no objects are deleted,
|
||||
# its content will remain valid even if the data accessed by the `all_objects` iterator is modified.
|
||||
for object in bpy.data.collections["Collection"].all_objects[:]:
|
||||
object.hide_viewport = True
|
||||
|
||||
|
||||
sys.exit
|
||||
========
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit ef57e2c2c65933a68811d58b40ed62b775e9b4b0
|
||||
Subproject commit 4a581c54af9b92cb670d750951b9382160f10f3e
|
|
@ -1 +1 @@
|
|||
Subproject commit bde68da02fde93968dc11b52d42060ac3b81ed37
|
||||
Subproject commit 0b0052bd53ad8249ed07dfb87705c338af698bde
|
|
@ -1 +1 @@
|
|||
Subproject commit e6179b3b112298e131bbd0faf648bf0d392b6cdd
|
||||
Subproject commit 96143b1a8b037ea3c81f065f557025db9fe1ace3
|
|
@ -252,6 +252,11 @@ class NLA_OT_bake(Operator):
|
|||
do_pose = 'POSE' in self.bake_types
|
||||
do_object = 'OBJECT' in self.bake_types
|
||||
|
||||
if do_pose and self.only_selected:
|
||||
pose_bones = context.selected_pose_bones or []
|
||||
armatures = {pose_bone.id_data for pose_bone in pose_bones}
|
||||
objects = list(armatures)
|
||||
else:
|
||||
objects = context.selected_editable_objects
|
||||
if do_pose and not do_object:
|
||||
objects = [obj for obj in objects if obj.pose is not None]
|
||||
|
|
|
@ -97,13 +97,12 @@ class ASSET_OT_open_containing_blend_file(Operator):
|
|||
|
||||
def execute(self, context):
|
||||
asset_file_handle = context.asset_file_handle
|
||||
asset_library_ref = context.asset_library_ref
|
||||
|
||||
if asset_file_handle.local_id:
|
||||
self.report({'WARNING'}, "This asset is stored in the current blend file")
|
||||
return {'CANCELLED'}
|
||||
|
||||
asset_lib_path = bpy.types.AssetHandle.get_full_library_path(asset_file_handle, asset_library_ref)
|
||||
asset_lib_path = bpy.types.AssetHandle.get_full_library_path(asset_file_handle)
|
||||
self.open_in_new_blender(asset_lib_path)
|
||||
|
||||
wm = context.window_manager
|
||||
|
|
|
@ -862,8 +862,7 @@ def asset_path_str_get(_self):
|
|||
if asset_file_handle.local_id:
|
||||
return "Current File"
|
||||
|
||||
asset_library_ref = bpy.context.asset_library_ref
|
||||
return bpy.types.AssetHandle.get_full_library_path(asset_file_handle, asset_library_ref)
|
||||
return bpy.types.AssetHandle.get_full_library_path(asset_file_handle)
|
||||
|
||||
|
||||
def register_props():
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup asset_system
|
||||
*
|
||||
* \brief Information to uniquely identify and locate an asset.
|
||||
*
|
||||
* https://wiki.blender.org/wiki/Source/Architecture/Asset_System/Back_End#Asset_Identifier
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace blender::asset_system {
|
||||
|
||||
class AssetIdentifier {
|
||||
std::shared_ptr<std::string> library_root_path_;
|
||||
std::string relative_asset_path_;
|
||||
|
||||
public:
|
||||
AssetIdentifier(std::shared_ptr<std::string> library_root_path, std::string relative_asset_path);
|
||||
AssetIdentifier(AssetIdentifier &&) = default;
|
||||
AssetIdentifier(const AssetIdentifier &) = default;
|
||||
|
||||
std::string full_path() const;
|
||||
};
|
||||
|
||||
} // namespace blender::asset_system
|
|
@ -24,6 +24,7 @@ struct Main;
|
|||
|
||||
namespace blender::asset_system {
|
||||
|
||||
class AssetIdentifier;
|
||||
class AssetRepresentation;
|
||||
class AssetStorage;
|
||||
|
||||
|
@ -35,8 +36,10 @@ class AssetStorage;
|
|||
*/
|
||||
class AssetLibrary {
|
||||
/** If this is an asset library on disk, the top-level directory path. Normalized using
|
||||
* #normalize_directory_path().*/
|
||||
std::string root_path_;
|
||||
* #normalize_directory_path(). Shared pointer so assets can safely point to it, and don't have
|
||||
* to hold a copy (which is the size of `std::string` + the allocated buffer, if no short string
|
||||
* optimization is used). With thousands of assets this might make a reasonable difference. */
|
||||
std::shared_ptr<std::string> root_path_;
|
||||
|
||||
/** Storage for assets (better said their representations) that are considered to be part of this
|
||||
* library. Assets are not automatically loaded into this when loading an asset library. Assets
|
||||
|
@ -85,10 +88,16 @@ class AssetLibrary {
|
|||
* representation is not needed anymore, it must be freed using #remove_asset(), or there will be
|
||||
* leaking that's only cleared when the library storage is destructed (typically on exit or
|
||||
* loading a different file).
|
||||
*
|
||||
* \param relative_asset_path: The path of the asset relative to the asset library root. With
|
||||
* this the asset must be uniquely identifiable within the asset
|
||||
* library.
|
||||
*/
|
||||
AssetRepresentation &add_external_asset(StringRef name, std::unique_ptr<AssetMetaData> metadata);
|
||||
AssetRepresentation &add_external_asset(StringRef relative_asset_path,
|
||||
StringRef name,
|
||||
std::unique_ptr<AssetMetaData> metadata);
|
||||
/** See #AssetLibrary::add_external_asset(). */
|
||||
AssetRepresentation &add_local_id_asset(ID &id);
|
||||
AssetRepresentation &add_local_id_asset(StringRef relative_asset_path, ID &id);
|
||||
/** Remove an asset from the library that was added using #add_external_asset() or
|
||||
* #add_local_id_asset(). Can usually be expected to be constant time complexity (worst case may
|
||||
* differ).
|
||||
|
@ -123,6 +132,12 @@ class AssetLibrary {
|
|||
|
||||
void on_blend_save_post(Main *bmain, PointerRNA **pointers, int num_pointers);
|
||||
|
||||
/**
|
||||
* Create an asset identifier from the root path of this asset library and the given relative
|
||||
* asset path (relative to the asset library root directory).
|
||||
*/
|
||||
AssetIdentifier derive_asset_identifier(StringRef relative_asset_path);
|
||||
|
||||
StringRefNull root_path() const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -16,21 +16,23 @@
|
|||
|
||||
#include "BLI_string_ref.hh"
|
||||
|
||||
#include "AS_asset_identifier.hh"
|
||||
|
||||
struct AssetMetaData;
|
||||
struct ID;
|
||||
|
||||
namespace blender::asset_system {
|
||||
|
||||
class AssetRepresentation {
|
||||
struct ExternalAsset {
|
||||
std::string name;
|
||||
std::unique_ptr<AssetMetaData> metadata_ = nullptr;
|
||||
};
|
||||
|
||||
AssetIdentifier identifier_;
|
||||
/** Indicate if this is a local or external asset, and as such, which of the union members below
|
||||
* should be used. */
|
||||
const bool is_local_id_ = false;
|
||||
|
||||
struct ExternalAsset {
|
||||
std::string name;
|
||||
std::unique_ptr<AssetMetaData> metadata_ = nullptr;
|
||||
};
|
||||
union {
|
||||
ExternalAsset external_asset_;
|
||||
ID *local_asset_id_ = nullptr; /* Non-owning. */
|
||||
|
@ -40,10 +42,12 @@ class AssetRepresentation {
|
|||
|
||||
public:
|
||||
/** Constructs an asset representation for an external ID. The asset will not be editable. */
|
||||
explicit AssetRepresentation(StringRef name, std::unique_ptr<AssetMetaData> metadata);
|
||||
AssetRepresentation(AssetIdentifier &&identifier,
|
||||
StringRef name,
|
||||
std::unique_ptr<AssetMetaData> metadata);
|
||||
/** Constructs an asset representation for an ID stored in the current file. This makes the asset
|
||||
* local and fully editable. */
|
||||
explicit AssetRepresentation(ID &id);
|
||||
AssetRepresentation(AssetIdentifier &&identifier, ID &id);
|
||||
AssetRepresentation(AssetRepresentation &&other);
|
||||
/* Non-copyable type. */
|
||||
AssetRepresentation(const AssetRepresentation &other) = delete;
|
||||
|
@ -55,6 +59,8 @@ class AssetRepresentation {
|
|||
/* Non-copyable type. */
|
||||
AssetRepresentation &operator=(const AssetRepresentation &other) = delete;
|
||||
|
||||
const AssetIdentifier &get_identifier() const;
|
||||
|
||||
StringRefNull get_name() const;
|
||||
AssetMetaData &get_metadata() const;
|
||||
/** Returns if this asset is stored inside this current file, and as such fully editable. */
|
||||
|
@ -62,3 +68,8 @@ class AssetRepresentation {
|
|||
};
|
||||
|
||||
} // namespace blender::asset_system
|
||||
|
||||
/* C-Handle */
|
||||
struct AssetRepresentation;
|
||||
|
||||
const std::string AS_asset_representation_full_path_get(const ::AssetRepresentation *asset);
|
||||
|
|
|
@ -17,6 +17,7 @@ set(SRC
|
|||
intern/asset_catalog.cc
|
||||
intern/asset_catalog_path.cc
|
||||
intern/asset_catalog_tree.cc
|
||||
intern/asset_identifier.cc
|
||||
intern/asset_library.cc
|
||||
intern/asset_library_service.cc
|
||||
intern/asset_representation.cc
|
||||
|
@ -26,6 +27,7 @@ set(SRC
|
|||
AS_asset_catalog.hh
|
||||
AS_asset_catalog_path.hh
|
||||
AS_asset_catalog_tree.hh
|
||||
AS_asset_identifier.hh
|
||||
AS_asset_library.hh
|
||||
AS_asset_representation.hh
|
||||
intern/asset_library_service.hh
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup asset_system
|
||||
*/
|
||||
|
||||
#include "BLI_path_util.h"
|
||||
#include <iostream>
|
||||
|
||||
#include "AS_asset_identifier.hh"
|
||||
|
||||
namespace blender::asset_system {
|
||||
|
||||
AssetIdentifier::AssetIdentifier(std::shared_ptr<std::string> library_root_path,
|
||||
std::string relative_asset_path)
|
||||
: library_root_path_(library_root_path), relative_asset_path_(relative_asset_path)
|
||||
{
|
||||
}
|
||||
|
||||
std::string AssetIdentifier::full_path() const
|
||||
{
|
||||
char path[FILE_MAX];
|
||||
BLI_path_join(path, sizeof(path), library_root_path_->c_str(), relative_asset_path_.c_str());
|
||||
return path;
|
||||
}
|
||||
|
||||
} // namespace blender::asset_system
|
|
@ -7,6 +7,7 @@
|
|||
#include <memory>
|
||||
|
||||
#include "AS_asset_catalog_tree.hh"
|
||||
#include "AS_asset_identifier.hh"
|
||||
#include "AS_asset_library.h"
|
||||
#include "AS_asset_library.hh"
|
||||
#include "AS_asset_representation.hh"
|
||||
|
@ -128,7 +129,7 @@ void AS_asset_library_remap_ids(const IDRemapper *mappings)
|
|||
namespace blender::asset_system {
|
||||
|
||||
AssetLibrary::AssetLibrary(StringRef root_path)
|
||||
: root_path_(utils::normalize_directory_path(root_path)),
|
||||
: root_path_(std::make_shared<std::string>(utils::normalize_directory_path(root_path))),
|
||||
asset_storage_(std::make_unique<AssetStorage>()),
|
||||
catalog_service(std::make_unique<AssetCatalogService>())
|
||||
{
|
||||
|
@ -143,7 +144,7 @@ AssetLibrary::~AssetLibrary()
|
|||
|
||||
void AssetLibrary::load_catalogs()
|
||||
{
|
||||
auto catalog_service = std::make_unique<AssetCatalogService>(root_path_);
|
||||
auto catalog_service = std::make_unique<AssetCatalogService>(root_path());
|
||||
catalog_service->load_from_disk();
|
||||
this->catalog_service = std::move(catalog_service);
|
||||
}
|
||||
|
@ -153,15 +154,18 @@ void AssetLibrary::refresh()
|
|||
this->catalog_service->reload_catalogs();
|
||||
}
|
||||
|
||||
AssetRepresentation &AssetLibrary::add_external_asset(StringRef name,
|
||||
AssetRepresentation &AssetLibrary::add_external_asset(StringRef relative_asset_path,
|
||||
StringRef name,
|
||||
std::unique_ptr<AssetMetaData> metadata)
|
||||
{
|
||||
return asset_storage_->add_external_asset(name, std::move(metadata));
|
||||
AssetIdentifier identifier = derive_asset_identifier(relative_asset_path);
|
||||
return asset_storage_->add_external_asset(std::move(identifier), name, std::move(metadata));
|
||||
}
|
||||
|
||||
AssetRepresentation &AssetLibrary::add_local_id_asset(ID &id)
|
||||
AssetRepresentation &AssetLibrary::add_local_id_asset(StringRef relative_asset_path, ID &id)
|
||||
{
|
||||
return asset_storage_->add_local_id_asset(id);
|
||||
AssetIdentifier identifier = derive_asset_identifier(relative_asset_path);
|
||||
return asset_storage_->add_local_id_asset(std::move(identifier), id);
|
||||
}
|
||||
|
||||
bool AssetLibrary::remove_asset(AssetRepresentation &asset)
|
||||
|
@ -229,9 +233,9 @@ void AssetLibrary::on_blend_save_post(struct Main *main,
|
|||
}
|
||||
}
|
||||
|
||||
StringRefNull AssetLibrary::root_path() const
|
||||
AssetIdentifier AssetLibrary::derive_asset_identifier(StringRef relative_asset_path)
|
||||
{
|
||||
return root_path_;
|
||||
return AssetIdentifier(root_path_, relative_asset_path);
|
||||
}
|
||||
|
||||
void AssetLibrary::refresh_catalog_simplename(struct AssetMetaData *asset_data)
|
||||
|
@ -249,6 +253,11 @@ void AssetLibrary::refresh_catalog_simplename(struct AssetMetaData *asset_data)
|
|||
STRNCPY(asset_data->catalog_simple_name, catalog->simple_name.c_str());
|
||||
}
|
||||
|
||||
StringRefNull AssetLibrary::root_path() const
|
||||
{
|
||||
return *root_path_;
|
||||
}
|
||||
|
||||
/* TODO get rid of this. */
|
||||
Vector<AssetLibraryReference> all_valid_asset_library_refs()
|
||||
{
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "DNA_ID.h"
|
||||
#include "DNA_asset_types.h"
|
||||
|
||||
#include "AS_asset_identifier.hh"
|
||||
#include "AS_asset_representation.h"
|
||||
#include "AS_asset_representation.hh"
|
||||
|
||||
|
@ -16,14 +17,17 @@
|
|||
|
||||
namespace blender::asset_system {
|
||||
|
||||
AssetRepresentation::AssetRepresentation(StringRef name, std::unique_ptr<AssetMetaData> metadata)
|
||||
: is_local_id_(false), external_asset_()
|
||||
AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier,
|
||||
StringRef name,
|
||||
std::unique_ptr<AssetMetaData> metadata)
|
||||
: identifier_(identifier), is_local_id_(false), external_asset_()
|
||||
{
|
||||
external_asset_.name = name;
|
||||
external_asset_.metadata_ = std::move(metadata);
|
||||
}
|
||||
|
||||
AssetRepresentation::AssetRepresentation(ID &id) : is_local_id_(true), local_asset_id_(&id)
|
||||
AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier, ID &id)
|
||||
: identifier_(identifier), is_local_id_(true), local_asset_id_(&id)
|
||||
{
|
||||
if (!id.asset_data) {
|
||||
throw std::invalid_argument("Passed ID is not an asset");
|
||||
|
@ -31,7 +35,7 @@ AssetRepresentation::AssetRepresentation(ID &id) : is_local_id_(true), local_ass
|
|||
}
|
||||
|
||||
AssetRepresentation::AssetRepresentation(AssetRepresentation &&other)
|
||||
: is_local_id_(other.is_local_id_)
|
||||
: identifier_(std::move(other.identifier_)), is_local_id_(other.is_local_id_)
|
||||
{
|
||||
if (is_local_id_) {
|
||||
local_asset_id_ = other.local_asset_id_;
|
||||
|
@ -49,6 +53,11 @@ AssetRepresentation::~AssetRepresentation()
|
|||
}
|
||||
}
|
||||
|
||||
const AssetIdentifier &AssetRepresentation::get_identifier() const
|
||||
{
|
||||
return identifier_;
|
||||
}
|
||||
|
||||
StringRefNull AssetRepresentation::get_name() const
|
||||
{
|
||||
if (is_local_id_) {
|
||||
|
@ -70,12 +79,20 @@ bool AssetRepresentation::is_local_id() const
|
|||
|
||||
} // namespace blender::asset_system
|
||||
|
||||
using namespace blender;
|
||||
|
||||
const std::string AS_asset_representation_full_path_get(const AssetRepresentation *asset_handle)
|
||||
{
|
||||
const asset_system::AssetRepresentation *asset =
|
||||
reinterpret_cast<const asset_system::AssetRepresentation *>(asset_handle);
|
||||
const asset_system::AssetIdentifier &identifier = asset->get_identifier();
|
||||
return identifier.full_path();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/** \name C-API
|
||||
* \{ */
|
||||
|
||||
using namespace blender;
|
||||
|
||||
const char *AS_asset_representation_name_get(const AssetRepresentation *asset_handle)
|
||||
{
|
||||
const asset_system::AssetRepresentation *asset =
|
||||
|
|
|
@ -15,16 +15,18 @@
|
|||
|
||||
namespace blender::asset_system {
|
||||
|
||||
AssetRepresentation &AssetStorage::add_local_id_asset(ID &id)
|
||||
AssetRepresentation &AssetStorage::add_local_id_asset(AssetIdentifier &&identifier, ID &id)
|
||||
{
|
||||
return *local_id_assets_.lookup_key_or_add(std::make_unique<AssetRepresentation>(id));
|
||||
return *local_id_assets_.lookup_key_or_add(
|
||||
std::make_unique<AssetRepresentation>(std::move(identifier), id));
|
||||
}
|
||||
|
||||
AssetRepresentation &AssetStorage::add_external_asset(StringRef name,
|
||||
AssetRepresentation &AssetStorage::add_external_asset(AssetIdentifier &&identifier,
|
||||
StringRef name,
|
||||
std::unique_ptr<AssetMetaData> metadata)
|
||||
{
|
||||
return *external_assets_.lookup_key_or_add(
|
||||
std::make_unique<AssetRepresentation>(name, std::move(metadata)));
|
||||
std::make_unique<AssetRepresentation>(std::move(identifier), name, std::move(metadata)));
|
||||
}
|
||||
|
||||
bool AssetStorage::remove_asset(AssetRepresentation &asset)
|
||||
|
|
|
@ -19,6 +19,7 @@ struct IDRemapper;
|
|||
|
||||
namespace blender::asset_system {
|
||||
|
||||
class AssetIdentifier;
|
||||
class AssetRepresentation;
|
||||
|
||||
class AssetStorage {
|
||||
|
@ -34,9 +35,11 @@ class AssetStorage {
|
|||
|
||||
public:
|
||||
/** See #AssetLibrary::add_external_asset(). */
|
||||
AssetRepresentation &add_external_asset(StringRef name, std::unique_ptr<AssetMetaData> metadata);
|
||||
AssetRepresentation &add_external_asset(AssetIdentifier &&identifier,
|
||||
StringRef name,
|
||||
std::unique_ptr<AssetMetaData> metadata);
|
||||
/** See #AssetLibrary::add_external_asset(). */
|
||||
AssetRepresentation &add_local_id_asset(ID &id);
|
||||
AssetRepresentation &add_local_id_asset(AssetIdentifier &&identifier, ID &id);
|
||||
|
||||
/** See #AssetLibrary::remove_asset(). */
|
||||
bool remove_asset(AssetRepresentation &asset);
|
||||
|
|
|
@ -38,44 +38,53 @@ enum {
|
|||
* Indicates whether this is direct (i.e. by local data) or indirect (i.e. by linked data) usage.
|
||||
*/
|
||||
IDWALK_CB_INDIRECT_USAGE = (1 << 2),
|
||||
/**
|
||||
* Indicates that this is a direct weak link usage, i.e. if the user is a local ID, and is using
|
||||
* (pointing to) a linked ID, that usage does not make the linked ID directly linked.
|
||||
*
|
||||
* E.g. usages of linked collections or objects by ViewLayerCollections or Bases in scenes.
|
||||
*
|
||||
* See also #LIB_INDIRECT_WEAK_LINK in DNA_ID.h
|
||||
*/
|
||||
IDWALK_CB_DIRECT_WEAK_LINK = (1 << 3),
|
||||
|
||||
/**
|
||||
* That ID is used as mere sub-data by its owner (only case currently: those root nodetrees in
|
||||
* materials etc., and the Scene's master collections).
|
||||
* This means callback shall not *do* anything, only use this as informative data if it needs it.
|
||||
*/
|
||||
IDWALK_CB_EMBEDDED = (1 << 3),
|
||||
IDWALK_CB_EMBEDDED = (1 << 4),
|
||||
|
||||
/**
|
||||
* That ID is not really used by its owner, it's just an internal hint/helper.
|
||||
* This marks the 'from' pointers issue, like Key->from.
|
||||
* How to handle that kind of cases totally depends on what caller code is doing... */
|
||||
IDWALK_CB_LOOPBACK = (1 << 4),
|
||||
IDWALK_CB_LOOPBACK = (1 << 5),
|
||||
|
||||
/** That ID is used as library override's reference by its owner. */
|
||||
IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE = (1 << 5),
|
||||
IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE = (1 << 6),
|
||||
|
||||
/** That ID pointer is not overridable. */
|
||||
IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE = (1 << 6),
|
||||
IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE = (1 << 7),
|
||||
|
||||
/**
|
||||
* Indicates that this is an internal runtime ID pointer, like e.g. `ID.newid` or `ID.original`.
|
||||
* \note Those should be ignored in most cases, and won't be processed/generated anyway unless
|
||||
* `IDWALK_DO_INTERNAL_RUNTIME_POINTERS` option is enabled.
|
||||
*/
|
||||
IDWALK_CB_INTERNAL = (1 << 7),
|
||||
IDWALK_CB_INTERNAL = (1 << 8),
|
||||
|
||||
/**
|
||||
* This ID usage is fully refcounted.
|
||||
* Callback is responsible to deal accordingly with #ID.us if needed.
|
||||
*/
|
||||
IDWALK_CB_USER = (1 << 8),
|
||||
IDWALK_CB_USER = (1 << 9),
|
||||
/**
|
||||
* This ID usage is not refcounted, but at least one user should be generated by it (to avoid
|
||||
* e.g. losing the used ID on save/reload).
|
||||
* Callback is responsible to deal accordingly with #ID.us if needed.
|
||||
*/
|
||||
IDWALK_CB_USER_ONE = (1 << 9),
|
||||
IDWALK_CB_USER_ONE = (1 << 10),
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
|
@ -46,11 +46,6 @@ class bNodeTreeRuntime : NonCopyable, NonMovable {
|
|||
*/
|
||||
uint8_t runtime_flag = 0;
|
||||
|
||||
/** Flag to prevent re-entrant update calls. */
|
||||
short is_updating = 0;
|
||||
/** Generic temporary flag for recursion check (DFS/BFS). */
|
||||
short done = 0;
|
||||
|
||||
/** Execution data.
|
||||
*
|
||||
* XXX It would be preferable to completely move this data out of the underlying node tree,
|
||||
|
|
|
@ -761,7 +761,8 @@ static void scene_foreach_layer_collection(LibraryForeachIDData *data, ListBase
|
|||
(lc->collection->id.flag & LIB_EMBEDDED_DATA) != 0) ?
|
||||
IDWALK_CB_EMBEDDED :
|
||||
IDWALK_CB_NOP;
|
||||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, lc->collection, cb_flag);
|
||||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(
|
||||
data, lc->collection, cb_flag | IDWALK_CB_DIRECT_WEAK_LINK);
|
||||
scene_foreach_layer_collection(data, &lc->layer_collections);
|
||||
}
|
||||
}
|
||||
|
@ -834,8 +835,11 @@ static void scene_foreach_id(ID *id, LibraryForeachIDData *data)
|
|||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, view_layer->mat_override, IDWALK_CB_USER);
|
||||
BKE_view_layer_synced_ensure(scene, view_layer);
|
||||
LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) {
|
||||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(
|
||||
data, base->object, IDWALK_CB_NOP | IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE);
|
||||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data,
|
||||
base->object,
|
||||
IDWALK_CB_NOP |
|
||||
IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE |
|
||||
IDWALK_CB_DIRECT_WEAK_LINK);
|
||||
}
|
||||
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
||||
|
|
|
@ -169,7 +169,7 @@ template<
|
|||
/**
|
||||
* Number of bits that can be stored in the vector without doing an allocation.
|
||||
*/
|
||||
int64_t InlineBufferCapacity = 32,
|
||||
int64_t InlineBufferCapacity = 64,
|
||||
/**
|
||||
* The allocator used by this vector. Should rarely be changed, except when you don't want that
|
||||
* MEM_* is used internally.
|
||||
|
@ -200,10 +200,10 @@ class BitVector {
|
|||
int64_t capacity_in_bits_;
|
||||
|
||||
/** Used for allocations when the inline buffer is too small. */
|
||||
Allocator allocator_;
|
||||
BLI_NO_UNIQUE_ADDRESS Allocator allocator_;
|
||||
|
||||
/** Contains the bits as long as the vector is small enough. */
|
||||
TypedBuffer<uint8_t, BytesInInlineBuffer> inline_buffer_;
|
||||
BLI_NO_UNIQUE_ADDRESS TypedBuffer<uint8_t, BytesInInlineBuffer> inline_buffer_;
|
||||
|
||||
public:
|
||||
BitVector(Allocator allocator = {}) noexcept : allocator_(allocator)
|
||||
|
|
|
@ -33,14 +33,14 @@
|
|||
*
|
||||
* There are three main ways to provide a hash table implementation with a custom hash function.
|
||||
*
|
||||
* - When you want to provide a default hash function for your own custom type: Add a `hash`
|
||||
* - When you want to provide a default hash function for your own custom type: Add a `hash()`
|
||||
* member function to it. The function should return `uint64_t` and take no arguments. This
|
||||
* method will be called by the default implementation of #DefaultHash. It will automatically be
|
||||
* used by hash table implementations.
|
||||
*
|
||||
* - When you want to provide a default hash function for a type that you cannot modify: Add a new
|
||||
* specialization to the #DefaultHash struct. This can be done by writing code like below in
|
||||
* either global or BLI namespace.
|
||||
* either global or `blender` namespace.
|
||||
*
|
||||
* template<> struct blender::DefaultHash<TheType> {
|
||||
* uint64_t operator()(const TheType &value) const {
|
||||
|
|
|
@ -102,6 +102,41 @@ template<typename T, BLI_ENABLE_IF((is_math_float_type<T>))> inline T fract(cons
|
|||
return a - std::floor(a);
|
||||
}
|
||||
|
||||
template<typename T> inline T cos(const T &a)
|
||||
{
|
||||
return std::cos(a);
|
||||
}
|
||||
|
||||
template<typename T> inline T sin(const T &a)
|
||||
{
|
||||
return std::sin(a);
|
||||
}
|
||||
|
||||
template<typename T> inline T tan(const T &a)
|
||||
{
|
||||
return std::tan(a);
|
||||
}
|
||||
|
||||
template<typename T> inline T acos(const T &a)
|
||||
{
|
||||
return std::acos(a);
|
||||
}
|
||||
|
||||
template<typename T> inline T asin(const T &a)
|
||||
{
|
||||
return std::asin(a);
|
||||
}
|
||||
|
||||
template<typename T> inline T atan(const T &a)
|
||||
{
|
||||
return std::atan(a);
|
||||
}
|
||||
|
||||
template<typename T> inline T atan2(const T &a, const T &b)
|
||||
{
|
||||
return std::atan2(a, b);
|
||||
}
|
||||
|
||||
template<typename T,
|
||||
typename FactorT,
|
||||
BLI_ENABLE_IF((std::is_arithmetic_v<T>)),
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "BLI_endian_switch.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_linklist.h"
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_memarena.h"
|
||||
#include "BLI_mempool.h"
|
||||
|
@ -229,119 +230,19 @@ static const char *library_parent_filepath(Library *lib)
|
|||
/** \name OldNewMap API
|
||||
* \{ */
|
||||
|
||||
struct OldNew {
|
||||
const void *oldp;
|
||||
struct NewAddress {
|
||||
void *newp;
|
||||
/* `nr` is "user count" for data, and ID code for libdata. */
|
||||
int nr;
|
||||
};
|
||||
|
||||
struct OldNewMap {
|
||||
/* Array that stores the actual entries. */
|
||||
OldNew *entries;
|
||||
int nentries;
|
||||
/* Hash-map that stores indices into the `entries` array. */
|
||||
int32_t *map;
|
||||
|
||||
int capacity_exp;
|
||||
blender::Map<const void *, NewAddress> map;
|
||||
};
|
||||
|
||||
#define ENTRIES_CAPACITY(onm) (1ll << (onm)->capacity_exp)
|
||||
#define MAP_CAPACITY(onm) (1ll << ((onm)->capacity_exp + 1))
|
||||
#define SLOT_MASK(onm) (MAP_CAPACITY(onm) - 1)
|
||||
#define DEFAULT_SIZE_EXP 6
|
||||
#define PERTURB_SHIFT 5
|
||||
|
||||
/* based on the probing algorithm used in Python dicts. */
|
||||
#define ITER_SLOTS(onm, KEY, SLOT_NAME, INDEX_NAME) \
|
||||
uint32_t hash = BLI_ghashutil_ptrhash(KEY); \
|
||||
uint32_t mask = SLOT_MASK(onm); \
|
||||
uint perturb = hash; \
|
||||
int SLOT_NAME = mask & hash; \
|
||||
int INDEX_NAME = onm->map[SLOT_NAME]; \
|
||||
for (;; SLOT_NAME = mask & ((5 * SLOT_NAME) + 1 + perturb), \
|
||||
perturb >>= PERTURB_SHIFT, \
|
||||
INDEX_NAME = onm->map[SLOT_NAME])
|
||||
|
||||
static void oldnewmap_insert_index_in_map(OldNewMap *onm, const void *ptr, int index)
|
||||
{
|
||||
ITER_SLOTS (onm, ptr, slot, stored_index) {
|
||||
if (stored_index == -1) {
|
||||
onm->map[slot] = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void oldnewmap_insert_or_replace(OldNewMap *onm, OldNew entry)
|
||||
{
|
||||
ITER_SLOTS (onm, entry.oldp, slot, index) {
|
||||
if (index == -1) {
|
||||
onm->entries[onm->nentries] = entry;
|
||||
onm->map[slot] = onm->nentries;
|
||||
onm->nentries++;
|
||||
break;
|
||||
}
|
||||
if (onm->entries[index].oldp == entry.oldp) {
|
||||
onm->entries[index] = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static OldNew *oldnewmap_lookup_entry(const OldNewMap *onm, const void *addr)
|
||||
{
|
||||
ITER_SLOTS (onm, addr, slot, index) {
|
||||
if (index >= 0) {
|
||||
OldNew *entry = &onm->entries[index];
|
||||
if (entry->oldp == addr) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void oldnewmap_clear_map(OldNewMap *onm)
|
||||
{
|
||||
memset(onm->map, 0xFF, MAP_CAPACITY(onm) * sizeof(*onm->map));
|
||||
}
|
||||
|
||||
static void oldnewmap_increase_size(OldNewMap *onm)
|
||||
{
|
||||
onm->capacity_exp++;
|
||||
onm->entries = static_cast<OldNew *>(
|
||||
MEM_reallocN(onm->entries, sizeof(*onm->entries) * ENTRIES_CAPACITY(onm)));
|
||||
onm->map = static_cast<int32_t *>(MEM_reallocN(onm->map, sizeof(*onm->map) * MAP_CAPACITY(onm)));
|
||||
oldnewmap_clear_map(onm);
|
||||
for (int i = 0; i < onm->nentries; i++) {
|
||||
oldnewmap_insert_index_in_map(onm, onm->entries[i].oldp, i);
|
||||
}
|
||||
}
|
||||
|
||||
/* Public OldNewMap API */
|
||||
|
||||
static void oldnewmap_init_data(OldNewMap *onm, const int capacity_exp)
|
||||
{
|
||||
memset(onm, 0x0, sizeof(*onm));
|
||||
|
||||
onm->capacity_exp = capacity_exp;
|
||||
onm->entries = static_cast<OldNew *>(
|
||||
MEM_malloc_arrayN(ENTRIES_CAPACITY(onm), sizeof(*onm->entries), "OldNewMap.entries"));
|
||||
onm->map = static_cast<int32_t *>(
|
||||
MEM_malloc_arrayN(MAP_CAPACITY(onm), sizeof(*onm->map), "OldNewMap.map"));
|
||||
oldnewmap_clear_map(onm);
|
||||
}
|
||||
|
||||
static OldNewMap *oldnewmap_new()
|
||||
{
|
||||
OldNewMap *onm = static_cast<OldNewMap *>(MEM_mallocN(sizeof(*onm), "OldNewMap"));
|
||||
|
||||
oldnewmap_init_data(onm, DEFAULT_SIZE_EXP);
|
||||
|
||||
return onm;
|
||||
return MEM_new<OldNewMap>(__func__);
|
||||
}
|
||||
|
||||
static void oldnewmap_insert(OldNewMap *onm, const void *oldaddr, void *newaddr, int nr)
|
||||
|
@ -350,15 +251,7 @@ static void oldnewmap_insert(OldNewMap *onm, const void *oldaddr, void *newaddr,
|
|||
return;
|
||||
}
|
||||
|
||||
if (UNLIKELY(onm->nentries == ENTRIES_CAPACITY(onm))) {
|
||||
oldnewmap_increase_size(onm);
|
||||
}
|
||||
|
||||
OldNew entry;
|
||||
entry.oldp = oldaddr;
|
||||
entry.newp = newaddr;
|
||||
entry.nr = nr;
|
||||
oldnewmap_insert_or_replace(onm, entry);
|
||||
onm->map.add_overwrite(oldaddr, NewAddress{newaddr, nr});
|
||||
}
|
||||
|
||||
static void oldnewmap_lib_insert(FileData *fd, const void *oldaddr, ID *newaddr, int nr)
|
||||
|
@ -373,7 +266,7 @@ void blo_do_versions_oldnewmap_insert(OldNewMap *onm, const void *oldaddr, void
|
|||
|
||||
static void *oldnewmap_lookup_and_inc(OldNewMap *onm, const void *addr, bool increase_users)
|
||||
{
|
||||
OldNew *entry = oldnewmap_lookup_entry(onm, addr);
|
||||
NewAddress *entry = onm->map.lookup_ptr(addr);
|
||||
if (entry == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -383,7 +276,7 @@ static void *oldnewmap_lookup_and_inc(OldNewMap *onm, const void *addr, bool inc
|
|||
return entry->newp;
|
||||
}
|
||||
|
||||
/* for libdata, OldNew.nr has ID code, no increment */
|
||||
/* for libdata, NewAddress.nr has ID code, no increment */
|
||||
static void *oldnewmap_liblookup(OldNewMap *onm, const void *addr, const void *lib)
|
||||
{
|
||||
if (addr == nullptr) {
|
||||
|
@ -403,34 +296,19 @@ static void *oldnewmap_liblookup(OldNewMap *onm, const void *addr, const void *l
|
|||
static void oldnewmap_clear(OldNewMap *onm)
|
||||
{
|
||||
/* Free unused data. */
|
||||
for (int i = 0; i < onm->nentries; i++) {
|
||||
OldNew *entry = &onm->entries[i];
|
||||
if (entry->nr == 0) {
|
||||
MEM_freeN(entry->newp);
|
||||
entry->newp = nullptr;
|
||||
for (NewAddress &new_addr : onm->map.values()) {
|
||||
if (new_addr.nr == 0) {
|
||||
MEM_freeN(new_addr.newp);
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(onm->entries);
|
||||
MEM_freeN(onm->map);
|
||||
|
||||
oldnewmap_init_data(onm, DEFAULT_SIZE_EXP);
|
||||
onm->map.clear();
|
||||
}
|
||||
|
||||
static void oldnewmap_free(OldNewMap *onm)
|
||||
{
|
||||
MEM_freeN(onm->entries);
|
||||
MEM_freeN(onm->map);
|
||||
MEM_freeN(onm);
|
||||
MEM_delete(onm);
|
||||
}
|
||||
|
||||
#undef ENTRIES_CAPACITY
|
||||
#undef MAP_CAPACITY
|
||||
#undef SLOT_MASK
|
||||
#undef DEFAULT_SIZE_EXP
|
||||
#undef PERTURB_SHIFT
|
||||
#undef ITER_SLOTS
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -1555,13 +1433,11 @@ static void change_link_placeholder_to_real_ID_pointer_fd(FileData *fd,
|
|||
const void *old,
|
||||
void *newp)
|
||||
{
|
||||
for (int i = 0; i < fd->libmap->nentries; i++) {
|
||||
OldNew *entry = &fd->libmap->entries[i];
|
||||
|
||||
if (old == entry->newp && entry->nr == ID_LINK_PLACEHOLDER) {
|
||||
entry->newp = newp;
|
||||
for (NewAddress &entry : fd->libmap->map.values()) {
|
||||
if (old == entry.newp && entry.nr == ID_LINK_PLACEHOLDER) {
|
||||
entry.newp = newp;
|
||||
if (newp) {
|
||||
entry->nr = GS(((ID *)newp)->name);
|
||||
entry.nr = GS(((ID *)newp)->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1640,12 +1516,10 @@ void blo_make_packed_pointer_map(FileData *fd, Main *oldmain)
|
|||
|
||||
void blo_end_packed_pointer_map(FileData *fd, Main *oldmain)
|
||||
{
|
||||
OldNew *entry = fd->packedmap->entries;
|
||||
|
||||
/* used entries were restored, so we put them to zero */
|
||||
for (int i = 0; i < fd->packedmap->nentries; i++, entry++) {
|
||||
if (entry->nr > 0) {
|
||||
entry->newp = nullptr;
|
||||
for (NewAddress &entry : fd->packedmap->map.values()) {
|
||||
if (entry.nr > 0) {
|
||||
entry.newp = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -102,6 +102,7 @@
|
|||
#include "BKE_layer.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_lib_override.h"
|
||||
#include "BKE_lib_query.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_packedFile.h"
|
||||
|
@ -1083,6 +1084,31 @@ static void write_thumb(WriteData *wd, const BlendThumbnail *thumb)
|
|||
/** \name File Writing (Private)
|
||||
* \{ */
|
||||
|
||||
/* Helper callback for checking linked IDs used by given ID (assumed local), to ensure directly
|
||||
* linked data is tagged accordingly. */
|
||||
static int write_id_direct_linked_data_process_cb(LibraryIDLinkCallbackData *cb_data)
|
||||
{
|
||||
ID *id_self = cb_data->id_self;
|
||||
ID *id = *cb_data->id_pointer;
|
||||
const int cb_flag = cb_data->cb_flag;
|
||||
|
||||
if (id == nullptr || !ID_IS_LINKED(id)) {
|
||||
return IDWALK_RET_NOP;
|
||||
}
|
||||
BLI_assert(!ID_IS_LINKED(id_self));
|
||||
BLI_assert((cb_flag & IDWALK_CB_INDIRECT_USAGE) == 0);
|
||||
UNUSED_VARS_NDEBUG(id_self);
|
||||
|
||||
if (cb_flag & IDWALK_CB_DIRECT_WEAK_LINK) {
|
||||
id_lib_indirect_weak_link(id);
|
||||
}
|
||||
else {
|
||||
id_lib_extern(id);
|
||||
}
|
||||
|
||||
return IDWALK_RET_NOP;
|
||||
}
|
||||
|
||||
/* if MemFile * there's filesave to memory */
|
||||
static bool write_file_handle(Main *mainvar,
|
||||
WriteWrap *ww,
|
||||
|
@ -1097,11 +1123,24 @@ static bool write_file_handle(Main *mainvar,
|
|||
char buf[16];
|
||||
WriteData *wd;
|
||||
|
||||
blo_split_main(&mainlist, mainvar);
|
||||
|
||||
wd = mywrite_begin(ww, compare, current);
|
||||
BlendWriter writer = {wd};
|
||||
|
||||
/* Clear 'directly linked' flag for all linked data, these are not necessarily valid/up-to-date
|
||||
* info, they will be re-generated while write code is processing local IDs below. */
|
||||
if (!wd->use_memfile) {
|
||||
ID *id_iter;
|
||||
FOREACH_MAIN_ID_BEGIN (mainvar, id_iter) {
|
||||
if (ID_IS_LINKED(id_iter)) {
|
||||
id_iter->tag |= LIB_TAG_INDIRECT;
|
||||
id_iter->tag &= ~LIB_TAG_EXTERN;
|
||||
}
|
||||
}
|
||||
FOREACH_MAIN_ID_END;
|
||||
}
|
||||
|
||||
blo_split_main(&mainlist, mainvar);
|
||||
|
||||
BLI_snprintf(buf,
|
||||
sizeof(buf),
|
||||
"BLENDER%c%c%.3d",
|
||||
|
@ -1169,6 +1208,12 @@ static bool write_file_handle(Main *mainvar,
|
|||
const bool do_override = !ELEM(override_storage, nullptr, bmain) &&
|
||||
ID_IS_OVERRIDE_LIBRARY_REAL(id);
|
||||
|
||||
/* If not writing undo data, properly set directly linked IDs as `LIB_TAG_EXTERN`. */
|
||||
if (!wd->use_memfile) {
|
||||
BKE_library_foreach_ID_link(
|
||||
bmain, id, write_id_direct_linked_data_process_cb, nullptr, IDWALK_READONLY);
|
||||
}
|
||||
|
||||
if (do_override) {
|
||||
BKE_lib_override_library_operations_store_start(bmain, override_storage, id);
|
||||
}
|
||||
|
|
|
@ -1408,6 +1408,7 @@ static void drw_subdiv_compute_dispatch(const DRWSubdivCache *cache,
|
|||
}
|
||||
|
||||
void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache,
|
||||
GPUVertBuf *flags_buffer,
|
||||
GPUVertBuf *pos_nor,
|
||||
GPUVertBuf *orco)
|
||||
{
|
||||
|
@ -1460,6 +1461,10 @@ void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache,
|
|||
GPU_vertbuf_bind_as_ssbo(patch_arrays_buffer, binding_point++);
|
||||
GPU_vertbuf_bind_as_ssbo(patch_index_buffer, binding_point++);
|
||||
GPU_vertbuf_bind_as_ssbo(patch_param_buffer, binding_point++);
|
||||
if (flags_buffer) {
|
||||
GPU_vertbuf_bind_as_ssbo(flags_buffer, binding_point);
|
||||
}
|
||||
binding_point++;
|
||||
GPU_vertbuf_bind_as_ssbo(pos_nor, binding_point++);
|
||||
if (orco) {
|
||||
GPU_vertbuf_bind_as_ssbo(src_extra_buffer, binding_point++);
|
||||
|
|
|
@ -242,6 +242,7 @@ void draw_subdiv_finalize_custom_normals(const DRWSubdivCache *cache,
|
|||
GPUVertBuf *pos_nor);
|
||||
|
||||
void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache,
|
||||
GPUVertBuf *flags_buffer,
|
||||
struct GPUVertBuf *pos_nor,
|
||||
struct GPUVertBuf *orco);
|
||||
|
||||
|
|
|
@ -236,7 +236,7 @@ static void extract_edituv_stretch_angle_init_subdiv(const DRWSubdivCache *subdi
|
|||
draw_subdiv_get_pos_nor_format(),
|
||||
subdiv_cache->num_subdiv_loops + loose_geom.loop_len);
|
||||
|
||||
draw_subdiv_extract_pos_nor(subdiv_cache, pos_nor, nullptr);
|
||||
draw_subdiv_extract_pos_nor(subdiv_cache, nullptr, pos_nor, nullptr);
|
||||
}
|
||||
|
||||
/* UVs are stored contiguously so we need to compute the offset in the UVs buffer for the active
|
||||
|
|
|
@ -200,8 +200,26 @@ static GPUVertFormat *get_custom_normals_format()
|
|||
return &format;
|
||||
}
|
||||
|
||||
static void extract_vertex_flags(const MeshRenderData *mr, char *flags)
|
||||
{
|
||||
for (int i = 0; i < mr->vert_len; i++) {
|
||||
char *flag = &flags[i];
|
||||
const bool vert_hidden = mr->hide_vert && mr->hide_vert[i];
|
||||
/* Flag for paint mode overlay. */
|
||||
if (vert_hidden || ((mr->v_origindex) && (mr->v_origindex[i] == ORIGINDEX_NONE))) {
|
||||
*flag = -1;
|
||||
}
|
||||
else if (mr->select_vert && mr->select_vert[i]) {
|
||||
*flag = 1;
|
||||
}
|
||||
else {
|
||||
*flag = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData * /*mr*/,
|
||||
const MeshRenderData *mr,
|
||||
MeshBatchCache *cache,
|
||||
void *buffer,
|
||||
void * /*data*/)
|
||||
|
@ -217,6 +235,17 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
|||
return;
|
||||
}
|
||||
|
||||
GPUVertBuf *flags_buffer = GPU_vertbuf_calloc();
|
||||
static GPUVertFormat flag_format = {0};
|
||||
if (flag_format.attr_len == 0) {
|
||||
GPU_vertformat_attr_add(&flag_format, "flag", GPU_COMP_I32, 1, GPU_FETCH_INT);
|
||||
}
|
||||
GPU_vertbuf_init_with_format(flags_buffer, &flag_format);
|
||||
GPU_vertbuf_data_alloc(flags_buffer, divide_ceil_u(mr->vert_len, 4));
|
||||
char *flags = static_cast<char *>(GPU_vertbuf_get_data(flags_buffer));
|
||||
extract_vertex_flags(mr, flags);
|
||||
GPU_vertbuf_tag_dirty(flags_buffer);
|
||||
|
||||
GPUVertBuf *orco_vbo = cache->final.buff.vbo.orco;
|
||||
|
||||
if (orco_vbo) {
|
||||
|
@ -231,7 +260,7 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
|||
GPU_vertbuf_init_build_on_device(orco_vbo, &format, subdiv_cache->num_subdiv_loops);
|
||||
}
|
||||
|
||||
draw_subdiv_extract_pos_nor(subdiv_cache, vbo, orco_vbo);
|
||||
draw_subdiv_extract_pos_nor(subdiv_cache, flags_buffer, vbo, orco_vbo);
|
||||
|
||||
if (subdiv_cache->use_custom_loop_normals) {
|
||||
Mesh *coarse_mesh = subdiv_cache->mesh;
|
||||
|
@ -279,6 +308,8 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
|||
GPU_vertbuf_discard(vertex_normals);
|
||||
GPU_vertbuf_discard(subdiv_loop_subdiv_vert_index);
|
||||
}
|
||||
|
||||
GPU_vertbuf_discard(flags_buffer);
|
||||
}
|
||||
|
||||
static void extract_pos_nor_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
|
|
|
@ -87,16 +87,30 @@ layout(std430, binding = 11) readonly buffer extraCoarseFaceData
|
|||
uint extra_coarse_face_data[];
|
||||
};
|
||||
#else
|
||||
layout(std430, binding = 8) writeonly buffer outputVertexData
|
||||
layout(std430, binding = 8) readonly buffer inputFlagsBuffer
|
||||
{
|
||||
int flags_buffer[]; /*char*/
|
||||
};
|
||||
float get_flag(int vertex)
|
||||
{
|
||||
int char4 = flags_buffer[vertex / 4];
|
||||
int flag = (char4 >> ((vertex % 4) * 8)) & 0xFF;
|
||||
if (flag >= 128) {
|
||||
flag = -128 + (flag - 128);
|
||||
}
|
||||
|
||||
return float(flag);
|
||||
}
|
||||
layout(std430, binding = 9) writeonly buffer outputVertexData
|
||||
{
|
||||
PosNorLoop output_verts[];
|
||||
};
|
||||
# if defined(ORCO_EVALUATION)
|
||||
layout(std430, binding = 9) buffer src_extra_buffer
|
||||
layout(std430, binding = 10) buffer src_extra_buffer
|
||||
{
|
||||
float srcExtraVertexBuffer[];
|
||||
};
|
||||
layout(std430, binding = 10) writeonly buffer outputOrcoData
|
||||
layout(std430, binding = 11) writeonly buffer outputOrcoData
|
||||
{
|
||||
vec4 output_orcos[];
|
||||
};
|
||||
|
@ -463,6 +477,9 @@ void main()
|
|||
if (origindex == -1) {
|
||||
flag = -1.0;
|
||||
}
|
||||
else {
|
||||
flag = get_flag(origindex);
|
||||
}
|
||||
|
||||
PosNorLoop vertex_data;
|
||||
set_vertex_pos(vertex_data, pos);
|
||||
|
|
|
@ -249,16 +249,15 @@ static void poselib_tempload_exit(PoseBlendData *pbd)
|
|||
static bAction *poselib_blend_init_get_action(bContext *C, wmOperator *op)
|
||||
{
|
||||
bool asset_handle_valid;
|
||||
const AssetLibraryReference *asset_library_ref = CTX_wm_asset_library_ref(C);
|
||||
const AssetHandle asset_handle = CTX_wm_asset_handle(C, &asset_handle_valid);
|
||||
/* Poll callback should check. */
|
||||
BLI_assert((asset_library_ref != NULL) && asset_handle_valid);
|
||||
BLI_assert(asset_handle_valid);
|
||||
|
||||
PoseBlendData *pbd = op->customdata;
|
||||
|
||||
pbd->temp_id_consumer = ED_asset_temp_id_consumer_create(&asset_handle);
|
||||
return (bAction *)ED_asset_temp_id_consumer_ensure_local_id(
|
||||
pbd->temp_id_consumer, C, asset_library_ref, ID_AC, CTX_data_main(C), op->reports);
|
||||
pbd->temp_id_consumer, ID_AC, CTX_data_main(C), op->reports);
|
||||
}
|
||||
|
||||
static bAction *flip_pose(bContext *C, Object *ob, bAction *action)
|
||||
|
@ -508,11 +507,9 @@ static bool poselib_asset_in_context(bContext *C)
|
|||
{
|
||||
bool asset_handle_valid;
|
||||
/* Check whether the context provides the asset data needed to add a pose. */
|
||||
const AssetLibraryReference *asset_library_ref = CTX_wm_asset_library_ref(C);
|
||||
AssetHandle asset_handle = CTX_wm_asset_handle(C, &asset_handle_valid);
|
||||
const AssetHandle asset_handle = CTX_wm_asset_handle(C, &asset_handle_valid);
|
||||
|
||||
return (asset_library_ref != NULL) && asset_handle_valid &&
|
||||
(ED_asset_handle_get_id_type(&asset_handle) == ID_AC);
|
||||
return asset_handle_valid && (ED_asset_handle_get_id_type(&asset_handle) == ID_AC);
|
||||
}
|
||||
|
||||
/* Poll callback for operators that require existing PoseLib data (with poses) to work. */
|
||||
|
|
|
@ -27,9 +27,7 @@ struct AssetMetaData *ED_asset_handle_get_metadata(const struct AssetHandle *ass
|
|||
struct ID *ED_asset_handle_get_local_id(const struct AssetHandle *asset);
|
||||
ID_Type ED_asset_handle_get_id_type(const struct AssetHandle *asset);
|
||||
int ED_asset_handle_get_preview_icon_id(const struct AssetHandle *asset);
|
||||
void ED_asset_handle_get_full_library_path(const struct bContext *C,
|
||||
const struct AssetLibraryReference *asset_library_ref,
|
||||
const struct AssetHandle *asset,
|
||||
void ED_asset_handle_get_full_library_path(const struct AssetHandle *asset,
|
||||
char r_full_lib_path[]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -41,9 +39,7 @@ void ED_asset_handle_get_full_library_path(const struct bContext *C,
|
|||
namespace blender::ed::asset {
|
||||
|
||||
/** If the ID already exists in the database, return it, otherwise add it. */
|
||||
ID *get_local_id_from_asset_or_append_and_reuse(Main &bmain,
|
||||
const AssetLibraryReference &library_ref,
|
||||
AssetHandle asset);
|
||||
ID *get_local_id_from_asset_or_append_and_reuse(Main &bmain, AssetHandle asset);
|
||||
|
||||
} // namespace blender::ed::asset
|
||||
|
||||
|
|
|
@ -51,7 +51,6 @@ void ED_assetlist_storage_id_remap(struct ID *id_old, struct ID *id_new);
|
|||
void ED_assetlist_storage_exit(void);
|
||||
|
||||
struct ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle);
|
||||
const char *ED_assetlist_library_path(const struct AssetLibraryReference *library_reference);
|
||||
|
||||
/**
|
||||
* \return True if the region needs a UI redraw.
|
||||
|
|
|
@ -15,10 +15,6 @@ struct AssetLibraryReference;
|
|||
struct FileDirEntry;
|
||||
struct bContext;
|
||||
|
||||
std::string ED_assetlist_asset_filepath_get(const bContext *C,
|
||||
const AssetLibraryReference &library_reference,
|
||||
const AssetHandle &asset_handle);
|
||||
|
||||
/* Can return false to stop iterating. */
|
||||
using AssetListIterFn = blender::FunctionRef<bool(AssetHandle)>;
|
||||
void ED_assetlist_iterate(const AssetLibraryReference &library_reference, AssetListIterFn fn);
|
||||
|
|
|
@ -27,10 +27,7 @@ struct bContext;
|
|||
|
||||
AssetTempIDConsumer *ED_asset_temp_id_consumer_create(const struct AssetHandle *handle);
|
||||
void ED_asset_temp_id_consumer_free(AssetTempIDConsumer **consumer);
|
||||
struct ID *ED_asset_temp_id_consumer_ensure_local_id(
|
||||
AssetTempIDConsumer *consumer,
|
||||
const struct bContext *C,
|
||||
const struct AssetLibraryReference *asset_library_ref,
|
||||
struct ID *ED_asset_temp_id_consumer_ensure_local_id(AssetTempIDConsumer *consumer,
|
||||
ID_Type id_type,
|
||||
struct Main *bmain,
|
||||
struct ReportList *reports);
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include "AS_asset_identifier.hh"
|
||||
#include "AS_asset_representation.h"
|
||||
#include "AS_asset_representation.hh"
|
||||
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
|
@ -42,14 +44,12 @@ int ED_asset_handle_get_preview_icon_id(const AssetHandle *asset)
|
|||
return asset->file_data->preview_icon_id;
|
||||
}
|
||||
|
||||
void ED_asset_handle_get_full_library_path(const bContext *C,
|
||||
const AssetLibraryReference *asset_library_ref,
|
||||
const AssetHandle *asset,
|
||||
void ED_asset_handle_get_full_library_path(const AssetHandle *asset_handle,
|
||||
char r_full_lib_path[FILE_MAX_LIBEXTRA])
|
||||
{
|
||||
*r_full_lib_path = '\0';
|
||||
|
||||
std::string asset_path = ED_assetlist_asset_filepath_get(C, *asset_library_ref, *asset);
|
||||
std::string asset_path = AS_asset_representation_full_path_get(asset_handle->file_data->asset);
|
||||
if (asset_path.empty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -59,16 +59,14 @@ void ED_asset_handle_get_full_library_path(const bContext *C,
|
|||
|
||||
namespace blender::ed::asset {
|
||||
|
||||
ID *get_local_id_from_asset_or_append_and_reuse(Main &bmain,
|
||||
const AssetLibraryReference &library_ref,
|
||||
const AssetHandle asset)
|
||||
ID *get_local_id_from_asset_or_append_and_reuse(Main &bmain, const AssetHandle asset)
|
||||
{
|
||||
if (ID *local_id = ED_asset_handle_get_local_id(&asset)) {
|
||||
return local_id;
|
||||
}
|
||||
|
||||
char blend_path[FILE_MAX_LIBEXTRA];
|
||||
ED_asset_handle_get_full_library_path(nullptr, &library_ref, &asset, blend_path);
|
||||
ED_asset_handle_get_full_library_path(&asset, blend_path);
|
||||
const char *id_name = ED_asset_handle_get_name(&asset);
|
||||
|
||||
return WM_file_append_datablock(&bmain,
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
|
||||
#include "BKE_preferences.h"
|
||||
|
||||
#include "ED_fileselect.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
|
||||
/* XXX uses private header of file-space. */
|
||||
|
@ -121,7 +119,6 @@ class AssetList : NonCopyable {
|
|||
int size() const;
|
||||
void tagMainDataDirty() const;
|
||||
void remapID(ID *id_old, ID *id_new) const;
|
||||
StringRef filepath() const;
|
||||
};
|
||||
|
||||
AssetList::AssetList(eFileSelectType filesel_type, const AssetLibraryReference &asset_library_ref)
|
||||
|
@ -286,11 +283,6 @@ void AssetList::remapID(ID * /*id_old*/, ID * /*id_new*/) const
|
|||
tagMainDataDirty();
|
||||
}
|
||||
|
||||
StringRef AssetList::filepath() const
|
||||
{
|
||||
return filelist_dir(filelist_);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -457,46 +449,6 @@ void ED_assetlist_iterate(const AssetLibraryReference &library_reference, AssetL
|
|||
}
|
||||
}
|
||||
|
||||
/* TODO hack to use the File Browser path, so we can keep all the import logic handled by the asset
|
||||
* API. Get rid of this once the File Browser is integrated better with the asset list. */
|
||||
static const char *assetlist_library_path_from_sfile_get_hack(const bContext *C)
|
||||
{
|
||||
SpaceFile *sfile = CTX_wm_space_file(C);
|
||||
if (!sfile || !ED_fileselect_is_asset_browser(sfile)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FileAssetSelectParams *asset_select_params = ED_fileselect_get_asset_params(sfile);
|
||||
if (!asset_select_params) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return filelist_dir(sfile->files);
|
||||
}
|
||||
|
||||
std::string ED_assetlist_asset_filepath_get(const bContext *C,
|
||||
const AssetLibraryReference &library_reference,
|
||||
const AssetHandle &asset_handle)
|
||||
{
|
||||
if (ED_asset_handle_get_local_id(&asset_handle) ||
|
||||
!ED_asset_handle_get_metadata(&asset_handle)) {
|
||||
return {};
|
||||
}
|
||||
const char *library_path = ED_assetlist_library_path(&library_reference);
|
||||
if (!library_path && C) {
|
||||
library_path = assetlist_library_path_from_sfile_get_hack(C);
|
||||
}
|
||||
if (!library_path) {
|
||||
return {};
|
||||
}
|
||||
const char *asset_relpath = asset_handle.file_data->relpath;
|
||||
|
||||
char path[FILE_MAX_LIBEXTRA];
|
||||
BLI_path_join(path, sizeof(path), library_path, asset_relpath);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle)
|
||||
{
|
||||
ImBuf *imbuf = filelist_file_getimage(asset_handle->file_data);
|
||||
|
@ -507,15 +459,6 @@ ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle)
|
|||
return filelist_geticon_image_ex(asset_handle->file_data);
|
||||
}
|
||||
|
||||
const char *ED_assetlist_library_path(const AssetLibraryReference *library_reference)
|
||||
{
|
||||
AssetList *list = AssetListStorage::lookup_list(*library_reference);
|
||||
if (list) {
|
||||
return list->filepath().data();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool ED_assetlist_listen(const AssetLibraryReference *library_reference,
|
||||
const wmNotifier *notifier)
|
||||
{
|
||||
|
|
|
@ -44,15 +44,11 @@ class AssetTemporaryIDConsumer : NonCopyable, NonMovable {
|
|||
return ED_asset_handle_get_local_id(&handle_);
|
||||
}
|
||||
|
||||
ID *import_id(const bContext *C,
|
||||
const AssetLibraryReference &asset_library_ref,
|
||||
ID_Type id_type,
|
||||
Main &bmain,
|
||||
ReportList &reports)
|
||||
ID *import_id(ID_Type id_type, Main &bmain, ReportList &reports)
|
||||
{
|
||||
const char *asset_name = ED_asset_handle_get_name(&handle_);
|
||||
char blend_file_path[FILE_MAX_LIBEXTRA];
|
||||
ED_asset_handle_get_full_library_path(C, &asset_library_ref, &handle_, blend_file_path);
|
||||
ED_asset_handle_get_full_library_path(&handle_, blend_file_path);
|
||||
|
||||
temp_lib_context_ = BLO_library_temp_load_id(
|
||||
&bmain, blend_file_path, id_type, asset_name, &reports);
|
||||
|
@ -84,13 +80,11 @@ void ED_asset_temp_id_consumer_free(AssetTempIDConsumer **consumer)
|
|||
}
|
||||
|
||||
ID *ED_asset_temp_id_consumer_ensure_local_id(AssetTempIDConsumer *consumer_,
|
||||
const bContext *C,
|
||||
const AssetLibraryReference *asset_library_ref,
|
||||
ID_Type id_type,
|
||||
Main *bmain,
|
||||
ReportList *reports)
|
||||
{
|
||||
if (!(consumer_ && asset_library_ref && bmain && reports)) {
|
||||
if (!(consumer_ && bmain && reports)) {
|
||||
return nullptr;
|
||||
}
|
||||
AssetTemporaryIDConsumer *consumer = reinterpret_cast<AssetTemporaryIDConsumer *>(consumer_);
|
||||
|
@ -98,5 +92,5 @@ ID *ED_asset_temp_id_consumer_ensure_local_id(AssetTempIDConsumer *consumer_,
|
|||
if (ID *local_id = consumer->get_local_id()) {
|
||||
return local_id;
|
||||
}
|
||||
return consumer->import_id(C, *asset_library_ref, id_type, *bmain, *reports);
|
||||
return consumer->import_id(id_type, *bmain, *reports);
|
||||
}
|
||||
|
|
|
@ -2229,10 +2229,8 @@ static void gpencil_paint_initstroke(tGPsdata *p,
|
|||
* -> If there are no strokes in that frame, don't add a new empty frame
|
||||
*/
|
||||
if (gpl->actframe && gpl->actframe->strokes.first) {
|
||||
if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) {
|
||||
short frame_mode = IS_AUTOKEY_ON(scene) ? GP_GETFRAME_ADD_COPY : GP_GETFRAME_USE_PREV;
|
||||
gpl->actframe = BKE_gpencil_layer_frame_get(gpl, scene->r.cfra, frame_mode);
|
||||
}
|
||||
has_layer_to_erase = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -36,9 +36,7 @@ struct AssetViewListData {
|
|||
bool show_names;
|
||||
};
|
||||
|
||||
static void asset_view_item_but_drag_set(uiBut *but,
|
||||
AssetViewListData *list_data,
|
||||
AssetHandle *asset_handle)
|
||||
static void asset_view_item_but_drag_set(uiBut *but, AssetHandle *asset_handle)
|
||||
{
|
||||
ID *id = ED_asset_handle_get_local_id(asset_handle);
|
||||
if (id != nullptr) {
|
||||
|
@ -49,8 +47,7 @@ static void asset_view_item_but_drag_set(uiBut *but,
|
|||
char blend_path[FILE_MAX_LIBEXTRA];
|
||||
/* Context can be null here, it's only needed for a File Browser specific hack that should go
|
||||
* away before too long. */
|
||||
ED_asset_handle_get_full_library_path(
|
||||
nullptr, &list_data->asset_library_ref, asset_handle, blend_path);
|
||||
ED_asset_handle_get_full_library_path(asset_handle, blend_path);
|
||||
|
||||
if (blend_path[0]) {
|
||||
ImBuf *imbuf = ED_assetlist_asset_image_get(asset_handle);
|
||||
|
@ -107,7 +104,7 @@ static void asset_view_draw_item(uiList *ui_list,
|
|||
/* NOLINTNEXTLINE: bugprone-suspicious-enum-usage */
|
||||
UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
|
||||
if (!ui_list->dyn_data->custom_drag_optype) {
|
||||
asset_view_item_but_drag_set(but, list_data, asset_handle);
|
||||
asset_view_item_but_drag_set(but, asset_handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2859,12 +2859,12 @@ static bool file_delete_poll(bContext *C)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool file_delete_single(const FileSelectParams *params,
|
||||
static bool file_delete_single(const struct FileList *files,
|
||||
FileDirEntry *file,
|
||||
const char **r_error_message)
|
||||
{
|
||||
char str[FILE_MAX];
|
||||
BLI_path_join(str, sizeof(str), params->dir, file->relpath);
|
||||
char str[FILE_MAX_LIBEXTRA];
|
||||
filelist_file_get_full_path(files, file, str);
|
||||
if (BLI_delete_soft(str, r_error_message) != 0 || BLI_exists(str)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2876,7 +2876,6 @@ static int file_delete_exec(bContext *C, wmOperator *op)
|
|||
{
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
SpaceFile *sfile = CTX_wm_space_file(C);
|
||||
FileSelectParams *params = ED_fileselect_get_active_params(sfile);
|
||||
int numfiles = filelist_files_ensure(sfile->files);
|
||||
|
||||
const char *error_message = NULL;
|
||||
|
@ -2885,7 +2884,7 @@ static int file_delete_exec(bContext *C, wmOperator *op)
|
|||
for (int i = 0; i < numfiles; i++) {
|
||||
if (filelist_entry_select_index_get(sfile->files, i, CHECK_ALL)) {
|
||||
FileDirEntry *file = filelist_file(sfile->files, i);
|
||||
if (!file_delete_single(params, file, &error_message)) {
|
||||
if (!file_delete_single(sfile->files, file, &error_message)) {
|
||||
report_error = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1139,6 +1139,18 @@ void filelist_free_icons(void)
|
|||
}
|
||||
}
|
||||
|
||||
void filelist_file_get_full_path(const FileList *filelist, const FileDirEntry *file, char *r_path)
|
||||
{
|
||||
if (file->asset) {
|
||||
const std::string asset_path = AS_asset_representation_full_path_get(file->asset);
|
||||
BLI_strncpy(r_path, asset_path.c_str(), FILE_MAX_LIBEXTRA);
|
||||
return;
|
||||
}
|
||||
|
||||
const char *root = filelist_dir(filelist);
|
||||
BLI_path_join(r_path, FILE_MAX_LIBEXTRA, root, file->relpath);
|
||||
}
|
||||
|
||||
static FileDirEntry *filelist_geticon_get_file(struct FileList *filelist, const int index)
|
||||
{
|
||||
BLI_assert(G.background == false);
|
||||
|
@ -1183,8 +1195,8 @@ ImBuf *filelist_geticon_image(struct FileList *filelist, const int index)
|
|||
return filelist_geticon_image_ex(file);
|
||||
}
|
||||
|
||||
static int filelist_geticon_ex(const FileDirEntry *file,
|
||||
const char *root,
|
||||
static int filelist_geticon_ex(const FileList *filelist,
|
||||
const FileDirEntry *file,
|
||||
const bool is_main,
|
||||
const bool ignore_libdir)
|
||||
{
|
||||
|
@ -1222,8 +1234,8 @@ static int filelist_geticon_ex(const FileDirEntry *file,
|
|||
if (file->redirection_path) {
|
||||
target = file->redirection_path;
|
||||
}
|
||||
else if (root) {
|
||||
BLI_path_join(fullpath, sizeof(fullpath), root, file->relpath);
|
||||
else if (filelist) {
|
||||
filelist_file_get_full_path(filelist, file, fullpath);
|
||||
BLI_path_slash_ensure(fullpath, sizeof(fullpath));
|
||||
}
|
||||
for (; tfsm; tfsm = tfsm->next) {
|
||||
|
@ -1303,13 +1315,13 @@ int filelist_geticon(struct FileList *filelist, const int index, const bool is_m
|
|||
{
|
||||
FileDirEntry *file = filelist_geticon_get_file(filelist, index);
|
||||
|
||||
return filelist_geticon_ex(file, filelist->filelist.root, is_main, false);
|
||||
return filelist_geticon_ex(filelist, file, is_main, false);
|
||||
}
|
||||
|
||||
int ED_file_icon(const FileDirEntry *file)
|
||||
{
|
||||
return file->preview_icon_id ? file->preview_icon_id :
|
||||
filelist_geticon_ex(file, nullptr, false, false);
|
||||
filelist_geticon_ex(nullptr, file, false, false);
|
||||
}
|
||||
|
||||
static bool filelist_intern_entry_is_main_file(const FileListInternEntry *intern_entry)
|
||||
|
@ -1636,8 +1648,7 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry
|
|||
BLI_strncpy(preview->filepath, entry->redirection_path, FILE_MAXDIR);
|
||||
}
|
||||
else {
|
||||
BLI_path_join(
|
||||
preview->filepath, sizeof(preview->filepath), filelist->filelist.root, entry->relpath);
|
||||
filelist_file_get_full_path(filelist, entry, preview->filepath);
|
||||
}
|
||||
// printf("%s: %d - %s\n", __func__, preview->index, preview->filepath);
|
||||
|
||||
|
@ -1967,7 +1978,7 @@ static const char *fileentry_uiname(const char *root, FileListInternEntry *entry
|
|||
return BLI_strdup(name);
|
||||
}
|
||||
|
||||
const char *filelist_dir(struct FileList *filelist)
|
||||
const char *filelist_dir(const FileList *filelist)
|
||||
{
|
||||
return filelist->filelist.root;
|
||||
}
|
||||
|
@ -2905,7 +2916,65 @@ struct TodoDir {
|
|||
char *dir;
|
||||
};
|
||||
|
||||
static int filelist_readjob_list_dir(const char *root,
|
||||
struct FileListReadJob {
|
||||
ThreadMutex lock;
|
||||
char main_name[FILE_MAX];
|
||||
Main *current_main;
|
||||
FileList *filelist;
|
||||
|
||||
/** The path currently being read, relative to the filelist root directory. Needed for recursive
|
||||
* reading. The full file path is then composed like: `<filelist root>/<cur_relbase>/<file name>.
|
||||
* (whereby the file name may also be a library path within a .blend, e.g.
|
||||
* `Materials/Material.001`). */
|
||||
char cur_relbase[FILE_MAX_LIBEXTRA];
|
||||
|
||||
/** Set to request a partial read that only adds files representing #Main data (IDs). Used when
|
||||
* #Main may have received changes of interest (e.g. asset removed or renamed). */
|
||||
bool only_main_data;
|
||||
|
||||
/** Shallow copy of #filelist for thread-safe access.
|
||||
*
|
||||
* The job system calls #filelist_readjob_update which moves any read file from #tmp_filelist
|
||||
* into #filelist in a thread-safe way.
|
||||
*
|
||||
* #tmp_filelist also keeps an `AssetLibrary *` so that it can be loaded in the same thread,
|
||||
* and moved to #filelist once all categories are loaded.
|
||||
*
|
||||
* NOTE: #tmp_filelist is freed in #filelist_readjob_free, so any copied pointers need to be
|
||||
* set to nullptr to avoid double-freeing them. */
|
||||
FileList *tmp_filelist;
|
||||
};
|
||||
|
||||
/**
|
||||
* Append \a filename (or even a path inside of a .blend, like `Material/Material.001`), to the
|
||||
* current relative path being read within the filelist root. The returned string needs freeing
|
||||
* with #MEM_freeN().
|
||||
*/
|
||||
static char *current_relpath_append(const FileListReadJob *job_params, const char *filename)
|
||||
{
|
||||
const char *relbase = job_params->cur_relbase;
|
||||
|
||||
/* Early exit, nothing to join. */
|
||||
if (!relbase[0]) {
|
||||
return BLI_strdup(filename);
|
||||
}
|
||||
|
||||
BLI_assert(relbase[strlen(relbase) - 1] == SEP);
|
||||
BLI_assert(BLI_path_is_rel(relbase));
|
||||
|
||||
char relpath[FILE_MAX_LIBEXTRA];
|
||||
/* Using #BLI_path_join works but isn't needed as `rel_subdir` has a trailing slash. */
|
||||
BLI_string_join(relpath,
|
||||
sizeof(relpath),
|
||||
/* + 2 to remove "//" relative path prefix. */
|
||||
relbase + 2,
|
||||
filename);
|
||||
|
||||
return BLI_strdup(relpath);
|
||||
}
|
||||
|
||||
static int filelist_readjob_list_dir(FileListReadJob *job_params,
|
||||
const char *root,
|
||||
ListBase *entries,
|
||||
const char *filter_glob,
|
||||
const bool do_lib,
|
||||
|
@ -2928,7 +2997,7 @@ static int filelist_readjob_list_dir(const char *root,
|
|||
}
|
||||
|
||||
entry = MEM_cnew<FileListInternEntry>(__func__);
|
||||
entry->relpath = static_cast<char *>(MEM_dupallocN(files[i].relname));
|
||||
entry->relpath = current_relpath_append(job_params, files[i].relname);
|
||||
entry->st = files[i].s;
|
||||
|
||||
BLI_path_join(full_path, FILE_MAX, root, entry->relpath);
|
||||
|
@ -3015,11 +3084,11 @@ enum ListLibOptions {
|
|||
};
|
||||
ENUM_OPERATORS(ListLibOptions, LIST_LIB_ADD_PARENT);
|
||||
|
||||
static FileListInternEntry *filelist_readjob_list_lib_group_create(const int idcode,
|
||||
const char *group_name)
|
||||
static FileListInternEntry *filelist_readjob_list_lib_group_create(
|
||||
const FileListReadJob *job_params, const int idcode, const char *group_name)
|
||||
{
|
||||
FileListInternEntry *entry = MEM_cnew<FileListInternEntry>(__func__);
|
||||
entry->relpath = BLI_strdup(group_name);
|
||||
entry->relpath = current_relpath_append(job_params, group_name);
|
||||
entry->typeflag |= FILE_TYPE_BLENDERLIB | FILE_TYPE_DIR;
|
||||
entry->blentype = idcode;
|
||||
return entry;
|
||||
|
@ -3029,19 +3098,21 @@ static FileListInternEntry *filelist_readjob_list_lib_group_create(const int idc
|
|||
* \warning: This "steals" the asset metadata from \a datablock_info. Not great design but fixing
|
||||
* this requires redesigning things on the caller side for proper ownership management.
|
||||
*/
|
||||
static void filelist_readjob_list_lib_add_datablock(FileList *filelist,
|
||||
static void filelist_readjob_list_lib_add_datablock(FileListReadJob *job_params,
|
||||
ListBase *entries,
|
||||
BLODataBlockInfo *datablock_info,
|
||||
const bool prefix_relpath_with_group_name,
|
||||
const int idcode,
|
||||
const char *group_name)
|
||||
{
|
||||
FileList *filelist = job_params->tmp_filelist; /* Use the thread-safe filelist queue. */
|
||||
FileListInternEntry *entry = MEM_cnew<FileListInternEntry>(__func__);
|
||||
if (prefix_relpath_with_group_name) {
|
||||
entry->relpath = BLI_sprintfN("%s/%s", group_name, datablock_info->name);
|
||||
std::string datablock_path = StringRef(group_name) + "/" + datablock_info->name;
|
||||
entry->relpath = current_relpath_append(job_params, datablock_path.c_str());
|
||||
}
|
||||
else {
|
||||
entry->relpath = BLI_strdup(datablock_info->name);
|
||||
entry->relpath = current_relpath_append(job_params, datablock_info->name);
|
||||
}
|
||||
entry->typeflag |= FILE_TYPE_BLENDERLIB;
|
||||
if (datablock_info) {
|
||||
|
@ -3056,8 +3127,8 @@ static void filelist_readjob_list_lib_add_datablock(FileList *filelist,
|
|||
datablock_info->asset_data);
|
||||
BKE_asset_metadata_free(&datablock_info->asset_data);
|
||||
|
||||
entry->asset = &filelist->asset_library->add_external_asset(datablock_info->name,
|
||||
std::move(metadata));
|
||||
entry->asset = &filelist->asset_library->add_external_asset(
|
||||
entry->relpath, datablock_info->name, std::move(metadata));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3065,7 +3136,7 @@ static void filelist_readjob_list_lib_add_datablock(FileList *filelist,
|
|||
BLI_addtail(entries, entry);
|
||||
}
|
||||
|
||||
static void filelist_readjob_list_lib_add_datablocks(FileList *filelist,
|
||||
static void filelist_readjob_list_lib_add_datablocks(FileListReadJob *job_params,
|
||||
ListBase *entries,
|
||||
LinkNode *datablock_infos,
|
||||
const bool prefix_relpath_with_group_name,
|
||||
|
@ -3075,12 +3146,12 @@ static void filelist_readjob_list_lib_add_datablocks(FileList *filelist,
|
|||
for (LinkNode *ln = datablock_infos; ln; ln = ln->next) {
|
||||
struct BLODataBlockInfo *datablock_info = static_cast<BLODataBlockInfo *>(ln->link);
|
||||
filelist_readjob_list_lib_add_datablock(
|
||||
filelist, entries, datablock_info, prefix_relpath_with_group_name, idcode, group_name);
|
||||
job_params, entries, datablock_info, prefix_relpath_with_group_name, idcode, group_name);
|
||||
}
|
||||
}
|
||||
|
||||
static void filelist_readjob_list_lib_add_from_indexer_entries(
|
||||
FileList *filelist,
|
||||
FileListReadJob *job_params,
|
||||
ListBase *entries,
|
||||
const FileIndexerEntries *indexer_entries,
|
||||
const bool prefix_relpath_with_group_name)
|
||||
|
@ -3088,7 +3159,7 @@ static void filelist_readjob_list_lib_add_from_indexer_entries(
|
|||
for (const LinkNode *ln = indexer_entries->entries; ln; ln = ln->next) {
|
||||
FileIndexerEntry *indexer_entry = static_cast<FileIndexerEntry *>(ln->link);
|
||||
const char *group_name = BKE_idtype_idcode_to_name(indexer_entry->idcode);
|
||||
filelist_readjob_list_lib_add_datablock(filelist,
|
||||
filelist_readjob_list_lib_add_datablock(job_params,
|
||||
entries,
|
||||
&indexer_entry->datablock_info,
|
||||
prefix_relpath_with_group_name,
|
||||
|
@ -3097,10 +3168,11 @@ static void filelist_readjob_list_lib_add_from_indexer_entries(
|
|||
}
|
||||
}
|
||||
|
||||
static FileListInternEntry *filelist_readjob_list_lib_navigate_to_parent_entry_create(void)
|
||||
static FileListInternEntry *filelist_readjob_list_lib_navigate_to_parent_entry_create(
|
||||
const FileListReadJob *job_params)
|
||||
{
|
||||
FileListInternEntry *entry = MEM_cnew<FileListInternEntry>(__func__);
|
||||
entry->relpath = BLI_strdup(FILENAME_PARENT);
|
||||
entry->relpath = current_relpath_append(job_params, FILENAME_PARENT);
|
||||
entry->typeflag |= (FILE_TYPE_BLENDERLIB | FILE_TYPE_DIR);
|
||||
return entry;
|
||||
}
|
||||
|
@ -3117,7 +3189,7 @@ typedef struct FileIndexer {
|
|||
void *user_data;
|
||||
} FileIndexer;
|
||||
|
||||
static int filelist_readjob_list_lib_populate_from_index(FileList *filelist,
|
||||
static int filelist_readjob_list_lib_populate_from_index(FileListReadJob *job_params,
|
||||
ListBase *entries,
|
||||
const ListLibOptions options,
|
||||
const int read_from_index,
|
||||
|
@ -3125,12 +3197,13 @@ static int filelist_readjob_list_lib_populate_from_index(FileList *filelist,
|
|||
{
|
||||
int navigate_to_parent_len = 0;
|
||||
if (options & LIST_LIB_ADD_PARENT) {
|
||||
FileListInternEntry *entry = filelist_readjob_list_lib_navigate_to_parent_entry_create();
|
||||
FileListInternEntry *entry = filelist_readjob_list_lib_navigate_to_parent_entry_create(
|
||||
job_params);
|
||||
BLI_addtail(entries, entry);
|
||||
navigate_to_parent_len = 1;
|
||||
}
|
||||
|
||||
filelist_readjob_list_lib_add_from_indexer_entries(filelist, entries, indexer_entries, true);
|
||||
filelist_readjob_list_lib_add_from_indexer_entries(job_params, entries, indexer_entries, true);
|
||||
return read_from_index + navigate_to_parent_len;
|
||||
}
|
||||
|
||||
|
@ -3138,7 +3211,7 @@ static int filelist_readjob_list_lib_populate_from_index(FileList *filelist,
|
|||
* \return The number of entries found if the \a root path points to a valid library file.
|
||||
* Otherwise returns no value (#std::nullopt).
|
||||
*/
|
||||
static std::optional<int> filelist_readjob_list_lib(FileList *filelist,
|
||||
static std::optional<int> filelist_readjob_list_lib(FileListReadJob *job_params,
|
||||
const char *root,
|
||||
ListBase *entries,
|
||||
const ListLibOptions options,
|
||||
|
@ -3178,7 +3251,7 @@ static std::optional<int> filelist_readjob_list_lib(FileList *filelist,
|
|||
dir, &indexer_entries, &read_from_index, indexer_runtime->user_data);
|
||||
if (indexer_result == FILE_INDEXER_ENTRIES_LOADED) {
|
||||
int entries_read = filelist_readjob_list_lib_populate_from_index(
|
||||
filelist, entries, options, read_from_index, &indexer_entries);
|
||||
job_params, entries, options, read_from_index, &indexer_entries);
|
||||
ED_file_indexer_entries_clear(&indexer_entries);
|
||||
return entries_read;
|
||||
}
|
||||
|
@ -3197,7 +3270,8 @@ static std::optional<int> filelist_readjob_list_lib(FileList *filelist,
|
|||
* the code clean and readable and not counting in a single variable. */
|
||||
int navigate_to_parent_len = 0;
|
||||
if (options & LIST_LIB_ADD_PARENT) {
|
||||
FileListInternEntry *entry = filelist_readjob_list_lib_navigate_to_parent_entry_create();
|
||||
FileListInternEntry *entry = filelist_readjob_list_lib_navigate_to_parent_entry_create(
|
||||
job_params);
|
||||
BLI_addtail(entries, entry);
|
||||
navigate_to_parent_len = 1;
|
||||
}
|
||||
|
@ -3209,7 +3283,7 @@ static std::optional<int> filelist_readjob_list_lib(FileList *filelist,
|
|||
LinkNode *datablock_infos = BLO_blendhandle_get_datablock_info(
|
||||
libfiledata, idcode, options & LIST_LIB_ASSETS_ONLY, &datablock_len);
|
||||
filelist_readjob_list_lib_add_datablocks(
|
||||
filelist, entries, datablock_infos, false, idcode, group);
|
||||
job_params, entries, datablock_infos, false, idcode, group);
|
||||
BLI_linklist_freeN(datablock_infos);
|
||||
}
|
||||
else {
|
||||
|
@ -3219,8 +3293,8 @@ static std::optional<int> filelist_readjob_list_lib(FileList *filelist,
|
|||
for (LinkNode *ln = groups; ln; ln = ln->next) {
|
||||
const char *group_name = static_cast<char *>(ln->link);
|
||||
const int idcode = groupname_to_code(group_name);
|
||||
FileListInternEntry *group_entry = filelist_readjob_list_lib_group_create(idcode,
|
||||
group_name);
|
||||
FileListInternEntry *group_entry = filelist_readjob_list_lib_group_create(
|
||||
job_params, idcode, group_name);
|
||||
BLI_addtail(entries, group_entry);
|
||||
|
||||
if (options & LIST_LIB_RECURSIVE) {
|
||||
|
@ -3228,7 +3302,7 @@ static std::optional<int> filelist_readjob_list_lib(FileList *filelist,
|
|||
LinkNode *group_datablock_infos = BLO_blendhandle_get_datablock_info(
|
||||
libfiledata, idcode, options & LIST_LIB_ASSETS_ONLY, &group_datablock_len);
|
||||
filelist_readjob_list_lib_add_datablocks(
|
||||
filelist, entries, group_datablock_infos, true, idcode, group_name);
|
||||
job_params, entries, group_datablock_infos, true, idcode, group_name);
|
||||
if (use_indexer) {
|
||||
ED_file_indexer_entries_extend_from_datablock_infos(
|
||||
&indexer_entries, group_datablock_infos, idcode);
|
||||
|
@ -3427,28 +3501,6 @@ static void filelist_readjob_main_recursive(Main *bmain, FileList *filelist)
|
|||
}
|
||||
#endif
|
||||
|
||||
struct FileListReadJob {
|
||||
ThreadMutex lock;
|
||||
char main_name[FILE_MAX];
|
||||
Main *current_main;
|
||||
FileList *filelist;
|
||||
/** Set to request a partial read that only adds files representing #Main data (IDs). Used when
|
||||
* #Main may have received changes of interest (e.g. asset removed or renamed). */
|
||||
bool only_main_data;
|
||||
|
||||
/** Shallow copy of #filelist for thread-safe access.
|
||||
*
|
||||
* The job system calls #filelist_readjob_update which moves any read file from #tmp_filelist
|
||||
* into #filelist in a thread-safe way.
|
||||
*
|
||||
* #tmp_filelist also keeps an `AssetLibrary *` so that it can be loaded in the same thread,
|
||||
* and moved to #filelist once all categories are loaded.
|
||||
*
|
||||
* NOTE: #tmp_filelist is freed in #filelist_readjob_free, so any copied pointers need to be
|
||||
* set to nullptr to avoid double-freeing them. */
|
||||
FileList *tmp_filelist;
|
||||
};
|
||||
|
||||
static void filelist_readjob_append_entries(FileListReadJob *job_params,
|
||||
ListBase *from_entries,
|
||||
int from_entries_num,
|
||||
|
@ -3562,6 +3614,9 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib,
|
|||
BLI_path_normalize_dir(root, rel_subdir, sizeof(rel_subdir));
|
||||
BLI_path_rel(rel_subdir, root);
|
||||
|
||||
/* Update the current relative base path within the filelist root. */
|
||||
BLI_strncpy(job_params->cur_relbase, rel_subdir, sizeof(job_params->cur_relbase));
|
||||
|
||||
bool is_lib = false;
|
||||
if (do_lib) {
|
||||
ListLibOptions list_lib_options = LIST_LIB_OPTION_NONE;
|
||||
|
@ -3580,7 +3635,7 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib,
|
|||
list_lib_options |= LIST_LIB_ASSETS_ONLY;
|
||||
}
|
||||
std::optional<int> lib_entries_num = filelist_readjob_list_lib(
|
||||
filelist, subdir, &entries, list_lib_options, &indexer_runtime);
|
||||
job_params, subdir, &entries, list_lib_options, &indexer_runtime);
|
||||
if (lib_entries_num) {
|
||||
is_lib = true;
|
||||
entries_num += *lib_entries_num;
|
||||
|
@ -3589,19 +3644,11 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib,
|
|||
|
||||
if (!is_lib && BLI_is_dir(subdir)) {
|
||||
entries_num = filelist_readjob_list_dir(
|
||||
subdir, &entries, filter_glob, do_lib, job_params->main_name, skip_currpar);
|
||||
job_params, subdir, &entries, filter_glob, do_lib, job_params->main_name, skip_currpar);
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (FileListInternEntry *, entry, &entries) {
|
||||
entry->uid = filelist_uid_generate(filelist);
|
||||
|
||||
/* When loading entries recursive, the `rel_path` should be relative from the root dir.
|
||||
* we combine the relative path to the `subdir` with the relative path of the entry.
|
||||
* Using #BLI_path_join works but isn't needed as `rel_subdir` has a trailing slash. */
|
||||
BLI_string_join(dir, sizeof(dir), rel_subdir, entry->relpath);
|
||||
MEM_freeN(entry->relpath);
|
||||
entry->relpath = BLI_strdup(dir + 2); /* + 2 to remove '//'
|
||||
* added by BLI_path_rel to rel_subdir. */
|
||||
entry->name = fileentry_uiname(root, entry, dir);
|
||||
entry->free_name = true;
|
||||
|
||||
|
@ -3726,7 +3773,8 @@ static void filelist_readjob_main_assets_add_items(FileListReadJob *job_params,
|
|||
const char *id_code_name = BKE_idtype_idcode_to_name(GS(id_iter->name));
|
||||
|
||||
entry = MEM_cnew<FileListInternEntry>(__func__);
|
||||
entry->relpath = BLI_strdup(id_code_name);
|
||||
std::string datablock_path = StringRef(id_code_name) + "/" + (id_iter->name + 2);
|
||||
entry->relpath = current_relpath_append(job_params, datablock_path.c_str());
|
||||
entry->name = id_iter->name + 2;
|
||||
entry->free_name = false;
|
||||
entry->typeflag |= FILE_TYPE_BLENDERLIB | FILE_TYPE_ASSET;
|
||||
|
@ -3736,7 +3784,7 @@ static void filelist_readjob_main_assets_add_items(FileListReadJob *job_params,
|
|||
id_iter);
|
||||
entry->local_data.id = id_iter;
|
||||
if (filelist->asset_library) {
|
||||
entry->asset = &filelist->asset_library->add_local_id_asset(*id_iter);
|
||||
entry->asset = &filelist->asset_library->add_local_id_asset(entry->relpath, *id_iter);
|
||||
}
|
||||
entries_num++;
|
||||
BLI_addtail(&tmp_entries, entry);
|
||||
|
|
|
@ -71,6 +71,9 @@ void filelist_setlibrary(struct FileList *filelist,
|
|||
|
||||
void filelist_init_icons(void);
|
||||
void filelist_free_icons(void);
|
||||
void filelist_file_get_full_path(const struct FileList *filelist,
|
||||
const FileDirEntry *file,
|
||||
char r_path[/*FILE_MAX_LIBEXTRA*/]);
|
||||
struct ImBuf *filelist_getimage(struct FileList *filelist, int index);
|
||||
struct ImBuf *filelist_file_getimage(const FileDirEntry *file);
|
||||
struct ImBuf *filelist_geticon_image_ex(const FileDirEntry *file);
|
||||
|
@ -91,7 +94,7 @@ void filelist_clear_ex(struct FileList *filelist,
|
|||
void filelist_clear_from_reset_tag(struct FileList *filelist);
|
||||
void filelist_free(struct FileList *filelist);
|
||||
|
||||
const char *filelist_dir(struct FileList *filelist);
|
||||
const char *filelist_dir(const struct FileList *filelist);
|
||||
bool filelist_is_dir(struct FileList *filelist, const char *path);
|
||||
/**
|
||||
* May modify in place given r_dir, which is expected to be FILE_MAX_LIBEXTRA length.
|
||||
|
|
|
@ -67,7 +67,6 @@ static void add_node_search_listen_fn(const wmRegionListenerParams *params, void
|
|||
}
|
||||
|
||||
static void search_items_for_asset_metadata(const bNodeTree &node_tree,
|
||||
const AssetLibraryReference &library_ref,
|
||||
const AssetHandle asset,
|
||||
Vector<AddNodeItem> &search_items)
|
||||
{
|
||||
|
@ -82,10 +81,10 @@ static void search_items_for_asset_metadata(const bNodeTree &node_tree,
|
|||
item.identifier = node_tree.typeinfo->group_idname;
|
||||
item.description = asset_data.description == nullptr ? "" : asset_data.description;
|
||||
item.asset = asset;
|
||||
item.after_add_fn = [asset, library_ref](const bContext &C, bNodeTree &node_tree, bNode &node) {
|
||||
item.after_add_fn = [asset](const bContext &C, bNodeTree &node_tree, bNode &node) {
|
||||
Main &bmain = *CTX_data_main(&C);
|
||||
node.flag &= ~NODE_OPTIONS;
|
||||
node.id = asset::get_local_id_from_asset_or_append_and_reuse(bmain, library_ref, asset);
|
||||
node.id = asset::get_local_id_from_asset_or_append_and_reuse(bmain, asset);
|
||||
id_us_plus(node.id);
|
||||
BKE_ntree_update_tag_node_property(&node_tree, &node);
|
||||
DEG_relations_tag_update(&bmain);
|
||||
|
@ -113,7 +112,7 @@ static void gather_search_items_for_asset_library(const bContext &C,
|
|||
/* If an asset with the same name has already been added, skip this. */
|
||||
return true;
|
||||
}
|
||||
search_items_for_asset_metadata(node_tree, library_ref, asset, search_items);
|
||||
search_items_for_asset_metadata(node_tree, asset, search_items);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -141,7 +141,6 @@ static void add_existing_group_input_fn(nodes::LinkSearchOpParams ¶ms,
|
|||
*/
|
||||
static void search_link_ops_for_asset_metadata(const bNodeTree &node_tree,
|
||||
const bNodeSocket &socket,
|
||||
const AssetLibraryReference &library_ref,
|
||||
const AssetHandle asset,
|
||||
Vector<SocketLinkOperation> &search_link_ops)
|
||||
{
|
||||
|
@ -186,13 +185,13 @@ static void search_link_ops_for_asset_metadata(const bNodeTree &node_tree,
|
|||
|
||||
search_link_ops.append(
|
||||
{asset_name + " " + UI_MENU_ARROW_SEP + socket_name,
|
||||
[library_ref, asset, socket_property, in_out](nodes::LinkSearchOpParams ¶ms) {
|
||||
[asset, socket_property, in_out](nodes::LinkSearchOpParams ¶ms) {
|
||||
Main &bmain = *CTX_data_main(¶ms.C);
|
||||
|
||||
bNode &node = params.add_node(params.node_tree.typeinfo->group_idname);
|
||||
node.flag &= ~NODE_OPTIONS;
|
||||
|
||||
node.id = asset::get_local_id_from_asset_or_append_and_reuse(bmain, library_ref, asset);
|
||||
node.id = asset::get_local_id_from_asset_or_append_and_reuse(bmain, asset);
|
||||
id_us_plus(node.id);
|
||||
BKE_ntree_update_tag_node_property(¶ms.node_tree, &node);
|
||||
DEG_relations_tag_update(&bmain);
|
||||
|
@ -232,7 +231,7 @@ static void gather_search_link_ops_for_asset_library(const bContext &C,
|
|||
if (skip_local && ED_asset_handle_get_local_id(&asset) != nullptr) {
|
||||
return true;
|
||||
}
|
||||
search_link_ops_for_asset_metadata(node_tree, socket, library_ref, asset, search_link_ops);
|
||||
search_link_ops_for_asset_metadata(node_tree, socket, asset, search_link_ops);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -372,17 +372,14 @@ void NODE_OT_add_group(wmOperatorType *ot)
|
|||
/** \name Add Node Group Asset Operator
|
||||
* \{ */
|
||||
|
||||
static bool add_node_group_asset(const bContext &C,
|
||||
const AssetLibraryReference &library_ref,
|
||||
const AssetHandle asset,
|
||||
ReportList &reports)
|
||||
static bool add_node_group_asset(const bContext &C, const AssetHandle asset, ReportList &reports)
|
||||
{
|
||||
Main &bmain = *CTX_data_main(&C);
|
||||
SpaceNode &snode = *CTX_wm_space_node(&C);
|
||||
bNodeTree &edit_tree = *snode.edittree;
|
||||
|
||||
bNodeTree *node_group = reinterpret_cast<bNodeTree *>(
|
||||
asset::get_local_id_from_asset_or_append_and_reuse(bmain, library_ref, asset));
|
||||
asset::get_local_id_from_asset_or_append_and_reuse(bmain, asset));
|
||||
if (!node_group) {
|
||||
return false;
|
||||
}
|
||||
|
@ -439,7 +436,7 @@ static int node_add_group_asset_invoke(bContext *C, wmOperator *op, const wmEven
|
|||
|
||||
snode.runtime->cursor /= UI_DPI_FAC;
|
||||
|
||||
if (!add_node_group_asset(*C, *library_ref, handle, *op->reports)) {
|
||||
if (!add_node_group_asset(*C, handle, *op->reports)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
|
|
|
@ -2793,18 +2793,19 @@ static bool node_shader_script_update_poll(bContext *C)
|
|||
static bool node_shader_script_update_text_recursive(RenderEngine *engine,
|
||||
RenderEngineType *type,
|
||||
bNodeTree *ntree,
|
||||
Text *text)
|
||||
Text *text,
|
||||
Set<bNodeTree *> &done_trees)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
ntree->runtime->done = true;
|
||||
done_trees.add_new(ntree);
|
||||
|
||||
/* update each script that is using this text datablock */
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (node->type == NODE_GROUP) {
|
||||
bNodeTree *ngroup = (bNodeTree *)node->id;
|
||||
if (ngroup && !ngroup->runtime->done) {
|
||||
found |= node_shader_script_update_text_recursive(engine, type, ngroup, text);
|
||||
if (ngroup && !done_trees.contains(ngroup)) {
|
||||
found |= node_shader_script_update_text_recursive(engine, type, ngroup, text, done_trees);
|
||||
}
|
||||
}
|
||||
else if (node->type == SH_NODE_SCRIPT && node->id == &text->id) {
|
||||
|
@ -2852,18 +2853,14 @@ static int node_shader_script_update_exec(bContext *C, wmOperator *op)
|
|||
Text *text = (Text *)CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
|
||||
|
||||
if (text) {
|
||||
/* clear flags for recursion check */
|
||||
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
|
||||
if (ntree->type == NTREE_SHADER) {
|
||||
ntree->runtime->done = false;
|
||||
}
|
||||
}
|
||||
FOREACH_NODETREE_END;
|
||||
|
||||
Set<bNodeTree *> done_trees;
|
||||
|
||||
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
|
||||
if (ntree->type == NTREE_SHADER) {
|
||||
if (!ntree->runtime->done) {
|
||||
found |= node_shader_script_update_text_recursive(engine, type, ntree, text);
|
||||
if (!done_trees.contains(ntree)) {
|
||||
found |= node_shader_script_update_text_recursive(
|
||||
engine, type, ntree, text, done_trees);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -902,8 +902,6 @@ static void node_link_exit(bContext &C, wmOperator &op, const bool apply_links)
|
|||
bNodeTree &ntree = *snode.edittree;
|
||||
bNodeLinkDrag *nldrag = (bNodeLinkDrag *)op.customdata;
|
||||
|
||||
/* avoid updates while applying links */
|
||||
ntree.runtime->is_updating = true;
|
||||
for (bNodeLink *link : nldrag->links) {
|
||||
link->flag &= ~NODE_LINK_DRAGGED;
|
||||
|
||||
|
@ -929,7 +927,6 @@ static void node_link_exit(bContext &C, wmOperator &op, const bool apply_links)
|
|||
nodeRemLink(&ntree, link);
|
||||
}
|
||||
}
|
||||
ntree.runtime->is_updating = false;
|
||||
|
||||
ED_node_tree_propagate_change(&C, bmain, &ntree);
|
||||
|
||||
|
|
|
@ -285,7 +285,7 @@ static void sequencer_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop)
|
|||
/* We are dropped inside the preview region. Put the strip on top of the
|
||||
* current displayed frame. */
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Editing *ed = SEQ_editing_get(scene);
|
||||
Editing *ed = SEQ_editing_ensure(scene);
|
||||
ListBase *seqbase = SEQ_active_seqbase_get(ed);
|
||||
ListBase *channels = SEQ_channels_displayed_get(ed);
|
||||
SpaceSeq *sseq = CTX_wm_space_seq(C);
|
||||
|
|
|
@ -565,7 +565,7 @@ static void sequencer_main_clamp_view(const bContext *C, ARegion *region)
|
|||
|
||||
/* Initialize default view with 7 channels, that are visible even if empty. */
|
||||
rctf strip_boundbox;
|
||||
BLI_rctf_init(&strip_boundbox, 0.0f, 0.0f, 1.0f, 7.0f);
|
||||
BLI_rctf_init(&strip_boundbox, 0.0f, 0.0f, 1.0f, 6.0f);
|
||||
SEQ_timeline_expand_boundbox(scene, ed->seqbasep, &strip_boundbox);
|
||||
|
||||
/* Clamp Y max. Scrubbing area height must be added, so strips aren't occluded. */
|
||||
|
@ -574,8 +574,8 @@ static void sequencer_main_clamp_view(const bContext *C, ARegion *region)
|
|||
const float pixel_view_size_y = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
|
||||
const float scrub_bar_height = BLI_rcti_size_y(&scrub_rect) * pixel_view_size_y;
|
||||
|
||||
/* Channel n has range of <n, n+1>. */
|
||||
strip_boundbox.ymax += 1.0f + scrub_bar_height;
|
||||
/* Channel n has range of <n, n+1>, +1 for empty channel. */
|
||||
strip_boundbox.ymax += 2.0f + scrub_bar_height;
|
||||
|
||||
/* Clamp Y min. Scroller and marker area height must be added, so strips aren't occluded. */
|
||||
float scroll_bar_height = v2d->hor.ymax * pixel_view_size_y;
|
||||
|
|
|
@ -297,17 +297,6 @@ static PHashLink *phash_next(PHash *ph, PHashKey key, PHashLink *link)
|
|||
return link;
|
||||
}
|
||||
|
||||
/* Geometry */
|
||||
|
||||
static float p_vec_angle(const float v1[3], const float v2[3], const float v3[3])
|
||||
{
|
||||
return angle_v3v3v3(v1, v2, v3);
|
||||
}
|
||||
static float p_vec2_angle(const float v1[2], const float v2[2], const float v3[2])
|
||||
{
|
||||
return angle_v2v2v2(v1, v2, v3);
|
||||
}
|
||||
|
||||
/* Angles close to 0 or 180 degrees cause rows filled with zeros in the linear_solver.
|
||||
* The matrix will then be rank deficient and / or have poor conditioning.
|
||||
* => Reduce the maximum angle to 179 degrees, and spread the remainder to the other angles.
|
||||
|
@ -358,9 +347,9 @@ static void fix_large_angle(const float v_fix[3],
|
|||
static void p_triangle_angles(
|
||||
const float v1[3], const float v2[3], const float v3[3], float *r_a1, float *r_a2, float *r_a3)
|
||||
{
|
||||
*r_a1 = p_vec_angle(v3, v1, v2);
|
||||
*r_a2 = p_vec_angle(v1, v2, v3);
|
||||
*r_a3 = p_vec_angle(v2, v3, v1);
|
||||
*r_a1 = angle_v3v3v3(v3, v1, v2);
|
||||
*r_a2 = angle_v3v3v3(v1, v2, v3);
|
||||
*r_a3 = angle_v3v3v3(v2, v3, v1);
|
||||
|
||||
/* Fix for degenerate geometry e.g. v1 = sum(v2 + v3). See T100874 */
|
||||
fix_large_angle(v1, v2, v3, r_a1, r_a2, r_a3);
|
||||
|
@ -437,9 +426,7 @@ static float p_chart_uv_area(PChart *chart)
|
|||
|
||||
static void p_chart_uv_scale(PChart *chart, float scale)
|
||||
{
|
||||
PVert *v;
|
||||
|
||||
for (v = chart->verts; v; v = v->nextlink) {
|
||||
for (PVert *v = chart->verts; v; v = v->nextlink) {
|
||||
v->uv[0] *= scale;
|
||||
v->uv[1] *= scale;
|
||||
}
|
||||
|
@ -447,9 +434,7 @@ static void p_chart_uv_scale(PChart *chart, float scale)
|
|||
|
||||
static void p_chart_uv_scale_xy(PChart *chart, float x, float y)
|
||||
{
|
||||
PVert *v;
|
||||
|
||||
for (v = chart->verts; v; v = v->nextlink) {
|
||||
for (PVert *v = chart->verts; v; v = v->nextlink) {
|
||||
v->uv[0] *= x;
|
||||
v->uv[1] *= y;
|
||||
}
|
||||
|
@ -457,9 +442,7 @@ static void p_chart_uv_scale_xy(PChart *chart, float x, float y)
|
|||
|
||||
static void p_chart_uv_translate(PChart *chart, const float trans[2])
|
||||
{
|
||||
PVert *v;
|
||||
|
||||
for (v = chart->verts; v; v = v->nextlink) {
|
||||
for (PVert *v = chart->verts; v; v = v->nextlink) {
|
||||
v->uv[0] += trans[0];
|
||||
v->uv[1] += trans[1];
|
||||
}
|
||||
|
@ -467,9 +450,7 @@ static void p_chart_uv_translate(PChart *chart, const float trans[2])
|
|||
|
||||
static void p_chart_uv_transform(PChart *chart, const float mat[2][2])
|
||||
{
|
||||
PVert *v;
|
||||
|
||||
for (v = chart->verts; v; v = v->nextlink) {
|
||||
for (PVert *v = chart->verts; v; v = v->nextlink) {
|
||||
mul_m2_v2(mat, v->uv);
|
||||
}
|
||||
}
|
||||
|
@ -628,26 +609,19 @@ static void p_vert_load_pin_select_uvs(ParamHandle *handle, PVert *v)
|
|||
|
||||
static void p_flush_uvs(ParamHandle *handle, PChart *chart)
|
||||
{
|
||||
PEdge *e;
|
||||
|
||||
for (e = chart->edges; e; e = e->nextlink) {
|
||||
const float blend = handle->blend;
|
||||
const float invblend = 1.0f - blend;
|
||||
for (PEdge *e = chart->edges; e; e = e->nextlink) {
|
||||
if (e->orig_uv) {
|
||||
if (blend) {
|
||||
e->orig_uv[0] = blend * e->old_uv[0] + invblend * e->vert->uv[0] / handle->aspx;
|
||||
e->orig_uv[1] = blend * e->old_uv[1] + invblend * e->vert->uv[1] / handle->aspy;
|
||||
}
|
||||
else {
|
||||
e->orig_uv[0] = e->vert->uv[0] / handle->aspx;
|
||||
e->orig_uv[1] = e->vert->uv[1] / handle->aspy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void p_flush_uvs_blend(ParamHandle *handle, PChart *chart, float blend)
|
||||
{
|
||||
PEdge *e;
|
||||
float invblend = 1.0f - blend;
|
||||
|
||||
for (e = chart->edges; e; e = e->nextlink) {
|
||||
if (e->orig_uv) {
|
||||
e->orig_uv[0] = blend * e->old_uv[0] + invblend * e->vert->uv[0] / handle->aspx;
|
||||
e->orig_uv[1] = blend * e->old_uv[1] + invblend * e->vert->uv[1] / handle->aspy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1229,7 +1203,7 @@ static float p_edge_boundary_angle(PEdge *e)
|
|||
do {
|
||||
v1 = we->next->vert;
|
||||
v2 = we->next->next->vert;
|
||||
angle -= p_vec_angle(v1->co, v->co, v2->co);
|
||||
angle -= angle_v3v3v3(v1->co, v->co, v2->co);
|
||||
|
||||
we = we->next->next->pair;
|
||||
n++;
|
||||
|
@ -3113,29 +3087,21 @@ static void p_chart_lscm_begin(PChart *chart, bool live, bool abf)
|
|||
static bool p_chart_lscm_solve(ParamHandle *handle, PChart *chart)
|
||||
{
|
||||
LinearSolver *context = chart->u.lscm.context;
|
||||
PVert *v, *pin1 = chart->u.lscm.pin1, *pin2 = chart->u.lscm.pin2;
|
||||
PFace *f;
|
||||
const float *alpha = chart->u.lscm.abf_alpha;
|
||||
float area_pinned_up, area_pinned_down;
|
||||
bool flip_faces;
|
||||
int row;
|
||||
|
||||
#if 0
|
||||
/* TODO: make loading pins work for simplify/complexify. */
|
||||
#endif
|
||||
|
||||
for (v = chart->verts; v; v = v->nextlink) {
|
||||
for (PVert *v = chart->verts; v; v = v->nextlink) {
|
||||
if (v->flag & PVERT_PIN) {
|
||||
p_vert_load_pin_select_uvs(handle, v); /* reload for live */
|
||||
p_vert_load_pin_select_uvs(handle, v); /* Reload for Live Unwrap. */
|
||||
}
|
||||
}
|
||||
|
||||
if (chart->u.lscm.single_pin) {
|
||||
/* If only one pin, save area and pin for transform later. */
|
||||
/* If only one pin, save pin location for transform later. */
|
||||
copy_v2_v2(chart->u.lscm.single_pin_uv, chart->u.lscm.single_pin->uv);
|
||||
}
|
||||
|
||||
if (chart->u.lscm.pin1) {
|
||||
PVert *pin1 = chart->u.lscm.pin1;
|
||||
PVert *pin2 = chart->u.lscm.pin2;
|
||||
EIG_linear_solver_variable_lock(context, 2 * pin1->u.id);
|
||||
EIG_linear_solver_variable_lock(context, 2 * pin1->u.id + 1);
|
||||
EIG_linear_solver_variable_lock(context, 2 * pin2->u.id);
|
||||
|
@ -3147,8 +3113,8 @@ static bool p_chart_lscm_solve(ParamHandle *handle, PChart *chart)
|
|||
EIG_linear_solver_variable_set(context, 0, 2 * pin2->u.id + 1, pin2->uv[1]);
|
||||
}
|
||||
else {
|
||||
/* set and lock the pins */
|
||||
for (v = chart->verts; v; v = v->nextlink) {
|
||||
/* Set and lock the pins. */
|
||||
for (PVert *v = chart->verts; v; v = v->nextlink) {
|
||||
if (v->flag & PVERT_PIN) {
|
||||
EIG_linear_solver_variable_lock(context, 2 * v->u.id);
|
||||
EIG_linear_solver_variable_lock(context, 2 * v->u.id + 1);
|
||||
|
@ -3159,16 +3125,16 @@ static bool p_chart_lscm_solve(ParamHandle *handle, PChart *chart)
|
|||
}
|
||||
}
|
||||
|
||||
/* detect up direction based on pinned vertices */
|
||||
area_pinned_up = 0.0f;
|
||||
area_pinned_down = 0.0f;
|
||||
/* Detect "up" direction based on pinned vertices. */
|
||||
float area_pinned_up = 0.0f;
|
||||
float area_pinned_down = 0.0f;
|
||||
|
||||
for (f = chart->faces; f; f = f->nextlink) {
|
||||
for (PFace *f = chart->faces; f; f = f->nextlink) {
|
||||
PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
|
||||
PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
|
||||
|
||||
if ((v1->flag & PVERT_PIN) && (v2->flag & PVERT_PIN) && (v3->flag & PVERT_PIN)) {
|
||||
float area = p_face_uv_area_signed(f);
|
||||
const float area = p_face_uv_area_signed(f);
|
||||
|
||||
if (area > 0.0f) {
|
||||
area_pinned_up += area;
|
||||
|
@ -3179,19 +3145,18 @@ static bool p_chart_lscm_solve(ParamHandle *handle, PChart *chart)
|
|||
}
|
||||
}
|
||||
|
||||
flip_faces = (area_pinned_down > area_pinned_up);
|
||||
const bool flip_faces = (area_pinned_down > area_pinned_up);
|
||||
|
||||
/* construct matrix */
|
||||
|
||||
row = 0;
|
||||
for (f = chart->faces; f; f = f->nextlink) {
|
||||
/* Construct matrix. */
|
||||
const float *alpha = chart->u.lscm.abf_alpha;
|
||||
int row = 0;
|
||||
for (PFace *f = chart->faces; f; f = f->nextlink) {
|
||||
PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
|
||||
PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
|
||||
float a1, a2, a3, ratio, cosine, sine;
|
||||
float sina1, sina2, sina3, sinmax;
|
||||
float a1, a2, a3;
|
||||
|
||||
if (alpha) {
|
||||
/* use abf angles if passed on */
|
||||
/* Use abf angles if present. */
|
||||
a1 = *(alpha++);
|
||||
a2 = *(alpha++);
|
||||
a3 = *(alpha++);
|
||||
|
@ -3206,13 +3171,13 @@ static bool p_chart_lscm_solve(ParamHandle *handle, PChart *chart)
|
|||
SWAP(PVert *, v2, v3);
|
||||
}
|
||||
|
||||
sina1 = sinf(a1);
|
||||
sina2 = sinf(a2);
|
||||
sina3 = sinf(a3);
|
||||
float sina1 = sinf(a1);
|
||||
float sina2 = sinf(a2);
|
||||
float sina3 = sinf(a3);
|
||||
|
||||
sinmax = max_fff(sina1, sina2, sina3);
|
||||
const float sinmax = max_fff(sina1, sina2, sina3);
|
||||
|
||||
/* shift vertices to find most stable order */
|
||||
/* Shift vertices to find most stable order. */
|
||||
if (sina3 != sinmax) {
|
||||
SHIFT3(PVert *, v1, v2, v3);
|
||||
SHIFT3(float, a1, a2, a3);
|
||||
|
@ -3225,10 +3190,10 @@ static bool p_chart_lscm_solve(ParamHandle *handle, PChart *chart)
|
|||
}
|
||||
}
|
||||
|
||||
/* angle based lscm formulation */
|
||||
ratio = (sina3 == 0.0f) ? 1.0f : sina2 / sina3;
|
||||
cosine = cosf(a1) * ratio;
|
||||
sine = sina1 * ratio;
|
||||
/* Angle based lscm formulation. */
|
||||
const float ratio = (sina3 == 0.0f) ? 1.0f : sina2 / sina3;
|
||||
const float cosine = cosf(a1) * ratio;
|
||||
const float sine = sina1 * ratio;
|
||||
|
||||
EIG_linear_solver_matrix_add(context, row, 2 * v1->u.id, cosine - 1.0f);
|
||||
EIG_linear_solver_matrix_add(context, row, 2 * v1->u.id + 1, -sine);
|
||||
|
@ -3250,7 +3215,7 @@ static bool p_chart_lscm_solve(ParamHandle *handle, PChart *chart)
|
|||
return true;
|
||||
}
|
||||
|
||||
for (v = chart->verts; v; v = v->nextlink) {
|
||||
for (PVert *v = chart->verts; v; v = v->nextlink) {
|
||||
v->uv[0] = 0.0f;
|
||||
v->uv[1] = 0.0f;
|
||||
}
|
||||
|
@ -3588,7 +3553,7 @@ static float p_chart_minimum_area_angle(PChart *chart)
|
|||
p2 = points[i];
|
||||
p3 = (i == npoints - 1) ? points[0] : points[i + 1];
|
||||
|
||||
angles[i] = float(M_PI) - p_vec2_angle(p1->uv, p2->uv, p3->uv);
|
||||
angles[i] = float(M_PI) - angle_v2v2v2(p1->uv, p2->uv, p3->uv);
|
||||
|
||||
if (points[i]->uv[1] < miny) {
|
||||
miny = points[i]->uv[1];
|
||||
|
@ -3608,19 +3573,19 @@ static float p_chart_minimum_area_angle(PChart *chart)
|
|||
|
||||
v[0] = points[idx[0]]->uv[0];
|
||||
v[1] = points[idx[0]]->uv[1] + 1.0f;
|
||||
a[0] = p_vec2_angle(points[(idx[0] + 1) % npoints]->uv, points[idx[0]]->uv, v);
|
||||
a[0] = angle_v2v2v2(points[(idx[0] + 1) % npoints]->uv, points[idx[0]]->uv, v);
|
||||
|
||||
v[0] = points[idx[1]]->uv[0] + 1.0f;
|
||||
v[1] = points[idx[1]]->uv[1];
|
||||
a[1] = p_vec2_angle(points[(idx[1] + 1) % npoints]->uv, points[idx[1]]->uv, v);
|
||||
a[1] = angle_v2v2v2(points[(idx[1] + 1) % npoints]->uv, points[idx[1]]->uv, v);
|
||||
|
||||
v[0] = points[idx[2]]->uv[0];
|
||||
v[1] = points[idx[2]]->uv[1] - 1.0f;
|
||||
a[2] = p_vec2_angle(points[(idx[2] + 1) % npoints]->uv, points[idx[2]]->uv, v);
|
||||
a[2] = angle_v2v2v2(points[(idx[2] + 1) % npoints]->uv, points[idx[2]]->uv, v);
|
||||
|
||||
v[0] = points[idx[3]]->uv[0] - 1.0f;
|
||||
v[1] = points[idx[3]]->uv[1];
|
||||
a[3] = p_vec2_angle(points[(idx[3] + 1) % npoints]->uv, points[idx[3]]->uv, v);
|
||||
a[3] = angle_v2v2v2(points[(idx[3] + 1) % npoints]->uv, points[idx[3]]->uv, v);
|
||||
|
||||
/* 4 rotating calipers */
|
||||
|
||||
|
@ -4018,14 +3983,11 @@ void GEO_uv_parametrizer_construct_end(ParamHandle *phandle,
|
|||
|
||||
void GEO_uv_parametrizer_lscm_begin(ParamHandle *phandle, bool live, bool abf)
|
||||
{
|
||||
PFace *f;
|
||||
int i;
|
||||
|
||||
param_assert(phandle->state == PHANDLE_STATE_CONSTRUCTED);
|
||||
phandle->state = PHANDLE_STATE_LSCM;
|
||||
|
||||
for (i = 0; i < phandle->ncharts; i++) {
|
||||
for (f = phandle->charts[i]->faces; f; f = f->nextlink) {
|
||||
for (int i = 0; i < phandle->ncharts; i++) {
|
||||
for (PFace *f = phandle->charts[i]->faces; f; f = f->nextlink) {
|
||||
p_face_backup_uvs(f);
|
||||
}
|
||||
p_chart_lscm_begin(phandle->charts[i], live, abf);
|
||||
|
@ -4034,13 +3996,10 @@ void GEO_uv_parametrizer_lscm_begin(ParamHandle *phandle, bool live, bool abf)
|
|||
|
||||
void GEO_uv_parametrizer_lscm_solve(ParamHandle *phandle, int *count_changed, int *count_failed)
|
||||
{
|
||||
PChart *chart;
|
||||
int i;
|
||||
|
||||
param_assert(phandle->state == PHANDLE_STATE_LSCM);
|
||||
|
||||
for (i = 0; i < phandle->ncharts; i++) {
|
||||
chart = phandle->charts[i];
|
||||
for (int i = 0; i < phandle->ncharts; i++) {
|
||||
PChart *chart = phandle->charts[i];
|
||||
|
||||
if (chart->u.lscm.context) {
|
||||
const bool result = p_chart_lscm_solve(phandle, chart);
|
||||
|
@ -4427,13 +4386,8 @@ void GEO_uv_parametrizer_flush(ParamHandle *phandle)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (phandle->blend == 0.0f) {
|
||||
p_flush_uvs(phandle, chart);
|
||||
}
|
||||
else {
|
||||
p_flush_uvs_blend(phandle, chart, phandle->blend);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GEO_uv_parametrizer_flush_restore(ParamHandle *phandle)
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
/** \file
|
||||
* \ingroup obj
|
||||
*/
|
||||
/* Silence warnings from copying deprecated fields. Needed for an Object copy constructor use. */
|
||||
#define DNA_DEPRECATED_ALLOW
|
||||
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_customdata.h"
|
||||
|
@ -101,9 +99,8 @@ std::pair<Mesh *, bool> OBJMesh::triangulate_mesh_eval()
|
|||
* triangulated here. */
|
||||
const int triangulate_min_verts = 4;
|
||||
|
||||
unique_bmesh_ptr bmesh(
|
||||
BKE_mesh_to_bmesh_ex(export_mesh_eval_, &bm_create_params, &bm_convert_params));
|
||||
BM_mesh_triangulate(bmesh.get(),
|
||||
BMesh *bmesh = BKE_mesh_to_bmesh_ex(export_mesh_eval_, &bm_create_params, &bm_convert_params);
|
||||
BM_mesh_triangulate(bmesh,
|
||||
MOD_TRIANGULATE_NGON_BEAUTY,
|
||||
MOD_TRIANGULATE_QUAD_SHORTEDGE,
|
||||
triangulate_min_verts,
|
||||
|
@ -112,8 +109,8 @@ std::pair<Mesh *, bool> OBJMesh::triangulate_mesh_eval()
|
|||
nullptr,
|
||||
nullptr);
|
||||
|
||||
Mesh *triangulated = BKE_mesh_from_bmesh_for_eval_nomain(
|
||||
bmesh.get(), nullptr, export_mesh_eval_);
|
||||
Mesh *triangulated = BKE_mesh_from_bmesh_for_eval_nomain(bmesh, nullptr, export_mesh_eval_);
|
||||
BM_mesh_free(bmesh);
|
||||
free_mesh_if_needed();
|
||||
return {triangulated, true};
|
||||
}
|
||||
|
|
|
@ -28,20 +28,6 @@ const int NOT_FOUND = -1;
|
|||
/** Any negative number other than `NOT_FOUND` to initialize usually non-negative numbers. */
|
||||
const int NEGATIVE_INIT = -10;
|
||||
|
||||
/**
|
||||
* #std::unique_ptr than handles freeing #BMesh.
|
||||
*/
|
||||
struct CustomBMeshDeleter {
|
||||
void operator()(BMesh *bmesh)
|
||||
{
|
||||
if (bmesh) {
|
||||
BM_mesh_free(bmesh);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using unique_bmesh_ptr = std::unique_ptr<BMesh, CustomBMeshDeleter>;
|
||||
|
||||
class OBJMesh : NonCopyable {
|
||||
private:
|
||||
/**
|
||||
|
|
|
@ -273,13 +273,12 @@ static void rna_AssetHandle_file_data_set(PointerRNA *ptr,
|
|||
|
||||
static void rna_AssetHandle_get_full_library_path(
|
||||
// AssetHandle *asset,
|
||||
bContext *C,
|
||||
FileDirEntry *asset_file,
|
||||
AssetLibraryReference *library,
|
||||
AssetLibraryReference *UNUSED(asset_library), /* Deprecated. */
|
||||
char r_result[/*FILE_MAX_LIBEXTRA*/])
|
||||
{
|
||||
AssetHandle asset = {.file_data = asset_file};
|
||||
ED_asset_handle_get_full_library_path(C, library, &asset, r_result);
|
||||
ED_asset_handle_get_full_library_path(&asset, r_result);
|
||||
}
|
||||
|
||||
static PointerRNA rna_AssetHandle_local_id_get(PointerRNA *ptr)
|
||||
|
@ -424,19 +423,18 @@ static void rna_def_asset_handle_api(StructRNA *srna)
|
|||
PropertyRNA *parm;
|
||||
|
||||
func = RNA_def_function(srna, "get_full_library_path", "rna_AssetHandle_get_full_library_path");
|
||||
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
|
||||
/* TODO temporarily static function, for until .py can receive the asset handle from context
|
||||
* properly. `asset_file_handle` should go away too then. */
|
||||
RNA_def_function_flag(func, FUNC_NO_SELF);
|
||||
parm = RNA_def_pointer(func, "asset_file_handle", "FileSelectEntry", "", "");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
parm = RNA_def_pointer(func,
|
||||
RNA_def_pointer(
|
||||
func,
|
||||
"asset_library_ref",
|
||||
"AssetLibraryReference",
|
||||
"",
|
||||
"The asset library containing the given asset, only valid if the asset "
|
||||
"library is external (i.e. not the \"Current File\" one");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
"The asset library containing the given asset. Deprecated and optional argument, will be "
|
||||
"ignored. Kept for API compatibility only.");
|
||||
parm = RNA_def_string(func, "result", NULL, FILE_MAX_LIBEXTRA, "result", "");
|
||||
RNA_def_parameter_flags(parm, PROP_THICK_WRAP, 0);
|
||||
RNA_def_function_output(func, parm);
|
||||
|
|
|
@ -143,10 +143,12 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
GeometryComponent &component = geometry_set.get_component_for_write(
|
||||
GEO_COMPONENT_TYPE_INSTANCES);
|
||||
if (!bke::try_capture_field_on_geometry(component, name, domain, field)) {
|
||||
if (component.attribute_domain_size(domain) != 0) {
|
||||
failure.store(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
|
||||
for (const GeometryComponentType type :
|
||||
|
@ -154,10 +156,12 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
if (geometry_set.has(type)) {
|
||||
GeometryComponent &component = geometry_set.get_component_for_write(type);
|
||||
if (!bke::try_capture_field_on_geometry(component, name, domain, field)) {
|
||||
if (component.attribute_domain_size(domain) != 0) {
|
||||
failure.store(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -102,7 +102,9 @@ bool nodeGroupPoll(const bNodeTree *nodetree,
|
|||
return false;
|
||||
}
|
||||
if (nodetree->type != grouptree->type) {
|
||||
if (r_disabled_hint) {
|
||||
*r_disabled_hint = TIP_("Node group has different type");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,16 +51,72 @@ struct PyC_StringEnumItems bpygpu_dataformat_items[] = {
|
|||
/** \name Utilities
|
||||
* \{ */
|
||||
|
||||
bool bpygpu_is_init_or_error(void)
|
||||
{
|
||||
if (!GPU_is_init()) {
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"GPU functions for drawing are not available in background mode");
|
||||
static const char g_error[] = "GPU API is not available in background mode";
|
||||
|
||||
return false;
|
||||
static PyObject *py_error__ml_meth(PyObject *UNUSED(self), PyObject *UNUSED(args))
|
||||
{
|
||||
PyErr_SetString(PyExc_SystemError, g_error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject *py_error__getter(PyObject *UNUSED(self), void *UNUSED(type))
|
||||
{
|
||||
PyErr_SetString(PyExc_SystemError, g_error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int py_error__setter(PyObject *UNUSED(self), PyObject *UNUSED(value), void *UNUSED(type))
|
||||
{
|
||||
PyErr_SetString(PyExc_SystemError, g_error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static PyObject *py_error__tp_new(PyTypeObject *UNUSED(type),
|
||||
PyObject *UNUSED(args),
|
||||
PyObject *UNUSED(kwds))
|
||||
{
|
||||
PyErr_SetString(PyExc_SystemError, g_error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *bpygpu_create_module(PyModuleDef *module_type)
|
||||
{
|
||||
if (!GPU_is_init() && module_type->m_methods) {
|
||||
/* Replace all methods with an error method.
|
||||
* That way when the method is called, an error will appear instead. */
|
||||
for (PyMethodDef *meth = module_type->m_methods; meth->ml_name; meth++) {
|
||||
meth->ml_meth = py_error__ml_meth;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
PyObject *module = PyModule_Create(module_type);
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
int bpygpu_finalize_type(PyTypeObject *py_type)
|
||||
{
|
||||
if (!GPU_is_init()) {
|
||||
if (py_type->tp_methods) {
|
||||
/* Replace all methods with an error method. */
|
||||
for (PyMethodDef *meth = py_type->tp_methods; meth->ml_name; meth++) {
|
||||
meth->ml_meth = py_error__ml_meth;
|
||||
}
|
||||
}
|
||||
if (py_type->tp_getset) {
|
||||
/* Replace all getters and setter with a functions that always returns error. */
|
||||
for (PyGetSetDef *getset = py_type->tp_getset; getset->name; getset++) {
|
||||
getset->get = py_error__getter;
|
||||
getset->set = py_error__setter;
|
||||
}
|
||||
}
|
||||
if (py_type->tp_new) {
|
||||
/* If initialized, return error. */
|
||||
py_type->tp_new = py_error__tp_new;
|
||||
}
|
||||
}
|
||||
|
||||
return PyType_Ready(py_type);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -6,18 +6,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../generic/py_capi_utils.h"
|
||||
|
||||
extern struct PyC_StringEnumItems bpygpu_primtype_items[];
|
||||
extern struct PyC_StringEnumItems bpygpu_dataformat_items[];
|
||||
|
||||
bool bpygpu_is_init_or_error(void);
|
||||
|
||||
#define BPYGPU_IS_INIT_OR_ERROR_OBJ \
|
||||
if (UNLIKELY(!bpygpu_is_init_or_error())) { \
|
||||
return NULL; \
|
||||
} \
|
||||
((void)0)
|
||||
#define BPYGPU_IS_INIT_OR_ERROR_INT \
|
||||
if (UNLIKELY(!bpygpu_is_init_or_error())) { \
|
||||
return -1; \
|
||||
} \
|
||||
((void)0)
|
||||
PyObject *bpygpu_create_module(PyModuleDef *module_type);
|
||||
int bpygpu_finalize_type(PyTypeObject *py_type);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "gpu_py_state.h"
|
||||
#include "gpu_py_types.h"
|
||||
|
||||
#include "gpu_py.h"
|
||||
#include "gpu_py_api.h" /* Own include. */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -48,7 +49,7 @@ PyObject *BPyInit_gpu(void)
|
|||
PyObject *submodule;
|
||||
PyObject *mod;
|
||||
|
||||
mod = PyModule_Create(&pygpu_module_def);
|
||||
mod = bpygpu_create_module(&pygpu_module_def);
|
||||
|
||||
PyModule_AddObject(mod, "types", (submodule = bpygpu_types_init()));
|
||||
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
|
||||
|
|
|
@ -47,8 +47,6 @@ static bool pygpu_batch_is_program_or_error(BPyGPUBatch *self)
|
|||
|
||||
static PyObject *pygpu_batch__tp_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
|
||||
{
|
||||
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
||||
|
||||
const char *exc_str_missing_arg = "GPUBatch.__new__() missing required argument '%s' (pos %d)";
|
||||
|
||||
struct PyC_StringEnum prim_type = {bpygpu_primtype_items, GPU_PRIM_NONE};
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "GPU_capabilities.h"
|
||||
|
||||
#include "gpu_py.h"
|
||||
#include "gpu_py_capabilities.h" /* own include */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -315,7 +316,7 @@ PyObject *bpygpu_capabilities_init(void)
|
|||
{
|
||||
PyObject *submodule;
|
||||
|
||||
submodule = PyModule_Create(&pygpu_capabilities_module_def);
|
||||
submodule = bpygpu_create_module(&pygpu_capabilities_module_def);
|
||||
|
||||
return submodule;
|
||||
}
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
|
||||
static PyObject *pygpu_IndexBuf__tp_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
|
||||
{
|
||||
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
||||
|
||||
const char *error_prefix = "IndexBuf.__new__";
|
||||
bool ok = true;
|
||||
|
||||
|
|
|
@ -267,7 +267,6 @@ static PyObject *pygpu_framebuffer__tp_new(PyTypeObject *UNUSED(self),
|
|||
PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
||||
if (!GPU_context_active_get()) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "No active GPU context found");
|
||||
return NULL;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "GPU_matrix.h"
|
||||
#undef USE_GPU_PY_MATRIX_API
|
||||
|
||||
#include "gpu_py.h"
|
||||
#include "gpu_py_matrix.h" /* own include */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -542,9 +543,9 @@ PyObject *bpygpu_matrix_init(void)
|
|||
{
|
||||
PyObject *submodule;
|
||||
|
||||
submodule = PyModule_Create(&pygpu_matrix_module_def);
|
||||
submodule = bpygpu_create_module(&pygpu_matrix_module_def);
|
||||
|
||||
if (PyType_Ready(&PyGPUMatrixStackContext_Type) < 0) {
|
||||
if (bpygpu_finalize_type(&PyGPUMatrixStackContext_Type) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -211,8 +211,6 @@ static PyObject *pygpu_offscreen__tp_new(PyTypeObject *UNUSED(self),
|
|||
PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
||||
|
||||
GPUOffScreen *ofs = NULL;
|
||||
int width, height;
|
||||
struct PyC_StringEnum pygpu_textureformat = {pygpu_framebuffer_color_texture_formats, GPU_RGBA8};
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "GPU_context.h"
|
||||
#include "GPU_platform.h"
|
||||
|
||||
#include "gpu_py.h"
|
||||
#include "gpu_py_platform.h" /* Own include. */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -155,7 +156,7 @@ PyObject *bpygpu_platform_init(void)
|
|||
{
|
||||
PyObject *submodule;
|
||||
|
||||
submodule = PyModule_Create(&pygpu_platform_module_def);
|
||||
submodule = bpygpu_create_module(&pygpu_platform_module_def);
|
||||
|
||||
return submodule;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "GPU_select.h"
|
||||
|
||||
#include "gpu_py.h"
|
||||
#include "gpu_py_select.h" /* Own include. */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -72,7 +73,7 @@ PyObject *bpygpu_select_init(void)
|
|||
{
|
||||
PyObject *submodule;
|
||||
|
||||
submodule = PyModule_Create(&pygpu_select_module_def);
|
||||
submodule = bpygpu_create_module(&pygpu_select_module_def);
|
||||
|
||||
return submodule;
|
||||
}
|
||||
|
|
|
@ -95,8 +95,6 @@ static int pygpu_shader_uniform_location_get(GPUShader *shader,
|
|||
|
||||
static PyObject *pygpu_shader__tp_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
|
||||
{
|
||||
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
||||
|
||||
struct {
|
||||
const char *vertexcode;
|
||||
const char *fragcode;
|
||||
|
@ -835,8 +833,6 @@ PyDoc_STRVAR(
|
|||
" :rtype: :class:`bpy.types.GPUShader`\n");
|
||||
static PyObject *pygpu_shader_from_builtin(PyObject *UNUSED(self), PyObject *args, PyObject *kwds)
|
||||
{
|
||||
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
||||
|
||||
struct PyC_StringEnum pygpu_bultinshader = {pygpu_shader_builtin_items};
|
||||
struct PyC_StringEnum pygpu_config = {pygpu_shader_config_items, GPU_SHADER_CFG_DEFAULT};
|
||||
|
||||
|
@ -954,7 +950,7 @@ PyObject *bpygpu_shader_init(void)
|
|||
{
|
||||
PyObject *submodule;
|
||||
|
||||
submodule = PyModule_Create(&pygpu_shader_module_def);
|
||||
submodule = bpygpu_create_module(&pygpu_shader_module_def);
|
||||
|
||||
return submodule;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "../generic/py_capi_utils.h"
|
||||
#include "../generic/python_utildefines.h"
|
||||
|
||||
#include "gpu_py.h"
|
||||
#include "gpu_py_framebuffer.h"
|
||||
#include "gpu_py_state.h" /* own include */
|
||||
|
||||
|
@ -445,7 +446,7 @@ PyObject *bpygpu_state_init(void)
|
|||
{
|
||||
PyObject *submodule;
|
||||
|
||||
submodule = PyModule_Create(&pygpu_state_module_def);
|
||||
submodule = bpygpu_create_module(&pygpu_state_module_def);
|
||||
|
||||
return submodule;
|
||||
}
|
||||
|
|
|
@ -111,8 +111,6 @@ static int pygpu_texture_valid_check(BPyGPUTexture *bpygpu_tex)
|
|||
|
||||
static PyObject *pygpu_texture__tp_new(PyTypeObject *UNUSED(self), PyObject *args, PyObject *kwds)
|
||||
{
|
||||
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
||||
|
||||
PyObject *py_size;
|
||||
int size[3] = {1, 1, 1};
|
||||
int layers = 0;
|
||||
|
@ -605,7 +603,7 @@ int bpygpu_ParseTexture(PyObject *o, void *p)
|
|||
PyObject *bpygpu_texture_init(void)
|
||||
{
|
||||
PyObject *submodule;
|
||||
submodule = PyModule_Create(&pygpu_texture_module_def);
|
||||
submodule = bpygpu_create_module(&pygpu_texture_module_def);
|
||||
|
||||
return submodule;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "../generic/py_capi_utils.h"
|
||||
|
||||
#include "gpu_py.h"
|
||||
#include "gpu_py_types.h" /* own include */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -33,42 +34,42 @@ PyObject *bpygpu_types_init(void)
|
|||
{
|
||||
PyObject *submodule;
|
||||
|
||||
submodule = PyModule_Create(&pygpu_types_module_def);
|
||||
submodule = bpygpu_create_module(&pygpu_types_module_def);
|
||||
|
||||
if (PyType_Ready(&BPyGPU_BufferType) < 0) {
|
||||
if (bpygpu_finalize_type(&BPyGPU_BufferType) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyType_Ready(&BPyGPUVertFormat_Type) < 0) {
|
||||
if (bpygpu_finalize_type(&BPyGPUVertFormat_Type) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyType_Ready(&BPyGPUVertBuf_Type) < 0) {
|
||||
if (bpygpu_finalize_type(&BPyGPUVertBuf_Type) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyType_Ready(&BPyGPUIndexBuf_Type) < 0) {
|
||||
if (bpygpu_finalize_type(&BPyGPUIndexBuf_Type) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyType_Ready(&BPyGPUBatch_Type) < 0) {
|
||||
if (bpygpu_finalize_type(&BPyGPUBatch_Type) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyType_Ready(&BPyGPUOffScreen_Type) < 0) {
|
||||
if (bpygpu_finalize_type(&BPyGPUOffScreen_Type) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyType_Ready(&BPyGPUShader_Type) < 0) {
|
||||
if (bpygpu_finalize_type(&BPyGPUShader_Type) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyType_Ready(&BPyGPUTexture_Type) < 0) {
|
||||
if (bpygpu_finalize_type(&BPyGPUTexture_Type) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyType_Ready(&BPyGPUFrameBuffer_Type) < 0) {
|
||||
if (bpygpu_finalize_type(&BPyGPUFrameBuffer_Type) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyType_Ready(&BPyGPUUniformBuf_Type) < 0) {
|
||||
if (bpygpu_finalize_type(&BPyGPUUniformBuf_Type) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyType_Ready(&BPyGPUShaderCreateInfo_Type) < 0) {
|
||||
if (bpygpu_finalize_type(&BPyGPUShaderCreateInfo_Type) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyType_Ready(&BPyGPUStageInterfaceInfo_Type) < 0) {
|
||||
if (bpygpu_finalize_type(&BPyGPUStageInterfaceInfo_Type) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,8 +59,6 @@ static PyObject *pygpu_uniformbuffer__tp_new(PyTypeObject *UNUSED(self),
|
|||
PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
BPYGPU_IS_INIT_OR_ERROR_OBJ;
|
||||
|
||||
GPUUniformBuf *ubo = NULL;
|
||||
PyObject *pybuffer_obj;
|
||||
char err_out[256] = "unknown error. See console";
|
||||
|
|
|
@ -1332,10 +1332,7 @@ struct wmDragAssetCatalog *WM_drag_get_asset_catalog_data(const struct wmDrag *d
|
|||
/**
|
||||
* \note Does not store \a asset in any way, so it's fine to pass a temporary.
|
||||
*/
|
||||
void WM_drag_add_asset_list_item(wmDrag *drag,
|
||||
const struct bContext *C,
|
||||
const struct AssetLibraryReference *asset_library_ref,
|
||||
const struct AssetHandle *asset);
|
||||
void WM_drag_add_asset_list_item(wmDrag *drag, const struct AssetHandle *asset);
|
||||
const ListBase *WM_drag_asset_list_get(const wmDrag *drag);
|
||||
|
||||
const char *WM_drag_get_item_name(struct wmDrag *drag);
|
||||
|
|
|
@ -206,12 +206,11 @@ wmDrag *WM_drag_data_create(bContext *C, int icon, int type, void *poin, double
|
|||
/* The asset-list case is special: We get multiple assets from context and attach them to the
|
||||
* drag item. */
|
||||
case WM_DRAG_ASSET_LIST: {
|
||||
const AssetLibraryReference *asset_library = CTX_wm_asset_library_ref(C);
|
||||
ListBase asset_file_links = CTX_data_collection_get(C, "selected_asset_files");
|
||||
LISTBASE_FOREACH (const CollectionPointerLink *, link, &asset_file_links) {
|
||||
const FileDirEntry *asset_file = static_cast<const FileDirEntry *>(link->ptr.data);
|
||||
const AssetHandle asset_handle = {asset_file};
|
||||
WM_drag_add_asset_list_item(drag, C, asset_library, &asset_handle);
|
||||
WM_drag_add_asset_list_item(drag, &asset_handle);
|
||||
}
|
||||
BLI_freelistN(&asset_file_links);
|
||||
break;
|
||||
|
@ -711,12 +710,7 @@ wmDragAssetCatalog *WM_drag_get_asset_catalog_data(const wmDrag *drag)
|
|||
return static_cast<wmDragAssetCatalog *>(drag->poin);
|
||||
}
|
||||
|
||||
void WM_drag_add_asset_list_item(
|
||||
wmDrag *drag,
|
||||
/* Context only needed for the hack in #ED_asset_handle_get_full_library_path(). */
|
||||
const bContext *C,
|
||||
const AssetLibraryReference *asset_library_ref,
|
||||
const AssetHandle *asset)
|
||||
void WM_drag_add_asset_list_item(wmDrag *drag, const AssetHandle *asset)
|
||||
{
|
||||
BLI_assert(drag->type == WM_DRAG_ASSET_LIST);
|
||||
|
||||
|
@ -731,7 +725,7 @@ void WM_drag_add_asset_list_item(
|
|||
}
|
||||
else {
|
||||
char asset_blend_path[FILE_MAX_LIBEXTRA];
|
||||
ED_asset_handle_get_full_library_path(C, asset_library_ref, asset, asset_blend_path);
|
||||
ED_asset_handle_get_full_library_path(asset, asset_blend_path);
|
||||
drag_asset->is_external = true;
|
||||
drag_asset->asset_data.external_info = WM_drag_create_asset_data(
|
||||
asset, BLI_strdup(asset_blend_path), FILE_ASSET_IMPORT_APPEND);
|
||||
|
|
|
@ -922,6 +922,7 @@ static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo)
|
|||
}
|
||||
}
|
||||
else {
|
||||
wm_draw_region_stereo_set(bmain, area, region, STEREO_LEFT_ID);
|
||||
wm_draw_region_buffer_create(region, false, use_viewport);
|
||||
wm_draw_region_bind(region, 0);
|
||||
ED_region_do_draw(C, region);
|
||||
|
|
|
@ -247,7 +247,7 @@ class TestBlendLibLinkIndirect(TestBlendLibLinkHelper):
|
|||
|
||||
assert material.users == 2
|
||||
# Currently linked data which has no more local user never gets reset to indirectly linked status.
|
||||
# ~ assert material.is_library_indirect == True
|
||||
assert material.is_library_indirect == True
|
||||
|
||||
bpy.ops.wm.open_mainfile(filepath=output_work_path, load_ui=False)
|
||||
|
||||
|
@ -264,7 +264,7 @@ class TestBlendLibLinkIndirect(TestBlendLibLinkHelper):
|
|||
assert material.users == 2 # Fake user is not cleared when linking.
|
||||
# Currently even re-reading the .blend file will not properly reset tag for indirectly linked data,
|
||||
# if their reference was written in the .blend file.
|
||||
# ~ assert material.is_library_indirect == True
|
||||
assert material.is_library_indirect == True
|
||||
|
||||
assert mesh.library is not None
|
||||
assert mesh.use_fake_user is False
|
||||
|
|
|
@ -146,6 +146,8 @@ def check_lib_linking():
|
|||
with bpy.data.libraries.load(lib_path, link=True) as (data_from, data_to):
|
||||
data_to.scenes = ["Scene_lib"]
|
||||
|
||||
bpy.context.window.scene = bpy.data.scenes["Scene_lib"]
|
||||
|
||||
o = bpy.data.scenes["Scene_lib"].objects['Unique_Cube']
|
||||
|
||||
expect_false_or_abort(o.prop_array[0].test_prop == bpy.data.scenes["Scene_lib"].objects['Light'])
|
||||
|
@ -158,9 +160,10 @@ def check_lib_linking():
|
|||
def check_linked_scene_copying():
|
||||
# full copy of the scene with datablock props
|
||||
bpy.ops.wm.open_mainfile(filepath=test_path)
|
||||
bpy.context.window.scene = bpy.data.scenes["Scene_lib"]
|
||||
bpy.ops.scene.new(type='FULL_COPY')
|
||||
|
||||
bpy.context.window.scene = get_scene("lib.blend", "Scene_lib")
|
||||
|
||||
# check save/open
|
||||
bpy.ops.wm.save_as_mainfile(filepath=test_path)
|
||||
bpy.ops.wm.open_mainfile(filepath=test_path)
|
||||
|
|
Loading…
Reference in New Issue