fix: bug-fix sweep across node, audio, render, plugin subsystems

Node core:
- MathNode/TrigonometryNode combo strings realigned with Operation enums
- mathbase scalar/vector operand pick no longer uses bitwise type checks
- NodeSetPositionAndDependenciesRecursively moves dependencies again
- RemoveAllKeyframes undo actually restores keyframes
- NodeGroup GetInputName null-deref guard, passthrough ids use input id
- NodeValueTable::Has is an exact type match; tag fallback only for
  empty tags; kStrCombo/kPushButton get data type names
- delete_all_keyframes no longer loops forever on unparented keyframes;
  keyframe-load failures propagate; rational interpolation falls back to
  double; OpacityEffect no longer leaks its internal MathNode

Audio/footage:
- AudioVisualWaveform: GetSummaryFromTime underflow OOB read, TrimIn
  prepend length bookkeeping, OverwriteSums source channel indexing
- PanNode inserts the pan value into the sample job (keyframed pan
  works); OutputParamsChanged is emitted on device change; PortAudio
  device indices are validated before Pa_GetDeviceInfo
- Footage: AdjustTimeByLoopMode no longer hangs/UBs on degenerate
  lengths, GetStreamIndex bounds-checked, CheckFootage clears stale
  state on missing files, failed probes are not cached,
  FootageDescription::Load requires its own root element

Render/track:
- ViewerOutput pushes the tagged samples value; TrackList disconnects
  the track-height lambda; GetTrackFromReference validity check
- RenderManager dummy backend: null-initialized threads, guarded
  decoder-cache/timer paths; Renderer::Destroy releases color cache
  shaders/textures; unknown dynamic backends no longer alias to oakgl
- SharedMemoryRegion POSIX attach validates segment size; ReadMessage
  skips blank lines instead of failing; GC counter clamped;
  IsRenderingCustomRange implemented; TimeOffsetNode gets a true
  inverse OutputTimeAdjustment; zero-speed clips return the held frame

Plugin/nodes:
- OliveClip: stored default region of definition is honored, on-demand
  images are cached; OliveHost sets host identity properties and logs
  instead of showing modal dialogs offscreen; Plugin.h dead decls gone
- DespillNode guards graph-less use with Rec.709 fallback; description
  typos fixed (despill, swirl); mosaic applies when only one axis
  matches; Windows-only Project filename separator test fixed
This commit is contained in:
2026-07-17 08:26:48 +08:00
parent d9a4e27045
commit 2aa921b215
61 changed files with 731 additions and 254 deletions
+15 -18
View File
@@ -214,16 +214,14 @@ TEST(MathNode, RetranslateSetsInputNamesAndComboStrings)
math.GetInputProperty(olive::MathNode::kMethodIn,
QStringLiteral("combo_str"))
.toStringList();
ASSERT_EQ(operations.size(), 6);
ASSERT_EQ(operations.size(), 5);
EXPECT_EQ(operations.at(0), QStringLiteral("Add"));
EXPECT_EQ(operations.at(1), QStringLiteral("Subtract"));
EXPECT_EQ(operations.at(2), QStringLiteral("Multiply"));
EXPECT_EQ(operations.at(3), QStringLiteral("Divide"));
// NOTE: kOpPower == 4, but the combo list has an empty string at index 4
// and "Power" at index 5, so the combo box is misaligned with the
// Operation enum (suspected bug, documented here).
EXPECT_TRUE(operations.at(4).isEmpty());
EXPECT_EQ(operations.at(5), QStringLiteral("Power"));
// The combo list matches the Operation enum exactly, so kOpPower == 4
// selects "Power"
EXPECT_EQ(operations.at(4), QStringLiteral("Power"));
}
TEST(MathNode, AddNumbers)
@@ -720,7 +718,7 @@ TEST(MathNode, AddVectorAndNumberIsNoOp)
EXPECT_FLOAT_EQ(result.toVec2().y(), 2.0f);
}
TEST(MathNode, NumberTimesVectorYieldsNoComputedValue)
TEST(MathNode, NumberTimesVectorScalesVector)
{
olive::ColorManager::SetUpDefaultConfig();
olive::Project project;
@@ -736,18 +734,17 @@ TEST(MathNode, NumberTimesVectorYieldsNoComputedValue)
QVector4D(1.0f, 2.0f, 3.0f, 4.0f)));
olive::Node::ConnectEdge(b, olive::NodeInput(math, olive::MathNode::kParamBIn));
// NOTE: With the number in parameter A and the vector in parameter B,
// ValueInternal() picks the *vector* as the number operand (the
// `val_a.type() & NodeValue::kMatrix` check is true for kFloat) and then
// pushes the result with type kFloat, which PushVector() drops. No
// computed value is produced, and nothing passes through into the output
// table either (suspected bug, documented here).
// With the number in parameter A and the vector in parameter B, the
// number is still picked as the number operand and the vector is scaled,
// mirroring MultiplyVectorByNumber with the operands swapped
olive::NodeValueTable table = GenerateMathTable(math);
EXPECT_EQ(table.Get(olive::NodeValue::kVec4).type(),
olive::NodeValue::kNone);
EXPECT_EQ(table.Get(olive::NodeValue::kFloat).type(),
olive::NodeValue::kNone);
olive::NodeValue result = table.Get(olive::NodeValue::kVec4);
ASSERT_EQ(result.type(), olive::NodeValue::kVec4);
const QVector4D vec = result.toVec4();
EXPECT_FLOAT_EQ(vec.x(), 2.0f);
EXPECT_FLOAT_EQ(vec.y(), 4.0f);
EXPECT_FLOAT_EQ(vec.z(), 6.0f);
EXPECT_FLOAT_EQ(vec.w(), 8.0f);
}
TEST(MathNode, MultiplyMatrixByVector)