Merge branch 'master' into temp_bmesh_multires
This commit is contained in:
commit
dbe767f5d9
|
@ -255,6 +255,7 @@ ForEachMacros:
|
|||
- SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN
|
||||
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN
|
||||
- SEQ_ALL_BEGIN
|
||||
- SEQ_ITERATOR_FOREACH
|
||||
- SURFACE_QUAD_ITER_BEGIN
|
||||
- foreach
|
||||
- ED_screen_areas_iter
|
||||
|
|
|
@ -96,7 +96,49 @@ bool BlenderSync::object_is_light(BL::Object &b_ob)
|
|||
return (b_ob_data && b_ob_data.is_a(&RNA_Light));
|
||||
}
|
||||
|
||||
/* Object */
|
||||
void BlenderSync::sync_object_motion_init(BL::Object &b_parent, BL::Object &b_ob, Object *object)
|
||||
{
|
||||
/* Initialize motion blur for object, detecting if it's enabled and creating motion
|
||||
* steps array if so. */
|
||||
array<Transform> motion;
|
||||
object->set_motion(motion);
|
||||
|
||||
Scene::MotionType need_motion = scene->need_motion();
|
||||
if (need_motion == Scene::MOTION_NONE || !object->get_geometry()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Geometry *geom = object->get_geometry();
|
||||
geom->set_use_motion_blur(false);
|
||||
geom->set_motion_steps(0);
|
||||
|
||||
uint motion_steps;
|
||||
|
||||
if (need_motion == Scene::MOTION_BLUR) {
|
||||
motion_steps = object_motion_steps(b_parent, b_ob, Object::MAX_MOTION_STEPS);
|
||||
geom->set_motion_steps(motion_steps);
|
||||
if (motion_steps && object_use_deform_motion(b_parent, b_ob)) {
|
||||
geom->set_use_motion_blur(true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
motion_steps = 3;
|
||||
geom->set_motion_steps(motion_steps);
|
||||
}
|
||||
|
||||
motion.resize(motion_steps, transform_empty());
|
||||
|
||||
if (motion_steps) {
|
||||
motion[motion_steps / 2] = object->get_tfm();
|
||||
|
||||
/* update motion socket before trying to access object->motion_time */
|
||||
object->set_motion(motion);
|
||||
|
||||
for (size_t step = 0; step < motion_steps; step++) {
|
||||
motion_times.insert(object->motion_time(step));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
|
||||
BL::ViewLayer &b_view_layer,
|
||||
|
@ -277,43 +319,6 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
|
|||
object->set_pass_id(b_ob.pass_index());
|
||||
object->set_color(get_float3(b_ob.color()));
|
||||
object->set_tfm(tfm);
|
||||
array<Transform> motion;
|
||||
object->set_motion(motion);
|
||||
|
||||
/* motion blur */
|
||||
Scene::MotionType need_motion = scene->need_motion();
|
||||
if (need_motion != Scene::MOTION_NONE && object->get_geometry()) {
|
||||
Geometry *geom = object->get_geometry();
|
||||
geom->set_use_motion_blur(false);
|
||||
geom->set_motion_steps(0);
|
||||
|
||||
uint motion_steps;
|
||||
|
||||
if (need_motion == Scene::MOTION_BLUR) {
|
||||
motion_steps = object_motion_steps(b_parent, b_ob, Object::MAX_MOTION_STEPS);
|
||||
geom->set_motion_steps(motion_steps);
|
||||
if (motion_steps && object_use_deform_motion(b_parent, b_ob)) {
|
||||
geom->set_use_motion_blur(true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
motion_steps = 3;
|
||||
geom->set_motion_steps(motion_steps);
|
||||
}
|
||||
|
||||
motion.resize(motion_steps, transform_empty());
|
||||
|
||||
if (motion_steps) {
|
||||
motion[motion_steps / 2] = tfm;
|
||||
|
||||
/* update motion socket before trying to access object->motion_time */
|
||||
object->set_motion(motion);
|
||||
|
||||
for (size_t step = 0; step < motion_steps; step++) {
|
||||
motion_times.insert(object->motion_time(step));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* dupli texture coordinates and random_id */
|
||||
if (is_instance) {
|
||||
|
@ -331,6 +336,8 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
|
|||
object->tag_update(scene);
|
||||
}
|
||||
|
||||
sync_object_motion_init(b_parent, b_ob, object);
|
||||
|
||||
if (is_instance) {
|
||||
/* Sync possible particle data. */
|
||||
sync_dupli_particle(b_parent, b_instance, object);
|
||||
|
@ -613,7 +620,7 @@ void BlenderSync::sync_motion(BL::RenderSettings &b_render,
|
|||
if (b_cam) {
|
||||
sync_camera_motion(b_render, b_cam, width, height, 0.0f);
|
||||
}
|
||||
sync_objects(b_depsgraph, b_v3d, 0.0f);
|
||||
sync_objects(b_depsgraph, b_v3d);
|
||||
}
|
||||
|
||||
/* Insert motion times from camera. Motion times from other objects
|
||||
|
|
|
@ -739,12 +739,18 @@ void BlenderSync::free_data_after_sync(BL::Depsgraph &b_depsgraph)
|
|||
* caches to be releases from blender side in order to reduce peak memory
|
||||
* footprint during synchronization process.
|
||||
*/
|
||||
|
||||
const bool is_interface_locked = b_engine.render() && b_engine.render().use_lock_interface();
|
||||
const bool can_free_caches = (BlenderSession::headless || is_interface_locked) &&
|
||||
/* Baking re-uses the depsgraph multiple times, clearing crashes
|
||||
* reading un-evaluated mesh data which isn't aligned with the
|
||||
* geometry we're baking, see T71012. */
|
||||
!scene->bake_manager->get_baking();
|
||||
const bool is_persistent_data = b_engine.render() && b_engine.render().use_persistent_data();
|
||||
const bool can_free_caches =
|
||||
(BlenderSession::headless || is_interface_locked) &&
|
||||
/* Baking re-uses the depsgraph multiple times, clearing crashes
|
||||
* reading un-evaluated mesh data which isn't aligned with the
|
||||
* geometry we're baking, see T71012. */
|
||||
!scene->bake_manager->get_baking() &&
|
||||
/* Persistent data must main caches for performance and correctness. */
|
||||
!is_persistent_data;
|
||||
|
||||
if (!can_free_caches) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -150,6 +150,7 @@ class BlenderSync {
|
|||
BlenderObjectCulling &culling,
|
||||
bool *use_portal,
|
||||
TaskPool *geom_task_pool);
|
||||
void sync_object_motion_init(BL::Object &b_parent, BL::Object &b_ob, Object *object);
|
||||
|
||||
bool sync_object_attributes(BL::DepsgraphObjectInstance &b_instance, Object *object);
|
||||
|
||||
|
|
|
@ -25,8 +25,9 @@ CCL_NAMESPACE_BEGIN
|
|||
ccl_device_inline float3
|
||||
subsurface_scatter_eval(ShaderData *sd, const ShaderClosure *sc, float disk_r, float r, bool all)
|
||||
{
|
||||
/* this is the veach one-sample model with balance heuristic, some pdf
|
||||
* factors drop out when using balance heuristic weighting */
|
||||
/* This is the Veach one-sample model with balance heuristic, some pdf
|
||||
* factors drop out when using balance heuristic weighting. For branched
|
||||
* path tracing (all) we sample all closure and don't use MIS. */
|
||||
float3 eval_sum = zero_float3();
|
||||
float pdf_sum = 0.0f;
|
||||
float sample_weight_inv = 0.0f;
|
||||
|
@ -65,6 +66,30 @@ subsurface_scatter_eval(ShaderData *sd, const ShaderClosure *sc, float disk_r, f
|
|||
return (pdf_sum > 0.0f) ? eval_sum / pdf_sum : zero_float3();
|
||||
}
|
||||
|
||||
ccl_device_inline float3 subsurface_scatter_walk_eval(ShaderData *sd,
|
||||
const ShaderClosure *sc,
|
||||
float3 throughput,
|
||||
bool all)
|
||||
{
|
||||
/* This is the Veach one-sample model with balance heuristic, some pdf
|
||||
* factors drop out when using balance heuristic weighting. For branched
|
||||
* path tracing (all) we sample all closure and don't use MIS. */
|
||||
if (!all) {
|
||||
float bssrdf_weight = 0.0f;
|
||||
float weight = sc->sample_weight;
|
||||
|
||||
for (int i = 0; i < sd->num_closure; i++) {
|
||||
sc = &sd->closure[i];
|
||||
|
||||
if (CLOSURE_IS_BSSRDF(sc->type)) {
|
||||
bssrdf_weight += sc->sample_weight;
|
||||
}
|
||||
}
|
||||
throughput *= bssrdf_weight / weight;
|
||||
}
|
||||
return throughput;
|
||||
}
|
||||
|
||||
/* replace closures with a single diffuse bsdf closure after scatter step */
|
||||
ccl_device void subsurface_scatter_setup_diffuse_bsdf(
|
||||
KernelGlobals *kg, ShaderData *sd, ClosureType type, float roughness, float3 weight, float3 N)
|
||||
|
@ -437,7 +462,8 @@ ccl_device_noinline
|
|||
ccl_addr_space PathState *state,
|
||||
const ShaderClosure *sc,
|
||||
const float bssrdf_u,
|
||||
const float bssrdf_v)
|
||||
const float bssrdf_v,
|
||||
bool all)
|
||||
{
|
||||
/* Sample diffuse surface scatter into the object. */
|
||||
float3 D;
|
||||
|
@ -669,7 +695,7 @@ ccl_device_noinline
|
|||
/* TODO: gain back performance lost from merging with disk BSSRDF. We
|
||||
* only need to return on hit so this indirect ray push/pop overhead
|
||||
* is not actually needed, but it does keep the code simpler. */
|
||||
ss_isect->weight[0] = throughput;
|
||||
ss_isect->weight[0] = subsurface_scatter_walk_eval(sd, sc, throughput, all);
|
||||
#ifdef __SPLIT_KERNEL__
|
||||
ss_isect->ray = *ray;
|
||||
#endif
|
||||
|
@ -691,7 +717,7 @@ ccl_device_inline int subsurface_scatter_multi_intersect(KernelGlobals *kg,
|
|||
return subsurface_scatter_disk(kg, ss_isect, sd, sc, lcg_state, bssrdf_u, bssrdf_v, all);
|
||||
}
|
||||
else {
|
||||
return subsurface_random_walk(kg, ss_isect, sd, state, sc, bssrdf_u, bssrdf_v);
|
||||
return subsurface_random_walk(kg, ss_isect, sd, state, sc, bssrdf_u, bssrdf_v, all);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -362,7 +362,7 @@ ccl_device float fast_atan2f(float y, float x)
|
|||
ccl_device float fast_log2f(float x)
|
||||
{
|
||||
/* NOTE: clamp to avoid special cases and make result "safe" from large
|
||||
* negative values/nans. */
|
||||
* negative values/NAN's. */
|
||||
x = clamp(x, FLT_MIN, FLT_MAX);
|
||||
unsigned bits = __float_as_uint(x);
|
||||
int exponent = (int)(bits >> 23) - 127;
|
||||
|
|
|
@ -22,10 +22,17 @@
|
|||
|
||||
#include <libavformat/avformat.h>
|
||||
|
||||
/* check our ffmpeg is new enough, avoids user complaints */
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR < 52) || \
|
||||
((LIBAVFORMAT_VERSION_MAJOR == 52) && (LIBAVFORMAT_VERSION_MINOR <= 64))
|
||||
# error "FFmpeg 0.7 or newer is needed, Upgrade your FFmpeg or disable it"
|
||||
/* Check if our ffmpeg is new enough, avoids user complaints.
|
||||
* Minimum supported version is currently 3.2.0 which mean the following library versions:
|
||||
* libavutil > 55.30
|
||||
* libavcodec > 57.60
|
||||
* libavformat > 57.50
|
||||
*
|
||||
* We only check for one of these as they are usually updated in tandem.
|
||||
*/
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR < 57) || \
|
||||
((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR <= 50))
|
||||
# error "FFmpeg 3.2.0 or newer is needed, Upgrade your FFmpeg or disable it"
|
||||
#endif
|
||||
/* end sanity check */
|
||||
|
||||
|
@ -36,274 +43,6 @@
|
|||
# define FFMPEG_INLINE static inline
|
||||
#endif
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/mathematics.h>
|
||||
#include <libavutil/opt.h>
|
||||
#include <libavutil/rational.h>
|
||||
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR > 52) || \
|
||||
((LIBAVFORMAT_VERSION_MAJOR >= 52) && (LIBAVFORMAT_VERSION_MINOR >= 101))
|
||||
# define FFMPEG_HAVE_PARSE_UTILS 1
|
||||
# include <libavutil/parseutils.h>
|
||||
#endif
|
||||
|
||||
#include <libswscale/swscale.h>
|
||||
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR > 52) || \
|
||||
((LIBAVFORMAT_VERSION_MAJOR >= 52) && (LIBAVFORMAT_VERSION_MINOR >= 105))
|
||||
# define FFMPEG_HAVE_AVIO 1
|
||||
#endif
|
||||
|
||||
#if (LIBAVCODEC_VERSION_MAJOR > 53) || \
|
||||
((LIBAVCODEC_VERSION_MAJOR == 53) && (LIBAVCODEC_VERSION_MINOR > 1)) || \
|
||||
((LIBAVCODEC_VERSION_MAJOR == 53) && (LIBAVCODEC_VERSION_MINOR == 1) && \
|
||||
(LIBAVCODEC_VERSION_MICRO >= 1)) || \
|
||||
((LIBAVCODEC_VERSION_MAJOR == 52) && (LIBAVCODEC_VERSION_MINOR >= 121))
|
||||
# define FFMPEG_HAVE_DEFAULT_VAL_UNION 1
|
||||
#endif
|
||||
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR > 52) || \
|
||||
((LIBAVFORMAT_VERSION_MAJOR >= 52) && (LIBAVFORMAT_VERSION_MINOR >= 101))
|
||||
# define FFMPEG_HAVE_AV_DUMP_FORMAT 1
|
||||
#endif
|
||||
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR > 52) || \
|
||||
((LIBAVFORMAT_VERSION_MAJOR >= 52) && (LIBAVFORMAT_VERSION_MINOR >= 45))
|
||||
# define FFMPEG_HAVE_AV_GUESS_FORMAT 1
|
||||
#endif
|
||||
|
||||
#if (LIBAVCODEC_VERSION_MAJOR > 52) || \
|
||||
((LIBAVCODEC_VERSION_MAJOR >= 52) && (LIBAVCODEC_VERSION_MINOR >= 23))
|
||||
# define FFMPEG_HAVE_DECODE_AUDIO3 1
|
||||
# define FFMPEG_HAVE_DECODE_VIDEO2 1
|
||||
#endif
|
||||
|
||||
#if (LIBAVCODEC_VERSION_MAJOR > 52) || \
|
||||
((LIBAVCODEC_VERSION_MAJOR >= 52) && (LIBAVCODEC_VERSION_MINOR >= 64))
|
||||
# define FFMPEG_HAVE_AVMEDIA_TYPES 1
|
||||
#endif
|
||||
|
||||
#if ((LIBAVCODEC_VERSION_MAJOR > 52) || \
|
||||
(LIBAVCODEC_VERSION_MAJOR >= 52) && (LIBAVCODEC_VERSION_MINOR >= 29)) && \
|
||||
((LIBSWSCALE_VERSION_MAJOR > 0) || \
|
||||
(LIBSWSCALE_VERSION_MAJOR >= 0) && (LIBSWSCALE_VERSION_MINOR >= 10))
|
||||
# define FFMPEG_SWSCALE_COLOR_SPACE_SUPPORT
|
||||
#endif
|
||||
|
||||
#if ((LIBAVCODEC_VERSION_MAJOR > 54) || \
|
||||
(LIBAVCODEC_VERSION_MAJOR >= 54) && (LIBAVCODEC_VERSION_MINOR > 14))
|
||||
# define FFMPEG_HAVE_CANON_H264_RESOLUTION_FIX
|
||||
#endif
|
||||
|
||||
#if ((LIBAVCODEC_VERSION_MAJOR > 53) || \
|
||||
(LIBAVCODEC_VERSION_MAJOR >= 53) && (LIBAVCODEC_VERSION_MINOR >= 60))
|
||||
# define FFMPEG_HAVE_ENCODE_AUDIO2
|
||||
#endif
|
||||
|
||||
#if ((LIBAVCODEC_VERSION_MAJOR > 53) || \
|
||||
(LIBAVCODEC_VERSION_MAJOR >= 53) && (LIBAVCODEC_VERSION_MINOR >= 42))
|
||||
# define FFMPEG_HAVE_DECODE_AUDIO4
|
||||
#endif
|
||||
|
||||
#if ((LIBAVCODEC_VERSION_MAJOR > 54) || \
|
||||
(LIBAVCODEC_VERSION_MAJOR >= 54) && (LIBAVCODEC_VERSION_MINOR >= 13))
|
||||
# define FFMPEG_HAVE_AVFRAME_SAMPLE_RATE
|
||||
#endif
|
||||
|
||||
#if ((LIBAVUTIL_VERSION_MAJOR > 51) || \
|
||||
(LIBAVUTIL_VERSION_MAJOR == 51) && (LIBAVUTIL_VERSION_MINOR >= 21))
|
||||
# define FFMPEG_FFV1_ALPHA_SUPPORTED
|
||||
# define FFMPEG_SAMPLE_FMT_S16P_SUPPORTED
|
||||
#else
|
||||
|
||||
FFMPEG_INLINE
|
||||
int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt)
|
||||
{
|
||||
/* no planar formats in FFmpeg < 0.9 */
|
||||
(void)sample_fmt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* XXX TODO Probably fix to correct modern flags in code? Not sure how old FFMPEG we want to
|
||||
* support though, so for now this will do. */
|
||||
|
||||
#ifndef FF_MIN_BUFFER_SIZE
|
||||
# ifdef AV_INPUT_BUFFER_MIN_SIZE
|
||||
# define FF_MIN_BUFFER_SIZE AV_INPUT_BUFFER_MIN_SIZE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef FF_INPUT_BUFFER_PADDING_SIZE
|
||||
# ifdef AV_INPUT_BUFFER_PADDING_SIZE
|
||||
# define FF_INPUT_BUFFER_PADDING_SIZE AV_INPUT_BUFFER_PADDING_SIZE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CODEC_FLAG_GLOBAL_HEADER
|
||||
# ifdef AV_CODEC_FLAG_GLOBAL_HEADER
|
||||
# define CODEC_FLAG_GLOBAL_HEADER AV_CODEC_FLAG_GLOBAL_HEADER
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CODEC_FLAG_GLOBAL_HEADER
|
||||
# ifdef AV_CODEC_FLAG_GLOBAL_HEADER
|
||||
# define CODEC_FLAG_GLOBAL_HEADER AV_CODEC_FLAG_GLOBAL_HEADER
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CODEC_FLAG_INTERLACED_DCT
|
||||
# ifdef AV_CODEC_FLAG_INTERLACED_DCT
|
||||
# define CODEC_FLAG_INTERLACED_DCT AV_CODEC_FLAG_INTERLACED_DCT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CODEC_FLAG_INTERLACED_ME
|
||||
# ifdef AV_CODEC_FLAG_INTERLACED_ME
|
||||
# define CODEC_FLAG_INTERLACED_ME AV_CODEC_FLAG_INTERLACED_ME
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* FFmpeg upstream 1.0 is the first who added AV_ prefix. */
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 59, 100)
|
||||
# define AV_CODEC_ID_NONE CODEC_ID_NONE
|
||||
# define AV_CODEC_ID_MPEG4 CODEC_ID_MPEG4
|
||||
# define AV_CODEC_ID_MJPEG CODEC_ID_MJPEG
|
||||
# define AV_CODEC_ID_DNXHD CODEC_ID_DNXHD
|
||||
# define AV_CODEC_ID_MPEG2VIDEO CODEC_ID_MPEG2VIDEO
|
||||
# define AV_CODEC_ID_MPEG1VIDEO CODEC_ID_MPEG1VIDEO
|
||||
# define AV_CODEC_ID_DVVIDEO CODEC_ID_DVVIDEO
|
||||
# define AV_CODEC_ID_THEORA CODEC_ID_THEORA
|
||||
# define AV_CODEC_ID_PNG CODEC_ID_PNG
|
||||
# define AV_CODEC_ID_QTRLE CODEC_ID_QTRLE
|
||||
# define AV_CODEC_ID_FFV1 CODEC_ID_FFV1
|
||||
# define AV_CODEC_ID_HUFFYUV CODEC_ID_HUFFYUV
|
||||
# define AV_CODEC_ID_H264 CODEC_ID_H264
|
||||
# define AV_CODEC_ID_FLV1 CODEC_ID_FLV1
|
||||
|
||||
# define AV_CODEC_ID_AAC CODEC_ID_AAC
|
||||
# define AV_CODEC_ID_AC3 CODEC_ID_AC3
|
||||
# define AV_CODEC_ID_MP3 CODEC_ID_MP3
|
||||
# define AV_CODEC_ID_MP2 CODEC_ID_MP2
|
||||
# define AV_CODEC_ID_FLAC CODEC_ID_FLAC
|
||||
# define AV_CODEC_ID_PCM_U8 CODEC_ID_PCM_U8
|
||||
# define AV_CODEC_ID_PCM_S16LE CODEC_ID_PCM_S16LE
|
||||
# define AV_CODEC_ID_PCM_S24LE CODEC_ID_PCM_S24LE
|
||||
# define AV_CODEC_ID_PCM_S32LE CODEC_ID_PCM_S32LE
|
||||
# define AV_CODEC_ID_PCM_F32LE CODEC_ID_PCM_F32LE
|
||||
# define AV_CODEC_ID_PCM_F64LE CODEC_ID_PCM_F64LE
|
||||
# define AV_CODEC_ID_VORBIS CODEC_ID_VORBIS
|
||||
#endif
|
||||
|
||||
FFMPEG_INLINE
|
||||
int av_get_cropped_height_from_codec(AVCodecContext *pCodecCtx)
|
||||
{
|
||||
int y = pCodecCtx->height;
|
||||
|
||||
#ifndef FFMPEG_HAVE_CANON_H264_RESOLUTION_FIX
|
||||
/* really bad hack to remove this dreadfull black bar at the bottom
|
||||
with Canon footage and old ffmpeg versions.
|
||||
(to fix this properly in older ffmpeg versions one has to write a new
|
||||
demuxer...)
|
||||
|
||||
see the actual fix here for reference:
|
||||
|
||||
http://git.libav.org/?p=libav.git;a=commit;h=30f515091c323da59c0f1b533703dedca2f4b95d
|
||||
|
||||
We do our best to apply this only to matching footage.
|
||||
*/
|
||||
if (pCodecCtx->width == 1920 && pCodecCtx->height == 1088 &&
|
||||
pCodecCtx->pix_fmt == PIX_FMT_YUVJ420P && pCodecCtx->codec_id == AV_CODEC_ID_H264) {
|
||||
y = 1080;
|
||||
}
|
||||
#endif
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
#if ((LIBAVUTIL_VERSION_MAJOR < 51) || \
|
||||
(LIBAVUTIL_VERSION_MAJOR == 51) && (LIBAVUTIL_VERSION_MINOR < 22))
|
||||
FFMPEG_INLINE
|
||||
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
|
||||
{
|
||||
const AVOption *rv = NULL;
|
||||
(void)search_flags;
|
||||
av_set_string3(obj, name, val, 1, &rv);
|
||||
return rv != NULL;
|
||||
}
|
||||
|
||||
FFMPEG_INLINE
|
||||
int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
|
||||
{
|
||||
const AVOption *rv = NULL;
|
||||
(void)search_flags;
|
||||
rv = av_set_int(obj, name, val);
|
||||
return rv != NULL;
|
||||
}
|
||||
|
||||
FFMPEG_INLINE
|
||||
int av_opt_set_double(void *obj, const char *name, double val, int search_flags)
|
||||
{
|
||||
const AVOption *rv = NULL;
|
||||
(void)search_flags;
|
||||
rv = av_set_double(obj, name, val);
|
||||
return rv != NULL;
|
||||
}
|
||||
|
||||
# define AV_OPT_TYPE_INT FF_OPT_TYPE_INT
|
||||
# define AV_OPT_TYPE_INT64 FF_OPT_TYPE_INT64
|
||||
# define AV_OPT_TYPE_STRING FF_OPT_TYPE_STRING
|
||||
# define AV_OPT_TYPE_CONST FF_OPT_TYPE_CONST
|
||||
# define AV_OPT_TYPE_DOUBLE FF_OPT_TYPE_DOUBLE
|
||||
# define AV_OPT_TYPE_FLOAT FF_OPT_TYPE_FLOAT
|
||||
#endif
|
||||
|
||||
#if ((LIBAVUTIL_VERSION_MAJOR < 51) || \
|
||||
(LIBAVUTIL_VERSION_MAJOR == 51) && (LIBAVUTIL_VERSION_MINOR < 54))
|
||||
FFMPEG_INLINE
|
||||
enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt)
|
||||
{
|
||||
if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB)
|
||||
return AV_SAMPLE_FMT_NONE;
|
||||
return sample_fmt;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ((LIBAVCODEC_VERSION_MAJOR < 53) || \
|
||||
(LIBAVCODEC_VERSION_MAJOR == 53 && LIBAVCODEC_VERSION_MINOR < 35))
|
||||
FFMPEG_INLINE
|
||||
int avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options)
|
||||
{
|
||||
/* TODO: no options are taking into account */
|
||||
(void)options;
|
||||
return avcodec_open(avctx, codec);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ((LIBAVFORMAT_VERSION_MAJOR < 53) || \
|
||||
(LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR < 21))
|
||||
FFMPEG_INLINE
|
||||
AVStream *avformat_new_stream(AVFormatContext *s, AVCodec *c)
|
||||
{
|
||||
/* TODO: no codec is taking into account */
|
||||
(void)c;
|
||||
return av_new_stream(s, 0);
|
||||
}
|
||||
|
||||
FFMPEG_INLINE
|
||||
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
|
||||
{
|
||||
/* TODO: no options are taking into account */
|
||||
(void)options;
|
||||
return av_find_stream_info(ic);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ((LIBAVFORMAT_VERSION_MAJOR > 53) || \
|
||||
((LIBAVFORMAT_VERSION_MAJOR == 53) && (LIBAVFORMAT_VERSION_MINOR > 32)) || \
|
||||
((LIBAVFORMAT_VERSION_MAJOR == 53) && (LIBAVFORMAT_VERSION_MINOR == 24) && \
|
||||
(LIBAVFORMAT_VERSION_MICRO >= 100)))
|
||||
FFMPEG_INLINE
|
||||
void my_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
|
||||
{
|
||||
|
@ -323,103 +62,12 @@ void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
|
|||
{
|
||||
my_update_cur_dts(s, ref_st, timestamp);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ((LIBAVCODEC_VERSION_MAJOR < 54) || \
|
||||
(LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR < 28))
|
||||
FFMPEG_INLINE
|
||||
void avcodec_free_frame(AVFrame **frame)
|
||||
{
|
||||
/* don't need to do anything with old AVFrame
|
||||
* since it does not have malloced members */
|
||||
(void)frame;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ((LIBAVCODEC_VERSION_MAJOR > 54) || \
|
||||
(LIBAVCODEC_VERSION_MAJOR >= 54) && (LIBAVCODEC_VERSION_MINOR >= 13))
|
||||
# define FFMPEG_HAVE_AVFRAME_SAMPLE_RATE
|
||||
#endif
|
||||
|
||||
#if ((LIBAVCODEC_VERSION_MAJOR > 54) || \
|
||||
(LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 13))
|
||||
# define FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT
|
||||
#endif
|
||||
|
||||
#ifndef FFMPEG_HAVE_AVIO
|
||||
# define AVIO_FLAG_WRITE URL_WRONLY
|
||||
# define avio_open url_fopen
|
||||
# define avio_tell url_ftell
|
||||
# define avio_close url_fclose
|
||||
# define avio_size url_fsize
|
||||
#endif
|
||||
|
||||
/* There are some version in between, which have avio_... functions but no
|
||||
* AVIO_FLAG_... */
|
||||
#ifndef AVIO_FLAG_WRITE
|
||||
# define AVIO_FLAG_WRITE URL_WRONLY
|
||||
#endif
|
||||
|
||||
#ifndef AV_PKT_FLAG_KEY
|
||||
# define AV_PKT_FLAG_KEY PKT_FLAG_KEY
|
||||
#endif
|
||||
|
||||
#ifndef FFMPEG_HAVE_AV_DUMP_FORMAT
|
||||
# define av_dump_format dump_format
|
||||
#endif
|
||||
|
||||
#ifndef FFMPEG_HAVE_AV_GUESS_FORMAT
|
||||
# define av_guess_format guess_format
|
||||
#endif
|
||||
|
||||
#ifndef FFMPEG_HAVE_PARSE_UTILS
|
||||
# define av_parse_video_rate av_parse_video_frame_rate
|
||||
#endif
|
||||
|
||||
#ifdef FFMPEG_HAVE_DEFAULT_VAL_UNION
|
||||
# define FFMPEG_DEF_OPT_VAL_INT(OPT) OPT->default_val.i64
|
||||
# define FFMPEG_DEF_OPT_VAL_DOUBLE(OPT) OPT->default_val.dbl
|
||||
#else
|
||||
# define FFMPEG_DEF_OPT_VAL_INT(OPT) OPT->default_val
|
||||
# define FFMPEG_DEF_OPT_VAL_DOUBLE(OPT) OPT->default_val
|
||||
#endif
|
||||
|
||||
#ifndef FFMPEG_HAVE_AVMEDIA_TYPES
|
||||
# define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
|
||||
# define AVMEDIA_TYPE_AUDIO CODEC_TYPE_AUDIO
|
||||
#endif
|
||||
|
||||
#ifndef FFMPEG_HAVE_DECODE_AUDIO3
|
||||
FFMPEG_INLINE
|
||||
int avcodec_decode_audio3(AVCodecContext *avctx,
|
||||
int16_t *samples,
|
||||
int *frame_size_ptr,
|
||||
AVPacket *avpkt)
|
||||
{
|
||||
return avcodec_decode_audio2(avctx, samples, frame_size_ptr, avpkt->data, avpkt->size);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef FFMPEG_HAVE_DECODE_VIDEO2
|
||||
FFMPEG_INLINE
|
||||
int avcodec_decode_video2(AVCodecContext *avctx,
|
||||
AVFrame *picture,
|
||||
int *got_picture_ptr,
|
||||
AVPacket *avpkt)
|
||||
{
|
||||
return avcodec_decode_video(avctx, picture, got_picture_ptr, avpkt->data, avpkt->size);
|
||||
}
|
||||
#endif
|
||||
|
||||
FFMPEG_INLINE
|
||||
int64_t av_get_pts_from_frame(AVFormatContext *avctx, AVFrame *picture)
|
||||
{
|
||||
int64_t pts;
|
||||
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 34, 100)
|
||||
pts = picture->pts;
|
||||
#else
|
||||
pts = picture->pkt_pts;
|
||||
#endif
|
||||
|
||||
if (pts == AV_NOPTS_VALUE) {
|
||||
pts = picture->pkt_dts;
|
||||
|
@ -432,124 +80,16 @@ int64_t av_get_pts_from_frame(AVFormatContext *avctx, AVFrame *picture)
|
|||
return pts;
|
||||
}
|
||||
|
||||
/* obsolete constant formerly defined in FFMpeg libavcodec/avcodec.h */
|
||||
#ifndef AVCODEC_MAX_AUDIO_FRAME_SIZE
|
||||
# define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio
|
||||
#endif
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Deinterlace code block
|
||||
*
|
||||
* NOTE: The code in this block are from FFmpeg 2.6.4, which is licensed by LGPL.
|
||||
* \{ */
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 1, 0)
|
||||
FFMPEG_INLINE
|
||||
int avcodec_encode_video2(AVCodecContext *avctx,
|
||||
AVPacket *pkt,
|
||||
const AVFrame *frame,
|
||||
int *got_output)
|
||||
{
|
||||
int outsize, ret;
|
||||
#define MAX_NEG_CROP 1024
|
||||
|
||||
ret = av_new_packet(pkt, avctx->width * avctx->height * 7 + 10000);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
outsize = avcodec_encode_video(avctx, pkt->data, pkt->size, frame);
|
||||
if (outsize <= 0) {
|
||||
*got_output = 0;
|
||||
av_free_packet(pkt);
|
||||
}
|
||||
else {
|
||||
*got_output = 1;
|
||||
av_shrink_packet(pkt, outsize);
|
||||
if (avctx->coded_frame) {
|
||||
pkt->pts = avctx->coded_frame->pts;
|
||||
if (avctx->coded_frame->key_frame)
|
||||
pkt->flags |= AV_PKT_FLAG_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
return outsize >= 0 ? 0 : outsize;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 17, 0)
|
||||
FFMPEG_INLINE
|
||||
void avformat_close_input(AVFormatContext **ctx)
|
||||
{
|
||||
av_close_input_file(*ctx);
|
||||
*ctx = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 8, 0)
|
||||
FFMPEG_INLINE
|
||||
AVFrame *av_frame_alloc(void)
|
||||
{
|
||||
return avcodec_alloc_frame();
|
||||
}
|
||||
|
||||
FFMPEG_INLINE
|
||||
void av_frame_free(AVFrame **frame)
|
||||
{
|
||||
av_freep(frame);
|
||||
}
|
||||
#endif
|
||||
|
||||
FFMPEG_INLINE
|
||||
const char *av_get_metadata_key_value(AVDictionary *metadata, const char *key)
|
||||
{
|
||||
if (metadata == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
AVDictionaryEntry *tag = NULL;
|
||||
while ((tag = av_dict_get(metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
|
||||
if (!strcmp(tag->key, key)) {
|
||||
return tag->value;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FFMPEG_INLINE
|
||||
bool av_check_encoded_with_ffmpeg(AVFormatContext *ctx)
|
||||
{
|
||||
const char *encoder = av_get_metadata_key_value(ctx->metadata, "ENCODER");
|
||||
if (encoder != NULL && !strncmp(encoder, "Lavf", 4)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51, 32, 0)
|
||||
# define AV_OPT_SEARCH_FAKE_OBJ 0
|
||||
#endif
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 59, 100)
|
||||
# define FFMPEG_HAVE_DEPRECATED_FLAGS2
|
||||
#endif
|
||||
|
||||
/* Since FFmpeg-1.1 this constant have AV_ prefix. */
|
||||
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 3, 100)
|
||||
# define AV_PIX_FMT_BGR32 PIX_FMT_BGR32
|
||||
# define AV_PIX_FMT_YUV422P PIX_FMT_YUV422P
|
||||
# define AV_PIX_FMT_BGRA PIX_FMT_BGRA
|
||||
# define AV_PIX_FMT_ARGB PIX_FMT_ARGB
|
||||
# define AV_PIX_FMT_RGBA PIX_FMT_RGBA
|
||||
#endif
|
||||
|
||||
/* New API from FFmpeg-2.0 which soon became recommended one. */
|
||||
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 38, 100)
|
||||
# define av_frame_alloc avcodec_alloc_frame
|
||||
# define av_frame_free avcodec_free_frame
|
||||
# define av_frame_unref avcodec_get_frame_defaults
|
||||
#endif
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 24, 102)
|
||||
|
||||
/* NOTE: The code in this block are from FFmpeg 2.6.4, which is licensed by LGPL. */
|
||||
|
||||
# define MAX_NEG_CROP 1024
|
||||
|
||||
# define times4(x) x, x, x, x
|
||||
# define times256(x) times4(times4(times4(times4(times4(x)))))
|
||||
#define times4(x) x, x, x, x
|
||||
#define times256(x) times4(times4(times4(times4(times4(x)))))
|
||||
|
||||
static const uint8_t ff_compat_crop_tab[256 + 2 * MAX_NEG_CROP] = {
|
||||
times256(0x00), 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
|
||||
|
@ -575,8 +115,8 @@ static const uint8_t ff_compat_crop_tab[256 + 2 * MAX_NEG_CROP] = {
|
|||
0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA,
|
||||
0xFB, 0xFC, 0xFD, 0xFE, 0xFF, times256(0xFF)};
|
||||
|
||||
# undef times4
|
||||
# undef times256
|
||||
#undef times4
|
||||
#undef times256
|
||||
|
||||
/* filter parameters: [-1 4 2 4 -1] // 8 */
|
||||
FFMPEG_INLINE
|
||||
|
@ -668,8 +208,9 @@ int deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap, int width, int
|
|||
uint8_t *src_m1, *src_0, *src_p1, *src_p2;
|
||||
int y;
|
||||
uint8_t *buf = (uint8_t *)av_malloc(width);
|
||||
if (!buf)
|
||||
if (!buf) {
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
src_m1 = src1;
|
||||
memcpy(buf, src_m1, width);
|
||||
|
@ -689,24 +230,21 @@ int deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap, int width, int
|
|||
return 0;
|
||||
}
|
||||
|
||||
# ifdef __GNUC__
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
# endif
|
||||
|
||||
FFMPEG_INLINE
|
||||
int avpicture_deinterlace(
|
||||
AVPicture *dst, const AVPicture *src, enum AVPixelFormat pix_fmt, int width, int height)
|
||||
int av_image_deinterlace(
|
||||
AVFrame *dst, const AVFrame *src, enum AVPixelFormat pix_fmt, int width, int height)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
if (pix_fmt != AV_PIX_FMT_YUV420P && pix_fmt != AV_PIX_FMT_YUVJ420P &&
|
||||
pix_fmt != AV_PIX_FMT_YUV422P && pix_fmt != AV_PIX_FMT_YUVJ422P &&
|
||||
pix_fmt != AV_PIX_FMT_YUV444P && pix_fmt != AV_PIX_FMT_YUV411P &&
|
||||
pix_fmt != AV_PIX_FMT_GRAY8)
|
||||
pix_fmt != AV_PIX_FMT_GRAY8) {
|
||||
return -1;
|
||||
if ((width & 3) != 0 || (height & 3) != 0)
|
||||
}
|
||||
if ((width & 3) != 0 || (height & 3) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (i == 1) {
|
||||
|
@ -732,8 +270,9 @@ int avpicture_deinterlace(
|
|||
}
|
||||
if (src == dst) {
|
||||
ret = deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i], width, height);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else {
|
||||
deinterlace_bottom_field(
|
||||
|
@ -743,10 +282,6 @@ int avpicture_deinterlace(
|
|||
return 0;
|
||||
}
|
||||
|
||||
# ifdef __GNUC__
|
||||
# pragma GCC diagnostic pop
|
||||
# endif
|
||||
|
||||
#endif
|
||||
/** \} Deinterlace code block */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -112,8 +112,7 @@ GHOST_DropTargetX11::~GHOST_DropTargetX11()
|
|||
}
|
||||
}
|
||||
|
||||
/* based on a code from Saul Rennison
|
||||
* http://stackoverflow.com/questions/2673207/c-c-url-decode-library */
|
||||
/* Based on: https://stackoverflow.com/a/2766963/432509 */
|
||||
|
||||
typedef enum DecodeState_e {
|
||||
STATE_SEARCH = 0, ///< searching for an ampersand to convert
|
||||
|
|
|
@ -1711,7 +1711,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
|
|||
dx = [event scrollingDeltaX];
|
||||
dy = [event scrollingDeltaY];
|
||||
|
||||
/* However, wacom tablet (intuos5) needs old deltas,
|
||||
/* However, Wacom tablet (intuos5) needs old deltas,
|
||||
* it then has momentum and phase at zero. */
|
||||
if (phase == NSEventPhaseNone && momentumPhase == NSEventPhaseNone) {
|
||||
dx = [event deltaX];
|
||||
|
|
|
@ -55,7 +55,6 @@ void *GHOST_XrContext::s_error_handler_customdata = nullptr;
|
|||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Create, Initialize and Destruct
|
||||
*
|
||||
* \{ */
|
||||
|
||||
GHOST_XrContext::GHOST_XrContext(const GHOST_XrContextCreateInfo *create_info)
|
||||
|
@ -153,7 +152,6 @@ void GHOST_XrContext::storeInstanceProperties()
|
|||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Debug Printing
|
||||
*
|
||||
* \{ */
|
||||
|
||||
void GHOST_XrContext::printInstanceInfo()
|
||||
|
@ -242,7 +240,6 @@ void GHOST_XrContext::initDebugMessenger()
|
|||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Error handling
|
||||
*
|
||||
* \{ */
|
||||
|
||||
void GHOST_XrContext::dispatchErrorMessage(const GHOST_XrException *exception) const
|
||||
|
@ -273,7 +270,6 @@ void GHOST_XrContext::setErrorHandler(GHOST_XrErrorHandlerFn handler_fn, void *c
|
|||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name OpenXR API-Layers and Extensions
|
||||
*
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
|
@ -564,7 +560,6 @@ bool GHOST_XrContext::needsUpsideDownDrawing() const
|
|||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Ghost Internal Accessors and Mutators
|
||||
*
|
||||
* \{ */
|
||||
|
||||
GHOST_TXrOpenXRRuntimeID GHOST_XrContext::getOpenXRRuntimeID() const
|
||||
|
|
|
@ -59,7 +59,6 @@ struct GHOST_XrDrawInfo {
|
|||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Create, Initialize and Destruct
|
||||
*
|
||||
* \{ */
|
||||
|
||||
GHOST_XrSession::GHOST_XrSession(GHOST_XrContext &xr_context)
|
||||
|
@ -110,7 +109,6 @@ void GHOST_XrSession::initSystem()
|
|||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name State Management
|
||||
*
|
||||
* \{ */
|
||||
|
||||
static void create_reference_spaces(OpenXRSessionData &oxr, const GHOST_XrPose &base_pose)
|
||||
|
@ -245,7 +243,6 @@ GHOST_XrSession::LifeExpectancy GHOST_XrSession::handleStateChangeEvent(
|
|||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Drawing
|
||||
*
|
||||
* \{ */
|
||||
|
||||
void GHOST_XrSession::prepareDrawing()
|
||||
|
@ -457,7 +454,6 @@ bool GHOST_XrSession::needsUpsideDownDrawing() const
|
|||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name State Queries
|
||||
*
|
||||
* \{ */
|
||||
|
||||
bool GHOST_XrSession::isRunning() const
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit d2d33a435d358fcd0ae7f3e2cd67bee2b500ec53
|
||||
Subproject commit 5ab29b1331d2103dae634b987f121c4599459d7f
|
|
@ -1 +1 @@
|
|||
Subproject commit eb3952fcd26e9897bcc0128eab925b070c0e7593
|
||||
Subproject commit bb16aba5bd3873794eefe167497118b6063b9a85
|
|
@ -305,7 +305,7 @@ url_manual_mapping = (
|
|||
("bpy.types.geometrynodealignrotationtovector*", "modeling/geometry_nodes/point/align_rotation_to_vector.html#bpy-types-geometrynodealignrotationtovector"),
|
||||
("bpy.types.greasepencil.curve_edit_threshold*", "grease_pencil/modes/edit/curve_editing.html#bpy-types-greasepencil-curve-edit-threshold"),
|
||||
("bpy.types.materialgpencilstyle.stroke_style*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-stroke-style"),
|
||||
("bpy.types.objectlineart.use_crease_override*", "scene_layout/object/properties/lineart.html#bpy-types-objectlineart-use-crease-override"),
|
||||
("bpy.types.objectlineart.use_crease_override*", "scene_layout/object/properties/line_art.html#bpy-types-objectlineart-use-crease-override"),
|
||||
("bpy.types.rendersettings.preview_pixel_size*", "render/cycles/render_settings/performance.html#bpy-types-rendersettings-preview-pixel-size"),
|
||||
("bpy.types.rendersettings.use_crop_to_border*", "render/output/properties/dimensions.html#bpy-types-rendersettings-use-crop-to-border"),
|
||||
("bpy.types.rendersettings.use_file_extension*", "render/output/properties/output.html#bpy-types-rendersettings-use-file-extension"),
|
||||
|
@ -449,7 +449,7 @@ url_manual_mapping = (
|
|||
("bpy.types.nodesocketinterface*.max_value*", "interface/controls/nodes/groups.html#bpy-types-nodesocketinterface-max-value"),
|
||||
("bpy.types.nodesocketinterface*.min_value*", "interface/controls/nodes/groups.html#bpy-types-nodesocketinterface-min-value"),
|
||||
("bpy.types.nodesocketinterface.hide_value*", "interface/controls/nodes/groups.html#bpy-types-nodesocketinterface-hide-value"),
|
||||
("bpy.types.objectlineart.crease_threshold*", "scene_layout/object/properties/lineart.html#bpy-types-objectlineart-crease-threshold"),
|
||||
("bpy.types.objectlineart.crease_threshold*", "scene_layout/object/properties/line_art.html#bpy-types-objectlineart-crease-threshold"),
|
||||
("bpy.types.rendersettings.use_compositing*", "render/output/properties/post_processing.html#bpy-types-rendersettings-use-compositing"),
|
||||
("bpy.types.rendersettings.use_placeholder*", "render/output/properties/output.html#bpy-types-rendersettings-use-placeholder"),
|
||||
("bpy.types.shadernodesubsurfacescattering*", "render/shader_nodes/shader/sss.html#bpy-types-shadernodesubsurfacescattering"),
|
||||
|
@ -487,6 +487,7 @@ url_manual_mapping = (
|
|||
("bpy.types.fluidflowsettings.temperature*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-temperature"),
|
||||
("bpy.types.fluidflowsettings.use_texture*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-use-texture"),
|
||||
("bpy.types.fmodifierenvelopecontrolpoint*", "editors/graph_editor/fcurves/sidebar/modifiers.html#bpy-types-fmodifierenvelopecontrolpoint"),
|
||||
("bpy.types.geometrynodeattributemaprange*", "modeling/geometry_nodes/attribute/attribute_map_range.html#bpy-types-geometrynodeattributemaprange"),
|
||||
("bpy.types.layercollection.hide_viewport*", "editors/outliner/interface.html#bpy-types-layercollection-hide-viewport"),
|
||||
("bpy.types.layercollection.indirect_only*", "editors/outliner/interface.html#bpy-types-layercollection-indirect-only"),
|
||||
("bpy.types.material.use_sss_translucency*", "render/eevee/materials/settings.html#bpy-types-material-use-sss-translucency"),
|
||||
|
@ -947,7 +948,7 @@ url_manual_mapping = (
|
|||
("bpy.types.imagepaint.use_occlude*", "sculpt_paint/texture_paint/tool_settings/options.html#bpy-types-imagepaint-use-occlude"),
|
||||
("bpy.types.imagesequence.use_flip*", "video_editing/sequencer/sidebar/strip.html#bpy-types-imagesequence-use-flip"),
|
||||
("bpy.types.latticegpencilmodifier*", "grease_pencil/modifiers/deform/lattice.html#bpy-types-latticegpencilmodifier"),
|
||||
("bpy.types.lineartgpencilmodifier*", "grease_pencil/modifiers/generate/lineart.html#bpy-types-lineartgpencilmodifier"),
|
||||
("bpy.types.lineartgpencilmodifier*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier"),
|
||||
("bpy.types.mesh.auto_smooth_angle*", "modeling/meshes/structure.html#bpy-types-mesh-auto-smooth-angle"),
|
||||
("bpy.types.objectsolverconstraint*", "animation/constraints/motion_tracking/object_solver.html#bpy-types-objectsolverconstraint"),
|
||||
("bpy.types.opacitygpencilmodifier*", "grease_pencil/modifiers/color/opacity.html#bpy-types-opacitygpencilmodifier"),
|
||||
|
@ -1110,6 +1111,7 @@ url_manual_mapping = (
|
|||
("bpy.types.ffmpegsettings.audio*", "render/output/properties/output.html#bpy-types-ffmpegsettings-audio"),
|
||||
("bpy.types.followpathconstraint*", "animation/constraints/relationship/follow_path.html#bpy-types-followpathconstraint"),
|
||||
("bpy.types.gaussianblursequence*", "video_editing/sequencer/strips/effects/blur.html#bpy-types-gaussianblursequence"),
|
||||
("bpy.types.geometrynodeboundbox*", "modeling/geometry_nodes/geometry/bounding_box.html#bpy-types-geometrynodeboundbox"),
|
||||
("bpy.types.geometrynodemeshcone*", "modeling/geometry_nodes/mesh_primitives/cone.html#bpy-types-geometrynodemeshcone"),
|
||||
("bpy.types.geometrynodemeshcube*", "modeling/geometry_nodes/mesh_primitives/cube.html#bpy-types-geometrynodemeshcube"),
|
||||
("bpy.types.geometrynodemeshgrid*", "modeling/geometry_nodes/mesh_primitives/grid.html#bpy-types-geometrynodemeshgrid"),
|
||||
|
@ -1152,6 +1154,7 @@ url_manual_mapping = (
|
|||
("bpy.ops.clip.set_scene_frames*", "movie_clip/tracking/clip/editing/clip.html#bpy-ops-clip-set-scene-frames"),
|
||||
("bpy.ops.curve.handle_type_set*", "modeling/curves/editing/control_points.html#bpy-ops-curve-handle-type-set"),
|
||||
("bpy.ops.curve.spline_type_set*", "modeling/curves/editing/curve.html#bpy-ops-curve-spline-type-set"),
|
||||
("bpy.ops.file.unpack_libraries*", "files/blend/packed_data.html#bpy-ops-file-unpack-libraries"),
|
||||
("bpy.ops.gpencil.move_to_layer*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-move-to-layer"),
|
||||
("bpy.ops.gpencil.stroke_sample*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-sample"),
|
||||
("bpy.ops.gpencil.stroke_smooth*", "grease_pencil/modes/edit/point_menu.html#bpy-ops-gpencil-stroke-smooth"),
|
||||
|
@ -1219,7 +1222,7 @@ url_manual_mapping = (
|
|||
("bpy.types.mesh.use_paint_mask*", "sculpt_paint/brush/introduction.html#bpy-types-mesh-use-paint-mask"),
|
||||
("bpy.types.movietrackingcamera*", "movie_clip/tracking/clip/sidebar/track/camera.html#bpy-types-movietrackingcamera"),
|
||||
("bpy.types.object.display_type*", "scene_layout/object/properties/display.html#bpy-types-object-display-type"),
|
||||
("bpy.types.objectlineart.usage*", "scene_layout/object/properties/lineart.html#bpy-types-objectlineart-usage"),
|
||||
("bpy.types.objectlineart.usage*", "scene_layout/object/properties/line_art.html#bpy-types-objectlineart-usage"),
|
||||
("bpy.types.particledupliweight*", "physics/particles/emitter/vertex_groups.html#bpy-types-particledupliweight"),
|
||||
("bpy.types.poseboneconstraints*", "animation/armatures/posing/bone_constraints/index.html#bpy-types-poseboneconstraints"),
|
||||
("bpy.types.rigidbodyconstraint*", "physics/rigid_body/constraints/index.html#bpy-types-rigidbodyconstraint"),
|
||||
|
@ -1260,6 +1263,7 @@ url_manual_mapping = (
|
|||
("bpy.ops.console.autocomplete*", "editors/python_console.html#bpy-ops-console-autocomplete"),
|
||||
("bpy.ops.curve.dissolve_verts*", "modeling/curves/editing/curve.html#bpy-ops-curve-dissolve-verts"),
|
||||
("bpy.ops.curve.duplicate_move*", "modeling/curves/editing/curve.html#bpy-ops-curve-duplicate-move"),
|
||||
("bpy.ops.file.autopack_toggle*", "files/blend/packed_data.html#bpy-ops-file-autopack-toggle"),
|
||||
("bpy.ops.fluid.bake_particles*", "physics/fluid/type/domain/liquid/particles.html#bpy-ops-fluid-bake-particles"),
|
||||
("bpy.ops.fluid.free_particles*", "physics/fluid/type/domain/liquid/particles.html#bpy-ops-fluid-free-particles"),
|
||||
("bpy.ops.gpencil.extrude_move*", "grease_pencil/modes/edit/point_menu.html#bpy-ops-gpencil-extrude-move"),
|
||||
|
@ -1297,6 +1301,7 @@ url_manual_mapping = (
|
|||
("bpy.types.alphaundersequence*", "video_editing/sequencer/strips/effects/alpha_over_under_overdrop.html#bpy-types-alphaundersequence"),
|
||||
("bpy.types.armature.show_axes*", "animation/armatures/properties/display.html#bpy-types-armature-show-axes"),
|
||||
("bpy.types.armatureconstraint*", "animation/constraints/relationship/armature.html#bpy-types-armatureconstraint"),
|
||||
("bpy.types.compositornodeblur*", "compositing/types/filter/blur_node.html#bpy-types-compositornodeblur"),
|
||||
("bpy.types.compositornodecomb*", "editors/texture_node/types/color/combine_separate.html#bpy-types-compositornodecomb"),
|
||||
("bpy.types.compositornodecrop*", "compositing/types/distort/crop.html#bpy-types-compositornodecrop"),
|
||||
("bpy.types.compositornodeflip*", "compositing/types/distort/flip.html#bpy-types-compositornodeflip"),
|
||||
|
@ -1358,6 +1363,7 @@ url_manual_mapping = (
|
|||
("bpy.ops.curve.primitive*add*", "modeling/curves/primitives.html#bpy-ops-curve-primitive-add"),
|
||||
("bpy.ops.curve.smooth_radius*", "modeling/curves/editing/control_points.html#bpy-ops-curve-smooth-radius"),
|
||||
("bpy.ops.curve.smooth_weight*", "modeling/curves/editing/control_points.html#bpy-ops-curve-smooth-weight"),
|
||||
("bpy.ops.file.pack_libraries*", "files/blend/packed_data.html#bpy-ops-file-pack-libraries"),
|
||||
("bpy.ops.font.change_spacing*", "modeling/texts/editing.html#bpy-ops-font-change-spacing"),
|
||||
("bpy.ops.gpencil.stroke_flip*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-flip"),
|
||||
("bpy.ops.gpencil.stroke_join*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-join"),
|
||||
|
@ -1453,7 +1459,7 @@ url_manual_mapping = (
|
|||
("bpy.types.viewlayer.use_sky*", "render/layers/introduction.html#bpy-types-viewlayer-use-sky"),
|
||||
("bpy.types.wireframemodifier*", "modeling/modifiers/generate/wireframe.html#bpy-types-wireframemodifier"),
|
||||
("bpy.types.worldmistsettings*", "render/cycles/world_settings.html#bpy-types-worldmistsettings"),
|
||||
("bpy.ops.anim.channels_move*", "editors/nla/editing.html#bpy-ops-anim-channels-move"),
|
||||
("bpy.ops.anim.channels_move*", "editors/graph_editor/channels.html#bpy-ops-anim-channels-move"),
|
||||
("bpy.ops.buttons.toggle_pin*", "editors/properties_editor.html#bpy-ops-buttons-toggle-pin"),
|
||||
("bpy.ops.clip.filter_tracks*", "movie_clip/tracking/clip/editing/track.html#bpy-ops-clip-filter-tracks"),
|
||||
("bpy.ops.clip.select_circle*", "movie_clip/tracking/clip/selecting.html#bpy-ops-clip-select-circle"),
|
||||
|
@ -1691,6 +1697,7 @@ url_manual_mapping = (
|
|||
("bpy.ops.clip.set_origin*", "movie_clip/tracking/clip/editing/reconstruction.html#bpy-ops-clip-set-origin"),
|
||||
("bpy.ops.curve.subdivide*", "modeling/curves/editing/segments.html#bpy-ops-curve-subdivide"),
|
||||
("bpy.ops.ed.undo_history*", "interface/undo_redo.html#bpy-ops-ed-undo-history"),
|
||||
("bpy.ops.file.unpack_all*", "files/blend/packed_data.html#bpy-ops-file-unpack-all"),
|
||||
("bpy.ops.fluid.bake_data*", "physics/fluid/type/domain/settings.html#bpy-ops-fluid-bake-data"),
|
||||
("bpy.ops.fluid.bake_mesh*", "physics/fluid/type/domain/liquid/mesh.html#bpy-ops-fluid-bake-mesh"),
|
||||
("bpy.ops.fluid.free_data*", "physics/fluid/type/domain/settings.html#bpy-ops-fluid-free-data"),
|
||||
|
@ -1749,7 +1756,7 @@ url_manual_mapping = (
|
|||
("bpy.types.nlastrip.name*", "editors/nla/sidebar.html#bpy-types-nlastrip-name"),
|
||||
("bpy.types.nodesmodifier*", "modeling/modifiers/generate/geometry_nodes.html#bpy-types-nodesmodifier"),
|
||||
("bpy.types.object.parent*", "scene_layout/object/editing/parent.html#bpy-types-object-parent"),
|
||||
("bpy.types.objectlineart*", "scene_layout/object/properties/lineart.html#bpy-types-objectlineart"),
|
||||
("bpy.types.objectlineart*", "scene_layout/object/properties/line_art.html#bpy-types-objectlineart"),
|
||||
("bpy.types.oceanmodifier*", "modeling/modifiers/physics/ocean.html#bpy-types-oceanmodifier"),
|
||||
("bpy.types.particlebrush*", "physics/particles/mode.html#bpy-types-particlebrush"),
|
||||
("bpy.types.scene.gravity*", "physics/forces/gravity.html#bpy-types-scene-gravity"),
|
||||
|
@ -1845,6 +1852,7 @@ url_manual_mapping = (
|
|||
("bpy.types.wipesequence*", "video_editing/sequencer/strips/transitions/wipe.html#bpy-types-wipesequence"),
|
||||
("bpy.ops.clip.prefetch*", "movie_clip/tracking/clip/editing/clip.html#bpy-ops-clip-prefetch"),
|
||||
("bpy.ops.clip.set_axis*", "movie_clip/tracking/clip/editing/reconstruction.html#bpy-ops-clip-set-axis"),
|
||||
("bpy.ops.file.pack_all*", "files/blend/packed_data.html#bpy-ops-file-pack-all"),
|
||||
("bpy.ops.gpencil.paste*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-paste"),
|
||||
("bpy.ops.image.project*", "sculpt_paint/texture_paint/tool_settings/options.html#bpy-ops-image-project"),
|
||||
("bpy.ops.material.copy*", "render/materials/assignment.html#bpy-ops-material-copy"),
|
||||
|
@ -2115,9 +2123,4 @@ url_manual_mapping = (
|
|||
("bpy.ops.ed*", "interface/undo_redo.html#bpy-ops-ed"),
|
||||
("bpy.ops.ui*", "interface/index.html#bpy-ops-ui"),
|
||||
("bpy.ops.wm*", "interface/index.html#bpy-ops-wm"),
|
||||
("bpy.ops.file.pack_all", "blend/packed_data#pack-resources"),
|
||||
("bpy.ops.file.unpack_all", "blend/packed_data#unpack-resources"),
|
||||
("bpy.ops.file.autopack_toggle", "blend/packed_data#automatically-pack-resources"),
|
||||
("bpy.ops.file.pack_libraries", "blend/packed_data#pack-linked-libraries"),
|
||||
("bpy.ops.file.unpack_libraries", "blend/packed_data#unpack-linked-libraries"),
|
||||
)
|
||||
|
|
|
@ -278,15 +278,11 @@ def _template_items_uv_select_mode(params):
|
|||
else:
|
||||
return [
|
||||
*_template_items_editmode_mesh_select_mode(params),
|
||||
# Hack to prevent fall-through, when sync select isn't enabled (and the island button isn't visible).
|
||||
("mesh.select_mode", {"type": 'FOUR', "value": 'PRESS'}, None),
|
||||
("wm.context_set_enum", {"type": 'ONE', "value": 'PRESS'},
|
||||
{"properties": [("data_path", 'tool_settings.uv_select_mode'), ("value", 'VERTEX')]}),
|
||||
("wm.context_set_enum", {"type": 'TWO', "value": 'PRESS'},
|
||||
{"properties": [("data_path", 'tool_settings.uv_select_mode'), ("value", 'EDGE')]}),
|
||||
("wm.context_set_enum", {"type": 'THREE', "value": 'PRESS'},
|
||||
{"properties": [("data_path", 'tool_settings.uv_select_mode'), ("value", 'FACE')]}),
|
||||
("wm.context_set_enum", {"type": 'FOUR', "value": 'PRESS'},
|
||||
{"properties": [("data_path", 'tool_settings.uv_select_mode'), ("value", 'ISLAND')]}),
|
||||
*(("wm.context_set_enum", {"type": NUMBERS_1[i], "value": 'PRESS'},
|
||||
{"properties": [("data_path", 'tool_settings.uv_select_mode'), ("value", ty)]})
|
||||
for i, ty in enumerate(('VERTEX', 'EDGE', 'FACE', 'ISLAND')))
|
||||
]
|
||||
|
||||
|
||||
|
@ -2009,8 +2005,7 @@ def km_file_browser_main(params):
|
|||
)
|
||||
|
||||
items.extend([
|
||||
("file.execute", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'},
|
||||
{"properties": [("need_active", True)]}),
|
||||
("file.mouse_execute", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'}, None),
|
||||
# Both .execute and .select are needed here. The former only works if
|
||||
# there's a file operator (i.e. not in regular editor mode) but is
|
||||
# needed to load files. The latter makes selection work if there's no
|
||||
|
@ -3382,6 +3377,11 @@ def km_grease_pencil_stroke_paint_mode(params):
|
|||
# Brush size
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_paint.brush.size')]}),
|
||||
# Increase/Decrease brush size
|
||||
("brush.scale_size", {"type": 'LEFT_BRACKET', "value": 'PRESS', "repeat": True},
|
||||
{"properties": [("scalar", 0.9)]}),
|
||||
("brush.scale_size", {"type": 'RIGHT_BRACKET', "value": 'PRESS', "repeat": True},
|
||||
{"properties": [("scalar", 1.0 / 0.9)]}),
|
||||
# Draw delete menu
|
||||
op_menu("GPENCIL_MT_gpencil_draw_delete", {"type": 'X', "value": 'PRESS'}),
|
||||
# Animation menu
|
||||
|
@ -3549,6 +3549,11 @@ def km_grease_pencil_stroke_sculpt_mode(params):
|
|||
# Brush size
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_sculpt_paint.brush.size')]}),
|
||||
# Increase/Decrease brush size
|
||||
("brush.scale_size", {"type": 'LEFT_BRACKET', "value": 'PRESS', "repeat": True},
|
||||
{"properties": [("scalar", 0.9)]}),
|
||||
("brush.scale_size", {"type": 'RIGHT_BRACKET', "value": 'PRESS', "repeat": True},
|
||||
{"properties": [("scalar", 1.0 / 0.9)]}),
|
||||
# Copy
|
||||
("gpencil.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
|
||||
# Display
|
||||
|
@ -3763,6 +3768,11 @@ def km_grease_pencil_stroke_weight_mode(params):
|
|||
# Brush size
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_weight_paint.brush.size')]}),
|
||||
# Increase/Decrease brush size
|
||||
("brush.scale_size", {"type": 'LEFT_BRACKET', "value": 'PRESS', "repeat": True},
|
||||
{"properties": [("scalar", 0.9)]}),
|
||||
("brush.scale_size", {"type": 'RIGHT_BRACKET', "value": 'PRESS', "repeat": True},
|
||||
{"properties": [("scalar", 1.0 / 0.9)]}),
|
||||
# Display
|
||||
*_grease_pencil_display(),
|
||||
# Keyframe menu
|
||||
|
@ -3820,6 +3830,11 @@ def km_grease_pencil_stroke_vertex_mode(params):
|
|||
# Brush size
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.size')]}),
|
||||
# Increase/Decrease brush size
|
||||
("brush.scale_size", {"type": 'LEFT_BRACKET', "value": 'PRESS', "repeat": True},
|
||||
{"properties": [("scalar", 0.9)]}),
|
||||
("brush.scale_size", {"type": 'RIGHT_BRACKET', "value": 'PRESS', "repeat": True},
|
||||
{"properties": [("scalar", 1.0 / 0.9)]}),
|
||||
# Display
|
||||
*_grease_pencil_display(),
|
||||
# Tools
|
||||
|
|
|
@ -1263,8 +1263,7 @@ def km_file_browser_main(params):
|
|||
)
|
||||
|
||||
items.extend([
|
||||
("file.execute", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'},
|
||||
{"properties": [("need_active", True)]}),
|
||||
("file.mouse_execute", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'}, None),
|
||||
("file.refresh", {"type": 'R', "value": 'PRESS', "ctrl": True}, None),
|
||||
("file.select", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'}, None),
|
||||
("file.select", {"type": 'LEFTMOUSE', "value": 'CLICK'},
|
||||
|
|
|
@ -130,6 +130,7 @@ class PlayRenderedAnim(Operator):
|
|||
"-s", str(frame_start),
|
||||
"-e", str(frame_end),
|
||||
"-j", str(scene.frame_step),
|
||||
"-c", str(prefs.system.memory_cache_limit),
|
||||
file,
|
||||
]
|
||||
cmd.extend(opts)
|
||||
|
|
|
@ -292,10 +292,15 @@ class BONE_PT_display_custom_shape(BoneButtonsPanel, Panel):
|
|||
sub = col.column()
|
||||
sub.active = bool(pchan and pchan.custom_shape)
|
||||
sub.separator()
|
||||
sub.prop(pchan, "custom_shape_scale", text="Scale")
|
||||
|
||||
sub.prop(pchan, "custom_shape_scale_xyz", text="Scale")
|
||||
sub.prop(pchan, "custom_shape_translation", text="Translation")
|
||||
sub.prop(pchan, "custom_shape_rotation_euler", text="Rotation")
|
||||
|
||||
sub.prop_search(pchan, "custom_shape_transform",
|
||||
ob.pose, "bones", text="Override Transform")
|
||||
sub.prop(pchan, "use_custom_shape_bone_size")
|
||||
|
||||
sub.separator()
|
||||
sub.prop(bone, "show_wire", text="Wireframe")
|
||||
|
||||
|
|
|
@ -113,7 +113,8 @@ class GPENCIL_MT_layer_context_menu(Menu):
|
|||
layout.operator("gpencil.layer_merge", icon='SORT_ASC', text="Merge Down")
|
||||
|
||||
layout.separator()
|
||||
layout.menu("VIEW3D_MT_gpencil_copy_layer")
|
||||
layout.menu("VIEW3D_MT_gpencil_append_active_layer")
|
||||
layout.menu("VIEW3D_MT_gpencil_append_all_layers")
|
||||
|
||||
|
||||
class DATA_PT_gpencil_layers(DataButtonsPanel, Panel):
|
||||
|
|
|
@ -53,6 +53,10 @@ class GPENCIL_MT_material_context_menu(Menu):
|
|||
layout.operator("gpencil.material_to_vertex_color", text="Convert Materials to Vertex Color")
|
||||
layout.operator("gpencil.extract_palette_vertex", text="Extract Palette from Vertex Color")
|
||||
|
||||
layout.separator()
|
||||
layout.menu("VIEW3D_MT_gpencil_append_active_material")
|
||||
layout.menu("VIEW3D_MT_gpencil_append_all_materials")
|
||||
|
||||
|
||||
class GPENCIL_UL_matslots(UIList):
|
||||
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
|
||||
|
|
|
@ -1289,7 +1289,7 @@ def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=False)
|
|||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "fill_factor")
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "dilate_pixels")
|
||||
row.prop(gp_settings, "dilate")
|
||||
row = layout.row(align=True)
|
||||
row.prop(brush, "size", text="Thickness")
|
||||
layout.use_property_split = use_property_split_prev
|
||||
|
|
|
@ -300,6 +300,8 @@ class TIME_PT_keyframing_settings(TimelinePanelButtons, Panel):
|
|||
col.label(text="New Keyframe Type")
|
||||
col.prop(tool_settings, "keyframe_type", text="")
|
||||
|
||||
layout.prop(tool_settings, "use_keyframe_cycle_aware")
|
||||
|
||||
|
||||
class TIME_PT_auto_keyframing(TimelinePanelButtons, Panel):
|
||||
bl_label = "Auto Keyframing"
|
||||
|
@ -327,8 +329,6 @@ class TIME_PT_auto_keyframing(TimelinePanelButtons, Panel):
|
|||
if not prefs.edit.use_keyframe_insert_available:
|
||||
col.prop(tool_settings, "use_record_with_nla", text="Layered Recording")
|
||||
|
||||
col.prop(tool_settings, "use_keyframe_cycle_aware")
|
||||
|
||||
|
||||
###################################
|
||||
|
||||
|
|
|
@ -4956,26 +4956,73 @@ class VIEW3D_MT_assign_material(Menu):
|
|||
icon='LAYER_ACTIVE' if mat == mat_active else 'BLANK1').material = mat.name
|
||||
|
||||
|
||||
class VIEW3D_MT_gpencil_copy_layer(Menu):
|
||||
bl_label = "Copy Layer to Object"
|
||||
def gpencil_layer_append_menu_items(context, layout, only_active):
|
||||
done = False
|
||||
view_layer = context.view_layer
|
||||
obact = context.active_object
|
||||
gpl = context.active_gpencil_layer
|
||||
|
||||
done = False
|
||||
if gpl is not None:
|
||||
for ob in view_layer.objects:
|
||||
if ob.type == 'GPENCIL' and ob != obact:
|
||||
op = layout.operator("gpencil.layer_duplicate_object", text=ob.name)
|
||||
op.object = ob.name
|
||||
op.only_active = only_active
|
||||
done = True
|
||||
|
||||
if done is False:
|
||||
layout.label(text="No destination object", icon='ERROR')
|
||||
else:
|
||||
layout.label(text="No layer to copy", icon='ERROR')
|
||||
|
||||
|
||||
class VIEW3D_MT_gpencil_append_active_layer(Menu):
|
||||
bl_label = "Append Active Layer to Object"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
view_layer = context.view_layer
|
||||
obact = context.active_object
|
||||
gpl = context.active_gpencil_layer
|
||||
gpencil_layer_append_menu_items(context, layout, True)
|
||||
|
||||
done = False
|
||||
if gpl is not None:
|
||||
for ob in view_layer.objects:
|
||||
if ob.type == 'GPENCIL' and ob != obact:
|
||||
layout.operator("gpencil.layer_duplicate_object", text=ob.name).object = ob.name
|
||||
done = True
|
||||
|
||||
if done is False:
|
||||
layout.label(text="No destination object", icon='ERROR')
|
||||
else:
|
||||
layout.label(text="No layer to copy", icon='ERROR')
|
||||
class VIEW3D_MT_gpencil_append_all_layers(Menu):
|
||||
bl_label = "Append All Layers to Object"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
gpencil_layer_append_menu_items(context, layout, False)
|
||||
|
||||
|
||||
def gpencil_material_menu_items(context, layout, only_selected):
|
||||
done = False
|
||||
view_layer = context.view_layer
|
||||
obact = context.active_object
|
||||
|
||||
for ob in view_layer.objects:
|
||||
if ob.type == 'GPENCIL' and ob != obact:
|
||||
op = layout.operator("gpencil.materials_append_to_object", text=ob.name)
|
||||
op.object = ob.name
|
||||
op.only_selected = only_selected
|
||||
done = True
|
||||
|
||||
if done is False:
|
||||
layout.label(text="No destination object", icon='ERROR')
|
||||
|
||||
|
||||
class VIEW3D_MT_gpencil_append_active_material(Menu):
|
||||
bl_label = "Append Active Material to Object"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
gpencil_material_menu_items(context, layout, True)
|
||||
|
||||
|
||||
class VIEW3D_MT_gpencil_append_all_materials(Menu):
|
||||
bl_label = "Append All Materials to Object"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
gpencil_material_menu_items(context, layout, False)
|
||||
|
||||
|
||||
class VIEW3D_MT_edit_gpencil(Menu):
|
||||
|
@ -6191,10 +6238,7 @@ class VIEW3D_PT_overlay_geometry(Panel):
|
|||
sub.prop(overlay, "wireframe_opacity", text="Opacity")
|
||||
|
||||
row = col.row(align=True)
|
||||
if context.mode not in {
|
||||
'EDIT_ARMATURE', 'POSE', 'OBJECT',
|
||||
'PAINT_GPENCIL', 'VERTEX_GPENCIL', 'WEIGHT_GPENCIL', 'SCULPT_GPENCIL', 'EDIT_GPENCIL',
|
||||
}:
|
||||
if context.mode != 'OBJECT':
|
||||
row.prop(overlay, "show_fade_inactive", text="")
|
||||
sub = row.row()
|
||||
sub.active = overlay.show_fade_inactive
|
||||
|
@ -7645,7 +7689,10 @@ classes = (
|
|||
VIEW3D_MT_weight_gpencil,
|
||||
VIEW3D_MT_gpencil_animation,
|
||||
VIEW3D_MT_gpencil_simplify,
|
||||
VIEW3D_MT_gpencil_copy_layer,
|
||||
VIEW3D_MT_gpencil_append_active_layer,
|
||||
VIEW3D_MT_gpencil_append_all_layers,
|
||||
VIEW3D_MT_gpencil_append_active_material,
|
||||
VIEW3D_MT_gpencil_append_all_materials,
|
||||
VIEW3D_MT_gpencil_autoweights,
|
||||
VIEW3D_MT_gpencil_edit_context_menu,
|
||||
VIEW3D_MT_edit_curve,
|
||||
|
|
|
@ -488,11 +488,13 @@ geometry_node_categories = [
|
|||
NodeItem("GeometryNodeAttributeClamp"),
|
||||
NodeItem("GeometryNodeAttributeCompare"),
|
||||
NodeItem("GeometryNodeAttributeConvert"),
|
||||
NodeItem("GeometryNodeAttributeCurveMap"),
|
||||
NodeItem("GeometryNodeAttributeFill"),
|
||||
NodeItem("GeometryNodeAttributeMix"),
|
||||
NodeItem("GeometryNodeAttributeProximity"),
|
||||
NodeItem("GeometryNodeAttributeColorRamp"),
|
||||
NodeItem("GeometryNodeAttributeVectorMath"),
|
||||
NodeItem("GeometryNodeAttributeVectorRotate"),
|
||||
NodeItem("GeometryNodeAttributeSampleTexture"),
|
||||
NodeItem("GeometryNodeAttributeCombineXYZ"),
|
||||
NodeItem("GeometryNodeAttributeSeparateXYZ"),
|
||||
|
@ -507,6 +509,7 @@ geometry_node_categories = [
|
|||
]),
|
||||
GeometryNodeCategory("GEO_CURVE", "Curve", items=[
|
||||
NodeItem("GeometryNodeCurveToMesh"),
|
||||
NodeItem("GeometryNodeCurveResample"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_GEOMETRY", "Geometry", items=[
|
||||
NodeItem("GeometryNodeBoundBox"),
|
||||
|
|
|
@ -597,6 +597,7 @@ class InstancesComponent : public GeometryComponent {
|
|||
void clear();
|
||||
|
||||
void reserve(int min_capacity);
|
||||
void resize(int capacity);
|
||||
|
||||
int add_reference(InstanceReference reference);
|
||||
void add_instance(int instance_handle, const blender::float4x4 &transform, const int id = -1);
|
||||
|
@ -604,6 +605,7 @@ class InstancesComponent : public GeometryComponent {
|
|||
blender::Span<InstanceReference> references() const;
|
||||
|
||||
blender::Span<int> instance_reference_handles() const;
|
||||
blender::MutableSpan<int> instance_reference_handles();
|
||||
blender::MutableSpan<blender::float4x4> instance_transforms();
|
||||
blender::Span<blender::float4x4> instance_transforms() const;
|
||||
blender::MutableSpan<int> instance_ids();
|
||||
|
|
|
@ -85,10 +85,12 @@ bool BKE_lib_override_library_resync(struct Main *bmain,
|
|||
struct ID *id_root,
|
||||
struct Collection *override_resync_residual_storage,
|
||||
const bool do_hierarchy_enforce,
|
||||
const bool do_post_process);
|
||||
const bool do_post_process,
|
||||
struct ReportList *reports);
|
||||
void BKE_lib_override_library_main_resync(struct Main *bmain,
|
||||
struct Scene *scene,
|
||||
struct ViewLayer *view_layer);
|
||||
struct ViewLayer *view_layer,
|
||||
struct ReportList *reports);
|
||||
|
||||
void BKE_lib_override_library_delete(struct Main *bmain, struct ID *id_root);
|
||||
|
||||
|
|
|
@ -446,8 +446,8 @@ bool BKE_modifier_is_preview(struct ModifierData *md);
|
|||
void BKE_modifiers_foreach_ID_link(struct Object *ob, IDWalkFunc walk, void *userData);
|
||||
void BKE_modifiers_foreach_tex_link(struct Object *ob, TexWalkFunc walk, void *userData);
|
||||
|
||||
struct ModifierData *BKE_modifiers_findby_type(struct Object *ob, ModifierType type);
|
||||
struct ModifierData *BKE_modifiers_findby_name(struct Object *ob, const char *name);
|
||||
struct ModifierData *BKE_modifiers_findby_type(const struct Object *ob, ModifierType type);
|
||||
struct ModifierData *BKE_modifiers_findby_name(const struct Object *ob, const char *name);
|
||||
void BKE_modifiers_clear_errors(struct Object *ob);
|
||||
int BKE_modifiers_get_cage_index(const struct Scene *scene,
|
||||
struct Object *ob,
|
||||
|
|
|
@ -1419,6 +1419,9 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
|
|||
#define GEO_NODE_SWITCH 1043
|
||||
#define GEO_NODE_ATTRIBUTE_TRANSFER 1044
|
||||
#define GEO_NODE_CURVE_TO_MESH 1045
|
||||
#define GEO_NODE_ATTRIBUTE_CURVE_MAP 1046
|
||||
#define GEO_NODE_CURVE_RESAMPLE 1047
|
||||
#define GEO_NODE_ATTRIBUTE_VECTOR_ROTATE 1048
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -1,153 +0,0 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*
|
||||
* A PersistentDataHandle is a weak reference to some data in a Blender file. The handle itself is
|
||||
* just a number. A PersistentDataHandleMap is used to convert between handles and the actual data.
|
||||
*/
|
||||
|
||||
#include "BLI_map.hh"
|
||||
|
||||
#include "DNA_ID.h"
|
||||
|
||||
struct Collection;
|
||||
struct Object;
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
class PersistentDataHandleMap;
|
||||
|
||||
class PersistentDataHandle {
|
||||
private:
|
||||
/* Negative values indicate that the handle is "empty". */
|
||||
int32_t handle_;
|
||||
|
||||
friend PersistentDataHandleMap;
|
||||
|
||||
protected:
|
||||
PersistentDataHandle(int handle) : handle_(handle)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
PersistentDataHandle() : handle_(-1)
|
||||
{
|
||||
}
|
||||
|
||||
friend bool operator==(const PersistentDataHandle &a, const PersistentDataHandle &b)
|
||||
{
|
||||
return a.handle_ == b.handle_;
|
||||
}
|
||||
|
||||
friend bool operator!=(const PersistentDataHandle &a, const PersistentDataHandle &b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &stream, const PersistentDataHandle &a)
|
||||
{
|
||||
stream << a.handle_;
|
||||
return stream;
|
||||
}
|
||||
|
||||
uint64_t hash() const
|
||||
{
|
||||
return static_cast<uint64_t>(handle_);
|
||||
}
|
||||
};
|
||||
|
||||
class PersistentIDHandle : public PersistentDataHandle {
|
||||
friend PersistentDataHandleMap;
|
||||
using PersistentDataHandle::PersistentDataHandle;
|
||||
};
|
||||
|
||||
class PersistentObjectHandle : public PersistentIDHandle {
|
||||
friend PersistentDataHandleMap;
|
||||
using PersistentIDHandle::PersistentIDHandle;
|
||||
};
|
||||
|
||||
class PersistentCollectionHandle : public PersistentIDHandle {
|
||||
friend PersistentDataHandleMap;
|
||||
using PersistentIDHandle::PersistentIDHandle;
|
||||
};
|
||||
|
||||
class PersistentDataHandleMap {
|
||||
private:
|
||||
Map<int32_t, ID *> id_by_handle_;
|
||||
Map<ID *, int32_t> handle_by_id_;
|
||||
|
||||
public:
|
||||
void add(int32_t handle, ID &id)
|
||||
{
|
||||
BLI_assert(handle >= 0);
|
||||
handle_by_id_.add(&id, handle);
|
||||
id_by_handle_.add(handle, &id);
|
||||
}
|
||||
|
||||
PersistentIDHandle lookup(ID *id) const
|
||||
{
|
||||
const int handle = handle_by_id_.lookup_default(id, -1);
|
||||
return PersistentIDHandle(handle);
|
||||
}
|
||||
|
||||
PersistentObjectHandle lookup(Object *object) const
|
||||
{
|
||||
const int handle = handle_by_id_.lookup_default((ID *)object, -1);
|
||||
return PersistentObjectHandle(handle);
|
||||
}
|
||||
|
||||
PersistentCollectionHandle lookup(Collection *collection) const
|
||||
{
|
||||
const int handle = handle_by_id_.lookup_default((ID *)collection, -1);
|
||||
return PersistentCollectionHandle(handle);
|
||||
}
|
||||
|
||||
ID *lookup(const PersistentIDHandle &handle) const
|
||||
{
|
||||
ID *id = id_by_handle_.lookup_default(handle.handle_, nullptr);
|
||||
return id;
|
||||
}
|
||||
|
||||
Object *lookup(const PersistentObjectHandle &handle) const
|
||||
{
|
||||
ID *id = this->lookup((const PersistentIDHandle &)handle);
|
||||
if (id == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (GS(id->name) != ID_OB) {
|
||||
return nullptr;
|
||||
}
|
||||
return (Object *)id;
|
||||
}
|
||||
|
||||
Collection *lookup(const PersistentCollectionHandle &handle) const
|
||||
{
|
||||
ID *id = this->lookup((const PersistentIDHandle &)handle);
|
||||
if (id == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (GS(id->name) != ID_GR) {
|
||||
return nullptr;
|
||||
}
|
||||
return (Collection *)id;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender::bke
|
|
@ -47,7 +47,7 @@ typedef struct BodyPoint {
|
|||
} BodyPoint;
|
||||
|
||||
/* allocates and initializes general main data */
|
||||
extern struct SoftBody *sbNew(struct Scene *scene);
|
||||
extern struct SoftBody *sbNew(void);
|
||||
|
||||
/* frees internal data and soft-body itself */
|
||||
extern void sbFree(struct Object *ob);
|
||||
|
|
|
@ -113,6 +113,7 @@ class Spline {
|
|||
bool is_cyclic() const;
|
||||
void set_cyclic(const bool value);
|
||||
|
||||
virtual void resize(const int size) = 0;
|
||||
virtual blender::MutableSpan<blender::float3> positions() = 0;
|
||||
virtual blender::Span<blender::float3> positions() const = 0;
|
||||
virtual blender::MutableSpan<float> radii() = 0;
|
||||
|
@ -163,6 +164,9 @@ class Spline {
|
|||
LookupResult lookup_evaluated_factor(const float factor) const;
|
||||
LookupResult lookup_evaluated_length(const float length) const;
|
||||
|
||||
blender::Array<float> sample_uniform_index_factors(const int samples_size) const;
|
||||
LookupResult lookup_data_from_index_factor(const float index_factor) const;
|
||||
|
||||
/**
|
||||
* Interpolate a virtual array of data with the size of the number of control points to the
|
||||
* evaluated points. For poly splines, the lifetime of the returned virtual array must not
|
||||
|
@ -194,15 +198,17 @@ class BezierSpline final : public Spline {
|
|||
};
|
||||
|
||||
private:
|
||||
blender::Vector<HandleType> handle_types_left_;
|
||||
blender::Vector<blender::float3> handle_positions_left_;
|
||||
blender::Vector<blender::float3> positions_;
|
||||
blender::Vector<HandleType> handle_types_right_;
|
||||
blender::Vector<blender::float3> handle_positions_right_;
|
||||
blender::Vector<float> radii_;
|
||||
blender::Vector<float> tilts_;
|
||||
int resolution_;
|
||||
|
||||
blender::Vector<HandleType> handle_types_left_;
|
||||
blender::Vector<HandleType> handle_types_right_;
|
||||
|
||||
blender::Vector<blender::float3> handle_positions_left_;
|
||||
blender::Vector<blender::float3> handle_positions_right_;
|
||||
|
||||
/** Start index in evaluated points array for every control point. */
|
||||
mutable blender::Vector<int> offset_cache_;
|
||||
mutable std::mutex offset_cache_mutex_;
|
||||
|
@ -225,14 +231,14 @@ class BezierSpline final : public Spline {
|
|||
}
|
||||
BezierSpline(const BezierSpline &other)
|
||||
: Spline((Spline &)other),
|
||||
handle_types_left_(other.handle_types_left_),
|
||||
handle_positions_left_(other.handle_positions_left_),
|
||||
positions_(other.positions_),
|
||||
handle_types_right_(other.handle_types_right_),
|
||||
handle_positions_right_(other.handle_positions_right_),
|
||||
radii_(other.radii_),
|
||||
tilts_(other.tilts_),
|
||||
resolution_(other.resolution_)
|
||||
resolution_(other.resolution_),
|
||||
handle_types_left_(other.handle_types_left_),
|
||||
handle_types_right_(other.handle_types_right_),
|
||||
handle_positions_left_(other.handle_positions_left_),
|
||||
handle_positions_right_(other.handle_positions_right_)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -248,6 +254,7 @@ class BezierSpline final : public Spline {
|
|||
const float radius,
|
||||
const float tilt);
|
||||
|
||||
void resize(const int size) final;
|
||||
blender::MutableSpan<blender::float3> positions() final;
|
||||
blender::Span<blender::float3> positions() const final;
|
||||
blender::MutableSpan<float> radii() final;
|
||||
|
@ -286,7 +293,7 @@ class BezierSpline final : public Spline {
|
|||
InterpolationData interpolation_data_from_index_factor(const float index_factor) const;
|
||||
|
||||
virtual blender::fn::GVArrayPtr interpolate_to_evaluated_points(
|
||||
const blender::fn::GVArray &source_data) const;
|
||||
const blender::fn::GVArray &source_data) const override;
|
||||
|
||||
private:
|
||||
void correct_end_tangents() const final;
|
||||
|
@ -294,7 +301,6 @@ class BezierSpline final : public Spline {
|
|||
void evaluate_bezier_segment(const int index,
|
||||
const int next_index,
|
||||
blender::MutableSpan<blender::float3> positions) const;
|
||||
blender::Array<int> evaluated_point_offsets() const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -387,6 +393,7 @@ class NURBSpline final : public Spline {
|
|||
bool check_valid_size_and_order() const;
|
||||
int knots_size() const;
|
||||
|
||||
void resize(const int size) final;
|
||||
blender::MutableSpan<blender::float3> positions() final;
|
||||
blender::Span<blender::float3> positions() const final;
|
||||
blender::MutableSpan<float> radii() final;
|
||||
|
@ -441,6 +448,7 @@ class PolySpline final : public Spline {
|
|||
|
||||
void add_point(const blender::float3 position, const float radius, const float tilt);
|
||||
|
||||
void resize(const int size) final;
|
||||
blender::MutableSpan<blender::float3> positions() final;
|
||||
blender::Span<blender::float3> positions() const final;
|
||||
blender::MutableSpan<float> radii() final;
|
||||
|
|
|
@ -112,7 +112,7 @@ set(SRC
|
|||
intern/curve_convert.c
|
||||
intern/curve_decimate.c
|
||||
intern/curve_deform.c
|
||||
intern/curve_eval.cc
|
||||
intern/curve_eval.cc
|
||||
intern/curveprofile.c
|
||||
intern/customdata.c
|
||||
intern/customdata_file.c
|
||||
|
@ -407,7 +407,6 @@ set(SRC
|
|||
BKE_paint.h
|
||||
BKE_particle.h
|
||||
BKE_pbvh.h
|
||||
BKE_persistent_data_handle.hh
|
||||
BKE_pointcache.h
|
||||
BKE_pointcloud.h
|
||||
BKE_preferences.h
|
||||
|
@ -593,10 +592,6 @@ if(WITH_CODEC_FFMPEG)
|
|||
${FFMPEG_LIBRARIES}
|
||||
)
|
||||
add_definitions(-DWITH_FFMPEG)
|
||||
|
||||
remove_strict_c_flags_file(
|
||||
intern/writeffmpeg.c
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_PYTHON)
|
||||
|
|
|
@ -1861,7 +1861,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
|
|||
|
||||
/* Ensure normals calculation below is correct (normal settings have transferred properly).
|
||||
* However, nodes modifiers might create meshes from scratch or transfer meshes from other
|
||||
* objects with different settings, and in general it doesn't make sense to guarentee that
|
||||
* objects with different settings, and in general it doesn't make sense to guarantee that
|
||||
* the settings are the same as the original mesh. If necessary, this could become a modifier
|
||||
* type flag. */
|
||||
BLI_assert(mesh_input->smoothresh == mesh_cage->smoothresh);
|
||||
|
|
|
@ -656,7 +656,9 @@ bPoseChannel *BKE_pose_channel_ensure(bPose *pose, const char *name)
|
|||
|
||||
BLI_strncpy(chan->name, name, sizeof(chan->name));
|
||||
|
||||
chan->custom_scale = 1.0f;
|
||||
copy_v3_fl(chan->custom_scale_xyz, 1.0f);
|
||||
zero_v3(chan->custom_translation);
|
||||
zero_v3(chan->custom_rotation_euler);
|
||||
|
||||
/* init vars to prevent math errors */
|
||||
unit_qt(chan->quat);
|
||||
|
@ -1235,8 +1237,10 @@ void BKE_pose_channel_copy_data(bPoseChannel *pchan, const bPoseChannel *pchan_f
|
|||
if (pchan->custom) {
|
||||
id_us_plus(&pchan->custom->id);
|
||||
}
|
||||
copy_v3_v3(pchan->custom_scale_xyz, pchan_from->custom_scale_xyz);
|
||||
copy_v3_v3(pchan->custom_translation, pchan_from->custom_translation);
|
||||
copy_v3_v3(pchan->custom_rotation_euler, pchan_from->custom_rotation_euler);
|
||||
|
||||
pchan->custom_scale = pchan_from->custom_scale;
|
||||
pchan->drawflag = pchan_from->drawflag;
|
||||
}
|
||||
|
||||
|
|
|
@ -2881,7 +2881,8 @@ bool BKE_pose_minmax(Object *ob, float r_min[3], float r_max[3], bool use_hidden
|
|||
NULL;
|
||||
if (bb_custom) {
|
||||
float mat[4][4], smat[4][4];
|
||||
scale_m4_fl(smat, PCHAN_CUSTOM_DRAW_SIZE(pchan));
|
||||
scale_m4_fl(smat, PCHAN_CUSTOM_BONE_LENGTH(pchan));
|
||||
mul_m4_v3(smat, pchan->custom_scale_xyz);
|
||||
mul_m4_series(mat, ob->obmat, pchan_tx->pose_mat, smat);
|
||||
BKE_boundbox_minmax(bb_custom, mat, r_min, r_max);
|
||||
}
|
||||
|
|
|
@ -340,13 +340,22 @@ static int position_tail_on_spline(bSplineIKConstraint *ik_data,
|
|||
float isect_1[3], isect_2[3];
|
||||
|
||||
/* Calculate the intersection point. */
|
||||
isect_line_sphere_v3(prev_bp->vec, bp->vec, head_pos, sphere_radius, isect_1, isect_2);
|
||||
int ret = isect_line_sphere_v3(prev_bp->vec, bp->vec, head_pos, sphere_radius, isect_1, isect_2);
|
||||
|
||||
/* Because of how `isect_line_sphere_v3` works, we know that `isect_1` contains the
|
||||
* intersection point we want. And it will always intersect as we go from inside to outside
|
||||
* of the sphere.
|
||||
*/
|
||||
copy_v3_v3(r_tail_pos, isect_1);
|
||||
if (ret > 0) {
|
||||
/* Because of how `isect_line_sphere_v3` works, we know that `isect_1` contains the
|
||||
* intersection point we want. And it will always intersect as we go from inside to outside
|
||||
* of the sphere.
|
||||
*/
|
||||
copy_v3_v3(r_tail_pos, isect_1);
|
||||
}
|
||||
else {
|
||||
/* Couldn't find an intersection point. This means that the floating point
|
||||
* values are too small and thus the intersection check fails.
|
||||
* So assume that the distance is so small that tail_pos == head_pos.
|
||||
*/
|
||||
copy_v3_v3(r_tail_pos, head_pos);
|
||||
}
|
||||
|
||||
cur_seg_idx = bp_idx - 2;
|
||||
float prev_seg_len = 0;
|
||||
|
@ -360,7 +369,7 @@ static int position_tail_on_spline(bSplineIKConstraint *ik_data,
|
|||
}
|
||||
|
||||
/* Convert the point back into the 0-1 interpolation range. */
|
||||
const float isect_seg_len = len_v3v3(prev_bp->vec, isect_1);
|
||||
const float isect_seg_len = len_v3v3(prev_bp->vec, r_tail_pos);
|
||||
const float frac = isect_seg_len / len_v3v3(prev_bp->vec, bp->vec);
|
||||
*r_new_curve_pos = (prev_seg_len + isect_seg_len) / spline_len;
|
||||
|
||||
|
@ -380,7 +389,7 @@ static void splineik_evaluate_bone(
|
|||
{
|
||||
bSplineIKConstraint *ik_data = tree->ik_data;
|
||||
|
||||
if (pchan->bone->length == 0.0f) {
|
||||
if (pchan->bone->length < FLT_EPSILON) {
|
||||
/* Only move the bone position with zero length bones. */
|
||||
float bone_pos[4], dir[3], rad;
|
||||
BKE_where_on_path(ik_data->tar, state->curve_position, bone_pos, dir, NULL, &rad, NULL);
|
||||
|
@ -516,6 +525,25 @@ static void splineik_evaluate_bone(
|
|||
*/
|
||||
cross_v3_v3v3(raxis, rmat[1], spline_vec);
|
||||
|
||||
/* Check if the old and new bone direction is parallel to each other.
|
||||
* If they are, then 'raxis' should be near zero and we will have to get the rotation axis in
|
||||
* some other way.
|
||||
*/
|
||||
float norm = normalize_v3(raxis);
|
||||
|
||||
if (norm < FLT_EPSILON) {
|
||||
/* Can't use cross product! */
|
||||
int order[3] = {0, 1, 2};
|
||||
float tmp_axis[3];
|
||||
zero_v3(tmp_axis);
|
||||
|
||||
axis_sort_v3(spline_vec, order);
|
||||
|
||||
/* Use the second largest axis as the basis for the rotation axis. */
|
||||
tmp_axis[order[1]] = 1.0f;
|
||||
cross_v3_v3v3(raxis, tmp_axis, spline_vec);
|
||||
}
|
||||
|
||||
rangle = dot_v3v3(rmat[1], spline_vec);
|
||||
CLAMP(rangle, -1.0f, 1.0f);
|
||||
rangle = acosf(rangle);
|
||||
|
|
|
@ -399,7 +399,8 @@ static void setup_app_data(bContext *C,
|
|||
BKE_lib_override_library_main_resync(
|
||||
bmain,
|
||||
curscene,
|
||||
bfd->cur_view_layer ? bfd->cur_view_layer : BKE_view_layer_default_view(curscene));
|
||||
bfd->cur_view_layer ? bfd->cur_view_layer : BKE_view_layer_default_view(curscene),
|
||||
reports);
|
||||
/* We need to rebuild some of the deleted override rules (for UI feedback purpose). */
|
||||
BKE_lib_override_library_main_operations_create(bmain, true);
|
||||
}
|
||||
|
|
|
@ -1702,7 +1702,7 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface
|
|||
}
|
||||
|
||||
for (int i = 0; i < totloop; i++) {
|
||||
rgba_uchar_to_float(pPoint[mloop[i].v].color, (const unsigned char *)&col[mloop[i].v].r);
|
||||
rgba_uchar_to_float(pPoint[mloop[i].v].color, (const unsigned char *)&col[i].r);
|
||||
}
|
||||
}
|
||||
else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
|
||||
|
|
|
@ -115,7 +115,7 @@ void CurveComponent::ensure_owns_direct_data()
|
|||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Attribute Access
|
||||
/** \name Attribute Access Helper Functions
|
||||
* \{ */
|
||||
|
||||
int CurveComponent::attribute_domain_size(const AttributeDomain domain) const
|
||||
|
@ -136,12 +136,33 @@ int CurveComponent::attribute_domain_size(const AttributeDomain domain) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
static CurveEval *get_curve_from_component_for_write(GeometryComponent &component)
|
||||
{
|
||||
BLI_assert(component.type() == GEO_COMPONENT_TYPE_CURVE);
|
||||
CurveComponent &curve_component = static_cast<CurveComponent &>(component);
|
||||
return curve_component.get_for_write();
|
||||
}
|
||||
|
||||
static const CurveEval *get_curve_from_component_for_read(const GeometryComponent &component)
|
||||
{
|
||||
BLI_assert(component.type() == GEO_COMPONENT_TYPE_CURVE);
|
||||
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
|
||||
return curve_component.get_for_read();
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Builtin Spline Attributes
|
||||
*
|
||||
* Attributes with a value for every spline, stored contiguously or in every spline separately.
|
||||
* \{ */
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
class BuiltinSplineAttributeProvider final : public BuiltinAttributeProvider {
|
||||
using AsReadAttribute = GVArrayPtr (*)(const CurveEval &data);
|
||||
using AsWriteAttribute = GVMutableArrayPtr (*)(CurveEval &data);
|
||||
using UpdateOnWrite = void (*)(Spline &spline);
|
||||
const AsReadAttribute as_read_attribute_;
|
||||
const AsWriteAttribute as_write_attribute_;
|
||||
|
||||
|
@ -164,12 +185,10 @@ class BuiltinSplineAttributeProvider final : public BuiltinAttributeProvider {
|
|||
|
||||
GVArrayPtr try_get_for_read(const GeometryComponent &component) const final
|
||||
{
|
||||
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
|
||||
const CurveEval *curve = curve_component.get_for_read();
|
||||
const CurveEval *curve = get_curve_from_component_for_read(component);
|
||||
if (curve == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return as_read_attribute_(*curve);
|
||||
}
|
||||
|
||||
|
@ -178,12 +197,10 @@ class BuiltinSplineAttributeProvider final : public BuiltinAttributeProvider {
|
|||
if (writable_ != Writable) {
|
||||
return {};
|
||||
}
|
||||
CurveComponent &curve_component = static_cast<CurveComponent &>(component);
|
||||
CurveEval *curve = curve_component.get_for_write();
|
||||
CurveEval *curve = get_curve_from_component_for_write(component);
|
||||
if (curve == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return as_write_attribute_(*curve);
|
||||
}
|
||||
|
||||
|
@ -266,6 +283,12 @@ static GVMutableArrayPtr make_cyclic_write_attribute(CurveEval &curve)
|
|||
curve.splines.as_mutable_span());
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Attribute Provider Declaration
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* In this function all the attribute providers for a curve component are created. Most data
|
||||
* in this function is statically allocated, because it does not change over time.
|
||||
|
|
|
@ -56,6 +56,19 @@ void InstancesComponent::reserve(int min_capacity)
|
|||
instance_ids_.reserve(min_capacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize the transform, handles, and ID vectors to the specified capacity.
|
||||
*
|
||||
* \note This function should be used carefully, only when it's guaranteed
|
||||
* that the data will be filled.
|
||||
*/
|
||||
void InstancesComponent::resize(int capacity)
|
||||
{
|
||||
instance_reference_handles_.resize(capacity);
|
||||
instance_transforms_.resize(capacity);
|
||||
instance_ids_.resize(capacity);
|
||||
}
|
||||
|
||||
void InstancesComponent::clear()
|
||||
{
|
||||
instance_reference_handles_.clear();
|
||||
|
@ -81,6 +94,11 @@ blender::Span<int> InstancesComponent::instance_reference_handles() const
|
|||
return instance_reference_handles_;
|
||||
}
|
||||
|
||||
blender::MutableSpan<int> InstancesComponent::instance_reference_handles()
|
||||
{
|
||||
return instance_reference_handles_;
|
||||
}
|
||||
|
||||
blender::MutableSpan<blender::float4x4> InstancesComponent::instance_transforms()
|
||||
{
|
||||
return instance_transforms_;
|
||||
|
|
|
@ -503,7 +503,7 @@ void IDP_SyncGroupValues(IDProperty *dest, const IDProperty *src)
|
|||
|
||||
void IDP_SyncGroupTypes(IDProperty *dest, const IDProperty *src, const bool do_arraylen)
|
||||
{
|
||||
LISTBASE_FOREACH_MUTABLE (IDProperty *, prop_dst, &src->data.group) {
|
||||
LISTBASE_FOREACH_MUTABLE (IDProperty *, prop_dst, &dest->data.group) {
|
||||
const IDProperty *prop_src = IDP_GetPropertyFromGroup((IDProperty *)src, prop_dst->name);
|
||||
if (prop_src != NULL) {
|
||||
/* check of we should replace? */
|
||||
|
|
|
@ -719,8 +719,19 @@ static void lib_override_library_create_post_process(Main *bmain,
|
|||
|
||||
if (BLI_gset_lookup(all_objects_in_scene, ob_new) == NULL) {
|
||||
if (id_root != NULL && default_instantiating_collection == NULL) {
|
||||
switch (GS(id_root->name)) {
|
||||
ID *id_ref = id_root->newid != NULL ? id_root->newid : id_root;
|
||||
switch (GS(id_ref->name)) {
|
||||
case ID_GR: {
|
||||
/* Adding the object to a specific collection outside of the root overridden one is a
|
||||
* fairly bad idea (it breaks the override hierarchy concept). But there is no other
|
||||
* way to do this currently (we cannot add new collections to overridden root one,
|
||||
* this is not currently supported).
|
||||
* Since that will be fairly annoying and noisy, only do that in case the override
|
||||
* object is not part of any existing collection (i.e. its user count is 0). In
|
||||
* practice this should never happen I think. */
|
||||
if (ID_REAL_USERS(ob_new) != 0) {
|
||||
continue;
|
||||
}
|
||||
default_instantiating_collection = BKE_collection_add(
|
||||
bmain, (Collection *)id_root, "OVERRIDE_HIDDEN");
|
||||
/* Hide the collection from viewport and render. */
|
||||
|
@ -731,9 +742,9 @@ static void lib_override_library_create_post_process(Main *bmain,
|
|||
case ID_OB: {
|
||||
/* Add the other objects to one of the collections instantiating the
|
||||
* root object, or scene's master collection if none found. */
|
||||
Object *ob_root = (Object *)id_root;
|
||||
Object *ob_ref = (Object *)id_ref;
|
||||
LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
|
||||
if (BKE_collection_has_object(collection, ob_root) &&
|
||||
if (BKE_collection_has_object(collection, ob_ref) &&
|
||||
BKE_view_layer_has_collection(view_layer, collection) &&
|
||||
!ID_IS_LINKED(collection) && !ID_IS_OVERRIDE_LIBRARY(collection)) {
|
||||
default_instantiating_collection = collection;
|
||||
|
@ -867,7 +878,8 @@ bool BKE_lib_override_library_resync(Main *bmain,
|
|||
ID *id_root,
|
||||
Collection *override_resync_residual_storage,
|
||||
const bool do_hierarchy_enforce,
|
||||
const bool do_post_process)
|
||||
const bool do_post_process,
|
||||
ReportList *reports)
|
||||
{
|
||||
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root));
|
||||
BLI_assert(!ID_IS_LINKED(id_root));
|
||||
|
@ -891,6 +903,19 @@ bool BKE_lib_override_library_resync(Main *bmain,
|
|||
BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
|
||||
ID *id;
|
||||
FOREACH_MAIN_ID_BEGIN (bmain, id) {
|
||||
/* IDs that get fully removed from linked data remain as local overrides (using place-holder
|
||||
* linked IDs as reference), but they are often not reachable from any current valid local
|
||||
* override hierarchy anymore. This will ensure they get properly deleted at the end of this
|
||||
* function. */
|
||||
if (!ID_IS_LINKED(id) && ID_IS_OVERRIDE_LIBRARY_REAL(id) &&
|
||||
(id->override_library->reference->tag & LIB_TAG_MISSING) != 0 &&
|
||||
/* Unfortunately deleting obdata means deleting their objects too. Since there is no
|
||||
* guarantee that a valid override object using an obsolete override obdata gets properly
|
||||
* updated, we ignore those here for now. In practice this should not be a big issue. */
|
||||
!OB_DATA_SUPPORT_ID(GS(id->name))) {
|
||||
id->tag |= LIB_TAG_MISSING;
|
||||
}
|
||||
|
||||
if (id->tag & LIB_TAG_DOIT && !ID_IS_LINKED(id) && ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
|
||||
/* While this should not happen in typical cases (and won't be properly supported here), user
|
||||
* is free to do all kind of very bad things, including having different local overrides of a
|
||||
|
@ -1033,6 +1058,7 @@ bool BKE_lib_override_library_resync(Main *bmain,
|
|||
/* Delete old override IDs.
|
||||
* Note that we have to use tagged group deletion here, since ID deletion also uses LIB_TAG_DOIT.
|
||||
* This improves performances anyway, so everything is fine. */
|
||||
int user_edited_overrides_deletion_count = 0;
|
||||
FOREACH_MAIN_ID_BEGIN (bmain, id) {
|
||||
if (id->tag & LIB_TAG_DOIT) {
|
||||
/* Note that this works because linked IDs are always after local ones (including overrides),
|
||||
|
@ -1057,6 +1083,7 @@ bool BKE_lib_override_library_resync(Main *bmain,
|
|||
id->tag &= ~LIB_TAG_MISSING;
|
||||
CLOG_INFO(&LOG, 2, "Old override %s is being deleted", id->name);
|
||||
}
|
||||
#if 0
|
||||
else {
|
||||
/* Otherwise, keep them, user needs to decide whether what to do with them. */
|
||||
BLI_assert((id->tag & LIB_TAG_DOIT) == 0);
|
||||
|
@ -1064,6 +1091,17 @@ bool BKE_lib_override_library_resync(Main *bmain,
|
|||
id->flag |= LIB_LIB_OVERRIDE_RESYNC_LEFTOVER;
|
||||
CLOG_INFO(&LOG, 2, "Old override %s is being kept around as it was user-edited", id->name);
|
||||
}
|
||||
#else
|
||||
else {
|
||||
/* Delete them nevertheless, with fat warning, user needs to decide whether they want to
|
||||
* save that version of the file (and accept the loss), or not. */
|
||||
id->tag |= LIB_TAG_DOIT;
|
||||
id->tag &= ~LIB_TAG_MISSING;
|
||||
CLOG_WARN(
|
||||
&LOG, "Old override %s is being deleted even though it was user-edited", id->name);
|
||||
user_edited_overrides_deletion_count++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
FOREACH_MAIN_ID_END;
|
||||
|
@ -1074,6 +1112,15 @@ bool BKE_lib_override_library_resync(Main *bmain,
|
|||
*/
|
||||
id_root = id_root_reference->newid;
|
||||
|
||||
if (user_edited_overrides_deletion_count > 0) {
|
||||
BKE_reportf(reports,
|
||||
RPT_WARNING,
|
||||
"During resync of data-block %s, %d obsolete overrides were deleted, that had "
|
||||
"local changes defined by user",
|
||||
id_root->name + 2,
|
||||
user_edited_overrides_deletion_count);
|
||||
}
|
||||
|
||||
if (do_post_process) {
|
||||
/* Essentially ensures that potentially new overrides of new objects will be instantiated. */
|
||||
/* Note: Here 'reference' collection and 'newly added' collection are the same, which is fine
|
||||
|
@ -1112,7 +1159,10 @@ bool BKE_lib_override_library_resync(Main *bmain,
|
|||
* Then it will handle the resync of necessary IDs (through calls to
|
||||
* #BKE_lib_override_library_resync).
|
||||
*/
|
||||
void BKE_lib_override_library_main_resync(Main *bmain, Scene *scene, ViewLayer *view_layer)
|
||||
void BKE_lib_override_library_main_resync(Main *bmain,
|
||||
Scene *scene,
|
||||
ViewLayer *view_layer,
|
||||
ReportList *reports)
|
||||
{
|
||||
/* We use a specific collection to gather/store all 'orphaned' override collections and objects
|
||||
* generated by re-sync-process. This avoids putting them in scene's master collection. */
|
||||
|
@ -1228,7 +1278,7 @@ void BKE_lib_override_library_main_resync(Main *bmain, Scene *scene, ViewLayer *
|
|||
|
||||
CLOG_INFO(&LOG, 2, "Resyncing %s...", id->name);
|
||||
const bool success = BKE_lib_override_library_resync(
|
||||
bmain, scene, view_layer, id, override_resync_residual_storage, false, false);
|
||||
bmain, scene, view_layer, id, override_resync_residual_storage, false, false, reports);
|
||||
CLOG_INFO(&LOG, 2, "\tSuccess: %d", success);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ typedef struct LibraryForeachIDData {
|
|||
*/
|
||||
ID *self_id;
|
||||
|
||||
/** Flags controlling the bahaviour of the 'foreach id' looping code. */
|
||||
/** Flags controlling the behavior of the 'foreach id' looping code. */
|
||||
int flag;
|
||||
/** Generic flags to be passed to all callback calls for current processed data. */
|
||||
int cb_flag;
|
||||
|
|
|
@ -281,7 +281,7 @@ bool BKE_modifier_is_preview(ModifierData *md)
|
|||
return false;
|
||||
}
|
||||
|
||||
ModifierData *BKE_modifiers_findby_type(Object *ob, ModifierType type)
|
||||
ModifierData *BKE_modifiers_findby_type(const Object *ob, ModifierType type)
|
||||
{
|
||||
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
|
||||
if (md->type == type) {
|
||||
|
@ -291,7 +291,7 @@ ModifierData *BKE_modifiers_findby_type(Object *ob, ModifierType type)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ModifierData *BKE_modifiers_findby_name(Object *ob, const char *name)
|
||||
ModifierData *BKE_modifiers_findby_name(const Object *ob, const char *name)
|
||||
{
|
||||
return BLI_findstring(&(ob->modifiers), name, offsetof(ModifierData, name));
|
||||
}
|
||||
|
|
|
@ -501,6 +501,12 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree)
|
|||
ELEM(node->type, SH_NODE_CURVE_VEC, SH_NODE_CURVE_RGB)) {
|
||||
BKE_curvemapping_blend_write(writer, (const CurveMapping *)node->storage);
|
||||
}
|
||||
else if ((ntree->type == NTREE_GEOMETRY) && (node->type == GEO_NODE_ATTRIBUTE_CURVE_MAP)) {
|
||||
BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage);
|
||||
NodeAttributeCurveMap *data = (NodeAttributeCurveMap *)node->storage;
|
||||
BKE_curvemapping_blend_write(writer, (const CurveMapping *)data->curve_vec);
|
||||
BKE_curvemapping_blend_write(writer, (const CurveMapping *)data->curve_rgb);
|
||||
}
|
||||
else if (ntree->type == NTREE_SHADER && (node->type == SH_NODE_SCRIPT)) {
|
||||
NodeShaderScript *nss = (NodeShaderScript *)node->storage;
|
||||
if (nss->bytecode) {
|
||||
|
@ -676,6 +682,18 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
|
|||
BKE_curvemapping_blend_read(reader, (CurveMapping *)node->storage);
|
||||
break;
|
||||
}
|
||||
case GEO_NODE_ATTRIBUTE_CURVE_MAP: {
|
||||
NodeAttributeCurveMap *data = (NodeAttributeCurveMap *)node->storage;
|
||||
BLO_read_data_address(reader, &data->curve_vec);
|
||||
if (data->curve_vec) {
|
||||
BKE_curvemapping_blend_read(reader, data->curve_vec);
|
||||
}
|
||||
BLO_read_data_address(reader, &data->curve_rgb);
|
||||
if (data->curve_rgb) {
|
||||
BKE_curvemapping_blend_read(reader, data->curve_rgb);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SH_NODE_SCRIPT: {
|
||||
NodeShaderScript *nss = (NodeShaderScript *)node->storage;
|
||||
BLO_read_data_address(reader, &nss->bytecode);
|
||||
|
@ -4934,6 +4952,7 @@ static void registerGeometryNodes()
|
|||
register_node_type_geo_attribute_combine_xyz();
|
||||
register_node_type_geo_attribute_compare();
|
||||
register_node_type_geo_attribute_convert();
|
||||
register_node_type_geo_attribute_curve_map();
|
||||
register_node_type_geo_attribute_fill();
|
||||
register_node_type_geo_attribute_map_range();
|
||||
register_node_type_geo_attribute_math();
|
||||
|
@ -4943,11 +4962,13 @@ static void registerGeometryNodes()
|
|||
register_node_type_geo_attribute_separate_xyz();
|
||||
register_node_type_geo_attribute_transfer();
|
||||
register_node_type_geo_attribute_vector_math();
|
||||
register_node_type_geo_attribute_vector_rotate();
|
||||
register_node_type_geo_attribute_remove();
|
||||
register_node_type_geo_boolean();
|
||||
register_node_type_geo_bounding_box();
|
||||
register_node_type_geo_collection_info();
|
||||
register_node_type_geo_curve_to_mesh();
|
||||
register_node_type_geo_curve_resample();
|
||||
register_node_type_geo_edge_split();
|
||||
register_node_type_geo_is_viewport();
|
||||
register_node_type_geo_join_geometry();
|
||||
|
|
|
@ -829,13 +829,13 @@ static void calculate_collision_balls(Object *ob)
|
|||
}
|
||||
|
||||
/* creates new softbody if didn't exist yet, makes new points and springs arrays */
|
||||
static void renew_softbody(Scene *scene, Object *ob, int totpoint, int totspring)
|
||||
static void renew_softbody(Object *ob, int totpoint, int totspring)
|
||||
{
|
||||
SoftBody *sb;
|
||||
int i;
|
||||
short softflag;
|
||||
if (ob->soft == NULL) {
|
||||
ob->soft = sbNew(scene);
|
||||
ob->soft = sbNew();
|
||||
}
|
||||
else {
|
||||
free_softbody_intern(ob->soft);
|
||||
|
@ -2679,7 +2679,7 @@ static void springs_from_mesh(Object *ob)
|
|||
}
|
||||
|
||||
/* makes totally fresh start situation */
|
||||
static void mesh_to_softbody(Scene *scene, Object *ob)
|
||||
static void mesh_to_softbody(Object *ob)
|
||||
{
|
||||
SoftBody *sb;
|
||||
Mesh *me = ob->data;
|
||||
|
@ -2697,7 +2697,7 @@ static void mesh_to_softbody(Scene *scene, Object *ob)
|
|||
}
|
||||
|
||||
/* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
|
||||
renew_softbody(scene, ob, me->totvert, totedge);
|
||||
renew_softbody(ob, me->totvert, totedge);
|
||||
|
||||
/* we always make body points */
|
||||
sb = ob->soft;
|
||||
|
@ -2909,7 +2909,7 @@ static void makelatticesprings(Lattice *lt, BodySpring *bs, int dostiff, Object
|
|||
}
|
||||
|
||||
/* makes totally fresh start situation */
|
||||
static void lattice_to_softbody(Scene *scene, Object *ob)
|
||||
static void lattice_to_softbody(Object *ob)
|
||||
{
|
||||
Lattice *lt = ob->data;
|
||||
SoftBody *sb;
|
||||
|
@ -2929,7 +2929,7 @@ static void lattice_to_softbody(Scene *scene, Object *ob)
|
|||
}
|
||||
|
||||
/* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
|
||||
renew_softbody(scene, ob, totvert, totspring);
|
||||
renew_softbody(ob, totvert, totspring);
|
||||
sb = ob->soft; /* can be created in renew_softbody() */
|
||||
bp = sb->bpoint;
|
||||
|
||||
|
@ -2972,7 +2972,7 @@ static void lattice_to_softbody(Scene *scene, Object *ob)
|
|||
}
|
||||
|
||||
/* makes totally fresh start situation */
|
||||
static void curve_surf_to_softbody(Scene *scene, Object *ob)
|
||||
static void curve_surf_to_softbody(Object *ob)
|
||||
{
|
||||
Curve *cu = ob->data;
|
||||
SoftBody *sb;
|
||||
|
@ -2993,7 +2993,7 @@ static void curve_surf_to_softbody(Scene *scene, Object *ob)
|
|||
}
|
||||
|
||||
/* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
|
||||
renew_softbody(scene, ob, totvert, totspring);
|
||||
renew_softbody(ob, totvert, totspring);
|
||||
sb = ob->soft; /* can be created in renew_softbody() */
|
||||
|
||||
/* set vars now */
|
||||
|
@ -3117,7 +3117,7 @@ static void sb_new_scratch(SoftBody *sb)
|
|||
/* ************ Object level, exported functions *************** */
|
||||
|
||||
/* allocates and initializes general main data */
|
||||
SoftBody *sbNew(Scene *scene)
|
||||
SoftBody *sbNew(void)
|
||||
{
|
||||
SoftBody *sb;
|
||||
|
||||
|
@ -3140,12 +3140,6 @@ SoftBody *sbNew(Scene *scene)
|
|||
/*todo backward file compat should copy inspring to inpush while reading old files*/
|
||||
sb->inpush = 0.5f;
|
||||
|
||||
sb->interval = 10;
|
||||
if (scene != NULL) {
|
||||
sb->sfra = scene->r.sfra;
|
||||
sb->efra = scene->r.efra;
|
||||
}
|
||||
|
||||
sb->colball = 0.49f;
|
||||
sb->balldamp = 0.50f;
|
||||
sb->ballstiff = 1.0f;
|
||||
|
@ -3577,17 +3571,17 @@ void sbObjectStep(struct Depsgraph *depsgraph,
|
|||
|
||||
switch (ob->type) {
|
||||
case OB_MESH:
|
||||
mesh_to_softbody(scene, ob);
|
||||
mesh_to_softbody(ob);
|
||||
break;
|
||||
case OB_LATTICE:
|
||||
lattice_to_softbody(scene, ob);
|
||||
lattice_to_softbody(ob);
|
||||
break;
|
||||
case OB_CURVE:
|
||||
case OB_SURF:
|
||||
curve_surf_to_softbody(scene, ob);
|
||||
curve_surf_to_softbody(ob);
|
||||
break;
|
||||
default:
|
||||
renew_softbody(scene, ob, numVerts, 0);
|
||||
renew_softbody(ob, numVerts, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,11 +16,13 @@
|
|||
|
||||
#include "BLI_array.hh"
|
||||
#include "BLI_span.hh"
|
||||
|
||||
#include "FN_generic_virtual_array.hh"
|
||||
#include "BLI_timeit.hh"
|
||||
|
||||
#include "BKE_spline.hh"
|
||||
|
||||
#include "FN_generic_virtual_array.hh"
|
||||
|
||||
using blender::Array;
|
||||
using blender::float3;
|
||||
using blender::IndexRange;
|
||||
using blender::MutableSpan;
|
||||
|
@ -59,7 +61,8 @@ int Spline::evaluated_edges_size() const
|
|||
|
||||
float Spline::length() const
|
||||
{
|
||||
return this->evaluated_lengths().last();
|
||||
Span<float> lengths = this->evaluated_lengths();
|
||||
return (lengths.size() == 0) ? 0 : this->evaluated_lengths().last();
|
||||
}
|
||||
|
||||
int Spline::segments_size() const
|
||||
|
@ -265,6 +268,72 @@ Spline::LookupResult Spline::lookup_evaluated_length(const float length) const
|
|||
return LookupResult{index, next_index, factor};
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of evenly spaced samples along the length of the spline. The samples are indices
|
||||
* and factors to the next index encoded in floats. The logic for converting from the float values
|
||||
* to interpolation data is in #lookup_data_from_index_factor.
|
||||
*/
|
||||
Array<float> Spline::sample_uniform_index_factors(const int samples_size) const
|
||||
{
|
||||
const Span<float> lengths = this->evaluated_lengths();
|
||||
|
||||
BLI_assert(samples_size > 0);
|
||||
Array<float> samples(samples_size);
|
||||
|
||||
samples[0] = 0.0f;
|
||||
if (samples_size == 1) {
|
||||
return samples;
|
||||
}
|
||||
|
||||
const float total_length = this->length();
|
||||
const float sample_length = total_length / (samples_size - (is_cyclic_ ? 0 : 1));
|
||||
|
||||
/* Store the length at the previous evaluated point in a variable so it can
|
||||
* start out at zero (the lengths array doesn't contain 0 for the first point). */
|
||||
float prev_length = 0.0f;
|
||||
int i_sample = 1;
|
||||
for (const int i_evaluated : IndexRange(this->evaluated_edges_size())) {
|
||||
const float length = lengths[i_evaluated];
|
||||
|
||||
/* Add every sample that fits in this evaluated edge. */
|
||||
while ((sample_length * i_sample) < length && i_sample < samples_size) {
|
||||
const float factor = (sample_length * i_sample - prev_length) / (length - prev_length);
|
||||
samples[i_sample] = i_evaluated + factor;
|
||||
i_sample++;
|
||||
}
|
||||
|
||||
prev_length = length;
|
||||
}
|
||||
|
||||
if (!is_cyclic_) {
|
||||
/* In rare cases this can prevent overflow of the stored index. */
|
||||
samples.last() = lengths.size();
|
||||
}
|
||||
|
||||
return samples;
|
||||
}
|
||||
|
||||
Spline::LookupResult Spline::lookup_data_from_index_factor(const float index_factor) const
|
||||
{
|
||||
const int points_len = this->evaluated_points_size();
|
||||
|
||||
if (is_cyclic_) {
|
||||
if (index_factor < points_len) {
|
||||
const int index = std::floor(index_factor);
|
||||
const int next_index = (index < points_len - 1) ? index + 1 : 0;
|
||||
return LookupResult{index, next_index, index_factor - index};
|
||||
}
|
||||
return LookupResult{points_len - 1, 0, 1.0f};
|
||||
}
|
||||
|
||||
if (index_factor < points_len - 1) {
|
||||
const int index = std::floor(index_factor);
|
||||
const int next_index = index + 1;
|
||||
return LookupResult{index, next_index, index_factor - index};
|
||||
}
|
||||
return LookupResult{points_len - 2, points_len - 1, 1.0f};
|
||||
}
|
||||
|
||||
void Spline::bounds_min_max(float3 &min, float3 &max, const bool use_evaluated) const
|
||||
{
|
||||
Span<float3> positions = use_evaluated ? this->evaluated_positions() : this->positions();
|
||||
|
|
|
@ -73,6 +73,18 @@ void BezierSpline::add_point(const float3 position,
|
|||
this->mark_cache_invalid();
|
||||
}
|
||||
|
||||
void BezierSpline::resize(const int size)
|
||||
{
|
||||
handle_types_left_.resize(size);
|
||||
handle_positions_left_.resize(size);
|
||||
positions_.resize(size);
|
||||
handle_types_right_.resize(size);
|
||||
handle_positions_right_.resize(size);
|
||||
radii_.resize(size);
|
||||
tilts_.resize(size);
|
||||
this->mark_cache_invalid();
|
||||
}
|
||||
|
||||
MutableSpan<float3> BezierSpline::positions()
|
||||
{
|
||||
return positions_;
|
||||
|
@ -192,7 +204,7 @@ int BezierSpline::evaluated_points_size() const
|
|||
|
||||
const int last_offset = this->control_point_offsets().last();
|
||||
if (is_cyclic_ && points_len > 1) {
|
||||
return last_offset + (this->segment_is_vector(points_len - 1) ? 0 : resolution_);
|
||||
return last_offset + (this->segment_is_vector(points_len - 1) ? 1 : resolution_);
|
||||
}
|
||||
|
||||
return last_offset + 1;
|
||||
|
@ -398,7 +410,7 @@ Span<float3> BezierSpline::evaluated_positions() const
|
|||
this->evaluate_bezier_segment(i_last, 0, positions.slice(offsets.last(), resolution_));
|
||||
}
|
||||
else {
|
||||
/* Since evualating the bezier segment doesn't add the final point,
|
||||
/* Since evaluating the bezier segment doesn't add the final point,
|
||||
* it must be added manually in the non-cyclic case. */
|
||||
positions.last() = positions_.last();
|
||||
}
|
||||
|
|
|
@ -78,6 +78,15 @@ void NURBSpline::add_point(const float3 position,
|
|||
this->mark_cache_invalid();
|
||||
}
|
||||
|
||||
void NURBSpline::resize(const int size)
|
||||
{
|
||||
positions_.resize(size);
|
||||
radii_.resize(size);
|
||||
tilts_.resize(size);
|
||||
weights_.resize(size);
|
||||
this->mark_cache_invalid();
|
||||
}
|
||||
|
||||
MutableSpan<float3> NURBSpline::positions()
|
||||
{
|
||||
return positions_;
|
||||
|
|
|
@ -44,6 +44,14 @@ void PolySpline::add_point(const float3 position, const float radius, const floa
|
|||
this->mark_cache_invalid();
|
||||
}
|
||||
|
||||
void PolySpline::resize(const int size)
|
||||
{
|
||||
positions_.resize(size);
|
||||
radii_.resize(size);
|
||||
tilts_.resize(size);
|
||||
this->mark_cache_invalid();
|
||||
}
|
||||
|
||||
MutableSpan<float3> PolySpline::positions()
|
||||
{
|
||||
return positions_;
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
# include <libavcodec/avcodec.h>
|
||||
# include <libavformat/avformat.h>
|
||||
# include <libavutil/imgutils.h>
|
||||
# include <libavutil/opt.h>
|
||||
# include <libavutil/rational.h>
|
||||
# include <libavutil/samplefmt.h>
|
||||
# include <libswscale/swscale.h>
|
||||
|
@ -80,6 +81,8 @@ typedef struct FFMpegContext {
|
|||
int ffmpeg_preset; /* see eFFMpegPreset */
|
||||
|
||||
AVFormatContext *outfile;
|
||||
AVCodecContext *video_codec;
|
||||
AVCodecContext *audio_codec;
|
||||
AVStream *video_stream;
|
||||
AVStream *audio_stream;
|
||||
AVFrame *current_frame; /* Image frame in output pixel format. */
|
||||
|
@ -91,10 +94,6 @@ typedef struct FFMpegContext {
|
|||
uint8_t *audio_input_buffer;
|
||||
uint8_t *audio_deinterleave_buffer;
|
||||
int audio_input_samples;
|
||||
# ifndef FFMPEG_HAVE_ENCODE_AUDIO2
|
||||
uint8_t *audio_output_buffer;
|
||||
int audio_outbuf_size;
|
||||
# endif
|
||||
double audio_time;
|
||||
bool audio_deinterleave;
|
||||
int audio_sample_size;
|
||||
|
@ -141,32 +140,22 @@ static int request_float_audio_buffer(int codec_id)
|
|||
}
|
||||
|
||||
# ifdef WITH_AUDASPACE
|
||||
|
||||
static int write_audio_frame(FFMpegContext *context)
|
||||
{
|
||||
AVCodecContext *c = NULL;
|
||||
AVPacket pkt;
|
||||
AVFrame *frame = NULL;
|
||||
int got_output = 0;
|
||||
|
||||
c = context->audio_stream->codec;
|
||||
|
||||
av_init_packet(&pkt);
|
||||
pkt.size = 0;
|
||||
pkt.data = NULL;
|
||||
AVCodecContext *c = context->audio_codec;
|
||||
|
||||
AUD_Device_read(
|
||||
context->audio_mixdown_device, context->audio_input_buffer, context->audio_input_samples);
|
||||
context->audio_time += (double)context->audio_input_samples / (double)c->sample_rate;
|
||||
|
||||
# ifdef FFMPEG_HAVE_ENCODE_AUDIO2
|
||||
frame = av_frame_alloc();
|
||||
av_frame_unref(frame);
|
||||
frame->pts = context->audio_time / av_q2d(c->time_base);
|
||||
frame->nb_samples = context->audio_input_samples;
|
||||
frame->format = c->sample_fmt;
|
||||
# ifdef FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT
|
||||
frame->channels = c->channels;
|
||||
frame->channel_layout = c->channel_layout;
|
||||
# endif
|
||||
|
||||
if (context->audio_deinterleave) {
|
||||
int channel, i;
|
||||
|
@ -194,61 +183,49 @@ static int write_audio_frame(FFMpegContext *context)
|
|||
context->audio_input_samples * c->channels * context->audio_sample_size,
|
||||
1);
|
||||
|
||||
if (avcodec_encode_audio2(c, &pkt, frame, &got_output) < 0) {
|
||||
// XXX error("Error writing audio packet");
|
||||
return -1;
|
||||
int success = 0;
|
||||
|
||||
int ret = avcodec_send_frame(c, frame);
|
||||
if (ret < 0) {
|
||||
/* Can't send frame to encoder. This shouldn't happen. */
|
||||
fprintf(stderr, "Can't send audio frame: %s\n", av_err2str(ret));
|
||||
success = -1;
|
||||
}
|
||||
|
||||
if (!got_output) {
|
||||
av_frame_free(&frame);
|
||||
return 0;
|
||||
}
|
||||
# else
|
||||
pkt.size = avcodec_encode_audio(c,
|
||||
context->audio_output_buffer,
|
||||
context->audio_outbuf_size,
|
||||
(short *)context->audio_input_buffer);
|
||||
AVPacket *pkt = av_packet_alloc();
|
||||
|
||||
if (pkt.size < 0) {
|
||||
// XXX error("Error writing audio packet");
|
||||
return -1;
|
||||
}
|
||||
while (ret >= 0) {
|
||||
|
||||
pkt.data = context->audio_output_buffer;
|
||||
got_output = 1;
|
||||
# endif
|
||||
|
||||
if (got_output) {
|
||||
if (pkt.pts != AV_NOPTS_VALUE) {
|
||||
pkt.pts = av_rescale_q(pkt.pts, c->time_base, context->audio_stream->time_base);
|
||||
ret = avcodec_receive_packet(c, pkt);
|
||||
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
|
||||
break;
|
||||
}
|
||||
if (pkt.dts != AV_NOPTS_VALUE) {
|
||||
pkt.dts = av_rescale_q(pkt.dts, c->time_base, context->audio_stream->time_base);
|
||||
}
|
||||
if (pkt.duration > 0) {
|
||||
pkt.duration = av_rescale_q(pkt.duration, c->time_base, context->audio_stream->time_base);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret));
|
||||
success = -1;
|
||||
}
|
||||
|
||||
pkt.stream_index = context->audio_stream->index;
|
||||
|
||||
pkt.flags |= AV_PKT_FLAG_KEY;
|
||||
|
||||
if (av_interleaved_write_frame(context->outfile, &pkt) != 0) {
|
||||
fprintf(stderr, "Error writing audio packet!\n");
|
||||
if (frame) {
|
||||
av_frame_free(&frame);
|
||||
}
|
||||
return -1;
|
||||
av_packet_rescale_ts(pkt, c->time_base, context->audio_stream->time_base);
|
||||
if (pkt->duration > 0) {
|
||||
pkt->duration = av_rescale_q(pkt->duration, c->time_base, context->audio_stream->time_base);
|
||||
}
|
||||
|
||||
av_free_packet(&pkt);
|
||||
pkt->stream_index = context->audio_stream->index;
|
||||
|
||||
pkt->flags |= AV_PKT_FLAG_KEY;
|
||||
|
||||
int write_ret = av_interleaved_write_frame(context->outfile, pkt);
|
||||
if (write_ret != 0) {
|
||||
fprintf(stderr, "Error writing audio packet: %s\n", av_err2str(write_ret));
|
||||
success = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (frame) {
|
||||
av_frame_free(&frame);
|
||||
}
|
||||
av_packet_free(&pkt);
|
||||
av_frame_free(&frame);
|
||||
|
||||
return 0;
|
||||
return success;
|
||||
}
|
||||
# endif /* #ifdef WITH_AUDASPACE */
|
||||
|
||||
|
@ -264,14 +241,15 @@ static AVFrame *alloc_picture(int pix_fmt, int width, int height)
|
|||
if (!f) {
|
||||
return NULL;
|
||||
}
|
||||
size = avpicture_get_size(pix_fmt, width, height);
|
||||
size = av_image_get_buffer_size(pix_fmt, width, height, 1);
|
||||
/* allocate the actual picture buffer */
|
||||
buf = MEM_mallocN(size, "AVFrame buffer");
|
||||
if (!buf) {
|
||||
free(f);
|
||||
return NULL;
|
||||
}
|
||||
avpicture_fill((AVPicture *)f, buf, pix_fmt, width, height);
|
||||
|
||||
av_image_fill_arrays(f->data, f->linesize, buf, pix_fmt, width, height, 1);
|
||||
f->format = pix_fmt;
|
||||
f->width = width;
|
||||
f->height = height;
|
||||
|
@ -341,58 +319,57 @@ static const char **get_file_extensions(int format)
|
|||
}
|
||||
|
||||
/* Write a frame to the output file */
|
||||
static int write_video_frame(
|
||||
FFMpegContext *context, const RenderData *rd, int cfra, AVFrame *frame, ReportList *reports)
|
||||
static int write_video_frame(FFMpegContext *context, int cfra, AVFrame *frame, ReportList *reports)
|
||||
{
|
||||
int got_output;
|
||||
int ret, success = 1;
|
||||
AVCodecContext *c = context->video_stream->codec;
|
||||
AVPacket packet = {0};
|
||||
AVPacket *packet = av_packet_alloc();
|
||||
|
||||
av_init_packet(&packet);
|
||||
AVCodecContext *c = context->video_codec;
|
||||
|
||||
frame->pts = cfra;
|
||||
|
||||
ret = avcodec_encode_video2(c, &packet, frame, &got_output);
|
||||
|
||||
if (ret >= 0 && got_output) {
|
||||
if (packet.pts != AV_NOPTS_VALUE) {
|
||||
packet.pts = av_rescale_q(packet.pts, c->time_base, context->video_stream->time_base);
|
||||
PRINT("Video Frame PTS: %d\n", (int)packet.pts);
|
||||
}
|
||||
else {
|
||||
PRINT("Video Frame PTS: not set\n");
|
||||
}
|
||||
if (packet.dts != AV_NOPTS_VALUE) {
|
||||
packet.dts = av_rescale_q(packet.dts, c->time_base, context->video_stream->time_base);
|
||||
PRINT("Video Frame DTS: %d\n", (int)packet.dts);
|
||||
}
|
||||
else {
|
||||
PRINT("Video Frame DTS: not set\n");
|
||||
}
|
||||
|
||||
packet.stream_index = context->video_stream->index;
|
||||
ret = av_interleaved_write_frame(context->outfile, &packet);
|
||||
success = (ret == 0);
|
||||
ret = avcodec_send_frame(c, frame);
|
||||
if (ret < 0) {
|
||||
/* Can't send frame to encoder. This shouldn't happen. */
|
||||
fprintf(stderr, "Can't send video frame: %s\n", av_err2str(ret));
|
||||
success = -1;
|
||||
}
|
||||
else if (ret < 0) {
|
||||
success = 0;
|
||||
|
||||
while (ret >= 0) {
|
||||
ret = avcodec_receive_packet(c, packet);
|
||||
|
||||
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
|
||||
/* No more packets available. */
|
||||
break;
|
||||
}
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error encoding frame: %s\n", av_err2str(ret));
|
||||
break;
|
||||
}
|
||||
|
||||
packet->stream_index = context->video_stream->index;
|
||||
av_packet_rescale_ts(packet, c->time_base, context->video_stream->time_base);
|
||||
if (av_interleaved_write_frame(context->outfile, packet) != 0) {
|
||||
success = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
BKE_report(reports, RPT_ERROR, "Error writing frame");
|
||||
PRINT("Error writing frame: %s\n", av_err2str(ret));
|
||||
}
|
||||
|
||||
av_packet_free(&packet);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/* read and encode a frame of audio from the buffer */
|
||||
static AVFrame *generate_video_frame(FFMpegContext *context,
|
||||
const uint8_t *pixels,
|
||||
ReportList *reports)
|
||||
static AVFrame *generate_video_frame(FFMpegContext *context, const uint8_t *pixels)
|
||||
{
|
||||
AVCodecContext *c = context->video_stream->codec;
|
||||
int height = c->height;
|
||||
AVCodecParameters *codec = context->video_stream->codecpar;
|
||||
int height = codec->height;
|
||||
AVFrame *rgb_frame;
|
||||
|
||||
if (context->img_convert_frame != NULL) {
|
||||
|
@ -437,7 +414,7 @@ static AVFrame *generate_video_frame(FFMpegContext *context,
|
|||
(const uint8_t *const *)rgb_frame->data,
|
||||
rgb_frame->linesize,
|
||||
0,
|
||||
c->height,
|
||||
codec->height,
|
||||
context->current_frame->data,
|
||||
context->current_frame->linesize);
|
||||
}
|
||||
|
@ -445,9 +422,7 @@ static AVFrame *generate_video_frame(FFMpegContext *context,
|
|||
return context->current_frame;
|
||||
}
|
||||
|
||||
static void set_ffmpeg_property_option(AVCodecContext *c,
|
||||
IDProperty *prop,
|
||||
AVDictionary **dictionary)
|
||||
static void set_ffmpeg_property_option(IDProperty *prop, AVDictionary **dictionary)
|
||||
{
|
||||
char name[128];
|
||||
char *param;
|
||||
|
@ -535,7 +510,7 @@ static void set_ffmpeg_properties(RenderData *rd,
|
|||
|
||||
for (curr = prop->data.group.first; curr; curr = curr->next) {
|
||||
if (ffmpeg_proprty_valid(c, prop_name, curr)) {
|
||||
set_ffmpeg_property_option(c, curr, dictionary);
|
||||
set_ffmpeg_property_option(curr, dictionary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -552,7 +527,6 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
|
|||
int error_size)
|
||||
{
|
||||
AVStream *st;
|
||||
AVCodecContext *c;
|
||||
AVCodec *codec;
|
||||
AVDictionary *opts = NULL;
|
||||
|
||||
|
@ -566,7 +540,8 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
|
|||
|
||||
/* Set up the codec context */
|
||||
|
||||
c = st->codec;
|
||||
context->video_codec = avcodec_alloc_context3(NULL);
|
||||
AVCodecContext *c = context->video_codec;
|
||||
c->codec_id = codec_id;
|
||||
c->codec_type = AVMEDIA_TYPE_VIDEO;
|
||||
|
||||
|
@ -649,11 +624,9 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
|
|||
}
|
||||
}
|
||||
|
||||
/* Deprecated and not doing anything since July 2015, deleted in recent ffmpeg */
|
||||
// c->me_method = ME_EPZS;
|
||||
|
||||
codec = avcodec_find_encoder(c->codec_id);
|
||||
if (!codec) {
|
||||
avcodec_free_context(&c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -713,7 +686,7 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
|
|||
|
||||
if ((of->oformat->flags & AVFMT_GLOBALHEADER)) {
|
||||
PRINT("Using global header\n");
|
||||
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||
c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
||||
}
|
||||
|
||||
/* xasp & yasp got float lately... */
|
||||
|
@ -741,6 +714,7 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
|
|||
if (avcodec_open2(c, codec, &opts) < 0) {
|
||||
BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
|
||||
av_dict_free(&opts);
|
||||
avcodec_free_context(&c);
|
||||
return NULL;
|
||||
}
|
||||
av_dict_free(&opts);
|
||||
|
@ -768,6 +742,8 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
|
|||
NULL);
|
||||
}
|
||||
|
||||
avcodec_parameters_from_context(st->codecpar, c);
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
|
@ -779,7 +755,6 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
|
|||
int error_size)
|
||||
{
|
||||
AVStream *st;
|
||||
AVCodecContext *c;
|
||||
AVCodec *codec;
|
||||
AVDictionary *opts = NULL;
|
||||
|
||||
|
@ -791,7 +766,8 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
|
|||
}
|
||||
st->id = 1;
|
||||
|
||||
c = st->codec;
|
||||
context->audio_codec = avcodec_alloc_context3(NULL);
|
||||
AVCodecContext *c = context->audio_codec;
|
||||
c->thread_count = BLI_system_thread_count();
|
||||
c->thread_type = FF_THREAD_SLICE;
|
||||
|
||||
|
@ -803,7 +779,6 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
|
|||
c->sample_fmt = AV_SAMPLE_FMT_S16;
|
||||
c->channels = rd->ffcodecdata.audio_channels;
|
||||
|
||||
# ifdef FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT
|
||||
switch (rd->ffcodecdata.audio_channels) {
|
||||
case FFM_CHANNELS_MONO:
|
||||
c->channel_layout = AV_CH_LAYOUT_MONO;
|
||||
|
@ -821,7 +796,6 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
|
|||
c->channel_layout = AV_CH_LAYOUT_7POINT1;
|
||||
break;
|
||||
}
|
||||
# endif
|
||||
|
||||
if (request_float_audio_buffer(codec_id)) {
|
||||
/* mainly for AAC codec which is experimental */
|
||||
|
@ -832,6 +806,7 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
|
|||
codec = avcodec_find_encoder(c->codec_id);
|
||||
if (!codec) {
|
||||
// XXX error("Couldn't find a valid audio codec");
|
||||
avcodec_free_context(&c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -843,13 +818,13 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
|
|||
* Float samples in particular are not always supported. */
|
||||
const enum AVSampleFormat *p = codec->sample_fmts;
|
||||
for (; *p != -1; p++) {
|
||||
if (*p == st->codec->sample_fmt) {
|
||||
if (*p == c->sample_fmt) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*p == -1) {
|
||||
/* sample format incompatible with codec. Defaulting to a format known to work */
|
||||
st->codec->sample_fmt = codec->sample_fmts[0];
|
||||
c->sample_fmt = codec->sample_fmts[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -858,18 +833,18 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
|
|||
int best = 0;
|
||||
int best_dist = INT_MAX;
|
||||
for (; *p; p++) {
|
||||
int dist = abs(st->codec->sample_rate - *p);
|
||||
int dist = abs(c->sample_rate - *p);
|
||||
if (dist < best_dist) {
|
||||
best_dist = dist;
|
||||
best = *p;
|
||||
}
|
||||
}
|
||||
/* best is the closest supported sample rate (same as selected if best_dist == 0) */
|
||||
st->codec->sample_rate = best;
|
||||
c->sample_rate = best;
|
||||
}
|
||||
|
||||
if (of->oformat->flags & AVFMT_GLOBALHEADER) {
|
||||
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||
c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
||||
}
|
||||
|
||||
set_ffmpeg_properties(rd, c, "audio", &opts);
|
||||
|
@ -878,32 +853,25 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
|
|||
// XXX error("Couldn't initialize audio codec");
|
||||
BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
|
||||
av_dict_free(&opts);
|
||||
avcodec_free_context(&c);
|
||||
return NULL;
|
||||
}
|
||||
av_dict_free(&opts);
|
||||
|
||||
/* need to prevent floating point exception when using vorbis audio codec,
|
||||
* initialize this value in the same way as it's done in FFmpeg itself (sergey) */
|
||||
st->codec->time_base.num = 1;
|
||||
st->codec->time_base.den = st->codec->sample_rate;
|
||||
|
||||
# ifndef FFMPEG_HAVE_ENCODE_AUDIO2
|
||||
context->audio_outbuf_size = FF_MIN_BUFFER_SIZE;
|
||||
# endif
|
||||
c->time_base.num = 1;
|
||||
c->time_base.den = c->sample_rate;
|
||||
|
||||
if (c->frame_size == 0) {
|
||||
/* Used to be if ((c->codec_id >= CODEC_ID_PCM_S16LE) && (c->codec_id <= CODEC_ID_PCM_DVD))
|
||||
* not sure if that is needed anymore, so let's try out if there are any
|
||||
* complaints regarding some FFmpeg versions users might have. */
|
||||
context->audio_input_samples = FF_MIN_BUFFER_SIZE * 8 / c->bits_per_coded_sample / c->channels;
|
||||
context->audio_input_samples = AV_INPUT_BUFFER_MIN_SIZE * 8 / c->bits_per_coded_sample /
|
||||
c->channels;
|
||||
}
|
||||
else {
|
||||
context->audio_input_samples = c->frame_size;
|
||||
# ifndef FFMPEG_HAVE_ENCODE_AUDIO2
|
||||
if (c->frame_size * c->channels * sizeof(int16_t) * 4 > context->audio_outbuf_size) {
|
||||
context->audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4;
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
context->audio_deinterleave = av_sample_fmt_is_planar(c->sample_fmt);
|
||||
|
@ -912,10 +880,6 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
|
|||
|
||||
context->audio_input_buffer = (uint8_t *)av_malloc(context->audio_input_samples * c->channels *
|
||||
context->audio_sample_size);
|
||||
# ifndef FFMPEG_HAVE_ENCODE_AUDIO2
|
||||
context->audio_output_buffer = (uint8_t *)av_malloc(context->audio_outbuf_size);
|
||||
# endif
|
||||
|
||||
if (context->audio_deinterleave) {
|
||||
context->audio_deinterleave_buffer = (uint8_t *)av_malloc(
|
||||
context->audio_input_samples * c->channels * context->audio_sample_size);
|
||||
|
@ -923,6 +887,8 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
|
|||
|
||||
context->audio_time = 0.0f;
|
||||
|
||||
avcodec_parameters_from_context(st->codecpar, c);
|
||||
|
||||
return st;
|
||||
}
|
||||
/* essential functions -- start, append, end */
|
||||
|
@ -948,7 +914,7 @@ static void ffmpeg_dict_set_float(AVDictionary **dict, const char *key, float va
|
|||
static void ffmpeg_add_metadata_callback(void *data,
|
||||
const char *propname,
|
||||
char *propvalue,
|
||||
int len)
|
||||
int UNUSED(len))
|
||||
{
|
||||
AVDictionary **metadata = (AVDictionary **)data;
|
||||
av_dict_set(metadata, propname, propvalue, 0);
|
||||
|
@ -1039,7 +1005,7 @@ static int start_ffmpeg_impl(FFMpegContext *context,
|
|||
|
||||
fmt->audio_codec = context->ffmpeg_audio_codec;
|
||||
|
||||
BLI_strncpy(of->filename, name, sizeof(of->filename));
|
||||
of->url = av_strdup(name);
|
||||
/* set the codec to the user's selection */
|
||||
switch (context->ffmpeg_type) {
|
||||
case FFMPEG_AVI:
|
||||
|
@ -1104,9 +1070,11 @@ static int start_ffmpeg_impl(FFMpegContext *context,
|
|||
if (!context->video_stream) {
|
||||
if (error[0]) {
|
||||
BKE_report(reports, RPT_ERROR, error);
|
||||
PRINT("Video stream error: %s\n", error);
|
||||
}
|
||||
else {
|
||||
BKE_report(reports, RPT_ERROR, "Error initializing video stream");
|
||||
PRINT("Error initializing video stream");
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
|
@ -1118,9 +1086,11 @@ static int start_ffmpeg_impl(FFMpegContext *context,
|
|||
if (!context->audio_stream) {
|
||||
if (error[0]) {
|
||||
BKE_report(reports, RPT_ERROR, error);
|
||||
PRINT("Audio stream error: %s\n", error);
|
||||
}
|
||||
else {
|
||||
BKE_report(reports, RPT_ERROR, "Error initializing audio stream");
|
||||
PRINT("Error initializing audio stream");
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
|
@ -1128,6 +1098,7 @@ static int start_ffmpeg_impl(FFMpegContext *context,
|
|||
if (!(fmt->flags & AVFMT_NOFILE)) {
|
||||
if (avio_open(&of->pb, name, AVIO_FLAG_WRITE) < 0) {
|
||||
BKE_report(reports, RPT_ERROR, "Could not open file for writing");
|
||||
PRINT("Could not open file for writing\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
@ -1137,10 +1108,12 @@ static int start_ffmpeg_impl(FFMpegContext *context,
|
|||
&of->metadata, context->stamp_data, ffmpeg_add_metadata_callback, false);
|
||||
}
|
||||
|
||||
if (avformat_write_header(of, NULL) < 0) {
|
||||
int ret = avformat_write_header(of, NULL);
|
||||
if (ret < 0) {
|
||||
BKE_report(reports,
|
||||
RPT_ERROR,
|
||||
"Could not initialize streams, probably unsupported codec combination");
|
||||
PRINT("Could not write media header: %s\n", av_err2str(ret));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -1155,13 +1128,11 @@ fail:
|
|||
avio_close(of->pb);
|
||||
}
|
||||
|
||||
if (context->video_stream && context->video_stream->codec) {
|
||||
avcodec_close(context->video_stream->codec);
|
||||
if (context->video_stream) {
|
||||
context->video_stream = NULL;
|
||||
}
|
||||
|
||||
if (context->audio_stream && context->audio_stream->codec) {
|
||||
avcodec_close(context->audio_stream->codec);
|
||||
if (context->audio_stream) {
|
||||
context->audio_stream = NULL;
|
||||
}
|
||||
|
||||
|
@ -1189,46 +1160,36 @@ fail:
|
|||
*/
|
||||
static void flush_ffmpeg(FFMpegContext *context)
|
||||
{
|
||||
int ret = 0;
|
||||
AVCodecContext *c = context->video_codec;
|
||||
AVPacket *packet = av_packet_alloc();
|
||||
|
||||
AVCodecContext *c = context->video_stream->codec;
|
||||
/* get the delayed frames */
|
||||
while (1) {
|
||||
int got_output;
|
||||
AVPacket packet = {0};
|
||||
av_init_packet(&packet);
|
||||
avcodec_send_frame(c, NULL);
|
||||
|
||||
ret = avcodec_encode_video2(c, &packet, NULL, &got_output);
|
||||
/* Get the packets frames. */
|
||||
int ret = 1;
|
||||
while (ret >= 0) {
|
||||
ret = avcodec_receive_packet(c, packet);
|
||||
|
||||
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
|
||||
/* No more packets to flush. */
|
||||
break;
|
||||
}
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error encoding delayed frame %d\n", ret);
|
||||
fprintf(stderr, "Error encoding delayed frame: %s\n", av_err2str(ret));
|
||||
break;
|
||||
}
|
||||
if (!got_output) {
|
||||
break;
|
||||
}
|
||||
if (packet.pts != AV_NOPTS_VALUE) {
|
||||
packet.pts = av_rescale_q(packet.pts, c->time_base, context->video_stream->time_base);
|
||||
PRINT("Video Frame PTS: %d\n", (int)packet.pts);
|
||||
}
|
||||
else {
|
||||
PRINT("Video Frame PTS: not set\n");
|
||||
}
|
||||
if (packet.dts != AV_NOPTS_VALUE) {
|
||||
packet.dts = av_rescale_q(packet.dts, c->time_base, context->video_stream->time_base);
|
||||
PRINT("Video Frame DTS: %d\n", (int)packet.dts);
|
||||
}
|
||||
else {
|
||||
PRINT("Video Frame DTS: not set\n");
|
||||
}
|
||||
|
||||
packet.stream_index = context->video_stream->index;
|
||||
ret = av_interleaved_write_frame(context->outfile, &packet);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Error writing delayed frame %d\n", ret);
|
||||
packet->stream_index = context->video_stream->index;
|
||||
av_packet_rescale_ts(packet, c->time_base, context->video_stream->time_base);
|
||||
|
||||
int write_ret = av_interleaved_write_frame(context->outfile, packet);
|
||||
if (write_ret != 0) {
|
||||
fprintf(stderr, "Error writing delayed frame: %s\n", av_err2str(write_ret));
|
||||
break;
|
||||
}
|
||||
}
|
||||
avcodec_flush_buffers(context->video_stream->codec);
|
||||
|
||||
av_packet_free(&packet);
|
||||
}
|
||||
|
||||
/* **********************************************************************
|
||||
|
@ -1326,7 +1287,8 @@ int BKE_ffmpeg_start(void *context_v,
|
|||
success = start_ffmpeg_impl(context, rd, rectx, recty, suffix, reports);
|
||||
# ifdef WITH_AUDASPACE
|
||||
if (context->audio_stream) {
|
||||
AVCodecContext *c = context->audio_stream->codec;
|
||||
AVCodecContext *c = context->audio_codec;
|
||||
|
||||
AUD_DeviceSpecs specs;
|
||||
specs.channels = c->channels;
|
||||
|
||||
|
@ -1353,10 +1315,6 @@ int BKE_ffmpeg_start(void *context_v,
|
|||
specs.rate = rd->ffcodecdata.audio_mixrate;
|
||||
context->audio_mixdown_device = BKE_sound_mixdown(
|
||||
scene, specs, preview ? rd->psfra : rd->sfra, rd->ffcodecdata.audio_volume);
|
||||
# ifdef FFMPEG_CODEC_TIME_BASE
|
||||
c->time_base.den = specs.rate;
|
||||
c->time_base.num = 1;
|
||||
# endif
|
||||
}
|
||||
# endif
|
||||
return success;
|
||||
|
@ -1397,8 +1355,8 @@ int BKE_ffmpeg_append(void *context_v,
|
|||
// write_audio_frames(frame / (((double)rd->frs_sec) / rd->frs_sec_base));
|
||||
|
||||
if (context->video_stream) {
|
||||
avframe = generate_video_frame(context, (unsigned char *)pixels, reports);
|
||||
success = (avframe && write_video_frame(context, rd, frame - start_frame, avframe, reports));
|
||||
avframe = generate_video_frame(context, (unsigned char *)pixels);
|
||||
success = (avframe && write_video_frame(context, frame - start_frame, avframe, reports));
|
||||
|
||||
if (context->ffmpeg_autosplit) {
|
||||
if (avio_tell(context->outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) {
|
||||
|
@ -1427,9 +1385,11 @@ static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit)
|
|||
context->audio_mixdown_device = NULL;
|
||||
}
|
||||
}
|
||||
# else
|
||||
UNUSED_VARS(is_autosplit);
|
||||
# endif
|
||||
|
||||
if (context->video_stream && context->video_stream->codec) {
|
||||
if (context->video_stream) {
|
||||
PRINT("Flushing delayed frames...\n");
|
||||
flush_ffmpeg(context);
|
||||
}
|
||||
|
@ -1440,14 +1400,12 @@ static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit)
|
|||
|
||||
/* Close the video codec */
|
||||
|
||||
if (context->video_stream != NULL && context->video_stream->codec != NULL) {
|
||||
avcodec_close(context->video_stream->codec);
|
||||
if (context->video_stream != NULL) {
|
||||
PRINT("zero video stream %p\n", context->video_stream);
|
||||
context->video_stream = NULL;
|
||||
}
|
||||
|
||||
if (context->audio_stream != NULL && context->audio_stream->codec != NULL) {
|
||||
avcodec_close(context->audio_stream->codec);
|
||||
if (context->audio_stream != NULL) {
|
||||
context->audio_stream = NULL;
|
||||
}
|
||||
|
||||
|
@ -1466,6 +1424,16 @@ static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit)
|
|||
avio_close(context->outfile->pb);
|
||||
}
|
||||
}
|
||||
|
||||
if (context->video_codec != NULL) {
|
||||
avcodec_free_context(&context->video_codec);
|
||||
context->video_codec = NULL;
|
||||
}
|
||||
if (context->audio_codec != NULL) {
|
||||
avcodec_free_context(&context->audio_codec);
|
||||
context->audio_codec = NULL;
|
||||
}
|
||||
|
||||
if (context->outfile != NULL) {
|
||||
avformat_free_context(context->outfile);
|
||||
context->outfile = NULL;
|
||||
|
@ -1474,12 +1442,6 @@ static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit)
|
|||
av_free(context->audio_input_buffer);
|
||||
context->audio_input_buffer = NULL;
|
||||
}
|
||||
# ifndef FFMPEG_HAVE_ENCODE_AUDIO2
|
||||
if (context->audio_output_buffer != NULL) {
|
||||
av_free(context->audio_output_buffer);
|
||||
context->audio_output_buffer = NULL;
|
||||
}
|
||||
# endif
|
||||
|
||||
if (context->audio_deinterleave_buffer != NULL) {
|
||||
av_free(context->audio_deinterleave_buffer);
|
||||
|
@ -1559,12 +1521,12 @@ static IDProperty *BKE_ffmpeg_property_add(RenderData *rd,
|
|||
switch (o->type) {
|
||||
case AV_OPT_TYPE_INT:
|
||||
case AV_OPT_TYPE_INT64:
|
||||
val.i = FFMPEG_DEF_OPT_VAL_INT(o);
|
||||
val.i = o->default_val.i64;
|
||||
idp_type = IDP_INT;
|
||||
break;
|
||||
case AV_OPT_TYPE_DOUBLE:
|
||||
case AV_OPT_TYPE_FLOAT:
|
||||
val.f = FFMPEG_DEF_OPT_VAL_DOUBLE(o);
|
||||
val.f = o->default_val.dbl;
|
||||
idp_type = IDP_FLOAT;
|
||||
break;
|
||||
case AV_OPT_TYPE_STRING:
|
||||
|
@ -1706,16 +1668,9 @@ static void ffmpeg_set_expert_options(RenderData *rd)
|
|||
|
||||
BKE_ffmpeg_property_add_string(rd, "video", "trellis:0");
|
||||
BKE_ffmpeg_property_add_string(rd, "video", "weightb:1");
|
||||
# ifdef FFMPEG_HAVE_DEPRECATED_FLAGS2
|
||||
BKE_ffmpeg_property_add_string(rd, "video", "flags2:dct8x8");
|
||||
BKE_ffmpeg_property_add_string(rd, "video", "directpred:3");
|
||||
BKE_ffmpeg_property_add_string(rd, "video", "flags2:fastpskip");
|
||||
BKE_ffmpeg_property_add_string(rd, "video", "flags2:wpred");
|
||||
# else
|
||||
BKE_ffmpeg_property_add_string(rd, "video", "8x8dct:1");
|
||||
BKE_ffmpeg_property_add_string(rd, "video", "fast-pskip:1");
|
||||
BKE_ffmpeg_property_add_string(rd, "video", "wpredp:2");
|
||||
# endif
|
||||
}
|
||||
else if (codec_id == AV_CODEC_ID_DNXHD) {
|
||||
if (rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT) {
|
||||
|
@ -1870,14 +1825,12 @@ bool BKE_ffmpeg_alpha_channel_is_supported(const RenderData *rd)
|
|||
{
|
||||
int codec = rd->ffcodecdata.codec;
|
||||
|
||||
# ifdef FFMPEG_FFV1_ALPHA_SUPPORTED
|
||||
/* Visual Studio 2019 doesn't like #ifdef within ELEM(). */
|
||||
if (codec == AV_CODEC_ID_FFV1) {
|
||||
return true;
|
||||
}
|
||||
# endif
|
||||
|
||||
return ELEM(codec, AV_CODEC_ID_QTRLE, AV_CODEC_ID_PNG, AV_CODEC_ID_VP9, AV_CODEC_ID_HUFFYUV);
|
||||
return ELEM(codec,
|
||||
AV_CODEC_ID_FFV1,
|
||||
AV_CODEC_ID_QTRLE,
|
||||
AV_CODEC_ID_PNG,
|
||||
AV_CODEC_ID_VP9,
|
||||
AV_CODEC_ID_HUFFYUV);
|
||||
}
|
||||
|
||||
void *BKE_ffmpeg_context_create(void)
|
||||
|
|
|
@ -78,7 +78,7 @@ float BLI_dial_angle(Dial *dial, const float current_position[2])
|
|||
cosval = dot_v2v2(current_direction, dial->initial_direction);
|
||||
sinval = cross_v2v2(current_direction, dial->initial_direction);
|
||||
|
||||
/* clamp to avoid nans in #acos */
|
||||
/* Clamp to avoid NAN's in #acos */
|
||||
angle = atan2f(sinval, cosval);
|
||||
|
||||
/* change of sign, we passed the 180 degree threshold. This means we need to add a turn.
|
||||
|
|
|
@ -111,6 +111,7 @@
|
|||
#include "SEQ_iterator.h"
|
||||
#include "SEQ_modifier.h"
|
||||
#include "SEQ_sequencer.h"
|
||||
#include "SEQ_utils.h"
|
||||
|
||||
#include "readfile.h"
|
||||
|
||||
|
@ -2696,7 +2697,7 @@ static int lib_link_seq_clipboard_cb(Sequence *seq, void *arg_pt)
|
|||
static void lib_link_clipboard_restore(struct IDNameLib_Map *id_map)
|
||||
{
|
||||
/* update IDs stored in sequencer clipboard */
|
||||
SEQ_iterator_seqbase_recursive_apply(&seqbase_clipboard, lib_link_seq_clipboard_cb, id_map);
|
||||
SEQ_seqbase_recursive_apply(&seqbase_clipboard, lib_link_seq_clipboard_cb, id_map);
|
||||
}
|
||||
|
||||
static int lib_link_main_data_restore_cb(LibraryIDLinkCallbackData *cb_data)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#define DNA_DEPRECATED_ALLOW
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "DNA_brush_types.h"
|
||||
|
@ -95,5 +96,15 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
*/
|
||||
{
|
||||
/* Keep this block, even when empty. */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "bPoseChannel", "float", "custom_scale_xyz[3]")) {
|
||||
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
|
||||
if (ob->pose == NULL) {
|
||||
continue;
|
||||
}
|
||||
LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
|
||||
copy_v3_fl(pchan->custom_scale_xyz, pchan->custom_scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1278,12 +1278,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
|
|||
if (ob->soft->physics_speed == 0.0f) {
|
||||
ob->soft->physics_speed = 1.0f;
|
||||
}
|
||||
|
||||
if (ob->soft->interval == 0) {
|
||||
ob->soft->interval = 2;
|
||||
ob->soft->sfra = 1;
|
||||
ob->soft->efra = 100;
|
||||
}
|
||||
}
|
||||
if (ob->soft && ob->soft->vertgroup == 0) {
|
||||
bDeformGroup *locGroup = BKE_object_defgroup_find_name(ob, "SOFTGOAL");
|
||||
|
|
|
@ -25,29 +25,49 @@ namespace blender::compositor {
|
|||
MemoryBuffer::MemoryBuffer(MemoryProxy *memoryProxy, const rcti &rect, MemoryBufferState state)
|
||||
{
|
||||
m_rect = rect;
|
||||
this->m_is_a_single_elem = false;
|
||||
this->m_memoryProxy = memoryProxy;
|
||||
this->m_num_channels = COM_data_type_num_channels(memoryProxy->getDataType());
|
||||
this->m_buffer = (float *)MEM_mallocN_aligned(
|
||||
sizeof(float) * buffer_len() * this->m_num_channels, 16, "COM_MemoryBuffer");
|
||||
this->m_state = state;
|
||||
this->m_datatype = memoryProxy->getDataType();
|
||||
|
||||
set_strides();
|
||||
}
|
||||
|
||||
MemoryBuffer::MemoryBuffer(DataType dataType, const rcti &rect)
|
||||
MemoryBuffer::MemoryBuffer(DataType dataType, const rcti &rect, bool is_a_single_elem)
|
||||
{
|
||||
m_rect = rect;
|
||||
this->m_is_a_single_elem = is_a_single_elem;
|
||||
this->m_memoryProxy = nullptr;
|
||||
this->m_num_channels = COM_data_type_num_channels(dataType);
|
||||
this->m_buffer = (float *)MEM_mallocN_aligned(
|
||||
sizeof(float) * buffer_len() * this->m_num_channels, 16, "COM_MemoryBuffer");
|
||||
this->m_state = MemoryBufferState::Temporary;
|
||||
this->m_datatype = dataType;
|
||||
|
||||
set_strides();
|
||||
}
|
||||
|
||||
MemoryBuffer::MemoryBuffer(const MemoryBuffer &src)
|
||||
: MemoryBuffer(src.m_memoryProxy, src.m_rect, MemoryBufferState::Temporary)
|
||||
: MemoryBuffer(src.m_datatype, src.m_rect, false)
|
||||
{
|
||||
memcpy(m_buffer, src.m_buffer, buffer_len() * m_num_channels * sizeof(float));
|
||||
m_memoryProxy = src.m_memoryProxy;
|
||||
/* src may be single elem buffer */
|
||||
fill_from(src);
|
||||
}
|
||||
|
||||
void MemoryBuffer::set_strides()
|
||||
{
|
||||
if (m_is_a_single_elem) {
|
||||
this->elem_stride = 0;
|
||||
this->row_stride = 0;
|
||||
}
|
||||
else {
|
||||
this->elem_stride = m_num_channels;
|
||||
this->row_stride = getWidth() * m_num_channels;
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryBuffer::clear()
|
||||
|
@ -100,6 +120,8 @@ MemoryBuffer::~MemoryBuffer()
|
|||
|
||||
void MemoryBuffer::fill_from(const MemoryBuffer &src)
|
||||
{
|
||||
BLI_assert(!this->is_a_single_elem());
|
||||
|
||||
unsigned int otherY;
|
||||
unsigned int minX = MAX2(this->m_rect.xmin, src.m_rect.xmin);
|
||||
unsigned int maxX = MIN2(this->m_rect.xmax, src.m_rect.xmax);
|
||||
|
@ -109,10 +131,8 @@ void MemoryBuffer::fill_from(const MemoryBuffer &src)
|
|||
int otherOffset;
|
||||
|
||||
for (otherY = minY; otherY < maxY; otherY++) {
|
||||
otherOffset = ((otherY - src.m_rect.ymin) * src.getWidth() + minX - src.m_rect.xmin) *
|
||||
this->m_num_channels;
|
||||
offset = ((otherY - this->m_rect.ymin) * getWidth() + minX - this->m_rect.xmin) *
|
||||
this->m_num_channels;
|
||||
otherOffset = src.get_coords_offset(minX, otherY);
|
||||
offset = this->get_coords_offset(minX, otherY);
|
||||
memcpy(&this->m_buffer[offset],
|
||||
&src.m_buffer[otherOffset],
|
||||
(maxX - minX) * this->m_num_channels * sizeof(float));
|
||||
|
@ -123,8 +143,7 @@ void MemoryBuffer::writePixel(int x, int y, const float color[4])
|
|||
{
|
||||
if (x >= this->m_rect.xmin && x < this->m_rect.xmax && y >= this->m_rect.ymin &&
|
||||
y < this->m_rect.ymax) {
|
||||
const int offset = (getWidth() * (y - this->m_rect.ymin) + x - this->m_rect.xmin) *
|
||||
this->m_num_channels;
|
||||
const int offset = get_coords_offset(x, y);
|
||||
memcpy(&this->m_buffer[offset], color, sizeof(float) * this->m_num_channels);
|
||||
}
|
||||
}
|
||||
|
@ -133,8 +152,7 @@ void MemoryBuffer::addPixel(int x, int y, const float color[4])
|
|||
{
|
||||
if (x >= this->m_rect.xmin && x < this->m_rect.xmax && y >= this->m_rect.ymin &&
|
||||
y < this->m_rect.ymax) {
|
||||
const int offset = (getWidth() * (y - this->m_rect.ymin) + x - this->m_rect.xmin) *
|
||||
this->m_num_channels;
|
||||
const int offset = get_coords_offset(x, y);
|
||||
float *dst = &this->m_buffer[offset];
|
||||
const float *src = color;
|
||||
for (int i = 0; i < this->m_num_channels; i++, dst++, src++) {
|
||||
|
@ -151,26 +169,31 @@ static void read_ewa_pixel_sampled(void *userdata, int x, int y, float result[4]
|
|||
|
||||
void MemoryBuffer::readEWA(float *result, const float uv[2], const float derivatives[2][2])
|
||||
{
|
||||
BLI_assert(this->m_datatype == DataType::Color);
|
||||
float inv_width = 1.0f / (float)this->getWidth(), inv_height = 1.0f / (float)this->getHeight();
|
||||
/* TODO(sergey): Render pipeline uses normalized coordinates and derivatives,
|
||||
* but compositor uses pixel space. For now let's just divide the values and
|
||||
* switch compositor to normalized space for EWA later.
|
||||
*/
|
||||
float uv_normal[2] = {uv[0] * inv_width, uv[1] * inv_height};
|
||||
float du_normal[2] = {derivatives[0][0] * inv_width, derivatives[0][1] * inv_height};
|
||||
float dv_normal[2] = {derivatives[1][0] * inv_width, derivatives[1][1] * inv_height};
|
||||
if (m_is_a_single_elem) {
|
||||
memcpy(result, m_buffer, sizeof(float) * this->m_num_channels);
|
||||
}
|
||||
else {
|
||||
BLI_assert(this->m_datatype == DataType::Color);
|
||||
float inv_width = 1.0f / (float)this->getWidth(), inv_height = 1.0f / (float)this->getHeight();
|
||||
/* TODO(sergey): Render pipeline uses normalized coordinates and derivatives,
|
||||
* but compositor uses pixel space. For now let's just divide the values and
|
||||
* switch compositor to normalized space for EWA later.
|
||||
*/
|
||||
float uv_normal[2] = {uv[0] * inv_width, uv[1] * inv_height};
|
||||
float du_normal[2] = {derivatives[0][0] * inv_width, derivatives[0][1] * inv_height};
|
||||
float dv_normal[2] = {derivatives[1][0] * inv_width, derivatives[1][1] * inv_height};
|
||||
|
||||
BLI_ewa_filter(this->getWidth(),
|
||||
this->getHeight(),
|
||||
false,
|
||||
true,
|
||||
uv_normal,
|
||||
du_normal,
|
||||
dv_normal,
|
||||
read_ewa_pixel_sampled,
|
||||
this,
|
||||
result);
|
||||
BLI_ewa_filter(this->getWidth(),
|
||||
this->getHeight(),
|
||||
false,
|
||||
true,
|
||||
uv_normal,
|
||||
du_normal,
|
||||
dv_normal,
|
||||
read_ewa_pixel_sampled,
|
||||
this,
|
||||
result);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::compositor
|
||||
|
|
|
@ -50,6 +50,25 @@ class MemoryProxy;
|
|||
* \brief a MemoryBuffer contains access to the data of a chunk
|
||||
*/
|
||||
class MemoryBuffer {
|
||||
public:
|
||||
/**
|
||||
* Offset between elements.
|
||||
*
|
||||
* Should always be used for the x dimension when calculating buffer offsets.
|
||||
* It will be 0 when is_a_single_elem=true.
|
||||
* e.g: buffer_index = y * buffer.row_stride + x * buffer.elem_stride
|
||||
*/
|
||||
int elem_stride;
|
||||
|
||||
/**
|
||||
* Offset between rows.
|
||||
*
|
||||
* Should always be used for the y dimension when calculating buffer offsets.
|
||||
* It will be 0 when is_a_single_elem=true.
|
||||
* e.g: buffer_index = y * buffer.row_stride + x * buffer.elem_stride
|
||||
*/
|
||||
int row_stride;
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief proxy of the memory (same for all chunks in the same buffer)
|
||||
|
@ -82,6 +101,11 @@ class MemoryBuffer {
|
|||
*/
|
||||
uint8_t m_num_channels;
|
||||
|
||||
/**
|
||||
* Whether buffer is a single element in memory.
|
||||
*/
|
||||
bool m_is_a_single_elem;
|
||||
|
||||
public:
|
||||
/**
|
||||
* \brief construct new temporarily MemoryBuffer for an area
|
||||
|
@ -91,7 +115,7 @@ class MemoryBuffer {
|
|||
/**
|
||||
* \brief construct new temporarily MemoryBuffer for an area
|
||||
*/
|
||||
MemoryBuffer(DataType datatype, const rcti &rect);
|
||||
MemoryBuffer(DataType datatype, const rcti &rect, bool is_a_single_elem = false);
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
|
@ -103,6 +127,102 @@ class MemoryBuffer {
|
|||
*/
|
||||
~MemoryBuffer();
|
||||
|
||||
/**
|
||||
* Whether buffer is a single element in memory independently of its resolution. True for set
|
||||
* operations buffers.
|
||||
*/
|
||||
bool is_a_single_elem() const
|
||||
{
|
||||
return m_is_a_single_elem;
|
||||
}
|
||||
|
||||
float &operator[](int index)
|
||||
{
|
||||
BLI_assert(m_is_a_single_elem ? index < m_num_channels :
|
||||
index < get_coords_offset(getWidth(), getHeight()));
|
||||
return m_buffer[index];
|
||||
}
|
||||
|
||||
const float &operator[](int index) const
|
||||
{
|
||||
BLI_assert(m_is_a_single_elem ? index < m_num_channels :
|
||||
index < get_coords_offset(getWidth(), getHeight()));
|
||||
return m_buffer[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get offset needed to jump from buffer start to given coordinates.
|
||||
*/
|
||||
int get_coords_offset(int x, int y) const
|
||||
{
|
||||
return (y - m_rect.ymin) * row_stride + (x - m_rect.xmin) * elem_stride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get buffer element at given coordinates.
|
||||
*/
|
||||
float *get_elem(int x, int y)
|
||||
{
|
||||
BLI_assert(x >= m_rect.xmin && x < m_rect.xmax && y >= m_rect.ymin && y < m_rect.ymax);
|
||||
return m_buffer + get_coords_offset(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get buffer element at given coordinates.
|
||||
*/
|
||||
const float *get_elem(int x, int y) const
|
||||
{
|
||||
BLI_assert(x >= m_rect.xmin && x < m_rect.xmax && y >= m_rect.ymin && y < m_rect.ymax);
|
||||
return m_buffer + get_coords_offset(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get channel value at given coordinates.
|
||||
*/
|
||||
float &get_value(int x, int y, int channel)
|
||||
{
|
||||
BLI_assert(x >= m_rect.xmin && x < m_rect.xmax && y >= m_rect.ymin && y < m_rect.ymax &&
|
||||
channel >= 0 && channel < m_num_channels);
|
||||
return m_buffer[get_coords_offset(x, y) + channel];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get channel value at given coordinates.
|
||||
*/
|
||||
const float &get_value(int x, int y, int channel) const
|
||||
{
|
||||
BLI_assert(x >= m_rect.xmin && x < m_rect.xmax && y >= m_rect.ymin && y < m_rect.ymax &&
|
||||
channel >= 0 && channel < m_num_channels);
|
||||
return m_buffer[get_coords_offset(x, y) + channel];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the buffer row end.
|
||||
*/
|
||||
const float *get_row_end(int y) const
|
||||
{
|
||||
BLI_assert(y >= 0 && y < getHeight());
|
||||
return m_buffer + (is_a_single_elem() ? m_num_channels : get_coords_offset(getWidth(), y));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of elements in memory for a row. For single element buffers it will always
|
||||
* be 1.
|
||||
*/
|
||||
int get_memory_width() const
|
||||
{
|
||||
return is_a_single_elem() ? 1 : getWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of elements in memory for a column. For single element buffers it will
|
||||
* always be 1.
|
||||
*/
|
||||
int get_memory_height() const
|
||||
{
|
||||
return is_a_single_elem() ? 1 : getHeight();
|
||||
}
|
||||
|
||||
uint8_t get_num_channels()
|
||||
{
|
||||
return this->m_num_channels;
|
||||
|
@ -216,7 +336,7 @@ class MemoryBuffer {
|
|||
int u = x;
|
||||
int v = y;
|
||||
this->wrap_pixel(u, v, extend_x, extend_y);
|
||||
const int offset = (getWidth() * y + x) * this->m_num_channels;
|
||||
const int offset = get_coords_offset(u, v);
|
||||
float *buffer = &this->m_buffer[offset];
|
||||
memcpy(result, buffer, sizeof(float) * this->m_num_channels);
|
||||
}
|
||||
|
@ -232,7 +352,7 @@ class MemoryBuffer {
|
|||
int v = y;
|
||||
|
||||
this->wrap_pixel(u, v, extend_x, extend_y);
|
||||
const int offset = (getWidth() * v + u) * this->m_num_channels;
|
||||
const int offset = get_coords_offset(u, v);
|
||||
|
||||
BLI_assert(offset >= 0);
|
||||
BLI_assert(offset < this->buffer_len() * this->m_num_channels);
|
||||
|
@ -258,15 +378,20 @@ class MemoryBuffer {
|
|||
copy_vn_fl(result, this->m_num_channels, 0.0f);
|
||||
return;
|
||||
}
|
||||
BLI_bilinear_interpolation_wrap_fl(this->m_buffer,
|
||||
result,
|
||||
getWidth(),
|
||||
getHeight(),
|
||||
this->m_num_channels,
|
||||
u,
|
||||
v,
|
||||
extend_x == MemoryBufferExtend::Repeat,
|
||||
extend_y == MemoryBufferExtend::Repeat);
|
||||
if (m_is_a_single_elem) {
|
||||
memcpy(result, m_buffer, sizeof(float) * this->m_num_channels);
|
||||
}
|
||||
else {
|
||||
BLI_bilinear_interpolation_wrap_fl(this->m_buffer,
|
||||
result,
|
||||
getWidth(),
|
||||
getHeight(),
|
||||
this->m_num_channels,
|
||||
u,
|
||||
v,
|
||||
extend_x == MemoryBufferExtend::Repeat,
|
||||
extend_y == MemoryBufferExtend::Repeat);
|
||||
}
|
||||
}
|
||||
|
||||
void readEWA(float *result, const float uv[2], const float derivatives[2][2]);
|
||||
|
@ -321,9 +446,10 @@ class MemoryBuffer {
|
|||
float get_max_value(const rcti &rect) const;
|
||||
|
||||
private:
|
||||
void set_strides();
|
||||
const int buffer_len() const
|
||||
{
|
||||
return getWidth() * getHeight();
|
||||
return get_memory_width() * get_memory_height();
|
||||
}
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
|
|
|
@ -121,7 +121,7 @@ void EEVEE_cryptomatte_renderpasses_init(EEVEE_Data *vedata)
|
|||
ViewLayer *view_layer = draw_ctx->view_layer;
|
||||
|
||||
/* Cryptomatte is only rendered for final image renders */
|
||||
if (!DRW_state_is_image_render()) {
|
||||
if (!DRW_state_is_scene_render()) {
|
||||
return;
|
||||
}
|
||||
const eViewLayerCryptomatteFlags active_layers = eevee_cryptomatte_active_layers(view_layer);
|
||||
|
@ -158,9 +158,9 @@ void EEVEE_cryptomatte_output_init(EEVEE_ViewLayerData *UNUSED(sldata),
|
|||
const ViewLayer *view_layer = draw_ctx->view_layer;
|
||||
|
||||
const int num_cryptomatte_layers = eevee_cryptomatte_layers_count(view_layer);
|
||||
eGPUTextureFormat format = (num_cryptomatte_layers == 1) ?
|
||||
GPU_R32F :
|
||||
(num_cryptomatte_layers == 2) ? GPU_RG32F : GPU_RGBA32F;
|
||||
eGPUTextureFormat format = (num_cryptomatte_layers == 1) ? GPU_R32F :
|
||||
(num_cryptomatte_layers == 2) ? GPU_RG32F :
|
||||
GPU_RGBA32F;
|
||||
const float *viewport_size = DRW_viewport_size_get();
|
||||
const int buffer_size = viewport_size[0] * viewport_size[1];
|
||||
|
||||
|
|
|
@ -623,6 +623,11 @@ static EeveeMaterialCache material_opaque(EEVEE_Data *vedata,
|
|||
/* This GPUShader has already been used by another material.
|
||||
* Add new shading group just after to avoid shader switching cost. */
|
||||
grp = DRW_shgroup_create_sub(*grp_p);
|
||||
|
||||
/* Per material uniforms. */
|
||||
if (use_ssrefract) {
|
||||
DRW_shgroup_uniform_float_copy(grp, "refractionDepth", ma->refract_depth);
|
||||
}
|
||||
}
|
||||
else {
|
||||
*grp_p = grp = DRW_shgroup_create(sh, shading_pass);
|
||||
|
@ -961,22 +966,9 @@ void EEVEE_material_renderpasses_init(EEVEE_Data *vedata)
|
|||
}
|
||||
}
|
||||
|
||||
static void material_renderpass_init(EEVEE_FramebufferList *fbl,
|
||||
GPUTexture **output_tx,
|
||||
const eGPUTextureFormat format,
|
||||
const bool do_clear)
|
||||
static void material_renderpass_init(GPUTexture **output_tx, const eGPUTextureFormat format)
|
||||
{
|
||||
DRW_texture_ensure_fullscreen_2d(output_tx, format, 0);
|
||||
/* Clear texture. */
|
||||
if (do_clear) {
|
||||
const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
/* TODO(fclem): replace by GPU_texture_clear once it is fast. */
|
||||
GPU_framebuffer_texture_attach(fbl->material_accum_fb, *output_tx, 0, 0);
|
||||
GPU_framebuffer_bind(fbl->material_accum_fb);
|
||||
GPU_framebuffer_clear_color(fbl->material_accum_fb, clear);
|
||||
GPU_framebuffer_bind(fbl->main_fb);
|
||||
GPU_framebuffer_texture_detach(fbl->material_accum_fb, *output_tx);
|
||||
}
|
||||
}
|
||||
|
||||
void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples)
|
||||
|
@ -991,33 +983,32 @@ void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
|
|||
/* Should be enough precision for many samples. */
|
||||
const eGPUTextureFormat texture_format = (tot_samples > 128) ? GPU_RGBA32F : GPU_RGBA16F;
|
||||
|
||||
const bool do_clear = (effects->taa_current_sample == 1);
|
||||
/* Create FrameBuffer. */
|
||||
GPU_framebuffer_ensure_config(&fbl->material_accum_fb,
|
||||
{GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_LEAVE});
|
||||
|
||||
if (pd->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) {
|
||||
material_renderpass_init(fbl, &txl->env_accum, texture_format, do_clear);
|
||||
material_renderpass_init(&txl->env_accum, texture_format);
|
||||
}
|
||||
if (pd->render_passes & EEVEE_RENDER_PASS_EMIT) {
|
||||
material_renderpass_init(fbl, &txl->emit_accum, texture_format, do_clear);
|
||||
material_renderpass_init(&txl->emit_accum, texture_format);
|
||||
}
|
||||
if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_COLOR) {
|
||||
material_renderpass_init(fbl, &txl->diff_color_accum, texture_format, do_clear);
|
||||
material_renderpass_init(&txl->diff_color_accum, texture_format);
|
||||
}
|
||||
if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) {
|
||||
material_renderpass_init(fbl, &txl->diff_light_accum, texture_format, do_clear);
|
||||
material_renderpass_init(&txl->diff_light_accum, texture_format);
|
||||
}
|
||||
if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_COLOR) {
|
||||
material_renderpass_init(fbl, &txl->spec_color_accum, texture_format, do_clear);
|
||||
material_renderpass_init(&txl->spec_color_accum, texture_format);
|
||||
}
|
||||
if (pd->render_passes & EEVEE_RENDER_PASS_AOV) {
|
||||
for (int aov_index = 0; aov_index < pd->num_aovs_used; aov_index++) {
|
||||
material_renderpass_init(fbl, &txl->aov_surface_accum[aov_index], texture_format, do_clear);
|
||||
material_renderpass_init(&txl->aov_surface_accum[aov_index], texture_format);
|
||||
}
|
||||
}
|
||||
if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) {
|
||||
material_renderpass_init(fbl, &txl->spec_light_accum, texture_format, do_clear);
|
||||
material_renderpass_init(&txl->spec_light_accum, texture_format);
|
||||
|
||||
if (effects->enabled_effects & EFFECT_SSR) {
|
||||
EEVEE_reflection_output_init(sldata, vedata, tot_samples);
|
||||
|
@ -1025,7 +1016,8 @@ void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
|
|||
}
|
||||
}
|
||||
|
||||
static void material_renderpass_accumulate(EEVEE_FramebufferList *fbl,
|
||||
static void material_renderpass_accumulate(EEVEE_EffectsInfo *effects,
|
||||
EEVEE_FramebufferList *fbl,
|
||||
DRWPass *renderpass,
|
||||
DRWPass *renderpass2,
|
||||
EEVEE_PrivateData *pd,
|
||||
|
@ -1035,6 +1027,11 @@ static void material_renderpass_accumulate(EEVEE_FramebufferList *fbl,
|
|||
GPU_framebuffer_texture_attach(fbl->material_accum_fb, output_tx, 0, 0);
|
||||
GPU_framebuffer_bind(fbl->material_accum_fb);
|
||||
|
||||
if (effects->taa_current_sample == 1) {
|
||||
const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
GPU_framebuffer_clear_color(fbl->material_accum_fb, clear);
|
||||
}
|
||||
|
||||
pd->renderpass_ubo = renderpass_option_ubo;
|
||||
DRW_draw_pass(renderpass);
|
||||
if (renderpass2) {
|
||||
|
@ -1056,15 +1053,21 @@ void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
|
|||
DRWPass *material_accum_ps = psl->material_accum_ps;
|
||||
DRWPass *background_accum_ps = psl->background_accum_ps;
|
||||
if (pd->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) {
|
||||
material_renderpass_accumulate(
|
||||
fbl, background_accum_ps, NULL, pd, txl->env_accum, sldata->renderpass_ubo.environment);
|
||||
material_renderpass_accumulate(effects,
|
||||
fbl,
|
||||
background_accum_ps,
|
||||
NULL,
|
||||
pd,
|
||||
txl->env_accum,
|
||||
sldata->renderpass_ubo.environment);
|
||||
}
|
||||
if (pd->render_passes & EEVEE_RENDER_PASS_EMIT) {
|
||||
material_renderpass_accumulate(
|
||||
fbl, material_accum_ps, NULL, pd, txl->emit_accum, sldata->renderpass_ubo.emit);
|
||||
effects, fbl, material_accum_ps, NULL, pd, txl->emit_accum, sldata->renderpass_ubo.emit);
|
||||
}
|
||||
if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_COLOR) {
|
||||
material_renderpass_accumulate(fbl,
|
||||
material_renderpass_accumulate(effects,
|
||||
fbl,
|
||||
material_accum_ps,
|
||||
NULL,
|
||||
pd,
|
||||
|
@ -1072,7 +1075,8 @@ void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
|
|||
sldata->renderpass_ubo.diff_color);
|
||||
}
|
||||
if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) {
|
||||
material_renderpass_accumulate(fbl,
|
||||
material_renderpass_accumulate(effects,
|
||||
fbl,
|
||||
material_accum_ps,
|
||||
NULL,
|
||||
pd,
|
||||
|
@ -1090,7 +1094,8 @@ void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
|
|||
sldata->common_data.ssr_toggle = false;
|
||||
GPU_uniformbuf_update(sldata->common_ubo, &sldata->common_data);
|
||||
}
|
||||
material_renderpass_accumulate(fbl,
|
||||
material_renderpass_accumulate(effects,
|
||||
fbl,
|
||||
material_accum_ps,
|
||||
NULL,
|
||||
pd,
|
||||
|
@ -1102,7 +1107,8 @@ void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
|
|||
}
|
||||
}
|
||||
if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) {
|
||||
material_renderpass_accumulate(fbl,
|
||||
material_renderpass_accumulate(effects,
|
||||
fbl,
|
||||
material_accum_ps,
|
||||
NULL,
|
||||
pd,
|
||||
|
@ -1115,7 +1121,8 @@ void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
|
|||
}
|
||||
if (pd->render_passes & EEVEE_RENDER_PASS_AOV) {
|
||||
for (int aov_index = 0; aov_index < pd->num_aovs_used; aov_index++) {
|
||||
material_renderpass_accumulate(fbl,
|
||||
material_renderpass_accumulate(effects,
|
||||
fbl,
|
||||
material_accum_ps,
|
||||
background_accum_ps,
|
||||
pd,
|
||||
|
|
|
@ -40,12 +40,9 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
|
|||
EEVEE_TextureList *txl = vedata->txl;
|
||||
EEVEE_StorageList *stl = vedata->stl;
|
||||
EEVEE_PassList *psl = vedata->psl;
|
||||
EEVEE_EffectsInfo *effects = stl->effects;
|
||||
EEVEE_PrivateData *g_data = stl->g_data;
|
||||
Scene *scene = draw_ctx->scene;
|
||||
|
||||
const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
/* Create FrameBuffer. */
|
||||
/* Should be enough precision for many samples. */
|
||||
DRW_texture_ensure_fullscreen_2d(&txl->mist_accum, GPU_R32F, 0);
|
||||
|
@ -53,12 +50,6 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
|
|||
GPU_framebuffer_ensure_config(&fbl->mist_accum_fb,
|
||||
{GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->mist_accum)});
|
||||
|
||||
/* Clear texture. */
|
||||
if (effects->taa_current_sample == 1) {
|
||||
GPU_framebuffer_bind(fbl->mist_accum_fb);
|
||||
GPU_framebuffer_clear_color(fbl->mist_accum_fb, clear);
|
||||
}
|
||||
|
||||
/* Mist settings. */
|
||||
if (scene && scene->world) {
|
||||
g_data->mist_start = scene->world->miststa;
|
||||
|
@ -103,9 +94,17 @@ void EEVEE_mist_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
|
|||
{
|
||||
EEVEE_FramebufferList *fbl = vedata->fbl;
|
||||
EEVEE_PassList *psl = vedata->psl;
|
||||
EEVEE_EffectsInfo *effects = vedata->stl->effects;
|
||||
|
||||
if (fbl->mist_accum_fb != NULL) {
|
||||
GPU_framebuffer_bind(fbl->mist_accum_fb);
|
||||
|
||||
/* Clear texture. */
|
||||
if (effects->taa_current_sample == 1) {
|
||||
const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
GPU_framebuffer_clear_color(fbl->mist_accum_fb, clear);
|
||||
}
|
||||
|
||||
DRW_draw_pass(psl->mist_accum_ps);
|
||||
|
||||
/* Restore */
|
||||
|
|
|
@ -120,7 +120,6 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata
|
|||
const eGPUTextureFormat texture_format = (tot_samples > 128) ? GPU_R32F : GPU_R16F;
|
||||
|
||||
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
|
||||
const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
/* Should be enough precision for many samples. */
|
||||
DRW_texture_ensure_fullscreen_2d(&txl->ao_accum, texture_format, 0);
|
||||
|
@ -128,12 +127,6 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata
|
|||
GPU_framebuffer_ensure_config(&fbl->ao_accum_fb,
|
||||
{GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->ao_accum)});
|
||||
|
||||
/* Clear texture. */
|
||||
if (effects->taa_current_sample == 1) {
|
||||
GPU_framebuffer_bind(fbl->ao_accum_fb);
|
||||
GPU_framebuffer_clear_color(fbl->ao_accum_fb, clear);
|
||||
}
|
||||
|
||||
/* Accumulation pass */
|
||||
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD;
|
||||
DRW_PASS_CREATE(psl->ao_accum_ps, state);
|
||||
|
@ -246,6 +239,7 @@ void EEVEE_occlusion_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *
|
|||
{
|
||||
EEVEE_FramebufferList *fbl = vedata->fbl;
|
||||
EEVEE_PassList *psl = vedata->psl;
|
||||
EEVEE_EffectsInfo *effects = vedata->stl->effects;
|
||||
|
||||
if (fbl->ao_accum_fb != NULL) {
|
||||
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
|
||||
|
@ -255,6 +249,13 @@ void EEVEE_occlusion_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *
|
|||
EEVEE_occlusion_compute(sldata, vedata);
|
||||
|
||||
GPU_framebuffer_bind(fbl->ao_accum_fb);
|
||||
|
||||
/* Clear texture. */
|
||||
if (effects->taa_current_sample == 1) {
|
||||
const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
GPU_framebuffer_clear_color(fbl->ao_accum_fb, clear);
|
||||
}
|
||||
|
||||
DRW_draw_pass(psl->ao_accum_ps);
|
||||
|
||||
/* Restore */
|
||||
|
|
|
@ -234,10 +234,6 @@ void EEVEE_reflection_output_init(EEVEE_ViewLayerData *UNUSED(sldata),
|
|||
{
|
||||
EEVEE_FramebufferList *fbl = vedata->fbl;
|
||||
EEVEE_TextureList *txl = vedata->txl;
|
||||
EEVEE_StorageList *stl = vedata->stl;
|
||||
EEVEE_EffectsInfo *effects = stl->effects;
|
||||
|
||||
const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
/* Create FrameBuffer. */
|
||||
const eGPUTextureFormat texture_format = (tot_samples > 256) ? GPU_RGBA32F : GPU_RGBA16F;
|
||||
|
@ -245,12 +241,6 @@ void EEVEE_reflection_output_init(EEVEE_ViewLayerData *UNUSED(sldata),
|
|||
|
||||
GPU_framebuffer_ensure_config(&fbl->ssr_accum_fb,
|
||||
{GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->ssr_accum)});
|
||||
|
||||
/* Clear texture. */
|
||||
if (effects->taa_current_sample == 1) {
|
||||
GPU_framebuffer_bind(fbl->ssr_accum_fb);
|
||||
GPU_framebuffer_clear_color(fbl->ssr_accum_fb, clear);
|
||||
}
|
||||
}
|
||||
|
||||
void EEVEE_reflection_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
|
||||
|
@ -258,9 +248,17 @@ void EEVEE_reflection_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEV
|
|||
EEVEE_FramebufferList *fbl = vedata->fbl;
|
||||
EEVEE_PassList *psl = vedata->psl;
|
||||
EEVEE_StorageList *stl = vedata->stl;
|
||||
EEVEE_EffectsInfo *effects = vedata->stl->effects;
|
||||
|
||||
if (stl->g_data->valid_double_buffer) {
|
||||
GPU_framebuffer_bind(fbl->ssr_accum_fb);
|
||||
|
||||
/* Clear texture. */
|
||||
if (effects->taa_current_sample == 1) {
|
||||
const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
GPU_framebuffer_clear_color(fbl->ssr_accum_fb, clear);
|
||||
}
|
||||
|
||||
DRW_draw_pass(psl->ssr_resolve);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -361,12 +361,8 @@ void EEVEE_shadow_output_init(EEVEE_ViewLayerData *sldata,
|
|||
EEVEE_FramebufferList *fbl = vedata->fbl;
|
||||
EEVEE_TextureList *txl = vedata->txl;
|
||||
EEVEE_PassList *psl = vedata->psl;
|
||||
EEVEE_StorageList *stl = vedata->stl;
|
||||
EEVEE_EffectsInfo *effects = stl->effects;
|
||||
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
|
||||
|
||||
const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
/* Create FrameBuffer. */
|
||||
const eGPUTextureFormat texture_format = GPU_R32F;
|
||||
DRW_texture_ensure_fullscreen_2d(&txl->shadow_accum, texture_format, 0);
|
||||
|
@ -374,12 +370,6 @@ void EEVEE_shadow_output_init(EEVEE_ViewLayerData *sldata,
|
|||
GPU_framebuffer_ensure_config(&fbl->shadow_accum_fb,
|
||||
{GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->shadow_accum)});
|
||||
|
||||
/* Clear texture. */
|
||||
if (effects->taa_current_sample == 1) {
|
||||
GPU_framebuffer_bind(fbl->shadow_accum_fb);
|
||||
GPU_framebuffer_clear_color(fbl->shadow_accum_fb, clear);
|
||||
}
|
||||
|
||||
/* Create Pass and shgroup. */
|
||||
DRW_PASS_CREATE(psl->shadow_accum_pass,
|
||||
DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ADD_FULL);
|
||||
|
@ -404,9 +394,17 @@ void EEVEE_shadow_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_D
|
|||
{
|
||||
EEVEE_FramebufferList *fbl = vedata->fbl;
|
||||
EEVEE_PassList *psl = vedata->psl;
|
||||
EEVEE_EffectsInfo *effects = vedata->stl->effects;
|
||||
|
||||
if (fbl->shadow_accum_fb != NULL) {
|
||||
GPU_framebuffer_bind(fbl->shadow_accum_fb);
|
||||
|
||||
/* Clear texture. */
|
||||
if (effects->taa_current_sample == 1) {
|
||||
const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
GPU_framebuffer_clear_color(fbl->shadow_accum_fb, clear);
|
||||
}
|
||||
|
||||
DRW_draw_pass(psl->shadow_accum_pass);
|
||||
|
||||
/* Restore */
|
||||
|
|
|
@ -800,8 +800,6 @@ void EEVEE_volumes_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
|
|||
EEVEE_PassList *psl = vedata->psl;
|
||||
EEVEE_EffectsInfo *effects = stl->effects;
|
||||
|
||||
const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
/* Create FrameBuffer. */
|
||||
|
||||
/* Should be enough precision for many samples. */
|
||||
|
@ -814,12 +812,6 @@ void EEVEE_volumes_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
|
|||
GPU_ATTACHMENT_TEXTURE(txl->volume_scatter_accum),
|
||||
GPU_ATTACHMENT_TEXTURE(txl->volume_transmittance_accum)});
|
||||
|
||||
/* Clear texture. */
|
||||
if (effects->taa_current_sample == 1) {
|
||||
GPU_framebuffer_bind(fbl->volumetric_accum_fb);
|
||||
GPU_framebuffer_clear_color(fbl->volumetric_accum_fb, clear);
|
||||
}
|
||||
|
||||
/* Create Pass and shgroup. */
|
||||
DRW_PASS_CREATE(psl->volumetric_accum_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD_FULL);
|
||||
DRWShadingGroup *grp = NULL;
|
||||
|
@ -843,10 +835,18 @@ void EEVEE_volumes_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_
|
|||
{
|
||||
EEVEE_FramebufferList *fbl = vedata->fbl;
|
||||
EEVEE_PassList *psl = vedata->psl;
|
||||
EEVEE_EffectsInfo *effects = vedata->stl->effects;
|
||||
|
||||
if (fbl->volumetric_accum_fb != NULL) {
|
||||
/* Accum pass */
|
||||
GPU_framebuffer_bind(fbl->volumetric_accum_fb);
|
||||
|
||||
/* Clear texture. */
|
||||
if (effects->taa_current_sample == 1) {
|
||||
const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
GPU_framebuffer_clear_color(fbl->volumetric_accum_fb, clear);
|
||||
}
|
||||
|
||||
DRW_draw_pass(psl->volumetric_accum_ps);
|
||||
|
||||
/* Restore */
|
||||
|
|
|
@ -183,16 +183,70 @@ vec3 light_translucent(LightData ld, vec3 P, vec3 N, vec4 l_vector, vec2 rand, f
|
|||
#undef scube
|
||||
#undef scsmd
|
||||
|
||||
/* Similar to https://atyuwen.github.io/posts/normal-reconstruction/.
|
||||
* This samples the depth buffer 4 time for each direction to get the most correct
|
||||
* implicit normal reconstruction out of the depth buffer. */
|
||||
vec3 view_position_derivative_from_depth(vec2 uvs, vec2 ofs, vec3 vP, float depth_center)
|
||||
{
|
||||
vec2 uv1 = uvs - ofs * 2.0;
|
||||
vec2 uv2 = uvs - ofs;
|
||||
vec2 uv3 = uvs + ofs;
|
||||
vec2 uv4 = uvs + ofs * 2.0;
|
||||
vec4 H;
|
||||
H.x = textureLod(depthBuffer, uv1, 0.0).r;
|
||||
H.y = textureLod(depthBuffer, uv2, 0.0).r;
|
||||
H.z = textureLod(depthBuffer, uv3, 0.0).r;
|
||||
H.w = textureLod(depthBuffer, uv4, 0.0).r;
|
||||
/* Fix issue with depth precision. Take even larger diff. */
|
||||
vec4 diff = abs(vec4(depth_center, H.yzw) - H.x);
|
||||
if (max_v4(diff) < 2.4e-7 && all(lessThan(diff.xyz, diff.www))) {
|
||||
return 0.25 * (get_view_space_from_depth(uv3, H.w) - get_view_space_from_depth(uv1, H.x));
|
||||
}
|
||||
/* Simplified (H.xw + 2.0 * (H.yz - H.xw)) - depth_center */
|
||||
vec2 deltas = abs((2.0 * H.yz - H.xw) - depth_center);
|
||||
if (deltas.x < deltas.y) {
|
||||
return vP - get_view_space_from_depth(uv2, H.y);
|
||||
}
|
||||
else {
|
||||
return get_view_space_from_depth(uv3, H.z) - vP;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO(fclem) port to a common place for other effects to use. */
|
||||
bool reconstruct_view_position_and_normal_from_depth(vec2 uvs, out vec3 vP, out vec3 vNg)
|
||||
{
|
||||
vec2 texel_size = vec2(abs(dFdx(uvs.x)), abs(dFdy(uvs.y)));
|
||||
float depth_center = textureLod(depthBuffer, uvs, 0.0).r;
|
||||
|
||||
vP = get_view_space_from_depth(uvs, depth_center);
|
||||
|
||||
vec3 dPdx = view_position_derivative_from_depth(uvs, texel_size * vec2(1, 0), vP, depth_center);
|
||||
vec3 dPdy = view_position_derivative_from_depth(uvs, texel_size * vec2(0, 1), vP, depth_center);
|
||||
|
||||
vNg = safe_normalize(cross(dPdx, dPdy));
|
||||
|
||||
/* Background case. */
|
||||
if (depth_center == 1.0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec2 uvs = uvcoordsvar.xy;
|
||||
float sss_scale = texture(sssRadius, uvs).r;
|
||||
vec3 P = get_world_space_from_depth(uvs, texture(depthBuffer, uvs).r);
|
||||
vec3 N = normalize(cross(dFdx(P), dFdy(P)));
|
||||
|
||||
vec3 rand = texelfetch_noise_tex(gl_FragCoord.xy).zwy;
|
||||
rand.xy *= fast_sqrt(rand.z);
|
||||
|
||||
vec3 vP, vNg;
|
||||
reconstruct_view_position_and_normal_from_depth(uvs, vP, vNg);
|
||||
|
||||
vec3 P = point_view_to_world(vP);
|
||||
vec3 Ng = normal_view_to_world(vNg);
|
||||
|
||||
vec3 accum = vec3(0.0);
|
||||
for (int i = 0; i < MAX_LIGHT && i < laNumLight; i++) {
|
||||
LightData ld = lights_data[i];
|
||||
|
@ -211,7 +265,7 @@ void main(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
accum += att * ld.l_color * light_translucent(ld, P, -N, l_vector, rand.xy, sss_scale);
|
||||
accum += att * ld.l_color * light_translucent(ld, P, -Ng, l_vector, rand.xy, sss_scale);
|
||||
}
|
||||
|
||||
FragColor = vec4(accum, 1.0);
|
||||
|
|
|
@ -1031,7 +1031,7 @@ static void pchan_draw_data_init(bPoseChannel *pchan)
|
|||
static void draw_bone_update_disp_matrix_default(EditBone *eBone, bPoseChannel *pchan)
|
||||
{
|
||||
float ebmat[4][4];
|
||||
float length;
|
||||
float bone_scale[3];
|
||||
float(*bone_mat)[4];
|
||||
float(*disp_mat)[4];
|
||||
float(*disp_tail_mat)[4];
|
||||
|
@ -1040,23 +1040,23 @@ static void draw_bone_update_disp_matrix_default(EditBone *eBone, bPoseChannel *
|
|||
* and not be tight to the draw pass creation.
|
||||
* This would refresh armature without invalidating the draw cache */
|
||||
if (pchan) {
|
||||
length = pchan->bone->length;
|
||||
bone_mat = pchan->pose_mat;
|
||||
disp_mat = pchan->disp_mat;
|
||||
disp_tail_mat = pchan->disp_tail_mat;
|
||||
mul_v3_v3fl(bone_scale, pchan->custom_scale_xyz, pchan->bone->length);
|
||||
}
|
||||
else {
|
||||
eBone->length = len_v3v3(eBone->tail, eBone->head);
|
||||
ED_armature_ebone_to_mat4(eBone, ebmat);
|
||||
|
||||
length = eBone->length;
|
||||
copy_v3_fl(bone_scale, eBone->length);
|
||||
bone_mat = ebmat;
|
||||
disp_mat = eBone->disp_mat;
|
||||
disp_tail_mat = eBone->disp_tail_mat;
|
||||
}
|
||||
|
||||
copy_m4_m4(disp_mat, bone_mat);
|
||||
rescale_m4(disp_mat, (float[3]){length, length, length});
|
||||
rescale_m4(disp_mat, bone_scale);
|
||||
copy_m4_m4(disp_tail_mat, disp_mat);
|
||||
translate_m4(disp_tail_mat, 0.0f, 1.0f, 0.0f);
|
||||
}
|
||||
|
@ -1255,19 +1255,27 @@ static void draw_bone_update_disp_matrix_bbone(EditBone *eBone, bPoseChannel *pc
|
|||
|
||||
static void draw_bone_update_disp_matrix_custom(bPoseChannel *pchan)
|
||||
{
|
||||
float length;
|
||||
float bone_scale[3];
|
||||
float(*bone_mat)[4];
|
||||
float(*disp_mat)[4];
|
||||
float(*disp_tail_mat)[4];
|
||||
float rot_mat[3][3];
|
||||
|
||||
/* See TODO above */
|
||||
length = PCHAN_CUSTOM_DRAW_SIZE(pchan);
|
||||
mul_v3_v3fl(bone_scale, pchan->custom_scale_xyz, PCHAN_CUSTOM_BONE_LENGTH(pchan));
|
||||
bone_mat = pchan->custom_tx ? pchan->custom_tx->pose_mat : pchan->pose_mat;
|
||||
disp_mat = pchan->disp_mat;
|
||||
disp_tail_mat = pchan->disp_tail_mat;
|
||||
|
||||
eulO_to_mat3(rot_mat, pchan->custom_rotation_euler, ROT_MODE_XYZ);
|
||||
|
||||
copy_m4_m4(disp_mat, bone_mat);
|
||||
rescale_m4(disp_mat, (float[3]){length, length, length});
|
||||
translate_m4(disp_mat,
|
||||
pchan->custom_translation[0],
|
||||
pchan->custom_translation[1],
|
||||
pchan->custom_translation[2]);
|
||||
mul_m4_m4m3(disp_mat, disp_mat, rot_mat);
|
||||
rescale_m4(disp_mat, bone_scale);
|
||||
copy_m4_m4(disp_tail_mat, disp_mat);
|
||||
translate_m4(disp_tail_mat, 0.0f, 1.0f, 0.0f);
|
||||
}
|
||||
|
|
|
@ -285,10 +285,6 @@ static bool overlay_should_fade_object(Object *ob, Object *active_object)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (ob->base_flag & BASE_FROM_DUPLI) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -557,6 +557,7 @@ static int gpencil_layer_duplicate_object_exec(bContext *C, wmOperator *op)
|
|||
if (name[0] == '\0') {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
const bool only_active = RNA_boolean_get(op->ptr, "only_active");
|
||||
|
||||
Object *ob_dst = (Object *)BKE_scene_object_find_by_name(scene, name);
|
||||
|
||||
|
@ -564,10 +565,10 @@ static int gpencil_layer_duplicate_object_exec(bContext *C, wmOperator *op)
|
|||
|
||||
Object *ob_src = CTX_data_active_object(C);
|
||||
bGPdata *gpd_src = (bGPdata *)ob_src->data;
|
||||
bGPDlayer *gpl_src = BKE_gpencil_layer_active_get(gpd_src);
|
||||
bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd_src);
|
||||
|
||||
/* Sanity checks. */
|
||||
if (ELEM(NULL, gpd_src, gpl_src, ob_dst)) {
|
||||
if (ELEM(NULL, gpd_src, ob_dst)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
/* Cannot copy itself and check destination type. */
|
||||
|
@ -576,47 +577,55 @@ static int gpencil_layer_duplicate_object_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
|
||||
bGPdata *gpd_dst = (bGPdata *)ob_dst->data;
|
||||
|
||||
/* Create new layer. */
|
||||
bGPDlayer *gpl_dst = BKE_gpencil_layer_addnew(gpd_dst, gpl_src->info, true);
|
||||
/* Need to copy some variables (not all). */
|
||||
gpl_dst->onion_flag = gpl_src->onion_flag;
|
||||
gpl_dst->thickness = gpl_src->thickness;
|
||||
gpl_dst->line_change = gpl_src->line_change;
|
||||
copy_v4_v4(gpl_dst->tintcolor, gpl_src->tintcolor);
|
||||
gpl_dst->opacity = gpl_src->opacity;
|
||||
|
||||
/* Create all frames. */
|
||||
LISTBASE_FOREACH (bGPDframe *, gpf_src, &gpl_src->frames) {
|
||||
|
||||
if ((mode == GP_LAYER_COPY_OBJECT_ACT_FRAME) && (gpf_src != gpl_src->actframe)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Create new frame. */
|
||||
bGPDframe *gpf_dst = BKE_gpencil_frame_addnew(gpl_dst, gpf_src->framenum);
|
||||
|
||||
/* Copy strokes. */
|
||||
LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) {
|
||||
|
||||
/* Make copy of source stroke. */
|
||||
bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true, true);
|
||||
|
||||
/* Check if material is in destination object,
|
||||
* otherwise add the slot with the material. */
|
||||
Material *ma_src = BKE_object_material_get(ob_src, gps_src->mat_nr + 1);
|
||||
if (ma_src != NULL) {
|
||||
int idx = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma_src);
|
||||
|
||||
/* Reassign the stroke material to the right slot in destination object. */
|
||||
gps_dst->mat_nr = idx;
|
||||
}
|
||||
|
||||
/* Add new stroke to frame. */
|
||||
BLI_addtail(&gpf_dst->strokes, gps_dst);
|
||||
}
|
||||
/* Disable destination active layer to keep order. */
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_dst->layers) {
|
||||
gpl->flag &= ~GP_LAYER_ACTIVE;
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd_src->layers) {
|
||||
if ((only_active) && (gpl_src != gpl_active)) {
|
||||
continue;
|
||||
}
|
||||
/* Create new layer. */
|
||||
bGPDlayer *gpl_dst = BKE_gpencil_layer_addnew(gpd_dst, gpl_src->info, true);
|
||||
/* Need to copy some variables (not all). */
|
||||
gpl_dst->onion_flag = gpl_src->onion_flag;
|
||||
gpl_dst->thickness = gpl_src->thickness;
|
||||
gpl_dst->line_change = gpl_src->line_change;
|
||||
copy_v4_v4(gpl_dst->tintcolor, gpl_src->tintcolor);
|
||||
gpl_dst->opacity = gpl_src->opacity;
|
||||
|
||||
/* Create all frames. */
|
||||
LISTBASE_FOREACH (bGPDframe *, gpf_src, &gpl_src->frames) {
|
||||
|
||||
if ((mode == GP_LAYER_COPY_OBJECT_ACT_FRAME) && (gpf_src != gpl_src->actframe)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Create new frame. */
|
||||
bGPDframe *gpf_dst = BKE_gpencil_frame_addnew(gpl_dst, gpf_src->framenum);
|
||||
|
||||
/* Copy strokes. */
|
||||
LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) {
|
||||
|
||||
/* Make copy of source stroke. */
|
||||
bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true, true);
|
||||
|
||||
/* Check if material is in destination object,
|
||||
* otherwise add the slot with the material. */
|
||||
Material *ma_src = BKE_object_material_get(ob_src, gps_src->mat_nr + 1);
|
||||
if (ma_src != NULL) {
|
||||
int idx = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma_src);
|
||||
|
||||
/* Reassign the stroke material to the right slot in destination object. */
|
||||
gps_dst->mat_nr = idx;
|
||||
}
|
||||
|
||||
/* Add new stroke to frame. */
|
||||
BLI_addtail(&gpf_dst->strokes, gps_dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* notifiers */
|
||||
DEG_id_tag_update(&gpd_dst->id,
|
||||
ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
|
||||
|
@ -628,6 +637,8 @@ static int gpencil_layer_duplicate_object_exec(bContext *C, wmOperator *op)
|
|||
|
||||
void GPENCIL_OT_layer_duplicate_object(wmOperatorType *ot)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
static const EnumPropertyItem copy_mode[] = {
|
||||
{GP_LAYER_COPY_OBJECT_ALL_FRAME, "ALL", 0, "All Frames", ""},
|
||||
{GP_LAYER_COPY_OBJECT_ACT_FRAME, "ACTIVE", 0, "Active Frame", ""},
|
||||
|
@ -651,6 +662,13 @@ void GPENCIL_OT_layer_duplicate_object(wmOperatorType *ot)
|
|||
RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
||||
|
||||
RNA_def_enum(ot->srna, "mode", copy_mode, GP_LAYER_COPY_OBJECT_ALL_FRAME, "Mode", "");
|
||||
|
||||
prop = RNA_def_boolean(ot->srna,
|
||||
"only_active",
|
||||
true,
|
||||
"Only Active",
|
||||
"Append only active Layer, uncheck to append all layers");
|
||||
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
||||
}
|
||||
|
||||
/* ********************* Duplicate Frame ************************** */
|
||||
|
@ -3589,6 +3607,101 @@ void GPENCIL_OT_set_active_material(wmOperatorType *ot)
|
|||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ********************* Append Materials in a new object ************************** */
|
||||
static bool gpencil_materials_append_to_object_poll(bContext *C)
|
||||
{
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
|
||||
return false;
|
||||
}
|
||||
short *totcolp = BKE_object_material_len_p(ob);
|
||||
if (*totcolp == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* check there are more grease pencil objects */
|
||||
LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
|
||||
if ((base->object != ob) && (base->object->type == OB_GPENCIL)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int gpencil_materials_append_to_object_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
char name[MAX_ID_NAME - 2];
|
||||
RNA_string_get(op->ptr, "object", name);
|
||||
|
||||
if (name[0] == '\0') {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
const bool only_selected = RNA_boolean_get(op->ptr, "only_selected");
|
||||
|
||||
Object *ob_dst = (Object *)BKE_scene_object_find_by_name(scene, name);
|
||||
Object *ob_src = CTX_data_active_object(C);
|
||||
Material *ma_active = BKE_gpencil_material(ob_src, ob_src->actcol);
|
||||
|
||||
/* Sanity checks. */
|
||||
if (ELEM(NULL, ob_src, ob_dst)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
/* Cannot copy itself and check destination type. */
|
||||
if ((ob_src == ob_dst) || (ob_dst->type != OB_GPENCIL)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* Duplicate materials. */
|
||||
for (int i = 0; i < ob_src->totcol; i++) {
|
||||
Material *ma_src = BKE_object_material_get(ob_src, i + 1);
|
||||
if (only_selected && ma_src != ma_active) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ma_src != NULL) {
|
||||
BKE_gpencil_object_material_ensure(bmain, ob_dst, ma_src);
|
||||
}
|
||||
}
|
||||
|
||||
/* notifiers */
|
||||
DEG_id_tag_update(&ob_dst->id, ID_RECALC_COPY_ON_WRITE);
|
||||
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GPENCIL_OT_materials_append_to_object(wmOperatorType *ot)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* identifiers */
|
||||
ot->name = "Append Materials to New Object";
|
||||
ot->idname = "GPENCIL_OT_materials_append_to_object";
|
||||
ot->description = "Append Materials of the active Grease Pencil to other object";
|
||||
|
||||
/* callbacks */
|
||||
ot->exec = gpencil_materials_append_to_object_exec;
|
||||
ot->poll = gpencil_materials_append_to_object_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
ot->prop = RNA_def_string(
|
||||
ot->srna, "object", NULL, MAX_ID_NAME - 2, "Object", "Name of the destination object");
|
||||
RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
||||
|
||||
prop = RNA_def_boolean(ot->srna,
|
||||
"only_selected",
|
||||
true,
|
||||
"Only Selected",
|
||||
"Append only selected material, uncheck to append all materials");
|
||||
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
||||
}
|
||||
|
||||
/* Parent GPencil object to Lattice */
|
||||
bool ED_gpencil_add_lattice_modifier(const bContext *C,
|
||||
ReportList *reports,
|
||||
|
|
|
@ -538,6 +538,7 @@ void GPENCIL_OT_material_lock_unused(struct wmOperatorType *ot);
|
|||
void GPENCIL_OT_material_select(struct wmOperatorType *ot);
|
||||
void GPENCIL_OT_material_set(struct wmOperatorType *ot);
|
||||
void GPENCIL_OT_set_active_material(struct wmOperatorType *ot);
|
||||
void GPENCIL_OT_materials_append_to_object(struct wmOperatorType *ot);
|
||||
|
||||
/* convert old 2.7 files to 2.8 */
|
||||
void GPENCIL_OT_convert_old_files(struct wmOperatorType *ot);
|
||||
|
|
|
@ -651,6 +651,7 @@ void ED_operatortypes_gpencil(void)
|
|||
|
||||
WM_operatortype_append(GPENCIL_OT_material_to_vertex_color);
|
||||
WM_operatortype_append(GPENCIL_OT_extract_palette_vertex);
|
||||
WM_operatortype_append(GPENCIL_OT_materials_append_to_object);
|
||||
|
||||
WM_operatortype_append(GPENCIL_OT_transform_fill);
|
||||
WM_operatortype_append(GPENCIL_OT_reset_transform_fill);
|
||||
|
|
|
@ -3677,14 +3677,6 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
* is essential for ensuring that they can quickly return to that view
|
||||
*/
|
||||
}
|
||||
else if ((event->type == EVT_BKEY) && (event->val == KM_RELEASE)) {
|
||||
/* Add Blank Frame
|
||||
* - Since this operator is non-modal, we can just call it here, and keep going...
|
||||
* - This operator is especially useful when animating
|
||||
*/
|
||||
WM_operator_name_call(C, "GPENCIL_OT_blank_frame_add", WM_OP_EXEC_DEFAULT, NULL);
|
||||
estate = OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
else if ((!ELEM(p->paintmode, GP_PAINTMODE_ERASER, GP_PAINTMODE_SET_CP))) {
|
||||
gpencil_guide_event_handling(C, op, event, p);
|
||||
estate = OPERATOR_RUNNING_MODAL;
|
||||
|
|
|
@ -247,6 +247,7 @@ void ED_object_texture_paint_mode_enter(struct bContext *C);
|
|||
void ED_object_texture_paint_mode_exit_ex(struct Main *bmain, struct Scene *scene, Object *ob);
|
||||
void ED_object_texture_paint_mode_exit(struct bContext *C);
|
||||
|
||||
bool ED_object_particle_edit_mode_supported(const Object *ob);
|
||||
void ED_object_particle_edit_mode_enter_ex(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
Object *ob);
|
||||
|
|
|
@ -477,6 +477,7 @@ static bool ui_do_but_extra_operator_icon(bContext *C,
|
|||
static void ui_do_but_extra_operator_icons_mousemove(uiBut *but,
|
||||
uiHandleButtonData *data,
|
||||
const wmEvent *event);
|
||||
static void ui_numedit_begin_set_values(uiBut *but, uiHandleButtonData *data);
|
||||
|
||||
#ifdef USE_DRAG_MULTINUM
|
||||
static void ui_multibut_restore(bContext *C, uiHandleButtonData *data, uiBlock *block);
|
||||
|
@ -3361,6 +3362,8 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
|
|||
if (is_num_but) {
|
||||
BLI_assert(data->is_str_dynamic == false);
|
||||
ui_but_convert_to_unit_alt_name(but, data->str, data->maxlen);
|
||||
|
||||
ui_numedit_begin_set_values(but, data);
|
||||
}
|
||||
|
||||
/* won't change from now on */
|
||||
|
@ -3897,6 +3900,14 @@ static void ui_do_but_textedit_select(
|
|||
/** \name Button Number Editing (various types)
|
||||
* \{ */
|
||||
|
||||
static void ui_numedit_begin_set_values(uiBut *but, uiHandleButtonData *data)
|
||||
{
|
||||
data->startvalue = ui_but_value_get(but);
|
||||
data->origvalue = data->startvalue;
|
||||
data->value = data->origvalue;
|
||||
but->editval = &data->value;
|
||||
}
|
||||
|
||||
static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data)
|
||||
{
|
||||
if (but->type == UI_BTYPE_CURVE) {
|
||||
|
@ -3922,16 +3933,11 @@ static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data)
|
|||
but->editvec = data->vec;
|
||||
}
|
||||
else {
|
||||
float softrange, softmin, softmax;
|
||||
ui_numedit_begin_set_values(but, data);
|
||||
|
||||
data->startvalue = ui_but_value_get(but);
|
||||
data->origvalue = data->startvalue;
|
||||
data->value = data->origvalue;
|
||||
but->editval = &data->value;
|
||||
|
||||
softmin = but->softmin;
|
||||
softmax = but->softmax;
|
||||
softrange = softmax - softmin;
|
||||
float softmin = but->softmin;
|
||||
float softmax = but->softmax;
|
||||
float softrange = softmax - softmin;
|
||||
|
||||
if ((but->type == UI_BTYPE_NUM) && (ui_but_is_cursor_warp(but) == false)) {
|
||||
uiButNumber *number_but = (uiButNumber *)but;
|
||||
|
|
|
@ -2547,6 +2547,7 @@ bool EDBM_selectmode_set_multi(bContext *C, const short selectmode)
|
|||
changed = true;
|
||||
}
|
||||
}
|
||||
MEM_freeN(objects);
|
||||
|
||||
if (changed) {
|
||||
WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
|
||||
|
|
|
@ -860,8 +860,9 @@ static int effector_add_exec(bContext *C, wmOperator *op)
|
|||
|
||||
float mat[4][4];
|
||||
ED_object_new_primitive_matrix(C, ob, loc, rot, mat);
|
||||
mul_mat3_m4_fl(mat, dia);
|
||||
BLI_addtail(&cu->editnurb->nurbs,
|
||||
ED_curve_add_nurbs_primitive(C, ob, mat, CU_NURBS | CU_PRIM_PATH, dia));
|
||||
ED_curve_add_nurbs_primitive(C, ob, mat, CU_NURBS | CU_PRIM_PATH, 1));
|
||||
if (!enter_editmode) {
|
||||
ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
|
||||
}
|
||||
|
@ -1310,6 +1311,8 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op)
|
|||
bGPdata *gpd = (ob && (ob->type == OB_GPENCIL)) ? ob->data : NULL;
|
||||
|
||||
const int type = RNA_enum_get(op->ptr, "type");
|
||||
const bool use_in_front = RNA_boolean_get(op->ptr, "use_in_front");
|
||||
const int stroke_depth_order = RNA_enum_get(op->ptr, "stroke_depth_order");
|
||||
|
||||
ushort local_view_bits;
|
||||
float loc[3], rot[3];
|
||||
|
@ -1337,6 +1340,7 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op)
|
|||
break;
|
||||
}
|
||||
case GP_LRT_OBJECT:
|
||||
case GP_LRT_SCENE:
|
||||
case GP_LRT_COLLECTION: {
|
||||
ob_name = "Line Art";
|
||||
break;
|
||||
|
@ -1429,7 +1433,15 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
|
||||
/* Stroke object is drawn in front of meshes by default. */
|
||||
ob->dtx |= OB_DRAW_IN_FRONT;
|
||||
if (use_in_front) {
|
||||
ob->dtx |= OB_DRAW_IN_FRONT;
|
||||
}
|
||||
else {
|
||||
if (stroke_depth_order == GP_DRAWMODE_3D) {
|
||||
gpd->draw_mode = GP_DRAWMODE_3D;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -1448,6 +1460,38 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void object_add_ui(bContext *UNUSED(C), wmOperator *op)
|
||||
{
|
||||
uiLayout *layout = op->layout;
|
||||
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
|
||||
uiItemR(layout, op->ptr, "radius", 0, NULL, ICON_NONE);
|
||||
uiItemR(layout, op->ptr, "align", 0, NULL, ICON_NONE);
|
||||
uiItemR(layout, op->ptr, "location", 0, NULL, ICON_NONE);
|
||||
uiItemR(layout, op->ptr, "rotation", 0, NULL, ICON_NONE);
|
||||
uiItemR(layout, op->ptr, "type", 0, NULL, ICON_NONE);
|
||||
|
||||
int type = RNA_enum_get(op->ptr, "type");
|
||||
if (type == GP_LRT_COLLECTION || type == GP_LRT_OBJECT || type == GP_LRT_SCENE) {
|
||||
uiItemR(layout, op->ptr, "use_in_front", 0, NULL, ICON_NONE);
|
||||
bool in_front = RNA_boolean_get(op->ptr, "use_in_front");
|
||||
uiLayout *row = uiLayoutRow(layout, false);
|
||||
uiLayoutSetActive(row, !in_front);
|
||||
uiItemR(row, op->ptr, "stroke_depth_order", 0, NULL, ICON_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
static EnumPropertyItem rna_enum_gpencil_add_stroke_depth_order_items[] = {
|
||||
{GP_DRAWMODE_2D,
|
||||
"2D",
|
||||
0,
|
||||
"2D Layers",
|
||||
"Display strokes using grease pencil layers to define order"},
|
||||
{GP_DRAWMODE_3D, "3D", 0, "3D Location", "Display strokes using real 3D position in 3D space"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
void OBJECT_OT_gpencil_add(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
|
@ -1463,11 +1507,26 @@ void OBJECT_OT_gpencil_add(wmOperatorType *ot)
|
|||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
/* ui */
|
||||
ot->ui = object_add_ui;
|
||||
|
||||
/* properties */
|
||||
ED_object_add_unit_props_radius(ot);
|
||||
ED_object_add_generic_props(ot, false);
|
||||
|
||||
ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_gpencil_type_items, 0, "Type", "");
|
||||
RNA_def_boolean(ot->srna,
|
||||
"use_in_front",
|
||||
false,
|
||||
"In Front",
|
||||
"Show line art grease pencil in front of everything");
|
||||
RNA_def_enum(
|
||||
ot->srna,
|
||||
"stroke_depth_order",
|
||||
rna_enum_gpencil_add_stroke_depth_order_items,
|
||||
GP_DRAWMODE_3D,
|
||||
"Stroke Depth Order",
|
||||
"Defines how the strokes are ordered in 3D space for objects not displayed 'In Front'");
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -1590,30 +1590,10 @@ static const EnumPropertyItem *object_mode_set_itemsf(bContext *C,
|
|||
return rna_enum_object_mode_items;
|
||||
}
|
||||
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
const Object *ob = CTX_data_active_object(C);
|
||||
if (ob) {
|
||||
const bool use_mode_particle_edit = (BLI_listbase_is_empty(&ob->particlesystem) == false) ||
|
||||
(ob->soft != NULL) ||
|
||||
(BKE_modifiers_findby_type(ob, eModifierType_Cloth) !=
|
||||
NULL);
|
||||
while (input->identifier) {
|
||||
if ((input->value == OB_MODE_EDIT && OB_TYPE_SUPPORT_EDITMODE(ob->type)) ||
|
||||
(input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) ||
|
||||
(input->value == OB_MODE_PARTICLE_EDIT && use_mode_particle_edit) ||
|
||||
(ELEM(input->value,
|
||||
OB_MODE_SCULPT,
|
||||
OB_MODE_VERTEX_PAINT,
|
||||
OB_MODE_WEIGHT_PAINT,
|
||||
OB_MODE_TEXTURE_PAINT) &&
|
||||
(ob->type == OB_MESH)) ||
|
||||
(ELEM(input->value,
|
||||
OB_MODE_EDIT_GPENCIL,
|
||||
OB_MODE_PAINT_GPENCIL,
|
||||
OB_MODE_SCULPT_GPENCIL,
|
||||
OB_MODE_WEIGHT_GPENCIL,
|
||||
OB_MODE_VERTEX_GPENCIL) &&
|
||||
(ob->type == OB_GPENCIL)) ||
|
||||
(input->value == OB_MODE_OBJECT)) {
|
||||
if (ED_object_mode_compat_test(ob, input->value)) {
|
||||
RNA_enum_item_add(&item, &totitem, input);
|
||||
}
|
||||
input++;
|
||||
|
|
|
@ -115,43 +115,46 @@ static const char *object_mode_op_string(eObjectMode mode)
|
|||
*/
|
||||
bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode)
|
||||
{
|
||||
if (ob) {
|
||||
if (mode == OB_MODE_OBJECT) {
|
||||
return true;
|
||||
}
|
||||
if (mode == OB_MODE_OBJECT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (ob->type) {
|
||||
case OB_MESH:
|
||||
if (mode & (OB_MODE_EDIT | OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT |
|
||||
OB_MODE_TEXTURE_PAINT | OB_MODE_PARTICLE_EDIT)) {
|
||||
switch (ob->type) {
|
||||
case OB_MESH:
|
||||
if (mode & (OB_MODE_EDIT | OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT |
|
||||
OB_MODE_TEXTURE_PAINT)) {
|
||||
return true;
|
||||
}
|
||||
if (mode & OB_MODE_PARTICLE_EDIT) {
|
||||
if (ED_object_particle_edit_mode_supported(ob)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case OB_CURVE:
|
||||
case OB_SURF:
|
||||
case OB_FONT:
|
||||
case OB_MBALL:
|
||||
if (mode & OB_MODE_EDIT) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case OB_LATTICE:
|
||||
if (mode & (OB_MODE_EDIT | OB_MODE_WEIGHT_PAINT)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case OB_ARMATURE:
|
||||
if (mode & (OB_MODE_EDIT | OB_MODE_POSE)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case OB_GPENCIL:
|
||||
if (mode & (OB_MODE_EDIT | OB_MODE_EDIT_GPENCIL | OB_MODE_PAINT_GPENCIL |
|
||||
OB_MODE_SCULPT_GPENCIL | OB_MODE_WEIGHT_GPENCIL | OB_MODE_VERTEX_GPENCIL)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OB_CURVE:
|
||||
case OB_SURF:
|
||||
case OB_FONT:
|
||||
case OB_MBALL:
|
||||
if (mode & OB_MODE_EDIT) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case OB_LATTICE:
|
||||
if (mode & (OB_MODE_EDIT | OB_MODE_WEIGHT_PAINT)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case OB_ARMATURE:
|
||||
if (mode & (OB_MODE_EDIT | OB_MODE_POSE)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case OB_GPENCIL:
|
||||
if (mode & (OB_MODE_EDIT_GPENCIL | OB_MODE_PAINT_GPENCIL | OB_MODE_SCULPT_GPENCIL |
|
||||
OB_MODE_WEIGHT_GPENCIL | OB_MODE_VERTEX_GPENCIL)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -210,7 +210,7 @@ ModifierData *ED_object_modifier_add(
|
|||
/* special cases */
|
||||
if (type == eModifierType_Softbody) {
|
||||
if (!ob->soft) {
|
||||
ob->soft = sbNew(scene);
|
||||
ob->soft = sbNew();
|
||||
ob->softflag |= OB_SB_GOAL | OB_SB_EDGES;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5375,8 +5375,7 @@ static bool particle_edit_toggle_poll(bContext *C)
|
|||
return 0;
|
||||
}
|
||||
|
||||
return (ob->particlesystem.first || BKE_modifiers_findby_type(ob, eModifierType_Cloth) ||
|
||||
BKE_modifiers_findby_type(ob, eModifierType_Softbody));
|
||||
return ED_object_particle_edit_mode_supported(ob);
|
||||
}
|
||||
|
||||
static void free_all_psys_edit(Object *object)
|
||||
|
@ -5391,6 +5390,12 @@ static void free_all_psys_edit(Object *object)
|
|||
}
|
||||
}
|
||||
|
||||
bool ED_object_particle_edit_mode_supported(const Object *ob)
|
||||
{
|
||||
return (ob->particlesystem.first || BKE_modifiers_findby_type(ob, eModifierType_Cloth) ||
|
||||
BKE_modifiers_findby_type(ob, eModifierType_Softbody));
|
||||
}
|
||||
|
||||
void ED_object_particle_edit_mode_enter_ex(Depsgraph *depsgraph, Scene *scene, Object *ob)
|
||||
{
|
||||
/* Needed so #ParticleSystemModifierData.mesh_final is set. */
|
||||
|
|
|
@ -139,13 +139,14 @@ static int brush_scale_size_exec(bContext *C, wmOperator *op)
|
|||
Scene *scene = CTX_data_scene(C);
|
||||
Paint *paint = BKE_paint_get_active_from_context(C);
|
||||
Brush *brush = BKE_paint_brush(paint);
|
||||
const bool is_gpencil = (brush && brush->gpencil_settings != NULL);
|
||||
// Object *ob = CTX_data_active_object(C);
|
||||
float scalar = RNA_float_get(op->ptr, "scalar");
|
||||
|
||||
if (brush) {
|
||||
/* pixel radius */
|
||||
{
|
||||
const int old_size = BKE_brush_size_get(scene, brush);
|
||||
const int old_size = (!is_gpencil) ? BKE_brush_size_get(scene, brush) : brush->size;
|
||||
int size = (int)(scalar * old_size);
|
||||
|
||||
if (abs(old_size - size) < U.pixelsize) {
|
||||
|
@ -156,6 +157,12 @@ static int brush_scale_size_exec(bContext *C, wmOperator *op)
|
|||
size -= U.pixelsize;
|
||||
}
|
||||
}
|
||||
/* Grease Pencil does not use unified size. */
|
||||
if (is_gpencil) {
|
||||
brush->size = max_ii(size, 1);
|
||||
WM_main_add_notifier(NC_BRUSH | NA_EDITED, brush);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
BKE_brush_size_set(scene, brush, size);
|
||||
}
|
||||
|
|
|
@ -1931,13 +1931,22 @@ static int sculpt_expand_modal(bContext *C, wmOperator *op, const wmEvent *event
|
|||
* The faces that were using the `delete_id` Face Set are filled
|
||||
* using the content from their neighbors.
|
||||
*/
|
||||
static void sculpt_expand_delete_face_set_id(
|
||||
int *r_face_sets, Mesh *mesh, MeshElemMap *pmap, const int totface, const int delete_id)
|
||||
static void sculpt_expand_delete_face_set_id(int *r_face_sets,
|
||||
SculptSession *ss,
|
||||
ExpandCache *expand_cache,
|
||||
Mesh *mesh,
|
||||
const int delete_id)
|
||||
{
|
||||
const int totface = ss->totvert;
|
||||
MeshElemMap *pmap = ss->pmap;
|
||||
|
||||
/* Check that all the face sets IDs in the mesh are not equal to `delete_id`
|
||||
* before attempting to delete it. */
|
||||
bool all_same_id = true;
|
||||
for (int i = 0; i < totface; i++) {
|
||||
if (!sculpt_expand_is_face_in_active_component(ss, expand_cache, i)) {
|
||||
continue;
|
||||
}
|
||||
if (r_face_sets[i] != delete_id) {
|
||||
all_same_id = false;
|
||||
break;
|
||||
|
@ -2109,9 +2118,9 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even
|
|||
|
||||
if (ss->expand_cache->modify_active_face_set) {
|
||||
sculpt_expand_delete_face_set_id(ss->expand_cache->initial_face_sets,
|
||||
ss,
|
||||
ss->expand_cache,
|
||||
ob->data,
|
||||
ss->pmap,
|
||||
ss->totfaces,
|
||||
ss->expand_cache->next_face_set);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "RNA_enum_types.h"
|
||||
|
||||
#include "SEQ_iterator.h"
|
||||
#include "SEQ_utils.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
|
||||
|
@ -258,7 +259,7 @@ static void sound_update_animation_flags(Scene *scene)
|
|||
scene->id.tag |= LIB_TAG_DOIT;
|
||||
|
||||
SEQ_ALL_BEGIN (scene->ed, seq) {
|
||||
SEQ_iterator_recursive_apply(seq, sound_update_animation_flags_fn, scene);
|
||||
SEQ_recursive_apply(seq, sound_update_animation_flags_fn, scene);
|
||||
}
|
||||
SEQ_ALL_END;
|
||||
|
||||
|
|
|
@ -24,8 +24,11 @@
|
|||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_main.h"
|
||||
|
@ -398,6 +401,28 @@ static int track_markers_modal(bContext *C, wmOperator *UNUSED(op), const wmEven
|
|||
return OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
static char *track_markers_desc(bContext *UNUSED(C), wmOperatorType *UNUSED(op), PointerRNA *ptr)
|
||||
{
|
||||
const bool backwards = RNA_boolean_get(ptr, "backwards");
|
||||
const bool sequence = RNA_boolean_get(ptr, "sequence");
|
||||
|
||||
if (backwards && sequence) {
|
||||
return BLI_strdup(TIP_("Track the selected markers backward for the entire clip"));
|
||||
}
|
||||
if (backwards && !sequence) {
|
||||
return BLI_strdup(TIP_("Track the selected markers backward by one frame"));
|
||||
}
|
||||
if (!backwards && sequence) {
|
||||
return BLI_strdup(TIP_("Track the selected markers forward for the entire clip"));
|
||||
}
|
||||
if (!backwards && !sequence) {
|
||||
return BLI_strdup(TIP_("Track the selected markers forward by one frame"));
|
||||
}
|
||||
|
||||
/* Use default description. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CLIP_OT_track_markers(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
|
@ -410,6 +435,7 @@ void CLIP_OT_track_markers(wmOperatorType *ot)
|
|||
ot->invoke = track_markers_invoke;
|
||||
ot->modal = track_markers_modal;
|
||||
ot->poll = ED_space_clip_tracking_poll;
|
||||
ot->get_description = track_markers_desc;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_UNDO;
|
||||
|
|
|
@ -63,6 +63,7 @@ void FILE_OT_bookmark_move(struct wmOperatorType *ot);
|
|||
void FILE_OT_reset_recent(wmOperatorType *ot);
|
||||
void FILE_OT_hidedot(struct wmOperatorType *ot);
|
||||
void FILE_OT_execute(struct wmOperatorType *ot);
|
||||
void FILE_OT_mouse_execute(struct wmOperatorType *ot);
|
||||
void FILE_OT_cancel(struct wmOperatorType *ot);
|
||||
void FILE_OT_parent(struct wmOperatorType *ot);
|
||||
void FILE_OT_directory_new(struct wmOperatorType *ot);
|
||||
|
|
|
@ -536,6 +536,14 @@ void FILE_OT_select_box(wmOperatorType *ot)
|
|||
/** \name Select Pick Operator
|
||||
* \{ */
|
||||
|
||||
static rcti file_select_mval_to_select_rect(const int mval[2])
|
||||
{
|
||||
rcti rect;
|
||||
rect.xmin = rect.xmax = mval[0];
|
||||
rect.ymin = rect.ymax = mval[1];
|
||||
return rect;
|
||||
}
|
||||
|
||||
static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
|
@ -551,8 +559,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
rect.xmin = rect.xmax = event->mval[0];
|
||||
rect.ymin = rect.ymax = event->mval[1];
|
||||
rect = file_select_mval_to_select_rect(event->mval);
|
||||
|
||||
if (!ED_fileselect_layout_is_inside_pt(sfile->layout, ®ion->v2d, rect.xmin, rect.ymin)) {
|
||||
return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
|
||||
|
@ -1711,14 +1718,14 @@ bool file_draw_check_exists(SpaceFile *sfile)
|
|||
/** \name Execute File Window Operator
|
||||
* \{ */
|
||||
|
||||
static int file_exec(bContext *C, wmOperator *exec_op)
|
||||
/**
|
||||
* Execute the active file, as set in the file select params.
|
||||
*/
|
||||
static bool file_execute(bContext *C, SpaceFile *sfile)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
SpaceFile *sfile = CTX_wm_space_file(C);
|
||||
FileSelectParams *params = ED_fileselect_get_active_params(sfile);
|
||||
struct FileDirEntry *file = filelist_file(sfile->files, params->active_file);
|
||||
char filepath[FILE_MAX];
|
||||
FileDirEntry *file = filelist_file(sfile->files, params->active_file);
|
||||
|
||||
if (file && file->redirection_path) {
|
||||
/* redirection_path is an absolute path that takes precedence
|
||||
|
@ -1753,22 +1760,7 @@ static int file_exec(bContext *C, wmOperator *exec_op)
|
|||
/* opening file - sends events now, so things get handled on windowqueue level */
|
||||
else if (sfile->op) {
|
||||
wmOperator *op = sfile->op;
|
||||
|
||||
/* When used as a macro, for double-click, to prevent closing when double-clicking on item. */
|
||||
if (RNA_boolean_get(exec_op->ptr, "need_active")) {
|
||||
const int numfiles = filelist_files_ensure(sfile->files);
|
||||
int i, active = 0;
|
||||
|
||||
for (i = 0; i < numfiles; i++) {
|
||||
if (filelist_entry_select_index_get(sfile->files, i, CHECK_ALL)) {
|
||||
active = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (active == 0) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
}
|
||||
char filepath[FILE_MAX];
|
||||
|
||||
sfile->op = NULL;
|
||||
|
||||
|
@ -1788,13 +1780,53 @@ static int file_exec(bContext *C, wmOperator *exec_op)
|
|||
BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL),
|
||||
BLENDER_BOOKMARK_FILE);
|
||||
fsmenu_write_file(ED_fsmenu_get(), filepath);
|
||||
WM_event_fileselect_event(wm, op, EVT_FILESELECT_EXEC);
|
||||
WM_event_fileselect_event(CTX_wm_manager(C), op, EVT_FILESELECT_EXEC);
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int file_exec_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
static int file_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
SpaceFile *sfile = CTX_wm_space_file(C);
|
||||
|
||||
if (!file_execute(C, sfile)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void FILE_OT_execute(struct wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Execute File Window";
|
||||
ot->description = "Execute selected file";
|
||||
ot->idname = "FILE_OT_execute";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = file_exec;
|
||||
/* Important since handler is on window level.
|
||||
*
|
||||
* Avoid using #file_operator_poll since this is also used for entering directories
|
||||
* which is used even when the file manager doesn't have an operator. */
|
||||
ot->poll = ED_operator_file_active;
|
||||
}
|
||||
|
||||
/**
|
||||
* \returns false if the mouse doesn't hover a selectable item.
|
||||
*/
|
||||
static bool file_ensure_hovered_is_active(bContext *C, const wmEvent *event)
|
||||
{
|
||||
rcti rect = file_select_mval_to_select_rect(event->mval);
|
||||
if (file_select(C, &rect, FILE_SEL_ADD, false, false) == FILE_SELECT_NOTHING) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int file_execute_mouse_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
|
||||
{
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
SpaceFile *sfile = CTX_wm_space_file(C);
|
||||
|
@ -1804,34 +1836,38 @@ static int file_exec_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
return file_exec(C, op);
|
||||
/* Note that this isn't needed practically, because the keymap already activates the hovered item
|
||||
* on mouse-press. This execute operator is called afterwards on the double-click event then.
|
||||
* However relying on this would be fragile and could break with keymap changes, so better to
|
||||
* have this mouse-execute operator that makes sure once more that the hovered file is active. */
|
||||
if (!file_ensure_hovered_is_active(C, event)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (!file_execute(C, sfile)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void FILE_OT_execute(struct wmOperatorType *ot)
|
||||
/**
|
||||
* Variation of #FILE_OT_execute that accounts for some mouse specific handling. Otherwise calls
|
||||
* the same logic.
|
||||
*/
|
||||
void FILE_OT_mouse_execute(wmOperatorType *ot)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* identifiers */
|
||||
ot->name = "Execute File Window";
|
||||
ot->description = "Execute selected file";
|
||||
ot->idname = "FILE_OT_execute";
|
||||
ot->name = "Execute File";
|
||||
ot->description =
|
||||
"Perform the current execute action for the file under the cursor (e.g. open the file)";
|
||||
ot->idname = "FILE_OT_mouse_execute";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = file_exec_invoke;
|
||||
ot->exec = file_exec;
|
||||
/* Important since handler is on window level.
|
||||
*
|
||||
* Avoid using #file_operator_poll since this is also used for entering directories
|
||||
* which is used even when the file manager doesn't have an operator. */
|
||||
ot->invoke = file_execute_mouse_invoke;
|
||||
ot->poll = ED_operator_file_active;
|
||||
|
||||
/* properties */
|
||||
prop = RNA_def_boolean(ot->srna,
|
||||
"need_active",
|
||||
0,
|
||||
"Need Active",
|
||||
"Only execute if there's an active selected file in the file list");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
ot->flag = OPTYPE_INTERNAL;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -663,6 +663,7 @@ static void file_operatortypes(void)
|
|||
WM_operatortype_append(FILE_OT_highlight);
|
||||
WM_operatortype_append(FILE_OT_sort_column_ui_context);
|
||||
WM_operatortype_append(FILE_OT_execute);
|
||||
WM_operatortype_append(FILE_OT_mouse_execute);
|
||||
WM_operatortype_append(FILE_OT_cancel);
|
||||
WM_operatortype_append(FILE_OT_parent);
|
||||
WM_operatortype_append(FILE_OT_previous);
|
||||
|
|
|
@ -456,7 +456,9 @@ static void node_draw_frame(const bContext *C,
|
|||
}
|
||||
|
||||
/* label */
|
||||
node_draw_frame_label(ntree, node, snode->runtime->aspect);
|
||||
if (node->label[0] != '\0') {
|
||||
node_draw_frame_label(ntree, node, snode->runtime->aspect);
|
||||
}
|
||||
|
||||
UI_block_end(C, node->block);
|
||||
UI_block_draw(C, node->block);
|
||||
|
|
|
@ -902,7 +902,7 @@ static void id_override_library_reset_fn(bContext *C,
|
|||
}
|
||||
|
||||
static void id_override_library_resync_fn(bContext *C,
|
||||
ReportList *UNUSED(reports),
|
||||
ReportList *reports,
|
||||
Scene *scene,
|
||||
TreeElement *te,
|
||||
TreeStoreElem *UNUSED(tsep),
|
||||
|
@ -931,7 +931,7 @@ static void id_override_library_resync_fn(bContext *C,
|
|||
}
|
||||
|
||||
BKE_lib_override_library_resync(
|
||||
bmain, scene, CTX_data_view_layer(C), id_root, NULL, do_hierarchy_enforce, true);
|
||||
bmain, scene, CTX_data_view_layer(C), id_root, NULL, do_hierarchy_enforce, true, reports);
|
||||
|
||||
WM_event_add_notifier(C, NC_WINDOW, NULL);
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ typedef struct SequencerAddData {
|
|||
#define SEQPROP_NOPATHS (1 << 2)
|
||||
#define SEQPROP_NOCHAN (1 << 3)
|
||||
#define SEQPROP_FIT_METHOD (1 << 4)
|
||||
#define SEQPROP_VIEW_TRANSFORM (1 << 4)
|
||||
#define SEQPROP_VIEW_TRANSFORM (1 << 5)
|
||||
|
||||
static const EnumPropertyItem scale_fit_methods[] = {
|
||||
{SEQ_SCALE_TO_FIT, "FIT", 0, "Scale to Fit", "Scale image to fit within the canvas"},
|
||||
|
|
|
@ -1522,10 +1522,10 @@ static void *sequencer_OCIO_transform_ibuf(const bContext *C,
|
|||
ImBuf *ibuf,
|
||||
bool *r_glsl_used,
|
||||
eGPUTextureFormat *r_format,
|
||||
eGPUDataFormat *r_data)
|
||||
eGPUDataFormat *r_data,
|
||||
void **r_buffer_cache_handle)
|
||||
{
|
||||
void *display_buffer;
|
||||
void *cache_handle = NULL;
|
||||
bool force_fallback = false;
|
||||
*r_glsl_used = false;
|
||||
force_fallback |= (ED_draw_imbuf_method(ibuf) != IMAGE_DRAW_METHOD_GLSL);
|
||||
|
@ -1578,13 +1578,10 @@ static void *sequencer_OCIO_transform_ibuf(const bContext *C,
|
|||
/* There is data to be displayed, but GLSL is not initialized
|
||||
* properly, in this case we fallback to CPU-based display transform. */
|
||||
if ((ibuf->rect || ibuf->rect_float) && !*r_glsl_used) {
|
||||
display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
|
||||
display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, r_buffer_cache_handle);
|
||||
*r_format = GPU_RGBA8;
|
||||
*r_data = GPU_DATA_UBYTE;
|
||||
}
|
||||
if (cache_handle) {
|
||||
IMB_display_buffer_release(cache_handle);
|
||||
}
|
||||
|
||||
return display_buffer;
|
||||
}
|
||||
|
@ -1658,6 +1655,7 @@ static void sequencer_draw_display_buffer(const bContext *C,
|
|||
bool draw_backdrop)
|
||||
{
|
||||
void *display_buffer;
|
||||
void *buffer_cache_handle = NULL;
|
||||
|
||||
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) {
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
|
@ -1685,7 +1683,8 @@ static void sequencer_draw_display_buffer(const bContext *C,
|
|||
data = GPU_DATA_UBYTE;
|
||||
}
|
||||
else {
|
||||
display_buffer = sequencer_OCIO_transform_ibuf(C, ibuf, &glsl_used, &format, &data);
|
||||
display_buffer = sequencer_OCIO_transform_ibuf(
|
||||
C, ibuf, &glsl_used, &format, &data, &buffer_cache_handle);
|
||||
}
|
||||
|
||||
if (draw_backdrop) {
|
||||
|
@ -1745,6 +1744,10 @@ static void sequencer_draw_display_buffer(const bContext *C,
|
|||
IMB_colormanagement_finish_glsl_draw();
|
||||
}
|
||||
|
||||
if (buffer_cache_handle) {
|
||||
IMB_display_buffer_release(buffer_cache_handle);
|
||||
}
|
||||
|
||||
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) {
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
}
|
||||
|
|
|
@ -1608,7 +1608,7 @@ static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
|
|||
BLI_movelisttolist(ed->seqbasep, &nseqbase);
|
||||
|
||||
for (; seq; seq = seq->next) {
|
||||
SEQ_iterator_recursive_apply(seq, apply_unique_name_fn, scene);
|
||||
SEQ_recursive_apply(seq, apply_unique_name_fn, scene);
|
||||
}
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
|
@ -2465,7 +2465,7 @@ static int sequencer_paste_exec(bContext *C, wmOperator *op)
|
|||
|
||||
for (iseq = iseq_first; iseq; iseq = iseq->next) {
|
||||
/* Make sure, that pasted strips have unique names. */
|
||||
SEQ_iterator_recursive_apply(iseq, apply_unique_name_fn, scene);
|
||||
SEQ_recursive_apply(iseq, apply_unique_name_fn, scene);
|
||||
/* Translate after name has been changed, otherwise this will affect animdata of original
|
||||
* strip. */
|
||||
SEQ_transform_translate_sequence(scene, iseq, ofs);
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
|
@ -1622,64 +1621,78 @@ static bool select_grouped_time_overlap(Editing *ed, Sequence *actseq)
|
|||
return changed;
|
||||
}
|
||||
|
||||
static bool select_grouped_effect_link(Editing *ed, Sequence *actseq, const int channel)
|
||||
/* Query all effect strips that are directly or indirectly connected to seq_reference. */
|
||||
static void query_strip_effect_chain(Sequence *seq_reference,
|
||||
ListBase *seqbase,
|
||||
SeqCollection *collection)
|
||||
{
|
||||
bool changed = false;
|
||||
const bool is_audio = ((actseq->type == SEQ_TYPE_META) || SEQ_IS_SOUND(actseq));
|
||||
int startdisp = actseq->startdisp;
|
||||
int enddisp = actseq->enddisp;
|
||||
int machine = actseq->machine;
|
||||
SeqIterator iter;
|
||||
|
||||
LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
|
||||
seq->tmp = NULL;
|
||||
if (!SEQ_collection_append_strip(seq_reference, collection)) {
|
||||
return; /* Strip is already in set, so all effects connected to it are as well. */
|
||||
}
|
||||
|
||||
actseq->tmp = POINTER_FROM_INT(true);
|
||||
|
||||
Sequence *seq = NULL;
|
||||
for (SEQ_iterator_begin(ed, &iter, true); iter.valid; SEQ_iterator_next(&iter)) {
|
||||
seq = iter.seq;
|
||||
|
||||
/* Ignore all seqs already selected. */
|
||||
/* Ignore all seqs not sharing some time with active one. */
|
||||
/* Ignore all seqs of incompatible types (audio vs video). */
|
||||
if (!SEQ_CHANNEL_CHECK(seq, channel) || (seq->flag & SELECT) || (seq->startdisp >= enddisp) ||
|
||||
(seq->enddisp < startdisp) || (!is_audio && SEQ_IS_SOUND(seq)) ||
|
||||
(is_audio && !((seq->type == SEQ_TYPE_META) || SEQ_IS_SOUND(seq)))) {
|
||||
continue;
|
||||
/* Find all strips that seq_reference is connected to. */
|
||||
if (seq_reference->type & SEQ_TYPE_EFFECT) {
|
||||
if (seq_reference->seq1) {
|
||||
query_strip_effect_chain(seq_reference->seq1, seqbase, collection);
|
||||
}
|
||||
|
||||
/* If the seq is an effect one, we need extra checking. */
|
||||
if (SEQ_IS_EFFECT(seq) && ((seq->seq1 && seq->seq1->tmp) || (seq->seq2 && seq->seq2->tmp) ||
|
||||
(seq->seq3 && seq->seq3->tmp))) {
|
||||
if (startdisp > seq->startdisp) {
|
||||
startdisp = seq->startdisp;
|
||||
}
|
||||
if (enddisp < seq->enddisp) {
|
||||
enddisp = seq->enddisp;
|
||||
}
|
||||
if (machine < seq->machine) {
|
||||
machine = seq->machine;
|
||||
}
|
||||
|
||||
seq->tmp = POINTER_FROM_INT(true);
|
||||
|
||||
seq->flag |= SELECT;
|
||||
changed = true;
|
||||
|
||||
/* Unfortunately, we must restart checks from the beginning. */
|
||||
SEQ_iterator_end(&iter);
|
||||
SEQ_iterator_begin(ed, &iter, true);
|
||||
if (seq_reference->seq2) {
|
||||
query_strip_effect_chain(seq_reference->seq2, seqbase, collection);
|
||||
}
|
||||
|
||||
/* Video strips below active one, or any strip for audio (order doesn't matter here). */
|
||||
else if (seq->machine < machine || is_audio) {
|
||||
seq->flag |= SELECT;
|
||||
changed = true;
|
||||
if (seq_reference->seq3) {
|
||||
query_strip_effect_chain(seq_reference->seq3, seqbase, collection);
|
||||
}
|
||||
}
|
||||
SEQ_iterator_end(&iter);
|
||||
|
||||
/* Find all strips connected to seq_reference. */
|
||||
LISTBASE_FOREACH (Sequence *, seq_test, seqbase) {
|
||||
if (seq_test->seq1 == seq_reference || seq_test->seq2 == seq_reference ||
|
||||
seq_test->seq3 == seq_reference) {
|
||||
query_strip_effect_chain(seq_test, seqbase, collection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Query strips that are in lower channel and intersect in time with seq_reference. */
|
||||
static void query_lower_channel_strips(Sequence *seq_reference,
|
||||
ListBase *seqbase,
|
||||
SeqCollection *collection)
|
||||
{
|
||||
LISTBASE_FOREACH (Sequence *, seq_test, seqbase) {
|
||||
if (seq_test->machine > seq_reference->machine) {
|
||||
continue; /* Not lower channel. */
|
||||
}
|
||||
if (seq_test->enddisp <= seq_reference->startdisp ||
|
||||
seq_test->startdisp >= seq_reference->enddisp) {
|
||||
continue; /* Not intersecting in time. */
|
||||
}
|
||||
SEQ_collection_append_strip(seq_test, collection);
|
||||
}
|
||||
}
|
||||
|
||||
/* Select all strips within time range and with lower channel of initial selection. Then select
|
||||
* effect chains of these strips. */
|
||||
static bool select_grouped_effect_link(Editing *ed,
|
||||
Sequence *UNUSED(actseq),
|
||||
const int UNUSED(channel))
|
||||
{
|
||||
ListBase *seqbase = SEQ_active_seqbase_get(ed);
|
||||
|
||||
/* Get collection of strips. */
|
||||
SeqCollection *collection = SEQ_query_selected_strips(seqbase);
|
||||
const int selected_strip_count = BLI_gset_len(collection->set);
|
||||
SEQ_collection_expand(seqbase, collection, query_lower_channel_strips);
|
||||
SEQ_collection_expand(seqbase, collection, query_strip_effect_chain);
|
||||
|
||||
/* Check if other strips will be affected. */
|
||||
const bool changed = BLI_gset_len(collection->set) > selected_strip_count;
|
||||
|
||||
/* Actual logic. */
|
||||
Sequence *seq;
|
||||
SEQ_ITERATOR_FOREACH (seq, collection) {
|
||||
seq->flag |= SELECT;
|
||||
}
|
||||
|
||||
SEQ_collection_free(collection);
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
|
|
@ -1288,6 +1288,11 @@ static void draw_viewport_name(ARegion *region, View3D *v3d, int xoffset, int *y
|
|||
name_array[name_array_len++] = IFACE_(" (Local)");
|
||||
}
|
||||
|
||||
/* Indicate that clipping region is enabled. */
|
||||
if (rv3d->rflag & RV3D_CLIPPING) {
|
||||
name_array[name_array_len++] = IFACE_(" (Clipped)");
|
||||
}
|
||||
|
||||
if (name_array_len > 1) {
|
||||
BLI_string_join_array(tmpstr, sizeof(tmpstr), name_array, name_array_len);
|
||||
name = tmpstr;
|
||||
|
|
|
@ -135,6 +135,9 @@ class GVArray {
|
|||
this->get_internal_single(r_value);
|
||||
}
|
||||
|
||||
void materialize(void *dst) const;
|
||||
void materialize(const IndexMask mask, void *dst) const;
|
||||
|
||||
void materialize_to_uninitialized(void *dst) const;
|
||||
void materialize_to_uninitialized(const IndexMask mask, void *dst) const;
|
||||
|
||||
|
@ -162,6 +165,7 @@ class GVArray {
|
|||
virtual bool is_single_impl() const;
|
||||
virtual void get_internal_single_impl(void *UNUSED(r_value)) const;
|
||||
|
||||
virtual void materialize_impl(const IndexMask mask, void *dst) const;
|
||||
virtual void materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const;
|
||||
|
||||
virtual const void *try_get_internal_varray_impl() const;
|
||||
|
@ -370,6 +374,11 @@ template<typename T> class GVArray_For_VArray : public GVArray {
|
|||
*(T *)r_value = varray_->get_internal_single();
|
||||
}
|
||||
|
||||
void materialize_impl(const IndexMask mask, void *dst) const override
|
||||
{
|
||||
varray_->materialize(mask, MutableSpan((T *)dst, mask.min_array_size()));
|
||||
}
|
||||
|
||||
void materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const override
|
||||
{
|
||||
varray_->materialize_to_uninitialized(mask, MutableSpan((T *)dst, mask.min_array_size()));
|
||||
|
@ -545,6 +554,16 @@ template<typename T> class GVMutableArray_For_VMutableArray : public GVMutableAr
|
|||
varray_->set(index, std::move(value_));
|
||||
}
|
||||
|
||||
void materialize_impl(const IndexMask mask, void *dst) const override
|
||||
{
|
||||
varray_->materialize(mask, MutableSpan((T *)dst, mask.min_array_size()));
|
||||
}
|
||||
|
||||
void materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const override
|
||||
{
|
||||
varray_->materialize_to_uninitialized(mask, MutableSpan((T *)dst, mask.min_array_size()));
|
||||
}
|
||||
|
||||
const void *try_get_internal_varray_impl() const override
|
||||
{
|
||||
return (const VArray<T> *)varray_;
|
||||
|
|
|
@ -53,6 +53,24 @@ class GVArray_For_ShallowCopy : public GVArray {
|
|||
* GVArray.
|
||||
*/
|
||||
|
||||
void GVArray::materialize(void *dst) const
|
||||
{
|
||||
this->materialize(IndexMask(size_), dst);
|
||||
}
|
||||
|
||||
void GVArray::materialize(const IndexMask mask, void *dst) const
|
||||
{
|
||||
this->materialize_impl(mask, dst);
|
||||
}
|
||||
|
||||
void GVArray::materialize_impl(const IndexMask mask, void *dst) const
|
||||
{
|
||||
for (const int64_t i : mask) {
|
||||
void *elem_dst = POINTER_OFFSET(dst, type_->size() * i);
|
||||
this->get(i, elem_dst);
|
||||
}
|
||||
}
|
||||
|
||||
void GVArray::materialize_to_uninitialized(void *dst) const
|
||||
{
|
||||
this->materialize_to_uninitialized(IndexMask(size_), dst);
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
* Use these instead of glGenBuffers & its friends
|
||||
* - alloc must be called from a thread that is bound
|
||||
* to the context that will be used for drawing with
|
||||
* this vao.
|
||||
* this VAO.
|
||||
* - free can be called from any thread
|
||||
*/
|
||||
|
||||
|
|
|
@ -543,7 +543,7 @@ bool GPU_matrix_unproject_precalc(struct GPUMatrixUnproject_Precalc *precalc,
|
|||
&precalc->dims.zmax);
|
||||
if (isinf(precalc->dims.zmax)) {
|
||||
/* We cannot retrieve the actual value of the clip_end.
|
||||
* Use `FLT_MAX` to avoid nans. */
|
||||
* Use `FLT_MAX` to avoid NAN's. */
|
||||
precalc->dims.zmax = FLT_MAX;
|
||||
}
|
||||
for (int i = 0; i < 4; i++) {
|
||||
|
|
|
@ -286,9 +286,10 @@ static void detect_workarounds()
|
|||
strstr(renderer, " RX 480 ") || strstr(renderer, " RX 490 ") ||
|
||||
strstr(renderer, " RX 560 ") || strstr(renderer, " RX 560X ") ||
|
||||
strstr(renderer, " RX 570 ") || strstr(renderer, " RX 580 ") ||
|
||||
strstr(renderer, " RX 590 ") || strstr(renderer, " RX550/550 ") ||
|
||||
strstr(renderer, " (TM) 520 ") || strstr(renderer, " (TM) 530 ") ||
|
||||
strstr(renderer, " R5 ") || strstr(renderer, " R7 ") || strstr(renderer, " R9 ")) {
|
||||
strstr(renderer, " RX 580X ") || strstr(renderer, " RX 590 ") ||
|
||||
strstr(renderer, " RX550/550 ") || strstr(renderer, " (TM) 520 ") ||
|
||||
strstr(renderer, " (TM) 530 ") || strstr(renderer, " R5 ") || strstr(renderer, " R7 ") ||
|
||||
strstr(renderer, " R9 ")) {
|
||||
GCaps.use_hq_normals_workaround = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
using namespace blender::gpu;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Vao cache
|
||||
/** \name VAO Cache
|
||||
*
|
||||
* Each #GLBatch has a small cache of VAO objects that are used to avoid VAO reconfiguration.
|
||||
* TODO(fclem): Could be revisited to avoid so much cross references.
|
||||
|
|
|
@ -43,7 +43,7 @@ class GLShaderInterface;
|
|||
|
||||
#define GPU_VAO_STATIC_LEN 3
|
||||
|
||||
/* Vao management: remembers all geometry state (vertex attribute bindings & element buffer)
|
||||
/* VAO management: remembers all geometry state (vertex attribute bindings & element buffer)
|
||||
* for each shader interface. Start with a static number of vaos and fallback to dynamic count
|
||||
* if necessary. Once a batch goes dynamic it does not go back. */
|
||||
class GLVaoCache {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue