WIP: Brush assets project #106303

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

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

View File

@ -73,8 +73,8 @@ Static Source Code Checking
Documentation Checking
* check_wiki_file_structure:
Check the WIKI documentation for the source-tree's file structure
* check_docs_file_structure:
Check the documentation for the source-tree's file structure
matches Blender's source-code.
See: https://developer.blender.org/docs/features/code_layout/
@ -503,9 +503,9 @@ check_clang_array: .FORCE
check_mypy: .FORCE
@$(PYTHON) "$(BLENDER_DIR)/tools/check_source/check_mypy.py"
check_wiki_file_structure: .FORCE
check_docs_file_structure: .FORCE
@PYTHONIOENCODING=utf_8 $(PYTHON) \
"$(BLENDER_DIR)/tools/check_wiki/check_wiki_file_structure.py"
"$(BLENDER_DIR)/tools/check_docs/check_docs_code_layout.py"
check_spelling_py: .FORCE
@PYTHONIOENCODING=utf_8 $(PYTHON) \

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
set(INC
include
PUBLIC include
)
set(INC_SYS
@ -20,3 +20,4 @@ set(LIB
)
blender_add_lib(extern_fmtlib "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
add_library(bf::extern::fmtlib ALIAS extern_fmtlib)

View File

@ -76,8 +76,9 @@ ccl_device int bsdf_transparent_sample(ccl_private const ShaderClosure *sc,
{
// only one direction is possible
*wo = -wi;
*pdf = 1;
*eval = one_spectrum();
/* Some high number for MIS. */
*pdf = 1e6f;
*eval = one_spectrum() * 1e6f;
return LABEL_TRANSMIT | LABEL_TRANSPARENT;
}

View File

@ -208,6 +208,7 @@ void Scene::device_update(Device *device_, Progress &progress)
if (film->update_lightgroups(this)) {
light_manager->tag_update(this, ccl::LightManager::LIGHT_MODIFIED);
object_manager->tag_update(this, ccl::ObjectManager::OBJECT_MODIFIED);
background->tag_modified();
}
if (film->exposure_is_modified()) {
integrator->tag_modified();

View File

@ -1320,9 +1320,14 @@ class UserExtensionRepo(StructRNA):
"""Return ``directory`` or a default path derived from the users scripts path."""
if self.use_custom_directory:
return self.custom_directory
import os
import bpy
return os.path.join(bpy.utils.user_resource('SCRIPTS', path="extensions"), self.module)
import os
# TODO: this should eventually be accessed via `bpy.utils.user_resource('EXTENSIONS')`
# which points to the same location (by default).
if (path := bpy.utils.resource_path('USER')):
return os.path.join(path, "extensions", self.module)
# Unlikely this is ever encountered.
return ""
class HydraRenderEngine(RenderEngine):

View File

@ -5,6 +5,7 @@
#pragma once
#include "BLI_fileops.hh"
#include "BLI_function_ref.hh"
#include "BLI_serialize.hh"
#include "BKE_bake_items.hh"
@ -33,6 +34,13 @@ class BlobReader {
* \return True on success, otherwise false.
*/
[[nodiscard]] virtual bool read(const BlobSlice &slice, void *r_data) const = 0;
/**
* Provides an #istream that can be used to read the data from the given slice.
* \return True on success, otherwise false.
*/
[[nodiscard]] virtual bool read_as_stream(const BlobSlice &slice,
FunctionRef<bool(std::istream &)> fn) const;
};
/**
@ -45,6 +53,15 @@ class BlobWriter {
* \return Slice where the data has been written to.
*/
virtual BlobSlice write(const void *data, int64_t size) = 0;
/**
* Provides an #ostream that can be used to write the blob.
* \param file_extension: May be used if the data is written to an independent file. Based on the
* implementation, this may be ignored.
* \return Slice where the data has been written to.
*/
virtual BlobSlice write_as_stream(StringRef file_extension,
FunctionRef<void(std::ostream &)> fn);
};
/**
@ -72,6 +89,24 @@ class BlobWriteSharing : NonCopyable, NonMovable {
*/
Map<const ImplicitSharingInfo *, StoredByRuntimeValue> stored_by_runtime_;
struct SliceHash {
uint64_t a;
uint64_t b;
BLI_STRUCT_EQUALITY_OPERATORS_2(SliceHash, a, b)
uint64_t hash() const
{
return get_default_hash(this->a, this->b);
}
};
/**
* Remembers where data was stored based on the hash of the data. This allows us to skip writing
* the same array again if it has the same hash.
*/
Map<SliceHash, BlobSlice> slice_by_content_hash_;
public:
~BlobWriteSharing();
@ -84,6 +119,14 @@ class BlobWriteSharing : NonCopyable, NonMovable {
[[nodiscard]] std::shared_ptr<io::serialize::DictionaryValue> write_implicitly_shared(
const ImplicitSharingInfo *sharing_info,
FunctionRef<std::shared_ptr<io::serialize::DictionaryValue>()> write_fn);
/**
* Checks if the given data was written before. If it was, it's not written again, but a
* reference to the previously written data is returned. If the data is new, it's written now.
* Its hash is remembered so that the same data won't be written again.
*/
[[nodiscard]] std::shared_ptr<io::serialize::DictionaryValue> write_deduplicated(
BlobWriter &writer, const void *data, int64_t size_in_bytes);
};
/**
@ -132,17 +175,25 @@ class DiskBlobReader : public BlobReader {
*/
class DiskBlobWriter : public BlobWriter {
private:
/** Directory path that contains all blob files. */
std::string blob_dir_;
/** Name of the file that data is written to. */
std::string base_name_;
std::string blob_name_;
/** File handle. */
std::ostream &blob_file_;
/** File handle. The file is opened when the first data is written. */
std::fstream blob_stream_;
/** Current position in the file. */
int64_t current_offset_;
int64_t current_offset_ = 0;
/** Used to generate file names for bake data that is stored in independent files. */
int independent_file_count_ = 0;
public:
DiskBlobWriter(std::string blob_name, std::ostream &blob_file, int64_t current_offset);
DiskBlobWriter(std::string blob_dir, std::string base_name);
BlobSlice write(const void *data, int64_t size) override;
BlobSlice write_as_stream(StringRef file_extension,
FunctionRef<void(std::ostream &)> fn) override;
};
void serialize_bake(const BakeState &bake_state,

View File

@ -24,6 +24,7 @@
#include "BLI_array.hh"
#include "BLI_function_ref.hh"
#include "BLI_index_mask_fwd.hh"
#include "BLI_math_matrix_types.hh"
#include "BLI_vector.hh"
@ -31,17 +32,11 @@
struct Object;
struct Collection;
namespace blender {
namespace index_mask {
class IndexMask;
}
using index_mask::IndexMask;
namespace bke {
namespace blender::bke {
class AnonymousAttributePropagationInfo;
class AttributeAccessor;
class MutableAttributeAccessor;
} // namespace bke
} // namespace blender
} // namespace blender::bke
namespace blender::bke {

View File

@ -8,13 +8,7 @@
* \ingroup bke
*/
namespace blender {
namespace index_mask {
class IndexMask;
}
using index_mask::IndexMask;
} // namespace blender
#include "BLI_index_mask_fwd.hh"
#include "BLI_offset_indices.hh"
#include "BKE_mesh.h"

View File

@ -7,6 +7,7 @@
* \ingroup bke
*/
#include <memory>
#include <string>
#include "BLI_compiler_attrs.h"
@ -67,8 +68,6 @@ struct wmSpaceTypeListenerParams {
};
struct SpaceType {
SpaceType *next, *prev;
char name[BKE_ST_MAXNAME]; /* for menus */
int spaceid; /* unique space identifier */
int iconid; /* icon lookup for menus */
@ -147,6 +146,8 @@ struct SpaceType {
/** Default key-maps to add. */
int keymapflag;
~SpaceType();
};
/* region types are also defined using spacetypes_init, via a callback */
@ -547,8 +548,8 @@ struct AssetShelfType {
SpaceType *BKE_spacetype_from_id(int spaceid);
ARegionType *BKE_regiontype_from_id(const SpaceType *st, int regionid);
const ListBase *BKE_spacetypes_list();
void BKE_spacetype_register(SpaceType *st);
blender::Span<std::unique_ptr<SpaceType>> BKE_spacetypes_list();
void BKE_spacetype_register(std::unique_ptr<SpaceType> st);
bool BKE_spacetype_exists(int spaceid);
void BKE_spacetypes_free(); /* only for quitting blender */

View File

@ -10,15 +10,9 @@
#include <memory>
namespace blender {
namespace index_mask {
class IndexMask;
}
using index_mask::IndexMask;
} // namespace blender
#include "BLI_array.hh"
#include "BLI_bit_group_vector.hh"
#include "BLI_index_mask_fwd.hh"
#include "BLI_offset_indices.hh"
#include "BLI_sys_types.h"

View File

@ -9,6 +9,7 @@
* \brief Volume data-block.
*/
#include <memory>
#include <optional>
#include "BLI_bounds_types.hh"
@ -24,6 +25,10 @@ struct Scene;
struct Volume;
struct VolumeGridVector;
namespace blender::bke::bake {
struct BakeMaterialsList;
}
/* Module */
void BKE_volumes_init();
@ -133,6 +138,8 @@ struct VolumeRuntime {
char velocity_x_grid[64] = "";
char velocity_y_grid[64] = "";
char velocity_z_grid[64] = "";
std::unique_ptr<bake::BakeMaterialsList> bake_materials;
};
} // namespace blender::bke

View File

@ -29,7 +29,6 @@ set(INC
../../../intern/memutil
../../../intern/mikktspace
../../../intern/opensubdiv
../../../extern/fmtlib/include
# RNA_prototypes.h
${CMAKE_BINARY_DIR}/source/blender/makesrna
@ -575,7 +574,7 @@ set(LIB
bf_rna
bf_shader_fx
bf_simulation
extern_fmtlib
PRIVATE bf::extern::fmtlib
PRIVATE bf::intern::atomic
# For `vfontdata_freetype.c`.
${FREETYPE_LIBRARIES} ${BROTLI_LIBRARIES}

View File

@ -9,6 +9,7 @@
#include "BKE_lib_id.hh"
#include "BKE_mesh.hh"
#include "BKE_pointcloud.hh"
#include "BKE_volume.hh"
#include "BLI_endian_defines.h"
#include "BLI_endian_switch.h"
@ -16,6 +17,7 @@
#include "BLI_path_util.h"
#include "DNA_material_types.h"
#include "DNA_volume_types.h"
#include "RNA_access.hh"
#include "RNA_enum_types.hh"
@ -71,12 +73,17 @@ void GeometryBakeItem::prepare_geometry_for_bake(GeometrySet &main_geometry,
pointcloud->runtime->bake_materials = materials_to_weak_references(
&pointcloud->mat, &pointcloud->totcol, data_block_map);
}
if (Volume *volume = geometry.get_volume_for_write()) {
volume->runtime->bake_materials = materials_to_weak_references(
&volume->mat, &volume->totcol, data_block_map);
}
if (bke::Instances *instances = geometry.get_instances_for_write()) {
instances->attributes_for_write().remove_anonymous();
}
geometry.keep_only_during_modify({GeometryComponent::Type::Mesh,
GeometryComponent::Type::Curve,
GeometryComponent::Type::PointCloud,
GeometryComponent::Type::Volume,
GeometryComponent::Type::Instance});
});
}
@ -125,6 +132,12 @@ void GeometryBakeItem::try_restore_data_blocks(GeometrySet &main_geometry,
std::move(pointcloud->runtime->bake_materials),
data_block_map);
}
if (Volume *volume = geometry.get_volume_for_write()) {
restore_materials(&volume->mat,
&volume->totcol,
std::move(volume->runtime->bake_materials),
data_block_map);
}
});
}

View File

@ -10,19 +10,30 @@
#include "BKE_lib_id.hh"
#include "BKE_mesh.hh"
#include "BKE_pointcloud.hh"
#include "BKE_volume.hh"
#include "BLI_endian_defines.h"
#include "BLI_endian_switch.h"
#include "BLI_hash_md5.hh"
#include "BLI_math_matrix_types.hh"
#include "BLI_path_util.h"
#include "DNA_material_types.h"
#include "DNA_volume_types.h"
#include "RNA_access.hh"
#include "RNA_enum_types.hh"
#include <fmt/format.h>
#include <sstream>
#ifdef WITH_OPENVDB
# include <openvdb/io/Stream.h>
# include <openvdb/openvdb.h>
# include "BKE_volume_grid.hh"
#endif
namespace blender::bke::bake {
using namespace io::serialize;
@ -49,6 +60,30 @@ std::optional<BlobSlice> BlobSlice::deserialize(const DictionaryValue &io_slice)
return BlobSlice{*name, {*start, *size}};
}
BlobSlice BlobWriter::write_as_stream(const StringRef /*file_extension*/,
const FunctionRef<void(std::ostream &)> fn)
{
std::ostringstream stream{std::ios::binary};
fn(stream);
std::string data = stream.rdbuf()->str();
return this->write(data.data(), data.size());
}
bool BlobReader::read_as_stream(const BlobSlice &slice, FunctionRef<bool(std::istream &)> fn) const
{
const int64_t size = slice.range.size();
std::string buffer;
buffer.resize(size);
if (!this->read(slice, buffer.data())) {
return false;
}
std::istringstream stream{buffer, std::ios::binary};
if (!fn(stream)) {
return false;
}
return true;
}
DiskBlobReader::DiskBlobReader(std::string blobs_dir) : blobs_dir_(std::move(blobs_dir)) {}
[[nodiscard]] bool DiskBlobReader::read(const BlobSlice &slice, void *r_data) const
@ -72,21 +107,44 @@ DiskBlobReader::DiskBlobReader(std::string blobs_dir) : blobs_dir_(std::move(blo
return true;
}
DiskBlobWriter::DiskBlobWriter(std::string blob_name,
std::ostream &blob_file,
const int64_t current_offset)
: blob_name_(std::move(blob_name)), blob_file_(blob_file), current_offset_(current_offset)
DiskBlobWriter::DiskBlobWriter(std::string blob_dir, std::string base_name)
: blob_dir_(std::move(blob_dir)), base_name_(std::move(base_name))
{
blob_name_ = base_name_ + ".blob";
}
BlobSlice DiskBlobWriter::write(const void *data, const int64_t size)
{
if (!blob_stream_.is_open()) {
char blob_path[FILE_MAX];
BLI_path_join(blob_path, sizeof(blob_path), blob_dir_.c_str(), blob_name_.c_str());
BLI_file_ensure_parent_dir_exists(blob_path);
blob_stream_.open(blob_path, std::ios::out | std::ios::binary);
}
const int64_t old_offset = current_offset_;
blob_file_.write(static_cast<const char *>(data), size);
blob_stream_.write(static_cast<const char *>(data), size);
current_offset_ += size;
return {blob_name_, {old_offset, size}};
}
BlobSlice DiskBlobWriter::write_as_stream(const StringRef file_extension,
const FunctionRef<void(std::ostream &)> fn)
{
BLI_assert(file_extension.startswith("."));
independent_file_count_++;
const std::string file_name = fmt::format(
"{}_file_{}{}", base_name_, independent_file_count_, file_extension);
char path[FILE_MAX];
BLI_path_join(path, sizeof(path), blob_dir_.c_str(), file_name.c_str());
BLI_file_ensure_parent_dir_exists(path);
std::fstream stream{path, std::ios::out | std::ios::binary};
fn(stream);
const int64_t written_bytes_num = stream.tellg();
return {file_name, {0, written_bytes_num}};
}
BlobWriteSharing::~BlobWriteSharing()
{
for (const ImplicitSharingInfo *sharing_info : stored_by_runtime_.keys()) {
@ -131,6 +189,16 @@ DictionaryValuePtr BlobWriteSharing::write_implicitly_shared(
});
}
std::shared_ptr<io::serialize::DictionaryValue> BlobWriteSharing::write_deduplicated(
BlobWriter &writer, const void *data, const int64_t size_in_bytes)
{
SliceHash content_hash;
BLI_hash_md5_buffer(static_cast<const char *>(data), size_in_bytes, &content_hash);
const BlobSlice slice = slice_by_content_hash_.lookup_or_add_cb(
content_hash, [&]() { return writer.write(data, size_in_bytes); });
return slice.serialize();
}
std::optional<ImplicitSharingInfoAndData> BlobReadSharing::read_shared(
const DictionaryValue &io_data,
FunctionRef<std::optional<ImplicitSharingInfoAndData>()> read_fn) const
@ -202,9 +270,12 @@ static std::optional<eCustomDataType> get_data_type_from_io_name(const StringRef
* Write the data and remember which endianness the data had.
*/
static std::shared_ptr<DictionaryValue> write_blob_raw_data_with_endian(
BlobWriter &blob_writer, const void *data, const int64_t size_in_bytes)
BlobWriter &blob_writer,
BlobWriteSharing &blob_sharing,
const void *data,
const int64_t size_in_bytes)
{
auto io_data = blob_writer.write(data, size_in_bytes).serialize();
auto io_data = blob_sharing.write_deduplicated(blob_writer, data, size_in_bytes);
if (ENDIAN_ORDER == B_ENDIAN) {
io_data->append_str("endian", get_endian_io_name(ENDIAN_ORDER));
}
@ -255,10 +326,11 @@ static std::shared_ptr<DictionaryValue> write_blob_raw_data_with_endian(
/** Write bytes ignoring endianness. */
static std::shared_ptr<DictionaryValue> write_blob_raw_bytes(BlobWriter &blob_writer,
BlobWriteSharing &blob_sharing,
const void *data,
const int64_t size_in_bytes)
{
return blob_writer.write(data, size_in_bytes).serialize();
return blob_sharing.write_deduplicated(blob_writer, data, size_in_bytes);
}
/** Read bytes ignoring endianness. */
@ -278,14 +350,16 @@ static std::shared_ptr<DictionaryValue> write_blob_raw_bytes(BlobWriter &blob_wr
}
static std::shared_ptr<DictionaryValue> write_blob_simple_gspan(BlobWriter &blob_writer,
BlobWriteSharing &blob_sharing,
const GSpan data)
{
const CPPType &type = data.type();
BLI_assert(type.is_trivial());
if (type.size() == 1 || type.is<ColorGeometry4b>()) {
return write_blob_raw_bytes(blob_writer, data.data(), data.size_in_bytes());
return write_blob_raw_bytes(blob_writer, blob_sharing, data.data(), data.size_in_bytes());
}
return write_blob_raw_data_with_endian(blob_writer, data.data(), data.size_in_bytes());
return write_blob_raw_data_with_endian(
blob_writer, blob_sharing, data.data(), data.size_in_bytes());
}
[[nodiscard]] static bool read_blob_simple_gspan(const BlobReader &blob_reader,
@ -327,7 +401,7 @@ static std::shared_ptr<DictionaryValue> write_blob_shared_simple_gspan(
const ImplicitSharingInfo *sharing_info)
{
return blob_sharing.write_implicitly_shared(
sharing_info, [&]() { return write_blob_simple_gspan(blob_writer, data); });
sharing_info, [&]() { return write_blob_simple_gspan(blob_writer, blob_sharing, data); });
}
[[nodiscard]] static const void *read_blob_shared_simple_gspan(
@ -666,6 +740,54 @@ static std::unique_ptr<Instances> try_load_instances(const DictionaryValue &io_g
return instances;
}
#ifdef WITH_OPENVDB
static Volume *try_load_volume(const DictionaryValue &io_geometry, const BlobReader &blob_reader)
{
const DictionaryValue *io_volume = io_geometry.lookup_dict("volume");
if (!io_volume) {
return nullptr;
}
const auto *io_vdb = io_volume->lookup_dict("vdb");
if (!io_vdb) {
return nullptr;
}
openvdb::GridPtrVecPtr vdb_grids;
if (std::optional<BlobSlice> vdb_slice = BlobSlice::deserialize(*io_vdb)) {
if (!blob_reader.read_as_stream(*vdb_slice, [&](std::istream &stream) {
try {
openvdb::io::Stream vdb_stream{stream};
vdb_grids = vdb_stream.getGrids();
return true;
}
catch (...) {
return false;
}
}))
{
return nullptr;
}
}
Volume *volume = reinterpret_cast<Volume *>(BKE_id_new_nomain(ID_VO, nullptr));
auto cancel = [&]() {
BKE_id_free(nullptr, volume);
return nullptr;
};
for (openvdb::GridBase::Ptr &vdb_grid : *vdb_grids) {
if (vdb_grid) {
bke::GVolumeGrid grid{std::move(vdb_grid)};
BKE_volume_grid_add(volume, *grid.release());
}
}
if (const io::serialize::ArrayValue *io_materials = io_volume->lookup_array("materials")) {
if (!load_materials(*io_materials, volume->runtime->bake_materials)) {
return cancel();
}
}
return volume;
}
#endif
static GeometrySet load_geometry(const DictionaryValue &io_geometry,
const BlobReader &blob_reader,
const BlobReadSharing &blob_sharing)
@ -675,6 +797,9 @@ static GeometrySet load_geometry(const DictionaryValue &io_geometry,
geometry.replace_pointcloud(try_load_pointcloud(io_geometry, blob_reader, blob_sharing));
geometry.replace_curves(try_load_curves(io_geometry, blob_reader, blob_sharing));
geometry.replace_instances(try_load_instances(io_geometry, blob_reader, blob_sharing).release());
#ifdef WITH_OPENVDB
geometry.replace_volume(try_load_volume(io_geometry, blob_reader));
#endif
return geometry;
}
@ -801,6 +926,34 @@ static std::shared_ptr<DictionaryValue> serialize_geometry_set(const GeometrySet
auto io_attributes = serialize_attributes(curves.attributes(), blob_writer, blob_sharing, {});
io_curves->append("attributes", io_attributes);
}
#ifdef WITH_OPENVDB
if (geometry.has_volume()) {
const Volume &volume = *geometry.get_volume();
const int grids_num = BKE_volume_num_grids(&volume);
auto io_volume = io_geometry->append_dict("volume");
auto io_vdb = blob_writer
.write_as_stream(".vdb",
[&](std::ostream &stream) {
openvdb::GridCPtrVec vdb_grids;
Vector<bke::VolumeTreeAccessToken> tree_tokens;
for (const int i : IndexRange(grids_num)) {
const bke::VolumeGridData *grid = BKE_volume_grid_get(
&volume, i);
tree_tokens.append_as();
vdb_grids.push_back(grid->grid_ptr(tree_tokens.last()));
}
openvdb::io::Stream vdb_stream(stream);
vdb_stream.write(vdb_grids);
})
.serialize();
io_volume->append("vdb", std::move(io_vdb));
auto io_materials = serialize_materials(volume.runtime->bake_materials);
io_volume->append("materials", io_materials);
}
#endif
if (geometry.has_instances()) {
const Instances &instances = *geometry.get_instances();
auto io_instances = io_geometry->append_dict("instances");
@ -814,10 +967,11 @@ static std::shared_ptr<DictionaryValue> serialize_geometry_set(const GeometrySet
serialize_geometry_set(reference.geometry_set(), blob_writer, blob_sharing));
}
io_instances->append("transforms",
write_blob_simple_gspan(blob_writer, instances.transforms()));
io_instances->append("handles",
write_blob_simple_gspan(blob_writer, instances.reference_handles()));
io_instances->append(
"transforms", write_blob_simple_gspan(blob_writer, blob_sharing, instances.transforms()));
io_instances->append(
"handles",
write_blob_simple_gspan(blob_writer, blob_sharing, instances.reference_handles()));
auto io_attributes = serialize_attributes(
instances.attributes(), blob_writer, blob_sharing, {"position"});
@ -1037,7 +1191,8 @@ static void serialize_bake_item(const BakeItem &item,
r_io_item.append_str("data", string_state_item->value());
}
else {
r_io_item.append("data", write_blob_raw_bytes(blob_writer, str.data(), str.size()));
r_io_item.append("data",
write_blob_raw_bytes(blob_writer, blob_sharing, str.data(), str.size()));
}
}
else if (const auto *primitive_state_item = dynamic_cast<const PrimitiveBakeItem *>(&item)) {

View File

@ -209,8 +209,13 @@ static void default_initialize_socket_value(const eNodeSocketDatatype socket_typ
{
const char *socket_idname = nodeStaticSocketType(socket_type, 0);
const bNodeSocketType *typeinfo = nodeSocketTypeFind(socket_idname);
typeinfo->geometry_nodes_cpp_type->copy_construct(typeinfo->geometry_nodes_default_cpp_value,
r_value);
if (typeinfo->geometry_nodes_default_cpp_value) {
typeinfo->geometry_nodes_cpp_type->copy_construct(typeinfo->geometry_nodes_default_cpp_value,
r_value);
}
else {
typeinfo->geometry_nodes_cpp_type->value_initialize(r_value);
}
}
void move_bake_items_to_socket_values(

View File

@ -242,15 +242,14 @@ void BKE_preferences_extension_repo_dirpath_get(const bUserExtensionRepo *repo,
return;
}
char subdir[16 + sizeof(bUserExtensionRepo::module)];
BLI_string_join(subdir, sizeof(subdir), "extensions", SEP_STR, repo->module);
const std::optional<std::string> path = BKE_appdir_folder_id(BLENDER_USER_SCRIPTS, subdir);
if (path.has_value()) {
BLI_strncpy(dirpath, path.value().c_str(), dirpath_maxncpy);
}
else {
/* TODO: support `BLENDER_USER_EXTENSIONS`, until then add to user resource. */
std::optional<std::string> path = BKE_appdir_resource_path_id(BLENDER_RESOURCE_PATH_USER, false);
/* Highly unlikely to fail as the directory doesn't have to exist. */
if (!path) {
dirpath[0] = '\0';
return;
}
BLI_path_join(dirpath, dirpath_maxncpy, path.value().c_str(), "extensions", repo->module);
}
bUserExtensionRepo *BKE_preferences_extension_repo_find_index(const UserDef *userdef, int index)

View File

@ -62,6 +62,9 @@
# include "BPY_extern.h"
#endif
using blender::Span;
using blender::Vector;
/* -------------------------------------------------------------------- */
/** \name ID Type Implementation
* \{ */
@ -201,12 +204,16 @@ IDTypeInfo IDType_ID_SCR = {
* \{ */
/** Keep global; this has to be accessible outside of window-manager. */
static ListBase spacetypes = {nullptr, nullptr};
static Vector<std::unique_ptr<SpaceType>> &get_space_types()
{
static Vector<std::unique_ptr<SpaceType>> space_types;
return space_types;
}
/* not SpaceType itself */
static void spacetype_free(SpaceType *st)
SpaceType::~SpaceType()
{
LISTBASE_FOREACH (ARegionType *, art, &st->regiontypes) {
LISTBASE_FOREACH (ARegionType *, art, &this->regiontypes) {
#ifdef WITH_PYTHON
BPY_callback_screen_free(art);
#endif
@ -230,24 +237,20 @@ static void spacetype_free(SpaceType *st)
BLI_freelistN(&art->headertypes);
}
BLI_freelistN(&st->regiontypes);
BLI_freelistN(&st->asset_shelf_types);
BLI_freelistN(&this->regiontypes);
BLI_freelistN(&this->asset_shelf_types);
}
void BKE_spacetypes_free()
{
LISTBASE_FOREACH (SpaceType *, st, &spacetypes) {
spacetype_free(st);
}
BLI_freelistN(&spacetypes);
get_space_types().clear_and_shrink();
}
SpaceType *BKE_spacetype_from_id(int spaceid)
{
LISTBASE_FOREACH (SpaceType *, st, &spacetypes) {
for (std::unique_ptr<SpaceType> &st : get_space_types()) {
if (st->spaceid == spaceid) {
return st;
return st.get();
}
}
return nullptr;
@ -263,22 +266,21 @@ ARegionType *BKE_regiontype_from_id(const SpaceType *st, int regionid)
return nullptr;
}
const ListBase *BKE_spacetypes_list()
Span<std::unique_ptr<SpaceType>> BKE_spacetypes_list()
{
return &spacetypes;
return get_space_types();
}
void BKE_spacetype_register(SpaceType *st)
void BKE_spacetype_register(std::unique_ptr<SpaceType> st)
{
/* sanity check */
SpaceType *stype = BKE_spacetype_from_id(st->spaceid);
if (stype) {
printf("error: redefinition of spacetype %s\n", stype->name);
spacetype_free(stype);
MEM_freeN(stype);
return;
}
BLI_addtail(&spacetypes, st);
get_space_types().append(std::move(st));
}
bool BKE_spacetype_exists(int spaceid)
@ -408,7 +410,7 @@ void BKE_spacedata_copylist(ListBase *lb_dst, ListBase *lb_src)
void BKE_spacedata_draw_locks(bool set)
{
LISTBASE_FOREACH (SpaceType *, st, &spacetypes) {
for (std::unique_ptr<SpaceType> &st : get_space_types()) {
LISTBASE_FOREACH (ARegionType *, art, &st->regiontypes) {
if (set) {
art->do_lock = art->lock;

View File

@ -30,6 +30,7 @@
#include "BLI_utildefines.h"
#include "BKE_anim_data.h"
#include "BKE_bake_data_block_id.hh"
#include "BKE_bpath.h"
#include "BKE_geometry_set.hh"
#include "BKE_global.h"
@ -170,6 +171,11 @@ static void volume_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, con
STRNCPY(volume_dst->runtime->velocity_y_grid, volume_src->runtime->velocity_y_grid);
STRNCPY(volume_dst->runtime->velocity_z_grid, volume_src->runtime->velocity_z_grid);
if (volume_src->runtime->bake_materials) {
volume_dst->runtime->bake_materials = std::make_unique<blender::bke::bake::BakeMaterialsList>(
*volume_src->runtime->bake_materials);
}
volume_dst->batch_cache = nullptr;
}

View File

@ -11,15 +11,13 @@
#include "BLI_bit_span.hh"
#include "BLI_function_ref.hh"
#include "BLI_index_mask_fwd.hh"
#include "BLI_linear_allocator.hh"
#include "BLI_offset_span.hh"
#include "BLI_task.hh"
#include "BLI_unique_sorted_indices.hh"
#include "BLI_vector.hh"
namespace blender {
template<typename T> class VArray;
}
#include "BLI_virtual_array_fwd.hh"
namespace blender::index_mask {

View File

@ -0,0 +1,17 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
namespace blender::index_mask {
class IndexMask;
} // namespace blender::index_mask
namespace blender {
using index_mask::IndexMask;
} // namespace blender

View File

@ -6,13 +6,7 @@
#include <algorithm>
namespace blender {
namespace index_mask {
class IndexMask;
}
using index_mask::IndexMask;
} // namespace blender
#include "BLI_index_mask_fwd.hh"
#include "BLI_index_range.hh"
#include "BLI_span.hh"

View File

@ -621,4 +621,18 @@ constexpr bool operator>=(StringRef a, StringRef b)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Formatting
* \{ */
/**
* Support using the fmt library with #StringRef and implicitly also #StringRefNull.
*/
inline std::string_view format_as(StringRef str)
{
return str;
}
/** \} */
} // namespace blender

View File

@ -0,0 +1,12 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
namespace blender {
template<typename T> class VArray;
template<typename T> class VMutableArray;
} // namespace blender

View File

@ -14,7 +14,6 @@ set(INC
set(INC_SYS
../../../extern/wcwidth
../../../extern/json/include
../../../extern/fmtlib/include
${EIGEN3_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIRS}
@ -252,6 +251,7 @@ set(SRC
BLI_implicit_sharing.hh
BLI_implicit_sharing_ptr.hh
BLI_index_mask.hh
BLI_index_mask_fwd.hh
BLI_index_range.hh
BLI_inplace_priority_queue.hh
BLI_iterator.h
@ -381,6 +381,7 @@ set(SRC
BLI_vector_set.hh
BLI_vector_set_slots.hh
BLI_virtual_array.hh
BLI_virtual_array_fwd.hh
BLI_virtual_vector_array.hh
BLI_voxel.h
BLI_winstuff.h
@ -392,6 +393,7 @@ set(SRC
set(LIB
PUBLIC bf::dna
PRIVATE bf::extern::fmtlib
bf_intern_eigen
PRIVATE bf::intern::guardedalloc
extern_wcwidth

View File

@ -84,7 +84,7 @@ static const unsigned char fillbuf[64] = {0x80, 0 /* , 0, 0, ... */};
* Initialize structure containing state of computation.
* (RFC 1321, 3.3: Step 3)
*/
static void md5_init_ctx(struct md5_ctx *ctx)
static void md5_init_ctx(md5_ctx *ctx)
{
ctx->A = 0x67452301;
ctx->B = 0xefcdab89;
@ -97,7 +97,7 @@ static void md5_init_ctx(struct md5_ctx *ctx)
* this function updates the 'ctx' context for the next 'len' bytes starting at 'buffer'.
* It is necessary that 'len' is a multiple of 64!!!
*/
static void md5_process_block(const void *buffer, size_t len, struct md5_ctx *ctx)
static void md5_process_block(const void *buffer, size_t len, md5_ctx *ctx)
{
/* These are the four functions used in the four steps of the MD5 algorithm and defined in the
* RFC 1321. The first function is a little bit optimized
@ -257,7 +257,7 @@ static void md5_process_block(const void *buffer, size_t len, struct md5_ctx *ct
* The result is always in little endian byte order,
* so that a byte-wise output yields to the wanted ASCII representation of the message digest.
*/
static void *md5_read_ctx(const struct md5_ctx *ctx, void *resbuf)
static void *md5_read_ctx(const md5_ctx *ctx, void *resbuf)
{
md5_uint32 *digest = static_cast<md5_uint32 *>(resbuf);
digest[0] = SWAP(ctx->A);
@ -274,7 +274,7 @@ Top level public functions. */
int BLI_hash_md5_stream(FILE *stream, void *resblock)
{
#define BLOCKSIZE 4096 /* IMPORTANT: must be a multiple of 64. */
struct md5_ctx ctx;
md5_ctx ctx;
md5_uint32 len[2];
char buffer[BLOCKSIZE + 72];
size_t pad, sum;
@ -346,7 +346,7 @@ int BLI_hash_md5_stream(FILE *stream, void *resblock)
void *BLI_hash_md5_buffer(const char *buffer, size_t len, void *resblock)
{
struct md5_ctx ctx;
md5_ctx ctx;
char restbuf[64 + 72];
size_t blocks = len & ~63;
size_t pad, rest;

View File

@ -1517,19 +1517,14 @@ bool isect_point_tri_v2_cw(const float pt[2],
int isect_point_tri_v2(const float pt[2], const float v1[2], const float v2[2], const float v3[2])
{
if (line_point_side_v2(v1, v2, pt) >= 0.0f) {
if (line_point_side_v2(v2, v3, pt) >= 0.0f) {
if (line_point_side_v2(v3, v1, pt) >= 0.0f) {
return 1;
}
}
float side12 = line_point_side_v2(v1, v2, pt);
float side23 = line_point_side_v2(v2, v3, pt);
float side31 = line_point_side_v2(v3, v1, pt);
if (side12 >= 0.0f && side23 >= 0.0f && side31 >= 0.0f) {
return 1;
}
else {
if (!(line_point_side_v2(v2, v3, pt) >= 0.0f)) {
if (!(line_point_side_v2(v3, v1, pt) >= 0.0f)) {
return -1;
}
}
if (side12 <= 0.0f && side23 <= 0.0f && side31 <= 0.0f) {
return -1;
}
return 0;
@ -1538,25 +1533,16 @@ int isect_point_tri_v2(const float pt[2], const float v1[2], const float v2[2],
int isect_point_quad_v2(
const float pt[2], const float v1[2], const float v2[2], const float v3[2], const float v4[2])
{
if (line_point_side_v2(v1, v2, pt) >= 0.0f) {
if (line_point_side_v2(v2, v3, pt) >= 0.0f) {
if (line_point_side_v2(v3, v4, pt) >= 0.0f) {
if (line_point_side_v2(v4, v1, pt) >= 0.0f) {
return 1;
}
}
}
float side12 = line_point_side_v2(v1, v2, pt);
float side23 = line_point_side_v2(v2, v3, pt);
float side34 = line_point_side_v2(v3, v4, pt);
float side41 = line_point_side_v2(v4, v1, pt);
if (side12 >= 0.0f && side23 >= 0.0f && side34 >= 0.0f && side41 >= 0.0f) {
return 1;
}
else {
if (!(line_point_side_v2(v2, v3, pt) >= 0.0f)) {
if (!(line_point_side_v2(v3, v4, pt) >= 0.0f)) {
if (!(line_point_side_v2(v4, v1, pt) >= 0.0f)) {
return -1;
}
}
}
if (side12 <= 0.0f && side23 <= 0.0f && side34 <= 0.0f && side41 <= 0.0f) {
return -1;
}
return 0;
}

View File

@ -2,12 +2,12 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_string_ref.hh"
#include "BLI_timeit.hh"
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <string_view>
#include <fmt/format.h>
@ -43,7 +43,7 @@ void print_duration(Nanoseconds duration)
{
fmt::memory_buffer buf;
format_duration(duration, buf);
std::cout << std::string_view(buf.data(), buf.size());
std::cout << StringRef(buf.data(), buf.size());
}
ScopedTimer::~ScopedTimer()
@ -54,8 +54,8 @@ ScopedTimer::~ScopedTimer()
fmt::memory_buffer buf;
fmt::format_to(fmt::appender(buf), FMT_STRING("Timer '{}' took "), name_);
format_duration(duration, buf);
buf.append(std::string_view("\n"));
std::cout << std::string_view(buf.data(), buf.size());
buf.append(StringRef("\n"));
std::cout << StringRef(buf.data(), buf.size());
}
ScopedTimerAveraged::~ScopedTimerAveraged()
@ -70,12 +70,12 @@ ScopedTimerAveraged::~ScopedTimerAveraged()
fmt::memory_buffer buf;
fmt::format_to(fmt::appender(buf), FMT_STRING("Timer '{}': (Average: "), name_);
format_duration(total_time_ / total_count_, buf);
buf.append(std::string_view(", Min: "));
buf.append(StringRef(", Min: "));
format_duration(min_time_, buf);
buf.append(std::string_view(", Last: "));
buf.append(StringRef(", Last: "));
format_duration(duration, buf);
buf.append(std::string_view(")\n"));
std::cout << std::string_view(buf.data(), buf.size());
buf.append(StringRef(")\n"));
std::cout << StringRef(buf.data(), buf.size());
}
} // namespace blender::timeit

View File

@ -1,10 +1,13 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: Apache-2.0 */
#include "testing/testing.h"
#include "BLI_math_geom.h"
#include "BLI_math_vector_types.hh"
using namespace blender;
TEST(math_geom, DistToLine2DSimple)
{
@ -19,3 +22,95 @@ TEST(math_geom, DistToLineSegment2DSimple)
float distance = dist_to_line_segment_v2(p, a, b);
EXPECT_NEAR(sqrtf(2.0f), distance, 1e-6);
}
TEST(math_geom, IsectPointTri2D)
{
float2 tri_cw[3] = {{-2, 1}, {4, 4}, {2, -3}};
float2 tri_ccw[3] = {{-2, 1}, {2, -3}, {4, 4}};
float2 inside1{0, 0};
float2 inside2{2, 2};
float2 inside3{2, -1};
float2 inside4{-1, 1};
EXPECT_EQ(-1, isect_point_tri_v2(inside1, tri_cw[0], tri_cw[1], tri_cw[2]));
EXPECT_EQ(+1, isect_point_tri_v2(inside1, tri_ccw[0], tri_ccw[1], tri_ccw[2]));
EXPECT_EQ(-1, isect_point_tri_v2(inside2, tri_cw[0], tri_cw[1], tri_cw[2]));
EXPECT_EQ(+1, isect_point_tri_v2(inside2, tri_ccw[0], tri_ccw[1], tri_ccw[2]));
EXPECT_EQ(-1, isect_point_tri_v2(inside3, tri_cw[0], tri_cw[1], tri_cw[2]));
EXPECT_EQ(+1, isect_point_tri_v2(inside3, tri_ccw[0], tri_ccw[1], tri_ccw[2]));
EXPECT_EQ(-1, isect_point_tri_v2(inside4, tri_cw[0], tri_cw[1], tri_cw[2]));
EXPECT_EQ(+1, isect_point_tri_v2(inside4, tri_ccw[0], tri_ccw[1], tri_ccw[2]));
float2 outside1{2, 4};
float2 outside2{-1, -1};
float2 outside3{0, 3};
float2 outside4{-4, 0};
EXPECT_EQ(0, isect_point_tri_v2(outside1, tri_cw[0], tri_cw[1], tri_cw[2]));
EXPECT_EQ(0, isect_point_tri_v2(outside1, tri_ccw[0], tri_ccw[1], tri_ccw[2]));
EXPECT_EQ(0, isect_point_tri_v2(outside2, tri_cw[0], tri_cw[1], tri_cw[2]));
EXPECT_EQ(0, isect_point_tri_v2(outside2, tri_ccw[0], tri_ccw[1], tri_ccw[2]));
EXPECT_EQ(0, isect_point_tri_v2(outside3, tri_cw[0], tri_cw[1], tri_cw[2]));
EXPECT_EQ(0, isect_point_tri_v2(outside3, tri_ccw[0], tri_ccw[1], tri_ccw[2]));
EXPECT_EQ(0, isect_point_tri_v2(outside4, tri_cw[0], tri_cw[1], tri_cw[2]));
EXPECT_EQ(0, isect_point_tri_v2(outside4, tri_ccw[0], tri_ccw[1], tri_ccw[2]));
float2 edge1{0, 2};
float2 edge2{1, -2};
EXPECT_EQ(-1, isect_point_tri_v2(edge1, tri_cw[0], tri_cw[1], tri_cw[2]));
EXPECT_EQ(+1, isect_point_tri_v2(edge1, tri_ccw[0], tri_ccw[1], tri_ccw[2]));
EXPECT_EQ(-1, isect_point_tri_v2(edge2, tri_cw[0], tri_cw[1], tri_cw[2]));
EXPECT_EQ(+1, isect_point_tri_v2(edge2, tri_ccw[0], tri_ccw[1], tri_ccw[2]));
float2 corner1{4, 4};
float2 corner2{2, -3};
EXPECT_EQ(-1, isect_point_tri_v2(corner1, tri_cw[0], tri_cw[1], tri_cw[2]));
EXPECT_EQ(+1, isect_point_tri_v2(corner1, tri_ccw[0], tri_ccw[1], tri_ccw[2]));
EXPECT_EQ(-1, isect_point_tri_v2(corner2, tri_cw[0], tri_cw[1], tri_cw[2]));
EXPECT_EQ(+1, isect_point_tri_v2(corner2, tri_ccw[0], tri_ccw[1], tri_ccw[2]));
}
TEST(math_geom, IsectPointQuad2D)
{
float2 quad_cw[4] = {{-2, 1}, {4, 4}, {5, 1}, {2, -3}};
float2 quad_ccw[4] = {{-2, 1}, {2, -3}, {5, 1}, {4, 4}};
float2 inside1{0, 0};
float2 inside2{2, 2};
float2 inside3{3, -1};
float2 inside4{-1, 1};
EXPECT_EQ(-1, isect_point_quad_v2(inside1, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3]));
EXPECT_EQ(+1, isect_point_quad_v2(inside1, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3]));
EXPECT_EQ(-1, isect_point_quad_v2(inside2, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3]));
EXPECT_EQ(+1, isect_point_quad_v2(inside2, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3]));
EXPECT_EQ(-1, isect_point_quad_v2(inside3, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3]));
EXPECT_EQ(+1, isect_point_quad_v2(inside3, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3]));
EXPECT_EQ(-1, isect_point_quad_v2(inside4, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3]));
EXPECT_EQ(+1, isect_point_quad_v2(inside4, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3]));
float2 outside1{2, 4};
float2 outside2{-1, -1};
float2 outside3{0, 3};
float2 outside4{-4, 0};
EXPECT_EQ(0, isect_point_quad_v2(outside1, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3]));
EXPECT_EQ(0, isect_point_quad_v2(outside1, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3]));
EXPECT_EQ(0, isect_point_quad_v2(outside2, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3]));
EXPECT_EQ(0, isect_point_quad_v2(outside2, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3]));
EXPECT_EQ(0, isect_point_quad_v2(outside3, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3]));
EXPECT_EQ(0, isect_point_quad_v2(outside3, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3]));
EXPECT_EQ(0, isect_point_quad_v2(outside4, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3]));
EXPECT_EQ(0, isect_point_quad_v2(outside4, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3]));
float2 edge1{0, 2};
float2 edge2{1, -2};
EXPECT_EQ(-1, isect_point_quad_v2(edge1, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3]));
EXPECT_EQ(+1, isect_point_quad_v2(edge1, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3]));
EXPECT_EQ(-1, isect_point_quad_v2(edge2, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3]));
EXPECT_EQ(+1, isect_point_quad_v2(edge2, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3]));
float2 corner1{4, 4};
float2 corner2{2, -3};
EXPECT_EQ(-1, isect_point_quad_v2(corner1, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3]));
EXPECT_EQ(+1, isect_point_quad_v2(corner1, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3]));
EXPECT_EQ(-1, isect_point_quad_v2(corner2, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3]));
EXPECT_EQ(+1, isect_point_quad_v2(corner2, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3]));
}

View File

@ -194,11 +194,26 @@ class MemoryBuffer {
return buffer_ + get_coords_offset(x, y);
}
/**
* Get buffer element at given coordinates, clamped to border.
*/
const float *get_elem_clamped(int x, int y) const
{
const int clamped_x = math::clamp(x, 0, this->get_width() - 1);
const int clamped_y = math::clamp(y, 0, this->get_height() - 1);
return buffer_ + get_coords_offset(clamped_x, clamped_y);
}
void read_elem(int x, int y, float *out) const
{
memcpy(out, get_elem(x, y), get_elem_bytes_len());
}
void read_elem_clamped(int x, int y, float *out) const
{
memcpy(out, get_elem_clamped(x, y), get_elem_bytes_len());
}
void read_elem_checked(int x, int y, float *out) const
{
if (!has_coords(x, y)) {

View File

@ -9,6 +9,7 @@
#include "BLI_ghash.h"
#include "BLI_hash.hh"
#include "BLI_math_base.hh"
#include "BLI_rect.h"
#include "BLI_span.hh"
#include "BLI_threads.h"
@ -591,6 +592,14 @@ class NodeOperation {
execute_pixel(result, x, y, chunk_data);
}
inline void read_clamped(float result[4], int x, int y, void *chunk_data)
{
execute_pixel(result,
math::clamp(x, 0, int(this->get_width()) - 1),
math::clamp(y, 0, int(this->get_height()) - 1),
chunk_data);
}
virtual void *initialize_tile_data(rcti * /*rect*/)
{
return 0;

View File

@ -34,12 +34,7 @@ void BilateralBlurOperation::execute_pixel(float output[4], int x, int y, void *
float temp_color[4];
float blur_color[4];
float blur_divider;
float space = space_;
float sigmacolor = data_->sigma_color;
int minx = floor(x - space);
int maxx = ceil(x + space);
int miny = floor(y - space);
int maxy = ceil(y + space);
float delta_color;
input_determinator_program_->read(determinator_reference_color, x, y, data);
@ -49,17 +44,17 @@ void BilateralBlurOperation::execute_pixel(float output[4], int x, int y, void *
* using gaussian bell for weights. Also sigma_color doesn't seem to be
* used correct at all.
*/
for (int yi = miny; yi < maxy; yi += QualityStepHelper::get_step()) {
for (int xi = minx; xi < maxx; xi += QualityStepHelper::get_step()) {
for (int yi = -radius_; yi <= radius_; yi += QualityStepHelper::get_step()) {
for (int xi = -radius_; xi <= radius_; xi += QualityStepHelper::get_step()) {
/* Read determinator. */
input_determinator_program_->read(determinator, xi, yi, data);
input_determinator_program_->read_clamped(determinator, x + xi, y + yi, data);
delta_color = (fabsf(determinator_reference_color[0] - determinator[0]) +
fabsf(determinator_reference_color[1] - determinator[1]) +
/* Do not take the alpha channel into account. */
fabsf(determinator_reference_color[2] - determinator[2]));
if (delta_color < sigmacolor) {
/* Add this to the blur. */
input_color_program_->read(temp_color, xi, yi, data);
input_color_program_->read_clamped(temp_color, x + xi, y + yi, data);
add_v4_v4(blur_color, temp_color);
blur_divider += 1.0f;
}
@ -87,7 +82,7 @@ bool BilateralBlurOperation::determine_depending_area_of_interest(
rcti *input, ReadBufferOperation *read_operation, rcti *output)
{
rcti new_input;
int add = ceil(space_) + 1;
int add = radius_ + 1;
new_input.xmax = input->xmax + (add);
new_input.xmin = input->xmin - (add);
@ -101,7 +96,7 @@ void BilateralBlurOperation::get_area_of_interest(const int /*input_idx*/,
const rcti &output_area,
rcti &r_input_area)
{
const int add = ceil(space_) + 1;
const int add = radius_ + 1;
r_input_area.xmax = output_area.xmax + (add);
r_input_area.xmin = output_area.xmin - (add);
@ -117,8 +112,9 @@ struct PixelCursor {
const float *determ_reference_color;
float temp_color[4];
float *out;
int min_x, max_x;
int min_y, max_y;
int radius;
int x;
int y;
};
static void blur_pixel(PixelCursor &p)
@ -130,16 +126,16 @@ static void blur_pixel(PixelCursor &p)
* using gaussian bell for weights. Also sigma_color doesn't seem to be
* used correct at all.
*/
for (int yi = p.min_y; yi < p.max_y; yi += p.step) {
for (int xi = p.min_x; xi < p.max_x; xi += p.step) {
p.input_determinator->read(p.temp_color, xi, yi);
for (int yi = -p.radius; yi <= p.radius; yi += p.step) {
for (int xi = -p.radius; xi <= p.radius; xi += p.step) {
p.input_determinator->read_elem_clamped(p.x + xi, p.y + yi, p.temp_color);
/* Do not take the alpha channel into account. */
const float delta_color = (fabsf(p.determ_reference_color[0] - p.temp_color[0]) +
fabsf(p.determ_reference_color[1] - p.temp_color[1]) +
fabsf(p.determ_reference_color[2] - p.temp_color[2]));
if (delta_color < p.sigma_color) {
/* Add this to the blur. */
p.input_color->read(p.temp_color, xi, yi);
p.input_color->read_elem_clamped(p.x + xi, p.y + yi, p.temp_color);
add_v4_v4(p.out, p.temp_color);
blur_divider += 1.0f;
}
@ -161,22 +157,17 @@ void BilateralBlurOperation::update_memory_buffer_partial(MemoryBuffer *output,
PixelCursor p = {};
p.step = QualityStepHelper::get_step();
p.sigma_color = data_->sigma_color;
p.radius = radius_;
p.input_color = inputs[0];
p.input_determinator = inputs[1];
const float space = space_;
for (int y = area.ymin; y < area.ymax; y++) {
p.out = output->get_elem(area.xmin, y);
/* This will be used as the reference color for the determinator. */
p.determ_reference_color = p.input_determinator->get_elem(area.xmin, y);
p.min_y = floor(y - space);
p.max_y = ceil(y + space);
p.y = y;
for (int x = area.xmin; x < area.xmax; x++) {
p.min_x = floor(x - space);
p.max_x = ceil(x + space);
p.x = x;
/* This will be used as the reference color for the determinator. */
p.determ_reference_color = p.input_determinator->get_elem(x, y);
blur_pixel(p);
p.determ_reference_color += p.input_determinator->elem_stride;
p.out += output->elem_stride;
}
}

View File

@ -4,6 +4,8 @@
#pragma once
#include "BLI_math_base.hh"
#include "COM_MultiThreadedOperation.h"
#include "COM_QualityStepHelper.h"
@ -14,7 +16,7 @@ class BilateralBlurOperation : public MultiThreadedOperation, public QualityStep
SocketReader *input_color_program_;
SocketReader *input_determinator_program_;
NodeBilateralBlurData *data_;
float space_;
int radius_;
public:
BilateralBlurOperation();
@ -41,7 +43,7 @@ class BilateralBlurOperation : public MultiThreadedOperation, public QualityStep
void set_data(NodeBilateralBlurData *data)
{
data_ = data;
space_ = data->sigma_space + data->iter;
radius_ = int(math::ceil(data->sigma_space + data->iter));
}
void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;

View File

@ -419,6 +419,8 @@ static bool bone_collection_assign_poll(bContext *C)
return false;
}
CTX_wm_operator_poll_msg_set(C, "Linked bone collections are not editable");
/* The target bone collection can be specified by name in an operator property, but that's not
* available here. So just allow in the poll function, and do the final check in the execute. */
return true;
@ -1004,6 +1006,8 @@ static bool move_to_collection_poll(bContext *C)
return false;
}
CTX_wm_operator_poll_msg_set(C, "Linked bone collections are not editable");
/* Ideally this would also check the target bone collection to move/assign to.
* However, that requires access to the operator properties, and those are not
* available in the poll function. */
@ -1134,7 +1138,6 @@ static void move_to_collection_menu_create(bContext *C, uiLayout *layout, void *
uiLayout *sub = uiLayoutRow(layout, false);
uiLayoutSetEnabled(sub, false);
/* TODO: figure out if we can add a 'disabled' message in the tooltip. */
menu_add_item_for_move_assign_unassign(sub, arm, bcoll, index, is_move_operation);
continue;
}

View File

@ -19,7 +19,6 @@ set(INC
../../render
../../windowmanager
../../../../intern/ghost
../../../../extern/fmtlib/include
../../bmesh
# RNA_prototypes.h
${CMAKE_BINARY_DIR}/source/blender/makesrna
@ -103,6 +102,7 @@ set(LIB
PRIVATE bf::depsgraph
PRIVATE bf::dna
bf_editor_datafiles
PRIVATE bf::extern::fmtlib
PRIVATE bf::intern::guardedalloc
PRIVATE bf::animrig
)

View File

@ -131,8 +131,8 @@ class BoneCollectionDropTarget : public TreeViewItemDropTarget {
const BoneCollection &drag_bcoll = drag_bone_collection->bcoll();
const BoneCollection &drop_bcoll = drop_bonecoll_.bcoll();
std::string_view drag_name = drag_bcoll.name;
std::string_view drop_name = drop_bcoll.name;
const StringRef drag_name = drag_bcoll.name;
const StringRef drop_name = drop_bcoll.name;
switch (drag_info.drop_location) {
case DropLocation::Into:

View File

@ -60,8 +60,8 @@ class LayerNodeDropTarget : public TreeViewItemDropTarget {
static_cast<const wmDragGreasePencilLayer *>(drag_info.drag_data.poin);
Layer &drag_layer = drag_grease_pencil->layer->wrap();
std::string_view drag_name = drag_layer.name();
std::string_view drop_name = drop_tree_node_.name();
const StringRef drag_name = drag_layer.name();
const StringRef drop_name = drop_tree_node_.name();
switch (drag_info.drop_location) {
case DropLocation::Into:

View File

@ -133,7 +133,7 @@ class ReorderCollectionDropTarget : public TreeViewItemDropTarget {
std::string drop_tooltip(const DragInfo &drag) const override
{
const std::string_view drop_name = std::string_view(drop_id_.name + 2);
const StringRef drop_name = drop_id_.name + 2;
switch (drag.drop_location) {
case DropLocation::Into:

View File

@ -19,7 +19,6 @@ set(INC
../../render
../../shader_fx
../../windowmanager
../../../../extern/fmtlib/include
# RNA_prototypes.h
${CMAKE_BINARY_DIR}/source/blender/makesrna
@ -69,6 +68,7 @@ set(LIB
PRIVATE bf::dna
bf_editor_mesh
bf_editor_grease_pencil
PRIVATE bf::extern::fmtlib
PRIVATE bf::intern::clog
PRIVATE bf::intern::guardedalloc
bf_render

View File

@ -318,19 +318,13 @@ static void bake_geometry_nodes_startjob(void *customdata, wmJobWorkerStatus *wo
const bake::BakePath path = request.path;
const std::string blob_file_name = frame_file_name + ".blob";
char blob_path[FILE_MAX];
BLI_path_join(blob_path, sizeof(blob_path), path.blobs_dir.c_str(), blob_file_name.c_str());
char meta_path[FILE_MAX];
BLI_path_join(meta_path,
sizeof(meta_path),
path.meta_dir.c_str(),
(frame_file_name + ".json").c_str());
BLI_file_ensure_parent_dir_exists(meta_path);
BLI_file_ensure_parent_dir_exists(blob_path);
fstream blob_file{blob_path, std::ios::out | std::ios::binary};
bake::DiskBlobWriter blob_writer{blob_file_name, blob_file, 0};
bake::DiskBlobWriter blob_writer{path.blobs_dir, frame_file_name};
fstream meta_file{meta_path, std::ios::out};
bake::serialize_bake(frame_cache.state, blob_writer, *request.blob_sharing, meta_file);
}

View File

@ -920,7 +920,8 @@ PaintStroke *paint_stroke_new(bContext *C,
ups->colorspace = nullptr;
if (br->mtex.tex && br->mtex.tex->type == TEX_IMAGE && br->mtex.tex->ima) {
ImBuf *tex_ibuf = BKE_image_pool_acquire_ibuf(br->mtex.tex->ima, &br->mtex.tex->iuser, NULL);
ImBuf *tex_ibuf = BKE_image_pool_acquire_ibuf(
br->mtex.tex->ima, &br->mtex.tex->iuser, nullptr);
if (tex_ibuf && tex_ibuf->float_buffer.data == nullptr) {
ups->do_linear_conversion = true;
ups->colorspace = tex_ibuf->byte_buffer.colorspace;

View File

@ -865,7 +865,7 @@ static void action_main_region_view2d_changed(const bContext * /*C*/, ARegion *r
void ED_spacetype_action()
{
SpaceType *st = MEM_cnew<SpaceType>("spacetype action");
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
ARegionType *art;
st->spaceid = SPACE_ACTION;
@ -942,7 +942,7 @@ void ED_spacetype_action()
art = ED_area_type_hud(st->spaceid);
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
BKE_spacetype_register(std::move(st));
}
/** \} */

View File

@ -136,8 +136,7 @@ void ED_spacetypes_init()
ED_gizmotypes_snap_3d();
/* Register types for operators and gizmos. */
const ListBase *spacetypes = BKE_spacetypes_list();
LISTBASE_FOREACH (const SpaceType *, type, spacetypes) {
for (const std::unique_ptr<SpaceType> &type : BKE_spacetypes_list()) {
/* Initialize gizmo types first, operator types need them. */
if (type->gizmos) {
type->gizmos();
@ -173,8 +172,7 @@ void ED_spacemacros_init()
/* Register dropboxes (can use macros). */
ED_dropboxes_ui();
const ListBase *spacetypes = BKE_spacetypes_list();
LISTBASE_FOREACH (const SpaceType *, type, spacetypes) {
for (const std::unique_ptr<SpaceType> &type : BKE_spacetypes_list()) {
if (type->dropboxes) {
type->dropboxes();
}
@ -207,8 +205,7 @@ void ED_spacetypes_keymap(wmKeyConfig *keyconf)
ED_keymap_transform(keyconf);
const ListBase *spacetypes = BKE_spacetypes_list();
LISTBASE_FOREACH (const SpaceType *, type, spacetypes) {
for (const std::unique_ptr<SpaceType> &type : BKE_spacetypes_list()) {
if (type->keymap) {
type->keymap(keyconf);
}
@ -292,61 +289,3 @@ void ED_region_draw_cb_remove_by_type(ARegionType *art, void *draw_fn, void (*fr
}
}
}
/* ********************* space template *********************** */
/* forward declare */
void ED_spacetype_xxx();
/* allocate and init some vars */
static SpaceLink *xxx_create(const ScrArea * /*area*/, const Scene * /*scene*/)
{
return nullptr;
}
/* Doesn't free the space-link itself. */
static void xxx_free(SpaceLink * /*sl*/) {}
/* spacetype; init callback for usage, should be re-doable. */
static void xxx_init(wmWindowManager * /*wm*/, ScrArea * /*area*/)
{
/* link area to SpaceXXX struct */
/* define how many regions, the order and types */
/* add types to regions */
}
static SpaceLink *xxx_duplicate(SpaceLink * /*sl*/)
{
return nullptr;
}
static void xxx_operatortypes()
{
/* register operator types for this space */
}
static void xxx_keymap(wmKeyConfig * /*keyconf*/)
{
/* add default items to keymap */
}
/* only called once, from screen/spacetypes.cc */
void ED_spacetype_xxx()
{
static SpaceType st;
st.spaceid = SPACE_VIEW3D;
st.create = xxx_create;
st.free = xxx_free;
st.init = xxx_init;
st.duplicate = xxx_duplicate;
st.operatortypes = xxx_operatortypes;
st.keymap = xxx_keymap;
BKE_spacetype_register(&st);
}
/* ****************************** end template *********************** */

View File

@ -971,7 +971,7 @@ static void buttons_space_blend_write(BlendWriter *writer, SpaceLink *sl)
void ED_spacetype_buttons()
{
SpaceType *st = static_cast<SpaceType *>(MEM_callocN(sizeof(SpaceType), "spacetype buttons"));
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
ARegionType *art;
st->spaceid = SPACE_PROPERTIES;
@ -1048,7 +1048,7 @@ void ED_spacetype_buttons()
art->message_subscribe = buttons_navigation_bar_region_message_subscribe;
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
BKE_spacetype_register(std::move(st));
}
/** \} */

View File

@ -1199,7 +1199,7 @@ static void clip_space_blend_write(BlendWriter *writer, SpaceLink *sl)
void ED_spacetype_clip()
{
SpaceType *st = MEM_cnew<SpaceType>("spacetype clip");
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
ARegionType *art;
st->spaceid = SPACE_CLIP;
@ -1281,8 +1281,6 @@ void ED_spacetype_clip()
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
/* channels */
art = MEM_cnew<ARegionType>("spacetype clip channels region");
art->regionid = RGN_TYPE_CHANNELS;
@ -1298,6 +1296,8 @@ void ED_spacetype_clip()
/* regions: hud */
art = ED_area_type_hud(st->spaceid);
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(std::move(st));
}
/** \} */

View File

@ -324,7 +324,7 @@ static void console_space_blend_write(BlendWriter *writer, SpaceLink *sl)
void ED_spacetype_console()
{
SpaceType *st = static_cast<SpaceType *>(MEM_callocN(sizeof(SpaceType), "spacetype console"));
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
ARegionType *art;
st->spaceid = SPACE_CONSOLE;
@ -364,5 +364,5 @@ void ED_spacetype_console()
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
BKE_spacetype_register(std::move(st));
}

View File

@ -14,7 +14,6 @@ set(INC
../../makesrna
../../render
../../windowmanager
../../../../extern/fmtlib/include
# RNA_prototypes.h
${CMAKE_BINARY_DIR}/source/blender/makesrna
@ -50,7 +49,7 @@ set(LIB
PRIVATE bf::blenlib
PRIVATE bf::dna
PRIVATE bf::intern::guardedalloc
extern_fmtlib
PRIVATE bf::extern::fmtlib
PRIVATE bf::intern::atomic
)

View File

@ -406,9 +406,8 @@ std::string AssetCatalogDropTarget::drop_tooltip_asset_catalog(const wmDrag &dra
BLI_assert(drag.type == WM_DRAG_ASSET_CATALOG);
const AssetCatalog *src_catalog = get_drag_catalog(drag, get_asset_library());
return fmt::format(TIP_("Move catalog {} into {}"),
std::string_view(src_catalog->path.name()),
std::string_view(catalog_item_.get_name()));
return fmt::format(
TIP_("Move catalog {} into {}"), src_catalog->path.name(), catalog_item_.get_name());
}
std::string AssetCatalogDropTarget::drop_tooltip_asset_list(const wmDrag &drag) const
@ -623,7 +622,7 @@ std::string AssetCatalogTreeViewAllItem::DropTarget::drop_tooltip(
drag_info.drag_data, *get_view<AssetCatalogTreeView>().asset_library_);
return fmt::format(TIP_("Move catalog {} to the top level of the tree"),
std::string_view(drag_catalog->path.name()));
drag_catalog->path.name());
}
bool AssetCatalogTreeViewAllItem::DropTarget::on_drop(bContext * /*C*/,

View File

@ -905,7 +905,7 @@ static void file_space_blend_write(BlendWriter *writer, SpaceLink *sl)
void ED_spacetype_file()
{
SpaceType *st = static_cast<SpaceType *>(MEM_callocN(sizeof(SpaceType), "spacetype file"));
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
ARegionType *art;
st->spaceid = SPACE_FILE;
@ -999,7 +999,7 @@ void ED_spacetype_file()
file_tool_props_region_panels_register(art);
file_external_operations_menu_register();
BKE_spacetype_register(st);
BKE_spacetype_register(std::move(st));
}
void ED_file_init()

View File

@ -874,7 +874,7 @@ static void graph_space_blend_write(BlendWriter *writer, SpaceLink *sl)
void ED_spacetype_ipo()
{
SpaceType *st = static_cast<SpaceType *>(MEM_callocN(sizeof(SpaceType), "spacetype ipo"));
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
ARegionType *art;
st->spaceid = SPACE_GRAPH;
@ -949,5 +949,5 @@ void ED_spacetype_ipo()
art = ED_area_type_hud(st->spaceid);
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
BKE_spacetype_register(std::move(st));
}

View File

@ -1102,7 +1102,7 @@ static void image_space_blend_write(BlendWriter *writer, SpaceLink *sl)
void ED_spacetype_image()
{
SpaceType *st = static_cast<SpaceType *>(MEM_callocN(sizeof(SpaceType), "spacetype image"));
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
ARegionType *art;
st->spaceid = SPACE_IMAGE;
@ -1192,5 +1192,5 @@ void ED_spacetype_image()
art = ED_area_type_hud(st->spaceid);
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
BKE_spacetype_register(std::move(st));
}

View File

@ -256,7 +256,7 @@ static void info_space_blend_write(BlendWriter *writer, SpaceLink *sl)
void ED_spacetype_info()
{
SpaceType *st = static_cast<SpaceType *>(MEM_callocN(sizeof(SpaceType), "spacetype info"));
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
ARegionType *art;
st->spaceid = SPACE_INFO;
@ -294,5 +294,5 @@ void ED_spacetype_info()
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
BKE_spacetype_register(std::move(st));
}

View File

@ -598,7 +598,7 @@ static void nla_space_blend_write(BlendWriter *writer, SpaceLink *sl)
void ED_spacetype_nla()
{
SpaceType *st = MEM_cnew<SpaceType>("spacetype nla");
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
ARegionType *art;
st->spaceid = SPACE_NLA;
@ -670,5 +670,5 @@ void ED_spacetype_nla()
art = ED_area_type_hud(st->spaceid);
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
BKE_spacetype_register(std::move(st));
}

View File

@ -18,7 +18,6 @@ set(INC
../../nodes
../../render
../../windowmanager
../../../../extern/fmtlib/include
# RNA_prototypes.h
${CMAKE_BINARY_DIR}/source/blender/makesrna
@ -58,7 +57,7 @@ set(LIB
PRIVATE bf::dna
bf_editor_screen
PRIVATE bf::intern::guardedalloc
extern_fmtlib
PRIVATE bf::extern::fmtlib
)
if(WITH_COMPOSITOR_CPU)

View File

@ -2524,7 +2524,7 @@ static std::string named_attribute_tooltip(bContext * /*C*/, void *argN, const c
for (const NameWithUsage &attribute : sorted_used_attribute) {
const StringRefNull name = attribute.name;
const geo_log::NamedAttributeUsage usage = attribute.usage;
ss << fmt::format(TIP_(" \u2022 \"{}\": "), std::string_view(name));
ss << fmt::format(TIP_(" \u2022 \"{}\": "), name);
Vector<std::string> usages;
if ((usage & geo_log::NamedAttributeUsage::Read) != geo_log::NamedAttributeUsage::None) {
usages.append(TIP_("read"));

View File

@ -1399,7 +1399,7 @@ void ED_spacetype_node()
{
using namespace blender::ed::space_node;
SpaceType *st = MEM_cnew<SpaceType>("spacetype node");
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
ARegionType *art;
st->spaceid = SPACE_NODE;
@ -1480,5 +1480,5 @@ void ED_spacetype_node()
WM_menutype_add(MEM_new<MenuType>(__func__, add_unassigned_assets_menu_type()));
WM_menutype_add(MEM_new<MenuType>(__func__, add_root_catalogs_menu_type()));
BKE_spacetype_register(st);
BKE_spacetype_register(std::move(st));
}

View File

@ -616,7 +616,7 @@ void ED_spacetype_outliner()
{
using namespace blender::ed::outliner;
SpaceType *st = MEM_cnew<SpaceType>("spacetype time");
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
ARegionType *art;
st->spaceid = SPACE_OUTLINER;
@ -661,5 +661,5 @@ void ED_spacetype_outliner()
art->listener = outliner_header_region_listener;
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
BKE_spacetype_register(std::move(st));
}

View File

@ -172,7 +172,7 @@ static void script_space_blend_write(BlendWriter *writer, SpaceLink *sl)
void ED_spacetype_script()
{
SpaceType *st = static_cast<SpaceType *>(MEM_callocN(sizeof(SpaceType), "spacetype script"));
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
ARegionType *art;
st->spaceid = SPACE_SCRIPT;
@ -210,5 +210,5 @@ void ED_spacetype_script()
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
BKE_spacetype_register(std::move(st));
}

View File

@ -631,28 +631,116 @@ static void draw_waveform_graticule(ARegion *region, SeqQuadsBatch &quads, const
UI_view2d_text_cache_draw(region);
}
static void draw_vectorscope_graticule(SeqQuadsBatch &quads, const rctf &area)
static void draw_vectorscope_graticule(ARegion *region, SeqQuadsBatch &quads, const rctf &area)
{
using namespace blender;
GPU_blend(GPU_BLEND_ALPHA);
const float skin_rad = DEG2RADF(123.0f); /* angle in radians of the skin tone line */
const float w = BLI_rctf_size_x(&area);
const float h = BLI_rctf_size_y(&area);
const float centerx = BLI_rctf_cent_x(&area);
const float centery = BLI_rctf_cent_y(&area);
const float rad_base = ((w < h) ? w : h) * 0.5f;
/* vectorscope image is scaled over YUV range, +/- (0.436, 0.615) */
const float rad_x = rad_base * (0.5f / 0.436f);
const float rad_y = rad_base * (0.5f / 0.615f);
const float2 center{BLI_rctf_cent_x(&area), BLI_rctf_cent_y(&area)};
/* Vectorscope image is scaled over UV range (+/-0.615). */
const float radius = ((w < h) ? w : h) * 0.5f * (0.5f / 0.615f);
/* center cross */
uchar col_grid[4] = {128, 128, 128, 96};
quads.add_line(centerx - rad_base * 0.1f, centery, centerx + rad_base * 0.1f, centery, col_grid);
quads.add_line(centerx, centery - rad_base * 0.1f, centerx, centery + rad_base * 0.1f, col_grid);
/* Precalculate circle points/colors. */
constexpr int circle_delta = 6;
constexpr int num_circle_points = 360 / circle_delta;
float2 circle_pos[num_circle_points];
float3 circle_col[num_circle_points];
for (int i = 0; i < num_circle_points; i++) {
float a = DEG2RADF(i * circle_delta);
float u = cosf(a);
float v = sinf(a);
circle_pos[i] = float2(u, v);
/* fully saturated vs "safe" (0.75) colored areas */
float3 col;
yuv_to_rgb(0.5f, u, v, &col.x, &col.y, &col.z, BLI_YUV_ITU_BT709);
circle_col[i] = col;
}
/* Draw colored background and outer ring, additively blended
* since vectorscope image is already drawn. */
GPU_blend(GPU_BLEND_ADDITIVE);
constexpr float alpha_f = 0.8f;
constexpr uchar alpha_b = uchar(alpha_f * 255.0f);
const uchar4 col_center(50, 50, 50, alpha_b);
uchar4 col1(0, 0, 0, alpha_b);
uchar4 col2(0, 0, 0, alpha_b);
uchar4 col3(0, 0, 0, alpha_b);
/* Background: since the quads batch utility draws quads, draw two
* segments of the circle (two triangles) in one iteration. */
constexpr float mul_background = 0.2f;
for (int i = 0; i < num_circle_points; i += 2) {
int idx1 = i;
int idx2 = (i + 1) % num_circle_points;
int idx3 = (i + 2) % num_circle_points;
float2 pt1 = center + circle_pos[idx1] * radius;
float2 pt2 = center + circle_pos[idx2] * radius;
float2 pt3 = center + circle_pos[idx3] * radius;
float3 rgb1 = circle_col[idx1] * mul_background;
float3 rgb2 = circle_col[idx2] * mul_background;
float3 rgb3 = circle_col[idx3] * mul_background;
rgb_float_to_uchar(col1, rgb1);
rgb_float_to_uchar(col2, rgb2);
rgb_float_to_uchar(col3, rgb3);
quads.add_quad(pt1.x,
pt1.y,
pt2.x,
pt2.y,
center.x,
center.y,
pt3.x,
pt3.y,
col1,
col2,
col_center,
col3);
}
/* Outer ring. */
const float outer_radius = radius * 1.02f;
for (int i = 0; i < num_circle_points; i++) {
int idx1 = i;
int idx2 = (i + 1) % num_circle_points;
float2 pt1a = center + circle_pos[idx1] * radius;
float2 pt2a = center + circle_pos[idx2] * radius;
float2 pt1b = center + circle_pos[idx1] * outer_radius;
float2 pt2b = center + circle_pos[idx2] * outer_radius;
float3 rgb1 = circle_col[idx1];
float3 rgb2 = circle_col[idx2];
rgb_float_to_uchar(col1, rgb1);
rgb_float_to_uchar(col2, rgb2);
quads.add_quad(
pt1a.x, pt1a.y, pt1b.x, pt1b.y, pt2a.x, pt2a.y, pt2b.x, pt2b.y, col1, col1, col2, col2);
}
quads.draw();
/* Draw grid and other labels using regular alpha blending. */
GPU_blend(GPU_BLEND_ALPHA);
const uchar4 col_grid(128, 128, 128, 128);
/* Cross. */
quads.add_line(center.x - radius, center.y, center.x + radius, center.y, col_grid);
quads.add_line(center.x, center.y - radius, center.x, center.y + radius, col_grid);
/* Inner circles. */
for (int j = 1; j < 5; j++) {
float r = radius * j * 0.2f;
for (int i = 0; i < num_circle_points; i++) {
int idx1 = i;
int idx2 = (i + 1) % num_circle_points;
float2 pt1 = center + circle_pos[idx1] * r;
float2 pt2 = center + circle_pos[idx2] * r;
quads.add_line(pt1.x, pt1.y, pt2.x, pt2.y, col_grid);
}
}
/* "Safe" (0.75 saturation) primary color locations and labels. */
const float3 primaries[6] = {
{1, 0, 0},
{1, 1, 0},
@ -661,35 +749,43 @@ static void draw_vectorscope_graticule(SeqQuadsBatch &quads, const rctf &area)
{0, 0, 1},
{1, 0, 1},
};
float2 center{centerx, centery};
float2 rad_scale{rad_x * 2, rad_y * 2};
const char *names = "RYGCBM";
/* Calculate size of single text letter. */
char buf[2] = {'M', 0};
float text_scale_x, text_scale_y;
UI_view2d_scale_get_inverse(&region->v2d, &text_scale_x, &text_scale_y);
float text_width, text_height;
BLF_width_and_height(BLF_default(), buf, 1, &text_width, &text_height);
text_width *= text_scale_x;
text_height *= text_scale_y;
const uchar4 col_target(128, 128, 128, 192);
const float delta = radius * 0.01f;
for (int i = 0; i < 6; i++) {
float3 prim0 = primaries[i];
float3 prim1 = primaries[(i + 1) % 6];
float3 safe0 = prim0 * 0.75f;
float3 safe1 = prim1 * 0.75f;
float2 uv0 = center + rgb_to_uv(prim0) * rad_scale;
float2 uv1 = center + rgb_to_uv(prim1) * rad_scale;
float2 uv2 = center + rgb_to_uv(safe0) * rad_scale;
float2 uv3 = center + rgb_to_uv(safe1) * rad_scale;
uchar col0[4] = {uchar(prim0.x * 255), uchar(prim0.y * 255), uchar(prim0.z * 255), 64};
uchar col1[4] = {uchar(prim1.x * 255), uchar(prim1.y * 255), uchar(prim1.z * 255), 64};
uchar col2[4] = {uchar(safe0.x * 255), uchar(safe0.y * 255), uchar(safe0.z * 255), 64};
uchar col3[4] = {uchar(safe1.x * 255), uchar(safe1.y * 255), uchar(safe1.z * 255), 64};
quads.add_quad(uv0.x, uv0.y, uv1.x, uv1.y, uv2.x, uv2.y, uv3.x, uv3.y, col0, col1, col2, col3);
col0[3] = col1[3] = col2[3] = col3[3] = 192;
quads.add_line(uv0.x, uv0.y, uv1.x, uv1.y, col0, col1);
quads.add_line(uv2.x, uv2.y, uv3.x, uv3.y, col2, col3);
float3 safe = primaries[i] * 0.75f;
float2 pos = center + rgb_to_uv(safe) * (radius * 2);
quads.add_wire_quad(pos.x - delta, pos.y - delta, pos.x + delta, pos.y + delta, col_target);
buf[0] = names[i];
UI_view2d_text_cache_add(&region->v2d,
pos.x + delta * 1.2f + text_width / 4,
pos.y - text_height / 2,
buf,
1,
col_target);
}
/* skin tone line */
uchar col_tone[4] = {255, 102, 0, 128};
const float tone_line_len = 0.895f; /* makes it end at outer edge of saturation ring. */
quads.add_line(centerx,
centery,
centerx + cosf(skin_rad) * rad_x * tone_line_len,
centery + sinf(skin_rad) * rad_y * tone_line_len,
/* Skin tone line. */
const uchar4 col_tone(255, 102, 0, 128);
quads.add_line(center.x,
center.y,
center.x + cosf(skin_rad) * radius,
center.y + sinf(skin_rad) * radius,
col_tone);
quads.draw();
UI_view2d_text_cache_draw(region);
}
static void sequencer_draw_scopes(Scene *scene, ARegion *region, SpaceSeq *sseq)
@ -794,7 +890,7 @@ static void sequencer_draw_scopes(Scene *scene, ARegion *region, SpaceSeq *sseq)
}
if (sseq->mainb == SEQ_DRAW_IMG_VECTORSCOPE) {
use_blend = true;
draw_vectorscope_graticule(quads, preview);
draw_vectorscope_graticule(region, quads, preview);
}
quads.draw();

View File

@ -64,8 +64,8 @@ static blender::float2 rgb_to_uv_normalized(const float rgb[3])
float u = -0.09991f * r - 0.33609f * g + 0.436f * b;
float v = 0.615f * r - 0.55861f * g - 0.05639f * b;
/* Normalize: (U, V) range is +/- (0.436, 0.615) */
u = clamp_f(u * (0.5f / 0.436f) + 0.5f, 0.0f, 1.0f);
/* Normalize: possible range is +/- 0.615. */
u = clamp_f(u * (0.5f / 0.615f) + 0.5f, 0.0f, 1.0f);
v = clamp_f(v * (0.5f / 0.615f) + 0.5f, 0.0f, 1.0f);
return float2(u, v);
}

View File

@ -974,7 +974,7 @@ static void sequencer_space_blend_write(BlendWriter *writer, SpaceLink *sl)
void ED_spacetype_sequencer()
{
SpaceType *st = MEM_cnew<SpaceType>("spacetype sequencer");
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
ARegionType *art;
st->spaceid = SPACE_SEQ;
@ -1088,7 +1088,7 @@ void ED_spacetype_sequencer()
art = ED_area_type_hud(st->spaceid);
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
BKE_spacetype_register(std::move(st));
/* Set the sequencer callback when not in background mode. */
if (G.background == 0) {

View File

@ -13,7 +13,6 @@ set(INC
../../makesrna
../../nodes
../../windowmanager
../../../../extern/fmtlib/include
# RNA_prototypes.h
${CMAKE_BINARY_DIR}/source/blender/makesrna
@ -54,6 +53,7 @@ set(LIB
PRIVATE bf::blenlib
PRIVATE bf::depsgraph
PRIVATE bf::dna
PRIVATE bf::extern::fmtlib
PRIVATE bf::intern::guardedalloc
)

View File

@ -718,7 +718,7 @@ static void spreadsheet_blend_write(BlendWriter *writer, SpaceLink *sl)
void register_spacetype()
{
SpaceType *st = MEM_cnew<SpaceType>("spacetype spreadsheet");
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
ARegionType *art;
st->spaceid = SPACE_SPREADSHEET;
@ -803,7 +803,7 @@ void register_spacetype()
spreadsheet_data_set_region_panels_register(*art);
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
BKE_spacetype_register(std::move(st));
}
} // namespace blender::ed::spreadsheet

View File

@ -132,7 +132,7 @@ static void statusbar_space_blend_write(BlendWriter *writer, SpaceLink *sl)
void ED_spacetype_statusbar()
{
SpaceType *st = static_cast<SpaceType *>(MEM_callocN(sizeof(*st), "spacetype statusbar"));
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
ARegionType *art;
st->spaceid = SPACE_STATUSBAR;
@ -159,5 +159,5 @@ void ED_spacetype_statusbar()
art->message_subscribe = statusbar_header_region_message_subscribe;
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
BKE_spacetype_register(std::move(st));
}

View File

@ -405,7 +405,7 @@ static void text_space_blend_write(BlendWriter *writer, SpaceLink *sl)
void ED_spacetype_text()
{
SpaceType *st = static_cast<SpaceType *>(MEM_callocN(sizeof(SpaceType), "spacetype text"));
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
ARegionType *art;
st->spaceid = SPACE_TEXT;
@ -465,7 +465,7 @@ void ED_spacetype_text()
art->draw = text_header_region_draw;
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
BKE_spacetype_register(std::move(st));
/* register formatters */
ED_text_format_register_py();

View File

@ -4107,6 +4107,9 @@ static int text_jump_to_file_at_point_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
/* Useful to copy-paste from the terminal. */
printf("%s:%d:%d\n", filepath, line_index + 1, column_index);
bool success;
if (U.text_editor[0] != '\0') {
success = text_jump_to_file_at_point_external(

View File

@ -277,7 +277,7 @@ static void topbar_space_blend_write(BlendWriter *writer, SpaceLink *sl)
void ED_spacetype_topbar()
{
SpaceType *st = static_cast<SpaceType *>(MEM_callocN(sizeof(SpaceType), "spacetype topbar"));
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
ARegionType *art;
st->spaceid = SPACE_TOPBAR;
@ -322,5 +322,5 @@ void ED_spacetype_topbar()
recent_files_menu_register();
undo_history_menu_register();
BKE_spacetype_register(st);
BKE_spacetype_register(std::move(st));
}

View File

@ -9,7 +9,6 @@ set(INC
../../blentranslation
../../makesrna
../../windowmanager
../../../../extern/fmtlib/include
)
@ -27,6 +26,7 @@ set(SRC
set(LIB
PRIVATE bf::blenlib
PRIVATE bf::dna
PRIVATE bf::extern::fmtlib
PRIVATE bf::intern::guardedalloc
)

View File

@ -186,7 +186,7 @@ static void userpref_space_blend_write(BlendWriter *writer, SpaceLink *sl)
void ED_spacetype_userpref()
{
SpaceType *st = static_cast<SpaceType *>(MEM_callocN(sizeof(SpaceType), "spacetype userpref"));
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
ARegionType *art;
st->spaceid = SPACE_USERPREF;
@ -246,5 +246,5 @@ void ED_spacetype_userpref()
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
BKE_spacetype_register(std::move(st));
}

View File

@ -243,7 +243,7 @@ static void PREFERENCES_OT_asset_library_remove(wmOperatorType *ot)
* \{ */
enum class bUserExtensionRepoAddType {
Online = 0,
Remote = 0,
Local = 1,
};
@ -274,7 +274,7 @@ static int preferences_extension_repo_add_exec(bContext *C, wmOperator *op)
new_repo->flag |= USER_EXTENSION_REPO_FLAG_USE_CUSTOM_DIRECTORY;
}
if (repo_type == bUserExtensionRepoAddType::Online) {
if (repo_type == bUserExtensionRepoAddType::Remote) {
RNA_string_get(op->ptr, "remote_path", new_repo->remote_path);
new_repo->flag |= USER_EXTENSION_REPO_FLAG_USE_REMOTE_PATH;
}
@ -298,8 +298,8 @@ static int preferences_extension_repo_add_invoke(bContext *C, wmOperator *op, co
PropertyRNA *prop_name = RNA_struct_find_property(op->ptr, "name");
if (!RNA_property_is_set(op->ptr, prop_name)) {
const char *name_default = nullptr;
if (repo_type == bUserExtensionRepoAddType::Online) {
name_default = "Online Repository";
if (repo_type == bUserExtensionRepoAddType::Remote) {
name_default = "Remote Repository";
}
else {
name_default = "User Repository";
@ -321,7 +321,7 @@ static bool preferences_extension_repo_add_poll_property(const bContext * /*C*/,
/* Only show remote_path for remote repositories. */
if (STREQ(prop_id, "remote_path")) {
if (repo_type != bUserExtensionRepoAddType::Online) {
if (repo_type != bUserExtensionRepoAddType::Remote) {
return false;
}
}
@ -349,10 +349,10 @@ static void PREFERENCES_OT_extension_repo_add(wmOperatorType *ot)
ot->flag = OPTYPE_INTERNAL | OPTYPE_REGISTER;
static const EnumPropertyItem repo_type_items[] = {
{int(bUserExtensionRepoAddType::Online),
"ONLINE",
{int(bUserExtensionRepoAddType::Remote),
"REMOTE",
ICON_WORLD,
"Add Online Repository",
"Add Remote Repository",
"Add a repository referencing an remote repository "
"with support for listing and updating extensions"},
{int(bUserExtensionRepoAddType::Local),

View File

@ -2107,7 +2107,7 @@ static void view3d_space_blend_write(BlendWriter *writer, SpaceLink *sl)
void ED_spacetype_view3d()
{
using namespace blender::ed;
SpaceType *st = MEM_cnew<SpaceType>("spacetype view3d");
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
ARegionType *art;
st->spaceid = SPACE_VIEW3D;
@ -2237,5 +2237,5 @@ void ED_spacetype_view3d()
WM_menutype_add(MEM_new<MenuType>(
__func__, blender::ed::geometry::node_group_operator_assets_menu_unassigned()));
BKE_spacetype_register(st);
BKE_spacetype_register(std::move(st));
}

View File

@ -207,8 +207,8 @@ static void WIDGETGROUP_navigate_setup(const bContext *C, wmGizmoGroup *gzgroup)
}
wmOperatorType *ot = WM_operatortype_find(info->opname, true);
PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ot, NULL);
if (info->op_prop_fn != NULL) {
PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ot, nullptr);
if (info->op_prop_fn != nullptr) {
info->op_prop_fn(ptr);
}
}

View File

@ -17,7 +17,6 @@ set(INC
set(INC_SYS
../../../../extern/fast_float
../../../../extern/fmtlib/include
)
set(SRC
@ -57,7 +56,7 @@ set(LIB
PRIVATE bf::dna
PRIVATE bf::intern::guardedalloc
bf_io_common
extern_fmtlib
PRIVATE bf::extern::fmtlib
)
blender_add_lib(bf_io_ply "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

View File

@ -44,26 +44,23 @@ void FileBuffer::close_file()
void FileBuffer::write_header_element(StringRef name, int count)
{
write_fstring("element {} {}\n", std::string_view(name), count);
write_fstring("element {} {}\n", name, count);
}
void FileBuffer::write_header_scalar_property(StringRef dataType, StringRef name)
{
write_fstring("property {} {}\n", std::string_view(dataType), std::string_view(name));
write_fstring("property {} {}\n", dataType, name);
}
void FileBuffer::write_header_list_property(StringRef countType,
StringRef dataType,
StringRef name)
{
write_fstring("property list {} {} {}\n",
std::string_view(countType),
std::string_view(dataType),
std::string_view(name));
write_fstring("property list {} {} {}\n", countType, dataType, name);
}
void FileBuffer::write_string(StringRef s)
{
write_fstring("{}\n", std::string_view(s));
write_fstring("{}\n", s);
}
void FileBuffer::write_newline()

View File

@ -18,7 +18,6 @@ set(INC
set(INC_SYS
../../../../extern/fast_float
../../../../extern/fmtlib/include
)
set(SRC
@ -46,7 +45,7 @@ set(LIB
PRIVATE bf::dna
PRIVATE bf::intern::guardedalloc
bf_io_common
extern_fmtlib
PRIVATE bf::extern::fmtlib
)
blender_add_lib(bf_io_stl "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

View File

@ -77,6 +77,7 @@ set(INC_SYS
${BOOST_INCLUDE_DIR}
${TBB_INCLUDE_DIR}
${PYTHON_INCLUDE_DIR}
)
set(SRC
@ -200,6 +201,7 @@ set(LIB
PRIVATE bf::intern::clog
PRIVATE bf::intern::guardedalloc
bf_io_common
PRIVATE bf::extern::fmtlib
)
list(APPEND LIB

View File

@ -223,8 +223,9 @@ void create_blend_shapes(pxr::UsdStageRefPtr stage,
pxr::UsdSkelBindingAPI skel_api = pxr::UsdSkelBindingAPI::Apply(mesh_prim);
if (!skel_api) {
printf("WARNING: couldn't apply UsdSkelBindingAPI to prim %s\n",
mesh_prim.GetPath().GetAsString().c_str());
CLOG_WARN(&LOG,
"Couldn't apply UsdSkelBindingAPI to mesh prim %s",
mesh_prim.GetPath().GetAsString().c_str());
return;
}

View File

@ -39,6 +39,7 @@ namespace usdtokens {
/* Parameter names. */
static const pxr::TfToken a("a", pxr::TfToken::Immortal);
static const pxr::TfToken b("b", pxr::TfToken::Immortal);
static const pxr::TfToken bias("bias", pxr::TfToken::Immortal);
static const pxr::TfToken clearcoat("clearcoat", pxr::TfToken::Immortal);
static const pxr::TfToken clearcoatRoughness("clearcoatRoughness", pxr::TfToken::Immortal);
static const pxr::TfToken diffuseColor("diffuseColor", pxr::TfToken::Immortal);
@ -57,6 +58,7 @@ static const pxr::TfToken result("result", pxr::TfToken::Immortal);
static const pxr::TfToken rgb("rgb", pxr::TfToken::Immortal);
static const pxr::TfToken rgba("rgba", pxr::TfToken::Immortal);
static const pxr::TfToken roughness("roughness", pxr::TfToken::Immortal);
static const pxr::TfToken scale("scale", pxr::TfToken::Immortal);
static const pxr::TfToken sourceColorSpace("sourceColorSpace", pxr::TfToken::Immortal);
static const pxr::TfToken specularColor("specularColor", pxr::TfToken::Immortal);
static const pxr::TfToken st("st", pxr::TfToken::Immortal);
@ -77,7 +79,6 @@ static const pxr::TfToken wrapT("wrapT", pxr::TfToken::Immortal);
/* Transform 2d names. */
static const pxr::TfToken rotation("rotation", pxr::TfToken::Immortal);
static const pxr::TfToken scale("scale", pxr::TfToken::Immortal);
static const pxr::TfToken translation("translation", pxr::TfToken::Immortal);
/* USD shader names. */
@ -679,6 +680,107 @@ bool USDMaterialReader::set_node_input(const pxr::UsdShadeInput &usd_input,
return false;
}
struct IntermediateNode {
bNode *node;
const char *sock_input_name;
const char *sock_output_name;
};
static IntermediateNode add_normal_map(const pxr::UsdShadeShader &usd_shader,
bNodeTree *ntree,
int column,
NodePlacementContext *r_ctx)
{
float locx = 0.0f;
float locy = 0.0f;
compute_node_loc(column, &locx, &locy, r_ctx);
/* Currently, the Normal Map node has Tangent Space as the default,
* which is what we need, so we don't need to explicitly set it. */
IntermediateNode normal_map{};
normal_map.node = add_node(nullptr, ntree, SH_NODE_NORMAL_MAP, locx, locy);
normal_map.sock_input_name = "Color";
normal_map.sock_output_name = "Normal";
return normal_map;
}
static IntermediateNode add_scale_bias(const pxr::UsdShadeShader &usd_shader,
bNodeTree *ntree,
int column,
bool feeds_normal_map,
NodePlacementContext *r_ctx)
{
/* Handle the scale-bias inputs if present. */
pxr::UsdShadeInput scale_input = usd_shader.GetInput(usdtokens::scale);
pxr::UsdShadeInput bias_input = usd_shader.GetInput(usdtokens::bias);
pxr::GfVec4f scale(1.0f, 1.0f, 1.0f, 1.0f);
pxr::GfVec4f bias(0.0f, 0.0f, 0.0f, 0.0f);
pxr::VtValue val;
if (scale_input.Get(&val) && val.CanCast<pxr::GfVec4f>()) {
scale = val.Cast<pxr::GfVec4f>(val).UncheckedGet<pxr::GfVec4f>();
}
if (bias_input.Get(&val) && val.CanCast<pxr::GfVec4f>()) {
bias = val.Cast<pxr::GfVec4f>(val).UncheckedGet<pxr::GfVec4f>();
}
/* Nothing to be done if the values match their defaults. */
if (scale == pxr::GfVec4f{1.0f, 1.0f, 1.0f, 1.0f} &&
bias == pxr::GfVec4f{0.0f, 0.0f, 0.0f, 0.0f})
{
return {};
}
/* Nothing to be done if this feeds a Normal Map and the values match those defaults. */
if (feeds_normal_map && (scale[0] == 2.0f && scale[1] == 2.0f && scale[2] == 2.0f) &&
(bias[0] == -1.0f && bias[1] == -1.0f && bias[2] == -1.0f))
{
return {};
}
float locx = 0.0f;
float locy = 0.0f;
/* If we know a Normal Map node will be involved, leave room for the another
* adjustment node which will be added later. */
compute_node_loc(feeds_normal_map ? column + 1 : column, &locx, &locy, r_ctx);
IntermediateNode scale_bias{};
scale_bias.node = add_node(nullptr, ntree, SH_NODE_VECTOR_MATH, locx, locy);
scale_bias.node->custom1 = NODE_VECTOR_MATH_MULTIPLY_ADD;
scale_bias.sock_input_name = "Vector";
scale_bias.sock_output_name = "Vector";
bNodeSocket *sock_scale = nodeFindSocket(scale_bias.node, SOCK_IN, "Vector_001");
bNodeSocket *sock_bias = nodeFindSocket(scale_bias.node, SOCK_IN, "Vector_002");
copy_v3_v3(((bNodeSocketValueVector *)sock_scale->default_value)->value, scale.data());
copy_v3_v3(((bNodeSocketValueVector *)sock_bias->default_value)->value, bias.data());
return scale_bias;
}
static IntermediateNode add_scale_bias_adjust(bNodeTree *ntree,
int column,
NodePlacementContext *r_ctx)
{
float locx = 0.0f;
float locy = 0.0f;
compute_node_loc(column, &locx, &locy, r_ctx);
IntermediateNode adjust{};
adjust.node = add_node(nullptr, ntree, SH_NODE_VECTOR_MATH, locx, locy);
adjust.node->custom1 = NODE_VECTOR_MATH_MULTIPLY_ADD;
adjust.sock_input_name = "Vector";
adjust.sock_output_name = "Vector";
bNodeSocket *sock_scale = nodeFindSocket(adjust.node, SOCK_IN, "Vector_001");
bNodeSocket *sock_bias = nodeFindSocket(adjust.node, SOCK_IN, "Vector_002");
copy_v3_fl3(((bNodeSocketValueVector *)sock_scale->default_value)->value, 0.5f, 0.5f, 0.5f);
copy_v3_fl3(((bNodeSocketValueVector *)sock_bias->default_value)->value, 0.5f, 0.5f, 0.5f);
return adjust;
}
bool USDMaterialReader::follow_connection(const pxr::UsdShadeInput &usd_input,
bNode *dest_node,
const char *dest_socket_name,
@ -717,40 +819,66 @@ bool USDMaterialReader::follow_connection(const pxr::UsdShadeInput &usd_input,
/* For now, only convert UsdUVTexture, UsdTransform2d and UsdPrimvarReader_float2 inputs. */
if (shader_id == usdtokens::UsdUVTexture) {
if (STREQ(dest_socket_name, "Normal")) {
/* The normal texture input requires creating a normal map node. */
float locx = 0.0f;
float locy = 0.0f;
compute_node_loc(column + 1, &locx, &locy, r_ctx);
int shift = 1;
bNode *normal_map = add_node(nullptr, ntree, SH_NODE_NORMAL_MAP, locx, locy);
/* Currently, the Normal Map node has Tangent Space as the default,
* which is what we need, so we don't need to explicitly set it. */
/* Connect the Normal Map to the Normal input. */
link_nodes(ntree, normal_map, "Normal", dest_node, "Normal");
/* Now, create the Texture Image node input to the Normal Map "Color" input. */
convert_usd_uv_texture(source_shader,
source_name,
normal_map,
"Color",
ntree,
column + 2,
r_ctx,
is_color_corrected);
/* Create a Normal Map node if the source is flowing into a 'Normal' socket. */
IntermediateNode normal_map{};
const bool is_normal_map = STREQ(dest_socket_name, "Normal");
if (is_normal_map) {
normal_map = add_normal_map(source_shader, ntree, column + shift, r_ctx);
shift++;
}
else {
convert_usd_uv_texture(source_shader,
source_name,
dest_node,
dest_socket_name,
ntree,
column + 1,
r_ctx,
is_color_corrected);
/* Create a Scale-Bias adjustment node if necessary. */
IntermediateNode scale_bias = add_scale_bias(
source_shader, ntree, column + shift, is_normal_map, r_ctx);
/* Wire up any intermediate nodes that are present. Keep track of the
* final "target" destination for the Image link. */
bNode *target_node = dest_node;
const char *target_sock_name = dest_socket_name;
if (normal_map.node) {
/* If a scale-bias node is required, we need to re-adjust the output
* so it can be passed into the NormalMap node properly. */
if (scale_bias.node) {
IntermediateNode re_adjust = add_scale_bias_adjust(ntree, column + shift, r_ctx);
link_nodes(ntree,
scale_bias.node,
scale_bias.sock_output_name,
re_adjust.node,
re_adjust.sock_input_name);
link_nodes(ntree,
re_adjust.node,
re_adjust.sock_output_name,
normal_map.node,
normal_map.sock_input_name);
target_node = scale_bias.node;
target_sock_name = scale_bias.sock_input_name;
shift += 2;
}
else {
target_node = normal_map.node;
target_sock_name = normal_map.sock_input_name;
}
link_nodes(ntree, normal_map.node, normal_map.sock_output_name, dest_node, dest_socket_name);
}
else if (scale_bias.node) {
link_nodes(ntree, scale_bias.node, scale_bias.sock_output_name, dest_node, dest_socket_name);
target_node = scale_bias.node;
target_sock_name = scale_bias.sock_input_name;
shift++;
}
convert_usd_uv_texture(source_shader,
source_name,
target_node,
target_sock_name,
ntree,
column + shift,
r_ctx,
is_color_corrected);
}
else if (shader_id == usdtokens::UsdPrimvarReader_float2) {
convert_usd_primvar_reader_float2(

View File

@ -16,8 +16,6 @@
#include "DNA_collection_types.h"
#include <iostream>
#include <pxr/usd/usdGeom/pointInstancer.h>
namespace blender::io::usd {

View File

@ -55,7 +55,7 @@
#include "DNA_collection_types.h"
#include "DNA_material_types.h"
#include <iomanip>
#include <fmt/format.h>
static CLG_LogRef LOG = {"io.usd"};
@ -690,7 +690,7 @@ void USDStageReader::create_proto_collections(Main *bmain, Collection *parent_co
/* Determine the max number of digits we will need for the possibly zero-padded
* string representing the prototype index. */
int max_index_digits = integer_digits_i(instancer_reader->proto_paths().size());
const int max_index_digits = integer_digits_i(instancer_reader->proto_paths().size());
int proto_index = 0;
@ -698,9 +698,7 @@ void USDStageReader::create_proto_collections(Main *bmain, Collection *parent_co
BLI_assert(max_index_digits > 0);
/* Format the collection name to follow the proto_<index> pattern. */
std::ostringstream ss;
ss << std::setw(max_index_digits) << std::setfill('0') << proto_index;
std::string coll_name = "proto_" + ss.str();
std::string coll_name = fmt::format("proto_{0:0{1}}", proto_index, max_index_digits);
/* Create the collection and populate it with the prototype objects. */
Collection *proto_coll = create_collection(bmain, instancer_protos_coll, coll_name.c_str());

View File

@ -15,6 +15,9 @@
#include "DNA_mesh_types.h"
#include "CLG_log.h"
static CLG_LogRef LOG = {"io.usd"};
/* TfToken objects are not cheap to construct, so we do it once. */
namespace usdtokens {
/* Materials */
@ -140,7 +143,9 @@ bool USDAbstractWriter::mark_as_instance(const HierarchyContext &context, const
BLI_assert(context.is_instance());
if (context.export_path == context.original_export_path) {
printf("USD ref error: export path is reference path: %s\n", context.export_path.c_str());
CLOG_ERROR(&LOG,
"Reference error: export path matches reference path: %s",
context.export_path.c_str());
BLI_assert_msg(0, "USD reference error");
return false;
}
@ -150,9 +155,10 @@ bool USDAbstractWriter::mark_as_instance(const HierarchyContext &context, const
/* See this URL for a description for why referencing may fail"
* https://graphics.pixar.com/usd/docs/api/class_usd_references.html#Usd_Failing_References
*/
printf("USD Export warning: unable to add reference from %s to %s, not instancing object\n",
context.export_path.c_str(),
context.original_export_path.c_str());
CLOG_WARN(&LOG,
"Unable to add reference from %s to %s, not instancing object for export",
context.export_path.c_str(),
context.original_export_path.c_str());
return false;
}

View File

@ -234,6 +234,45 @@ static void create_usd_preview_surface_material(const USDExporterContext &usd_ex
export_texture(usd_export_context, input_node);
}
/* If a Vector Math node was detected ahead of the texture node, and it has
* the correct type, NODE_VECTOR_MATH_MULTIPLY_ADD, assume it's meant to be
* used for scale-bias. */
bNodeLink *scale_link = traverse_channel(sock, SH_NODE_VECTOR_MATH);
if (scale_link) {
bNode *vector_math_node = scale_link->fromnode;
if (vector_math_node->custom1 == NODE_VECTOR_MATH_MULTIPLY_ADD) {
/* Attempt one more traversal in case the current node is not not the
* correct NODE_VECTOR_MATH_MULTIPLY_ADD (see code in usd_reader_material). */
bNodeSocket *sock_current = nodeFindSocket(vector_math_node, SOCK_IN, "Vector");
bNodeLink *temp_link = traverse_channel(sock_current, SH_NODE_VECTOR_MATH);
if (temp_link && temp_link->fromnode->custom1 == NODE_VECTOR_MATH_MULTIPLY_ADD) {
vector_math_node = temp_link->fromnode;
}
bNodeSocket *sock_scale = nodeFindSocket(vector_math_node, SOCK_IN, "Vector_001");
bNodeSocket *sock_bias = nodeFindSocket(vector_math_node, SOCK_IN, "Vector_002");
const float *scale_value =
static_cast<bNodeSocketValueVector *>(sock_scale->default_value)->value;
const float *bias_value =
static_cast<bNodeSocketValueVector *>(sock_bias->default_value)->value;
const pxr::GfVec4f scale(scale_value[0], scale_value[1], scale_value[2], 1.0f);
const pxr::GfVec4f bias(bias_value[0], bias_value[1], bias_value[2], 0.0f);
pxr::UsdShadeInput scale_attr = usd_shader.GetInput(usdtokens::scale);
if (!scale_attr) {
scale_attr = usd_shader.CreateInput(usdtokens::scale, pxr::SdfValueTypeNames->Float4);
}
scale_attr.Set(scale);
pxr::UsdShadeInput bias_attr = usd_shader.GetInput(usdtokens::bias);
if (!bias_attr) {
bias_attr = usd_shader.CreateInput(usdtokens::bias, pxr::SdfValueTypeNames->Float4);
}
bias_attr.Set(bias);
}
}
/* Look for a connected uvmap node. */
if (bNodeSocket *socket = nodeFindSocket(input_node, SOCK_IN, "Vector")) {
if (pxr::UsdShadeInput st_input = usd_shader.CreateInput(usdtokens::st,
@ -244,8 +283,6 @@ static void create_usd_preview_surface_material(const USDExporterContext &usd_ex
}
}
set_normal_texture_range(usd_shader, input_spec);
/* Set opacityThreshold if an alpha cutout is used. */
if ((input_spec.input_name == usdtokens::opacity) &&
(material->blend_method == MA_BM_CLIP) && (material->alpha_threshold > 0.0))

View File

@ -18,7 +18,6 @@ set(INC
set(INC_SYS
../../../../extern/fast_float
../../../../extern/fmtlib/include
)
set(SRC
@ -60,7 +59,7 @@ set(LIB
PRIVATE bf::dna
PRIVATE bf::intern::guardedalloc
bf_io_common
extern_fmtlib
PRIVATE bf::extern::fmtlib
)
if(WITH_TBB)

View File

@ -111,11 +111,11 @@ class FormatHandler : NonCopyable, NonMovable {
}
void write_obj_usemtl(StringRef s)
{
write_impl("usemtl {}\n", std::string_view(s));
write_impl("usemtl {}\n", s);
}
void write_obj_mtllib(StringRef s)
{
write_impl("mtllib {}\n", std::string_view(s));
write_impl("mtllib {}\n", s);
}
void write_obj_smooth(int s)
{
@ -123,11 +123,11 @@ class FormatHandler : NonCopyable, NonMovable {
}
void write_obj_group(StringRef s)
{
write_impl("g {}\n", std::string_view(s));
write_impl("g {}\n", s);
}
void write_obj_object(StringRef s)
{
write_impl("o {}\n", std::string_view(s));
write_impl("o {}\n", s);
}
void write_obj_edge(int a, int b)
{
@ -172,7 +172,7 @@ class FormatHandler : NonCopyable, NonMovable {
void write_mtl_newmtl(StringRef s)
{
write_impl("newmtl {}\n", std::string_view(s));
write_impl("newmtl {}\n", s);
}
void write_mtl_float(const char *type, float v)
{
@ -189,12 +189,12 @@ class FormatHandler : NonCopyable, NonMovable {
/* NOTE: options, if present, will have its own leading space. */
void write_mtl_map(const char *type, StringRef options, StringRef value)
{
write_impl("{}{} {}\n", type, std::string_view(options), std::string_view(value));
write_impl("{}{} {}\n", type, options, value);
}
void write_string(StringRef s)
{
write_impl("{}\n", std::string_view(s));
write_impl("{}\n", s);
}
private:

View File

@ -625,7 +625,7 @@ typedef struct bUserExtensionRepo {
/**
* The "local" directory where extensions are stored.
* When unset, use `{BLENDER_USER_SCRIPTS}/extensions/{bUserExtensionRepo::module}`.
* When unset, use `{BLENDER_RESOURCE_PATH_USER}/extensions/{bUserExtensionRepo::module}`.
*/
char custom_dirpath[1024]; /* FILE_MAX */
char remote_path[1024]; /* FILE_MAX */

View File

@ -1969,7 +1969,7 @@ static void rna_def_gpencil_layer_mask(BlenderRNA *brna)
prop = RNA_def_property(srna, "invert", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "flag", GP_MASK_INVERT);
RNA_def_property_ui_icon(prop, ICON_SELECT_INTERSECT, -1);
RNA_def_property_ui_icon(prop, ICON_SELECT_INTERSECT, 1);
RNA_def_property_ui_text(prop, "Invert", "Invert mask");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
}

View File

@ -978,7 +978,7 @@ static std::optional<std::string> rna_prepend_real_ID_path(Main * /*bmain*/,
if (!path.is_empty()) {
if (real_id) {
if (prefix[0]) {
return fmt::format("{}{}{}", prefix, path[0] == '[' ? "" : ".", std::string_view(path));
return fmt::format("{}{}{}", prefix, path[0] == '[' ? "" : ".", path);
}
return path;
}
@ -1105,11 +1105,11 @@ static std::string rna_path_from_ptr_to_property_index_ex(const PointerRNA *ptr,
if (!path_prefix.is_empty()) {
if (is_rna) {
return fmt::format("{}.{}{}", std::string_view(path_prefix), propname, index_str);
return fmt::format("{}.{}{}", path_prefix, propname, index_str);
}
char propname_esc[MAX_IDPROP_NAME * 2];
BLI_str_escape(propname_esc, propname, sizeof(propname_esc));
return fmt::format("{}[\"{}\"]{}", std::string_view(path_prefix), propname_esc, index_str);
return fmt::format("{}[\"{}\"]{}", path_prefix, propname_esc, index_str);
}
if (is_rna) {

View File

@ -17,7 +17,6 @@ set(INC
../render
../windowmanager
../../../intern/eigen
../../../extern/fmtlib/include
# RNA_prototypes.h
${CMAKE_BINARY_DIR}/source/blender/makesrna
@ -123,7 +122,7 @@ set(LIB
PRIVATE bf::depsgraph
PUBLIC bf::dna
PRIVATE bf::intern::guardedalloc
extern_fmtlib
PRIVATE bf::extern::fmtlib
)
if(WITH_ALEMBIC)

View File

@ -66,7 +66,6 @@ set(INC
../modifiers
../render
../windowmanager
../../../extern/fmtlib/include
# RNA_prototypes.h
${CMAKE_BINARY_DIR}/source/blender/makesrna
@ -134,7 +133,7 @@ set(LIB
bf_nodes_geometry
bf_nodes_shader
bf_nodes_texture
extern_fmtlib
PRIVATE bf::extern::fmtlib
)
if(WITH_BULLET)

View File

@ -18,7 +18,6 @@ set(INC
../../modifiers
../../render
../../windowmanager
../../../../extern/fmtlib/include
# RNA_prototypes.h
${CMAKE_BINARY_DIR}/source/blender/makesrna
)
@ -215,7 +214,7 @@ set(LIB
bf_geometry
PRIVATE bf::intern::guardedalloc
bf_nodes
extern_fmtlib
PRIVATE bf::extern::fmtlib
)
if(WITH_BULLET)

View File

@ -274,14 +274,14 @@ static void node_geo_exec(GeoNodeExecParams params)
if (!mesh_attributes_eval.contains(uv_map_name)) {
pass_through_input();
const std::string message = fmt::format(TIP_("Evaluated surface missing UV map: \"{}\""),
std::string_view(uv_map_name));
uv_map_name);
params.error_message_add(NodeWarningType::Error, message);
return;
}
if (!mesh_attributes_orig.contains(uv_map_name)) {
pass_through_input();
const std::string message = fmt::format(TIP_("Original surface missing UV map: \"{}\""),
std::string_view(uv_map_name));
uv_map_name);
params.error_message_add(NodeWarningType::Error, message);
return;
}

View File

@ -345,7 +345,7 @@ class LazyFunctionForGeometryNode : public LazyFunction {
GField output_field{std::make_shared<AnonymousAttributeFieldInput>(
std::move(attribute_id),
*bsocket.typeinfo->base_cpp_type,
fmt::format(TIP_("{} node"), std::string_view(node_.label_or_name())))};
fmt::format(TIP_("{} node"), node_.label_or_name()))};
void *r_value = params.get_output_data_ptr(lf_index);
new (r_value) SocketValueVariant(std::move(output_field));
params.output_set(lf_index);

View File

@ -222,7 +222,9 @@ static bool python_script_exec(
}
}
}
PyErr_Print();
if (!reports) {
PyErr_Print();
}
PyErr_Clear();
}
else {

View File

@ -20,7 +20,6 @@ set(INC
../render
../sequencer
../../../intern/memutil
../../../extern/fmtlib/include
../bmesh
# RNA_prototypes.h
@ -101,6 +100,7 @@ set(LIB
PRIVATE bf::depsgraph
PRIVATE bf::dna
bf_editor_screen
PRIVATE bf::extern::fmtlib
PRIVATE bf::intern::clog
PRIVATE bf::intern::guardedalloc
PRIVATE bf::animrig

View File

@ -52,13 +52,15 @@ def html_extract_markdown_from_url(url: str) -> Optional[str]:
with urllib.request.urlopen(req) as fh:
data = fh.read().decode('utf-8')
# Quiet `mypy` checker warning.
assert isinstance(data, str)
return data
# -----------------------------------------------------------------------------
# markdown Text Parsing
def markdown_to_paths(markdown: str) -> Tuple[List[str], List[str]]:
def markdown_to_paths(markdown: str) -> List[str]:
file_paths = []
markdown = markdown.replace("<p>", "")
markdown = markdown.replace("</p>", "")
@ -113,7 +115,7 @@ def report_incomplete(file_paths: List[str]) -> int:
basedirs = {os.path.dirname(p) for p in file_paths}
for base in sorted(basedirs):
base_abs = os.path.join(SOURCE_DIR, base)
if(os.path.exists(base_abs)):
if os.path.exists(base_abs):
for p in os.listdir(base_abs):
if not p.startswith("."):
p_abs = os.path.join(base_abs, p)

View File

@ -14,10 +14,11 @@ PATHS: Tuple[Tuple[str, Tuple[Any, ...], Dict[str, str]], ...] = (
("build_files/utils/", (), {'MYPYPATH': "modules"}),
("doc/manpage/blender.1.py", (), {}),
("release/datafiles/", (), {}),
("tests/utils/", (), {}),
("tools/check_blender_release/", (), {}),
("tools/check_docs/", (), {}),
("tools/check_source/", (), {'MYPYPATH': "modules"}),
("tools/check_wiki/", (), {}),
("tools/config/", (), {}),
("tools/triage/", (), {}),
("tools/utils/", (), {}),
("tools/utils_api/", (), {}),
("tools/utils_build/", (), {}),
@ -36,9 +37,6 @@ PATHS_EXCLUDE = set(
"build_files/cmake/clang_array_check.py",
"build_files/cmake/cmake_netbeans_project.py",
"build_files/cmake/cmake_qtcreator_project.py",
"build_files/cmake/cmake_static_check_smatch.py",
"build_files/cmake/cmake_static_check_sparse.py",
"build_files/cmake/cmake_static_check_splint.py",
"release/datafiles/blender_icons_geom.py", # Uses `bpy` too much.
"tests/utils/bl_run_operators.py", # Uses `bpy` too much.
"tests/utils/bl_run_operators_event_simulate.py", # Uses `bpy` too much.
@ -54,6 +52,9 @@ PATHS_EXCLUDE = set(
"tools/check_source/check_descriptions.py",
"tools/check_source/check_header_duplicate.py",
"tools/check_source/check_unused_defines.py",
"tools/triage/gitea_utils.py", # TODO (low priority).
"tools/triage/issues_needing_info.py", # TODO (low priority).
"tools/triage/weekly_report.py", # TODO (low priority).
"tools/utils/blend2json.py",
"tools/utils/blender_keyconfig_export_permutations.py",
"tools/utils/blender_merge_format_changes.py",
@ -67,7 +68,6 @@ PATHS_EXCLUDE = set(
"tools/utils/make_cursor_gui.py",
"tools/utils/make_gl_stipple_from_xpm.py",
"tools/utils/make_shape_2d_from_blend.py",
"tools/utils/weekly_report.py",
"tools/utils_api/bpy_introspect_ui.py", # Uses `bpy`.
"tools/utils_doc/rna_manual_reference_updater.py",
"tools/utils_ide/qtcreator/externaltools/qtc_assembler_preview.py",
@ -87,3 +87,12 @@ PATHS = tuple(
(os.path.join(SOURCE_DIR, p_items[0].replace("/", os.sep)), *p_items[1:])
for p_items in PATHS
)
# Validate:
for p_items in PATHS:
if not os.path.exists(os.path.join(SOURCE_DIR, p_items[0])):
print("PATH:", p_items[0], "doesn't exist")
for p in PATHS_EXCLUDE:
if not os.path.exists(os.path.join(SOURCE_DIR, p)):
print("PATHS_EXCLUDE:", p, "doesn't exist")