Eevee-Next: World Reflective Light #108149
|
@ -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
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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:
|
||||
/* --------------------------------------------------------------------
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
* \{ */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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); });
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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? */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -5636,7 +5636,7 @@ uiBlock *uiLayoutGetBlock(uiLayout *layout)
|
|||
return layout->root->block;
|
||||
}
|
||||
|
||||
int uiLayoutGetOperatorContext(uiLayout *layout)
|
||||
wmOperatorCallContext uiLayoutGetOperatorContext(uiLayout *layout)
|
||||
{
|
||||
return layout->root->opcontext;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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') {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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(); });
|
||||
}
|
||||
|
||||
|
|
|
@ -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_);
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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)});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -14,9 +14,9 @@ namespace blender::ed::spreadsheet {
|
|||
void spreadsheet_data_set_region_panels_register(ARegionType ®ion_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(®ion_type.paneltypes, panel_type);
|
||||
|
|
|
@ -341,10 +341,10 @@ void register_row_filter_panels(ARegionType ®ion_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(®ion_type.paneltypes, panel_type);
|
||||
|
@ -352,10 +352,10 @@ void register_row_filter_panels(ARegionType ®ion_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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ¶ms, const Context &context) const override;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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*/,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue