The previous commit introduced a new `RPT_()` macro to translate strings which are not tooltips or regular interface elements, but longer reports or statuses. This commit uses the new macro to translate many strings all over the UI. Most of it is a simple replace from `TIP_()` or `IFACE_()` to `RPT_()`, but there are some additional changes: - A few translations inside `BKE_report()` are removed altogether because they are already handled by the translation system. - Messages inside `UI_but_disable()` are no longer translated manually, but they are handled by a new regex in the translation system. Pull Request: https://projects.blender.org/blender/blender/pulls/116804 Pull Request: https://projects.blender.org/blender/blender/pulls/116804
283 lines
7.4 KiB
C++
283 lines
7.4 KiB
C++
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup modifiers
|
|
*/
|
|
|
|
#include <cerrno>
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
#include "BLI_fileops.h"
|
|
#ifdef __BIG_ENDIAN__
|
|
# include "BLI_endian_switch.h"
|
|
#endif
|
|
|
|
#ifdef WIN32
|
|
# include "BLI_winstuff.h"
|
|
#endif
|
|
|
|
#include "BLT_translation.h"
|
|
|
|
#include "DNA_modifier_types.h"
|
|
|
|
#include "MOD_meshcache_util.hh" /* own include */
|
|
|
|
struct PC2Head {
|
|
char header[12]; /* 'POINTCACHE2\0' */
|
|
int file_version; /* unused - should be 1 */
|
|
int verts_tot;
|
|
float start;
|
|
float sampling;
|
|
int frame_tot;
|
|
}; /* frames, verts */
|
|
|
|
static bool meshcache_read_pc2_head(FILE *fp,
|
|
const int verts_tot,
|
|
PC2Head *pc2_head,
|
|
const char **err_str)
|
|
{
|
|
if (!fread(pc2_head, sizeof(*pc2_head), 1, fp)) {
|
|
*err_str = RPT_("Missing header");
|
|
return false;
|
|
}
|
|
|
|
if (!STREQ(pc2_head->header, "POINTCACHE2")) {
|
|
*err_str = RPT_("Invalid header");
|
|
return false;
|
|
}
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
BLI_endian_switch_int32_array(&pc2_head->file_version,
|
|
(sizeof(*pc2_head) - sizeof(pc2_head->header)) / sizeof(int));
|
|
#endif
|
|
|
|
if (pc2_head->verts_tot != verts_tot) {
|
|
*err_str = RPT_("Vertex count mismatch");
|
|
return false;
|
|
}
|
|
|
|
if (pc2_head->frame_tot <= 0) {
|
|
*err_str = RPT_("Invalid frame total");
|
|
return false;
|
|
}
|
|
/* Intentionally don't seek back. */
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Gets the index range and factor
|
|
*
|
|
* currently same as for MDD
|
|
*/
|
|
static bool meshcache_read_pc2_range(FILE *fp,
|
|
const int verts_tot,
|
|
const float frame,
|
|
const char interp,
|
|
int r_index_range[2],
|
|
float *r_factor,
|
|
const char **err_str)
|
|
{
|
|
PC2Head pc2_head;
|
|
|
|
/* first check interpolation and get the vert locations */
|
|
|
|
if (meshcache_read_pc2_head(fp, verts_tot, &pc2_head, err_str) == false) {
|
|
return false;
|
|
}
|
|
|
|
MOD_meshcache_calc_range(frame, interp, pc2_head.frame_tot, r_index_range, r_factor);
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool meshcache_read_pc2_range_from_time(FILE *fp,
|
|
const int verts_tot,
|
|
const float time,
|
|
const float fps,
|
|
float *r_frame,
|
|
const char **err_str)
|
|
{
|
|
PC2Head pc2_head;
|
|
float frame;
|
|
|
|
if (meshcache_read_pc2_head(fp, verts_tot, &pc2_head, err_str) == false) {
|
|
return false;
|
|
}
|
|
|
|
frame = ((time / fps) - pc2_head.start) / pc2_head.sampling;
|
|
|
|
if (frame >= pc2_head.frame_tot) {
|
|
frame = float(pc2_head.frame_tot - 1);
|
|
}
|
|
else if (frame < 0.0f) {
|
|
frame = 0.0f;
|
|
}
|
|
|
|
*r_frame = frame;
|
|
return true;
|
|
}
|
|
|
|
bool MOD_meshcache_read_pc2_index(FILE *fp,
|
|
float (*vertexCos)[3],
|
|
const int verts_tot,
|
|
const int index,
|
|
const float factor,
|
|
const char **err_str)
|
|
{
|
|
PC2Head pc2_head;
|
|
|
|
if (meshcache_read_pc2_head(fp, verts_tot, &pc2_head, err_str) == false) {
|
|
return false;
|
|
}
|
|
|
|
if (BLI_fseek(fp, sizeof(float[3]) * index * pc2_head.verts_tot, SEEK_CUR) != 0) {
|
|
*err_str = RPT_("Failed to seek frame");
|
|
return false;
|
|
}
|
|
|
|
size_t verts_read_num = 0;
|
|
errno = 0;
|
|
if (factor >= 1.0f) {
|
|
float *vco = *vertexCos;
|
|
uint i;
|
|
for (i = pc2_head.verts_tot; i != 0; i--, vco += 3) {
|
|
verts_read_num += fread(vco, sizeof(float[3]), 1, fp);
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
BLI_endian_switch_float(vco + 0);
|
|
BLI_endian_switch_float(vco + 1);
|
|
BLI_endian_switch_float(vco + 2);
|
|
#endif /* __BIG_ENDIAN__ */
|
|
}
|
|
}
|
|
else {
|
|
const float ifactor = 1.0f - factor;
|
|
float *vco = *vertexCos;
|
|
uint i;
|
|
for (i = pc2_head.verts_tot; i != 0; i--, vco += 3) {
|
|
float tvec[3];
|
|
verts_read_num += fread(tvec, sizeof(float[3]), 1, fp);
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
BLI_endian_switch_float(tvec + 0);
|
|
BLI_endian_switch_float(tvec + 1);
|
|
BLI_endian_switch_float(tvec + 2);
|
|
#endif /* __BIG_ENDIAN__ */
|
|
|
|
vco[0] = (vco[0] * ifactor) + (tvec[0] * factor);
|
|
vco[1] = (vco[1] * ifactor) + (tvec[1] * factor);
|
|
vco[2] = (vco[2] * ifactor) + (tvec[2] * factor);
|
|
}
|
|
}
|
|
|
|
if (verts_read_num != pc2_head.verts_tot) {
|
|
*err_str = errno ? strerror(errno) : RPT_("Vertex coordinate read failed");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool MOD_meshcache_read_pc2_frame(FILE *fp,
|
|
float (*vertexCos)[3],
|
|
const int verts_tot,
|
|
const char interp,
|
|
const float frame,
|
|
const char **err_str)
|
|
{
|
|
int index_range[2];
|
|
float factor;
|
|
|
|
if (meshcache_read_pc2_range(fp,
|
|
verts_tot,
|
|
frame,
|
|
interp,
|
|
index_range,
|
|
&factor, /* read into these values */
|
|
err_str) == false)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (index_range[0] == index_range[1]) {
|
|
/* read single */
|
|
if ((BLI_fseek(fp, 0, SEEK_SET) == 0) &&
|
|
MOD_meshcache_read_pc2_index(fp, vertexCos, verts_tot, index_range[0], 1.0f, err_str))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/* read both and interpolate */
|
|
if ((BLI_fseek(fp, 0, SEEK_SET) == 0) &&
|
|
MOD_meshcache_read_pc2_index(fp, vertexCos, verts_tot, index_range[0], 1.0f, err_str) &&
|
|
(BLI_fseek(fp, 0, SEEK_SET) == 0) &&
|
|
MOD_meshcache_read_pc2_index(fp, vertexCos, verts_tot, index_range[1], factor, err_str))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool MOD_meshcache_read_pc2_times(const char *filepath,
|
|
float (*vertexCos)[3],
|
|
const int verts_tot,
|
|
const char interp,
|
|
const float time,
|
|
const float fps,
|
|
const char time_mode,
|
|
const char **err_str)
|
|
{
|
|
float frame;
|
|
|
|
FILE *fp = BLI_fopen(filepath, "rb");
|
|
bool ok;
|
|
|
|
if (fp == nullptr) {
|
|
*err_str = errno ? strerror(errno) : RPT_("Unknown error opening file");
|
|
return false;
|
|
}
|
|
|
|
switch (time_mode) {
|
|
case MOD_MESHCACHE_TIME_FRAME: {
|
|
frame = time;
|
|
break;
|
|
}
|
|
case MOD_MESHCACHE_TIME_SECONDS: {
|
|
/* we need to find the closest time */
|
|
if (meshcache_read_pc2_range_from_time(fp, verts_tot, time, fps, &frame, err_str) == false) {
|
|
fclose(fp);
|
|
return false;
|
|
}
|
|
rewind(fp);
|
|
break;
|
|
}
|
|
case MOD_MESHCACHE_TIME_FACTOR:
|
|
default: {
|
|
PC2Head pc2_head;
|
|
if (meshcache_read_pc2_head(fp, verts_tot, &pc2_head, err_str) == false) {
|
|
fclose(fp);
|
|
return false;
|
|
}
|
|
|
|
frame = CLAMPIS(time, 0.0f, 1.0f) * float(pc2_head.frame_tot);
|
|
rewind(fp);
|
|
break;
|
|
}
|
|
}
|
|
|
|
ok = MOD_meshcache_read_pc2_frame(fp, vertexCos, verts_tot, interp, frame, err_str);
|
|
|
|
fclose(fp);
|
|
return ok;
|
|
}
|