Skip to content

Commit a71cbf4

Browse files
図形内エフェクトによる例外を修正
1 parent 3b0dee9 commit a71cbf4

File tree

3 files changed

+32
-83
lines changed

3 files changed

+32
-83
lines changed

AddShapeEffect/AddShapeEffectProcessor.cs

Lines changed: 19 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,17 @@ internal class AddShapeEffectProcessor : IVideoEffectProcessor
1616
readonly VideoEffectChainNode chain;
1717
int oldLenOfEffects;
1818

19-
2019
DisposeCollector disposer = new();
21-
2220
bool isFirst = true;
2321
IShapeParameter? shapeParameter;
24-
2522
IShapeSource? shapeSource;
2623

2724
private readonly Transform3D transformEffect;
28-
2925
private readonly Opacity opacityEffect;
30-
3126
private readonly Transform3D inputTransformEffect;
32-
3327
private readonly AlphaMask alphaMaskEffect;
3428
private readonly Composite finalCompositeEffect;
3529

36-
3730
public ID2D1Image Output { get; }
3831

3932
public AddShapeEffectProcessor(IGraphicsDevicesAndContext devices, AddShapeEffect item)
@@ -45,24 +38,19 @@ public AddShapeEffectProcessor(IGraphicsDevicesAndContext devices, AddShapeEffec
4538

4639
transformEffect = new Transform3D(devices.DeviceContext);
4740
disposer.Collect(transformEffect);
48-
4941
opacityEffect = new Opacity(devices.DeviceContext);
5042
disposer.Collect(opacityEffect);
51-
5243
inputTransformEffect = new Transform3D(devices.DeviceContext);
5344
disposer.Collect(inputTransformEffect);
54-
55-
5645
alphaMaskEffect = new AlphaMask(devices.DeviceContext);
5746
disposer.Collect(alphaMaskEffect);
58-
5947
finalCompositeEffect = new Composite(devices.DeviceContext);
6048
disposer.Collect(finalCompositeEffect);
6149

6250
Output = finalCompositeEffect.Output;
6351
disposer.Collect(Output);
64-
6552
}
53+
6654
public DrawDescription Update(EffectDescription effectDescription)
6755
{
6856
long Frame = effectDescription.ItemPosition.Frame;
@@ -71,13 +59,11 @@ public DrawDescription Update(EffectDescription effectDescription)
7159

7260
ID2D1Image? shapeOutputImage = null;
7361
ID2D1Image? transformedShapeImage = null;
74-
ID2D1Image? maskedShapeImage = null;
7562
DrawDescription descAfterChain = effectDescription.DrawDescription;
7663
inputTransformEffect.TransformMatrix = Matrix4x4.Identity;
7764

7865
{
7966
var shapeParameter = item.ShapeParameter;
80-
8167
if (isFirst || this.shapeParameter != shapeParameter)
8268
{
8369
if (shapeSource is not null) { disposer.RemoveAndDispose(ref shapeSource); }
@@ -93,27 +79,16 @@ public DrawDescription Update(EffectDescription effectDescription)
9379
if (shapeSource is not null)
9480
{
9581
shapeSource.Update(effectDescription);
96-
ID2D1Image current = shapeSource.Output;
97-
98-
shapeOutputImage = current;
82+
shapeOutputImage = shapeSource.Output;
9983
}
10084
}
85+
10186
if (shapeOutputImage != null)
10287
{
10388
chain.SetInput(shapeOutputImage);
104-
DrawDescription initialDesc;
105-
initialDesc = new(
106-
effectDescription.DrawDescription.Draw,
107-
new System.Numerics.Vector2(0, 0),
108-
new System.Numerics.Vector2(1f, 1f),
109-
new System.Numerics.Vector3(0, 0, 0),
110-
effectDescription.DrawDescription.Camera,
111-
effectDescription.DrawDescription.ZoomInterpolationMode,
112-
1.0f,
113-
false,
114-
effectDescription.DrawDescription.Controllers
115-
);
11689

90+
// 【修正】引数を effectDescription だけにして、内部プロパティへの直接参照を回避
91+
descAfterChain = chain.UpdateOutputAndDescription(effectDescription);
11792
ID2D1Image imageAfterChain = chain.Output;
11893

11994
var x = (float)item.X.GetValue(Frame, length, FPS);
@@ -122,58 +97,48 @@ public DrawDescription Update(EffectDescription effectDescription)
12297
var rotX = (float)item.RotationX.GetValue(Frame, length, FPS);
12398
var rotY = (float)item.RotationY.GetValue(Frame, length, FPS);
12499
var rotZ = (float)item.RotationZ.GetValue(Frame, length, FPS);
125-
var zoomItem = (float)item.Zoom.GetValue(Frame, length, FPS) / 100.0f;
100+
101+
var zoomItem = Math.Max(0.0001f, (float)item.Zoom.GetValue(Frame, length, FPS) / 100.0f);
126102
var zoomXItem = (float)item.ZoomX.GetValue(Frame, length, FPS) / 100.0f;
127103
var zoomYItem = (float)item.ZoomY.GetValue(Frame, length, FPS) / 100.0f;
128104
var opacityItem = (float)item.Opacity.GetValue(Frame, length, FPS) / 100.0f;
129-
float finalOpacity = opacityItem;
130105

131106
if (item.InvertX) zoomXItem *= -1f;
132107
if (item.InvertY) zoomYItem *= -1f;
133-
Matrix4x4 scale = Matrix4x4.CreateScale(
134-
zoomXItem * zoomItem,
135-
zoomYItem * zoomItem,
136-
1.0f);
108+
109+
Matrix4x4 scale = Matrix4x4.CreateScale(zoomXItem * zoomItem, zoomYItem * zoomItem, 1.0f);
137110
Matrix4x4 rotXMat = Matrix4x4.CreateRotationX((float)MathHelper.ToRadians(rotX));
138111
Matrix4x4 rotYMat = Matrix4x4.CreateRotationY((float)MathHelper.ToRadians(rotY));
139112
Matrix4x4 rotZMat = Matrix4x4.CreateRotationZ((float)MathHelper.ToRadians(rotZ));
140113

141114
float cameraDistance = 1000.0f;
142115
Matrix4x4 perspective = Matrix4x4.Identity;
143116
perspective.M34 = -1.0f / cameraDistance;
144-
145117
Matrix4x4 translation = Matrix4x4.CreateTranslation(x, y, z);
146118

147-
Matrix4x4 finalTransform =
148-
scale *
149-
rotXMat *
150-
rotYMat *
151-
rotZMat *
152-
translation *
153-
perspective;
119+
Matrix4x4 finalTransform = scale * rotXMat * rotYMat * rotZMat * translation * perspective;
154120

155121
transformEffect.SetInput(0, imageAfterChain, true);
156122
transformEffect.TransformMatrix = finalTransform;
157-
158123
opacityEffect.SetInput(0, transformEffect.Output, true);
159-
160-
opacityEffect.SetValue(0, finalOpacity);
124+
opacityEffect.SetValue(0, opacityItem);
161125

162126
transformedShapeImage = opacityEffect.Output;
163127
}
164128
else
165129
{
166-
chain.ClearChain();
130+
chain.ClearInput();
167131
transformedShapeImage = null;
168132
}
133+
169134
ID2D1Image? compositeInput1 = transformedShapeImage;
170135
if (item.IsClippingEnabled && compositeInput1 != null)
171136
{
172137
alphaMaskEffect.SetInput(0, compositeInput1, true);
173138
alphaMaskEffect.SetInput(1, finalCompositeEffect.GetInput(0), true);
174-
maskedShapeImage = alphaMaskEffect.Output;
175-
compositeInput1 = maskedShapeImage;
139+
compositeInput1 = alphaMaskEffect.Output;
176140
}
141+
177142
if (compositeInput1 != null)
178143
{
179144
finalCompositeEffect.SetInput(1, compositeInput1, true);
@@ -192,13 +157,12 @@ public void ClearInput()
192157
{
193158
finalCompositeEffect.SetInput(0, null, true);
194159
finalCompositeEffect.SetInput(1, null, true);
195-
196160
inputTransformEffect.SetInput(0, null, true);
197-
161+
transformEffect.SetInput(0, null, true);
162+
opacityEffect.SetInput(0, null, true);
198163
alphaMaskEffect.SetInput(0, null, true);
199164
alphaMaskEffect.SetInput(1, null, true);
200165
if (shapeSource is not null) { disposer.RemoveAndDispose(ref shapeSource); }
201-
202166
isFirst = true;
203167
shapeParameter = null;
204168
chain.ClearInput();
@@ -210,14 +174,13 @@ public void Dispose()
210174
chain.Dispose();
211175
inputTransformEffect.Dispose();
212176
}
177+
213178
public void SetInput(ID2D1Image? input)
214179
{
215180
inputTransformEffect.SetInput(0, input, true);
216-
217181
finalCompositeEffect.SetInput(0, inputTransformEffect.Output, true);
218-
219182
chain.SetInput(input);
220183
chain.UpdateChain(item.Effects);
221184
}
222185
}
223-
}
186+
}

