Eevee-Next: World Reflective Light #108149

Merged
Jeroen Bakker merged 33 commits from Jeroen-Bakker/blender:eevee-next-world-shader into main 2023-06-29 15:25:04 +02:00
130 changed files with 1655 additions and 1204 deletions
Showing only changes of commit 9463720cff - Show all commits

View File

@ -928,6 +928,27 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
unset(MOLD_BIN)
endif()
if(WITH_LINKER_LLD AND _IS_LINKER_DEFAULT)
find_program(LLD_BIN "ld.lld")
mark_as_advanced(LLD_BIN)
if(NOT LLD_BIN)
message(STATUS "The \"ld.lld\" binary could not be found, using system linker.")
set(WITH_LINKER_LLD OFF)
else()
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0)
string(APPEND CMAKE_EXE_LINKER_FLAGS " --ld-path=\"${LLD_BIN}\"")
string(APPEND CMAKE_SHARED_LINKER_FLAGS " --ld-path=\"${LLD_BIN}\"")
string(APPEND CMAKE_MODULE_LINKER_FLAGS " --ld-path=\"${LLD_BIN}\"")
else()
string(APPEND CMAKE_EXE_LINKER_FLAGS " -fuse-ld=\"${LLD_BIN}\"")
string(APPEND CMAKE_SHARED_LINKER_FLAGS " -fuse-ld=\"${LLD_BIN}\"")
string(APPEND CMAKE_MODULE_LINKER_FLAGS " -fuse-ld=\"${LLD_BIN}\"")
endif()
set(_IS_LINKER_DEFAULT OFF)
endif()
unset(LLD_BIN)
endif()
# Intel C++ Compiler
elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
# think these next two are broken

View File

