Geometry Nodes: add simulation support #104924
|
@ -383,7 +383,8 @@ bool BKE_image_is_filename_tokenized(char *filepath);
|
||||||
* Ensures that `filename` contains a UDIM token if we find a supported format pattern.
|
* Ensures that `filename` contains a UDIM token if we find a supported format pattern.
|
||||||
* \note This must only be the name component (without slashes).
|
* \note This must only be the name component (without slashes).
|
||||||
*/
|
*/
|
||||||
void BKE_image_ensure_tile_token(char *filename);
|
void BKE_image_ensure_tile_token(char *filepath, size_t filepath_maxncpy);
|
||||||
|
void BKE_image_ensure_tile_token_filename_only(char *filename, size_t filename_maxncpy);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When provided with an absolute virtual `filepath`, check to see if at least
|
* When provided with an absolute virtual `filepath`, check to see if at least
|
||||||
|
|
|
@ -531,7 +531,7 @@ static bool absolute_convert_foreach_path_cb(BPathForeachPathData *bpath_data,
|
||||||
return false; /* Already absolute. */
|
return false; /* Already absolute. */
|
||||||
}
|
}
|
||||||
|
|
||||||
BLI_strncpy(path_dst, path_src, FILENAME_MAX);
|
BLI_strncpy(path_dst, path_src, FILE_MAX);
|
||||||
BLI_path_abs(path_dst, data->basedir);
|
BLI_path_abs(path_dst, data->basedir);
|
||||||
if (BLI_path_is_rel(path_dst) == false) {
|
if (BLI_path_is_rel(path_dst) == false) {
|
||||||
data->count_changed++;
|
data->count_changed++;
|
||||||
|
|
|
@ -3112,8 +3112,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* When changing to UDIM, attempt to tokenize the filepath. */
|
/* When changing to UDIM, attempt to tokenize the filepath. */
|
||||||
char *filename = (char *)BLI_path_basename(ima->filepath);
|
BKE_image_ensure_tile_token(ima->filepath, sizeof(ima->filepath));
|
||||||
BKE_image_ensure_tile_token(filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* image buffers for non-sequence multilayer will share buffers with RenderResult,
|
/* image buffers for non-sequence multilayer will share buffers with RenderResult,
|
||||||
|
@ -3304,7 +3303,7 @@ bool BKE_image_get_tile_info(char *filepath, ListBase *tiles, int *r_tile_start,
|
||||||
BLI_split_dirfile(filepath, dirname, filename, sizeof(dirname), sizeof(filename));
|
BLI_split_dirfile(filepath, dirname, filename, sizeof(dirname), sizeof(filename));
|
||||||
|
|
||||||
if (!BKE_image_is_filename_tokenized(filename)) {
|
if (!BKE_image_is_filename_tokenized(filename)) {
|
||||||
BKE_image_ensure_tile_token(filename);
|
BKE_image_ensure_tile_token_filename_only(filename, sizeof(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
eUDIM_TILE_FORMAT tile_format;
|
eUDIM_TILE_FORMAT tile_format;
|
||||||
|
@ -3494,7 +3493,7 @@ bool BKE_image_is_filename_tokenized(char *filepath)
|
||||||
return strstr(filename, "<UDIM>") != nullptr || strstr(filename, "<UVTILE>") != nullptr;
|
return strstr(filename, "<UDIM>") != nullptr || strstr(filename, "<UVTILE>") != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BKE_image_ensure_tile_token(char *filename)
|
void BKE_image_ensure_tile_token_filename_only(char *filename, size_t filename_maxncpy)
|
||||||
{
|
{
|
||||||
BLI_assert_msg(BLI_path_slash_find(filename) == nullptr,
|
BLI_assert_msg(BLI_path_slash_find(filename) == nullptr,
|
||||||
"Only the file-name component should be used!");
|
"Only the file-name component should be used!");
|
||||||
|
@ -3511,18 +3510,24 @@ void BKE_image_ensure_tile_token(char *filename)
|
||||||
* 1000 through 2000 to provide better detection. */
|
* 1000 through 2000 to provide better detection. */
|
||||||
std::regex pattern(R"((.*[._-])([12]\d{3})([._-].*))");
|
std::regex pattern(R"((.*[._-])([12]\d{3})([._-].*))");
|
||||||
if (std::regex_search(path, match, pattern)) {
|
if (std::regex_search(path, match, pattern)) {
|
||||||
BLI_strncpy(filename, match.format("$1<UDIM>$3").c_str(), FILE_MAX);
|
BLI_strncpy(filename, match.format("$1<UDIM>$3").c_str(), filename_maxncpy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* General `u##_v###` `uvtile` pattern. */
|
/* General `u##_v###` `uvtile` pattern. */
|
||||||
pattern = std::regex(R"((.*)(u\d{1,2}_v\d{1,3})(\D.*))");
|
pattern = std::regex(R"((.*)(u\d{1,2}_v\d{1,3})(\D.*))");
|
||||||
if (std::regex_search(path, match, pattern)) {
|
if (std::regex_search(path, match, pattern)) {
|
||||||
BLI_strncpy(filename, match.format("$1<UVTILE>$3").c_str(), FILE_MAX);
|
BLI_strncpy(filename, match.format("$1<UVTILE>$3").c_str(), filename_maxncpy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BKE_image_ensure_tile_token(char *filepath, size_t filepath_maxncpy)
|
||||||
|
{
|
||||||
|
char *filename = (char *)BLI_path_basename(filepath);
|
||||||
|
BKE_image_ensure_tile_token_filename_only(filename, filepath_maxncpy - (filename - filepath));
|
||||||
|
}
|
||||||
|
|
||||||
bool BKE_image_tile_filepath_exists(const char *filepath)
|
bool BKE_image_tile_filepath_exists(const char *filepath)
|
||||||
{
|
{
|
||||||
BLI_assert(!BLI_path_is_rel(filepath));
|
BLI_assert(!BLI_path_is_rel(filepath));
|
||||||
|
@ -5136,8 +5141,8 @@ void BKE_image_user_file_path_ex(const Main *bmain,
|
||||||
int index;
|
int index;
|
||||||
if (ima->source == IMA_SRC_SEQUENCE) {
|
if (ima->source == IMA_SRC_SEQUENCE) {
|
||||||
index = iuser ? iuser->framenr : ima->lastframe;
|
index = iuser ? iuser->framenr : ima->lastframe;
|
||||||
BLI_path_sequence_decode(filepath, head, tail, &numlen);
|
BLI_path_sequence_decode(filepath, head, sizeof(head), tail, sizeof(tail), &numlen);
|
||||||
BLI_path_sequence_encode(filepath, head, tail, numlen, index);
|
BLI_path_sequence_encode(filepath, FILE_MAX, head, tail, numlen, index);
|
||||||
}
|
}
|
||||||
else if (resolve_udim) {
|
else if (resolve_udim) {
|
||||||
index = image_get_tile_number_from_iuser(ima, iuser);
|
index = image_get_tile_number_from_iuser(ima, iuser);
|
||||||
|
@ -5277,7 +5282,7 @@ float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame, int
|
||||||
|
|
||||||
int BKE_image_sequence_guess_offset(Image *image)
|
int BKE_image_sequence_guess_offset(Image *image)
|
||||||
{
|
{
|
||||||
return BLI_path_sequence_decode(image->filepath, nullptr, nullptr, nullptr);
|
return BLI_path_sequence_decode(image->filepath, nullptr, 0, nullptr, 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BKE_image_has_anim(Image *ima)
|
bool BKE_image_has_anim(Image *ima)
|
||||||
|
|
|
@ -18,7 +18,7 @@ TEST(udim, image_ensure_tile_token)
|
||||||
char result[FILE_MAX];
|
char result[FILE_MAX];
|
||||||
|
|
||||||
BLI_strncpy(result, original, sizeof(result));
|
BLI_strncpy(result, original, sizeof(result));
|
||||||
BKE_image_ensure_tile_token(result);
|
BKE_image_ensure_tile_token_filename_only(result, sizeof(result));
|
||||||
EXPECT_STREQ(result, expected);
|
EXPECT_STREQ(result, expected);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -332,6 +332,14 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
||||||
result_corner_edges[i] += src_edges_num;
|
result_corner_edges[i] += src_edges_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mesh->runtime->subsurf_optimal_display_edges.is_empty()) {
|
||||||
|
const blender::BoundedBitSpan src = mesh->runtime->subsurf_optimal_display_edges;
|
||||||
|
result->runtime->subsurf_optimal_display_edges.resize(result->totedge);
|
||||||
|
blender::MutableBoundedBitSpan dst = result->runtime->subsurf_optimal_display_edges;
|
||||||
|
dst.slice({0, src.size()}).copy_from(src);
|
||||||
|
dst.slice({src.size(), src.size()}).copy_from(src);
|
||||||
|
}
|
||||||
|
|
||||||
/* handle uvs,
|
/* handle uvs,
|
||||||
* let tessface recalc handle updating the MTFace data */
|
* let tessface recalc handle updating the MTFace data */
|
||||||
if (mmd->flag & (MOD_MIR_MIRROR_U | MOD_MIR_MIRROR_V) ||
|
if (mmd->flag & (MOD_MIR_MIRROR_U | MOD_MIR_MIRROR_V) ||
|
||||||
|
|
|
@ -481,15 +481,19 @@ static void get_sequence_filepath(const MovieClip *clip, const int framenr, char
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
BLI_strncpy(filepath, clip->filepath, sizeof(clip->filepath));
|
BLI_strncpy(filepath, clip->filepath, sizeof(clip->filepath));
|
||||||
BLI_path_sequence_decode(filepath, head, tail, &numlen);
|
BLI_path_sequence_decode(filepath, head, sizeof(head), tail, sizeof(tail), &numlen);
|
||||||
|
|
||||||
/* Movie-clips always points to first image from sequence, auto-guess offset for now.
|
/* Movie-clips always points to first image from sequence, auto-guess offset for now.
|
||||||
* Could be something smarter in the future. */
|
* Could be something smarter in the future. */
|
||||||
offset = sequence_guess_offset(clip->filepath, strlen(head), numlen);
|
offset = sequence_guess_offset(clip->filepath, strlen(head), numlen);
|
||||||
|
|
||||||
if (numlen) {
|
if (numlen) {
|
||||||
BLI_path_sequence_encode(
|
BLI_path_sequence_encode(filepath,
|
||||||
filepath, head, tail, numlen, offset + framenr - clip->start_frame + clip->frame_offset);
|
sizeof(filepath),
|
||||||
|
head,
|
||||||
|
tail,
|
||||||
|
numlen,
|
||||||
|
offset + framenr - clip->start_frame + clip->frame_offset);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
BLI_strncpy(filepath, clip->filepath, sizeof(clip->filepath));
|
BLI_strncpy(filepath, clip->filepath, sizeof(clip->filepath));
|
||||||
|
@ -702,7 +706,7 @@ static void movieclip_calc_length(MovieClip *clip)
|
||||||
ushort numlen;
|
ushort numlen;
|
||||||
char filepath[FILE_MAX], head[FILE_MAX], tail[FILE_MAX];
|
char filepath[FILE_MAX], head[FILE_MAX], tail[FILE_MAX];
|
||||||
|
|
||||||
BLI_path_sequence_decode(clip->filepath, head, tail, &numlen);
|
BLI_path_sequence_decode(clip->filepath, head, sizeof(head), tail, sizeof(tail), &numlen);
|
||||||
|
|
||||||
if (numlen == 0) {
|
if (numlen == 0) {
|
||||||
/* there's no number group in file name, assume it's single framed sequence */
|
/* there's no number group in file name, assume it's single framed sequence */
|
||||||
|
@ -790,7 +794,7 @@ static int user_frame_to_cache_frame(MovieClip *clip, int framenr)
|
||||||
ushort numlen;
|
ushort numlen;
|
||||||
char head[FILE_MAX], tail[FILE_MAX];
|
char head[FILE_MAX], tail[FILE_MAX];
|
||||||
|
|
||||||
BLI_path_sequence_decode(clip->filepath, head, tail, &numlen);
|
BLI_path_sequence_decode(clip->filepath, head, sizeof(head), tail, sizeof(tail), &numlen);
|
||||||
|
|
||||||
/* see comment in get_sequence_filepath */
|
/* see comment in get_sequence_filepath */
|
||||||
clip->cache->sequence_offset = sequence_guess_offset(clip->filepath, strlen(head), numlen);
|
clip->cache->sequence_offset = sequence_guess_offset(clip->filepath, strlen(head), numlen);
|
||||||
|
@ -933,7 +937,7 @@ static bool put_imbuf_cache(
|
||||||
clip->cache->sequence_offset = -1;
|
clip->cache->sequence_offset = -1;
|
||||||
if (clip->source == MCLIP_SRC_SEQUENCE) {
|
if (clip->source == MCLIP_SRC_SEQUENCE) {
|
||||||
ushort numlen;
|
ushort numlen;
|
||||||
BLI_path_sequence_decode(clip->filepath, NULL, NULL, &numlen);
|
BLI_path_sequence_decode(clip->filepath, NULL, 0, NULL, 0, &numlen);
|
||||||
clip->cache->is_still_sequence = (numlen == 0);
|
clip->cache->is_still_sequence = (numlen == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -654,8 +654,7 @@ int BKE_packedfile_unpack_image(Main *bmain,
|
||||||
BLI_strncpy(ima->filepath, new_file_path, sizeof(imapf->filepath));
|
BLI_strncpy(ima->filepath, new_file_path, sizeof(imapf->filepath));
|
||||||
if (ima->source == IMA_SRC_TILED) {
|
if (ima->source == IMA_SRC_TILED) {
|
||||||
/* Ensure that the Image filepath is kept in a tokenized format. */
|
/* Ensure that the Image filepath is kept in a tokenized format. */
|
||||||
char *filename = (char *)BLI_path_basename(ima->filepath);
|
BKE_image_ensure_tile_token(ima->filepath, sizeof(ima->filepath));
|
||||||
BKE_image_ensure_tile_token(filename);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MEM_freeN(new_file_path);
|
MEM_freeN(new_file_path);
|
||||||
|
|
|
@ -1301,7 +1301,7 @@ static int ptcache_frame_from_filename(const char *filename, const char *ext)
|
||||||
#define MAX_PTCACHE_PATH FILE_MAX
|
#define MAX_PTCACHE_PATH FILE_MAX
|
||||||
#define MAX_PTCACHE_FILE (FILE_MAX * 2)
|
#define MAX_PTCACHE_FILE (FILE_MAX * 2)
|
||||||
|
|
||||||
static int ptcache_path(PTCacheID *pid, char *dirname)
|
static int ptcache_path(PTCacheID *pid, char dirname[MAX_PTCACHE_PATH])
|
||||||
{
|
{
|
||||||
const char *blendfile_path = BKE_main_blendfile_path_from_global();
|
const char *blendfile_path = BKE_main_blendfile_path_from_global();
|
||||||
Library *lib = (pid->owner_id) ? pid->owner_id->lib : NULL;
|
Library *lib = (pid->owner_id) ? pid->owner_id->lib : NULL;
|
||||||
|
@ -1311,13 +1311,13 @@ static int ptcache_path(PTCacheID *pid, char *dirname)
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if (pid->cache->flag & PTCACHE_EXTERNAL) {
|
if (pid->cache->flag & PTCACHE_EXTERNAL) {
|
||||||
strcpy(dirname, pid->cache->path);
|
BLI_strncpy(dirname, pid->cache->path, MAX_PTCACHE_PATH);
|
||||||
|
|
||||||
if (BLI_path_is_rel(dirname)) {
|
if (BLI_path_is_rel(dirname)) {
|
||||||
BLI_path_abs(dirname, blendfilename);
|
BLI_path_abs(dirname, blendfilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
return BLI_path_slash_ensure(dirname, MAX_PTCACHE_FILE); /* new strlen() */
|
return BLI_path_slash_ensure(dirname, MAX_PTCACHE_PATH); /* new strlen() */
|
||||||
}
|
}
|
||||||
if ((blendfile_path[0] != '\0') || lib) {
|
if ((blendfile_path[0] != '\0') || lib) {
|
||||||
char file[MAX_PTCACHE_PATH]; /* we don't want the dir, only the file */
|
char file[MAX_PTCACHE_PATH]; /* we don't want the dir, only the file */
|
||||||
|
@ -1334,18 +1334,18 @@ static int ptcache_path(PTCacheID *pid, char *dirname)
|
||||||
BLI_snprintf(dirname, MAX_PTCACHE_PATH, "//" PTCACHE_PATH "%s", file);
|
BLI_snprintf(dirname, MAX_PTCACHE_PATH, "//" PTCACHE_PATH "%s", file);
|
||||||
|
|
||||||
BLI_path_abs(dirname, blendfilename);
|
BLI_path_abs(dirname, blendfilename);
|
||||||
return BLI_path_slash_ensure(dirname, MAX_PTCACHE_FILE); /* new strlen() */
|
return BLI_path_slash_ensure(dirname, MAX_PTCACHE_PATH); /* new strlen() */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* use the temp path. this is weak but better than not using point cache at all */
|
/* use the temp path. this is weak but better than not using point cache at all */
|
||||||
/* temporary directory is assumed to exist and ALWAYS has a trailing slash */
|
/* temporary directory is assumed to exist and ALWAYS has a trailing slash */
|
||||||
BLI_snprintf(dirname, MAX_PTCACHE_PATH, "%s" PTCACHE_PATH, BKE_tempdir_session());
|
BLI_snprintf(dirname, MAX_PTCACHE_PATH, "%s" PTCACHE_PATH, BKE_tempdir_session());
|
||||||
|
|
||||||
return BLI_path_slash_ensure(dirname, MAX_PTCACHE_FILE); /* new strlen() */
|
return BLI_path_slash_ensure(dirname, MAX_PTCACHE_PATH); /* new strlen() */
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t ptcache_filepath_ext_append(PTCacheID *pid,
|
static size_t ptcache_filepath_ext_append(PTCacheID *pid,
|
||||||
char *filepath,
|
char filepath[MAX_PTCACHE_FILE],
|
||||||
const size_t filepath_len,
|
const size_t filepath_len,
|
||||||
const bool use_frame_number,
|
const bool use_frame_number,
|
||||||
const int cfra)
|
const int cfra)
|
||||||
|
@ -1396,8 +1396,11 @@ static size_t ptcache_filepath_ext_append(PTCacheID *pid,
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ptcache_filepath(
|
static int ptcache_filepath(PTCacheID *pid,
|
||||||
PTCacheID *pid, char *filepath, int cfra, const bool do_path, const bool do_ext)
|
char filepath[MAX_PTCACHE_FILE],
|
||||||
|
int cfra,
|
||||||
|
const bool do_path,
|
||||||
|
const bool do_ext)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
char *idname;
|
char *idname;
|
||||||
|
@ -2591,7 +2594,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, uint cfra)
|
||||||
char path[MAX_PTCACHE_PATH];
|
char path[MAX_PTCACHE_PATH];
|
||||||
char filepath[MAX_PTCACHE_FILE];
|
char filepath[MAX_PTCACHE_FILE];
|
||||||
char path_full[MAX_PTCACHE_FILE];
|
char path_full[MAX_PTCACHE_FILE];
|
||||||
char ext[MAX_PTCACHE_PATH];
|
char ext[MAX_PTCACHE_FILE];
|
||||||
|
|
||||||
if (!pid || !pid->cache || pid->cache->flag & PTCACHE_BAKED) {
|
if (!pid || !pid->cache || pid->cache->flag & PTCACHE_BAKED) {
|
||||||
return;
|
return;
|
||||||
|
@ -2818,7 +2821,7 @@ void BKE_ptcache_id_time(
|
||||||
struct dirent *de;
|
struct dirent *de;
|
||||||
char path[MAX_PTCACHE_PATH];
|
char path[MAX_PTCACHE_PATH];
|
||||||
char filepath[MAX_PTCACHE_FILE];
|
char filepath[MAX_PTCACHE_FILE];
|
||||||
char ext[MAX_PTCACHE_PATH];
|
char ext[MAX_PTCACHE_FILE];
|
||||||
uint len; /* store the length of the string */
|
uint len; /* store the length of the string */
|
||||||
|
|
||||||
ptcache_path(pid, path);
|
ptcache_path(pid, path);
|
||||||
|
@ -3490,7 +3493,7 @@ void BKE_ptcache_disk_cache_rename(PTCacheID *pid, const char *name_src, const c
|
||||||
char old_filepath[MAX_PTCACHE_FILE];
|
char old_filepath[MAX_PTCACHE_FILE];
|
||||||
char new_path_full[MAX_PTCACHE_FILE];
|
char new_path_full[MAX_PTCACHE_FILE];
|
||||||
char old_path_full[MAX_PTCACHE_FILE];
|
char old_path_full[MAX_PTCACHE_FILE];
|
||||||
char ext[MAX_PTCACHE_PATH];
|
char ext[MAX_PTCACHE_FILE];
|
||||||
|
|
||||||
/* If both names are the same, there is nothing to do. */
|
/* If both names are the same, there is nothing to do. */
|
||||||
if (STREQ(name_src, name_dst)) {
|
if (STREQ(name_src, name_dst)) {
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include "BLI_bit_ref.hh"
|
#include "BLI_bit_ref.hh"
|
||||||
#include "BLI_index_range.hh"
|
#include "BLI_index_range.hh"
|
||||||
#include "BLI_math_bits.h"
|
#include "BLI_math_bits.h"
|
||||||
|
@ -129,6 +131,72 @@ class BitSpan {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the span fullfills the requirements for a bounded span. Bounded spans can often be
|
||||||
|
* processed more efficiently, because fewer cases have to be considered when aligning multiple
|
||||||
|
* such spans.
|
||||||
|
*
|
||||||
|
* See comments in the function for the exact requirements.
|
||||||
|
*/
|
||||||
|
inline bool is_bounded_span(const BitSpan span)
|
||||||
|
{
|
||||||
|
const int64_t offset = span.bit_range().start();
|
||||||
|
const int64_t size = span.size();
|
||||||
|
if (offset >= BitsPerInt) {
|
||||||
|
/* The data pointer must point at the first int already. If the offset is a multiple of
|
||||||
|
* #BitsPerInt, the bit span could theoretically become bounded as well if the data pointer is
|
||||||
|
* adjusted. But that is not handled here. */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (size < BitsPerInt) {
|
||||||
|
/** Don't allow small sized spans to cross `BitInt` boundaries. */
|
||||||
|
return offset + size <= 64;
|
||||||
|
}
|
||||||
|
if (offset != 0) {
|
||||||
|
/* Start of larger spans must be aligned to `BitInt` boundaries. */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as #BitSpan but fullfills the requirements mentioned on #is_bounded_span.
|
||||||
|
*/
|
||||||
|
class BoundedBitSpan : public BitSpan {
|
||||||
|
public:
|
||||||
|
BoundedBitSpan() = default;
|
||||||
|
|
||||||
|
BoundedBitSpan(const BitInt *data, const int64_t size_in_bits) : BitSpan(data, size_in_bits)
|
||||||
|
{
|
||||||
|
BLI_assert(is_bounded_span(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
BoundedBitSpan(const BitInt *data, const IndexRange bit_range) : BitSpan(data, bit_range)
|
||||||
|
{
|
||||||
|
BLI_assert(is_bounded_span(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit BoundedBitSpan(const BitSpan other) : BitSpan(other)
|
||||||
|
{
|
||||||
|
BLI_assert(is_bounded_span(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t offset() const
|
||||||
|
{
|
||||||
|
return bit_range_.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t full_ints_num() const
|
||||||
|
{
|
||||||
|
return bit_range_.size() >> BitToIntIndexShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t final_bits_num() const
|
||||||
|
{
|
||||||
|
return bit_range_.size() & BitIndexMask;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/** Same as #BitSpan, but also allows modifying the referenced bits. */
|
/** Same as #BitSpan, but also allows modifying the referenced bits. */
|
||||||
class MutableBitSpan {
|
class MutableBitSpan {
|
||||||
protected:
|
protected:
|
||||||
|
@ -200,6 +268,9 @@ class MutableBitSpan {
|
||||||
/** Sets all referenced bits to 0. */
|
/** Sets all referenced bits to 0. */
|
||||||
void reset_all();
|
void reset_all();
|
||||||
|
|
||||||
|
void copy_from(const BitSpan other);
|
||||||
|
void copy_from(const BoundedBitSpan other);
|
||||||
|
|
||||||
/** Sets all referenced bits to either 0 or 1. */
|
/** Sets all referenced bits to either 0 or 1. */
|
||||||
void set_all(const bool value)
|
void set_all(const bool value)
|
||||||
{
|
{
|
||||||
|
@ -218,71 +289,6 @@ class MutableBitSpan {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the span fullfills the requirements for a bounded span. Bounded spans can often be
|
|
||||||
* processed more efficiently, because fewer cases have to be considered when aligning multiple
|
|
||||||
* such spans.
|
|
||||||
*
|
|
||||||
* See comments in the function for the exact requirements.
|
|
||||||
*/
|
|
||||||
inline bool is_bounded_span(const BitSpan data)
|
|
||||||
{
|
|
||||||
const int64_t offset = data.bit_range().start();
|
|
||||||
const int64_t size = data.size();
|
|
||||||
if (offset >= BitsPerInt) {
|
|
||||||
/* The data pointer must point at the first int already. In general it's ok not to enforce
|
|
||||||
* this, because it might just add overhead when e.g. slicing a span. */
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (size < BitsPerInt) {
|
|
||||||
/** Don't allow small sized spans to cross `BitInt` boundaries. */
|
|
||||||
return offset + size <= 64;
|
|
||||||
}
|
|
||||||
if (offset != 0) {
|
|
||||||
/* Start of larger spans must be aligned to `BitInt` boundaries. */
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Same as #BitSpan but fullfills the requirements mentioned on #is_bounded_span.
|
|
||||||
*/
|
|
||||||
class BoundedBitSpan : public BitSpan {
|
|
||||||
public:
|
|
||||||
BoundedBitSpan() = default;
|
|
||||||
|
|
||||||
BoundedBitSpan(const BitInt *data, const int64_t size_in_bits) : BitSpan(data, size_in_bits)
|
|
||||||
{
|
|
||||||
BLI_assert(is_bounded_span(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
BoundedBitSpan(const BitInt *data, const IndexRange bit_range) : BitSpan(data, bit_range)
|
|
||||||
{
|
|
||||||
BLI_assert(is_bounded_span(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit BoundedBitSpan(const BitSpan other) : BitSpan(other)
|
|
||||||
{
|
|
||||||
BLI_assert(is_bounded_span(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t offset() const
|
|
||||||
{
|
|
||||||
return bit_range_.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t full_ints_num() const
|
|
||||||
{
|
|
||||||
return bit_range_.size() >> BitToIntIndexShift;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t final_bits_num() const
|
|
||||||
{
|
|
||||||
return bit_range_.size() & BitIndexMask;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as #MutableBitSpan but fullfills the requirements mentioned on #is_bounded_span.
|
* Same as #MutableBitSpan but fullfills the requirements mentioned on #is_bounded_span.
|
||||||
*/
|
*/
|
||||||
|
@ -324,12 +330,26 @@ class MutableBoundedBitSpan : public MutableBitSpan {
|
||||||
{
|
{
|
||||||
return bit_range_.size() & BitIndexMask;
|
return bit_range_.size() & BitIndexMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void copy_from(const BitSpan other);
|
||||||
|
void copy_from(const BoundedBitSpan other);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline std::optional<BoundedBitSpan> try_get_bounded_span(const BitSpan span)
|
||||||
|
{
|
||||||
|
if (is_bounded_span(span)) {
|
||||||
|
return BoundedBitSpan(span);
|
||||||
|
}
|
||||||
|
if (span.bit_range().start() % BitsPerInt == 0) {
|
||||||
|
return BoundedBitSpan(span.data() + (span.bit_range().start() >> BitToIntIndexShift),
|
||||||
|
span.size());
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is overloaded in BLI_bit_vector.hh. The purpose is to make passing #BitVector into bit span
|
* Overloaded in BLI_bit_vector.hh. The purpose is to make passing #BitVector into bit span
|
||||||
* operations more simpler and efficient (interpreting it as `BoundedBitSpan` instead of just
|
* operations more efficient (interpreting it as `BoundedBitSpan` instead of just `BitSpan`).
|
||||||
* `BitSpan`).
|
|
||||||
*/
|
*/
|
||||||
template<typename T> inline T to_best_bit_span(const T &data)
|
template<typename T> inline T to_best_bit_span(const T &data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
namespace blender::bits {
|
namespace blender::bits {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluates the expression on one or more bit spans and stores the result in the first.
|
* Evaluates the expression on one or more bit spans and stores the result in the first.
|
||||||
*
|
*
|
||||||
|
@ -129,6 +130,7 @@ inline void foreach_1_index_expr(ExprFn &&expr,
|
||||||
BitInt tmp = expr(first_data[int_i], args.data()[int_i]...);
|
BitInt tmp = expr(first_data[int_i], args.data()[int_i]...);
|
||||||
const int64_t offset = int_i << BitToIntIndexShift;
|
const int64_t offset = int_i << BitToIntIndexShift;
|
||||||
while (tmp != 0) {
|
while (tmp != 0) {
|
||||||
|
static_assert(std::is_same_v<BitInt, uint64_t>);
|
||||||
const int index = bitscan_forward_uint64(tmp);
|
const int index = bitscan_forward_uint64(tmp);
|
||||||
handle(index + offset);
|
handle(index + offset);
|
||||||
tmp &= ~mask_single_bit(index);
|
tmp &= ~mask_single_bit(index);
|
||||||
|
@ -141,6 +143,7 @@ inline void foreach_1_index_expr(ExprFn &&expr,
|
||||||
mask_first_n_bits(final_bits);
|
mask_first_n_bits(final_bits);
|
||||||
const int64_t offset = full_ints_num << BitToIntIndexShift;
|
const int64_t offset = full_ints_num << BitToIntIndexShift;
|
||||||
while (tmp != 0) {
|
while (tmp != 0) {
|
||||||
|
static_assert(std::is_same_v<BitInt, uint64_t>);
|
||||||
const int index = bitscan_forward_uint64(tmp);
|
const int index = bitscan_forward_uint64(tmp);
|
||||||
handle(index + offset);
|
handle(index + offset);
|
||||||
tmp &= ~mask_single_bit(index);
|
tmp &= ~mask_single_bit(index);
|
||||||
|
@ -191,6 +194,13 @@ inline void inplace_or(FirstBitSpanT &first_arg, const BitSpanT &...args)
|
||||||
mix_into_first_expr([](const auto... x) { return (x | ...); }, first_arg, args...);
|
mix_into_first_expr([](const auto... x) { return (x | ...); }, first_arg, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename FirstBitSpanT, typename... BitSpanT>
|
||||||
|
inline void copy_from_or(FirstBitSpanT &first_arg, const BitSpanT &...args)
|
||||||
|
{
|
||||||
|
mix_into_first_expr(
|
||||||
|
[](auto /*first*/, auto... rest) { return (rest | ...); }, first_arg, args...);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename FirstBitSpanT, typename... BitSpanT>
|
template<typename FirstBitSpanT, typename... BitSpanT>
|
||||||
inline void inplace_and(FirstBitSpanT &first_arg, const BitSpanT &...args)
|
inline void inplace_and(FirstBitSpanT &first_arg, const BitSpanT &...args)
|
||||||
{
|
{
|
||||||
|
|
|
@ -311,14 +311,20 @@ bool BLI_path_filename_ensure(char *filepath, size_t maxlen, const char *filenam
|
||||||
*/
|
*/
|
||||||
int BLI_path_sequence_decode(const char *string,
|
int BLI_path_sequence_decode(const char *string,
|
||||||
char *head,
|
char *head,
|
||||||
|
size_t head_maxncpy,
|
||||||
char *tail,
|
char *tail,
|
||||||
|
size_t tail_maxncpy,
|
||||||
unsigned short *r_digits_len);
|
unsigned short *r_digits_len);
|
||||||
/**
|
/**
|
||||||
* Returns in area pointed to by string a string of the form `<head><pic><tail>`,
|
* Returns in area pointed to by string a string of the form `<head><pic><tail>`,
|
||||||
* where pic is formatted as `numlen` digits with leading zeroes.
|
* where pic is formatted as `numlen` digits with leading zeroes.
|
||||||
*/
|
*/
|
||||||
void BLI_path_sequence_encode(
|
void BLI_path_sequence_encode(char *string,
|
||||||
char *string, const char *head, const char *tail, unsigned short numlen, int pic);
|
size_t string_maxncpy,
|
||||||
|
const char *head,
|
||||||
|
const char *tail,
|
||||||
|
unsigned short numlen,
|
||||||
|
int pic);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove redundant characters from \a path.
|
* Remove redundant characters from \a path.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
#include "BLI_bit_span.hh"
|
#include "BLI_bit_span.hh"
|
||||||
|
#include "BLI_bit_span_ops.hh"
|
||||||
|
|
||||||
namespace blender::bits {
|
namespace blender::bits {
|
||||||
|
|
||||||
|
@ -54,6 +55,30 @@ void MutableBitSpan::reset_all()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MutableBitSpan::copy_from(const BitSpan other)
|
||||||
|
{
|
||||||
|
BLI_assert(this->size() == other.size());
|
||||||
|
copy_from_or(*this, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MutableBitSpan::copy_from(const BoundedBitSpan other)
|
||||||
|
{
|
||||||
|
BLI_assert(this->size() == other.size());
|
||||||
|
copy_from_or(*this, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MutableBoundedBitSpan::copy_from(const BitSpan other)
|
||||||
|
{
|
||||||
|
BLI_assert(this->size() == other.size());
|
||||||
|
copy_from_or(*this, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MutableBoundedBitSpan::copy_from(const BoundedBitSpan other)
|
||||||
|
{
|
||||||
|
BLI_assert(this->size() == other.size());
|
||||||
|
copy_from_or(*this, other);
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &stream, const BitSpan &span)
|
std::ostream &operator<<(std::ostream &stream, const BitSpan &span)
|
||||||
{
|
{
|
||||||
stream << "(Size: " << span.size() << ", ";
|
stream << "(Size: " << span.size() << ", ";
|
||||||
|
|
|
@ -47,8 +47,22 @@ static bool BLI_path_is_abs_win32(const char *name);
|
||||||
|
|
||||||
// #define DEBUG_STRSIZE
|
// #define DEBUG_STRSIZE
|
||||||
|
|
||||||
int BLI_path_sequence_decode(const char *string, char *head, char *tail, ushort *r_digits_len)
|
int BLI_path_sequence_decode(const char *string,
|
||||||
|
char *head,
|
||||||
|
const size_t head_maxncpy,
|
||||||
|
char *tail,
|
||||||
|
const size_t tail_maxncpy,
|
||||||
|
ushort *r_digits_len)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG_STRSIZE
|
||||||
|
if (head) {
|
||||||
|
memset(head, 0xff, sizeof(*head) * head_maxncpy);
|
||||||
|
}
|
||||||
|
if (tail) {
|
||||||
|
memset(tail, 0xff, sizeof(*tail) * tail_maxncpy);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
uint nums = 0, nume = 0;
|
uint nums = 0, nume = 0;
|
||||||
int i;
|
int i;
|
||||||
bool found_digit = false;
|
bool found_digit = false;
|
||||||
|
@ -82,8 +96,7 @@ int BLI_path_sequence_decode(const char *string, char *head, char *tail, ushort
|
||||||
strcpy(tail, &string[nume + 1]);
|
strcpy(tail, &string[nume + 1]);
|
||||||
}
|
}
|
||||||
if (head) {
|
if (head) {
|
||||||
strcpy(head, string);
|
BLI_strncpy(head, string, MIN2(head_maxncpy, nums + 1));
|
||||||
head[nums] = 0;
|
|
||||||
}
|
}
|
||||||
if (r_digits_len) {
|
if (r_digits_len) {
|
||||||
*r_digits_len = nume - nums + 1;
|
*r_digits_len = nume - nums + 1;
|
||||||
|
@ -93,7 +106,7 @@ int BLI_path_sequence_decode(const char *string, char *head, char *tail, ushort
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tail) {
|
if (tail) {
|
||||||
strcpy(tail, string + name_end);
|
BLI_strncpy(tail, string + name_end, tail_maxncpy);
|
||||||
}
|
}
|
||||||
if (head) {
|
if (head) {
|
||||||
/* Name_end points to last character of head,
|
/* Name_end points to last character of head,
|
||||||
|
@ -106,10 +119,17 @@ int BLI_path_sequence_decode(const char *string, char *head, char *tail, ushort
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BLI_path_sequence_encode(
|
void BLI_path_sequence_encode(char *string,
|
||||||
char *string, const char *head, const char *tail, ushort numlen, int pic)
|
const size_t string_maxncpy,
|
||||||
|
const char *head,
|
||||||
|
const char *tail,
|
||||||
|
ushort numlen,
|
||||||
|
int pic)
|
||||||
{
|
{
|
||||||
BLI_sprintf(string, "%s%.*d%s", head, numlen, MAX2(0, pic), tail);
|
#ifdef DEBUG_STRSIZE
|
||||||
|
memset(string, 0xff, sizeof(*string) * string_maxncpy);
|
||||||
|
#endif
|
||||||
|
BLI_snprintf(string, string_maxncpy, "%s%.*d%s", head, numlen, MAX2(0, pic), tail);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BLI_path_normalize(char *path)
|
void BLI_path_normalize(char *path)
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "BLI_bit_span.hh"
|
#include "BLI_bit_span.hh"
|
||||||
|
#include "BLI_bit_span_ops.hh"
|
||||||
|
#include "BLI_timeit.hh"
|
||||||
|
#include "BLI_vector.hh"
|
||||||
|
|
||||||
#include "testing/testing.h"
|
#include "testing/testing.h"
|
||||||
|
|
||||||
|
@ -159,14 +162,88 @@ TEST(bit_span, IsBounded)
|
||||||
EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), IndexRange(1, 3))));
|
EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), IndexRange(1, 3))));
|
||||||
EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), IndexRange(10, 20))));
|
EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), IndexRange(10, 20))));
|
||||||
EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), IndexRange(63, 1))));
|
EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), IndexRange(63, 1))));
|
||||||
EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), IndexRange(64, 0))));
|
|
||||||
EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), IndexRange(10, 54))));
|
EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), IndexRange(10, 54))));
|
||||||
|
|
||||||
EXPECT_FALSE(is_bounded_span(BitSpan(data.data(), IndexRange(1, 64))));
|
EXPECT_FALSE(is_bounded_span(BitSpan(data.data(), IndexRange(1, 64))));
|
||||||
EXPECT_FALSE(is_bounded_span(BitSpan(data.data(), IndexRange(10, 64))));
|
EXPECT_FALSE(is_bounded_span(BitSpan(data.data(), IndexRange(10, 64))));
|
||||||
EXPECT_FALSE(is_bounded_span(BitSpan(data.data(), IndexRange(10, 200))));
|
EXPECT_FALSE(is_bounded_span(BitSpan(data.data(), IndexRange(10, 200))));
|
||||||
EXPECT_FALSE(is_bounded_span(BitSpan(data.data(), IndexRange(60, 5))));
|
EXPECT_FALSE(is_bounded_span(BitSpan(data.data(), IndexRange(60, 5))));
|
||||||
|
EXPECT_FALSE(is_bounded_span(BitSpan(data.data(), IndexRange(64, 0))));
|
||||||
EXPECT_FALSE(is_bounded_span(BitSpan(data.data(), IndexRange(70, 5))));
|
EXPECT_FALSE(is_bounded_span(BitSpan(data.data(), IndexRange(70, 5))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(bit_span, CopyFrom)
|
||||||
|
{
|
||||||
|
std::array<uint64_t, 30> src_data;
|
||||||
|
uint64_t i = 0;
|
||||||
|
for (uint64_t &value : src_data) {
|
||||||
|
value = i;
|
||||||
|
i += 234589766883;
|
||||||
|
}
|
||||||
|
const BitSpan src(src_data.data(), src_data.size() * BitsPerInt);
|
||||||
|
|
||||||
|
std::array<uint64_t, 4> dst_data;
|
||||||
|
dst_data.fill(-1);
|
||||||
|
MutableBitSpan dst(dst_data.data(), 100);
|
||||||
|
dst.copy_from(src.slice({401, 100}));
|
||||||
|
|
||||||
|
for (const int i : dst.index_range()) {
|
||||||
|
EXPECT_TRUE(dst[i].test() == src[401 + i].test());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(bit_span, InPlaceOr)
|
||||||
|
{
|
||||||
|
std::array<uint64_t, 100> data_1;
|
||||||
|
MutableBitSpan span_1(data_1.data(), data_1.size() * BitsPerInt);
|
||||||
|
for (const int i : span_1.index_range()) {
|
||||||
|
span_1[i].set(i % 2 == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<uint64_t, 100> data_2;
|
||||||
|
MutableBitSpan span_2(data_2.data(), data_2.size() * BitsPerInt);
|
||||||
|
for (const int i : span_2.index_range()) {
|
||||||
|
span_2[i].set(i % 2 != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
span_1 |= span_2;
|
||||||
|
for (const int i : span_1.index_range()) {
|
||||||
|
EXPECT_TRUE(span_1[i].test());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(bit_span, InPlaceAnd)
|
||||||
|
{
|
||||||
|
std::array<uint64_t, 100> data_1;
|
||||||
|
MutableBitSpan span_1(data_1.data(), data_1.size() * BitsPerInt);
|
||||||
|
for (const int i : span_1.index_range()) {
|
||||||
|
span_1[i].set(i % 2 == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<uint64_t, 100> data_2;
|
||||||
|
MutableBitSpan span_2(data_2.data(), data_2.size() * BitsPerInt);
|
||||||
|
for (const int i : span_2.index_range()) {
|
||||||
|
span_2[i].set(i % 2 != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
span_1 &= span_2;
|
||||||
|
for (const int i : span_1.index_range()) {
|
||||||
|
EXPECT_FALSE(span_1[i].test());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(bit_span, ForEach1)
|
||||||
|
{
|
||||||
|
std::array<uint64_t, 2> data{};
|
||||||
|
MutableBitSpan span(data.data(), data.size() * BitsPerInt);
|
||||||
|
for (const int i : {1, 28, 37, 86}) {
|
||||||
|
span[i].set();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<int> indices_test;
|
||||||
|
foreach_1_index(span.slice({4, span.size() - 4}), [&](const int i) { indices_test.append(i); });
|
||||||
|
|
||||||
|
EXPECT_EQ(indices_test.as_span(), Span({24, 33, 82}));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace blender::bits::tests
|
} // namespace blender::bits::tests
|
||||||
|
|
|
@ -1059,7 +1059,8 @@ TEST(path_util, FrameGet)
|
||||||
char head[FILE_MAX]; \
|
char head[FILE_MAX]; \
|
||||||
char tail[FILE_MAX]; \
|
char tail[FILE_MAX]; \
|
||||||
ushort numdigits = 0; \
|
ushort numdigits = 0; \
|
||||||
const int result = BLI_path_sequence_decode(path, head, tail, &numdigits); \
|
const int result = BLI_path_sequence_decode( \
|
||||||
|
path, head, sizeof(head), tail, sizeof(tail), &numdigits); \
|
||||||
EXPECT_EQ(result, expect_result); \
|
EXPECT_EQ(result, expect_result); \
|
||||||
EXPECT_STREQ(head, expect_head); \
|
EXPECT_STREQ(head, expect_head); \
|
||||||
EXPECT_STREQ(tail, expect_tail); \
|
EXPECT_STREQ(tail, expect_tail); \
|
||||||
|
|
|
@ -1047,10 +1047,12 @@ class StringEscape : public testing::Test {
|
||||||
void testEscapeWords(const CompareWordsArray &items)
|
void testEscapeWords(const CompareWordsArray &items)
|
||||||
{
|
{
|
||||||
size_t dst_test_len;
|
size_t dst_test_len;
|
||||||
char dst_test[64];
|
char dst_test[64]; /* Must be big enough for all input. */
|
||||||
for (const auto &item : items) {
|
for (const auto &item : items) {
|
||||||
|
/* Validate the static size is big enough (test the test it's self). */
|
||||||
|
EXPECT_LT((strlen(item[0]) * 2) + 1, sizeof(dst_test));
|
||||||
/* Escape the string. */
|
/* Escape the string. */
|
||||||
dst_test_len = BLI_str_escape(dst_test, item[0], SIZE_MAX);
|
dst_test_len = BLI_str_escape(dst_test, item[0], sizeof(dst_test));
|
||||||
EXPECT_STREQ(dst_test, item[1]);
|
EXPECT_STREQ(dst_test, item[1]);
|
||||||
EXPECT_EQ(dst_test_len, strlen(dst_test));
|
EXPECT_EQ(dst_test_len, strlen(dst_test));
|
||||||
/* Escape back. */
|
/* Escape back. */
|
||||||
|
|
|
@ -428,10 +428,9 @@ static void do_version_layers_to_collections(Main *bmain, Scene *scene)
|
||||||
if (base->lay & (1 << layer)) {
|
if (base->lay & (1 << layer)) {
|
||||||
/* Create collections when needed only. */
|
/* Create collections when needed only. */
|
||||||
if (collections[layer] == NULL) {
|
if (collections[layer] == NULL) {
|
||||||
char name[MAX_NAME];
|
char name[MAX_ID_NAME - 2];
|
||||||
|
|
||||||
BLI_snprintf(
|
BLI_snprintf(name, sizeof(name), DATA_("Collection %d"), layer + 1);
|
||||||
name, sizeof(collection_master->id.name), DATA_("Collection %d"), layer + 1);
|
|
||||||
|
|
||||||
Collection *collection = BKE_collection_add(bmain, collection_master, name);
|
Collection *collection = BKE_collection_add(bmain, collection_master, name);
|
||||||
collection->id.lib = scene->id.lib;
|
collection->id.lib = scene->id.lib;
|
||||||
|
|
|
@ -1263,8 +1263,7 @@ void do_versions_after_linking_300(FileData * /*fd*/, Main *bmain)
|
||||||
/* Ensure tiled image sources contain a UDIM token. */
|
/* Ensure tiled image sources contain a UDIM token. */
|
||||||
LISTBASE_FOREACH (Image *, ima, &bmain->images) {
|
LISTBASE_FOREACH (Image *, ima, &bmain->images) {
|
||||||
if (ima->source == IMA_SRC_TILED) {
|
if (ima->source == IMA_SRC_TILED) {
|
||||||
char *filename = (char *)BLI_path_basename(ima->filepath);
|
BKE_image_ensure_tile_token(ima->filepath, sizeof(ima->filepath));
|
||||||
BKE_image_ensure_tile_token(filename);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2975,7 +2975,7 @@ static void filenum_newname(char *name, size_t name_size, int add)
|
||||||
int pic;
|
int pic;
|
||||||
ushort digits;
|
ushort digits;
|
||||||
|
|
||||||
pic = BLI_path_sequence_decode(name, head, tail, &digits);
|
pic = BLI_path_sequence_decode(name, head, sizeof(head), tail, sizeof(tail), &digits);
|
||||||
|
|
||||||
/* are we going from 100 -> 99 or from 10 -> 9 */
|
/* are we going from 100 -> 99 or from 10 -> 9 */
|
||||||
if (add < 0 && digits > 0) {
|
if (add < 0 && digits > 0) {
|
||||||
|
@ -2993,7 +2993,7 @@ static void filenum_newname(char *name, size_t name_size, int add)
|
||||||
if (pic < 0) {
|
if (pic < 0) {
|
||||||
pic = 0;
|
pic = 0;
|
||||||
}
|
}
|
||||||
BLI_path_sequence_encode(name_temp, head, tail, digits, pic);
|
BLI_path_sequence_encode(name_temp, sizeof(name_temp), head, tail, digits, pic);
|
||||||
BLI_strncpy(name, name_temp, name_size);
|
BLI_strncpy(name, name_temp, name_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1586,8 +1586,7 @@ static int image_file_browse_exec(bContext *C, wmOperator *op)
|
||||||
|
|
||||||
/* If loading into a tiled texture, ensure that the filename is tokenized. */
|
/* If loading into a tiled texture, ensure that the filename is tokenized. */
|
||||||
if (ima->source == IMA_SRC_TILED) {
|
if (ima->source == IMA_SRC_TILED) {
|
||||||
char *filename = (char *)BLI_path_basename(filepath);
|
BKE_image_ensure_tile_token(filepath, sizeof(filepath));
|
||||||
BKE_image_ensure_tile_token(filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PointerRNA imaptr;
|
PointerRNA imaptr;
|
||||||
|
|
|
@ -55,7 +55,8 @@ static void image_sequence_get_frame_ranges(wmOperator *op, ListBase *ranges)
|
||||||
ImageFrame *frame = MEM_callocN(sizeof(ImageFrame), "image_frame");
|
ImageFrame *frame = MEM_callocN(sizeof(ImageFrame), "image_frame");
|
||||||
|
|
||||||
/* use the first file in the list as base filename */
|
/* use the first file in the list as base filename */
|
||||||
frame->framenr = BLI_path_sequence_decode(filename, head, tail, &digits);
|
frame->framenr = BLI_path_sequence_decode(
|
||||||
|
filename, head, sizeof(head), tail, sizeof(tail), &digits);
|
||||||
|
|
||||||
/* still in the same sequence */
|
/* still in the same sequence */
|
||||||
if (do_frame_range && (range != NULL) && STREQLEN(base_head, head, FILE_MAX) &&
|
if (do_frame_range && (range != NULL) && STREQLEN(base_head, head, FILE_MAX) &&
|
||||||
|
|
|
@ -856,10 +856,12 @@ float ED_view3d_grid_scale(const Scene *scene, View3D *v3d, const char **r_grid_
|
||||||
}
|
}
|
||||||
|
|
||||||
#define STEPS_LEN 8
|
#define STEPS_LEN 8
|
||||||
void ED_view3d_grid_steps(const Scene *scene,
|
static void view3d_grid_steps_ex(const Scene *scene,
|
||||||
View3D *v3d,
|
View3D *v3d,
|
||||||
RegionView3D *rv3d,
|
RegionView3D *rv3d,
|
||||||
float r_grid_steps[STEPS_LEN])
|
float r_grid_steps[STEPS_LEN],
|
||||||
|
void const **r_usys_pt,
|
||||||
|
int *r_len)
|
||||||
{
|
{
|
||||||
const void *usys;
|
const void *usys;
|
||||||
int len;
|
int len;
|
||||||
|
@ -881,7 +883,7 @@ void ED_view3d_grid_steps(const Scene *scene,
|
||||||
}
|
}
|
||||||
for (; i < STEPS_LEN; i++) {
|
for (; i < STEPS_LEN; i++) {
|
||||||
/* Fill last slots */
|
/* Fill last slots */
|
||||||
r_grid_steps[i] = 10.0f * r_grid_steps[i - 1];
|
r_grid_steps[i] = r_grid_steps[len - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -899,6 +901,20 @@ void ED_view3d_grid_steps(const Scene *scene,
|
||||||
subdiv *= v3d->gridsubdiv;
|
subdiv *= v3d->gridsubdiv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (r_usys_pt) {
|
||||||
|
*r_usys_pt = usys;
|
||||||
|
}
|
||||||
|
if (r_len) {
|
||||||
|
*r_len = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ED_view3d_grid_steps(const Scene *scene,
|
||||||
|
View3D *v3d,
|
||||||
|
RegionView3D *rv3d,
|
||||||
|
float r_grid_steps[STEPS_LEN])
|
||||||
|
{
|
||||||
|
view3d_grid_steps_ex(scene, v3d, rv3d, r_grid_steps, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
float ED_view3d_grid_view_scale(Scene *scene,
|
float ED_view3d_grid_view_scale(Scene *scene,
|
||||||
|
@ -912,23 +928,20 @@ float ED_view3d_grid_view_scale(Scene *scene,
|
||||||
/* Decrease the distance between grid snap points depending on zoom. */
|
/* Decrease the distance between grid snap points depending on zoom. */
|
||||||
float dist = 12.0f / (region->sizex * rv3d->winmat[0][0]);
|
float dist = 12.0f / (region->sizex * rv3d->winmat[0][0]);
|
||||||
float grid_steps[STEPS_LEN];
|
float grid_steps[STEPS_LEN];
|
||||||
ED_view3d_grid_steps(scene, v3d, rv3d, grid_steps);
|
const void *usys;
|
||||||
/* Skip last item, in case the 'mid_dist' is greater than the largest unit. */
|
int grid_steps_len;
|
||||||
int i;
|
view3d_grid_steps_ex(scene, v3d, rv3d, grid_steps, &usys, &grid_steps_len);
|
||||||
for (i = 0; i < ARRAY_SIZE(grid_steps) - 1; i++) {
|
int i = 0;
|
||||||
|
while (true) {
|
||||||
grid_scale = grid_steps[i];
|
grid_scale = grid_steps[i];
|
||||||
if (grid_scale > dist) {
|
if (grid_scale > dist || i == (grid_steps_len - 1)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r_grid_unit) {
|
if (r_grid_unit && usys) {
|
||||||
const void *usys;
|
*r_grid_unit = IFACE_(BKE_unit_display_name_get(usys, grid_steps_len - i - 1));
|
||||||
int len;
|
|
||||||
BKE_unit_system_get(scene->unit.system, B_UNIT_LENGTH, &usys, &len);
|
|
||||||
if (usys && i < len) {
|
|
||||||
*r_grid_unit = IFACE_(BKE_unit_display_name_get(usys, len - i - 1));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -43,8 +43,44 @@
|
||||||
|
|
||||||
#include "view3d_navigate.h" /* own include */
|
#include "view3d_navigate.h" /* own include */
|
||||||
|
|
||||||
|
/* Prototypes. */
|
||||||
|
static void viewops_data_init_context(bContext *C, ViewOpsData *vod);
|
||||||
|
static void viewops_data_init_navigation(bContext *C,
|
||||||
|
const wmEvent *event,
|
||||||
|
const eV3D_OpMode nav_type,
|
||||||
|
const bool use_cursor_init,
|
||||||
|
ViewOpsData *vod);
|
||||||
|
static void viewops_data_end_navigation(bContext *C, ViewOpsData *vod);
|
||||||
|
static int viewpan_invoke_impl(ViewOpsData *vod, PointerRNA *ptr);
|
||||||
|
|
||||||
|
const char *viewops_operator_idname_get(eV3D_OpMode nav_type)
|
||||||
|
{
|
||||||
|
switch (nav_type) {
|
||||||
|
case V3D_OP_MODE_ZOOM:
|
||||||
|
return "VIEW3D_OT_zoom";
|
||||||
|
case V3D_OP_MODE_ROTATE:
|
||||||
|
return "VIEW3D_OT_rotate";
|
||||||
|
case V3D_OP_MODE_MOVE:
|
||||||
|
return "VIEW3D_OT_move";
|
||||||
|
case V3D_OP_MODE_VIEW_PAN:
|
||||||
|
return "VIEW3D_OT_view_pan";
|
||||||
|
case V3D_OP_MODE_VIEW_ROLL:
|
||||||
|
return "VIEW3D_OT_view_roll";
|
||||||
|
case V3D_OP_MODE_DOLLY:
|
||||||
|
return "VIEW3D_OT_dolly";
|
||||||
|
#ifdef WITH_INPUT_NDOF
|
||||||
|
case V3D_OP_MODE_NDOF_ORBIT:
|
||||||
|
return "VIEW3D_OT_ndof_orbit";
|
||||||
|
case V3D_OP_MODE_NDOF_ORBIT_ZOOM:
|
||||||
|
return "VIEW3D_OT_ndof_orbit_zoom";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
BLI_assert(false);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/** \name Navigation Polls
|
/** \name Generic Operator Callback Utils
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
static bool view3d_navigation_poll_impl(bContext *C, const char viewlock)
|
static bool view3d_navigation_poll_impl(bContext *C, const char viewlock)
|
||||||
|
@ -57,6 +93,128 @@ static bool view3d_navigation_poll_impl(bContext *C, const char viewlock)
|
||||||
return !(RV3D_LOCK_FLAGS(rv3d) & viewlock);
|
return !(RV3D_LOCK_FLAGS(rv3d) & viewlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static eV3D_OpEvent view3d_navigate_event(ViewOpsData *vod, const wmEvent *event)
|
||||||
|
{
|
||||||
|
if (event->type == EVT_MODAL_MAP) {
|
||||||
|
switch (event->val) {
|
||||||
|
case VIEW_MODAL_CONFIRM:
|
||||||
|
return VIEW_CONFIRM;
|
||||||
|
case VIEWROT_MODAL_AXIS_SNAP_ENABLE:
|
||||||
|
vod->axis_snap = true;
|
||||||
|
return VIEW_APPLY;
|
||||||
|
case VIEWROT_MODAL_AXIS_SNAP_DISABLE:
|
||||||
|
vod->rv3d->persp = vod->init.persp_with_auto_persp_applied;
|
||||||
|
vod->axis_snap = false;
|
||||||
|
return VIEW_APPLY;
|
||||||
|
case VIEWROT_MODAL_SWITCH_ZOOM:
|
||||||
|
case VIEWROT_MODAL_SWITCH_MOVE:
|
||||||
|
case VIEWROT_MODAL_SWITCH_ROTATE: {
|
||||||
|
const eV3D_OpMode nav_type_new = (event->val == VIEWROT_MODAL_SWITCH_ZOOM) ?
|
||||||
|
V3D_OP_MODE_ZOOM :
|
||||||
|
(event->val == VIEWROT_MODAL_SWITCH_MOVE) ?
|
||||||
|
V3D_OP_MODE_MOVE :
|
||||||
|
V3D_OP_MODE_ROTATE;
|
||||||
|
if (nav_type_new == vod->nav_type) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
vod->nav_type = nav_type_new;
|
||||||
|
return VIEW_APPLY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (event->type == TIMER && event->customdata == vod->timer) {
|
||||||
|
/* Zoom uses timer for continuous zoom. */
|
||||||
|
return VIEW_APPLY;
|
||||||
|
}
|
||||||
|
if (event->type == MOUSEMOVE) {
|
||||||
|
return VIEW_APPLY;
|
||||||
|
}
|
||||||
|
if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
|
||||||
|
return VIEW_CONFIRM;
|
||||||
|
}
|
||||||
|
if (event->type == EVT_ESCKEY && event->val == KM_PRESS) {
|
||||||
|
return VIEW_CANCEL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return VIEW_PASS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int view3d_navigation_modal(bContext *C,
|
||||||
|
ViewOpsData *vod,
|
||||||
|
const eV3D_OpEvent event_code,
|
||||||
|
const int xy[2])
|
||||||
|
{
|
||||||
|
switch (vod->nav_type) {
|
||||||
|
case V3D_OP_MODE_ZOOM:
|
||||||
|
return viewzoom_modal_impl(C, vod, event_code, xy);
|
||||||
|
case V3D_OP_MODE_ROTATE:
|
||||||
|
return viewrotate_modal_impl(C, vod, event_code, xy);
|
||||||
|
case V3D_OP_MODE_MOVE:
|
||||||
|
return viewmove_modal_impl(C, vod, event_code, xy);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int view3d_navigation_invoke_generic(bContext *C,
|
||||||
|
ViewOpsData *vod,
|
||||||
|
const wmEvent *event,
|
||||||
|
PointerRNA *ptr,
|
||||||
|
const eV3D_OpMode nav_type)
|
||||||
|
{
|
||||||
|
bool use_cursor_init = false;
|
||||||
|
if (PropertyRNA *prop = RNA_struct_find_property(ptr, "use_cursor_init")) {
|
||||||
|
use_cursor_init = RNA_property_boolean_get(ptr, prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
viewops_data_init_navigation(C, event, nav_type, use_cursor_init, vod);
|
||||||
|
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
|
||||||
|
|
||||||
|
switch (nav_type) {
|
||||||
|
case V3D_OP_MODE_ZOOM:
|
||||||
|
return viewzoom_invoke_impl(C, vod, event, ptr);
|
||||||
|
case V3D_OP_MODE_ROTATE:
|
||||||
|
return viewrotate_invoke_impl(vod, event);
|
||||||
|
case V3D_OP_MODE_MOVE:
|
||||||
|
return viewmove_invoke_impl(vod, event);
|
||||||
|
case V3D_OP_MODE_VIEW_PAN: {
|
||||||
|
return viewpan_invoke_impl(vod, ptr);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
int view3d_navigate_invoke_impl(bContext *C,
|
||||||
|
wmOperator *op,
|
||||||
|
const wmEvent *event,
|
||||||
|
const eV3D_OpMode nav_type)
|
||||||
|
{
|
||||||
|
ViewOpsData *vod = MEM_cnew<ViewOpsData>(__func__);
|
||||||
|
viewops_data_init_context(C, vod);
|
||||||
|
int ret = view3d_navigation_invoke_generic(C, vod, event, op->ptr, nav_type);
|
||||||
|
op->customdata = (void *)vod;
|
||||||
|
|
||||||
|
if (ret == OPERATOR_RUNNING_MODAL) {
|
||||||
|
WM_event_add_modal_handler(C, op);
|
||||||
|
return OPERATOR_RUNNING_MODAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
viewops_data_free(C, vod);
|
||||||
|
op->customdata = nullptr;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Generic Callbacks
|
||||||
|
* \{ */
|
||||||
|
|
||||||
bool view3d_location_poll(bContext *C)
|
bool view3d_location_poll(bContext *C)
|
||||||
{
|
{
|
||||||
return view3d_navigation_poll_impl(C, RV3D_LOCK_LOCATION);
|
return view3d_navigation_poll_impl(C, RV3D_LOCK_LOCATION);
|
||||||
|
@ -72,11 +230,32 @@ bool view3d_zoom_or_dolly_poll(bContext *C)
|
||||||
return view3d_navigation_poll_impl(C, RV3D_LOCK_ZOOM_AND_DOLLY);
|
return view3d_navigation_poll_impl(C, RV3D_LOCK_ZOOM_AND_DOLLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \} */
|
int view3d_navigate_modal_fn(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
|
{
|
||||||
|
ViewOpsData *vod = static_cast<ViewOpsData *>(op->customdata);
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
const eV3D_OpMode nav_type_prev = vod->nav_type;
|
||||||
/** \name Generic Callbacks
|
const eV3D_OpEvent event_code = view3d_navigate_event(vod, event);
|
||||||
* \{ */
|
if (nav_type_prev != vod->nav_type) {
|
||||||
|
wmOperatorType *ot_new = WM_operatortype_find(viewops_operator_idname_get(vod->nav_type),
|
||||||
|
false);
|
||||||
|
WM_operator_type_set(op, ot_new);
|
||||||
|
viewops_data_end_navigation(C, vod);
|
||||||
|
return view3d_navigation_invoke_generic(C, vod, event, op->ptr, vod->nav_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = view3d_navigation_modal(C, vod, event_code, event->xy);
|
||||||
|
|
||||||
|
if ((ret & OPERATOR_RUNNING_MODAL) == 0) {
|
||||||
|
if (ret & OPERATOR_FINISHED) {
|
||||||
|
ED_view3d_camera_lock_undo_push(op->type->name, vod->v3d, vod->rv3d, C);
|
||||||
|
}
|
||||||
|
viewops_data_free(C, vod);
|
||||||
|
op->customdata = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void view3d_navigate_cancel_fn(bContext *C, wmOperator *op)
|
void view3d_navigate_cancel_fn(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
|
@ -312,8 +491,12 @@ bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
|
||||||
return is_set;
|
return is_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum eViewOpsFlag viewops_flag_from_args(bool use_select, bool use_depth)
|
static eViewOpsFlag viewops_flag_from_prefs(void)
|
||||||
{
|
{
|
||||||
|
const bool use_select = (U.uiflag & USER_ORBIT_SELECTION) != 0;
|
||||||
|
const bool use_depth = (U.uiflag & VIEWOPS_FLAG_DEPTH_NAVIGATE) != 0;
|
||||||
|
const bool use_zoom_to_mouse = (U.uiflag & USER_ZOOM_TO_MOUSEPOS) != 0;
|
||||||
|
|
||||||
enum eViewOpsFlag flag = VIEWOPS_FLAG_NONE;
|
enum eViewOpsFlag flag = VIEWOPS_FLAG_NONE;
|
||||||
if (use_select) {
|
if (use_select) {
|
||||||
flag |= VIEWOPS_FLAG_ORBIT_SELECT;
|
flag |= VIEWOPS_FLAG_ORBIT_SELECT;
|
||||||
|
@ -321,20 +504,15 @@ static enum eViewOpsFlag viewops_flag_from_args(bool use_select, bool use_depth)
|
||||||
if (use_depth) {
|
if (use_depth) {
|
||||||
flag |= VIEWOPS_FLAG_DEPTH_NAVIGATE;
|
flag |= VIEWOPS_FLAG_DEPTH_NAVIGATE;
|
||||||
}
|
}
|
||||||
|
if (use_zoom_to_mouse) {
|
||||||
|
flag |= VIEWOPS_FLAG_ZOOM_TO_MOUSE;
|
||||||
|
}
|
||||||
|
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum eViewOpsFlag viewops_flag_from_prefs(void)
|
static void viewops_data_init_context(bContext *C, ViewOpsData *vod)
|
||||||
{
|
{
|
||||||
return viewops_flag_from_args((U.uiflag & USER_ORBIT_SELECTION) != 0,
|
|
||||||
(U.uiflag & USER_DEPTH_NAVIGATE) != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ViewOpsData *viewops_data_create(bContext *C, const wmEvent *event, enum eViewOpsFlag viewops_flag)
|
|
||||||
{
|
|
||||||
ViewOpsData *vod = MEM_cnew<ViewOpsData>(__func__);
|
|
||||||
|
|
||||||
/* Store data. */
|
/* Store data. */
|
||||||
vod->bmain = CTX_data_main(C);
|
vod->bmain = CTX_data_main(C);
|
||||||
vod->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
vod->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||||
|
@ -343,13 +521,46 @@ ViewOpsData *viewops_data_create(bContext *C, const wmEvent *event, enum eViewOp
|
||||||
vod->region = CTX_wm_region(C);
|
vod->region = CTX_wm_region(C);
|
||||||
vod->v3d = static_cast<View3D *>(vod->area->spacedata.first);
|
vod->v3d = static_cast<View3D *>(vod->area->spacedata.first);
|
||||||
vod->rv3d = static_cast<RegionView3D *>(vod->region->regiondata);
|
vod->rv3d = static_cast<RegionView3D *>(vod->region->regiondata);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void viewops_data_init_navigation(bContext *C,
|
||||||
|
const wmEvent *event,
|
||||||
|
const eV3D_OpMode nav_type,
|
||||||
|
const bool use_cursor_init,
|
||||||
|
ViewOpsData *vod)
|
||||||
|
{
|
||||||
Depsgraph *depsgraph = vod->depsgraph;
|
Depsgraph *depsgraph = vod->depsgraph;
|
||||||
RegionView3D *rv3d = vod->rv3d;
|
RegionView3D *rv3d = vod->rv3d;
|
||||||
|
|
||||||
|
eViewOpsFlag viewops_flag = viewops_flag_from_prefs();
|
||||||
|
|
||||||
|
if (use_cursor_init) {
|
||||||
|
viewops_flag |= VIEWOPS_FLAG_USE_MOUSE_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (nav_type) {
|
||||||
|
case V3D_OP_MODE_ZOOM:
|
||||||
|
case V3D_OP_MODE_MOVE:
|
||||||
|
case V3D_OP_MODE_VIEW_PAN:
|
||||||
|
case V3D_OP_MODE_DOLLY:
|
||||||
|
viewops_flag &= ~VIEWOPS_FLAG_ORBIT_SELECT;
|
||||||
|
break;
|
||||||
|
case V3D_OP_MODE_ROTATE:
|
||||||
|
viewops_flag |= VIEWOPS_FLAG_PERSP_ENSURE;
|
||||||
|
break;
|
||||||
|
#ifdef WITH_INPUT_NDOF
|
||||||
|
case V3D_OP_MODE_NDOF_ORBIT:
|
||||||
|
case V3D_OP_MODE_NDOF_ORBIT_ZOOM:
|
||||||
|
viewops_flag &= ~VIEWOPS_FLAG_DEPTH_NAVIGATE;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Could do this more nicely. */
|
/* Could do this more nicely. */
|
||||||
if ((viewops_flag & VIEWOPS_FLAG_USE_MOUSE_INIT) == 0) {
|
if ((viewops_flag & VIEWOPS_FLAG_USE_MOUSE_INIT) == 0) {
|
||||||
viewops_flag &= ~VIEWOPS_FLAG_DEPTH_NAVIGATE;
|
viewops_flag &= ~(VIEWOPS_FLAG_DEPTH_NAVIGATE | VIEWOPS_FLAG_ZOOM_TO_MOUSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we need the depth info before changing any viewport options */
|
/* we need the depth info before changing any viewport options */
|
||||||
|
@ -496,12 +707,27 @@ ViewOpsData *viewops_data_create(bContext *C, const wmEvent *event, enum eViewOp
|
||||||
vod->reverse = -1.0f;
|
vod->reverse = -1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv3d->rflag |= RV3D_NAVIGATING;
|
vod->nav_type = nav_type;
|
||||||
|
vod->viewops_flag = viewops_flag;
|
||||||
|
|
||||||
|
/* Default. */
|
||||||
|
vod->use_dyn_ofs_ortho_correction = false;
|
||||||
|
|
||||||
|
rv3d->rflag |= RV3D_NAVIGATING;
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewOpsData *viewops_data_create(bContext *C,
|
||||||
|
const wmEvent *event,
|
||||||
|
const eV3D_OpMode nav_type,
|
||||||
|
const bool use_cursor_init)
|
||||||
|
{
|
||||||
|
ViewOpsData *vod = MEM_cnew<ViewOpsData>(__func__);
|
||||||
|
viewops_data_init_context(C, vod);
|
||||||
|
viewops_data_init_navigation(C, event, nav_type, use_cursor_init, vod);
|
||||||
return vod;
|
return vod;
|
||||||
}
|
}
|
||||||
|
|
||||||
void viewops_data_free(bContext *C, ViewOpsData *vod)
|
static void viewops_data_end_navigation(bContext *C, ViewOpsData *vod)
|
||||||
{
|
{
|
||||||
ARegion *region;
|
ARegion *region;
|
||||||
if (vod) {
|
if (vod) {
|
||||||
|
@ -512,11 +738,7 @@ void viewops_data_free(bContext *C, ViewOpsData *vod)
|
||||||
WM_event_remove_timer(CTX_wm_manager(C), vod->timer->win, vod->timer);
|
WM_event_remove_timer(CTX_wm_manager(C), vod->timer->win, vod->timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vod->init.dial) {
|
MEM_SAFE_FREE(vod->init.dial);
|
||||||
MEM_freeN(vod->init.dial);
|
|
||||||
}
|
|
||||||
|
|
||||||
MEM_freeN(vod);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
region = CTX_wm_region(C);
|
region = CTX_wm_region(C);
|
||||||
|
@ -527,6 +749,14 @@ void viewops_data_free(bContext *C, ViewOpsData *vod)
|
||||||
ED_region_tag_redraw(region);
|
ED_region_tag_redraw(region);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void viewops_data_free(bContext *C, ViewOpsData *vod)
|
||||||
|
{
|
||||||
|
viewops_data_end_navigation(C, vod);
|
||||||
|
if (vod) {
|
||||||
|
MEM_freeN(vod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
@ -1658,10 +1888,10 @@ static const EnumPropertyItem prop_view_pan_items[] = {
|
||||||
{0, nullptr, 0, nullptr, nullptr},
|
{0, nullptr, 0, nullptr, nullptr},
|
||||||
};
|
};
|
||||||
|
|
||||||
static int viewpan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
static int viewpan_invoke_impl(ViewOpsData *vod, PointerRNA *ptr)
|
||||||
{
|
{
|
||||||
int x = 0, y = 0;
|
int x = 0, y = 0;
|
||||||
int pandir = RNA_enum_get(op->ptr, "type");
|
int pandir = RNA_enum_get(ptr, "type");
|
||||||
|
|
||||||
if (pandir == V3D_VIEW_PANRIGHT) {
|
if (pandir == V3D_VIEW_PANRIGHT) {
|
||||||
x = -32;
|
x = -32;
|
||||||
|
@ -1676,23 +1906,22 @@ static int viewpan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
y = 25;
|
y = 25;
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewOpsData *vod = viewops_data_create(
|
|
||||||
C, event, (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT));
|
|
||||||
|
|
||||||
viewmove_apply(vod, vod->prev.event_xy[0] + x, vod->prev.event_xy[1] + y);
|
viewmove_apply(vod, vod->prev.event_xy[0] + x, vod->prev.event_xy[1] + y);
|
||||||
|
|
||||||
ED_view3d_camera_lock_undo_push(op->type->name, vod->v3d, vod->rv3d, C);
|
|
||||||
viewops_data_free(C, vod);
|
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int viewpan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
|
{
|
||||||
|
return view3d_navigate_invoke_impl(C, op, event, V3D_OP_MODE_VIEW_PAN);
|
||||||
|
}
|
||||||
|
|
||||||
void VIEW3D_OT_view_pan(wmOperatorType *ot)
|
void VIEW3D_OT_view_pan(wmOperatorType *ot)
|
||||||
{
|
{
|
||||||
/* identifiers */
|
/* identifiers */
|
||||||
ot->name = "Pan View Direction";
|
ot->name = "Pan View Direction";
|
||||||
ot->description = "Pan the view in a given direction";
|
ot->description = "Pan the view in a given direction";
|
||||||
ot->idname = "VIEW3D_OT_view_pan";
|
ot->idname = viewops_operator_idname_get(V3D_OP_MODE_VIEW_PAN);
|
||||||
|
|
||||||
/* api callbacks */
|
/* api callbacks */
|
||||||
ot->invoke = viewpan_invoke;
|
ot->invoke = viewpan_invoke;
|
||||||
|
|
|
@ -32,6 +32,19 @@ struct rcti;
|
||||||
struct wmEvent;
|
struct wmEvent;
|
||||||
struct wmOperator;
|
struct wmOperator;
|
||||||
|
|
||||||
|
typedef enum eV3D_OpMode {
|
||||||
|
V3D_OP_MODE_ZOOM = 0,
|
||||||
|
V3D_OP_MODE_ROTATE,
|
||||||
|
V3D_OP_MODE_MOVE,
|
||||||
|
V3D_OP_MODE_VIEW_PAN,
|
||||||
|
V3D_OP_MODE_VIEW_ROLL,
|
||||||
|
V3D_OP_MODE_DOLLY,
|
||||||
|
#ifdef WITH_INPUT_NDOF
|
||||||
|
V3D_OP_MODE_NDOF_ORBIT,
|
||||||
|
V3D_OP_MODE_NDOF_ORBIT_ZOOM,
|
||||||
|
#endif
|
||||||
|
} eV3D_OpMode;
|
||||||
|
|
||||||
enum eV3D_OpPropFlag {
|
enum eV3D_OpPropFlag {
|
||||||
V3D_OP_PROP_MOUSE_CO = (1 << 0),
|
V3D_OP_PROP_MOUSE_CO = (1 << 0),
|
||||||
V3D_OP_PROP_DELTA = (1 << 1),
|
V3D_OP_PROP_DELTA = (1 << 1),
|
||||||
|
@ -39,13 +52,13 @@ enum eV3D_OpPropFlag {
|
||||||
V3D_OP_PROP_USE_MOUSE_INIT = (1 << 3),
|
V3D_OP_PROP_USE_MOUSE_INIT = (1 << 3),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
typedef enum eV3D_OpEvent {
|
||||||
VIEW_PASS = 0,
|
VIEW_PASS = 0,
|
||||||
VIEW_APPLY,
|
VIEW_APPLY,
|
||||||
VIEW_CONFIRM,
|
VIEW_CONFIRM,
|
||||||
/** Only supported by some viewport operators. */
|
/** Only supported by some viewport operators. */
|
||||||
VIEW_CANCEL,
|
VIEW_CANCEL,
|
||||||
};
|
} eV3D_OpEvent;
|
||||||
|
|
||||||
/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
|
/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
|
||||||
enum {
|
enum {
|
||||||
|
@ -58,7 +71,7 @@ enum {
|
||||||
VIEWROT_MODAL_SWITCH_ROTATE = 6,
|
VIEWROT_MODAL_SWITCH_ROTATE = 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum eViewOpsFlag {
|
typedef enum eViewOpsFlag {
|
||||||
VIEWOPS_FLAG_NONE = 0,
|
VIEWOPS_FLAG_NONE = 0,
|
||||||
/** When enabled, rotate around the selection. */
|
/** When enabled, rotate around the selection. */
|
||||||
VIEWOPS_FLAG_ORBIT_SELECT = (1 << 0),
|
VIEWOPS_FLAG_ORBIT_SELECT = (1 << 0),
|
||||||
|
@ -72,8 +85,10 @@ enum eViewOpsFlag {
|
||||||
VIEWOPS_FLAG_PERSP_ENSURE = (1 << 2),
|
VIEWOPS_FLAG_PERSP_ENSURE = (1 << 2),
|
||||||
/** When set, ignore any options that depend on initial cursor location. */
|
/** When set, ignore any options that depend on initial cursor location. */
|
||||||
VIEWOPS_FLAG_USE_MOUSE_INIT = (1 << 3),
|
VIEWOPS_FLAG_USE_MOUSE_INIT = (1 << 3),
|
||||||
};
|
|
||||||
ENUM_OPERATORS(eViewOpsFlag, VIEWOPS_FLAG_USE_MOUSE_INIT);
|
VIEWOPS_FLAG_ZOOM_TO_MOUSE = (1 << 4),
|
||||||
|
} eViewOpsFlag;
|
||||||
|
ENUM_OPERATORS(eViewOpsFlag, VIEWOPS_FLAG_ZOOM_TO_MOUSE);
|
||||||
|
|
||||||
/** Generic View Operator Custom-Data */
|
/** Generic View Operator Custom-Data */
|
||||||
typedef struct ViewOpsData {
|
typedef struct ViewOpsData {
|
||||||
|
@ -146,6 +161,9 @@ typedef struct ViewOpsData {
|
||||||
float viewquat[4];
|
float viewquat[4];
|
||||||
} curr;
|
} curr;
|
||||||
|
|
||||||
|
eV3D_OpMode nav_type;
|
||||||
|
eViewOpsFlag viewops_flag;
|
||||||
|
|
||||||
float reverse;
|
float reverse;
|
||||||
bool axis_snap; /* view rotate only */
|
bool axis_snap; /* view rotate only */
|
||||||
|
|
||||||
|
@ -165,13 +183,22 @@ typedef struct ViewOpsData {
|
||||||
|
|
||||||
/* view3d_navigate.cc */
|
/* view3d_navigate.cc */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigation operators that share the `ViewOpsData` utility.
|
||||||
|
*/
|
||||||
|
const char *viewops_operator_idname_get(eV3D_OpMode nav_type);
|
||||||
|
|
||||||
bool view3d_location_poll(struct bContext *C);
|
bool view3d_location_poll(struct bContext *C);
|
||||||
bool view3d_rotation_poll(struct bContext *C);
|
bool view3d_rotation_poll(struct bContext *C);
|
||||||
bool view3d_zoom_or_dolly_poll(struct bContext *C);
|
bool view3d_zoom_or_dolly_poll(struct bContext *C);
|
||||||
|
|
||||||
|
int view3d_navigate_invoke_impl(bContext *C,
|
||||||
|
wmOperator *op,
|
||||||
|
const wmEvent *event,
|
||||||
|
const eV3D_OpMode nav_type);
|
||||||
|
int view3d_navigate_modal_fn(bContext *C, wmOperator *op, const wmEvent *event);
|
||||||
void view3d_navigate_cancel_fn(struct bContext *C, struct wmOperator *op);
|
void view3d_navigate_cancel_fn(struct bContext *C, struct wmOperator *op);
|
||||||
|
|
||||||
enum eViewOpsFlag viewops_flag_from_prefs(void);
|
|
||||||
void calctrackballvec(const struct rcti *rect, const int event_xy[2], float r_dir[3]);
|
void calctrackballvec(const struct rcti *rect, const int event_xy[2], float r_dir[3]);
|
||||||
void viewmove_apply(ViewOpsData *vod, int x, int y);
|
void viewmove_apply(ViewOpsData *vod, int x, int y);
|
||||||
void viewmove_apply_reset(ViewOpsData *vod);
|
void viewmove_apply_reset(ViewOpsData *vod);
|
||||||
|
@ -193,9 +220,10 @@ void viewops_data_free(struct bContext *C, ViewOpsData *vod);
|
||||||
/**
|
/**
|
||||||
* Allocate, fill in context pointers and calculate the values for #ViewOpsData
|
* Allocate, fill in context pointers and calculate the values for #ViewOpsData
|
||||||
*/
|
*/
|
||||||
ViewOpsData *viewops_data_create(struct bContext *C,
|
ViewOpsData *viewops_data_create(bContext *C,
|
||||||
const struct wmEvent *event,
|
const wmEvent *event,
|
||||||
enum eViewOpsFlag viewops_flag);
|
const eV3D_OpMode nav_type,
|
||||||
|
const bool use_cursor_init);
|
||||||
|
|
||||||
void VIEW3D_OT_view_all(struct wmOperatorType *ot);
|
void VIEW3D_OT_view_all(struct wmOperatorType *ot);
|
||||||
void VIEW3D_OT_view_selected(struct wmOperatorType *ot);
|
void VIEW3D_OT_view_selected(struct wmOperatorType *ot);
|
||||||
|
@ -219,6 +247,11 @@ void VIEW3D_OT_fly(struct wmOperatorType *ot);
|
||||||
|
|
||||||
/* view3d_navigate_move.c */
|
/* view3d_navigate_move.c */
|
||||||
|
|
||||||
|
int viewmove_modal_impl(bContext *C,
|
||||||
|
ViewOpsData *vod,
|
||||||
|
const eV3D_OpEvent event_code,
|
||||||
|
const int xy[2]);
|
||||||
|
int viewmove_invoke_impl(ViewOpsData *vod, const wmEvent *event);
|
||||||
void viewmove_modal_keymap(struct wmKeyConfig *keyconf);
|
void viewmove_modal_keymap(struct wmKeyConfig *keyconf);
|
||||||
void VIEW3D_OT_move(struct wmOperatorType *ot);
|
void VIEW3D_OT_move(struct wmOperatorType *ot);
|
||||||
|
|
||||||
|
@ -249,6 +282,11 @@ void VIEW3D_OT_view_roll(struct wmOperatorType *ot);
|
||||||
|
|
||||||
/* view3d_navigate_rotate.c */
|
/* view3d_navigate_rotate.c */
|
||||||
|
|
||||||
|
int viewrotate_modal_impl(bContext *C,
|
||||||
|
ViewOpsData *vod,
|
||||||
|
const eV3D_OpEvent event_code,
|
||||||
|
const int xy[2]);
|
||||||
|
int viewrotate_invoke_impl(ViewOpsData *vod, const wmEvent *event);
|
||||||
void viewrotate_modal_keymap(struct wmKeyConfig *keyconf);
|
void viewrotate_modal_keymap(struct wmKeyConfig *keyconf);
|
||||||
void VIEW3D_OT_rotate(struct wmOperatorType *ot);
|
void VIEW3D_OT_rotate(struct wmOperatorType *ot);
|
||||||
|
|
||||||
|
@ -326,6 +364,11 @@ void VIEW3D_OT_walk(struct wmOperatorType *ot);
|
||||||
|
|
||||||
/* view3d_navigate_zoom.c */
|
/* view3d_navigate_zoom.c */
|
||||||
|
|
||||||
|
int viewzoom_modal_impl(bContext *C,
|
||||||
|
ViewOpsData *vod,
|
||||||
|
const eV3D_OpEvent event_code,
|
||||||
|
const int xy[2]);
|
||||||
|
int viewzoom_invoke_impl(bContext *C, ViewOpsData *vod, const wmEvent *event, PointerRNA *ptr);
|
||||||
void viewzoom_modal_keymap(struct wmKeyConfig *keyconf);
|
void viewzoom_modal_keymap(struct wmKeyConfig *keyconf);
|
||||||
void VIEW3D_OT_zoom(struct wmOperatorType *ot);
|
void VIEW3D_OT_zoom(struct wmOperatorType *ot);
|
||||||
|
|
||||||
|
|
|
@ -246,11 +246,7 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
|
|
||||||
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
|
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
|
||||||
|
|
||||||
vod = op->customdata = viewops_data_create(
|
vod = op->customdata = viewops_data_create(C, event, V3D_OP_MODE_DOLLY, use_cursor_init);
|
||||||
C,
|
|
||||||
event,
|
|
||||||
(viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
|
|
||||||
(use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
|
|
||||||
|
|
||||||
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
|
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
|
||||||
|
|
||||||
|
@ -314,7 +310,7 @@ void VIEW3D_OT_dolly(wmOperatorType *ot)
|
||||||
/* identifiers */
|
/* identifiers */
|
||||||
ot->name = "Dolly View";
|
ot->name = "Dolly View";
|
||||||
ot->description = "Dolly in/out in the view";
|
ot->description = "Dolly in/out in the view";
|
||||||
ot->idname = "VIEW3D_OT_dolly";
|
ot->idname = viewops_operator_idname_get(V3D_OP_MODE_DOLLY);
|
||||||
|
|
||||||
/* api callbacks */
|
/* api callbacks */
|
||||||
ot->invoke = viewdolly_invoke;
|
ot->invoke = viewdolly_invoke;
|
||||||
|
|
|
@ -49,52 +49,17 @@ void viewmove_modal_keymap(wmKeyConfig *keyconf)
|
||||||
WM_modalkeymap_assign(keymap, "VIEW3D_OT_move");
|
WM_modalkeymap_assign(keymap, "VIEW3D_OT_move");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
int viewmove_modal_impl(bContext *C,
|
||||||
|
ViewOpsData *vod,
|
||||||
|
const eV3D_OpEvent event_code,
|
||||||
|
const int xy[2])
|
||||||
{
|
{
|
||||||
|
|
||||||
ViewOpsData *vod = op->customdata;
|
|
||||||
short event_code = VIEW_PASS;
|
|
||||||
bool use_autokey = false;
|
bool use_autokey = false;
|
||||||
int ret = OPERATOR_RUNNING_MODAL;
|
int ret = OPERATOR_RUNNING_MODAL;
|
||||||
|
|
||||||
/* Execute the events. */
|
|
||||||
if (event->type == EVT_MODAL_MAP) {
|
|
||||||
switch (event->val) {
|
|
||||||
case VIEW_MODAL_CONFIRM:
|
|
||||||
event_code = VIEW_CONFIRM;
|
|
||||||
break;
|
|
||||||
case VIEW_MODAL_CANCEL:
|
|
||||||
event_code = VIEW_CANCEL;
|
|
||||||
break;
|
|
||||||
case VIEWROT_MODAL_SWITCH_ZOOM:
|
|
||||||
WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL, event);
|
|
||||||
event_code = VIEW_CONFIRM;
|
|
||||||
break;
|
|
||||||
case VIEWROT_MODAL_SWITCH_ROTATE:
|
|
||||||
WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL, event);
|
|
||||||
event_code = VIEW_CONFIRM;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (event->type == MOUSEMOVE) {
|
|
||||||
event_code = VIEW_APPLY;
|
|
||||||
}
|
|
||||||
else if (event->type == vod->init.event_type) {
|
|
||||||
if (event->val == KM_RELEASE) {
|
|
||||||
event_code = VIEW_CONFIRM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (event->type == EVT_ESCKEY) {
|
|
||||||
if (event->val == KM_PRESS) {
|
|
||||||
event_code = VIEW_CANCEL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (event_code) {
|
switch (event_code) {
|
||||||
case VIEW_APPLY: {
|
case VIEW_APPLY: {
|
||||||
viewmove_apply(vod, event->xy[0], event->xy[1]);
|
viewmove_apply(vod, xy[0], xy[1]);
|
||||||
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
|
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
|
||||||
use_autokey = true;
|
use_autokey = true;
|
||||||
}
|
}
|
||||||
|
@ -111,66 +76,47 @@ static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
ret = OPERATOR_CANCELLED;
|
ret = OPERATOR_CANCELLED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case VIEW_PASS:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_autokey) {
|
if (use_autokey) {
|
||||||
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
|
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret & OPERATOR_RUNNING_MODAL) == 0) {
|
|
||||||
if (ret & OPERATOR_FINISHED) {
|
|
||||||
ED_view3d_camera_lock_undo_push(op->type->name, vod->v3d, vod->rv3d, C);
|
|
||||||
}
|
|
||||||
viewops_data_free(C, op->customdata);
|
|
||||||
op->customdata = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
int viewmove_invoke_impl(ViewOpsData *vod, const wmEvent *event)
|
||||||
{
|
{
|
||||||
ViewOpsData *vod;
|
eV3D_OpEvent event_code = event->type == MOUSEPAN ? VIEW_CONFIRM : VIEW_PASS;
|
||||||
|
|
||||||
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
|
|
||||||
|
|
||||||
vod = op->customdata = viewops_data_create(
|
|
||||||
C,
|
|
||||||
event,
|
|
||||||
(viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
|
|
||||||
(use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
|
|
||||||
vod = op->customdata;
|
|
||||||
|
|
||||||
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
|
|
||||||
|
|
||||||
if (event->type == MOUSEPAN) {
|
|
||||||
/* invert it, trackpad scroll follows same principle as 2d windows this way */
|
|
||||||
viewmove_apply(
|
|
||||||
vod, 2 * event->xy[0] - event->prev_xy[0], 2 * event->xy[1] - event->prev_xy[1]);
|
|
||||||
|
|
||||||
viewops_data_free(C, op->customdata);
|
|
||||||
op->customdata = NULL;
|
|
||||||
|
|
||||||
|
if (event_code == VIEW_CONFIRM) {
|
||||||
|
/* Invert it, trackpad scroll follows same principle as 2d windows this way. */
|
||||||
|
int mx = 2 * event->xy[0] - event->prev_xy[0];
|
||||||
|
int my = 2 * event->xy[1] - event->prev_xy[1];
|
||||||
|
viewmove_apply(vod, mx, my);
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add temp handler */
|
|
||||||
WM_event_add_modal_handler(C, op);
|
|
||||||
|
|
||||||
return OPERATOR_RUNNING_MODAL;
|
return OPERATOR_RUNNING_MODAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
|
{
|
||||||
|
return view3d_navigate_invoke_impl(C, op, event, V3D_OP_MODE_MOVE);
|
||||||
|
}
|
||||||
|
|
||||||
void VIEW3D_OT_move(wmOperatorType *ot)
|
void VIEW3D_OT_move(wmOperatorType *ot)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* identifiers */
|
/* identifiers */
|
||||||
ot->name = "Pan View";
|
ot->name = "Pan View";
|
||||||
ot->description = "Move the view";
|
ot->description = "Move the view";
|
||||||
ot->idname = "VIEW3D_OT_move";
|
ot->idname = viewops_operator_idname_get(V3D_OP_MODE_MOVE);
|
||||||
|
|
||||||
/* api callbacks */
|
/* api callbacks */
|
||||||
ot->invoke = viewmove_invoke;
|
ot->invoke = viewmove_invoke;
|
||||||
ot->modal = viewmove_modal;
|
ot->modal = view3d_navigate_modal_fn;
|
||||||
ot->poll = view3d_location_poll;
|
ot->poll = view3d_location_poll;
|
||||||
ot->cancel = view3d_navigate_cancel_fn;
|
ot->cancel = view3d_navigate_cancel_fn;
|
||||||
|
|
||||||
|
|
|
@ -435,8 +435,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
|
|
||||||
const wmNDOFMotionData *ndof = event->customdata;
|
const wmNDOFMotionData *ndof = event->customdata;
|
||||||
|
|
||||||
vod = op->customdata = viewops_data_create(
|
vod = op->customdata = viewops_data_create(C, event, V3D_OP_MODE_NDOF_ORBIT, false);
|
||||||
C, event, (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_DEPTH_NAVIGATE));
|
|
||||||
|
|
||||||
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
|
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
|
||||||
|
|
||||||
|
@ -522,8 +521,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
|
||||||
|
|
||||||
const wmNDOFMotionData *ndof = event->customdata;
|
const wmNDOFMotionData *ndof = event->customdata;
|
||||||
|
|
||||||
vod = op->customdata = viewops_data_create(
|
vod = op->customdata = viewops_data_create(C, event, V3D_OP_MODE_NDOF_ORBIT_ZOOM, false);
|
||||||
C, event, (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_DEPTH_NAVIGATE));
|
|
||||||
|
|
||||||
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
|
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
|
||||||
|
|
||||||
|
|
|
@ -253,7 +253,7 @@ static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* makes op->customdata */
|
/* makes op->customdata */
|
||||||
vod = op->customdata = viewops_data_create(C, event, viewops_flag_from_prefs());
|
vod = op->customdata = viewops_data_create(C, event, V3D_OP_MODE_VIEW_ROLL, false);
|
||||||
vod->init.dial = BLI_dial_init((const float[2]){BLI_rcti_cent_x(&vod->region->winrct),
|
vod->init.dial = BLI_dial_init((const float[2]){BLI_rcti_cent_x(&vod->region->winrct),
|
||||||
BLI_rcti_cent_y(&vod->region->winrct)},
|
BLI_rcti_cent_y(&vod->region->winrct)},
|
||||||
FLT_EPSILON);
|
FLT_EPSILON);
|
||||||
|
@ -287,7 +287,7 @@ void VIEW3D_OT_view_roll(wmOperatorType *ot)
|
||||||
/* identifiers */
|
/* identifiers */
|
||||||
ot->name = "View Roll";
|
ot->name = "View Roll";
|
||||||
ot->description = "Roll the view";
|
ot->description = "Roll the view";
|
||||||
ot->idname = "VIEW3D_OT_view_roll";
|
ot->idname = viewops_operator_idname_get(V3D_OP_MODE_VIEW_ROLL);
|
||||||
|
|
||||||
/* api callbacks */
|
/* api callbacks */
|
||||||
ot->invoke = viewroll_invoke;
|
ot->invoke = viewroll_invoke;
|
||||||
|
|
|
@ -293,60 +293,17 @@ static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2])
|
||||||
ED_region_tag_redraw(vod->region);
|
ED_region_tag_redraw(vod->region);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
int viewrotate_modal_impl(bContext *C,
|
||||||
|
ViewOpsData *vod,
|
||||||
|
const eV3D_OpEvent event_code,
|
||||||
|
const int xy[2])
|
||||||
{
|
{
|
||||||
ViewOpsData *vod = op->customdata;
|
|
||||||
short event_code = VIEW_PASS;
|
|
||||||
bool use_autokey = false;
|
bool use_autokey = false;
|
||||||
int ret = OPERATOR_RUNNING_MODAL;
|
int ret = OPERATOR_RUNNING_MODAL;
|
||||||
|
|
||||||
/* Execute the events. */
|
|
||||||
if (event->type == EVT_MODAL_MAP) {
|
|
||||||
switch (event->val) {
|
|
||||||
case VIEW_MODAL_CONFIRM:
|
|
||||||
event_code = VIEW_CONFIRM;
|
|
||||||
break;
|
|
||||||
case VIEW_MODAL_CANCEL:
|
|
||||||
event_code = VIEW_CANCEL;
|
|
||||||
break;
|
|
||||||
case VIEWROT_MODAL_AXIS_SNAP_ENABLE:
|
|
||||||
vod->axis_snap = true;
|
|
||||||
event_code = VIEW_APPLY;
|
|
||||||
break;
|
|
||||||
case VIEWROT_MODAL_AXIS_SNAP_DISABLE:
|
|
||||||
vod->rv3d->persp = vod->init.persp_with_auto_persp_applied;
|
|
||||||
vod->axis_snap = false;
|
|
||||||
event_code = VIEW_APPLY;
|
|
||||||
break;
|
|
||||||
case VIEWROT_MODAL_SWITCH_ZOOM:
|
|
||||||
WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL, event);
|
|
||||||
event_code = VIEW_CONFIRM;
|
|
||||||
break;
|
|
||||||
case VIEWROT_MODAL_SWITCH_MOVE:
|
|
||||||
WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL, event);
|
|
||||||
event_code = VIEW_CONFIRM;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (event->type == MOUSEMOVE) {
|
|
||||||
event_code = VIEW_APPLY;
|
|
||||||
}
|
|
||||||
else if (event->type == vod->init.event_type) {
|
|
||||||
if (event->val == KM_RELEASE) {
|
|
||||||
event_code = VIEW_CONFIRM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (event->type == EVT_ESCKEY) {
|
|
||||||
if (event->val == KM_PRESS) {
|
|
||||||
event_code = VIEW_CANCEL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (event_code) {
|
switch (event_code) {
|
||||||
case VIEW_APPLY: {
|
case VIEW_APPLY: {
|
||||||
viewrotate_apply(vod, event->xy);
|
viewrotate_apply(vod, xy);
|
||||||
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
|
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
|
||||||
use_autokey = true;
|
use_autokey = true;
|
||||||
}
|
}
|
||||||
|
@ -376,84 +333,60 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
ret = OPERATOR_CANCELLED;
|
ret = OPERATOR_CANCELLED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case VIEW_PASS:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_autokey) {
|
if (use_autokey) {
|
||||||
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, true);
|
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret & OPERATOR_RUNNING_MODAL) == 0) {
|
|
||||||
if (ret & OPERATOR_FINISHED) {
|
|
||||||
ED_view3d_camera_lock_undo_push(op->type->name, vod->v3d, vod->rv3d, C);
|
|
||||||
}
|
|
||||||
viewops_data_free(C, op->customdata);
|
|
||||||
op->customdata = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
int viewrotate_invoke_impl(ViewOpsData *vod, const wmEvent *event)
|
||||||
{
|
{
|
||||||
ViewOpsData *vod;
|
|
||||||
|
|
||||||
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
|
|
||||||
|
|
||||||
/* makes op->customdata */
|
|
||||||
vod = op->customdata = viewops_data_create(
|
|
||||||
C,
|
|
||||||
event,
|
|
||||||
viewops_flag_from_prefs() | VIEWOPS_FLAG_PERSP_ENSURE |
|
|
||||||
(use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
|
|
||||||
|
|
||||||
if (vod->use_dyn_ofs && (vod->rv3d->is_persp == false)) {
|
if (vod->use_dyn_ofs && (vod->rv3d->is_persp == false)) {
|
||||||
vod->use_dyn_ofs_ortho_correction = true;
|
vod->use_dyn_ofs_ortho_correction = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
|
eV3D_OpEvent event_code = ELEM(event->type, MOUSEROTATE, MOUSEPAN) ? VIEW_CONFIRM : VIEW_PASS;
|
||||||
|
|
||||||
if (ELEM(event->type, MOUSEPAN, MOUSEROTATE)) {
|
if (event_code == VIEW_CONFIRM) {
|
||||||
/* Rotate direction we keep always same */
|
/* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */
|
||||||
int event_xy[2];
|
const bool is_inverted = (event->flag & WM_EVENT_SCROLL_INVERT) &&
|
||||||
|
(event->type != MOUSEROTATE);
|
||||||
|
|
||||||
if (event->type == MOUSEPAN) {
|
int m_xy[2];
|
||||||
if (event->flag & WM_EVENT_SCROLL_INVERT) {
|
if (is_inverted) {
|
||||||
event_xy[0] = 2 * event->xy[0] - event->prev_xy[0];
|
m_xy[0] = 2 * event->xy[0] - event->prev_xy[0];
|
||||||
event_xy[1] = 2 * event->xy[1] - event->prev_xy[1];
|
m_xy[1] = 2 * event->xy[1] - event->prev_xy[1];
|
||||||
}
|
|
||||||
else {
|
|
||||||
copy_v2_v2_int(event_xy, event->prev_xy);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */
|
copy_v2_v2_int(m_xy, event->prev_xy);
|
||||||
copy_v2_v2_int(event_xy, event->prev_xy);
|
|
||||||
}
|
}
|
||||||
|
viewrotate_apply(vod, m_xy);
|
||||||
viewrotate_apply(vod, event_xy);
|
|
||||||
|
|
||||||
viewops_data_free(C, op->customdata);
|
|
||||||
op->customdata = NULL;
|
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add temp handler */
|
|
||||||
WM_event_add_modal_handler(C, op);
|
|
||||||
|
|
||||||
return OPERATOR_RUNNING_MODAL;
|
return OPERATOR_RUNNING_MODAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
|
{
|
||||||
|
return view3d_navigate_invoke_impl(C, op, event, V3D_OP_MODE_ROTATE);
|
||||||
|
}
|
||||||
|
|
||||||
void VIEW3D_OT_rotate(wmOperatorType *ot)
|
void VIEW3D_OT_rotate(wmOperatorType *ot)
|
||||||
{
|
{
|
||||||
/* identifiers */
|
/* identifiers */
|
||||||
ot->name = "Rotate View";
|
ot->name = "Rotate View";
|
||||||
ot->description = "Rotate the view";
|
ot->description = "Rotate the view";
|
||||||
ot->idname = "VIEW3D_OT_rotate";
|
ot->idname = viewops_operator_idname_get(V3D_OP_MODE_ROTATE);
|
||||||
|
|
||||||
/* api callbacks */
|
/* api callbacks */
|
||||||
ot->invoke = viewrotate_invoke;
|
ot->invoke = viewrotate_invoke;
|
||||||
ot->modal = viewrotate_modal;
|
ot->modal = view3d_navigate_modal_fn;
|
||||||
ot->poll = view3d_rotation_poll;
|
ot->poll = view3d_rotation_poll;
|
||||||
ot->cancel = view3d_navigate_cancel_fn;
|
ot->cancel = view3d_navigate_cancel_fn;
|
||||||
|
|
||||||
|
|
|
@ -331,9 +331,10 @@ static void viewzoom_apply_3d(ViewOpsData *vod,
|
||||||
static void viewzoom_apply(ViewOpsData *vod,
|
static void viewzoom_apply(ViewOpsData *vod,
|
||||||
const int xy[2],
|
const int xy[2],
|
||||||
const eViewZoom_Style viewzoom,
|
const eViewZoom_Style viewzoom,
|
||||||
const bool zoom_invert,
|
const bool zoom_invert)
|
||||||
const bool zoom_to_pos)
|
|
||||||
{
|
{
|
||||||
|
const bool zoom_to_pos = (vod->viewops_flag & VIEWOPS_FLAG_ZOOM_TO_MOUSE) != 0;
|
||||||
|
|
||||||
if ((vod->rv3d->persp == RV3D_CAMOB) &&
|
if ((vod->rv3d->persp == RV3D_CAMOB) &&
|
||||||
(vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) == 0) {
|
(vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) == 0) {
|
||||||
viewzoom_apply_camera(vod, xy, viewzoom, zoom_invert, zoom_to_pos);
|
viewzoom_apply_camera(vod, xy, viewzoom, zoom_invert, zoom_to_pos);
|
||||||
|
@ -343,62 +344,17 @@ static void viewzoom_apply(ViewOpsData *vod,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
int viewzoom_modal_impl(bContext *C,
|
||||||
|
ViewOpsData *vod,
|
||||||
|
const eV3D_OpEvent event_code,
|
||||||
|
const int xy[2])
|
||||||
{
|
{
|
||||||
ViewOpsData *vod = op->customdata;
|
|
||||||
short event_code = VIEW_PASS;
|
|
||||||
bool use_autokey = false;
|
bool use_autokey = false;
|
||||||
int ret = OPERATOR_RUNNING_MODAL;
|
int ret = OPERATOR_RUNNING_MODAL;
|
||||||
|
|
||||||
/* Execute the events. */
|
|
||||||
if (event->type == EVT_MODAL_MAP) {
|
|
||||||
switch (event->val) {
|
|
||||||
case VIEW_MODAL_CONFIRM:
|
|
||||||
event_code = VIEW_CONFIRM;
|
|
||||||
break;
|
|
||||||
case VIEW_MODAL_CANCEL:
|
|
||||||
event_code = VIEW_CANCEL;
|
|
||||||
break;
|
|
||||||
case VIEWROT_MODAL_SWITCH_MOVE:
|
|
||||||
WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL, event);
|
|
||||||
event_code = VIEW_CONFIRM;
|
|
||||||
break;
|
|
||||||
case VIEWROT_MODAL_SWITCH_ROTATE:
|
|
||||||
WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL, event);
|
|
||||||
event_code = VIEW_CONFIRM;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (event->type == MOUSEMOVE) {
|
|
||||||
event_code = VIEW_APPLY;
|
|
||||||
}
|
|
||||||
else if (event->type == TIMER) {
|
|
||||||
if (event->customdata == vod->timer) {
|
|
||||||
/* Continuous zoom. */
|
|
||||||
event_code = VIEW_APPLY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (event->type == vod->init.event_type) {
|
|
||||||
if (event->val == KM_RELEASE) {
|
|
||||||
event_code = VIEW_CONFIRM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (event->type == EVT_ESCKEY) {
|
|
||||||
if (event->val == KM_PRESS) {
|
|
||||||
event_code = VIEW_CANCEL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (event_code) {
|
switch (event_code) {
|
||||||
case VIEW_APPLY: {
|
case VIEW_APPLY: {
|
||||||
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
|
viewzoom_apply(vod, xy, (eViewZoom_Style)U.viewzoom, (U.uiflag & USER_ZOOM_INVERT) != 0);
|
||||||
viewzoom_apply(vod,
|
|
||||||
event->xy,
|
|
||||||
(eViewZoom_Style)U.viewzoom,
|
|
||||||
(U.uiflag & USER_ZOOM_INVERT) != 0,
|
|
||||||
(use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
|
|
||||||
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
|
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
|
||||||
use_autokey = true;
|
use_autokey = true;
|
||||||
}
|
}
|
||||||
|
@ -423,64 +379,33 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
ret = OPERATOR_CANCELLED;
|
ret = OPERATOR_CANCELLED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case VIEW_PASS:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_autokey) {
|
if (use_autokey) {
|
||||||
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
|
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret & OPERATOR_RUNNING_MODAL) == 0) {
|
|
||||||
if (ret & OPERATOR_FINISHED) {
|
|
||||||
ED_view3d_camera_lock_undo_push(op->type->name, vod->v3d, vod->rv3d, C);
|
|
||||||
}
|
|
||||||
viewops_data_free(C, op->customdata);
|
|
||||||
op->customdata = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int viewzoom_exec(bContext *C, wmOperator *op)
|
static void view_zoom_apply_step(bContext *C,
|
||||||
|
Depsgraph *depsgraph,
|
||||||
|
Scene *scene,
|
||||||
|
ScrArea *area,
|
||||||
|
ARegion *region,
|
||||||
|
const int delta,
|
||||||
|
const int zoom_xy[2])
|
||||||
{
|
{
|
||||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
View3D *v3d = area->spacedata.first;
|
||||||
Scene *scene = CTX_data_scene(C);
|
RegionView3D *rv3d = region->regiondata;
|
||||||
View3D *v3d;
|
|
||||||
RegionView3D *rv3d;
|
|
||||||
ScrArea *area;
|
|
||||||
ARegion *region;
|
|
||||||
bool use_cam_zoom;
|
bool use_cam_zoom;
|
||||||
float dist_range[2];
|
float dist_range[2];
|
||||||
|
|
||||||
const int delta = RNA_int_get(op->ptr, "delta");
|
|
||||||
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
|
|
||||||
|
|
||||||
if (op->customdata) {
|
|
||||||
ViewOpsData *vod = op->customdata;
|
|
||||||
|
|
||||||
area = vod->area;
|
|
||||||
region = vod->region;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
area = CTX_wm_area(C);
|
|
||||||
region = CTX_wm_region(C);
|
|
||||||
}
|
|
||||||
|
|
||||||
v3d = area->spacedata.first;
|
|
||||||
rv3d = region->regiondata;
|
|
||||||
|
|
||||||
use_cam_zoom = (rv3d->persp == RV3D_CAMOB) &&
|
use_cam_zoom = (rv3d->persp == RV3D_CAMOB) &&
|
||||||
!(rv3d->is_persp && ED_view3d_camera_lock_check(v3d, rv3d));
|
!(rv3d->is_persp && ED_view3d_camera_lock_check(v3d, rv3d));
|
||||||
|
|
||||||
int zoom_xy_buf[2];
|
|
||||||
const int *zoom_xy = NULL;
|
|
||||||
if (use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) {
|
|
||||||
zoom_xy_buf[0] = RNA_struct_property_is_set(op->ptr, "mx") ? RNA_int_get(op->ptr, "mx") :
|
|
||||||
region->winx / 2;
|
|
||||||
zoom_xy_buf[1] = RNA_struct_property_is_set(op->ptr, "my") ? RNA_int_get(op->ptr, "my") :
|
|
||||||
region->winy / 2;
|
|
||||||
zoom_xy = zoom_xy_buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
ED_view3d_dist_range_get(v3d, dist_range);
|
ED_view3d_dist_range_get(v3d, dist_range);
|
||||||
|
|
||||||
if (delta < 0) {
|
if (delta < 0) {
|
||||||
|
@ -514,73 +439,96 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
|
||||||
ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, true);
|
ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, true);
|
||||||
|
|
||||||
ED_region_tag_redraw(region);
|
ED_region_tag_redraw(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int viewzoom_exec(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
BLI_assert(op->customdata == NULL);
|
||||||
|
|
||||||
|
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||||
|
Scene *scene = CTX_data_scene(C);
|
||||||
|
ScrArea *area = CTX_wm_area(C);
|
||||||
|
ARegion *region = CTX_wm_region(C);
|
||||||
|
View3D *v3d = area->spacedata.first;
|
||||||
|
RegionView3D *rv3d = region->regiondata;
|
||||||
|
|
||||||
|
const int delta = RNA_int_get(op->ptr, "delta");
|
||||||
|
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
|
||||||
|
|
||||||
|
int zoom_xy_buf[2];
|
||||||
|
const int *zoom_xy = NULL;
|
||||||
|
const bool do_zoom_to_mouse_pos = (use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS));
|
||||||
|
if (do_zoom_to_mouse_pos) {
|
||||||
|
zoom_xy_buf[0] = RNA_struct_property_is_set(op->ptr, "mx") ? RNA_int_get(op->ptr, "mx") :
|
||||||
|
region->winx / 2;
|
||||||
|
zoom_xy_buf[1] = RNA_struct_property_is_set(op->ptr, "my") ? RNA_int_get(op->ptr, "my") :
|
||||||
|
region->winy / 2;
|
||||||
|
zoom_xy = zoom_xy_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
view_zoom_apply_step(C, depsgraph, scene, area, region, delta, zoom_xy);
|
||||||
ED_view3d_camera_lock_undo_grouped_push(op->type->name, v3d, rv3d, C);
|
ED_view3d_camera_lock_undo_grouped_push(op->type->name, v3d, rv3d, C);
|
||||||
viewops_data_free(C, op->customdata);
|
|
||||||
op->customdata = NULL;
|
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int viewzoom_invoke_impl(bContext *C, ViewOpsData *vod, const wmEvent *event, PointerRNA *ptr)
|
||||||
|
{
|
||||||
|
int xy[2];
|
||||||
|
|
||||||
|
PropertyRNA *prop;
|
||||||
|
prop = RNA_struct_find_property(ptr, "mx");
|
||||||
|
xy[0] = RNA_property_is_set(ptr, prop) ? RNA_property_int_get(ptr, prop) : event->xy[0];
|
||||||
|
|
||||||
|
prop = RNA_struct_find_property(ptr, "my");
|
||||||
|
xy[1] = RNA_property_is_set(ptr, prop) ? RNA_property_int_get(ptr, prop) : event->xy[1];
|
||||||
|
|
||||||
|
prop = RNA_struct_find_property(ptr, "delta");
|
||||||
|
const int delta = RNA_property_is_set(ptr, prop) ? RNA_property_int_get(ptr, prop) : 0;
|
||||||
|
|
||||||
|
if (delta) {
|
||||||
|
const bool do_zoom_to_mouse_pos = (vod->viewops_flag & VIEWOPS_FLAG_ZOOM_TO_MOUSE) != 0;
|
||||||
|
view_zoom_apply_step(C,
|
||||||
|
vod->depsgraph,
|
||||||
|
vod->scene,
|
||||||
|
vod->area,
|
||||||
|
vod->region,
|
||||||
|
delta,
|
||||||
|
do_zoom_to_mouse_pos ? xy : NULL);
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
eV3D_OpEvent event_code = ELEM(event->type, MOUSEZOOM, MOUSEPAN) ? VIEW_CONFIRM : VIEW_PASS;
|
||||||
|
if (event_code == VIEW_CONFIRM) {
|
||||||
|
if (U.uiflag & USER_ZOOM_HORIZ) {
|
||||||
|
vod->init.event_xy[0] = vod->prev.event_xy[0] = xy[0];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
|
||||||
|
vod->init.event_xy[1] = vod->prev.event_xy[1] = vod->init.event_xy[1] + xy[0] -
|
||||||
|
event->prev_xy[0];
|
||||||
|
}
|
||||||
|
viewzoom_apply(vod, event->prev_xy, USER_ZOOM_DOLLY, (U.uiflag & USER_ZOOM_INVERT) != 0);
|
||||||
|
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (U.viewzoom == USER_ZOOM_CONTINUE) {
|
||||||
|
/* needs a timer to continue redrawing */
|
||||||
|
vod->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
|
||||||
|
vod->prev.time = PIL_check_seconds_timer();
|
||||||
|
}
|
||||||
|
|
||||||
|
return OPERATOR_RUNNING_MODAL;
|
||||||
|
}
|
||||||
|
|
||||||
/* viewdolly_invoke() copied this function, changes here may apply there */
|
/* viewdolly_invoke() copied this function, changes here may apply there */
|
||||||
static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
{
|
{
|
||||||
ViewOpsData *vod;
|
return view3d_navigate_invoke_impl(C, op, event, V3D_OP_MODE_ZOOM);
|
||||||
|
|
||||||
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
|
|
||||||
|
|
||||||
vod = op->customdata = viewops_data_create(
|
|
||||||
C,
|
|
||||||
event,
|
|
||||||
(viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
|
|
||||||
(use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
|
|
||||||
|
|
||||||
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
|
|
||||||
|
|
||||||
/* if one or the other zoom position aren't set, set from event */
|
|
||||||
if (!RNA_struct_property_is_set(op->ptr, "mx") || !RNA_struct_property_is_set(op->ptr, "my")) {
|
|
||||||
RNA_int_set(op->ptr, "mx", event->xy[0]);
|
|
||||||
RNA_int_set(op->ptr, "my", event->xy[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RNA_struct_property_is_set(op->ptr, "delta")) {
|
|
||||||
viewzoom_exec(C, op);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (ELEM(event->type, MOUSEZOOM, MOUSEPAN)) {
|
|
||||||
|
|
||||||
if (U.uiflag & USER_ZOOM_HORIZ) {
|
|
||||||
vod->init.event_xy[0] = vod->prev.event_xy[0] = event->xy[0];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
|
|
||||||
vod->init.event_xy[1] = vod->prev.event_xy[1] = vod->init.event_xy[1] + event->xy[0] -
|
|
||||||
event->prev_xy[0];
|
|
||||||
}
|
|
||||||
viewzoom_apply(vod,
|
|
||||||
event->prev_xy,
|
|
||||||
USER_ZOOM_DOLLY,
|
|
||||||
(U.uiflag & USER_ZOOM_INVERT) != 0,
|
|
||||||
(use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
|
|
||||||
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
|
|
||||||
|
|
||||||
viewops_data_free(C, op->customdata);
|
|
||||||
op->customdata = NULL;
|
|
||||||
return OPERATOR_FINISHED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (U.viewzoom == USER_ZOOM_CONTINUE) {
|
|
||||||
/* needs a timer to continue redrawing */
|
|
||||||
vod->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
|
|
||||||
vod->prev.time = PIL_check_seconds_timer();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add temp handler */
|
|
||||||
WM_event_add_modal_handler(C, op);
|
|
||||||
|
|
||||||
return OPERATOR_RUNNING_MODAL;
|
|
||||||
}
|
|
||||||
return OPERATOR_FINISHED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VIEW3D_OT_zoom(wmOperatorType *ot)
|
void VIEW3D_OT_zoom(wmOperatorType *ot)
|
||||||
|
@ -588,12 +536,12 @@ void VIEW3D_OT_zoom(wmOperatorType *ot)
|
||||||
/* identifiers */
|
/* identifiers */
|
||||||
ot->name = "Zoom View";
|
ot->name = "Zoom View";
|
||||||
ot->description = "Zoom in/out in the view";
|
ot->description = "Zoom in/out in the view";
|
||||||
ot->idname = "VIEW3D_OT_zoom";
|
ot->idname = viewops_operator_idname_get(V3D_OP_MODE_ZOOM);
|
||||||
|
|
||||||
/* api callbacks */
|
/* api callbacks */
|
||||||
ot->invoke = viewzoom_invoke;
|
ot->invoke = viewzoom_invoke;
|
||||||
ot->exec = viewzoom_exec;
|
ot->exec = viewzoom_exec;
|
||||||
ot->modal = viewzoom_modal;
|
ot->modal = view3d_navigate_modal_fn;
|
||||||
ot->poll = view3d_zoom_or_dolly_poll;
|
ot->poll = view3d_zoom_or_dolly_poll;
|
||||||
ot->cancel = view3d_navigate_cancel_fn;
|
ot->cancel = view3d_navigate_cancel_fn;
|
||||||
|
|
||||||
|
|
|
@ -139,9 +139,14 @@ static int an_stringdec(const char *string, char *head, char *tail, ushort *numl
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void an_stringenc(char *string, const char *head, const char *tail, ushort numlen, int pic)
|
static void an_stringenc(char *string,
|
||||||
|
const size_t string_maxncpy,
|
||||||
|
const char *head,
|
||||||
|
const char *tail,
|
||||||
|
ushort numlen,
|
||||||
|
int pic)
|
||||||
{
|
{
|
||||||
BLI_path_sequence_encode(string, head, tail, numlen, pic);
|
BLI_path_sequence_encode(string, string_maxncpy, head, tail, numlen, pic);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_AVI
|
#ifdef WITH_AVI
|
||||||
|
@ -1614,7 +1619,7 @@ struct ImBuf *IMB_anim_absolute(struct anim *anim,
|
||||||
case ANIM_SEQUENCE:
|
case ANIM_SEQUENCE:
|
||||||
pic = an_stringdec(anim->first, head, tail, &digits);
|
pic = an_stringdec(anim->first, head, tail, &digits);
|
||||||
pic += position;
|
pic += position;
|
||||||
an_stringenc(anim->name, head, tail, digits, pic);
|
an_stringenc(anim->name, sizeof(anim->name), head, tail, digits, pic);
|
||||||
ibuf = IMB_loadiffname(anim->name, IB_rect, anim->colorspace);
|
ibuf = IMB_loadiffname(anim->name, IB_rect, anim->colorspace);
|
||||||
if (ibuf) {
|
if (ibuf) {
|
||||||
anim->cur_position = position;
|
anim->cur_position = position;
|
||||||
|
|
|
@ -519,7 +519,10 @@ static std::string float3_to_string(const float3 &numbers)
|
||||||
MTLWriter::MTLWriter(const char *obj_filepath) noexcept(false)
|
MTLWriter::MTLWriter(const char *obj_filepath) noexcept(false)
|
||||||
{
|
{
|
||||||
mtl_filepath_ = obj_filepath;
|
mtl_filepath_ = obj_filepath;
|
||||||
const bool ok = BLI_path_extension_replace(mtl_filepath_.data(), FILE_MAX, ".mtl");
|
/* It only makes sense to replace this extension if it's at least as long as the existing one. */
|
||||||
|
BLI_assert(strlen(BLI_path_extension(obj_filepath)) == 4);
|
||||||
|
const bool ok = BLI_path_extension_replace(
|
||||||
|
mtl_filepath_.data(), mtl_filepath_.size() + 1, ".mtl");
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
throw std::system_error(ENAMETOOLONG, std::system_category(), "");
|
throw std::system_error(ENAMETOOLONG, std::system_category(), "");
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,8 +155,8 @@ static std::string get_image_filepath(const bNode *tex_node)
|
||||||
char head[FILE_MAX], tail[FILE_MAX];
|
char head[FILE_MAX], tail[FILE_MAX];
|
||||||
ushort numlen;
|
ushort numlen;
|
||||||
int framenr = static_cast<NodeTexImage *>(tex_node->storage)->iuser.framenr;
|
int framenr = static_cast<NodeTexImage *>(tex_node->storage)->iuser.framenr;
|
||||||
BLI_path_sequence_decode(path, head, tail, &numlen);
|
BLI_path_sequence_decode(path, head, sizeof(head), tail, sizeof(tail), &numlen);
|
||||||
BLI_path_sequence_encode(path, head, tail, numlen, framenr);
|
BLI_path_sequence_encode(path, sizeof(path), head, tail, numlen, framenr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
|
|
|
@ -279,7 +279,8 @@ class obj_exporter_regression_test : public obj_exporter_test {
|
||||||
strncpy(params.filepath, out_file_path.c_str(), FILE_MAX - 1);
|
strncpy(params.filepath, out_file_path.c_str(), FILE_MAX - 1);
|
||||||
params.blen_filepath = bfile->main->filepath;
|
params.blen_filepath = bfile->main->filepath;
|
||||||
std::string golden_file_path = blender::tests::flags_test_asset_dir() + SEP_STR + golden_obj;
|
std::string golden_file_path = blender::tests::flags_test_asset_dir() + SEP_STR + golden_obj;
|
||||||
BLI_split_dir_part(golden_file_path.c_str(), params.file_base_for_tests, PATH_MAX);
|
BLI_split_dir_part(
|
||||||
|
golden_file_path.c_str(), params.file_base_for_tests, sizeof(params.file_base_for_tests));
|
||||||
export_frame(depsgraph, params, out_file_path.c_str());
|
export_frame(depsgraph, params, out_file_path.c_str());
|
||||||
std::string output_str = read_temp_file_in_string(out_file_path);
|
std::string output_str = read_temp_file_in_string(out_file_path);
|
||||||
|
|
||||||
|
|
|
@ -688,6 +688,36 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!use_merge && !mesh->runtime->subsurf_optimal_display_edges.is_empty()) {
|
||||||
|
const BoundedBitSpan src = mesh->runtime->subsurf_optimal_display_edges;
|
||||||
|
|
||||||
|
result->runtime->subsurf_optimal_display_edges.resize(result->totedge);
|
||||||
|
MutableBoundedBitSpan dst = result->runtime->subsurf_optimal_display_edges;
|
||||||
|
for (const int i : IndexRange(count)) {
|
||||||
|
dst.slice({i * mesh->totedge, mesh->totedge}).copy_from(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start_cap_mesh) {
|
||||||
|
MutableBitSpan cap_bits = dst.slice(
|
||||||
|
{result_nedges - start_cap_nedges - end_cap_nedges, start_cap_mesh->totedge});
|
||||||
|
if (start_cap_mesh->runtime->subsurf_optimal_display_edges.is_empty()) {
|
||||||
|
cap_bits.set_all(true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cap_bits.copy_from(start_cap_mesh->runtime->subsurf_optimal_display_edges);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (end_cap_mesh) {
|
||||||
|
MutableBitSpan cap_bits = dst.slice({result_nedges - end_cap_nedges, end_cap_mesh->totedge});
|
||||||
|
if (end_cap_mesh->runtime->subsurf_optimal_display_edges.is_empty()) {
|
||||||
|
cap_bits.set_all(true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cap_bits.copy_from(end_cap_mesh->runtime->subsurf_optimal_display_edges);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
last_chunk_start = (count - 1) * chunk_nverts;
|
last_chunk_start = (count - 1) * chunk_nverts;
|
||||||
last_chunk_nverts = chunk_nverts;
|
last_chunk_nverts = chunk_nverts;
|
||||||
|
|
||||||
|
|
|
@ -667,8 +667,12 @@ static void build_pict_list_ex(
|
||||||
|
|
||||||
char filepath[FILE_MAX];
|
char filepath[FILE_MAX];
|
||||||
BLI_strncpy(filepath, first, sizeof(filepath));
|
BLI_strncpy(filepath, first, sizeof(filepath));
|
||||||
fp_framenr = BLI_path_sequence_decode(
|
fp_framenr = BLI_path_sequence_decode(filepath,
|
||||||
filepath, fp_decoded.head, fp_decoded.tail, &fp_decoded.digits);
|
fp_decoded.head,
|
||||||
|
sizeof(fp_decoded.head),
|
||||||
|
fp_decoded.tail,
|
||||||
|
sizeof(fp_decoded.tail),
|
||||||
|
&fp_decoded.digits);
|
||||||
|
|
||||||
pupdate_time();
|
pupdate_time();
|
||||||
ptottime = 1.0;
|
ptottime = 1.0;
|
||||||
|
@ -774,8 +778,12 @@ static void build_pict_list_ex(
|
||||||
|
|
||||||
/* create a new filepath each time */
|
/* create a new filepath each time */
|
||||||
fp_framenr += fstep;
|
fp_framenr += fstep;
|
||||||
BLI_path_sequence_encode(
|
BLI_path_sequence_encode(filepath,
|
||||||
filepath, fp_decoded.head, fp_decoded.tail, fp_decoded.digits, fp_framenr);
|
sizeof(filepath),
|
||||||
|
fp_decoded.head,
|
||||||
|
fp_decoded.tail,
|
||||||
|
fp_decoded.digits,
|
||||||
|
fp_framenr);
|
||||||
|
|
||||||
while ((has_event = GHOST_ProcessEvents(g_WS.ghost_system, false))) {
|
while ((has_event = GHOST_ProcessEvents(g_WS.ghost_system, false))) {
|
||||||
GHOST_DispatchEvents(g_WS.ghost_system);
|
GHOST_DispatchEvents(g_WS.ghost_system);
|
||||||
|
|
Loading…
Reference in New Issue