-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathLingoRuntime.Clone.cs
98 lines (82 loc) · 2.92 KB
/
LingoRuntime.Clone.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
using System;
using System.Diagnostics.CodeAnalysis;
using Serilog;
namespace Drizzle.Lingo.Runtime;
public partial class LingoRuntime
{
public LingoRuntime Clone()
{
Log.Debug("Cloning Lingo runtime...");
var newRuntime = new LingoRuntime(_assembly);
newRuntime.InitNoCast();
CloneCast(this, newRuntime);
CloneGlobals(this, newRuntime);
return newRuntime;
}
private static void CloneCast(LingoRuntime src, LingoRuntime dst)
{
Log.Debug("Cloning cast...");
dst.InitCastLibs();
dst._castMemberNameIndexDirty = true;
for (var i = 0; i < src._castLibs.Length; i++)
{
var srcLib = src._castLibs[i];
var dstLib = dst._castLibs[i];
for (var j = 1; j <= srcLib.NumMembers; j++)
{
var srcMem = srcLib.GetMember(j)!;
var dstMem = dstLib.GetMember(j)!;
dstMem.CloneFrom(srcMem);
}
}
}
private static void CloneGlobals(LingoRuntime src, LingoRuntime dst)
{
Log.Debug("Cloning globals...");
var srcMovieScript = src.MovieScriptInstance;
var dstMovieScript = dst.MovieScriptInstance;
foreach (var field in srcMovieScript.GetType().GetFields())
{
if (!Attribute.IsDefined(field, typeof(LingoGlobalAttribute)))
continue;
var srcValue = field.GetValue(srcMovieScript);
field.SetValue(dstMovieScript, DeepClone(srcValue));
}
[return: NotNullIfNotNull("value")]
object? DeepClone(object? value)
{
if (value is LingoList list)
{
var newList = new LingoList(list.List.Count);
foreach (var listValue in list.List)
{
newList.List.Add(DeepClone(listValue));
}
return newList;
}
if (value is LingoPropertyList propList)
{
var newList = new LingoPropertyList(propList.Dict.Count);
foreach (var (key, dictValue) in propList.Dict)
{
newList.Dict.Add(DeepClone(key), DeepClone(dictValue));
}
return newList;
}
if (value is LingoScriptRuntimeBase script)
{
var scriptType = script.GetType();
var newScript = dst.InstantiateScriptType(scriptType);
newScript.Init(dstMovieScript, dst.Global);
foreach (var field in scriptType.GetFields())
{
if (!Attribute.IsDefined(field, typeof(LingoPropertyAttribute)))
continue;
var srcValue = field.GetValue(script);
field.SetValue(newScript, DeepClone(srcValue));
}
}
return value;
}
}
}