@ -398,7 +398,7 @@ def lightmap_uvpack(
# Since the boxes are sized in powers of 2, we can neatly group them into bigger squares
# this is done hierarchically, so that we may avoid running the pack function
# on many thousands of boxes, (under 1k is best) because it would get slow.
# Using an off and even dict us useful because they are packed differently
# Using an odd and even dict is useful because they are packed differently
# where w/h are the same, their packed in groups of 4
# where they are different they are packed in pairs
#

View File

@ -3592,9 +3592,6 @@ class VIEW3D_MT_face_sets_init(Menu):
props = layout.operator("sculpt.face_sets_init", text="By Sharp Edges")
props.mode = 'SHARP_EDGES'
props = layout.operator("sculpt.face_sets_init", text="By Face Maps")
props.mode = 'FACE_MAPS'
class VIEW3D_MT_random_mask(Menu):
bl_label = "Random Mask"

View File

@ -258,12 +258,9 @@ class CurvesGeometry : public ::CurvesGeometry {
MutableSpan<float2> surface_uv_coords_for_write();
/**
* Calculate the largest and smallest position values, only including control points
* (rather than evaluated points). The existing values of `min` and `max` are taken into account.
*
* \return Whether there are any points. If the curve is empty, the inputs will be unaffected.
* The largest and smallest position values of evaluated points.
*/
bool bounds_min_max(float3 &min, float3 &max) const;
std::optional<Bounds<float3>> bounds_min_max() const;
private:
/* --------------------------------------------------------------------

View File

@ -8,13 +8,12 @@
* \ingroup bke
*/
#include <atomic>
#include <iostream>
#include <mutex>
#include "BLI_bounds_types.hh"
#include "BLI_function_ref.hh"
#include "BLI_map.hh"
#include "BLI_vector_set.hh"
#include "BKE_attribute.hh"
@ -194,7 +193,7 @@ struct GeometrySet {
*/
Vector<const GeometryComponent *> get_components_for_read() const;
bool compute_boundbox_without_instances(float3 *r_min, float3 *r_max) const;
std::optional<Bounds<float3>> compute_boundbox_without_instances() const;
friend std::ostream &operator<<(std::ostream &stream, const GeometrySet &geometry_set);

View File

@ -265,7 +265,6 @@ void BKE_mesh_nomain_to_meshkey(struct Mesh *mesh_src, struct Mesh *mesh_dst, st
/* vertex level transformations & checks (no derived mesh) */
/* basic vertex data functions */
bool BKE_mesh_minmax(const struct Mesh *me, float r_min[3], float r_max[3]);
void BKE_mesh_transform(struct Mesh *me, const float mat[4][4], bool do_keys);
void BKE_mesh_translate(struct Mesh *me, const float offset[3], bool do_keys);
@ -512,7 +511,6 @@ bool BKE_mesh_center_median(const struct Mesh *me, float r_cent[3]);
* use when we want to ignore vertex locations that don't have connected faces.
*/
bool BKE_mesh_center_median_from_polys(const struct Mesh *me, float r_cent[3]);
bool BKE_mesh_center_bounds(const struct Mesh *me, float r_cent[3]);
bool BKE_mesh_center_of_surface(const struct Mesh *me, float r_cent[3]);
/**
* \note Mesh must be manifold with consistent face-winding,

View File

@ -576,17 +576,15 @@ int ntreeGetPanelIndex(const bNodeTree *ntree, const bNodePanel *panel);
/**
* Add a new panel to the node tree.
* \param name: Name of the new panel.
* \param flag: Flags of the new panel.
*/
bNodePanel *ntreeAddPanel(bNodeTree *ntree, const char *name, int flag);
bNodePanel *ntreeAddPanel(bNodeTree *ntree, const char *name);
/**
* Insert a new panel in the node tree.
* \param name: Name of the new panel.
* \param flag: Flags of the new panel.
* \param index: Index at which to insert the panel.
*/
bNodePanel *ntreeInsertPanel(bNodeTree *ntree, const char *name, int flag, int index);
bNodePanel *ntreeInsertPanel(bNodeTree *ntree, const char *name, int index);
/** Remove a panel from the node tree. */
void ntreeRemovePanel(bNodeTree *ntree, bNodePanel *panel);

View File

@ -291,6 +291,9 @@ class bNodeRuntime : NonCopyable, NonMovable {
bool has_available_linked_outputs = false;
Vector<bNode *> direct_children_in_frame;
bNodeTree *owner_tree = nullptr;
/** Can be used to toposort a subset of nodes. */
int toposort_left_to_right_index = -1;
int toposort_right_to_left_index = -1;
};
namespace node_tree_runtime {
@ -515,6 +518,18 @@ inline blender::Span<bNode *> bNodeTree::root_frames() const
return this->runtime->root_frames;
}
inline blender::Span<bNodeLink *> bNodeTree::all_links()
{
BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*this));
return this->runtime->links;
}
inline blender::Span<const bNodeLink *> bNodeTree::all_links() const
{
BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*this));
return this->runtime->links;
}
inline blender::Span<const bNodePanel *> bNodeTree::panels() const
{
return blender::Span(panels_array, panels_num);
@ -525,6 +540,8 @@ inline blender::MutableSpan<bNodePanel *> bNodeTree::panels_for_write()
return blender::MutableSpan(panels_array, panels_num);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name #bNode Inline Methods
* \{ */

View File

@ -28,16 +28,31 @@ struct TreeZone {
TreeZone *parent_zone = nullptr;
/** Direct children zones. Does not contain recursively nested zones. */
Vector<TreeZone *> child_zones;
/** Direct children nodes. Does not contain recursively nested nodes. */
/** Direct children nodes excluding nodes that belong to child zones. */
Vector<const bNode *> child_nodes;
/** Links that enter the zone through the zone border. */
Vector<const bNodeLink *> border_links;
bool contains_node_recursively(const bNode &node) const;
bool contains_zone_recursively(const TreeZone &other_zone) const;
};
class TreeZones {
public:
Vector<std::unique_ptr<TreeZone>> zones;
Map<int, int> parent_zone_by_node_id;
Vector<TreeZone *> root_zones;
Vector<const bNode *> nodes_outside_zones;
/**
* Zone index by node. Nodes that are in no zone, are not included. Nodes that are at the border
* of a zone (e.g. Simulation Input) are mapped to the zone they create.
*/
Map<int, int> zone_by_node_id;
/**
* Get the deepest zone that a socket is in. Note that the inputs of a Simulation Input node are
* in a different zone than its output sockets.
*/
const TreeZone *get_zone_by_socket(const bNodeSocket &socket) const;
};
const TreeZones *get_tree_zones(const bNodeTree &tree);

View File

@ -151,6 +151,9 @@ struct StatesAroundFrame {
class ModifierSimulationCache {
private:
mutable std::mutex states_at_frames_mutex_;
/**
* All simulation states, sorted by frame.
*/
Vector<std::unique_ptr<ModifierSimulationStateAtFrame>> states_at_frames_;
/**
* Used for baking to deduplicate arrays when writing and writing from storage. Sharing info

View File

@ -39,7 +39,7 @@ typedef struct bMovieHandle {
void (*end_movie)(void *context_v);
/* Optional function. */
void (*get_movie_path)(char *filepath,
void (*get_movie_path)(char filepath[/*FILE_MAX*/ 1024],
const struct RenderData *rd,
bool preview,
const char *suffix);
@ -53,7 +53,7 @@ bMovieHandle *BKE_movie_handle_get(char imtype);
/**
* \note Similar to #BKE_image_path_from_imformat()
*/
void BKE_movie_filepath_get(char *filepath,
void BKE_movie_filepath_get(char filepath[/*FILE_MAX*/ 1024],
const struct RenderData *rd,
bool preview,
const char *suffix);

View File

@ -65,7 +65,7 @@ int BKE_ffmpeg_append(void *context_v,
int recty,
const char *suffix,
struct ReportList *reports);
void BKE_ffmpeg_filepath_get(char *filepath,
void BKE_ffmpeg_filepath_get(char filepath[/*FILE_MAX*/ 1024],
const struct RenderData *rd,
bool preview,
const char *suffix);

View File

@ -235,6 +235,7 @@ set(SRC
intern/node.cc
intern/node_runtime.cc
intern/node_tree_anonymous_attributes.cc
intern/node_tree_dot_export.cc
intern/node_tree_field_inferencing.cc
intern/node_tree_update.cc
intern/node_tree_zones.cc

View File

@ -192,6 +192,7 @@ void *BKE_curves_add(Main *bmain, const char *name)
BoundBox *BKE_curves_boundbox_get(Object *ob)
{
using namespace blender;
BLI_assert(ob->type == OB_CURVES);
const Curves *curves_id = static_cast<const Curves *>(ob->data);
@ -201,17 +202,13 @@ BoundBox *BKE_curves_boundbox_get(Object *ob)
if (ob->runtime.bb == nullptr) {
ob->runtime.bb = MEM_cnew<BoundBox>(__func__);
const blender::bke::CurvesGeometry &curves = curves_id->geometry.wrap();
float3 min(FLT_MAX);
float3 max(-FLT_MAX);
if (!curves.bounds_min_max(min, max)) {
min = float3(-1);
max = float3(1);
const bke::CurvesGeometry &curves = curves_id->geometry.wrap();
if (const std::optional<Bounds<float3>> bounds = curves.bounds_min_max()) {
BKE_boundbox_init_from_minmax(ob->runtime.bb, bounds->min, bounds->max);
}
else {
BKE_boundbox_init_from_minmax(ob->runtime.bb, float3(-1), float3(1));
}
BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
}
return ob->runtime.bb;

View File

@ -1096,19 +1096,14 @@ void CurvesGeometry::transform(const float4x4 &matrix)
this->tag_positions_changed();
}
bool CurvesGeometry::bounds_min_max(float3 &min, float3 &max) const
std::optional<Bounds<float3>> CurvesGeometry::bounds_min_max() const
{
if (this->points_num() == 0) {
return false;
return std::nullopt;
}
this->runtime->bounds_cache.ensure(
[&](Bounds<float3> &r_bounds) { r_bounds = *bounds::min_max(this->evaluated_positions()); });
const Bounds<float3> &bounds = this->runtime->bounds_cache.data();
min = math::min(bounds.min, min);
max = math::max(bounds.max, max);
return true;
return this->runtime->bounds_cache.data();
}
CurvesGeometry curves_copy_point_selection(

View File

@ -33,9 +33,7 @@ TEST(curves_geometry, Empty)
{
CurvesGeometry empty(0, 0);
empty.cyclic();
float3 min;
float3 max;
EXPECT_FALSE(empty.bounds_min_max(min, max));
EXPECT_FALSE(empty.bounds_min_max());
}
TEST(curves_geometry, Move)
@ -52,9 +50,7 @@ TEST(curves_geometry, Move)
EXPECT_EQ(curves.curve_offsets, nullptr); /* NOLINT: bugprone-use-after-move */
/* Just a basic check that the new curves work okay. */
float3 min;
float3 max;
EXPECT_TRUE(other.bounds_min_max(min, max));
EXPECT_TRUE(other.bounds_min_max());
curves = std::move(other);

View File

@ -196,24 +196,30 @@ Vector<const GeometryComponent *> GeometrySet::get_components_for_read() const
return components;
}
bool GeometrySet::compute_boundbox_without_instances(float3 *r_min, float3 *r_max) const
std::optional<Bounds<float3>> GeometrySet::compute_boundbox_without_instances() const
{
using namespace blender;
bool have_minmax = false;
std::optional<Bounds<float3>> bounds;
if (const PointCloud *pointcloud = this->get_pointcloud_for_read()) {
have_minmax |= pointcloud->bounds_min_max(*r_min, *r_max);
bounds = bounds::merge(bounds, pointcloud->bounds_min_max());
}
if (const Mesh *mesh = this->get_mesh_for_read()) {
have_minmax |= BKE_mesh_wrapper_minmax(mesh, *r_min, *r_max);
Bounds<float3> mesh_bounds{float3(std::numeric_limits<float>::max()),
float3(std::numeric_limits<float>::min())};
if (BKE_mesh_wrapper_minmax(mesh, mesh_bounds.min, mesh_bounds.max)) {
bounds = bounds::merge(bounds, {mesh_bounds});
}
}
if (const Volume *volume = this->get_volume_for_read()) {
have_minmax |= BKE_volume_min_max(volume, *r_min, *r_max);
Bounds<float3> volume_bounds{float3(std::numeric_limits<float>::max()),
float3(std::numeric_limits<float>::min())};
if (BKE_volume_min_max(volume, volume_bounds.min, volume_bounds.max)) {
bounds = bounds::merge(bounds, {volume_bounds});
}
}
if (const Curves *curves_id = this->get_curves_for_read()) {
const bke::CurvesGeometry &curves = curves_id->geometry.wrap();
have_minmax |= curves.bounds_min_max(*r_min, *r_max);
bounds = bounds::merge(bounds, curves_id->geometry.wrap().bounds_min_max());
}
return have_minmax;
return bounds;
}
std::ostream &operator<<(std::ostream &stream, const GeometrySet &geometry_set)

View File

@ -17,6 +17,7 @@
#include "BKE_material.h"
#include "BKE_object.h"
#include "BLI_bounds.hh"
#include "BLI_map.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_memarena.h"
@ -699,25 +700,21 @@ GreasePencil *BKE_grease_pencil_new_nomain()
BoundBox *BKE_grease_pencil_boundbox_get(Object *ob)
{
using namespace blender;
BLI_assert(ob->type == OB_GREASE_PENCIL);
const GreasePencil *grease_pencil = static_cast<const GreasePencil *>(ob->data);
if (ob->runtime.bb != nullptr && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) {
return ob->runtime.bb;
}
if (ob->runtime.bb == nullptr) {
ob->runtime.bb = MEM_cnew<BoundBox>(__func__);
}
float3 min(FLT_MAX);
float3 max(-FLT_MAX);
if (!grease_pencil->bounds_min_max(min, max)) {
min = float3(-1);
max = float3(1);
}
BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
if (const std::optional<Bounds<float3>> bounds = grease_pencil->bounds_min_max()) {
BKE_boundbox_init_from_minmax(ob->runtime.bb, bounds->min, bounds->max);
}
else {
BKE_boundbox_init_from_minmax(ob->runtime.bb, float3(-1), float3(1));
}
return ob->runtime.bb;
@ -1109,21 +1106,19 @@ void GreasePencil::foreach_editable_drawing(
foreach_drawing_ex(*this, frame, EDITABLE, function);
}
bool GreasePencil::bounds_min_max(float3 &min, float3 &max) const
std::optional<blender::Bounds<blender::float3>> GreasePencil::bounds_min_max() const
{
bool found = false;
using namespace blender;
/* FIXME: this should somehow go through the visible drawings. We don't have access to the
* scene time here, so we probably need to cache the visible drawing for each layer somehow. */
std::optional<Bounds<float3>> bounds;
for (int i = 0; i < this->drawing_array_num; i++) {
GreasePencilDrawingBase *drawing_base = this->drawing_array[i];
switch (drawing_base->type) {
case GP_DRAWING: {
GreasePencilDrawing *drawing = reinterpret_cast<GreasePencilDrawing *>(drawing_base);
const blender::bke::CurvesGeometry &curves = drawing->geometry.wrap();
if (curves.bounds_min_max(min, max)) {
found = true;
}
const bke::CurvesGeometry &curves = drawing->geometry.wrap();
bounds = bounds::merge(bounds, curves.bounds_min_max());
break;
}
case GP_DRAWING_REFERENCE: {
@ -1133,7 +1128,7 @@ bool GreasePencil::bounds_min_max(float3 &min, float3 &max) const
}
}
return found;
return bounds;
}
blender::Span<const blender::bke::greasepencil::Layer *> GreasePencil::layers() const

View File

@ -244,32 +244,7 @@ MetaElem *BKE_mball_element_add(MetaBall *mb, const int type)
BoundBox *BKE_mball_boundbox_get(Object *ob)
{
BLI_assert(ob->type == OB_MBALL);
if (ob->runtime.bb != nullptr && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) {
return ob->runtime.bb;
}
if (ob->runtime.bb == nullptr) {
ob->runtime.bb = MEM_cnew<BoundBox>(__func__);
}
/* Expect that this function is only called for evaluated objects. */
const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
float min[3];
float max[3];
if (mesh_eval) {
INIT_MINMAX(min, max);
if (!BKE_mesh_minmax(mesh_eval, min, max)) {
copy_v3_fl(min, -1.0f);
copy_v3_fl(max, 1.0f);
}
}
else {
copy_v3_fl(min, 0.0f);
copy_v3_fl(max, 0.0f);
}
BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY;
BKE_object_boundbox_calc_from_evaluated_geometry(ob);
return ob->runtime.bb;
}
@ -704,14 +679,5 @@ void BKE_mball_data_update(Depsgraph *depsgraph, Scene *scene, Object *ob)
ob->runtime.geometry_set_eval = new GeometrySet(GeometrySet::create_with_mesh(mesh));
if (ob->runtime.bb == nullptr) {
ob->runtime.bb = MEM_cnew<BoundBox>(__func__);
}
float3 min(std::numeric_limits<float>::max());
float3 max(-std::numeric_limits<float>::max());
if (!ob->runtime.geometry_set_eval->compute_boundbox_without_instances(&min, &max)) {
min = float3(0);
max = float3(0);
}
BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
BKE_object_boundbox_calc_from_evaluated_geometry(ob);
};

View File

@ -1502,21 +1502,15 @@ void BKE_mesh_looptri_get_real_edges(const blender::int2 *edges,
}
}
bool BKE_mesh_minmax(const Mesh *me, float r_min[3], float r_max[3])
std::optional<blender::Bounds<blender::float3>> Mesh::bounds_min_max() const
{
using namespace blender;
if (me->totvert == 0) {
return false;
if (this->totvert == 0) {
return std::nullopt;
}
me->runtime->bounds_cache.ensure(
[me](Bounds<float3> &r_bounds) { r_bounds = *bounds::min_max(me->vert_positions()); });
const Bounds<float3> &bounds = me->runtime->bounds_cache.data();
copy_v3_v3(r_min, math::min(bounds.min, float3(r_min)));
copy_v3_v3(r_max, math::max(bounds.max, float3(r_max)));
return true;
this->runtime->bounds_cache.ensure(
[&](Bounds<float3> &r_bounds) { r_bounds = *bounds::min_max(this->vert_positions()); });
return this->runtime->bounds_cache.data();
}
void Mesh::bounds_set_eager(const blender::Bounds<float3> &bounds)

View File

@ -276,18 +276,6 @@ bool BKE_mesh_center_median_from_polys(const Mesh *me, float r_cent[3])
return (me->totpoly != 0);
}
bool BKE_mesh_center_bounds(const Mesh *me, float r_cent[3])
{
float min[3], max[3];
INIT_MINMAX(min, max);
if (BKE_mesh_minmax(me, min, max)) {
mid_v3_v3v3(r_cent, min, max);
return true;
}
return false;
}
bool BKE_mesh_center_of_surface(const Mesh *me, float r_cent[3])
{
float poly_area;

View File

@ -29,6 +29,7 @@
#include "BLI_ghash.h"
#include "BLI_math.h"
#include "BLI_math_vector.hh"
#include "BLI_task.hh"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
@ -153,12 +154,19 @@ void BKE_mesh_wrapper_ensure_mdata(Mesh *me)
bool BKE_mesh_wrapper_minmax(const Mesh *me, float min[3], float max[3])
{
using namespace blender;
switch (me->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_BMESH:
return BKE_editmesh_cache_calc_minmax(me->edit_mesh, me->runtime->edit_data, min, max);
case ME_WRAPPER_TYPE_MDATA:
case ME_WRAPPER_TYPE_SUBD:
return BKE_mesh_minmax(me, min, max);
case ME_WRAPPER_TYPE_SUBD: {
if (const std::optional<Bounds<float3>> bounds = me->bounds_min_max()) {
copy_v3_v3(min, math::min(bounds->min, float3(min)));
copy_v3_v3(max, math::max(bounds->max, float3(max)));
return true;
}
return false;
}
}
BLI_assert_unreachable();
return false;

View File

@ -3854,7 +3854,7 @@ int ntreeGetPanelIndex(const bNodeTree *ntree, const bNodePanel *panel)
return ntree->panels().first_index_try(const_cast<bNodePanel *>(panel));
}
bNodePanel *ntreeAddPanel(bNodeTree *ntree, const char *name, int flag)
bNodePanel *ntreeAddPanel(bNodeTree *ntree, const char *name)
{
bNodePanel **old_panels_array = ntree->panels_array;
const Span<const bNodePanel *> old_panels = ntree->panels();
@ -3867,7 +3867,7 @@ bNodePanel *ntreeAddPanel(bNodeTree *ntree, const char *name, int flag)
new_panels.data());
bNodePanel *new_panel = MEM_cnew<bNodePanel>(__func__);
*new_panel = {BLI_strdup(name), flag, ntree->next_panel_identifier++};
*new_panel = {BLI_strdup(name)};
new_panels[new_panels.size() - 1] = new_panel;
MEM_SAFE_FREE(old_panels_array);
@ -3877,7 +3877,7 @@ bNodePanel *ntreeAddPanel(bNodeTree *ntree, const char *name, int flag)
return new_panel;
}
bNodePanel *ntreeInsertPanel(bNodeTree *ntree, const char *name, int flag, int index)
bNodePanel *ntreeInsertPanel(bNodeTree *ntree, const char *name, int index)
{
if (!blender::IndexRange(ntree->panels().size() + 1).contains(index)) {
return nullptr;
@ -3899,7 +3899,7 @@ bNodePanel *ntreeInsertPanel(bNodeTree *ntree, const char *name, int flag, int i
new_panels.drop_front(index + 1).data());
bNodePanel *new_panel = MEM_cnew<bNodePanel>(__func__);
*new_panel = {BLI_strdup(name), flag, ntree->next_panel_identifier++};
*new_panel = {BLI_strdup(name)};
new_panels[index] = new_panel;
MEM_SAFE_FREE(old_panels_array);

View File

@ -506,11 +506,19 @@ static void ensure_topology_cache(const bNodeTree &ntree)
ToposortDirection::LeftToRight,
tree_runtime.toposort_left_to_right,
tree_runtime.has_available_link_cycle);
for (const int i : tree_runtime.toposort_left_to_right.index_range()) {
const bNode &node = *tree_runtime.toposort_left_to_right[i];
node.runtime->toposort_left_to_right_index = i;
}
},
[&]() {
bool dummy;
update_toposort(
ntree, ToposortDirection::RightToLeft, tree_runtime.toposort_right_to_left, dummy);
for (const int i : tree_runtime.toposort_right_to_left.index_range()) {
const bNode &node = *tree_runtime.toposort_right_to_left[i];
node.runtime->toposort_right_to_left_index = i;
}
},
[&]() { update_root_frames(ntree); },
[&]() { update_direct_frames_childrens(ntree); });

View File

@ -57,7 +57,7 @@ std::string node_tree_to_dot(const bNodeTree &tree, const bNodeTreeToDotOptions
dot_nodes.add_new(node, dot::NodeWithSocketsRef(dot_node, dot_node_with_sockets));
}
LISTBASE_FOREACH (const bNodeLink *, link, &tree.links) {
for (const bNodeLink *link : tree.all_links()) {
const dot::NodeWithSocketsRef &from_dot_node = dot_nodes.lookup(link->fromnode);
const dot::NodeWithSocketsRef &to_dot_node = dot_nodes.lookup(link->tonode);
const dot::NodePort from_dot_port = from_dot_node.output(link->fromsock->index());

View File

@ -107,10 +107,12 @@ static Vector<ZoneRelation> get_direct_zone_relations(
return zone_relations;
}
static void update_parent_zone_per_node(const Span<const bNode *> all_nodes,
const Span<std::unique_ptr<TreeZone>> all_zones,
const BitGroupVector<> &depend_on_input_flag_array,
Map<int, int> &r_parent_zone_by_node_id)
static void update_zone_per_node(const Span<const bNode *> all_nodes,
const Span<std::unique_ptr<TreeZone>> all_zones,
const BitGroupVector<> &depend_on_input_flag_array,
const Map<const bNode *, TreeZone *> &zone_by_inout_node,
Map<int, int> &r_zone_by_node_id,
Vector<const bNode *> &r_node_outside_zones)
{
for (const int node_i : all_nodes.index_range()) {
const bNode &node = *all_nodes[node_i];
@ -125,8 +127,37 @@ static void update_parent_zone_per_node(const Span<const bNode *> all_nodes,
parent_zone = zone;
}
});
if (parent_zone != nullptr) {
r_parent_zone_by_node_id.add(node.identifier, parent_zone->index);
if (parent_zone == nullptr) {
if (!zone_by_inout_node.contains(&node)) {
r_node_outside_zones.append(&node);
}
}
else {
r_zone_by_node_id.add(node.identifier, parent_zone->index);
}
}
for (const MapItem<const bNode *, TreeZone *> item : zone_by_inout_node.items()) {
r_zone_by_node_id.add_overwrite(item.key->identifier, item.value->index);
}
}
static void update_zone_border_links(const bNodeTree &tree, TreeZones &tree_zones)
{
for (const bNodeLink *link : tree.all_links()) {
if (!link->is_available()) {
continue;
}
if (link->is_muted()) {
continue;
}
TreeZone *from_zone = const_cast<TreeZone *>(tree_zones.get_zone_by_socket(*link->fromsock));
TreeZone *to_zone = const_cast<TreeZone *>(tree_zones.get_zone_by_socket(*link->tosock));
if (from_zone == to_zone) {
continue;
}
BLI_assert(from_zone == nullptr || from_zone->contains_zone_recursively(*to_zone));
for (TreeZone *zone = to_zone; zone != from_zone; zone = zone->parent_zone) {
zone->border_links.append(link);
}
}
}
@ -212,20 +243,34 @@ static std::unique_ptr<TreeZones> discover_tree_zones(const bNodeTree &tree)
update_zone_depths(*zone);
}
update_parent_zone_per_node(all_nodes,
tree_zones->zones,
depend_on_input_flag_array,
tree_zones->parent_zone_by_node_id);
for (std::unique_ptr<TreeZone> &zone : tree_zones->zones) {
if (zone->depth == 0) {
tree_zones->root_zones.append(zone.get());
}
}
update_zone_per_node(all_nodes,
tree_zones->zones,
depend_on_input_flag_array,
zone_by_inout_node,
tree_zones->zone_by_node_id,
tree_zones->nodes_outside_zones);
for (const int node_i : all_nodes.index_range()) {
const bNode *node = all_nodes[node_i];
const int parent_zone_i = tree_zones->parent_zone_by_node_id.lookup_default(node->identifier,
-1);
if (parent_zone_i != -1) {
tree_zones->zones[parent_zone_i]->child_nodes.append(node);
const int zone_i = tree_zones->zone_by_node_id.lookup_default(node->identifier, -1);
if (zone_i == -1) {
continue;
}
const TreeZone &zone = *tree_zones->zones[zone_i];
if (ELEM(node, zone.input_node, zone.output_node)) {
continue;
}
tree_zones->zones[zone_i]->child_nodes.append(node);
}
update_zone_border_links(tree, *tree_zones);
return tree_zones;
}
@ -239,11 +284,11 @@ const TreeZones *get_tree_zones(const bNodeTree &tree)
bool TreeZone::contains_node_recursively(const bNode &node) const
{
const TreeZones *zones = this->owner;
const int parent_zone_i = zones->parent_zone_by_node_id.lookup_default(node.identifier, -1);
if (parent_zone_i == -1) {
const int zone_i = zones->zone_by_node_id.lookup_default(node.identifier, -1);
if (zone_i == -1) {
return false;
}
for (const TreeZone *zone = zones->zones[parent_zone_i].get(); zone; zone = zone->parent_zone) {
for (const TreeZone *zone = zones->zones[zone_i].get(); zone; zone = zone->parent_zone) {
if (zone == this) {
return true;
}
@ -251,4 +296,35 @@ bool TreeZone::contains_node_recursively(const bNode &node) const
return false;
}
bool TreeZone::contains_zone_recursively(const TreeZone &other_zone) const
{
for (const TreeZone *zone = other_zone.parent_zone; zone; zone = zone->parent_zone) {
if (zone == this) {
return true;
}
}
return false;
}
const TreeZone *TreeZones::get_zone_by_socket(const bNodeSocket &socket) const
{
const bNode &node = socket.owner_node();
const int zone_i = this->zone_by_node_id.lookup_default(node.identifier, -1);
if (zone_i == -1) {
return nullptr;
}
const TreeZone &zone = *this->zones[zone_i];
if (zone.input_node == &node) {
if (socket.is_input()) {
return zone.parent_zone;
}
}
if (zone.output_node == &node) {
if (socket.is_output()) {
return zone.parent_zone;
}
}
return &zone;
}
} // namespace blender::bke::node_tree_zones

View File

@ -52,6 +52,7 @@
#include "DNA_world_types.h"
#include "BLI_blenlib.h"
#include "BLI_bounds.hh"
#include "BLI_kdtree.h"
#include "BLI_linklist.h"
#include "BLI_listbase.h"
@ -615,7 +616,7 @@ static void object_blend_write(BlendWriter *writer, ID *id, const void *id_addre
BLO_write_struct(writer, LightgroupMembership, ob->lightgroup);
}
if (ob->light_linking) {
BLO_write_struct(writer, LightgroupMembership, ob->light_linking);
BLO_write_struct(writer, LightLinking, ob->light_linking);
}
if (ob->lightprobe_cache) {
@ -3847,24 +3848,19 @@ void BKE_object_boundbox_calc_from_mesh(Object *ob, const Mesh *me_eval)
bool BKE_object_boundbox_calc_from_evaluated_geometry(Object *ob)
{
float3 min(FLT_MAX);
float3 max(-FLT_MAX);
using namespace blender;
std::optional<Bounds<float3>> bounds;
if (ob->runtime.geometry_set_eval) {
if (!ob->runtime.geometry_set_eval->compute_boundbox_without_instances(&min, &max)) {
min = float3(0);
max = float3(0);
}
bounds = ob->runtime.geometry_set_eval->compute_boundbox_without_instances();
}
else if (const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob)) {
if (!BKE_mesh_wrapper_minmax(mesh_eval, min, max)) {
min = float3(0);
max = float3(0);
Bounds<float3> mesh_bounds{float3(std::numeric_limits<float>::max()),
float3(std::numeric_limits<float>::min())};
if (BKE_mesh_wrapper_minmax(mesh_eval, mesh_bounds.min, mesh_bounds.max)) {
bounds = bounds::merge(bounds, {mesh_bounds});
}
}
else if (ob->runtime.curve_cache) {
BKE_displist_minmax(&ob->runtime.curve_cache->disp, min, max);
}
else {
return false;
}
@ -3872,8 +3868,12 @@ bool BKE_object_boundbox_calc_from_evaluated_geometry(Object *ob)
if (ob->runtime.bb == nullptr) {
ob->runtime.bb = MEM_cnew<BoundBox>(__func__);
}
BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
if (bounds) {
BKE_boundbox_init_from_minmax(ob->runtime.bb, bounds->min, bounds->max);
}
else {
BKE_boundbox_init_from_minmax(ob->runtime.bb, float3(0), float3(0));
}
ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY;

View File

@ -263,12 +263,12 @@ void BKE_pointcloud_nomain_to_pointcloud(PointCloud *pointcloud_src, PointCloud
BKE_id_free(nullptr, pointcloud_src);
}
bool PointCloud::bounds_min_max(blender::float3 &min, blender::float3 &max) const
std::optional<blender::Bounds<blender::float3>> PointCloud::bounds_min_max() const
{
using namespace blender;
using namespace blender::bke;
if (this->totpoint == 0) {
return false;
return std::nullopt;
}
this->runtime->bounds_cache.ensure([&](Bounds<float3> &r_bounds) {
const AttributeAccessor attributes = this->attributes();
@ -281,34 +281,35 @@ bool PointCloud::bounds_min_max(blender::float3 &min, blender::float3 &max) cons
r_bounds = *bounds::min_max(positions);
}
});
const Bounds<float3> &bounds = this->runtime->bounds_cache.data();
min = math::min(bounds.min, min);
max = math::max(bounds.max, max);
return true;
return this->runtime->bounds_cache.data();
}
BoundBox *BKE_pointcloud_boundbox_get(Object *ob)
{
using namespace blender;
BLI_assert(ob->type == OB_POINTCLOUD);
if (ob->runtime.bb != nullptr && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) {
return ob->runtime.bb;
}
if (ob->runtime.bb == nullptr) {
ob->runtime.bb = static_cast<BoundBox *>(MEM_callocN(sizeof(BoundBox), "pointcloud boundbox"));
ob->runtime.bb = MEM_cnew<BoundBox>(__func__);
}
float3 min, max;
INIT_MINMAX(min, max);
if (ob->runtime.geometry_set_eval != nullptr) {
ob->runtime.geometry_set_eval->compute_boundbox_without_instances(&min, &max);
std::optional<Bounds<float3>> bounds;
if (ob->runtime.geometry_set_eval) {
bounds = ob->runtime.geometry_set_eval->compute_boundbox_without_instances();
}
else {
const PointCloud *pointcloud = static_cast<PointCloud *>(ob->data);
pointcloud->bounds_min_max(min, max);
bounds = pointcloud->bounds_min_max();
}
if (bounds) {
BKE_boundbox_init_from_minmax(ob->runtime.bb, bounds->min, bounds->max);
}
else {
BKE_boundbox_init_from_minmax(ob->runtime.bb, float3(-1), float3(1));
}
BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
return ob->runtime.bb;
}

View File

@ -11,6 +11,7 @@
#include "DNA_node_types.h"
#include "DNA_pointcloud_types.h"
#include "BLI_binary_search.hh"
#include "BLI_fileops.hh"
#include "BLI_hash_md5.h"
#include "BLI_path_util.h"
@ -94,15 +95,34 @@ void ModifierSimulationCache::try_discover_bake(const StringRefNull absolute_bak
}
}
static int64_t find_state_at_frame(
const Span<std::unique_ptr<ModifierSimulationStateAtFrame>> states, const SubFrame &frame)
{
const int64_t i = binary_search::find_predicate_begin(
states, [&](const auto &item) { return item->frame >= frame; });
if (i == states.size()) {
return -1;
}
return i;
}
static int64_t find_state_at_frame_exact(
const Span<std::unique_ptr<ModifierSimulationStateAtFrame>> states, const SubFrame &frame)
{
const int64_t i = find_state_at_frame(states, frame);
if (i == -1) {
return -1;
}
if (states[i]->frame != frame) {
return -1;
}
return i;
}
bool ModifierSimulationCache::has_state_at_frame(const SubFrame &frame) const
{
std::lock_guard lock(states_at_frames_mutex_);
for (const auto &item : states_at_frames_) {
if (item->frame == frame) {
return true;
}
}
return false;
return find_state_at_frame_exact(states_at_frames_, frame) != -1;
}
bool ModifierSimulationCache::has_states() const
@ -115,23 +135,26 @@ const ModifierSimulationState *ModifierSimulationCache::get_state_at_exact_frame
const SubFrame &frame) const
{
std::lock_guard lock(states_at_frames_mutex_);
for (const auto &item : states_at_frames_) {
if (item->frame == frame) {
return &item->state;
}
const int64_t i = find_state_at_frame_exact(states_at_frames_, frame);
if (i == -1) {
return nullptr;
}
return nullptr;
return &states_at_frames_[i]->state;
}
ModifierSimulationState &ModifierSimulationCache::get_state_at_frame_for_write(
const SubFrame &frame)
{
std::lock_guard lock(states_at_frames_mutex_);
for (const auto &item : states_at_frames_) {
if (item->frame == frame) {
return item->state;
}
const int64_t i = find_state_at_frame_exact(states_at_frames_, frame);
if (i != -1) {
return states_at_frames_[i]->state;
}
if (!states_at_frames_.is_empty()) {
BLI_assert(frame > states_at_frames_.last()->frame);
}
states_at_frames_.append(std::make_unique<ModifierSimulationStateAtFrame>());
states_at_frames_.last()->frame = frame;
states_at_frames_.last()->state.owner_ = this;
@ -141,23 +164,22 @@ ModifierSimulationState &ModifierSimulationCache::get_state_at_frame_for_write(
StatesAroundFrame ModifierSimulationCache::get_states_around_frame(const SubFrame &frame) const
{
std::lock_guard lock(states_at_frames_mutex_);
StatesAroundFrame states_around_frame;
for (const auto &item : states_at_frames_) {
if (item->frame < frame) {
if (states_around_frame.prev == nullptr || item->frame > states_around_frame.prev->frame) {
states_around_frame.prev = item.get();
}
}
if (item->frame == frame) {
if (states_around_frame.current == nullptr) {
states_around_frame.current = item.get();
}
}
if (item->frame > frame) {
if (states_around_frame.next == nullptr || item->frame < states_around_frame.next->frame) {
states_around_frame.next = item.get();
}
const int64_t i = find_state_at_frame(states_at_frames_, frame);
StatesAroundFrame states_around_frame{};
if (i == -1) {
if (!states_at_frames_.is_empty() && states_at_frames_.last()->frame < frame) {
states_around_frame.prev = states_at_frames_.last().get();
}
return states_around_frame;
}
if (states_at_frames_[i]->frame == frame) {
states_around_frame.current = states_at_frames_[i].get();
}
if (i > 0) {
states_around_frame.prev = states_at_frames_[i - 1].get();
}
if (i < states_at_frames_.size() - 2) {
states_around_frame.next = states_at_frames_[i + 1].get();
}
return states_around_frame;
}

View File

@ -83,7 +83,10 @@ static int append_avi(void *context_v,
int recty,
const char *suffix,
ReportList *reports);
static void filepath_avi(char *string, const RenderData *rd, bool preview, const char *suffix);
static void filepath_avi(char filepath[FILE_MAX],
const RenderData *rd,
bool preview,
const char *suffix);
static void *context_create_avi(void);
static void context_free_avi(void *context_v);
#endif /* WITH_AVI */
@ -141,7 +144,10 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
#ifdef WITH_AVI
static void filepath_avi(char *filepath, const RenderData *rd, bool preview, const char *suffix)
static void filepath_avi(char filepath[FILE_MAX],
const RenderData *rd,
bool preview,
const char *suffix)
{
int sfra, efra;
@ -158,7 +164,7 @@ static void filepath_avi(char *filepath, const RenderData *rd, bool preview, con
efra = rd->efra;
}
strcpy(filepath, rd->pic);
BLI_strncpy(filepath, rd->pic, FILE_MAX);
BLI_path_abs(filepath, BKE_main_blendfile_path_from_global());
BLI_file_ensure_parent_dir_exists(filepath);
@ -188,13 +194,13 @@ static int start_avi(void *context_v,
const char *suffix)
{
int x, y;
char name[256];
char filepath[FILE_MAX];
AviFormat format;
int quality;
double framerate;
AviMovie *avi = context_v;
filepath_avi(name, rd, preview, suffix);
filepath_avi(filepath, rd, preview, suffix);
x = rectx;
y = recty;
@ -209,7 +215,7 @@ static int start_avi(void *context_v,
format = AVI_FORMAT_MJPEG;
}
if (AVI_open_compress(name, avi, 1, format) != AVI_ERROR_NONE) {
if (AVI_open_compress(filepath, avi, 1, format) != AVI_ERROR_NONE) {
BKE_report(reports, RPT_ERROR, "Cannot open or start AVI movie file");
return 0;
}
@ -222,7 +228,7 @@ static int start_avi(void *context_v,
avi->interlace = 0;
avi->odd_fields = 0;
printf("Created avi: %s\n", name);
printf("Created avi: %s\n", filepath);
return 1;
}
@ -298,7 +304,10 @@ static void context_free_avi(void *context_v)
#endif /* WITH_AVI */
void BKE_movie_filepath_get(char *filepath, const RenderData *rd, bool preview, const char *suffix)
void BKE_movie_filepath_get(char filepath[/*FILE_MAX*/ 1024],
const RenderData *rd,
bool preview,
const char *suffix)
{
bMovieHandle *mh = BKE_movie_handle_get(rd->im_format.imtype);
if (mh && mh->get_movie_path) {

View File

@ -1428,7 +1428,7 @@ static void ffmpeg_filepath_get(FFMpegContext *context,
BLI_path_suffix(filepath, FILE_MAX, suffix, "");
}
void BKE_ffmpeg_filepath_get(char *filepath,
void BKE_ffmpeg_filepath_get(char filepath[/*FILE_MAX*/ 1024],
const RenderData *rd,
bool preview,
const char *suffix)

View File

@ -21,7 +21,7 @@ namespace blender::bounds {
/**
* Find the smallest and largest values element-wise in the span.
*/
template<typename T> inline std::optional<Bounds<T>> min_max(Span<T> values)
template<typename T> [[nodiscard]] inline std::optional<Bounds<T>> min_max(Span<T> values)
{
if (values.is_empty()) {
return std::nullopt;
@ -48,7 +48,8 @@ template<typename T> inline std::optional<Bounds<T>> min_max(Span<T> values)
* first. The template type T is expected to have an addition operator implemented with RadiusT.
*/
template<typename T, typename RadiusT>
inline std::optional<Bounds<T>> min_max_with_radii(Span<T> values, Span<RadiusT> radii)
[[nodiscard]] inline std::optional<Bounds<T>> min_max_with_radii(Span<T> values,
Span<RadiusT> radii)
{
BLI_assert(values.size() == radii.size());
if (values.is_empty()) {
@ -72,4 +73,25 @@ inline std::optional<Bounds<T>> min_max_with_radii(Span<T> values, Span<RadiusT>
});
}
template<typename T> [[nodiscard]] inline Bounds<T> merge(const Bounds<T> &a, const Bounds<T> &b)
{
return {math::min(a.min, b.min), math::max(a.max, b.max)};
}
template<typename T>
[[nodiscard]] inline std::optional<Bounds<T>> merge(const std::optional<Bounds<T>> &a,
const std::optional<Bounds<T>> &b)
{
if (a.has_value() && b.has_value()) {
return merge(*a, *b);
}
if (a.has_value()) {
return a;
}
if (b.has_value()) {
return b;
}
return std::nullopt;
}
} // namespace blender::bounds

View File

@ -117,7 +117,7 @@ int BLI_path_sequence_decode(const char *path,
if (head) {
/* Name_end points to last character of head,
* make it +1 so null-terminator is nicely placed. */
BLI_strncpy(head, path, name_end + 1);
BLI_strncpy(head, path, MIN2(head_maxncpy, name_end + 1));
}
if (r_digits_len) {
*r_digits_len = 0;

View File

@ -32,6 +32,9 @@
int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
{
/* Could make an argument, it's a documented limit at the moment. */
const size_t name_maxncpy = 256;
int icon = 0;
/* sanity checks */
@ -41,13 +44,13 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
if (ELEM(NULL, id, fcu, fcu->rna_path)) {
if (fcu == NULL) {
strcpy(name, TIP_("<invalid>"));
BLI_strncpy(name, TIP_("<invalid>"), name_maxncpy);
}
else if (fcu->rna_path == NULL) {
strcpy(name, TIP_("<no path>"));
BLI_strncpy(name, TIP_("<no path>"), name_maxncpy);
}
else { /* id == NULL */
BLI_snprintf(name, 256, "%s[%d]", fcu->rna_path, fcu->array_index);
BLI_snprintf(name, name_maxncpy, "%s[%d]", fcu->rna_path, fcu->array_index);
}
}
else {
@ -171,10 +174,10 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
/* XXX we need to check for invalid names...
* XXX the name length limit needs to be passed in or as some define */
if (structname) {
BLI_snprintf(name, 256, "%s%s (%s)", arrayname, propname, structname);
BLI_snprintf(name, name_maxncpy, "%s%s (%s)", arrayname, propname, structname);
}
else {
BLI_snprintf(name, 256, "%s%s", arrayname, propname);
BLI_snprintf(name, name_maxncpy, "%s%s", arrayname, propname);
}
/* free temp name if nameprop is set */
@ -193,7 +196,7 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
}
else {
/* invalid path */
BLI_snprintf(name, 256, "\"%s[%d]\"", fcu->rna_path, fcu->array_index);
BLI_snprintf(name, name_maxncpy, "\"%s[%d]\"", fcu->rna_path, fcu->array_index);
/* icon for this should be the icon for the base ID */
/* TODO: or should we just use the error icon? */

View File

@ -497,10 +497,10 @@ static int poselib_blend_modal(bContext *C, wmOperator *op, const wmEvent *event
ED_slider_status_string_get(pbd->slider, slider_string, sizeof(slider_string));
if (pbd->state == POSE_BLEND_BLENDING) {
strcpy(tab_string, TIP_("[Tab] - Show original pose"));
STRNCPY(tab_string, TIP_("[Tab] - Show original pose"));
}
else {
strcpy(tab_string, TIP_("[Tab] - Show blended pose"));
STRNCPY(tab_string, TIP_("[Tab] - Show blended pose"));
}
SNPRINTF(status_string, "%s | %s | [Ctrl] - Flip Pose", tab_string, slider_string);

View File

@ -941,21 +941,21 @@ static void pose_slide_draw_status(bContext *C, tPoseSlideOp *pso)
switch (pso->mode) {
case POSESLIDE_PUSH:
strcpy(mode_str, TIP_("Push Pose"));
STRNCPY(mode_str, TIP_("Push Pose"));
break;
case POSESLIDE_RELAX:
strcpy(mode_str, TIP_("Relax Pose"));
STRNCPY(mode_str, TIP_("Relax Pose"));
break;
case POSESLIDE_BREAKDOWN:
strcpy(mode_str, TIP_("Breakdown"));
STRNCPY(mode_str, TIP_("Breakdown"));
break;
case POSESLIDE_BLEND:
strcpy(mode_str, TIP_("Blend to Neighbor"));
STRNCPY(mode_str, TIP_("Blend to Neighbor"));
break;
default:
/* Unknown. */
strcpy(mode_str, TIP_("Sliding-Tool"));
STRNCPY(mode_str, TIP_("Sliding-Tool"));
break;
}

View File

@ -1273,7 +1273,6 @@ void ED_curve_editnurb_make(Object *obedit)
actkey = BKE_keyblock_from_object(obedit);
if (actkey) {
// XXX strcpy(G.editModeTitleExtra, "(Key) ");
/* TODO(@ideasman42): undo_system: investigate why this was needed. */
#if 0
undo_editmode_clear();

View File

@ -231,7 +231,7 @@ static int gpencil_layer_add_exec(bContext *C, wmOperator *op)
RNA_property_string_get(op->ptr, prop, name);
}
else {
strcpy(name, "GP_Layer");
STRNCPY(name, "GP_Layer");
}
bGPDlayer *gpl = BKE_gpencil_layer_addnew(gpd, name, true, false);

View File

@ -1853,7 +1853,7 @@ static int gpencil_move_to_layer_exec(bContext *C, wmOperator *op)
RNA_property_string_get(op->ptr, prop, name);
}
else {
strcpy(name, "GP_Layer");
STRNCPY(name, "GP_Layer");
}
target_layer = BKE_gpencil_layer_addnew(gpd, name, true, false);
}

View File

@ -735,24 +735,25 @@ typedef struct GPMatArray {
static uint get_material_type(MaterialGPencilStyle *gp_style,
bool use_stroke,
bool use_fill,
char *name)
char *name,
size_t name_maxncpy)
{
uint r_i = 0;
if ((use_stroke) && (use_fill)) {
switch (gp_style->mode) {
case GP_MATERIAL_MODE_LINE: {
r_i = 1;
strcpy(name, "Line Stroke-Fill");
BLI_strncpy(name, "Line Stroke-Fill", name_maxncpy);
break;
}
case GP_MATERIAL_MODE_DOT: {
r_i = 2;
strcpy(name, "Dots Stroke-Fill");
BLI_strncpy(name, "Dots Stroke-Fill", name_maxncpy);
break;
}
case GP_MATERIAL_MODE_SQUARE: {
r_i = 3;
strcpy(name, "Squares Stroke-Fill");
BLI_strncpy(name, "Squares Stroke-Fill", name_maxncpy);
break;
}
default:
@ -763,17 +764,17 @@ static uint get_material_type(MaterialGPencilStyle *gp_style,
switch (gp_style->mode) {
case GP_MATERIAL_MODE_LINE: {
r_i = 4;
strcpy(name, "Line Stroke");
BLI_strncpy(name, "Line Stroke", name_maxncpy);
break;
}
case GP_MATERIAL_MODE_DOT: {
r_i = 5;
strcpy(name, "Dots Stroke");
BLI_strncpy(name, "Dots Stroke", name_maxncpy);
break;
}
case GP_MATERIAL_MODE_SQUARE: {
r_i = 6;
strcpy(name, "Squares Stroke");
BLI_strncpy(name, "Squares Stroke", name_maxncpy);
break;
}
default:
@ -782,7 +783,7 @@ static uint get_material_type(MaterialGPencilStyle *gp_style,
}
else {
r_i = 7;
strcpy(name, "Solid Fill");
BLI_strncpy(name, "Solid Fill", name_maxncpy);
}
/* Create key TSSSSFFFF (T: Type S: Stroke Alpha F: Fill Alpha) */
@ -878,7 +879,7 @@ static int gpencil_material_to_vertex_exec(bContext *C, wmOperator *op)
/* Only for no Stencil materials. */
if (!is_stencil) {
/* Create material type unique key by type and alpha. */
uint key = get_material_type(gp_style, use_stroke, use_fill, name);
uint key = get_material_type(gp_style, use_stroke, use_fill, name, sizeof(name));
/* Check if material exist. */
bool found = false;

View File

@ -51,6 +51,9 @@ void ED_node_cursor_location_get(const struct SpaceNode *snode, float value[2]);
void ED_node_cursor_location_set(struct SpaceNode *snode, const float value[2]);
int ED_node_tree_path_length(struct SpaceNode *snode);
/**
* \param value: The path output at least the size of `ED_node_tree_path_length(snode) + 1`.
*/
void ED_node_tree_path_get(struct SpaceNode *snode, char *value);
void ED_node_tree_start(struct SpaceNode *snode,

View File

@ -2175,7 +2175,7 @@ void uiLayoutSetPropSep(uiLayout *layout, bool is_sep);
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep);
int uiLayoutGetLocalDir(const uiLayout *layout);
int uiLayoutGetOperatorContext(uiLayout *layout);
wmOperatorCallContext uiLayoutGetOperatorContext(uiLayout *layout);
bool uiLayoutGetActive(uiLayout *layout);
bool uiLayoutGetActiveDefault(uiLayout *layout);
bool uiLayoutGetActivateInit(uiLayout *layout);
@ -2523,7 +2523,7 @@ enum uiTemplateListFlags {
UI_TEMPLATE_LIST_FLAGS_LAST
};
ENUM_OPERATORS(enum uiTemplateListFlags, UI_TEMPLATE_LIST_FLAGS_LAST);
ENUM_OPERATORS(uiTemplateListFlags, UI_TEMPLATE_LIST_FLAGS_LAST);
void uiTemplateList(uiLayout *layout,
const struct bContext *C,

View File

@ -2166,7 +2166,7 @@ static bool ui_but_drag_init(bContext *C,
else if (but->type == UI_BTYPE_VIEW_ITEM) {
const uiButViewItem *view_item_but = (uiButViewItem *)but;
if (view_item_but->view_item) {
UI_view_item_drag_start(C, view_item_but->view_item);
return UI_view_item_drag_start(C, view_item_but->view_item);
}
}
else {
@ -11347,6 +11347,10 @@ static int ui_handle_menus_recursive(bContext *C,
}
}
if (!menu->retvalue) {
ui_handle_viewlist_items_hover(event, menu->region);
}
if (do_towards_reinit) {
ui_mouse_motion_towards_reinit(menu, event->xy);
}

View File

@ -5636,7 +5636,7 @@ uiBlock *uiLayoutGetBlock(uiLayout *layout)
return layout->root->block;
}
int uiLayoutGetOperatorContext(uiLayout *layout)
wmOperatorCallContext uiLayoutGetOperatorContext(uiLayout *layout)
{
return layout->root->opcontext;
}

View File

@ -1026,8 +1026,8 @@ static void override_idtemplate_menu()
MenuType *mt;
mt = MEM_cnew<MenuType>(__func__);
strcpy(mt->idname, "UI_MT_idtemplate_liboverride");
strcpy(mt->label, N_("Library Override"));
STRNCPY(mt->idname, "UI_MT_idtemplate_liboverride");
STRNCPY(mt->label, N_("Library Override"));
mt->poll = override_idtemplate_menu_poll;
mt->draw = override_idtemplate_menu_draw;
WM_menutype_add(mt);

View File

@ -214,9 +214,8 @@ static void ui_update_color_picker_buts_rgb(uiBut *from_but,
}
rgb_float_to_uchar(rgb_hex_uchar, rgb_hex);
SNPRINTF(col, "%02X%02X%02X", UNPACK3_EX((uint), rgb_hex_uchar, ));
strcpy(bt->poin, col);
const int col_len = SNPRINTF_RLEN(col, "%02X%02X%02X", UNPACK3_EX((uint), rgb_hex_uchar, ));
memcpy(bt->poin, col, col_len + 1);
}
else if (bt->str[1] == ' ') {
if (bt->str[0] == 'R') {

View File

@ -123,9 +123,9 @@ static void hud_panel_operator_redo_draw(const bContext *C, Panel *panel)
static void hud_panels_register(ARegionType *art, int space_type, int region_type)
{
PanelType *pt = MEM_cnew<PanelType>(__func__);
strcpy(pt->idname, "OPERATOR_PT_redo");
strcpy(pt->label, N_("Redo"));
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "OPERATOR_PT_redo");
STRNCPY(pt->label, N_("Redo"));
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw_header = hud_panel_operator_redo_draw_header;
pt->draw = hud_panel_operator_redo_draw;
pt->poll = hud_panel_operator_redo_poll;

View File

@ -647,7 +647,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
if (has_valid_context == false) {
/* pass */
}
else if (BPY_run_string_as_string_and_size(
else if (BPY_run_string_as_string_and_len(
C, expr_imports, expr, nullptr, &expr_result, &expr_result_len))
{
/* pass. */

View File

@ -490,8 +490,9 @@ static bool add_collection_search_item(CollItemSearch *cis,
* removed). */
BKE_id_full_name_ui_prefix_get(
name_buf, static_cast<const ID *>(cis->data), false, UI_SEP_CHAR, &name_prefix_offset);
BLI_assert(strlen(name_buf) <= MEM_allocN_len(cis->name));
strcpy(cis->name, name_buf);
const int name_buf_len = strlen(name_buf);
BLI_assert(name_buf_len <= strlen(cis->name));
memcpy(cis->name, name_buf, name_buf_len + 1);
}
return UI_search_item_add(items,

View File

@ -1571,7 +1571,7 @@ float UI_text_clip_middle_ex(const uiFontStyle *fstyle,
const float parts_strwidth = (okwidth - sep_strwidth) / 2.0f;
if (rpart) {
strcpy(rpart_buf, rpart);
STRNCPY(rpart_buf, rpart);
*rpart = '\0';
rpart = rpart_buf;
}

View File

@ -68,6 +68,20 @@ void AbstractGridView::change_state_delayed()
BLI_assert_msg(
is_reconstructed(),
"These state changes are supposed to be delayed until reconstruction is completed");
/* Debug-only sanity check: Ensure only one item requests to be active. */
#ifndef NDEBUG
bool has_active = false;
foreach_item([&has_active](AbstractGridViewItem &item) {
if (item.should_be_active().value_or(false)) {
BLI_assert_msg(
!has_active,
"Only one view item should ever return true for its `should_be_active()` method");
has_active = true;
}
});
#endif
foreach_item([](AbstractGridViewItem &item) { item.change_state_delayed(); });
}

View File

@ -108,7 +108,7 @@ AbstractTreeViewItem *AbstractTreeView::find_matching_child(
const AbstractTreeViewItem &lookup_item, const TreeViewOrItem &items)
{
for (const auto &iter_item : items.children_) {
if (lookup_item.matches_single(*iter_item)) {
if (lookup_item.matches(*iter_item)) {
/* We have a matching item! */
return iter_item.get();
}
@ -122,6 +122,20 @@ void AbstractTreeView::change_state_delayed()
BLI_assert_msg(
is_reconstructed(),
"These state changes are supposed to be delayed until reconstruction is completed");
/* Debug-only sanity check: Ensure only one item requests to be active. */
#ifndef NDEBUG
bool has_active = false;
foreach_item([&has_active](AbstractTreeViewItem &item) {
if (item.should_be_active().value_or(false)) {
BLI_assert_msg(
!has_active,
"Only one view item should ever return true for its `should_be_active()` method");
has_active = true;
}
});
#endif
foreach_item([](AbstractTreeViewItem &item) { item.change_state_delayed(); });
}
@ -176,7 +190,7 @@ void AbstractTreeViewItem::collapse_chevron_click_fn(bContext *C,
* lookup the hovered item via context here. */
const wmWindow *win = CTX_wm_window(C);
const ARegion *region = CTX_wm_region(C);
const ARegion *region = CTX_wm_menu(C) ? CTX_wm_menu(C) : CTX_wm_region(C);
uiViewItemHandle *hovered_item_handle = UI_region_views_find_item_at(region,
win->eventstate->xy);
@ -474,14 +488,16 @@ void TreeViewLayoutBuilder::build_row(AbstractTreeViewItem &item) const
uiLayoutSetActive(overlap, false);
}
uiLayoutRow(overlap, false);
uiLayout *row = uiLayoutRow(overlap, false);
/* Enable emboss for mouse hover highlight. */
uiLayoutSetEmboss(row, UI_EMBOSS);
/* Every item gets one! Other buttons can be overlapped on top. */
item.add_treerow_button(block_);
/* After adding tree-row button (would disable hover highlighting). */
UI_block_emboss_set(&block_, UI_EMBOSS_NONE);
uiLayout *row = uiLayoutRow(overlap, true);
row = uiLayoutRow(overlap, true);
item.add_indent(*row);
item.add_collapse_chevron(block_);

View File

@ -737,7 +737,7 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key, Undo
/* Copy the ID name characters to the mesh so code that depends on accessing the ID type can work
* on it. Necessary to use the attribute API. */
strcpy(um->me.id.name, "MEundomesh_from_editmesh");
STRNCPY(um->me.id.name, "MEundomesh_from_editmesh");
/* Runtime data is necessary for some asserts in other code, and the overhead of creating it for
* undo meshes should be low. */

View File

@ -1449,7 +1449,7 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op)
md->source_type = LRT_SOURCE_SCENE;
}
/* Only created one layer and one material. */
strcpy(md->target_layer, ((bGPDlayer *)gpd->layers.first)->info);
STRNCPY(md->target_layer, ((bGPDlayer *)gpd->layers.first)->info);
md->target_material = BKE_gpencil_material(ob, 1);
if (md->target_material) {
id_us_plus(&md->target_material->id);

View File

@ -51,6 +51,10 @@
#include "object_intern.h"
#include "WM_api.h"
#include "UI_interface.h"
namespace blender::ed::object::bake_simulation {
static bool calculate_to_frame_poll(bContext *C)
@ -252,10 +256,6 @@ static void bake_simulation_job_startjob(void *customdata,
if (md->type == eModifierType_Nodes) {
NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
nmd->simulation_cache->ptr->reset();
if (StringRef(nmd->simulation_bake_directory).is_empty()) {
nmd->simulation_bake_directory = BLI_strdup(
bke::sim::get_default_modifier_bake_directory(*job.bmain, *object, *md).c_str());
}
char absolute_bake_dir[FILE_MAX];
STRNCPY(absolute_bake_dir, nmd->simulation_bake_directory);
BLI_path_abs(absolute_bake_dir, base_path);
@ -362,7 +362,7 @@ static void bake_simulation_job_endjob(void *customdata)
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, nullptr);
}
static int bake_simulation_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
static int bake_simulation_execute(bContext *C, wmOperator *op)
{
wmWindowManager *wm = CTX_wm_manager(C);
Scene *scene = CTX_data_scene(C);
@ -405,6 +405,160 @@ static int bake_simulation_invoke(bContext *C, wmOperator *op, const wmEvent * /
return OPERATOR_RUNNING_MODAL;
}
struct PathStringHash {
uint64_t operator()(const StringRef s) const
{
/* Normalize the paths so we can compare them. */
DynamicStackBuffer<256> norm_buf(s.size() + 1, 8);
memcpy(norm_buf.buffer(), s.data(), s.size() + 1);
char *norm = static_cast<char *>(norm_buf.buffer());
BLI_path_slash_native(norm);
/* Strip ending slash. */
BLI_path_slash_rstrip(norm);
BLI_path_normalize(norm);
return get_default_hash(norm);
}
};
struct PathStringEquality {
bool operator()(const StringRef a, const StringRef b) const
{
return BLI_path_cmp_normalized(a.data(), b.data()) == 0;
}
};
static bool bake_directory_has_data(const StringRefNull absolute_bake_dir)
{
char meta_dir[FILE_MAX];
BLI_path_join(meta_dir, sizeof(meta_dir), absolute_bake_dir.c_str(), "meta");
char bdata_dir[FILE_MAX];
BLI_path_join(bdata_dir, sizeof(bdata_dir), absolute_bake_dir.c_str(), "bdata");
if (!BLI_is_dir(meta_dir) || !BLI_is_dir(bdata_dir)) {
return false;
}
return true;
}
static void bake_simulation_validate_paths(bContext *C,
wmOperator *op,
const Span<Object *> objects)
{
Main *bmain = CTX_data_main(C);
for (Object *object : objects) {
if (!BKE_id_is_editable(bmain, &object->id)) {
continue;
}
LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
if (md->type != eModifierType_Nodes) {
continue;
}
NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
if (StringRef(nmd->simulation_bake_directory).is_empty()) {
BKE_reportf(op->reports,
RPT_INFO,
"Bake directory of object %s, modifier %s is empty, setting default path",
object->id.name + 2,
md->name);
nmd->simulation_bake_directory = BLI_strdup(
bke::sim::get_default_modifier_bake_directory(*bmain, *object, *md).c_str());
}
}
}
}
/* Map for counting path references. */
using PathUsersMap = Map<std::string,
int,
default_inline_buffer_capacity(sizeof(std::string)),
DefaultProbingStrategy,
PathStringHash,
PathStringEquality>;
static PathUsersMap bake_simulation_get_path_users(bContext *C, const Span<Object *> objects)
{
Main *bmain = CTX_data_main(C);
PathUsersMap path_users;
for (const Object *object : objects) {
const char *base_path = ID_BLEND_PATH(bmain, &object->id);
LISTBASE_FOREACH (const ModifierData *, md, &object->modifiers) {
if (md->type != eModifierType_Nodes) {
continue;
}
const NodesModifierData *nmd = reinterpret_cast<const NodesModifierData *>(md);
if (StringRef(nmd->simulation_bake_directory).is_empty()) {
continue;
}
char absolute_bake_dir[FILE_MAX];
STRNCPY(absolute_bake_dir, nmd->simulation_bake_directory);
BLI_path_abs(absolute_bake_dir, base_path);
path_users.add_or_modify(
absolute_bake_dir, [](int *value) { *value = 1; }, [](int *value) { ++(*value); });
}
}
return path_users;
}
static int bake_simulation_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
{
Vector<Object *> objects;
if (RNA_boolean_get(op->ptr, "selected")) {
CTX_DATA_BEGIN (C, Object *, object, selected_objects) {
objects.append(object);
}
CTX_DATA_END;
}
else {
if (Object *object = CTX_data_active_object(C)) {
objects.append(object);
}
}
/* Set empty paths to default. */
bake_simulation_validate_paths(C, op, objects);
PathUsersMap path_users = bake_simulation_get_path_users(C, objects);
bool has_path_conflict = false;
bool has_existing_bake_data = false;
for (const auto &item : path_users.items()) {
/* Check if multiple caches are writing to the same bake directory. */
if (item.value > 1) {
BKE_reportf(op->reports,
RPT_ERROR,
"Path conflict: %d caches set to path %s",
item.value,
item.key.data());
has_path_conflict = true;
}
/* Check if path exists and contains bake data already. */
if (bake_directory_has_data(item.key.data())) {
has_existing_bake_data = true;
}
}
if (has_path_conflict) {
UI_popup_menu_reports(C, op->reports);
return OPERATOR_CANCELLED;
}
if (has_existing_bake_data) {
return WM_operator_confirm_message(C, op, "Overwrite existing bake data");
}
return bake_simulation_execute(C, op);
}
static int bake_simulation_modal(bContext *C, wmOperator * /*op*/, const wmEvent * /*event*/)
{
if (!WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_BAKE_SIMULATION_NODES)) {
@ -493,6 +647,7 @@ void OBJECT_OT_simulation_nodes_cache_bake(wmOperatorType *ot)
ot->description = "Bake simulations in geometry nodes modifiers";
ot->idname = __func__;
ot->exec = bake_simulation_execute;
ot->invoke = bake_simulation_invoke;
ot->modal = bake_simulation_modal;
ot->poll = bake_simulation_poll;

View File

@ -1452,7 +1452,7 @@ static int constraint_delete_exec(bContext *C, wmOperator *op)
/* Store name temporarily for report. */
char name[MAX_NAME];
strcpy(name, con->name);
STRNCPY(name, con->name);
/* free the constraint */
if (BKE_constraint_remove_ex(lb, ob, con, true)) {
@ -1525,7 +1525,7 @@ static int constraint_apply_exec(bContext *C, wmOperator *op)
/* Store name temporarily for report. */
char name[MAX_NAME];
strcpy(name, con->name);
STRNCPY(name, con->name);
const bool is_first_constraint = con != constraints->first;
/* Copy the constraint. */
@ -1622,7 +1622,7 @@ static int constraint_copy_exec(bContext *C, wmOperator *op)
/* Store name temporarily for report. */
char name[MAX_NAME];
strcpy(name, con->name);
STRNCPY(name, con->name);
/* Copy the constraint. */
bConstraint *copy_con;

View File

@ -20,6 +20,7 @@
#include "DNA_scene_types.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
@ -552,7 +553,7 @@ static int gpencil_modifier_remove_exec(bContext *C, wmOperator *op)
/* Store name temporarily for report. */
char name[MAX_NAME];
strcpy(name, md->name);
STRNCPY(name, md->name);
if (!ED_object_gpencil_modifier_remove(op->reports, bmain, ob, md)) {
return OPERATOR_CANCELLED;
@ -735,7 +736,7 @@ static int gpencil_modifier_apply_exec(bContext *C, wmOperator *op)
char name[MAX_NAME];
if (do_report) {
reports_len = BLI_listbase_count(&op->reports->list);
strcpy(name, md->name); /* Store name temporarily since the modifier is removed. */
STRNCPY(name, md->name); /* Store name temporarily since the modifier is removed. */
}
if (!ED_object_gpencil_modifier_apply(bmain, op->reports, depsgraph, ob, md, apply_as)) {

View File

@ -1517,7 +1517,7 @@ static int modifier_remove_exec(bContext *C, wmOperator *op)
/* Store name temporarily for report. */
char name[MAX_NAME];
strcpy(name, md->name);
STRNCPY(name, md->name);
if (!ED_object_modifier_remove(op->reports, bmain, scene, ob, md)) {
return OPERATOR_CANCELLED;
@ -1769,7 +1769,7 @@ static int modifier_apply_exec_ex(bContext *C, wmOperator *op, int apply_as, boo
char name[MAX_NAME];
if (do_report) {
reports_len = BLI_listbase_count(&op->reports->list);
strcpy(name, md->name); /* Store name temporarily since the modifier is removed. */
STRNCPY(name, md->name); /* Store name temporarily since the modifier is removed. */
}
if (!ED_object_modifier_apply(

View File

@ -488,7 +488,7 @@ static int shaderfx_remove_exec(bContext *C, wmOperator *op)
/* Store name temporarily for report. */
char name[MAX_NAME];
strcpy(name, fx->name);
STRNCPY(name, fx->name);
if (!ED_object_shaderfx_remove(op->reports, bmain, ob, fx)) {
return OPERATOR_CANCELLED;

View File

@ -1444,7 +1444,9 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
BKE_mesh_center_of_volume(me, cent);
}
else if (around == V3D_AROUND_CENTER_BOUNDS) {
BKE_mesh_center_bounds(me, cent);
if (const std::optional<Bounds<float3>> bounds = me->bounds_min_max()) {
cent = math::midpoint(bounds->min, bounds->max);
}
}
else { /* #V3D_AROUND_CENTER_MEDIAN. */
BKE_mesh_center_median(me, cent);
@ -1696,11 +1698,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
/* done */
}
else if (around == V3D_AROUND_CENTER_BOUNDS) {
float3 min(std::numeric_limits<float>::max());
float3 max(-std::numeric_limits<float>::max());
if (curves.bounds_min_max(min, max)) {
cent = math::midpoint(min, max);
}
const Bounds<float3> bounds = *curves.bounds_min_max();
cent = math::midpoint(bounds.min, bounds.max);
}
else if (around == V3D_AROUND_CENTER_MEDIAN) {
cent = calculate_mean(curves.positions());
@ -1729,10 +1728,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
/* Done. */
}
else if (around == V3D_AROUND_CENTER_BOUNDS) {
float3 min(std::numeric_limits<float>::max());
float3 max(-std::numeric_limits<float>::max());
if (pointcloud.bounds_min_max(min, max)) {
cent = math::midpoint(min, max);
if (const std::optional<Bounds<float3>> bounds = pointcloud.bounds_min_max()) {
cent = math::midpoint(bounds->min, bounds->max);
}
}
else if (around == V3D_AROUND_CENTER_MEDIAN) {

View File

@ -620,7 +620,8 @@ static Scene *preview_prepare_scene(
/* new UI convention: draw is in pixel space already. */
/* uses UI_BTYPE_ROUNDBOX button in block to get the rect */
static bool ed_preview_draw_rect(ScrArea *area, int split, int first, rcti *rect, rcti *newrect)
static bool ed_preview_draw_rect(
Scene *scene, ScrArea *area, int split, int first, rcti *rect, rcti *newrect)
{
Render *re;
RenderView *rv;
@ -668,35 +669,21 @@ static bool ed_preview_draw_rect(ScrArea *area, int split, int first, rcti *rect
}
if (rv && rv->combined_buffer.data) {
if (abs(rres.rectx - newx) < 2 && abs(rres.recty - newy) < 2) {
newrect->xmax = max_ii(newrect->xmax, rect->xmin + rres.rectx + offx);
newrect->ymax = max_ii(newrect->ymax, rect->ymin + rres.recty);
if (rres.rectx && rres.recty) {
uchar *rect_byte = static_cast<uchar *>(
MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect"));
float fx = rect->xmin + offx;
float fy = rect->ymin;
/* material preview only needs monoscopy (view 0) */
RE_AcquiredResultGet32(re, &rres, (uint *)rect_byte, 0);
ImBuf *ibuf = IMB_allocImBuf(rres.rectx, rres.recty, 0, 0);
IMB_assign_float_buffer(ibuf, rv->combined_buffer.data, IB_DO_NOT_TAKE_OWNERSHIP);
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_3D_IMAGE_COLOR);
immDrawPixelsTexTiled(&state,
fx,
fy,
rres.rectx,
rres.recty,
GPU_RGBA8,
false,
rect_byte,
1.0f,
1.0f,
nullptr);
ED_draw_imbuf(
ibuf, fx, fy, false, &scene->view_settings, &scene->display_settings, 1.0f, 1.0f);
MEM_freeN(rect_byte);
IMB_freeImBuf(ibuf);
ok = true;
}
@ -711,6 +698,7 @@ static bool ed_preview_draw_rect(ScrArea *area, int split, int first, rcti *rect
void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, rcti *rect)
{
if (idp) {
Scene *scene = CTX_data_scene(C);
wmWindowManager *wm = CTX_wm_manager(C);
ScrArea *area = CTX_wm_area(C);
ID *id = (ID *)idp;
@ -730,11 +718,11 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r
newrect.ymax = rect->ymin;
if (parent) {
ok = ed_preview_draw_rect(area, 1, 1, rect, &newrect);
ok &= ed_preview_draw_rect(area, 1, 0, rect, &newrect);
ok = ed_preview_draw_rect(scene, area, 1, 1, rect, &newrect);
ok &= ed_preview_draw_rect(scene, area, 1, 0, rect, &newrect);
}
else {
ok = ed_preview_draw_rect(area, 0, 0, rect, &newrect);
ok = ed_preview_draw_rect(scene, area, 0, 0, rect, &newrect);
}
if (ok) {

View File

@ -328,9 +328,9 @@ static void screen_user_menu_draw(const bContext *C, Menu *menu)
void ED_screen_user_menu_register(void)
{
MenuType *mt = MEM_callocN(sizeof(MenuType), __func__);
strcpy(mt->idname, "SCREEN_MT_user_menu");
strcpy(mt->label, N_("Quick Favorites"));
strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(mt->idname, "SCREEN_MT_user_menu");
STRNCPY(mt->label, N_("Quick Favorites"));
STRNCPY(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
mt->draw = screen_user_menu_draw;
WM_menutype_add(mt);
}

View File

@ -15,6 +15,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
#include "BLI_math_vector.hh"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@ -792,21 +793,20 @@ void PAINT_OT_sample_color(wmOperatorType *ot)
/** \name Texture Paint Toggle Operator
* \{ */
static void paint_init_pivot_mesh(Object *ob, float location[3])
static blender::float3 paint_init_pivot_mesh(Object *ob)
{
using namespace blender;
const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
if (!me_eval) {
me_eval = (const Mesh *)ob->data;
}
float min[3] = {FLT_MAX, FLT_MAX, FLT_MAX}, max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
if (!BKE_mesh_minmax(me_eval, min, max)) {
zero_v3(location);
zero_v3(max);
const std::optional<Bounds<float3>> bounds = me_eval->bounds_min_max();
if (!bounds) {
return float3(0.0f);
}
interp_v3_v3v3(location, min, max, 0.5f);
return math::midpoint(bounds->min, bounds->max);
}
static void paint_init_pivot_curves(Object *ob, float location[3])
@ -824,11 +824,11 @@ static void paint_init_pivot_grease_pencil(Object *ob, float location[3])
void paint_init_pivot(Object *ob, Scene *scene)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
float location[3];
blender::float3 location;
switch (ob->type) {
case OB_MESH:
paint_init_pivot_mesh(ob, location);
location = paint_init_pivot_mesh(ob);
break;
case OB_CURVES:
paint_init_pivot_curves(ob, location);

View File

@ -30,25 +30,25 @@ void action_buttons_register(ARegionType * /*art*/)
/* TODO: AnimData / Actions List */
pt = MEM_cnew<PanelType>("spacetype action panel properties");
strcpy(pt->idname, "ACTION_PT_properties");
strcpy(pt->label, N_("Active F-Curve"));
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "ACTION_PT_properties");
STRNCPY(pt->label, N_("Active F-Curve"));
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = action_anim_panel_properties;
pt->poll = action_anim_panel_poll;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_cnew<PanelType>("spacetype action panel properties");
strcpy(pt->idname, "ACTION_PT_key_properties");
strcpy(pt->label, N_("Active Keyframe"));
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "ACTION_PT_key_properties");
STRNCPY(pt->label, N_("Active Keyframe"));
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = action_anim_panel_key_properties;
pt->poll = action_anim_panel_poll;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype action panel modifiers");
strcpy(pt->idname, "ACTION_PT_modifiers");
strcpy(pt->label, N_("Modifiers"));
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "ACTION_PT_modifiers");
STRNCPY(pt->label, N_("Modifiers"));
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = action_anim_panel_modifiers;
pt->poll = action_anim_panel_poll;
BLI_addtail(&art->paneltypes, pt);

View File

@ -12,6 +12,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@ -1254,9 +1255,9 @@ static void buttons_panel_context_draw(const bContext *C, Panel *panel)
void buttons_context_register(ARegionType *art)
{
PanelType *pt = MEM_callocN(sizeof(PanelType), "spacetype buttons panel context");
strcpy(pt->idname, "PROPERTIES_PT_context");
strcpy(pt->label, N_("Context")); /* XXX C panels unavailable through RNA bpy.types! */
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "PROPERTIES_PT_context");
STRNCPY(pt->label, N_("Context")); /* XXX C panels unavailable through RNA bpy.types! */
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->poll = buttons_panel_context_poll;
pt->draw = buttons_panel_context_draw;
pt->flag = PANEL_TYPE_NO_HEADER | PANEL_TYPE_NO_SEARCH;

View File

@ -73,10 +73,10 @@ void ED_clip_buttons_register(ARegionType *art)
PanelType *pt;
pt = MEM_cnew<PanelType>("spacetype clip panel metadata");
strcpy(pt->idname, "CLIP_PT_metadata");
strcpy(pt->label, N_("Metadata"));
strcpy(pt->category, "Footage");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "CLIP_PT_metadata");
STRNCPY(pt->label, N_("Metadata"));
STRNCPY(pt->category, "Footage");
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->poll = metadata_panel_context_poll;
pt->draw = metadata_panel_context_draw;
pt->flag |= PANEL_TYPE_DEFAULT_CLOSED;

View File

@ -273,7 +273,7 @@ static void draw_movieclip_notes(SpaceClip *sc, ARegion *region)
}
else {
if (sc->flag & SC_LOCK_SELECTION) {
strcpy(str, "Locked");
STRNCPY(str, "Locked");
}
}
@ -1082,16 +1082,16 @@ static void draw_marker_texts(SpaceClip *sc,
pos[1] = pos[1] * zoomy - fontsize;
if (marker->flag & MARKER_DISABLED) {
strcpy(state, "disabled");
STRNCPY(state, "disabled");
}
else if (marker->framenr != ED_space_clip_get_clip_frame_number(sc)) {
strcpy(state, "estimated");
STRNCPY(state, "estimated");
}
else if (marker->flag & MARKER_TRACKED) {
strcpy(state, "tracked");
STRNCPY(state, "tracked");
}
else {
strcpy(state, "keyframed");
STRNCPY(state, "keyframed");
}
if (state[0]) {

View File

@ -2023,9 +2023,9 @@ void file_external_operations_menu_register(void)
MenuType *mt;
mt = MEM_callocN(sizeof(MenuType), "spacetype file menu file operations");
strcpy(mt->idname, "FILEBROWSER_MT_operations_menu");
strcpy(mt->label, N_("External"));
strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(mt->idname, "FILEBROWSER_MT_operations_menu");
STRNCPY(mt->label, N_("External"));
STRNCPY(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
mt->draw = file_os_operations_menu_draw;
mt->poll = file_os_operations_menu_poll;
WM_menutype_add(mt);

View File

@ -94,9 +94,9 @@ void file_tool_props_region_panels_register(ARegionType *art)
PanelType *pt;
pt = MEM_callocN(sizeof(PanelType), "spacetype file operator properties");
strcpy(pt->idname, "FILE_PT_operator");
strcpy(pt->label, N_("Operator"));
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "FILE_PT_operator");
STRNCPY(pt->label, N_("Operator"));
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->flag = PANEL_TYPE_NO_HEADER;
pt->poll = file_panel_operator_poll;
pt->draw_header = file_panel_operator_header;
@ -208,9 +208,9 @@ void file_execute_region_panels_register(ARegionType *art)
PanelType *pt;
pt = MEM_callocN(sizeof(PanelType), "spacetype file execution buttons");
strcpy(pt->idname, "FILE_PT_execution_buttons");
strcpy(pt->label, N_("Execute Buttons"));
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "FILE_PT_execution_buttons");
STRNCPY(pt->label, N_("Execute Buttons"));
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->flag = PANEL_TYPE_NO_HEADER;
pt->poll = file_panel_operator_poll;
pt->draw = file_panel_execution_buttons_draw;
@ -260,9 +260,9 @@ void file_tools_region_panels_register(ARegionType *art)
PanelType *pt;
pt = MEM_callocN(sizeof(PanelType), "spacetype file asset catalog buttons");
strcpy(pt->idname, "FILE_PT_asset_catalog_buttons");
strcpy(pt->label, N_("Asset Catalogs"));
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "FILE_PT_asset_catalog_buttons");
STRNCPY(pt->label, N_("Asset Catalogs"));
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->flag = PANEL_TYPE_NO_HEADER;
pt->poll = file_panel_asset_browsing_poll;
pt->draw = file_panel_asset_catalog_buttons_draw;

View File

@ -1345,7 +1345,7 @@ static void parent_dir_until_exists_or_default_root(char *dir)
#ifdef WIN32
BLI_windows_get_default_root_dir(dir);
#else
strcpy(dir, "/");
ARRAY_SET_ITEMS(dir, '/', '\0');
#endif
}
}

View File

@ -205,7 +205,7 @@ static void graph_panel_properties(const bContext *C, Panel *panel)
acf->name(ale, name);
}
else {
strcpy(name, IFACE_("<invalid>"));
STRNCPY(name, IFACE_("<invalid>"));
icon = ICON_ERROR;
}
@ -1469,47 +1469,47 @@ void graph_buttons_register(ARegionType *art)
PanelType *pt;
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel properties");
strcpy(pt->idname, "GRAPH_PT_properties");
strcpy(pt->label, N_("Active F-Curve"));
strcpy(pt->category, "F-Curve");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "GRAPH_PT_properties");
STRNCPY(pt->label, N_("Active F-Curve"));
STRNCPY(pt->category, "F-Curve");
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = graph_panel_properties;
pt->poll = graph_panel_poll;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel properties");
strcpy(pt->idname, "GRAPH_PT_key_properties");
strcpy(pt->label, N_("Active Keyframe"));
strcpy(pt->category, "F-Curve");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "GRAPH_PT_key_properties");
STRNCPY(pt->label, N_("Active Keyframe"));
STRNCPY(pt->category, "F-Curve");
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = graph_panel_key_properties;
pt->poll = graph_panel_poll;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel drivers driven");
strcpy(pt->idname, "GRAPH_PT_driven_property");
strcpy(pt->label, N_("Driven Property"));
strcpy(pt->category, "Drivers");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "GRAPH_PT_driven_property");
STRNCPY(pt->label, N_("Driven Property"));
STRNCPY(pt->category, "Drivers");
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = graph_panel_driven_property;
pt->poll = graph_panel_drivers_poll;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel drivers");
strcpy(pt->idname, "GRAPH_PT_drivers");
strcpy(pt->label, N_("Driver"));
strcpy(pt->category, "Drivers");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "GRAPH_PT_drivers");
STRNCPY(pt->label, N_("Driver"));
STRNCPY(pt->category, "Drivers");
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = graph_panel_drivers;
pt->draw_header = graph_panel_drivers_header;
pt->poll = graph_panel_drivers_poll;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel drivers popover");
strcpy(pt->idname, "GRAPH_PT_drivers_popover");
strcpy(pt->label, N_("Add/Edit Driver"));
strcpy(pt->category, "Drivers");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "GRAPH_PT_drivers_popover");
STRNCPY(pt->label, N_("Add/Edit Driver"));
STRNCPY(pt->category, "Drivers");
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = graph_panel_drivers_popover;
pt->poll = graph_panel_drivers_popover_poll;
BLI_addtail(&art->paneltypes, pt);
@ -1518,10 +1518,10 @@ void graph_buttons_register(ARegionType *art)
WM_paneltype_add(pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel modifiers");
strcpy(pt->idname, "GRAPH_PT_modifiers");
strcpy(pt->label, N_("Modifiers"));
strcpy(pt->category, "Modifiers");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "GRAPH_PT_modifiers");
STRNCPY(pt->label, N_("Modifiers"));
STRNCPY(pt->category, "Modifiers");
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->flag = PANEL_TYPE_NO_HEADER;
pt->draw = graph_panel_modifiers;
pt->poll = graph_panel_poll;
@ -1531,10 +1531,10 @@ void graph_buttons_register(ARegionType *art)
ANIM_modifier_panels_register_graph_only(art, GRAPH_FMODIFIER_PANEL_PREFIX, graph_panel_poll);
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel view");
strcpy(pt->idname, "GRAPH_PT_view");
strcpy(pt->label, N_("Show Cursor"));
strcpy(pt->category, "View");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "GRAPH_PT_view");
STRNCPY(pt->label, N_("Show Cursor"));
STRNCPY(pt->category, "View");
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = graph_panel_cursor;
pt->draw_header = graph_panel_cursor_header;
BLI_addtail(&art->paneltypes, pt);

View File

@ -125,7 +125,7 @@ static void common_draw_status_header(bContext *C, tGraphSliderOp *gso, const ch
ED_slider_status_string_get(gso->slider, slider_string, UI_MAX_DRAW_STR);
strcpy(mode_str, TIP_(operator_name));
STRNCPY(mode_str, TIP_(operator_name));
if (hasNumInput(&gso->num)) {
char str_ofs[NUM_STR_REP_LEN];
@ -424,7 +424,7 @@ static void decimate_draw_status(bContext *C, tGraphSliderOp *gso)
ED_slider_status_string_get(gso->slider, slider_string, UI_MAX_DRAW_STR);
strcpy(mode_str, TIP_("Decimate Keyframes"));
STRNCPY(mode_str, TIP_("Decimate Keyframes"));
if (hasNumInput(&gso->num)) {
char str_ofs[NUM_STR_REP_LEN];

View File

@ -1296,10 +1296,10 @@ void image_buttons_register(ARegionType *art)
PanelType *pt;
pt = MEM_callocN(sizeof(PanelType), "spacetype image panel metadata");
strcpy(pt->idname, "IMAGE_PT_metadata");
strcpy(pt->label, N_("Metadata"));
strcpy(pt->category, "Image");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "IMAGE_PT_metadata");
STRNCPY(pt->label, N_("Metadata"));
STRNCPY(pt->category, "Image");
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->order = 10;
pt->poll = metadata_panel_context_poll;
pt->draw = metadata_panel_context_draw;

View File

@ -610,50 +610,50 @@ void nla_buttons_register(ARegionType *art)
PanelType *pt;
pt = MEM_cnew<PanelType>("spacetype nla panel animdata");
strcpy(pt->idname, "NLA_PT_animdata");
strcpy(pt->label, N_("Animation Data"));
strcpy(pt->category, "Edited Action");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "NLA_PT_animdata");
STRNCPY(pt->label, N_("Animation Data"));
STRNCPY(pt->category, "Edited Action");
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->flag = PANEL_TYPE_NO_HEADER;
pt->draw = nla_panel_animdata;
pt->poll = nla_animdata_panel_poll;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_cnew<PanelType>("spacetype nla panel properties");
strcpy(pt->idname, "NLA_PT_stripname");
strcpy(pt->label, N_("Active Strip Name"));
strcpy(pt->category, "Strip");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "NLA_PT_stripname");
STRNCPY(pt->label, N_("Active Strip Name"));
STRNCPY(pt->category, "Strip");
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->flag = PANEL_TYPE_NO_HEADER;
pt->draw = nla_panel_stripname;
pt->poll = nla_strip_panel_poll;
BLI_addtail(&art->paneltypes, pt);
PanelType *pt_properties = pt = MEM_cnew<PanelType>("spacetype nla panel properties");
strcpy(pt->idname, "NLA_PT_properties");
strcpy(pt->label, N_("Active Strip"));
strcpy(pt->category, "Strip");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "NLA_PT_properties");
STRNCPY(pt->label, N_("Active Strip"));
STRNCPY(pt->category, "Strip");
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_properties;
pt->poll = nla_strip_panel_poll;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_cnew<PanelType>("spacetype nla panel properties");
strcpy(pt->idname, "NLA_PT_actionclip");
strcpy(pt->label, N_("Action Clip"));
strcpy(pt->category, "Strip");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "NLA_PT_actionclip");
STRNCPY(pt->label, N_("Action Clip"));
STRNCPY(pt->category, "Strip");
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_actclip;
pt->flag = PANEL_TYPE_DEFAULT_CLOSED;
pt->poll = nla_strip_actclip_panel_poll;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_cnew<PanelType>("spacetype nla panel evaluation");
strcpy(pt->idname, "NLA_PT_evaluation");
strcpy(pt->parent_id, "NLA_PT_properties");
strcpy(pt->label, N_("Animated Influence"));
strcpy(pt->category, "Strip");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "NLA_PT_evaluation");
STRNCPY(pt->parent_id, "NLA_PT_properties");
STRNCPY(pt->label, N_("Animated Influence"));
STRNCPY(pt->category, "Strip");
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_evaluation;
pt->draw_header = nla_panel_animated_influence_header;
pt->parent = pt_properties;
@ -663,11 +663,11 @@ void nla_buttons_register(ARegionType *art)
BLI_addtail(&art->paneltypes, pt);
pt = MEM_cnew<PanelType>("spacetype nla panel animated strip time");
strcpy(pt->idname, "NLA_PT_animated_strip_time");
strcpy(pt->parent_id, "NLA_PT_properties");
strcpy(pt->label, N_("Animated Strip Time"));
strcpy(pt->category, "Strip");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "NLA_PT_animated_strip_time");
STRNCPY(pt->parent_id, "NLA_PT_properties");
STRNCPY(pt->label, N_("Animated Strip Time"));
STRNCPY(pt->category, "Strip");
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_animated_strip_time;
pt->draw_header = nla_panel_animated_strip_time_header;
pt->parent = pt_properties;
@ -677,10 +677,10 @@ void nla_buttons_register(ARegionType *art)
BLI_addtail(&art->paneltypes, pt);
pt = MEM_cnew<PanelType>("spacetype nla panel modifiers");
strcpy(pt->idname, "NLA_PT_modifiers");
strcpy(pt->label, N_("Modifiers"));
strcpy(pt->category, "Modifiers");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "NLA_PT_modifiers");
STRNCPY(pt->label, N_("Modifiers"));
STRNCPY(pt->category, "Modifiers");
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_modifiers;
pt->poll = nla_strip_eval_panel_poll;
pt->flag = PANEL_TYPE_NO_HEADER;

View File

@ -412,7 +412,7 @@ static void nla_main_region_message_subscribe(const wmRegionMessageSubscribePara
PointerRNA ptr;
RNA_pointer_create(&screen->id, &RNA_SpaceNLA, area->spacedata.first, &ptr);
wmMsgSubscribeValue msg_sub_value_region_tag_redraw;
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {};
msg_sub_value_region_tag_redraw.owner = region;
msg_sub_value_region_tag_redraw.user_data = region;
msg_sub_value_region_tag_redraw.notify = ED_region_do_msg_notify_tag_redraw;
@ -488,7 +488,7 @@ static void nla_channel_region_message_subscribe(const wmRegionMessageSubscribeP
PointerRNA ptr;
RNA_pointer_create(&screen->id, &RNA_SpaceNLA, area->spacedata.first, &ptr);
wmMsgSubscribeValue msg_sub_value_region_tag_redraw;
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {};
msg_sub_value_region_tag_redraw.owner = region;
msg_sub_value_region_tag_redraw.user_data = region;
msg_sub_value_region_tag_redraw.notify = ED_region_do_msg_notify_tag_redraw;

View File

@ -186,33 +186,6 @@ void NODE_OT_clipboard_copy(wmOperatorType *ot)
/** \name Paste
* \{ */
static void remap_pairing(bNodeTree &dst_tree, const Map<const bNode *, bNode *> &node_map)
{
/* We don't have the old tree for looking up output nodes by ID,
* so we have to build a map first to find copied output nodes in the new tree. */
Map<int32_t, bNode *> dst_output_node_map;
for (const auto &item : node_map.items()) {
if (item.key->type == GEO_NODE_SIMULATION_OUTPUT) {
dst_output_node_map.add_new(item.key->identifier, item.value);
}
}
for (bNode *dst_node : node_map.values()) {
if (dst_node->type == GEO_NODE_SIMULATION_INPUT) {
NodeGeometrySimulationInput &data = *static_cast<NodeGeometrySimulationInput *>(
dst_node->storage);
if (const bNode *output_node = dst_output_node_map.lookup_default(data.output_node_id,
nullptr)) {
data.output_node_id = output_node->identifier;
}
else {
data.output_node_id = 0;
blender::nodes::update_node_declaration_and_sockets(dst_tree, *dst_node);
}
}
}
}
static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
{
SpaceNode &snode = *CTX_wm_space_node(C);
@ -278,6 +251,8 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
for (bNode *new_node : node_map.values()) {
nodeSetSelected(new_node, true);
new_node->flag &= ~NODE_ACTIVE;
/* The parent pointer must be redirected to new node. */
if (new_node->parent) {
if (node_map.contains(new_node->parent)) {
@ -327,7 +302,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
bke::nodeDeclarationEnsure(&tree, new_node);
}
remap_pairing(tree, node_map);
remap_node_pairing(tree, node_map);
tree.ensure_topology_cache();
for (bNode *new_node : node_map.values()) {

View File

@ -3100,7 +3100,7 @@ static void find_bounds_by_zone_recursive(const SpaceNode &snode,
if (link.fromnode == nullptr) {
continue;
}
if (zone.contains_node_recursively(*link.fromnode) || zone.input_node == link.fromnode) {
if (zone.contains_node_recursively(*link.fromnode) && zone.output_node != link.fromnode) {
const float2 pos = node_link_bezier_points_dragged(snode, link)[3];
rctf rect;
BLI_rctf_init_pt_radius(&rect, pos, node_padding);
@ -3246,14 +3246,14 @@ static void node_draw_nodetree(const bContext &C,
GPU_blend(GPU_BLEND_ALPHA);
nodelink_batch_start(snode);
LISTBASE_FOREACH (const bNodeLink *, link, &ntree.links) {
for (const bNodeLink *link : ntree.all_links()) {
if (!nodeLinkIsHidden(link) && !bke::nodeLinkIsSelected(link)) {
node_draw_link(C, region.v2d, snode, *link, false);
}
}
/* Draw selected node links after the unselected ones, so they are shown on top. */
LISTBASE_FOREACH (const bNodeLink *, link, &ntree.links) {
for (const bNodeLink *link : ntree.all_links()) {
if (!nodeLinkIsHidden(link) && bke::nodeLinkIsSelected(link)) {
node_draw_link(C, region.v2d, snode, *link, true);
}

View File

@ -1261,11 +1261,11 @@ static void node_duplicate_reparent_recursive(bNodeTree *ntree,
}
}
static void remap_pairing(bNodeTree &dst_tree, const Map<bNode *, bNode *> &node_map)
void remap_node_pairing(bNodeTree &dst_tree, const Map<const bNode *, bNode *> &node_map)
{
/* We don't have the old tree for looking up output nodes by ID,
* so we have to build a map first to find copied output nodes in the new tree. */
Map<uint32_t, bNode *> dst_output_node_map;
Map<int32_t, bNode *> dst_output_node_map;
for (const auto &item : node_map.items()) {
if (item.key->type == GEO_NODE_SIMULATION_OUTPUT) {
dst_output_node_map.add_new(item.key->identifier, item.value);
@ -1376,7 +1376,14 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
}
}
remap_pairing(*ntree, node_map);
{
/* Use temporary map that has const key, because that's what the function below expects. */
Map<const bNode *, bNode *> const_node_map;
for (const auto item : node_map.items()) {
const_node_map.add(item.key, item.value);
}
remap_node_pairing(*ntree, const_node_map);
}
/* Deselect old nodes, select the copies instead. */
for (const auto item : node_map.items()) {

View File

@ -914,16 +914,19 @@ static void node_group_make_insert_selected(const bContext &C,
links_to_remove.add(link);
continue;
}
if (link->fromnode == gnode) {
links_to_remove.add(link);
continue;
}
if (nodes_to_move.contains(link->fromnode)) {
internal_links_to_move.add(link);
continue;
}
else {
InputSocketInfo &info = input_links.lookup_or_add_default(link->fromsock);
info.from_node = link->fromnode;
info.links.append(link);
if (!info.interface_socket) {
info.interface_socket = add_interface_from_socket(ntree, group, *link->tosock);
}
InputSocketInfo &info = input_links.lookup_or_add_default(link->fromsock);
info.from_node = link->fromnode;
info.links.append(link);
if (!info.interface_socket) {
info.interface_socket = add_interface_from_socket(ntree, group, *link->tosock);
}
}
}
@ -933,12 +936,15 @@ static void node_group_make_insert_selected(const bContext &C,
links_to_remove.add(link);
continue;
}
if (link->tonode == gnode) {
links_to_remove.add(link);
continue;
}
if (nodes_to_move.contains(link->tonode)) {
internal_links_to_move.add(link);
continue;
}
else {
output_links.append({link, add_interface_from_socket(ntree, group, *link->fromsock)});
}
output_links.append({link, add_interface_from_socket(ntree, group, *link->fromsock)});
}
}
}

View File

@ -336,6 +336,8 @@ bNodeSocket *node_find_indicated_socket(SpaceNode &snode,
float node_link_dim_factor(const View2D &v2d, const bNodeLink &link);
bool node_link_is_hidden_or_dimmed(const View2D &v2d, const bNodeLink &link);
void remap_node_pairing(bNodeTree &dst_tree, const Map<const bNode *, bNode *> &node_map);
void NODE_OT_duplicate(wmOperatorType *ot);
void NODE_OT_delete(wmOperatorType *ot);
void NODE_OT_delete_reconnect(wmOperatorType *ot);

View File

@ -178,18 +178,20 @@ int ED_node_tree_path_length(SpaceNode *snode)
void ED_node_tree_path_get(SpaceNode *snode, char *value)
{
int i = 0;
value[0] = '\0';
#ifndef NDEBUG
const char *value_orig = value;
#endif
/* Note that the caller ensures there is enough space available. */
LISTBASE_FOREACH_INDEX (bNodeTreePath *, path, &snode->treepath, i) {
if (i == 0) {
strcpy(value, path->display_name);
value += strlen(path->display_name);
}
else {
BLI_sprintf(value, "/%s", path->display_name);
value += strlen(path->display_name) + 1;
const int len = strlen(path->display_name);
if (i != 0) {
*value++ = '/';
}
memcpy(value, path->display_name, len);
value += len;
}
*value = '\0';
BLI_assert(ptrdiff_t(ED_node_tree_path_length(snode)) == ptrdiff_t(value - value_orig));
}
void ED_node_set_active_viewer_key(SpaceNode *snode)
@ -247,7 +249,7 @@ static SpaceLink *node_create(const ScrArea * /*area*/, const Scene * /*scene*/)
/* select the first tree type for valid type */
NODE_TREE_TYPES_BEGIN (treetype) {
strcpy(snode->tree_idname, treetype->idname);
STRNCPY(snode->tree_idname, treetype->idname);
break;
}
NODE_TREE_TYPES_END;

View File

@ -85,9 +85,9 @@ void sequencer_buttons_register(ARegionType *art)
#if 0
pt = MEM_callocN(sizeof(PanelType), "spacetype sequencer panel gpencil");
strcpy(pt->idname, "SEQUENCER_PT_gpencil");
strcpy(pt->label, N_("Grease Pencil"));
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "SEQUENCER_PT_gpencil");
STRNCPY(pt->label, N_("Grease Pencil"));
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw_header = ED_gpencil_panel_standard_header;
pt->draw = ED_gpencil_panel_standard;
pt->poll = sequencer_grease_pencil_panel_poll;
@ -95,10 +95,10 @@ void sequencer_buttons_register(ARegionType *art)
#endif
pt = MEM_cnew<PanelType>("spacetype sequencer panel metadata");
strcpy(pt->idname, "SEQUENCER_PT_metadata");
strcpy(pt->label, N_("Metadata"));
strcpy(pt->category, "Metadata");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "SEQUENCER_PT_metadata");
STRNCPY(pt->label, N_("Metadata"));
STRNCPY(pt->category, "Metadata");
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->poll = metadata_panel_context_poll;
pt->draw = metadata_panel_context_draw;
pt->order = 10;

View File

@ -14,6 +14,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_string.h"
#include "BLI_timecode.h"
#include "BLI_utildefines.h"
@ -2016,7 +2017,7 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
}
seqm->machine = active_seq ? active_seq->machine : channel_max;
strcpy(seqm->name + 2, "MetaStrip");
BLI_strncpy(seqm->name + 2, "MetaStrip", sizeof(seqm->name) - 2);
SEQ_sequence_base_unique_name_recursive(scene, &ed->seqbase, seqm);
seqm->start = meta_start_frame;
seqm->len = meta_end_frame - meta_start_frame;

View File

@ -14,9 +14,9 @@ namespace blender::ed::spreadsheet {
void spreadsheet_data_set_region_panels_register(ARegionType &region_type)
{
PanelType *panel_type = MEM_cnew<PanelType>(__func__);
strcpy(panel_type->idname, "SPREADSHEET_PT_data_set");
strcpy(panel_type->label, N_("Data Set"));
strcpy(panel_type->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(panel_type->idname, "SPREADSHEET_PT_data_set");
STRNCPY(panel_type->label, N_("Data Set"));
STRNCPY(panel_type->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
panel_type->flag = PANEL_TYPE_NO_HEADER;
panel_type->draw = spreadsheet_data_set_panel_draw;
BLI_addtail(&region_type.paneltypes, panel_type);

View File

@ -341,10 +341,10 @@ void register_row_filter_panels(ARegionType &region_type)
{
{
PanelType *panel_type = MEM_cnew<PanelType>(__func__);
strcpy(panel_type->idname, "SPREADSHEET_PT_row_filters");
strcpy(panel_type->label, N_("Filters"));
strcpy(panel_type->category, "Filters");
strcpy(panel_type->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(panel_type->idname, "SPREADSHEET_PT_row_filters");
STRNCPY(panel_type->label, N_("Filters"));
STRNCPY(panel_type->category, "Filters");
STRNCPY(panel_type->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
panel_type->flag = PANEL_TYPE_NO_HEADER;
panel_type->draw = spreadsheet_row_filters_layout;
BLI_addtail(&region_type.paneltypes, panel_type);
@ -352,10 +352,10 @@ void register_row_filter_panels(ARegionType &region_type)
{
PanelType *panel_type = MEM_cnew<PanelType>(__func__);
strcpy(panel_type->idname, "SPREADSHEET_PT_filter");
strcpy(panel_type->label, "");
strcpy(panel_type->category, "Filters");
strcpy(panel_type->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(panel_type->idname, "SPREADSHEET_PT_filter");
STRNCPY(panel_type->label, "");
STRNCPY(panel_type->category, "Filters");
STRNCPY(panel_type->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
panel_type->flag = PANEL_TYPE_INSTANCED | PANEL_TYPE_HEADER_EXPAND;
panel_type->draw_header = spreadsheet_filter_panel_draw_header;
panel_type->draw = spreadsheet_filter_panel_draw;

View File

@ -212,9 +212,9 @@ static void recent_files_menu_register(void)
MenuType *mt;
mt = MEM_callocN(sizeof(MenuType), "spacetype info menu recent files");
strcpy(mt->idname, "TOPBAR_MT_file_open_recent");
strcpy(mt->label, N_("Open Recent"));
strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(mt->idname, "TOPBAR_MT_file_open_recent");
STRNCPY(mt->label, N_("Open Recent"));
STRNCPY(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
mt->draw = recent_files_menu_draw;
WM_menutype_add(mt);
}
@ -270,9 +270,9 @@ static void undo_history_menu_register(void)
MenuType *mt;
mt = MEM_callocN(sizeof(MenuType), __func__);
strcpy(mt->idname, "TOPBAR_MT_undo_history");
strcpy(mt->label, N_("Undo History"));
strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(mt->idname, "TOPBAR_MT_undo_history");
STRNCPY(mt->label, N_("Undo History"));
STRNCPY(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
mt->draw = undo_history_draw_menu;
WM_menutype_add(mt);
}

View File

@ -1799,19 +1799,19 @@ void view3d_buttons_register(ARegionType *art)
PanelType *pt;
pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel object");
strcpy(pt->idname, "VIEW3D_PT_transform");
strcpy(pt->label, N_("Transform")); /* XXX C panels unavailable through RNA bpy.types! */
strcpy(pt->category, "Item");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "VIEW3D_PT_transform");
STRNCPY(pt->label, N_("Transform")); /* XXX C panels unavailable through RNA bpy.types! */
STRNCPY(pt->category, "Item");
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = view3d_panel_transform;
pt->poll = view3d_panel_transform_poll;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel vgroup");
strcpy(pt->idname, "VIEW3D_PT_vgroup");
strcpy(pt->label, N_("Vertex Weights")); /* XXX C panels unavailable through RNA bpy.types! */
strcpy(pt->category, "Item");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(pt->idname, "VIEW3D_PT_vgroup");
STRNCPY(pt->label, N_("Vertex Weights")); /* XXX C panels unavailable through RNA bpy.types! */
STRNCPY(pt->category, "Item");
STRNCPY(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = view3d_panel_vgroup;
pt->poll = view3d_panel_vgroup_poll;
BLI_addtail(&art->paneltypes, pt);
@ -1819,9 +1819,9 @@ void view3d_buttons_register(ARegionType *art)
MenuType *mt;
mt = MEM_callocN(sizeof(MenuType), "spacetype view3d menu collections");
strcpy(mt->idname, "VIEW3D_MT_collection");
strcpy(mt->label, N_("Collection"));
strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
STRNCPY(mt->idname, "VIEW3D_MT_collection");
STRNCPY(mt->label, N_("Collection"));
STRNCPY(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
mt->draw = hide_collections_menu_draw;
WM_menutype_add(mt);
}

View File

@ -263,10 +263,10 @@ void ED_uvedit_buttons_register(ARegionType *art)
{
PanelType *pt = MEM_cnew<PanelType>(__func__);
strcpy(pt->idname, "IMAGE_PT_uv");
strcpy(pt->label, N_("UV Vertex")); /* XXX C panels unavailable through RNA bpy.types! */
STRNCPY(pt->idname, "IMAGE_PT_uv");
STRNCPY(pt->label, N_("UV Vertex")); /* XXX C panels unavailable through RNA bpy.types! */
/* Could be 'Item' matching 3D view, avoid new tab for two buttons. */
strcpy(pt->category, "Image");
STRNCPY(pt->category, "Image");
pt->draw = image_panel_uv;
pt->poll = image_panel_uv_poll;
BLI_addtail(&art->paneltypes, pt);

View File

@ -93,6 +93,9 @@ class GraphExecutor : public LazyFunction {
void *init_storage(LinearAllocator<> &allocator) const override;
void destruct_storage(void *storage) const override;
std::string input_name(int index) const override;
std::string output_name(int index) const override;
private:
void execute_impl(Params &params, const Context &context) const override;
};

View File

@ -1451,6 +1451,22 @@ void GraphExecutor::destruct_storage(void *storage) const
std::destroy_at(static_cast<Executor *>(storage));
}
std::string GraphExecutor::input_name(const int index) const
{
const lf::OutputSocket &socket = *graph_inputs_[index];
std::stringstream ss;
ss << socket.node().name() << " - " << socket.name();
return ss.str();
}
std::string GraphExecutor::output_name(const int index) const
{
const lf::InputSocket &socket = *graph_outputs_[index];
std::stringstream ss;
ss << socket.node().name() << " - " << socket.name();
return ss.str();
}
void GraphExecutorLogger::log_socket_value(const Socket &socket,
const GPointer value,
const Context &context) const

View File

@ -2413,14 +2413,13 @@ static bool lineart_geometry_check_visible(double model_view_proj[4][4],
double shift_y,
Mesh *use_mesh)
{
using namespace blender;
if (!use_mesh) {
return false;
}
float mesh_min[3], mesh_max[3];
INIT_MINMAX(mesh_min, mesh_max);
BKE_mesh_minmax(use_mesh, mesh_min, mesh_max);
const Bounds<float3> bounds = *use_mesh->bounds_min_max();
BoundBox bb;
BKE_boundbox_init_from_minmax(&bb, mesh_min, mesh_max);
BKE_boundbox_init_from_minmax(&bb, bounds.min, bounds.max);
double co[8][4];
double tmp[3];

View File

@ -198,38 +198,49 @@ void ShaderCreateInfo::validate_merge(const ShaderCreateInfo &other_info)
}
};
auto print_error_msg = [&](const Resource &res) {
std::cout << name_ << ": Validation failed : Overlapping ";
auto print_error_msg = [&](const Resource &res, Vector<Resource> &resources) {
auto print_resource_name = [&](const Resource &res) {
switch (res.bind_type) {
case Resource::BindType::UNIFORM_BUFFER:
std::cout << "Uniform Buffer " << res.uniformbuf.name;
break;
case Resource::BindType::STORAGE_BUFFER:
std::cout << "Storage Buffer " << res.storagebuf.name;
break;
case Resource::BindType::SAMPLER:
std::cout << "Sampler " << res.sampler.name;
break;
case Resource::BindType::IMAGE:
std::cout << "Image " << res.image.name;
break;
default:
std::cout << "Unknown Type";
break;
}
};
switch (res.bind_type) {
case Resource::BindType::UNIFORM_BUFFER:
std::cout << "Uniform Buffer " << res.uniformbuf.name;
break;
case Resource::BindType::STORAGE_BUFFER:
std::cout << "Storage Buffer " << res.storagebuf.name;
break;
case Resource::BindType::SAMPLER:
std::cout << "Sampler " << res.sampler.name;
break;
case Resource::BindType::IMAGE:
std::cout << "Image " << res.image.name;
break;
default:
std::cout << "Unknown Type";
break;
for (const Resource &_res : resources) {
if (&res != &_res && res.bind_type == _res.bind_type && res.slot == _res.slot) {
std::cout << name_ << ": Validation failed : Overlapping ";
print_resource_name(res);
std::cout << " and ";
print_resource_name(_res);
std::cout << " at (" << res.slot << ") while merging " << other_info.name_ << std::endl;
}
}
std::cout << " (" << res.slot << ") while merging " << other_info.name_ << std::endl;
};
for (auto &res : batch_resources_) {
if (register_resource(res) == false) {
print_error_msg(res);
print_error_msg(res, batch_resources_);
print_error_msg(res, pass_resources_);
}
}
for (auto &res : pass_resources_) {
if (register_resource(res) == false) {
print_error_msg(res);
print_error_msg(res, batch_resources_);
print_error_msg(res, pass_resources_);
}
}
}

View File

@ -67,7 +67,7 @@ void IMB_exrtile_begin_write(
*
* \param passname: Here is the raw channel name without the layer.
*/
void IMB_exr_set_channel(void *handle,
bool IMB_exr_set_channel(void *handle,
const char *layname,
const char *passname,
int xstride,

View File

@ -95,26 +95,30 @@ static void free_anim_movie(anim * /*anim*/)
/* pass */
}
static int an_stringdec(const char *filepath, char *head, char *tail, ushort *numlen)
static int an_stringdec(const char *filepath,
char *head,
size_t head_maxncpy,
char *tail,
size_t tail_maxncpy,
ushort *r_numlen)
{
ushort len, nume, nums = 0;
short i;
const ushort len = strlen(filepath);
bool found = false;
len = strlen(filepath);
nume = len;
ushort num_beg = 0;
ushort num_end = len;
for (i = len - 1; i >= 0; i--) {
for (short i = (short)len - 1; i >= 0; i--) {
if (filepath[i] == SEP) {
break;
}
if (isdigit(filepath[i])) {
if (found) {
nums = i;
num_beg = i;
}
else {
nume = i;
nums = i;
num_end = i;
num_beg = i;
found = true;
}
}
@ -125,15 +129,14 @@ static int an_stringdec(const char *filepath, char *head, char *tail, ushort *nu
}
}
if (found) {
strcpy(tail, &filepath[nume + 1]);
strcpy(head, filepath);
head[nums] = '\0';
*numlen = nume - nums + 1;
return int(atoi(&(filepath)[nums]));
BLI_strncpy(tail, &filepath[num_end + 1], MIN2(num_beg + 1, tail_maxncpy));
BLI_strncpy(head, filepath, head_maxncpy);
*r_numlen = num_end - num_beg + 1;
return int(atoi(&(filepath)[num_beg]));
}
tail[0] = '\0';
strcpy(head, filepath);
*numlen = 0;
BLI_strncpy(head, filepath, head_maxncpy);
*r_numlen = 0;
return true;
}
@ -1593,9 +1596,6 @@ ImBuf *IMB_anim_absolute(anim *anim,
IMB_Proxy_Size preview_size)
{
ImBuf *ibuf = nullptr;
char head[256], tail[256];
ushort digits;
int pic;
int filter_y;
if (anim == nullptr) {
return nullptr;
@ -1628,15 +1628,19 @@ ImBuf *IMB_anim_absolute(anim *anim,
}
switch (anim->curtype) {
case ANIM_SEQUENCE:
pic = an_stringdec(anim->filepath_first, head, tail, &digits);
pic += position;
case ANIM_SEQUENCE: {
char head[ARRAY_SIZE(anim->filepath_first)], tail[ARRAY_SIZE(anim->filepath_first)];
ushort digits;
const int pic = an_stringdec(
anim->filepath_first, head, sizeof(head), tail, sizeof(tail), &digits) +
position;
an_stringenc(anim->filepath, sizeof(anim->filepath), head, tail, digits, pic);
ibuf = IMB_loadiffname(anim->filepath, IB_rect, anim->colorspace);
if (ibuf) {
anim->cur_position = position;
}
break;
}
case ANIM_MOVIE:
ibuf = movie_fetchibuf(anim, position);
if (ibuf) {

View File

@ -1095,11 +1095,10 @@ bool IMB_exr_begin_read(
return true;
}
void IMB_exr_set_channel(
bool IMB_exr_set_channel(
void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect)
{
ExrHandle *data = (ExrHandle *)handle;
ExrChannel *echan;
char name[EXR_TOT_MAXNAME + 1];
if (layname && layname[0] != '\0') {
@ -1113,16 +1112,17 @@ void IMB_exr_set_channel(
BLI_strncpy(name, passname, EXR_TOT_MAXNAME - 1);
}
echan = (ExrChannel *)BLI_findstring(&data->channels, name, offsetof(ExrChannel, name));
ExrChannel *echan = (ExrChannel *)BLI_findstring(
&data->channels, name, offsetof(ExrChannel, name));
if (echan) {
echan->xstride = xstride;
echan->ystride = ystride;
echan->rect = rect;
}
else {
printf("IMB_exr_set_channel error %s\n", name);
if (echan == nullptr) {
return false;
}
echan->xstride = xstride;
echan->ystride = ystride;
echan->rect = rect;
return true;
}
float *IMB_exr_channel_rect(void *handle,
@ -1354,9 +1354,6 @@ void IMB_exr_read_channels(void *handle)
frameBuffer.insert(echan->m->internal_name,
Slice(Imf::FLOAT, (char *)rect, xstride, ystride));
}
else {
printf("warning, channel with no rect set %s\n", echan->m->internal_name.c_str());
}
}
/* Read pixels. */

View File

@ -56,13 +56,14 @@ void IMB_exrtile_begin_write(void * /*handle*/,
{
}
void IMB_exr_set_channel(void * /*handle*/,
bool IMB_exr_set_channel(void * /*handle*/,
const char * /*layname*/,
const char * /*passname*/,
int /*xstride*/,
int /*ystride*/,
float * /*rect*/)
{
return false;
}
float *IMB_exr_channel_rect(void * /*handle*/,
const char * /*layname*/,

View File

@ -323,13 +323,12 @@ void USDGenericMeshWriter::write_mesh(HierarchyContext &context, Mesh *mesh)
}
/* Blender grows its bounds cache to cover animated meshes, so only author once. */
float bound_min[3];
float bound_max[3];
INIT_MINMAX(bound_min, bound_max);
BKE_mesh_minmax(mesh, bound_min, bound_max);
pxr::VtArray<pxr::GfVec3f> extent{pxr::GfVec3f{bound_min[0], bound_min[1], bound_min[2]},
pxr::GfVec3f{bound_max[0], bound_max[1], bound_max[2]}};
usd_mesh.CreateExtentAttr().Set(extent);
if (const std::optional<Bounds<float3>> bounds = mesh->bounds_min_max()) {
pxr::VtArray<pxr::GfVec3f> extent{
pxr::GfVec3f{bounds->min[0], bounds->min[1], bounds->min[2]},
pxr::GfVec3f{bounds->max[0], bounds->max[1], bounds->max[2]}};
usd_mesh.CreateExtentAttr().Set(extent);
}
}
static void get_vertices(const Mesh *mesh, USDMeshData &usd_mesh_data)

View File

@ -13,6 +13,7 @@
#include "DNA_listBase.h"
#ifdef __cplusplus
# include "BLI_bounds_types.hh"
# include "BLI_function_ref.hh"
# include "BLI_map.hh"
# include "BLI_math_vector_types.hh"
@ -457,7 +458,7 @@ typedef struct GreasePencil {
void foreach_editable_drawing(int frame,
blender::FunctionRef<void(int, GreasePencilDrawing &)> function);
bool bounds_min_max(blender::float3 &min, blender::float3 &max) const;
std::optional<blender::Bounds<blender::float3>> bounds_min_max() const;
/* For debugging purposes. */
void print_layer_tree();

View File

@ -17,6 +17,8 @@
/** Workaround to forward-declare C++ type in C header. */
#ifdef __cplusplus
# include <optional>
# include "BLI_bounds_types.hh"
# include "BLI_math_vector_types.hh"
# include "BLI_offset_indices.hh"
@ -302,6 +304,12 @@ typedef struct Mesh {
*/
blender::Span<int> looptri_polys() const;
/**
* Calculate the largest and smallest position values of vertices.
* \note Does not take non-mesh data (edit mesh) into account, see #BKE_mesh_wrapper_minmax,
*/
std::optional<blender::Bounds<blender::float3>> bounds_min_max() const;
/** Set cached mesh bounds to a known-correct value to avoid their lazy calculation later on. */
void bounds_set_eager(const blender::Bounds<blender::float3> &bounds);

View File

@ -536,9 +536,8 @@ typedef struct bNodeLink {
/** Panel in node tree for grouping sockets. */
typedef struct bNodePanel {
/* UI name of the panel (not unique) */
char *name;
int flag;
int _pad;
} bNodePanel;
/* the basis for a Node tree, all links and nodes reside internal here */
@ -608,8 +607,6 @@ typedef struct bNodeTree {
struct bNodePanel **panels_array;
int panels_num;
int active_panel;
int next_panel_identifier;
char _pad2[4];
bNodeTreeRuntimeHandle *runtime;
@ -649,6 +646,9 @@ typedef struct bNodeTree {
blender::Span<const bNode *> nodes_by_type(blender::StringRefNull type_idname) const;
/** Frame nodes without any parents. */
blender::Span<bNode *> root_frames() const;
/** A span containing all links in the node tree. */
blender::Span<bNodeLink *> all_links();
blender::Span<const bNodeLink *> all_links() const;
/**
* Cached toposort of all nodes. If there are cycles, the returned array is not actually a
* toposort. However, if a connected component does not contain a cycle, this component is sorted

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