MacOS: Enable support for EDR rendering #105662
|
@ -14,14 +14,14 @@ if [ `id -u` -ne 0 ]; then
|
|||
fi
|
||||
|
||||
# Required by: config manager command below to enable powertools.
|
||||
dnf install 'dnf-command(config-manager)'
|
||||
dnf -y install 'dnf-command(config-manager)'
|
||||
|
||||
# Packages `ninja-build` and `meson` are not available unless CBR or PowerTools repositories are enabled.
|
||||
# See: https://wiki.rockylinux.org/rocky/repo/#notes-on-unlisted-repositories
|
||||
dnf config-manager --set-enabled powertools
|
||||
|
||||
# Required by: epel-release has the patchelf and rubygem-asciidoctor packages
|
||||
dnf install epel-release
|
||||
dnf -y install epel-release
|
||||
|
||||
# `yum-config-manager` does not come in the default minimal install,
|
||||
# so make sure it is installed and available.
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
"""
|
||||
USD Hook Example
|
||||
++++++++++++++++
|
||||
|
||||
This example shows an implementation of ``USDHook`` to extend USD
|
||||
export functionalty.
|
||||
|
||||
One may optionally define one or both of the following callback functions
|
||||
in the ``USDHook`` subclass.
|
||||
|
||||
Hook function ``on_export()`` is called before the USD export finalizes,
|
||||
allowing modifications to the USD stage immediately before it is
|
||||
saved. This function takes as an argument an instance of an
|
||||
internally defined class ``USDSceneExportContext`` which provides the
|
||||
following accessors to the scene data:
|
||||
|
||||
- ``get_stage()`` returns the USD stage to be saved.
|
||||
- ``get_depsgraph()`` returns the Blender scene dependency graph.
|
||||
|
||||
Hook function ``on_material_export()`` is called for each material that is exported,
|
||||
allowing modifications to the USD material, such as shader generation.
|
||||
It is called with three arguments:
|
||||
|
||||
-``export_context``: An instance of the internally defined type ``USDMaterialExportContext``.
|
||||
-``bl_material``: The source Blender material.
|
||||
-``usd_material``: The target USD material to be exported.
|
||||
|
||||
``USDMaterialExportContext`` implements a ``get_stage()`` function which returns the
|
||||
USD stage to be saved.
|
||||
|
||||
Note that the target USD material might already have connected shaders created by the USD exporter or
|
||||
by other material export hooks.
|
||||
|
||||
The hook functions should return ``True`` on success or ``False`` if the operation was bypasssed or
|
||||
otherwise failed to complete. Exceptions raised by these functions will be reported in Blender, with
|
||||
the exception details printed to the console.
|
||||
|
||||
The ``USDHookExample`` class in this example impements an ``on_export()`` function to add custom data to
|
||||
the stage's root layer and an ``on_material_export()`` function to create a simple ``MaterialX`` shader
|
||||
on the USD material.
|
||||
|
||||
"""
|
||||
|
||||
import bpy
|
||||
import bpy.types
|
||||
import pxr.Gf as Gf
|
||||
import pxr.Sdf as Sdf
|
||||
import pxr.Usd as Usd
|
||||
import pxr.UsdShade as UsdShade
|
||||
|
||||
class USDHookExample(bpy.types.USDHook):
|
||||
bl_idname = "usd_hook_example"
|
||||
bl_label = "Example"
|
||||
bl_description = "Example implementation of USD IO hooks"
|
||||
|
||||
@staticmethod
|
||||
def on_export(export_context):
|
||||
""" Include the Blender filepath in the root layer custom data.
|
||||
"""
|
||||
|
||||
stage = export_context.get_stage()
|
||||
|
||||
if stage is None:
|
||||
return False
|
||||
data = bpy.data
|
||||
if data is None:
|
||||
return False
|
||||
|
||||
# Set the custom data.
|
||||
rootLayer = stage.GetRootLayer()
|
||||
customData = rootLayer.customLayerData
|
||||
customData["blenderFilepath"] = data.filepath
|
||||
rootLayer.customLayerData = customData
|
||||
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def on_material_export(export_context, bl_material, usd_material):
|
||||
""" Create a simple MaterialX shader on the exported material.
|
||||
"""
|
||||
|
||||
stage = export_context.get_stage()
|
||||
|
||||
# Create a MaterialX standard surface shader
|
||||
mtl_path = usd_material.GetPrim().GetPath()
|
||||
shader = UsdShade.Shader.Define(stage, mtl_path.AppendPath("mtlxstandard_surface"))
|
||||
shader.CreateIdAttr("ND_standard_surface_surfaceshader")
|
||||
|
||||
# Connect the shader. MaterialX materials use "mtlx" renderContext
|
||||
usd_material.CreateSurfaceOutput("mtlx").ConnectToSource(shader.ConnectableAPI(), "out")
|
||||
|
||||
# Set the color to the Blender material's viewport display color.
|
||||
col = bl_material.diffuse_color
|
||||
shader.CreateInput("base_color", Sdf.ValueTypeNames.Color3f).Set(Gf.Vec3f(col[0], col[1], col[2]))
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_class(USDHookExample)
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_class(USDHookExample)
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
|
@ -19,6 +19,11 @@ float safe_modulo(float a, float b)
|
|||
return (b != 0.0) ? fmod(a, b) : 0.0;
|
||||
}
|
||||
|
||||
float safe_floored_modulo(float a, float b)
|
||||
{
|
||||
return (b != 0.0) ? a - floor(a / b) * b : 0.0;
|
||||
}
|
||||
|
||||
float fract(float a)
|
||||
{
|
||||
return a - floor(a);
|
||||
|
|
|
@ -52,6 +52,8 @@ shader node_math(string math_type = "add",
|
|||
Value = Value1 - floor(Value1);
|
||||
else if (math_type == "modulo")
|
||||
Value = safe_modulo(Value1, Value2);
|
||||
else if (math_type == "floored_modulo")
|
||||
Value = safe_floored_modulo(Value1, Value2);
|
||||
else if (math_type == "trunc")
|
||||
Value = trunc(Value1);
|
||||
else if (math_type == "snap")
|
||||
|
|
|
@ -145,6 +145,8 @@ ccl_device float svm_math(NodeMathType type, float a, float b, float c)
|
|||
return a - floorf(a);
|
||||
case NODE_MATH_MODULO:
|
||||
return safe_modulo(a, b);
|
||||
case NODE_MATH_FLOORED_MODULO:
|
||||
return safe_floored_modulo(a, b);
|
||||
case NODE_MATH_TRUNC:
|
||||
return a >= 0.0f ? floorf(a) : ceilf(a);
|
||||
case NODE_MATH_SNAP:
|
||||
|
|
|
@ -182,6 +182,7 @@ typedef enum NodeMathType {
|
|||
NODE_MATH_PINGPONG,
|
||||
NODE_MATH_SMOOTH_MIN,
|
||||
NODE_MATH_SMOOTH_MAX,
|
||||
NODE_MATH_FLOORED_MODULO,
|
||||
} NodeMathType;
|
||||
|
||||
typedef enum NodeVectorMathType {
|
||||
|
|
|
@ -6292,6 +6292,7 @@ NODE_DEFINE(MathNode)
|
|||
type_enum.insert("less_than", NODE_MATH_LESS_THAN);
|
||||
type_enum.insert("greater_than", NODE_MATH_GREATER_THAN);
|
||||
type_enum.insert("modulo", NODE_MATH_MODULO);
|
||||
type_enum.insert("floored_modulo", NODE_MATH_FLOORED_MODULO);
|
||||
type_enum.insert("absolute", NODE_MATH_ABSOLUTE);
|
||||
type_enum.insert("arctan2", NODE_MATH_ARCTAN2);
|
||||
type_enum.insert("floor", NODE_MATH_FLOOR);
|
||||
|
|
|
@ -732,6 +732,11 @@ ccl_device float safe_modulo(float a, float b)
|
|||
return (b != 0.0f) ? fmodf(a, b) : 0.0f;
|
||||
}
|
||||
|
||||
ccl_device float safe_floored_modulo(float a, float b)
|
||||
{
|
||||
return (b != 0.0f) ? a - floorf(a / b) * b : 0.0f;
|
||||
}
|
||||
|
||||
ccl_device_inline float sqr(float a)
|
||||
{
|
||||
return a * a;
|
||||
|
|
|
@ -114,8 +114,7 @@ colorspaces:
|
|||
description: |
|
||||
sRGB display space
|
||||
isdata: false
|
||||
to_reference: !<FileTransform> {src: srgb.spi1d, interpolation: linear}
|
||||
from_reference: !<FileTransform> {src: srgb_inv.spi1d, interpolation: linear}
|
||||
from_reference: !<ExponentWithLinearTransform> {gamma: 2.4, offset: 0.055, direction: inverse}
|
||||
|
||||
- !<ColorSpace>
|
||||
name: Non-Color
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -676,7 +676,7 @@ const bTheme U_theme_default = {
|
|||
.scene = RGBA(0x808033ff),
|
||||
.audio = RGBA(0x448080ff),
|
||||
.effect = RGBA(0x514a73ff),
|
||||
.transition = RGBA(0x8f4571ff),
|
||||
.transition = RGBA(0x50458fff),
|
||||
.meta = RGBA(0x5b4d91ff),
|
||||
.text_strip = RGBA(0x824c8fff),
|
||||
.color_strip = RGBA(0x8f8f8fff),
|
||||
|
|
|
@ -942,6 +942,10 @@ class KeyingSetInfo(StructRNA, metaclass=RNAMeta):
|
|||
__slots__ = ()
|
||||
|
||||
|
||||
class USDHook(StructRNA, metaclass=RNAMeta):
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
class AddonPreferences(StructRNA, metaclass=RNAMeta):
|
||||
__slots__ = ()
|
||||
|
||||
|
|
|
@ -819,6 +819,7 @@
|
|||
scene_strip="#828f50"
|
||||
audio_strip="#4c8f8f"
|
||||
effect_strip="#4c456c"
|
||||
transition_strip="#50458F"
|
||||
color_strip="#8f8f8f"
|
||||
meta_strip="#5b4d91"
|
||||
mask_strip="#8f5656"
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct bDeformGroup;
|
||||
struct CustomData;
|
||||
struct CustomDataLayer;
|
||||
struct ID;
|
||||
|
@ -117,6 +118,12 @@ void BKE_id_attributes_default_color_set(struct ID *id, const char *name);
|
|||
|
||||
const struct CustomDataLayer *BKE_id_attributes_color_find(const struct ID *id, const char *name);
|
||||
|
||||
typedef struct AttributeAndDefgroupUniqueNameData {
|
||||
struct ID *id;
|
||||
struct bDeformGroup *dg;
|
||||
} AttributeAndDefgroupUniqueNameData;
|
||||
|
||||
bool BKE_id_attribute_and_defgroup_unique_name_check(void *arg, const char *name);
|
||||
bool BKE_id_attribute_calc_unique_name(struct ID *id, const char *name, char *outname);
|
||||
|
||||
const char *BKE_uv_map_vert_select_name_get(const char *uv_map_name, char *buffer);
|
||||
|
|
|
@ -89,6 +89,7 @@ int *BKE_object_defgroup_flip_map_single(const struct Object *ob,
|
|||
int BKE_object_defgroup_flip_index(const struct Object *ob, int index, bool use_default);
|
||||
int BKE_object_defgroup_name_index(const struct Object *ob, const char *name);
|
||||
void BKE_object_defgroup_unique_name(struct bDeformGroup *dg, struct Object *ob);
|
||||
bool BKE_defgroup_unique_name_check(void *arg, const char *name);
|
||||
|
||||
struct MDeformWeight *BKE_defvert_find_index(const struct MDeformVert *dv, int defgroup);
|
||||
/**
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "BKE_attribute.hh"
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_deform.h"
|
||||
#include "BKE_editmesh.h"
|
||||
#include "BKE_mesh.hh"
|
||||
#include "BKE_pointcloud.h"
|
||||
|
@ -223,13 +224,14 @@ bool BKE_id_attribute_rename(ID *id,
|
|||
return true;
|
||||
}
|
||||
|
||||
struct AttrUniqueData {
|
||||
ID *id;
|
||||
};
|
||||
|
||||
static bool unique_name_cb(void *arg, const char *name)
|
||||
bool BKE_id_attribute_and_defgroup_unique_name_check(void *arg, const char *name)
|
||||
{
|
||||
AttrUniqueData *data = (AttrUniqueData *)arg;
|
||||
AttributeAndDefgroupUniqueNameData *data = static_cast<AttributeAndDefgroupUniqueNameData *>(
|
||||
arg);
|
||||
|
||||
if (BKE_defgroup_unique_name_check(data, name)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
DomainInfo info[ATTR_DOMAIN_NUM];
|
||||
get_domains(data->id, info);
|
||||
|
@ -254,15 +256,18 @@ static bool unique_name_cb(void *arg, const char *name)
|
|||
|
||||
bool BKE_id_attribute_calc_unique_name(ID *id, const char *name, char *outname)
|
||||
{
|
||||
AttrUniqueData data{id};
|
||||
AttributeAndDefgroupUniqueNameData data{id, nullptr};
|
||||
|
||||
const int name_maxncpy = CustomData_name_maxncpy_calc(name);
|
||||
|
||||
/* Set default name if none specified.
|
||||
* NOTE: We only call IFACE_() if needed to avoid locale lookup overhead. */
|
||||
BLI_strncpy_utf8(outname, (name && name[0]) ? name : IFACE_("Attribute"), name_maxncpy);
|
||||
|
||||
/* Avoid name collisions with vertex groups and other attributes. */
|
||||
const char *defname = ""; /* Dummy argument, never used as `name` is never zero length. */
|
||||
return BLI_uniquename_cb(unique_name_cb, &data, defname, '.', outname, name_maxncpy);
|
||||
return BLI_uniquename_cb(
|
||||
BKE_id_attribute_and_defgroup_unique_name_check, &data, defname, '.', outname, name_maxncpy);
|
||||
}
|
||||
|
||||
CustomDataLayer *BKE_id_attribute_new(ID *id,
|
||||
|
@ -301,6 +306,10 @@ CustomDataLayer *BKE_id_attribute_new(ID *id,
|
|||
attributes->add(uniquename, domain, eCustomDataType(type), AttributeInitDefaultValue());
|
||||
|
||||
const int index = CustomData_get_named_layer_index(customdata, type, uniquename);
|
||||
if (index == -1) {
|
||||
BKE_reportf(reports, RPT_WARNING, "Layer '%s' could not be created", uniquename);
|
||||
}
|
||||
|
||||
return (index == -1) ? nullptr : &(customdata->layers[index]);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_data_transfer.h"
|
||||
#include "BKE_deform.h" /* own include */
|
||||
|
@ -681,9 +682,9 @@ int BKE_object_defgroup_flip_index(const Object *ob, int index, const bool use_d
|
|||
return (flip_index == -1 && use_default) ? index : flip_index;
|
||||
}
|
||||
|
||||
static bool defgroup_find_name_dupe(const char *name, bDeformGroup *dg, Object *ob)
|
||||
static bool defgroup_find_name_dupe(const char *name, bDeformGroup *dg, ID *id)
|
||||
{
|
||||
const ListBase *defbase = BKE_object_defgroup_list(ob);
|
||||
const ListBase *defbase = BKE_id_defgroup_list_get(id);
|
||||
|
||||
LISTBASE_FOREACH (bDeformGroup *, curdef, defbase) {
|
||||
if (dg != curdef) {
|
||||
|
@ -696,21 +697,31 @@ static bool defgroup_find_name_dupe(const char *name, bDeformGroup *dg, Object *
|
|||
return false;
|
||||
}
|
||||
|
||||
struct DeformGroupUniqueNameData {
|
||||
Object *ob;
|
||||
bDeformGroup *dg;
|
||||
};
|
||||
|
||||
static bool defgroup_unique_check(void *arg, const char *name)
|
||||
bool BKE_defgroup_unique_name_check(void *arg, const char *name)
|
||||
{
|
||||
DeformGroupUniqueNameData *data = static_cast<DeformGroupUniqueNameData *>(arg);
|
||||
return defgroup_find_name_dupe(name, data->dg, data->ob);
|
||||
AttributeAndDefgroupUniqueNameData *data = static_cast<AttributeAndDefgroupUniqueNameData *>(
|
||||
arg);
|
||||
return defgroup_find_name_dupe(name, data->dg, data->id);
|
||||
}
|
||||
|
||||
void BKE_object_defgroup_unique_name(bDeformGroup *dg, Object *ob)
|
||||
{
|
||||
DeformGroupUniqueNameData data{ob, dg};
|
||||
BLI_uniquename_cb(defgroup_unique_check, &data, DATA_("Group"), '.', dg->name, sizeof(dg->name));
|
||||
/* Avoid name collisions with other vertex groups and (mesh) attributes. */
|
||||
if (ob->type == OB_MESH) {
|
||||
Mesh *me = static_cast<Mesh *>(ob->data);
|
||||
AttributeAndDefgroupUniqueNameData data{&me->id, dg};
|
||||
BLI_uniquename_cb(BKE_id_attribute_and_defgroup_unique_name_check,
|
||||
&data,
|
||||
DATA_("Group"),
|
||||
'.',
|
||||
dg->name,
|
||||
sizeof(dg->name));
|
||||
}
|
||||
else {
|
||||
AttributeAndDefgroupUniqueNameData data{static_cast<ID *>(ob->data), dg};
|
||||
BLI_uniquename_cb(
|
||||
BKE_defgroup_unique_name_check, &data, DATA_("Group"), '.', dg->name, sizeof(dg->name));
|
||||
}
|
||||
}
|
||||
|
||||
float BKE_defvert_find_weight(const MDeformVert *dvert, const int defgroup)
|
||||
|
|
|
@ -1728,6 +1728,14 @@ void GreasePencil::set_active_layer(const blender::bke::greasepencil::Layer *lay
|
|||
reinterpret_cast<const GreasePencilLayer *>(layer));
|
||||
}
|
||||
|
||||
bool GreasePencil::is_layer_active(const blender::bke::greasepencil::Layer *layer) const
|
||||
{
|
||||
if (layer == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return this->get_active_layer() == layer;
|
||||
}
|
||||
|
||||
static blender::VectorSet<blender::StringRefNull> get_node_names(GreasePencil &grease_pencil)
|
||||
{
|
||||
using namespace blender;
|
||||
|
|
|
@ -4571,6 +4571,9 @@ void BKE_lib_override_library_id_unused_cleanup(ID *local)
|
|||
BKE_lib_override_library_property_operation_delete(op, opop);
|
||||
}
|
||||
}
|
||||
if (BLI_listbase_is_empty(&op->operations)) {
|
||||
BKE_lib_override_library_property_delete(local->override_library, op);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,11 @@ MINLINE float safe_modf(float a, float b)
|
|||
return (b != 0.0f) ? fmodf(a, b) : 0.0f;
|
||||
}
|
||||
|
||||
MINLINE float safe_floored_modf(float a, float b)
|
||||
{
|
||||
return (b != 0.0f) ? a - floorf(a / b) * b : 0.0f;
|
||||
}
|
||||
|
||||
MINLINE float safe_logf(float a, float base)
|
||||
{
|
||||
if (UNLIKELY(a <= 0.0f || base <= 0.0f)) {
|
||||
|
|
|
@ -126,6 +126,7 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
|
|||
*/
|
||||
{
|
||||
/* Keep this block, even when empty. */
|
||||
FROM_DEFAULT_V4_UCHAR(space_sequencer.transition);
|
||||
}
|
||||
|
||||
#undef FROM_DEFAULT_V4_UCHAR
|
||||
|
|
|
@ -76,6 +76,9 @@ void MathNode::convert_to_operations(NodeConverter &converter,
|
|||
case NODE_MATH_MODULO:
|
||||
operation = new MathModuloOperation();
|
||||
break;
|
||||
case NODE_MATH_FLOORED_MODULO:
|
||||
operation = new MathFlooredModuloOperation();
|
||||
break;
|
||||
case NODE_MATH_ABSOLUTE:
|
||||
operation = new MathAbsoluteOperation();
|
||||
break;
|
||||
|
|
|
@ -58,8 +58,7 @@ void KuwaharaAnisotropicOperation::execute_pixel_sampled(float output[4],
|
|||
const float q = 3.0;
|
||||
const float EPS = 1.0e-10;
|
||||
|
||||
/* For now use green channel to compute orientation. */
|
||||
/* TODO: convert to HSV and compute orientation and strength on luminance channel */
|
||||
/* All channels are identical. Take first channel for simplicity. */
|
||||
float tmp[4];
|
||||
s_xx_reader_->read(tmp, x, y, nullptr);
|
||||
const float a = tmp[1];
|
||||
|
|
|
@ -589,6 +589,36 @@ void MathModuloOperation::update_memory_buffer_partial(BuffersIterator<float> &i
|
|||
}
|
||||
}
|
||||
|
||||
void MathFlooredModuloOperation::execute_pixel_sampled(float output[4],
|
||||
float x,
|
||||
float y,
|
||||
PixelSampler sampler)
|
||||
{
|
||||
float input_value1[4];
|
||||
float input_value2[4];
|
||||
|
||||
input_value1_operation_->read_sampled(input_value1, x, y, sampler);
|
||||
input_value2_operation_->read_sampled(input_value2, x, y, sampler);
|
||||
|
||||
if (input_value2[0] == 0) {
|
||||
output[0] = 0.0;
|
||||
}
|
||||
else {
|
||||
output[0] = input_value1[0] - floorf(input_value1[0] / input_value2[0]) * input_value2[0];
|
||||
}
|
||||
|
||||
clamp_if_needed(output);
|
||||
}
|
||||
|
||||
void MathFlooredModuloOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
|
||||
{
|
||||
for (; !it.is_end(); ++it) {
|
||||
const float value2 = *it.in(1);
|
||||
*it.out = (value2 == 0) ? 0 : *it.in(0) - floorf(*it.in(0) / value2) * value2;
|
||||
clamp_when_enabled(it.out);
|
||||
}
|
||||
}
|
||||
|
||||
void MathAbsoluteOperation::execute_pixel_sampled(float output[4],
|
||||
float x,
|
||||
float y,
|
||||
|
|
|
@ -224,6 +224,14 @@ class MathModuloOperation : public MathBaseOperation {
|
|||
void update_memory_buffer_partial(BuffersIterator<float> &it) override;
|
||||
};
|
||||
|
||||
class MathFlooredModuloOperation : public MathBaseOperation {
|
||||
public:
|
||||
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
protected:
|
||||
void update_memory_buffer_partial(BuffersIterator<float> &it) override;
|
||||
};
|
||||
|
||||
class MathAbsoluteOperation : public MathBaseOperation {
|
||||
public:
|
||||
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "BKE_context.h"
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_gpencil_legacy.h"
|
||||
#include "BKE_grease_pencil.hh"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_node.h"
|
||||
|
||||
|
@ -291,9 +292,10 @@ void ANIM_sync_animchannels_to_data(const bContext *C)
|
|||
animchan_sync_gplayer(ale);
|
||||
break;
|
||||
case ANIMTYPE_GREASE_PENCIL_LAYER:
|
||||
using namespace blender::bke::greasepencil;
|
||||
GreasePencil *grease_pencil = reinterpret_cast<GreasePencil *>(ale->id);
|
||||
GreasePencilLayer *layer = static_cast<GreasePencilLayer *>(ale->data);
|
||||
if (grease_pencil->active_layer == layer) {
|
||||
Layer *layer = static_cast<Layer *>(ale->data);
|
||||
if (grease_pencil->is_layer_active(layer)) {
|
||||
layer->base.flag |= GP_LAYER_TREE_NODE_SELECT;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -1767,7 +1767,7 @@ static size_t animdata_filter_grease_pencil_layers_data(ListBase *anim_data,
|
|||
}
|
||||
|
||||
/* Only if the layer is active. */
|
||||
if ((filter_mode & ANIMFILTER_ACTIVE) && (grease_pencil->active_layer == layer)) {
|
||||
if ((filter_mode & ANIMFILTER_ACTIVE) && grease_pencil->is_layer_active(layer)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -196,6 +196,7 @@ enum ThemeColorID {
|
|||
TH_SEQ_SCENE,
|
||||
TH_SEQ_AUDIO,
|
||||
TH_SEQ_EFFECT,
|
||||
TH_SEQ_TRANSITION,
|
||||
TH_SEQ_META,
|
||||
TH_SEQ_TEXT,
|
||||
TH_SEQ_PREVIEW,
|
||||
|
|
|
@ -691,6 +691,9 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
|
|||
case TH_SEQ_EFFECT:
|
||||
cp = ts->effect;
|
||||
break;
|
||||
case TH_SEQ_TRANSITION:
|
||||
cp = ts->transition;
|
||||
break;
|
||||
case TH_SEQ_META:
|
||||
cp = ts->meta;
|
||||
break;
|
||||
|
|
|
@ -150,9 +150,15 @@ void color3ubv_from_seq(const Scene *curscene,
|
|||
case SEQ_TYPE_CROSS:
|
||||
case SEQ_TYPE_GAMCROSS:
|
||||
case SEQ_TYPE_WIPE:
|
||||
r_col[0] = 130;
|
||||
r_col[1] = 130;
|
||||
r_col[2] = 130;
|
||||
UI_GetThemeColor3ubv(TH_SEQ_TRANSITION, r_col);
|
||||
|
||||
/* Slightly offset hue to distinguish different transition types. */
|
||||
if (seq->type == SEQ_TYPE_GAMCROSS) {
|
||||
rgb_byte_set_hue_float_offset(r_col, 0.03);
|
||||
}
|
||||
else if (seq->type == SEQ_TYPE_WIPE) {
|
||||
rgb_byte_set_hue_float_offset(r_col, 0.06);
|
||||
}
|
||||
break;
|
||||
|
||||
/* Effects. */
|
||||
|
@ -642,7 +648,7 @@ static void draw_seq_handle(const Scene *scene,
|
|||
uint pos,
|
||||
bool seq_active,
|
||||
float pixelx,
|
||||
bool y_threshold)
|
||||
const bool draw_strip_preview)
|
||||
{
|
||||
float rx1 = 0, rx2 = 0;
|
||||
float x1, x2, y1, y2;
|
||||
|
@ -693,7 +699,7 @@ static void draw_seq_handle(const Scene *scene,
|
|||
}
|
||||
|
||||
/* Draw numbers for start and end of the strip next to its handles. */
|
||||
if (y_threshold &&
|
||||
if (draw_strip_preview &&
|
||||
(((seq->flag & SELECT) && (G.moving & G_TRANSFORM_SEQ)) || (seq->flag & whichsel)))
|
||||
{
|
||||
|
||||
|
@ -988,6 +994,21 @@ static void draw_sequence_extensions_overlay(
|
|||
GPU_blend(GPU_BLEND_NONE);
|
||||
}
|
||||
|
||||
static uchar mute_overlap_alpha_factor_get(const ListBase *channels, const Sequence *seq)
|
||||
{
|
||||
/* Draw muted strips semi-transparent. */
|
||||
if (SEQ_render_is_muted(channels, seq)) {
|
||||
return MUTE_ALPHA;
|
||||
}
|
||||
/* Draw background semi-transparent when overlapping strips. */
|
||||
else if (seq->flag & SEQ_OVERLAP) {
|
||||
return OVERLAP_ALPHA;
|
||||
}
|
||||
else {
|
||||
return 255;
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_color_strip_band(
|
||||
const Scene *scene, ListBase *channels, Sequence *seq, uint pos, float text_margin_y, float y1)
|
||||
{
|
||||
|
@ -997,17 +1018,7 @@ static void draw_color_strip_band(
|
|||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
rgb_float_to_uchar(col, colvars->col);
|
||||
|
||||
/* Draw muted strips semi-transparent. */
|
||||
if (SEQ_render_is_muted(channels, seq)) {
|
||||
col[3] = MUTE_ALPHA;
|
||||
}
|
||||
/* Draw background semi-transparent when overlapping strips. */
|
||||
else if (seq->flag & SEQ_OVERLAP) {
|
||||
col[3] = OVERLAP_ALPHA;
|
||||
}
|
||||
else {
|
||||
col[3] = 255;
|
||||
}
|
||||
col[3] = mute_overlap_alpha_factor_get(channels, seq);
|
||||
|
||||
immUniformColor4ubv(col);
|
||||
|
||||
|
@ -1044,32 +1055,9 @@ static void draw_seq_background(Scene *scene,
|
|||
uchar col[4];
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
|
||||
/* Get the correct color per strip type, transitions use their inputs ones. */
|
||||
if (ELEM(seq->type, SEQ_TYPE_CROSS, SEQ_TYPE_GAMCROSS, SEQ_TYPE_WIPE)) {
|
||||
Sequence *seq1 = seq->seq1;
|
||||
if (seq1->type == SEQ_TYPE_COLOR) {
|
||||
SolidColorVars *colvars = (SolidColorVars *)seq1->effectdata;
|
||||
rgb_float_to_uchar(col, colvars->col);
|
||||
}
|
||||
else {
|
||||
color3ubv_from_seq(scene, seq1, show_strip_color_tag, col);
|
||||
}
|
||||
}
|
||||
else {
|
||||
color3ubv_from_seq(scene, seq, show_strip_color_tag, col);
|
||||
}
|
||||
color3ubv_from_seq(scene, seq, show_strip_color_tag, col);
|
||||
|
||||
/* Draw muted strips semi-transparent. */
|
||||
if (SEQ_render_is_muted(channels, seq)) {
|
||||
col[3] = MUTE_ALPHA;
|
||||
}
|
||||
/* Draw background semi-transparent when overlapping strips. */
|
||||
else if (seq->flag & SEQ_OVERLAP) {
|
||||
col[3] = OVERLAP_ALPHA;
|
||||
}
|
||||
else {
|
||||
col[3] = 255;
|
||||
}
|
||||
col[3] = mute_overlap_alpha_factor_get(channels, seq);
|
||||
|
||||
immUniformColor4ubv(col);
|
||||
|
||||
|
@ -1102,39 +1090,95 @@ static void draw_seq_background(Scene *scene,
|
|||
}
|
||||
}
|
||||
|
||||
/* Draw right half of transition strips. */
|
||||
if (ELEM(seq->type, SEQ_TYPE_CROSS, SEQ_TYPE_GAMCROSS, SEQ_TYPE_WIPE)) {
|
||||
float vert_pos[3][2];
|
||||
Sequence *seq1 = seq->seq1;
|
||||
Sequence *seq2 = seq->seq2;
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
}
|
||||
|
||||
if (seq2->type == SEQ_TYPE_COLOR) {
|
||||
SolidColorVars *colvars = (SolidColorVars *)seq2->effectdata;
|
||||
rgb_float_to_uchar(col, colvars->col);
|
||||
}
|
||||
else {
|
||||
color3ubv_from_seq(scene, seq2, show_strip_color_tag, col);
|
||||
/* If the transition inputs are of the same type, draw the right side slightly darker. */
|
||||
if (seq1->type == seq2->type) {
|
||||
UI_GetColorPtrShade3ubv(col, col, -15);
|
||||
}
|
||||
}
|
||||
immUniformColor4ubv(col);
|
||||
typedef enum {
|
||||
STRIP_TRANSITION_IN,
|
||||
STRIP_TRANSITION_OUT,
|
||||
} TransitionType;
|
||||
|
||||
static void draw_seq_transition_strip_half(const Scene *scene,
|
||||
const Sequence *transition_seq,
|
||||
const float x1,
|
||||
const float x2,
|
||||
const float y1,
|
||||
const float y2,
|
||||
const int timeline_overlay_flags,
|
||||
const TransitionType transition_type)
|
||||
{
|
||||
Editing *ed = SEQ_editing_get(scene);
|
||||
const ListBase *channels = SEQ_channels_displayed_get(ed);
|
||||
|
||||
const Sequence *seq1 = transition_seq->seq1;
|
||||
const Sequence *seq2 = transition_seq->seq2;
|
||||
const Sequence *target_seq = (transition_type == STRIP_TRANSITION_IN) ? seq1 : seq2;
|
||||
|
||||
const bool show_strip_color_tag = (timeline_overlay_flags & SEQ_TIMELINE_SHOW_STRIP_COLOR_TAG);
|
||||
|
||||
float col[4];
|
||||
if (target_seq->type == SEQ_TYPE_COLOR) {
|
||||
SolidColorVars *colvars = (SolidColorVars *)target_seq->effectdata;
|
||||
memcpy(col, colvars->col, sizeof(colvars->col));
|
||||
}
|
||||
else {
|
||||
uchar ucol[3];
|
||||
color3ubv_from_seq(scene, target_seq, show_strip_color_tag, ucol);
|
||||
/* If the transition inputs are of the same type, draw the right side slightly darker. */
|
||||
if ((seq1->type == seq2->type) && (transition_type == STRIP_TRANSITION_OUT)) {
|
||||
UI_GetColorPtrShade3ubv(ucol, ucol, -15);
|
||||
}
|
||||
rgb_uchar_to_float(col, ucol);
|
||||
}
|
||||
|
||||
col[3] = mute_overlap_alpha_factor_get(channels, transition_seq) / 255.0f;
|
||||
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
|
||||
const uint pos = GPU_vertformat_attr_add(
|
||||
immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
|
||||
immUniformColor4fv(col);
|
||||
|
||||
float vert_pos[3][2];
|
||||
|
||||
if (transition_type == STRIP_TRANSITION_IN) {
|
||||
copy_v2_fl2(vert_pos[0], x1, y1);
|
||||
copy_v2_fl2(vert_pos[1], x1, y2);
|
||||
copy_v2_fl2(vert_pos[2], x2, y1);
|
||||
}
|
||||
else {
|
||||
copy_v2_fl2(vert_pos[0], x1, y2);
|
||||
copy_v2_fl2(vert_pos[1], x2, y2);
|
||||
copy_v2_fl2(vert_pos[2], x2, y1);
|
||||
|
||||
immBegin(GPU_PRIM_TRIS, 3);
|
||||
immVertex2fv(pos, vert_pos[0]);
|
||||
immVertex2fv(pos, vert_pos[1]);
|
||||
immVertex2fv(pos, vert_pos[2]);
|
||||
immEnd();
|
||||
}
|
||||
|
||||
immBegin(GPU_PRIM_TRIS, 3);
|
||||
immVertex2fv(pos, vert_pos[0]);
|
||||
immVertex2fv(pos, vert_pos[1]);
|
||||
immVertex2fv(pos, vert_pos[2]);
|
||||
immEnd();
|
||||
|
||||
immUnbindProgram();
|
||||
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
}
|
||||
|
||||
static void draw_seq_transition_strip(const Scene *scene,
|
||||
const Sequence *seq,
|
||||
const float x1,
|
||||
const float x2,
|
||||
const float y1,
|
||||
const float y2,
|
||||
const int timeline_overlay_flags)
|
||||
{
|
||||
draw_seq_transition_strip_half(
|
||||
scene, seq, x1, x2, y1, y2, timeline_overlay_flags, STRIP_TRANSITION_IN);
|
||||
draw_seq_transition_strip_half(
|
||||
scene, seq, x1, x2, y1, y2, timeline_overlay_flags, STRIP_TRANSITION_OUT);
|
||||
}
|
||||
|
||||
static void draw_seq_locked(float x1, float y1, float x2, float y2)
|
||||
{
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
|
@ -1327,7 +1371,14 @@ static void draw_seq_strip(const bContext *C,
|
|||
x2 = max_ff(x2, SEQ_time_left_handle_frame_get(scene, seq));
|
||||
|
||||
float text_margin_y;
|
||||
bool y_threshold;
|
||||
/* Whether there is enough space for the strip preview. */
|
||||
const bool draw_strip_preview = ((y2 - y1) / pixely) > 20 * UI_SCALE_FAC;
|
||||
/* If there is not enough vertical space, don't draw any previews nor the title. */
|
||||
const bool strip_content_none = (y2 - y1) < 8 * pixely * UI_SCALE_FAC;
|
||||
/* Only a single vertical element is drawn on the strip: the waveform in the case of
|
||||
* sound strips, or the strip title for most other strip types. */
|
||||
bool strip_content_single;
|
||||
|
||||
if ((sseq->timeline_overlay.flag & SEQ_TIMELINE_SHOW_STRIP_NAME) ||
|
||||
(sseq->timeline_overlay.flag & SEQ_TIMELINE_SHOW_STRIP_SOURCE) ||
|
||||
(sseq->timeline_overlay.flag & SEQ_TIMELINE_SHOW_STRIP_DURATION))
|
||||
|
@ -1336,13 +1387,16 @@ static void draw_seq_strip(const bContext *C,
|
|||
/* Calculate height needed for drawing text on strip. */
|
||||
text_margin_y = y2 - min_ff(0.40f, 20 * UI_SCALE_FAC * pixely);
|
||||
|
||||
/* Is there enough space for drawing something else than text? */
|
||||
y_threshold = ((y2 - y1) / pixely) > 20 * UI_SCALE_FAC;
|
||||
strip_content_single = !draw_strip_preview;
|
||||
}
|
||||
else {
|
||||
text_margin_y = y2;
|
||||
y_threshold = false;
|
||||
strip_content_single = true;
|
||||
}
|
||||
/* When a text overlay is enabled and there is space for both the text and the strip content,
|
||||
* draw below the text. */
|
||||
/* When text is disabled or there is space for only one or the other, use entire strip area. */
|
||||
const float strip_preview_y2 = strip_content_single ? y2 : text_margin_y;
|
||||
|
||||
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
|
@ -1350,8 +1404,8 @@ static void draw_seq_strip(const bContext *C,
|
|||
draw_seq_background(scene, seq, pos, x1, x2, y1, y2, is_single_image, show_strip_color_tag);
|
||||
|
||||
/* Draw a color band inside color strip. */
|
||||
if (seq->type == SEQ_TYPE_COLOR && y_threshold) {
|
||||
draw_color_strip_band(scene, channels, seq, pos, text_margin_y, y1);
|
||||
if ((sseq->flag & SEQ_SHOW_OVERLAY) && (seq->type == SEQ_TYPE_COLOR)) {
|
||||
draw_color_strip_band(scene, channels, seq, pos, strip_preview_y2, y1);
|
||||
}
|
||||
|
||||
/* Draw strip offsets when flag is enabled or during "solo preview". */
|
||||
|
@ -1365,32 +1419,41 @@ static void draw_seq_strip(const bContext *C,
|
|||
}
|
||||
immUnbindProgram();
|
||||
|
||||
if (draw_strip_preview && (sseq->flag & SEQ_SHOW_OVERLAY) &&
|
||||
ELEM(seq->type, SEQ_TYPE_CROSS, SEQ_TYPE_GAMCROSS, SEQ_TYPE_WIPE))
|
||||
{
|
||||
draw_seq_transition_strip(
|
||||
scene, seq, x1, x2, y1, strip_preview_y2, sseq->timeline_overlay.flag);
|
||||
}
|
||||
|
||||
x1 = SEQ_time_left_handle_frame_get(scene, seq);
|
||||
x2 = SEQ_time_right_handle_frame_get(scene, seq);
|
||||
|
||||
if ((seq->type == SEQ_TYPE_META) ||
|
||||
((seq->type == SEQ_TYPE_SCENE) && (seq->flag & SEQ_SCENE_STRIPS)))
|
||||
{
|
||||
drawmeta_contents(scene, seq, x1, y1, x2, y2, show_strip_color_tag);
|
||||
if (draw_strip_preview && (sseq->flag & SEQ_SHOW_OVERLAY)) {
|
||||
if ((seq->type == SEQ_TYPE_META) ||
|
||||
((seq->type == SEQ_TYPE_SCENE) && (seq->flag & SEQ_SCENE_STRIPS)))
|
||||
{
|
||||
drawmeta_contents(scene, seq, x1, y1, x2, strip_preview_y2, show_strip_color_tag);
|
||||
}
|
||||
}
|
||||
|
||||
if ((sseq->flag & SEQ_SHOW_OVERLAY) &&
|
||||
(sseq->timeline_overlay.flag & SEQ_TIMELINE_SHOW_THUMBNAILS) &&
|
||||
ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE))
|
||||
{
|
||||
draw_seq_strip_thumbnail(
|
||||
v2d, C, scene, seq, y1, y_threshold ? text_margin_y : y2, pixelx, pixely);
|
||||
draw_seq_strip_thumbnail(v2d, C, scene, seq, y1, strip_preview_y2, pixelx, pixely);
|
||||
}
|
||||
|
||||
if ((sseq->flag & SEQ_SHOW_OVERLAY) && (sseq->timeline_overlay.flag & SEQ_TIMELINE_SHOW_FCURVES))
|
||||
if (draw_strip_preview && (sseq->flag & SEQ_SHOW_OVERLAY) &&
|
||||
(sseq->timeline_overlay.flag & SEQ_TIMELINE_SHOW_FCURVES))
|
||||
{
|
||||
draw_seq_fcurve_overlay(scene, v2d, seq, x1, y1, x2, y2, pixelx);
|
||||
draw_seq_fcurve_overlay(scene, v2d, seq, x1, y1, x2, strip_preview_y2, pixelx);
|
||||
}
|
||||
|
||||
/* Draw sound strip waveform. */
|
||||
if (seq_draw_waveforms_poll(C, sseq, seq)) {
|
||||
if (seq_draw_waveforms_poll(C, sseq, seq) && !strip_content_none) {
|
||||
draw_seq_waveform_overlay(
|
||||
C, region, seq, x1, y_threshold ? y1 + 0.05f : y1, x2, y_threshold ? text_margin_y : y2);
|
||||
C, region, seq, x1, strip_content_single ? y1 : y1 + 0.05f, x2, strip_preview_y2);
|
||||
}
|
||||
/* Draw locked state. */
|
||||
if (SEQ_transform_is_locked(channels, seq)) {
|
||||
|
@ -1406,34 +1469,51 @@ static void draw_seq_strip(const bContext *C,
|
|||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
|
||||
if (!SEQ_transform_is_locked(channels, seq)) {
|
||||
draw_seq_handle(
|
||||
scene, v2d, seq, handsize_clamped, SEQ_LEFTHANDLE, pos, seq_active, pixelx, y_threshold);
|
||||
draw_seq_handle(
|
||||
scene, v2d, seq, handsize_clamped, SEQ_RIGHTHANDLE, pos, seq_active, pixelx, y_threshold);
|
||||
draw_seq_handle(scene,
|
||||
v2d,
|
||||
seq,
|
||||
handsize_clamped,
|
||||
SEQ_LEFTHANDLE,
|
||||
pos,
|
||||
seq_active,
|
||||
pixelx,
|
||||
draw_strip_preview);
|
||||
draw_seq_handle(scene,
|
||||
v2d,
|
||||
seq,
|
||||
handsize_clamped,
|
||||
SEQ_RIGHTHANDLE,
|
||||
pos,
|
||||
seq_active,
|
||||
pixelx,
|
||||
draw_strip_preview);
|
||||
}
|
||||
|
||||
draw_seq_outline(scene, seq, pos, x1, x2, y1, y2, pixelx, pixely, seq_active);
|
||||
|
||||
immUnbindProgram();
|
||||
|
||||
calculate_seq_text_offsets(scene, v2d, seq, &x1, &x2, pixelx);
|
||||
|
||||
/* If a waveform is drawn, avoid drawing text when there is not enough vertical space. */
|
||||
if (seq->type == SEQ_TYPE_SOUND_RAM) {
|
||||
if (!y_threshold && (sseq->timeline_overlay.flag & SEQ_TIMELINE_NO_WAVEFORMS) == 0 &&
|
||||
((sseq->timeline_overlay.flag & SEQ_TIMELINE_ALL_WAVEFORMS) ||
|
||||
(seq->flag & SEQ_AUDIO_DRAW_WAVEFORM)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
/* If a waveform or a color strip is drawn,
|
||||
* avoid drawing text when there is not enough vertical space. */
|
||||
if (strip_content_single &&
|
||||
(seq_draw_waveforms_poll(C, sseq, seq) || seq->type == SEQ_TYPE_COLOR)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sseq->flag & SEQ_SHOW_OVERLAY) {
|
||||
/* Don't draw strip if there is not enough vertical or horizontal space. */
|
||||
if (((x2 - x1) > 32 * pixelx * UI_SCALE_FAC) && ((y2 - y1) > 8 * pixely * UI_SCALE_FAC)) {
|
||||
/* Draw text only if there is enough horizontal or vertical space. */
|
||||
if (((x2 - x1) > 32 * pixelx * UI_SCALE_FAC) && !strip_content_none) {
|
||||
calculate_seq_text_offsets(scene, v2d, seq, &x1, &x2, pixelx);
|
||||
/* Depending on the vertical space, draw text on top or in the center of strip. */
|
||||
draw_seq_text_overlay(
|
||||
scene, v2d, seq, sseq, x1, x2, y_threshold ? text_margin_y : y1, y2, seq_active);
|
||||
draw_seq_text_overlay(scene,
|
||||
v2d,
|
||||
seq,
|
||||
sseq,
|
||||
x1,
|
||||
x2,
|
||||
strip_content_single ? y1 : text_margin_y,
|
||||
y2,
|
||||
seq_active);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -650,7 +650,9 @@ static bool transform_modal_item_poll(const wmOperator *op, int value)
|
|||
return false;
|
||||
}
|
||||
if (value == TFM_MODAL_RESIZE && t->mode == TFM_RESIZE) {
|
||||
return false;
|
||||
/* The tracking transform in MovieClip has an alternate resize that only affects the
|
||||
* tracker size and not the search area. */
|
||||
return t->data_type == &TransConvertType_Tracking;
|
||||
}
|
||||
if (value == TFM_MODAL_VERT_EDGE_SLIDE &&
|
||||
(t->data_type != &TransConvertType_Mesh ||
|
||||
|
|
|
@ -481,7 +481,7 @@ static void flushTransTracking(TransInfo *t)
|
|||
|
||||
if (t->flag & T_ALT_TRANSFORM) {
|
||||
if (t->mode == TFM_RESIZE) {
|
||||
if (tdt->area != TRACK_AREA_PAT) {
|
||||
if (tdt->area != TRACK_AREA_PAT && !(t->state == TRANS_CANCEL)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,6 +111,11 @@ void math_modulo(float a, float b, float c, out float result)
|
|||
result = compatible_fmod(a, b);
|
||||
}
|
||||
|
||||
void math_floored_modulo(float a, float b, float c, out float result)
|
||||
{
|
||||
result = (b != 0.0) ? a - floor(a / b) * b : 0.0;
|
||||
}
|
||||
|
||||
void math_trunc(float a, float b, float c, out float result)
|
||||
{
|
||||
result = trunc(a);
|
||||
|
|
|
@ -239,6 +239,8 @@ void imb_filetypes_init()
|
|||
{
|
||||
const ImFileType *type;
|
||||
|
||||
OIIO_init();
|
||||
|
||||
for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
|
||||
if (type->init) {
|
||||
type->init();
|
||||
|
|
|
@ -7,12 +7,24 @@
|
|||
*/
|
||||
|
||||
#include "openimageio_api.h"
|
||||
|
||||
#include <OpenImageIO/imageio.h>
|
||||
|
||||
#include "BLI_threads.h"
|
||||
|
||||
OIIO_NAMESPACE_USING
|
||||
|
||||
extern "C" {
|
||||
|
||||
void OIIO_init()
|
||||
{
|
||||
/* Make OIIO thread pool follow Blender number of threads override. */
|
||||
const int threads_override = BLI_system_num_threads_override_get();
|
||||
if (threads_override) {
|
||||
OIIO::attribute("threads", threads_override);
|
||||
}
|
||||
}
|
||||
|
||||
int OIIO_getVersionHex()
|
||||
{
|
||||
return openimageio_version();
|
||||
|
|
|
@ -12,6 +12,14 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialize OpenImageIO on startup.
|
||||
*/
|
||||
void OIIO_init(void);
|
||||
|
||||
/*
|
||||
* Get OpenImageIO version.
|
||||
*/
|
||||
int OIIO_getVersionHex(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -86,6 +86,7 @@ set(SRC
|
|||
intern/usd_capi_export.cc
|
||||
intern/usd_capi_import.cc
|
||||
intern/usd_hierarchy_iterator.cc
|
||||
intern/usd_hook.cc
|
||||
intern/usd_writer_abstract.cc
|
||||
intern/usd_writer_camera.cc
|
||||
intern/usd_writer_curves.cc
|
||||
|
@ -116,6 +117,7 @@ set(SRC
|
|||
intern/usd_asset_utils.h
|
||||
intern/usd_exporter_context.h
|
||||
intern/usd_hierarchy_iterator.h
|
||||
intern/usd_hook.h
|
||||
intern/usd_writer_abstract.h
|
||||
intern/usd_writer_camera.h
|
||||
intern/usd_writer_curves.h
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "usd.h"
|
||||
#include "usd.hh"
|
||||
#include "usd_hierarchy_iterator.h"
|
||||
#include "usd_hook.h"
|
||||
|
||||
#include <pxr/base/plug/registry.h>
|
||||
#include <pxr/pxr.h>
|
||||
|
@ -228,6 +229,9 @@ static pxr::UsdStageRefPtr export_to_stage(const USDExportParams ¶ms,
|
|||
/* For restoring the current frame after exporting animation is done. */
|
||||
const int orig_frame = scene->r.cfra;
|
||||
|
||||
/* Ensure Python types for invoking export hooks are registered. */
|
||||
register_export_hook_converters();
|
||||
|
||||
usd_stage->SetMetadata(pxr::UsdGeomTokens->upAxis, pxr::VtValue(pxr::UsdGeomTokens->z));
|
||||
ensure_root_prim(usd_stage, params);
|
||||
|
||||
|
@ -275,6 +279,8 @@ static pxr::UsdStageRefPtr export_to_stage(const USDExportParams ¶ms,
|
|||
}
|
||||
}
|
||||
|
||||
call_export_hooks(usd_stage, depsgraph);
|
||||
|
||||
/* Finish up by going back to the keyframe that was current before we started. */
|
||||
if (scene->r.cfra != orig_frame) {
|
||||
scene->r.cfra = orig_frame;
|
||||
|
|
|
@ -0,0 +1,300 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "usd.h"
|
||||
|
||||
#include "usd_hook.h"
|
||||
|
||||
#include <boost/python/call_method.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/import.hpp>
|
||||
#include <boost/python/object.hpp>
|
||||
#include <boost/python/return_value_policy.hpp>
|
||||
#include <boost/python/to_python_converter.hpp>
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
#include "RNA_types.h"
|
||||
#include "bpy_rna.h"
|
||||
|
||||
#include "WM_api.hh"
|
||||
#include "WM_types.hh"
|
||||
|
||||
#include <list>
|
||||
|
||||
using namespace boost;
|
||||
|
||||
using USDHookList = std::list<USDHook *>;
|
||||
|
||||
/* USD hook type declarations */
|
||||
static USDHookList g_usd_hooks;
|
||||
|
||||
void USD_register_hook(struct USDHook *hook)
|
||||
{
|
||||
if (std::find(g_usd_hooks.begin(), g_usd_hooks.end(), hook) != g_usd_hooks.end()) {
|
||||
/* The hook is already in the list. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add hook type to the list. */
|
||||
g_usd_hooks.push_back(hook);
|
||||
}
|
||||
|
||||
void USD_unregister_hook(struct USDHook *hook)
|
||||
{
|
||||
g_usd_hooks.remove(hook);
|
||||
}
|
||||
|
||||
USDHook *USD_find_hook_name(const char name[])
|
||||
{
|
||||
/* sanity checks */
|
||||
if (g_usd_hooks.empty() || (name == NULL) || (name[0] == 0)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
USDHookList::iterator hook_iter = std::find_if(
|
||||
g_usd_hooks.begin(), g_usd_hooks.end(), [name](USDHook *hook) {
|
||||
return strcmp(hook->idname, name) == 0;
|
||||
});
|
||||
|
||||
return (hook_iter == g_usd_hooks.end()) ? NULL : *hook_iter;
|
||||
}
|
||||
|
||||
namespace blender::io::usd {
|
||||
|
||||
/* Convert PointerRNA to a PyObject*. */
|
||||
struct PointerRNAToPython {
|
||||
|
||||
/* We pass the argument by value because we need
|
||||
* to obtain a non-const pointer to it. */
|
||||
static PyObject *convert(PointerRNA ptr)
|
||||
{
|
||||
return pyrna_struct_CreatePyObject(&ptr);
|
||||
}
|
||||
};
|
||||
|
||||
/* Encapsulate arguments for scene export. */
|
||||
struct USDSceneExportContext {
|
||||
|
||||
USDSceneExportContext() : depsgraph_ptr({}) {}
|
||||
|
||||
USDSceneExportContext(pxr::UsdStageRefPtr in_stage, Depsgraph *depsgraph) : stage(in_stage)
|
||||
{
|
||||
RNA_pointer_create(NULL, &RNA_Depsgraph, depsgraph, &depsgraph_ptr);
|
||||
}
|
||||
|
||||
pxr::UsdStageRefPtr get_stage()
|
||||
{
|
||||
return stage;
|
||||
}
|
||||
|
||||
const PointerRNA &get_depsgraph() const
|
||||
{
|
||||
return depsgraph_ptr;
|
||||
}
|
||||
|
||||
pxr::UsdStageRefPtr stage;
|
||||
PointerRNA depsgraph_ptr;
|
||||
};
|
||||
|
||||
/* Encapsulate arguments for material export. */
|
||||
struct USDMaterialExportContext {
|
||||
USDMaterialExportContext() {}
|
||||
|
||||
USDMaterialExportContext(pxr::UsdStageRefPtr in_stage) : stage(in_stage) {}
|
||||
|
||||
pxr::UsdStageRefPtr get_stage()
|
||||
{
|
||||
return stage;
|
||||
}
|
||||
|
||||
pxr::UsdStageRefPtr stage;
|
||||
};
|
||||
|
||||
void register_export_hook_converters()
|
||||
{
|
||||
static bool registered = false;
|
||||
|
||||
/* No need to register if there are no hooks. */
|
||||
if (g_usd_hooks.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (registered) {
|
||||
return;
|
||||
}
|
||||
|
||||
registered = true;
|
||||
|
||||
PyGILState_STATE gilstate = PyGILState_Ensure();
|
||||
|
||||
/* We must import these modules for the USD type converters to work. */
|
||||
python::import("pxr.Usd");
|
||||
python::import("pxr.UsdShade");
|
||||
|
||||
/* Register converter from PoinerRNA to a PyObject*. */
|
||||
python::to_python_converter<PointerRNA, PointerRNAToPython>();
|
||||
|
||||
/* Register context class converters. */
|
||||
python::class_<USDSceneExportContext>("USDSceneExportContext")
|
||||
.def("get_stage", &USDSceneExportContext::get_stage)
|
||||
.def("get_depsgraph",
|
||||
&USDSceneExportContext::get_depsgraph,
|
||||
python::return_value_policy<python::return_by_value>());
|
||||
|
||||
python::class_<USDMaterialExportContext>("USDMaterialExportContext")
|
||||
.def("get_stage", &USDMaterialExportContext::get_stage);
|
||||
|
||||
PyGILState_Release(gilstate);
|
||||
}
|
||||
|
||||
/* Retrieve and report the current Python error. */
|
||||
static void handle_python_error(USDHook *hook)
|
||||
{
|
||||
if (!PyErr_Occurred()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PyErr_Print();
|
||||
|
||||
WM_reportf(RPT_ERROR,
|
||||
"An exception occurred invoking USD hook '%s'. Please see the console for details",
|
||||
hook->name);
|
||||
}
|
||||
|
||||
/* Abstract base class to facilitate calling a function with a given
|
||||
* signature defined by the registered USDHook classes. Subclasses
|
||||
* override virtual methods to specify the hook function name and to
|
||||
* call the hook with the required arguments.
|
||||
*/
|
||||
class USDHookInvoker {
|
||||
public:
|
||||
/* Attempt to call the function, if defined by the registered hooks. */
|
||||
void call() const
|
||||
{
|
||||
if (g_usd_hooks.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PyGILState_STATE gilstate = PyGILState_Ensure();
|
||||
|
||||
/* Iterate over the hooks and invoke the hook function, if it's defined. */
|
||||
USDHookList::const_iterator hook_iter = g_usd_hooks.begin();
|
||||
while (hook_iter != g_usd_hooks.end()) {
|
||||
|
||||
/* XXX: Not sure if this is necessary:
|
||||
* Advance the iterator before invoking the callback, to guard
|
||||
* against the unlikely error where the hook is deregistered in
|
||||
* the callback. This would prevent a crash due to the iterator
|
||||
* getting invalidated. */
|
||||
USDHook *hook = *hook_iter;
|
||||
++hook_iter;
|
||||
|
||||
if (!hook->rna_ext.data) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
PyObject *hook_obj = static_cast<PyObject *>(hook->rna_ext.data);
|
||||
|
||||
if (!PyObject_HasAttrString(hook_obj, function_name())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
call_hook(hook_obj);
|
||||
}
|
||||
catch (python::error_already_set const &) {
|
||||
handle_python_error(hook);
|
||||
}
|
||||
catch (...) {
|
||||
WM_reportf(RPT_ERROR, "An exception occurred invoking USD hook '%s'", hook->name);
|
||||
}
|
||||
}
|
||||
|
||||
PyGILState_Release(gilstate);
|
||||
}
|
||||
|
||||
protected:
|
||||
/* Override to specify the name of the function to be called. */
|
||||
virtual const char *function_name() const = 0;
|
||||
/* Override to call the function of the given object with the
|
||||
* required arguments, e.g.,
|
||||
*
|
||||
* python::call_method<void>(hook_obj, function_name(), arg1, arg2); */
|
||||
virtual void call_hook(PyObject *hook_obj) const = 0;
|
||||
};
|
||||
|
||||
class OnExportInvoker : public USDHookInvoker {
|
||||
private:
|
||||
USDSceneExportContext hook_context_;
|
||||
|
||||
public:
|
||||
OnExportInvoker(pxr::UsdStageRefPtr stage, Depsgraph *depsgraph)
|
||||
: hook_context_(stage, depsgraph)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
const char *function_name() const override
|
||||
{
|
||||
return "on_export";
|
||||
}
|
||||
|
||||
void call_hook(PyObject *hook_obj) const override
|
||||
{
|
||||
python::call_method<bool>(hook_obj, function_name(), hook_context_);
|
||||
}
|
||||
};
|
||||
|
||||
class OnMaterialExportInvoker : public USDHookInvoker {
|
||||
private:
|
||||
USDMaterialExportContext hook_context_;
|
||||
pxr::UsdShadeMaterial usd_material_;
|
||||
PointerRNA material_ptr_;
|
||||
|
||||
public:
|
||||
OnMaterialExportInvoker(pxr::UsdStageRefPtr stage,
|
||||
Material *material,
|
||||
pxr::UsdShadeMaterial &usd_material)
|
||||
: hook_context_(stage), usd_material_(usd_material)
|
||||
{
|
||||
RNA_pointer_create(NULL, &RNA_Material, material, &material_ptr_);
|
||||
}
|
||||
|
||||
protected:
|
||||
const char *function_name() const override
|
||||
{
|
||||
return "on_material_export";
|
||||
}
|
||||
|
||||
void call_hook(PyObject *hook_obj) const override
|
||||
{
|
||||
python::call_method<bool>(
|
||||
hook_obj, function_name(), hook_context_, material_ptr_, usd_material_);
|
||||
}
|
||||
};
|
||||
|
||||
void call_export_hooks(pxr::UsdStageRefPtr stage, Depsgraph *depsgraph)
|
||||
{
|
||||
if (g_usd_hooks.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
OnExportInvoker on_export(stage, depsgraph);
|
||||
on_export.call();
|
||||
}
|
||||
|
||||
void call_material_export_hooks(pxr::UsdStageRefPtr stage,
|
||||
Material *material,
|
||||
pxr::UsdShadeMaterial &usd_material)
|
||||
{
|
||||
if (g_usd_hooks.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
OnMaterialExportInvoker on_material_export(stage, material, usd_material);
|
||||
on_material_export.call();
|
||||
}
|
||||
|
||||
} // namespace blender::io::usd
|
|
@ -0,0 +1,27 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <pxr/usd/usd/stage.h>
|
||||
#include <pxr/usd/usdShade/material.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
struct Depsgraph;
|
||||
struct ExportJobData;
|
||||
struct Material;
|
||||
struct USDExportParams;
|
||||
|
||||
namespace blender::io::usd {
|
||||
|
||||
/* Ensure classes and type converters necessary for invoking export hook are registered. */
|
||||
void register_export_hook_converters();
|
||||
|
||||
/* Call the 'on_export' chaser function defined in the registred USDHook classes. */
|
||||
void call_export_hooks(pxr::UsdStageRefPtr stage, Depsgraph *depsgraph);
|
||||
|
||||
/* Call the 'on_material_export' hook functions defined in the registered USDHook classes. */
|
||||
void call_material_export_hooks(pxr::UsdStageRefPtr stage,
|
||||
Material *material,
|
||||
pxr::UsdShadeMaterial &usd_material);
|
||||
|
||||
} // namespace blender::io::usd
|
|
@ -113,6 +113,7 @@ pxr::UsdShadeMaterial USDAbstractWriter::ensure_usd_material(const HierarchyCont
|
|||
if (usd_material) {
|
||||
return usd_material;
|
||||
}
|
||||
|
||||
std::string active_uv = get_mesh_active_uvlayer_name(context.object);
|
||||
return create_usd_material(usd_export_context_, usd_path, material, active_uv);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "usd.h"
|
||||
#include "usd_exporter_context.h"
|
||||
#include "usd_hook.h"
|
||||
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_image_format.h"
|
||||
|
@ -841,6 +842,8 @@ pxr::UsdShadeMaterial create_usd_material(const USDExporterContext &usd_export_c
|
|||
create_usd_viewport_material(usd_export_context, material, usd_material);
|
||||
}
|
||||
|
||||
call_material_export_hooks(usd_export_context.stage, material, usd_material);
|
||||
|
||||
return usd_material;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
||||
#include "RNA_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -149,6 +151,29 @@ struct CacheReader *CacheReader_open_usd_object(struct CacheArchiveHandle *handl
|
|||
|
||||
void USD_CacheReader_incref(struct CacheReader *reader);
|
||||
void USD_CacheReader_free(struct CacheReader *reader);
|
||||
|
||||
/* Data for registering USD IO hooks. */
|
||||
typedef struct USDHook {
|
||||
|
||||
/* Identifier used for class name. */
|
||||
char idname[64];
|
||||
/* Identifier used as label. */
|
||||
char name[64];
|
||||
/* Short help/description. */
|
||||
char description[1024]; /* #RNA_DYN_DESCR_MAX */
|
||||
|
||||
/* rna_ext.data points to the USDHook class PyObject. */
|
||||
struct ExtensionRNA rna_ext;
|
||||
} USDHook;
|
||||
|
||||
void USD_register_hook(struct USDHook *hook);
|
||||
/* Remove the given entry from the list of registered hooks.
|
||||
* Note that this does not free the allocated memory for the
|
||||
* hook instance, so a separate call to MEM_freeN(hook) is
|
||||
* required. */
|
||||
void USD_unregister_hook(struct USDHook *hook);
|
||||
USDHook *USD_find_hook_name(const char name[]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -451,6 +451,7 @@ typedef struct GreasePencil {
|
|||
const blender::bke::greasepencil::Layer *get_active_layer() const;
|
||||
blender::bke::greasepencil::Layer *get_active_layer_for_write();
|
||||
void set_active_layer(const blender::bke::greasepencil::Layer *layer);
|
||||
bool is_layer_active(const blender::bke::greasepencil::Layer *layer) const;
|
||||
|
||||
blender::bke::greasepencil::Layer &add_layer(blender::bke::greasepencil::LayerGroup &group,
|
||||
blender::StringRefNull name);
|
||||
|
|
|
@ -2124,6 +2124,7 @@ typedef enum NodeMathOperation {
|
|||
NODE_MATH_PINGPONG = 37,
|
||||
NODE_MATH_SMOOTH_MIN = 38,
|
||||
NODE_MATH_SMOOTH_MAX = 39,
|
||||
NODE_MATH_FLOORED_MODULO = 40,
|
||||
} NodeMathOperation;
|
||||
|
||||
typedef enum NodeVectorMathOperation {
|
||||
|
|
|
@ -90,6 +90,13 @@ set(DEFSRC
|
|||
rna_xr.cc
|
||||
)
|
||||
|
||||
if(WITH_USD)
|
||||
list(APPEND DEFSRC
|
||||
rna_usd.cc
|
||||
)
|
||||
add_definitions(-DWITH_USD)
|
||||
endif()
|
||||
|
||||
if(WITH_EXPERIMENTAL_FEATURES)
|
||||
add_definitions(-DWITH_SIMULATION_DATABLOCK)
|
||||
add_definitions(-DWITH_GREASE_PENCIL_V3)
|
||||
|
@ -229,6 +236,7 @@ set(INC
|
|||
../../gpu
|
||||
../../ikplugin
|
||||
../../imbuf
|
||||
../../io/usd
|
||||
../../modifiers
|
||||
../../nodes
|
||||
../../sequencer
|
||||
|
|
|
@ -4750,6 +4750,9 @@ static RNAProcessItem PROCESS_ITEMS[] = {
|
|||
{"rna_timeline.cc", nullptr, RNA_def_timeline_marker},
|
||||
{"rna_sound.cc", "rna_sound_api.cc", RNA_def_sound},
|
||||
{"rna_ui.cc", "rna_ui_api.cc", RNA_def_ui},
|
||||
#ifdef WITH_USD
|
||||
{"rna_usd.cc", NULL, RNA_def_usd},
|
||||
#endif
|
||||
{"rna_userdef.cc", nullptr, RNA_def_userdef},
|
||||
{"rna_vfont.cc", "rna_vfont_api.cc", RNA_def_vfont},
|
||||
{"rna_volume.cc", nullptr, RNA_def_volume},
|
||||
|
|
|
@ -202,6 +202,7 @@ void RNA_def_texture(struct BlenderRNA *brna);
|
|||
void RNA_def_timeline_marker(struct BlenderRNA *brna);
|
||||
void RNA_def_sound(struct BlenderRNA *brna);
|
||||
void RNA_def_ui(struct BlenderRNA *brna);
|
||||
void RNA_def_usd(struct BlenderRNA *brna);
|
||||
void RNA_def_userdef(struct BlenderRNA *brna);
|
||||
void RNA_def_vfont(struct BlenderRNA *brna);
|
||||
void RNA_def_volume(struct BlenderRNA *brna);
|
||||
|
|
|
@ -223,7 +223,16 @@ const EnumPropertyItem rna_enum_node_math_items[] = {
|
|||
{NODE_MATH_TRUNC, "TRUNC", 0, "Truncate", "The integer part of A, removing fractional digits"},
|
||||
RNA_ENUM_ITEM_SEPR,
|
||||
{NODE_MATH_FRACTION, "FRACT", 0, "Fraction", "The fraction part of A"},
|
||||
{NODE_MATH_MODULO, "MODULO", 0, "Modulo", "Modulo using fmod(A,B)"},
|
||||
{NODE_MATH_MODULO,
|
||||
"MODULO",
|
||||
0,
|
||||
"Truncated Modulo",
|
||||
"The remainder of truncated division using fmod(A,B)"},
|
||||
{NODE_MATH_FLOORED_MODULO,
|
||||
"FLOORED_MODULO",
|
||||
0,
|
||||
"Floored Modulo",
|
||||
"The remainder of floored division"},
|
||||
{NODE_MATH_WRAP, "WRAP", 0, "Wrap", "Wrap value to range, wrap(A,B)"},
|
||||
{NODE_MATH_SNAP, "SNAP", 0, "Snap", "Snap to increment, snap(A,B)"},
|
||||
{NODE_MATH_PINGPONG,
|
||||
|
|
|
@ -1624,6 +1624,18 @@ static void rna_property_override_diff_propptr(Main *bmain,
|
|||
&ptrdiff_ctx.rnadiff_ctx.report_flag);
|
||||
ptrdiff_ctx.rnadiff_ctx.comparison = !match;
|
||||
|
||||
/* Regardless of whether the data from both pointers matches or not, a potentially existing
|
||||
* operation on current extended rna path should be removed. This is done by tagging said
|
||||
* operation as unused, while clearing the property tag (see also
|
||||
* #RNA_struct_override_matches handling of #LIBOVERRIDE_PROP_OP_TAG_UNUSED). Note that a
|
||||
* property with no operations will also be cleared by
|
||||
* #BKE_lib_override_library_id_unused_cleanup. */
|
||||
IDOverrideLibraryProperty *op = BKE_lib_override_library_property_find(liboverride,
|
||||
extended_rna_path);
|
||||
if (op != nullptr) {
|
||||
op->tag &= ~LIBOVERRIDE_PROP_OP_TAG_UNUSED;
|
||||
}
|
||||
|
||||
if (!ELEM(extended_rna_path, extended_rna_path_buffer, rna_path)) {
|
||||
MEM_freeN(extended_rna_path);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,163 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup RNA
|
||||
*/
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
#include "RNA_enum_types.h"
|
||||
|
||||
#include "rna_internal.h"
|
||||
|
||||
#include "WM_types.hh"
|
||||
|
||||
#include "usd.h"
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
# include "DNA_object_types.h"
|
||||
# include "WM_api.hh"
|
||||
|
||||
static StructRNA *rna_USDHook_refine(PointerRNA *ptr)
|
||||
{
|
||||
USDHook *hook = (USDHook *)ptr->data;
|
||||
return (hook->rna_ext.srna) ? hook->rna_ext.srna : &RNA_USDHook;
|
||||
}
|
||||
|
||||
static bool rna_USDHook_unregister(Main *bmain, StructRNA *type)
|
||||
{
|
||||
USDHook *hook = static_cast<USDHook *>(RNA_struct_blender_type_get(type));
|
||||
|
||||
if (hook == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* free RNA data referencing this */
|
||||
RNA_struct_free_extension(type, &hook->rna_ext);
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
|
||||
WM_main_add_notifier(NC_WINDOW, NULL);
|
||||
|
||||
/* unlink Blender-side data */
|
||||
USD_unregister_hook(hook);
|
||||
|
||||
MEM_freeN(hook);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static StructRNA *rna_USDHook_register(Main *bmain,
|
||||
ReportList *reports,
|
||||
void *data,
|
||||
const char *identifier,
|
||||
StructValidateFunc validate,
|
||||
StructCallbackFunc call,
|
||||
StructFreeFunc free)
|
||||
{
|
||||
const char *error_prefix = "Registering USD hook class:";
|
||||
USDHook dummy_hook = {NULL};
|
||||
USDHook *hook;
|
||||
PointerRNA dummy_hook_ptr = {NULL};
|
||||
|
||||
/* setup dummy type info to store static properties in */
|
||||
RNA_pointer_create(NULL, &RNA_USDHook, &dummy_hook, &dummy_hook_ptr);
|
||||
|
||||
/* validate the python class */
|
||||
if (validate(&dummy_hook_ptr, data, NULL) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strlen(identifier) >= sizeof(dummy_hook.idname)) {
|
||||
BKE_reportf(reports,
|
||||
RPT_ERROR,
|
||||
"%s '%s' is too long, maximum length is %d",
|
||||
error_prefix,
|
||||
identifier,
|
||||
(int)sizeof(dummy_hook.idname));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* check if we have registered this hook before, and remove it */
|
||||
hook = USD_find_hook_name(dummy_hook.idname);
|
||||
if (hook) {
|
||||
StructRNA *srna = hook->rna_ext.srna;
|
||||
if (!rna_USDHook_unregister(bmain, srna)) {
|
||||
BKE_reportf(reports,
|
||||
RPT_ERROR,
|
||||
"%s '%s', bl_idname '%s' %s",
|
||||
error_prefix,
|
||||
identifier,
|
||||
dummy_hook.idname,
|
||||
"could not be unregistered");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* create a new KeyingSetInfo type */
|
||||
hook = static_cast<USDHook *>(MEM_mallocN(sizeof(USDHook), "python USD hook"));
|
||||
memcpy(hook, &dummy_hook, sizeof(USDHook));
|
||||
|
||||
/* set RNA-extensions info */
|
||||
hook->rna_ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, hook->idname, &RNA_USDHook);
|
||||
hook->rna_ext.data = data;
|
||||
hook->rna_ext.call = call;
|
||||
hook->rna_ext.free = free;
|
||||
RNA_struct_blender_type_set(hook->rna_ext.srna, hook);
|
||||
|
||||
/* add and register with other info as needed */
|
||||
USD_register_hook(hook);
|
||||
|
||||
WM_main_add_notifier(NC_WINDOW, NULL);
|
||||
|
||||
/* return the struct-rna added */
|
||||
return hook->rna_ext.srna;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void rna_def_usd_hook(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *parm;
|
||||
|
||||
srna = RNA_def_struct(brna, "USDHook", NULL);
|
||||
RNA_def_struct_ui_text(srna, "USD Hook", "Defines callback functions to extend USD IO");
|
||||
RNA_def_struct_sdna(srna, "USDHook");
|
||||
RNA_def_struct_refine_func(srna, "rna_USDHook_refine");
|
||||
RNA_def_struct_register_funcs(srna, "rna_USDHook_register", "rna_USDHook_unregister", NULL);
|
||||
|
||||
///* Properties --------------------- */
|
||||
|
||||
RNA_define_verify_sdna(0); /* not in sdna */
|
||||
|
||||
prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, NULL, "idname");
|
||||
RNA_def_property_flag(prop, PROP_REGISTER);
|
||||
RNA_def_property_ui_text(prop, "ID Name", "");
|
||||
|
||||
prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, NULL, "name");
|
||||
RNA_def_property_ui_text(prop, "UI Name", "");
|
||||
RNA_def_struct_name_property(srna, prop);
|
||||
RNA_def_property_flag(prop, PROP_REGISTER);
|
||||
|
||||
prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, NULL, "description");
|
||||
RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */
|
||||
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
|
||||
RNA_def_property_ui_text(prop, "Description", "A short description of the USD hook");
|
||||
}
|
||||
|
||||
/* --- */
|
||||
|
||||
void RNA_def_usd(BlenderRNA *brna)
|
||||
{
|
||||
rna_def_usd_hook(brna);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -3302,6 +3302,12 @@ static void rna_def_userdef_theme_space_seq(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Effect Strip", "");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
|
||||
|
||||
prop = RNA_def_property(srna, "transition_strip", PROP_FLOAT, PROP_COLOR_GAMMA);
|
||||
RNA_def_property_float_sdna(prop, NULL, "transition");
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_ui_text(prop, "Transition Strip", "");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
|
||||
|
||||
prop = RNA_def_property(srna, "color_strip", PROP_FLOAT, PROP_COLOR_GAMMA);
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_ui_text(prop, "Color Strip", "");
|
||||
|
|
|
@ -152,6 +152,8 @@ inline bool try_dispatch_float_math_fl_fl_to_fl(const int operation, Callback &&
|
|||
return dispatch(exec_preset_fast, [](float a, float b) { return (float)(a > b); });
|
||||
case NODE_MATH_MODULO:
|
||||
return dispatch(exec_preset_fast, [](float a, float b) { return safe_modf(a, b); });
|
||||
case NODE_MATH_FLOORED_MODULO:
|
||||
return dispatch(exec_preset_fast, [](float a, float b) { return safe_floored_modf(a, b); });
|
||||
case NODE_MATH_SNAP:
|
||||
return dispatch(exec_preset_fast,
|
||||
[](float a, float b) { return floorf(safe_divide(a, b)) * b; });
|
||||
|
|
|
@ -53,6 +53,8 @@ const FloatMathOperationInfo *get_float_math_operation_info(const int operation)
|
|||
RETURN_OPERATION_INFO("Greater Than", "math_greater_than");
|
||||
case NODE_MATH_MODULO:
|
||||
RETURN_OPERATION_INFO("Modulo", "math_modulo");
|
||||
case NODE_MATH_FLOORED_MODULO:
|
||||
RETURN_OPERATION_INFO("Floored Modulo", "math_floored_modulo");
|
||||
case NODE_MATH_ABSOLUTE:
|
||||
RETURN_OPERATION_INFO("Absolute", "math_absolute");
|
||||
case NODE_MATH_ARCTAN2:
|
||||
|
|
|
@ -175,6 +175,16 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
|
|||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_FLOORED_MODULO: {
|
||||
if (in1 == 0.0f) {
|
||||
*out = 0.0f;
|
||||
}
|
||||
else {
|
||||
*out = in0 - floorf(in0 / in1) * in1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case NODE_MATH_ABSOLUTE: {
|
||||
*out = fabsf(in0);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue