Files
test/source/blender/modifiers/intern/MOD_meshcache_pc2.cc
Damien Picard 3bd41cf9bc I18n: Go over TIP_ and IFACE_ usages, change to RPT_ when relevant
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
2024-01-12 13:37:32 +01:00

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;
}