AddShapeEffect/Types.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ internal static class Types
1616

1717
public static Type? NumberText = YukkuriMovieMakerPluginCommunity.GetType("YukkuriMovieMaker.Plugin.Community.Shape.NumberText.NumberText");
1818
}
19-
}
19+
}

AddShapeEffect/VideoEffectChainNode.cs

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,10 @@ public VideoEffectChainNode(IGraphicsDevicesAndContext devices)
2525
this.devices = devices;
2626
transform = new AffineTransform2D(devices.DeviceContext);
2727
output = transform.Output;
28-
2928
empty = devices.DeviceContext.CreateEmptyBitmap();
30-
3129
isEmpty = true;
3230
}
31+
3332
public void UpdateChain(ImmutableList<IVideoEffect> effects)
3433
{
3534
var disposedIndex = from tuple in Chain
@@ -52,7 +51,6 @@ orderby i descending
5251
int index = keeped.IndexOf(effect);
5352
newChain.Add(index < 0 ? (effect, effect.CreateVideoEffect(devices)) : Chain[index]);
5453
}
55-
5654
Chain = newChain;
5755
}
5856

@@ -62,6 +60,7 @@ public void SetInput(ID2D1Image? input)
6260
if (input == null)
6361
{
6462
isEmpty = true;
63+
transform.SetInput(0, null, true);
6564
return;
6665
}
6766
else
@@ -102,39 +101,27 @@ public void ClearInput()
102101
Chain.Clear();
103102
}
104103

