chore: checkpoint web Blender migration source, tools and docs
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled

Accumulated uncommitted work: GHOST Web backend, WebGL/GPU web layer,
web workflow engine and protocol, tooling, docs and task records.
Large generated evidence, user-testing archives, build snapshots and
imported test assets remain untracked.

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
mes123456
2026-11-10 11:18:01 +08:00
parent 122142c26c
commit f3e21c6b98
6887 changed files with 257154 additions and 12294 deletions

View File

@@ -29,6 +29,8 @@
#include "BKE_fcurve.hh"
#include "RNA_access_guard.hh"
namespace blender {
static CLG_LogRef LOG = {"anim.fmodifier"};
@@ -388,6 +390,7 @@ static void fcm_envelope_free(FModifier *fcm)
/* free envelope data array */
if (env->data) {
RNAPropertyAccessScope::invalidate_storage_array(env->data, env->totvert);
MEM_delete(env->data);
}
}
@@ -416,12 +419,74 @@ static void fcm_envelope_verify(FModifier *fcm)
{
FMod_Envelope *env = static_cast<FMod_Envelope *>(fcm->data);
/* if the are points, perform bubble-sort on them, as user may have changed the order */
if (env->data) {
/* XXX todo... */
/* Evaluation and insertion both require time order. Keep ties stable and
* retain every point, including its min/max and selection flags. */
if (env->data && env->totvert > 1) {
const auto less = [](const FCM_EnvelopeData &a, const FCM_EnvelopeData &b) {
return a.time < b.time;
};
if (!std::is_sorted(env->data, env->data + env->totvert, less)) {
RNAPropertyAccessScope::invalidate_storage_array(env->data, env->totvert);
std::stable_sort(env->data, env->data + env->totvert, less);
}
}
}
FCM_EnvelopeData *BKE_fcm_envelope_point_add(FModifier *fcm, const float frame)
{
FMod_Envelope *env = static_cast<FMod_Envelope *>(fcm->data);
bool exists = false;
const int index = env->data ?
BKE_fcm_envelope_find_index(env->data, frame, env->totvert, &exists) :
0;
if (exists) {
return nullptr;
}
RNAPropertyAccessScope::invalidate_storage_array(env->data, env->totvert);
env->data = env->data ?
static_cast<FCM_EnvelopeData *>(MEM_realloc_uninitialized(
env->data, sizeof(FCM_EnvelopeData) * (env->totvert + 1))) :
MEM_new<FCM_EnvelopeData>("FCM_EnvelopeData");
memmove(env->data + index + 1,
env->data + index,
sizeof(FCM_EnvelopeData) * (env->totvert - index));
env->data[index] = {};
env->data[index].time = frame;
env->data[index].min = -1.0f;
env->data[index].max = 1.0f;
env->totvert++;
return &env->data[index];
}
bool BKE_fcm_envelope_point_remove(FModifier *fcm, const FCM_EnvelopeData *point)
{
FMod_Envelope *env = static_cast<FMod_Envelope *>(fcm->data);
/* Equality is defined even for a point from another modifier; subtracting
* unrelated pointers is not. Never reinterpret a stale row index. */
int index = 0;
for (; index < env->totvert; index++) {
if (&env->data[index] == point) {
break;
}
}
if (index == env->totvert) {
return false;
}
RNAPropertyAccessScope::invalidate_storage_array(env->data, env->totvert);
memmove(env->data + index,
env->data + index + 1,
sizeof(FCM_EnvelopeData) * (env->totvert - index - 1));
env->totvert--;
if (env->totvert == 0) {
MEM_SAFE_DELETE(env->data);
}
else {
env->data = static_cast<FCM_EnvelopeData *>(MEM_realloc_uninitialized(
env->data, sizeof(FCM_EnvelopeData) * env->totvert));
}
return true;
}
static void fcm_envelope_evaluate(const FCurve * /*fcu*/,
const FModifier *fcm,
float *cvalue,
@@ -1287,6 +1352,12 @@ bool remove_fmodifier(ListBaseT<FModifier> *modifiers, FModifier *fcm)
return false;
}
/* Strip modifiers and control-curve modifiers share this native release.
* Notify before type-specific data destruction, while aliases still have
* their original identities. */
RNAPropertyAccessScope::invalidate_storage(fcm);
RNAPropertyAccessScope::invalidate_storage(fcm->data);
/* removing the cycles modifier requires a handle update */
FCurve *update_fcu = (fcm->type == FMODIFIER_TYPE_CYCLES) ? fcm->curve : nullptr;