105-
public DrawDescription UpdateOutputAndDescription(TimelineItemSourceDescription timelineSourceDescription, DrawDescription drawDescription)
104+
// 引数を EffectDescription に変更し、内部で安全にプロパティを解決
105+
public DrawDescription UpdateOutputAndDescription(EffectDescription effectDescription)
106106
{
107107
if (input == null)
108108
{
109109
isEmpty = true;
110-
return drawDescription;
110+
transform.SetInput(0, null, true);
111+
return effectDescription.DrawDescription;
111112
}
112113

113-
fl.UpdateFrom(timelineSourceDescription);
114-
DrawDescription desc = new(
115-
drawDescription.Draw,
116-
drawDescription.CenterPoint,
117-
drawDescription.Zoom,
118-
drawDescription.Rotation,
119-
drawDescription.Camera,
120-
drawDescription.ZoomInterpolationMode,
121-
drawDescription.Opacity,
122-
drawDescription.Invert,
123-
drawDescription.Controllers
124-
);
125-
126114
ID2D1Image? image = input;
115+
DrawDescription desc = effectDescription.DrawDescription;
116+
127117
foreach (var (effect, processor) in Chain)
128118
{
129119
if (effect.IsEnabled)
130120
{
131-
IVideoEffectProcessor item = processor;
132-
item.SetInput(image);
133-
TimelineItemSourceDescription timeLineItemSourceDescription
134-
= new(timelineSourceDescription, fl.Frame, fl.Length, 0);
135-
EffectDescription effectDescription = new(timeLineItemSourceDescription, desc, 0, 1);
136-
desc = item.Update(effectDescription);
137-
image = item.Output;
121+
processor.SetInput(image);
122+
// 個別のエフェクトを更新。元の effectDescription をそのまま渡すのが最も安全
123+
desc = processor.Update(effectDescription with { DrawDescription = desc });
124+
image = processor.Output;
138125
}
139126
}
140127

@@ -149,7 +136,6 @@ public void Dispose()
149136
transform.Dispose();
150137
empty.Dispose();
151138
output.Dispose();
152-
153139
Chain.ForEach(i =>
154140
{
155141
i.processor.ClearInput();

0 commit comments

Comments
 (0)