Skip to content

Commit 339855a

Browse files
committed
Change tracking improvements
Add few more type checks to handle new types introduced by ZoneImporter. This will continue to be updated as other importers are added. I think a more general approach should be made for structs and classes so any struct/class field is supported. Structs and classes that don't inherit `EditorObject` will likely be treated as plain data. It might need a concept of ownership too. That would let the system distinguish between referenced objects and fields which must be classes to manage complex data. Though if they're complex enough to be a class maybe they should be required to inherit `EditorObject`. I'll figure it out as I work on the remaining importers. They'll have more complex data to test with.
1 parent cf8de5b commit 339855a

File tree

3 files changed

+80
-21
lines changed

3 files changed

+80
-21
lines changed

Dependencies/Common

src/App/Project/Snapshot.bf

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,12 @@ namespace Nanoforge.App.Project
7676
Compiler.EmitTypeBody(selfType, "}\n");
7777
}
7878

79-
//Generate ISnapshot.Commit()
79+
//Generate ISnapshot.GenerateDiffTransactions()
8080
[Comptime]
8181
public static void EmitGenerateDiffTransactions()
8282
{
8383
Type selfType = typeof(Self);
84-
var genericTypeName = typeof(T).GetFullName(.. scope .());
84+
StringView genericTypeName = typeof(T).GetFullName(.. scope .());
8585

8686
Compiler.EmitTypeBody(selfType, scope $"\npublic virtual void GenerateDiffTransactions(List<ITransaction> transactions)");
8787
Compiler.EmitTypeBody(selfType, "\n{\n");
@@ -98,16 +98,37 @@ namespace Nanoforge.App.Project
9898
switch (fieldType)
9999
{
100100
case typeof(i8), typeof(i16), typeof(i32), typeof(i64), typeof(int), typeof(u8), typeof(u16), typeof(u32), typeof(u64), typeof(bool), typeof(f32), typeof(f64),
101-
typeof(Vec2<f32>), typeof(Vec3<f32>), typeof(Vec4<f32>), typeof(Mat2), typeof(Mat3), typeof(Mat4), typeof(Rect), typeof(String):
101+
typeof(Vec2<f32>), typeof(Vec3<f32>), typeof(Vec4<f32>), typeof(Mat2), typeof(Mat3), typeof(Mat4), typeof(Rect), typeof(BoundingBox), typeof(String):
102102
Compiler.EmitTypeBody(selfType, scope $" if (this.{fieldName} != S_Target.{fieldName})\n");
103103
Compiler.EmitTypeBody(selfType, " {\n");
104104
Compiler.EmitTypeBody(selfType, scope $" transactions.Add(new SetPropertyTransaction<{genericTypeName}, {fieldTypeName}, \"{fieldName}\">(S_Target, this.{fieldName}, S_Target.{fieldName}));\n");
105105
Compiler.EmitTypeBody(selfType, " }\n");
106106
default:
107-
Compiler.EmitTypeBody(selfType, scope $" //Failed to emit code for {field.FieldType.GetFullName(.. scope .())} {fieldName}");
108-
Compiler.EmitTypeBody(selfType, "\n");
109-
//Note: Temporarily disabled while the zone importers and projectDB are being developed
110-
//Runtime.FatalError(scope $"Unsupported type '{fieldTypeName}' used in editor property {genericTypeName}.{fieldName}. Please implement in Snapshot<T>.GenerateCommit()");
107+
if (fieldType.HasInterface(typeof(IList)))
108+
{
109+
Compiler.EmitTypeBody(selfType, scope $" if (this.{fieldName} != S_Target.{fieldName})\n");
110+
Compiler.EmitTypeBody(selfType, " {\n");
111+
Compiler.EmitTypeBody(selfType, scope $" {genericTypeName} target = S_Target;\n");
112+
Compiler.EmitTypeBody(selfType, scope $" {fieldTypeName} initialValue = this.{fieldName}.ShallowClone(.. new {fieldTypeName}());\n");
113+
Compiler.EmitTypeBody(selfType, scope $" {fieldTypeName} finalValue = S_Target.{fieldName}.ShallowClone(.. new {fieldTypeName}());\n");
114+
Compiler.EmitTypeBody(selfType, scope $" var transaction = new SetPropertyTransaction<{genericTypeName}, {fieldTypeName}, \"{fieldName}\">(target, initialValue, finalValue);\n");
115+
Compiler.EmitTypeBody(selfType, scope $" transactions.Add(transaction);\n");
116+
Compiler.EmitTypeBody(selfType, " }\n");
117+
}
118+
else if (fieldType.BaseType == typeof(Enum) || fieldType.BaseType == typeof(EditorObject))
119+
{
120+
Compiler.EmitTypeBody(selfType, scope $" if (this.{fieldName} != S_Target.{fieldName})\n");
121+
Compiler.EmitTypeBody(selfType, " {\n");
122+
Compiler.EmitTypeBody(selfType, scope $" transactions.Add(new SetPropertyTransaction<{genericTypeName}, {fieldTypeName}, \"{fieldName}\">(S_Target, this.{fieldName}, S_Target.{fieldName}));\n");
123+
Compiler.EmitTypeBody(selfType, " }\n");
124+
}
125+
else
126+
{
127+
Compiler.EmitTypeBody(selfType, scope $" //Failed to emit ISnapshot.GenerateDiffTransactions() for {field.FieldType.GetFullName(.. scope .())} {fieldName}\n");
128+
StringView baseTypeName = fieldType.BaseType != null ? fieldType.BaseType.GetFullName(.. scope .()) : "";
129+
Compiler.EmitTypeBody(selfType, "}\n");
130+
Runtime.FatalError(scope $"Unsupported type '{fieldTypeName}' used in editor property {genericTypeName}.{fieldName}. BaseTypeName = {baseTypeName}. Please implement in Snapshot<T>.GenerateDiffTransactions()");
131+
}
111132
}
112133
}
113134
Compiler.EmitTypeBody(selfType, "}\n");
@@ -132,22 +153,32 @@ namespace Nanoforge.App.Project
132153
if (result == .Err)
133154
continue;
134155

156+
Type fieldType = field.FieldType;
135157
StringView fieldName = field.Name;
136-
StringView fieldTypeName = field.FieldType.GetFullName(.. scope .());
158+
StringView fieldTypeName = fieldType.GetFullName(.. scope .());
137159
switch (field.FieldType)
138160
{
139161
case typeof(i8), typeof(i16), typeof(i32), typeof(i64), typeof(int), typeof(u8), typeof(u16), typeof(u32), typeof(u64), typeof(bool), typeof(f32), typeof(f64),
140-
typeof(Vec2<f32>), typeof(Vec3<f32>), typeof(Vec4<f32>), typeof(Mat2), typeof(Mat3), typeof(Mat4), typeof(Rect):
162+
typeof(Vec2<f32>), typeof(Vec3<f32>), typeof(Vec4<f32>), typeof(Mat2), typeof(Mat3), typeof(Mat4), typeof(Rect), typeof(BoundingBox):
141163
Compiler.EmitTypeBody(selfType, scope $" targetTyped.[Friend]{fieldName} = this.{fieldName};\n");
142164
case typeof(String):
143165
Compiler.EmitTypeBody(selfType, scope $" targetTyped.[Friend]{fieldName}.Set(this.{fieldName});\n");
144-
case typeof(List<Zone>), typeof(List<ZoneObject>):
145-
Compiler.EmitTypeBody(selfType, scope $" targetTyped.[Friend]{fieldName}.Set(this.{fieldName});\n");
146166
default:
147-
Compiler.EmitTypeBody(selfType, scope $" //Failed to emit code for {field.FieldType.GetFullName(.. scope .())} {fieldName}");
148-
Compiler.EmitTypeBody(selfType, "\n");
149-
//Note: Temporarily disabled while the zone importers and projectDB are being developed
150-
//Runtime.FatalError(scope $"Unsupported type '{fieldTypeName}' used in editor property {genericTypeName}.{fieldName}. Please implement in Snapshot<T>.GenerateApply()");
167+
if (fieldType.HasInterface(typeof(IList)))
168+
{
169+
Compiler.EmitTypeBody(selfType, scope $" targetTyped.[Friend]{fieldName}.Set(this.{fieldName});\n");
170+
}
171+
else if (fieldType.BaseType == typeof(Enum) || fieldType.BaseType == typeof(EditorObject))
172+
{
173+
Compiler.EmitTypeBody(selfType, scope $" targetTyped.[Friend]{fieldName} = this.{fieldName};\n");
174+
}
175+
else
176+
{
177+
Compiler.EmitTypeBody(selfType, scope $" //Failed to emit code for {field.FieldType.GetFullName(.. scope .())} {fieldName}\n");
178+
StringView baseTypeName = fieldType.BaseType != null ? fieldType.BaseType.GetFullName(.. scope .()) : "";
179+
Compiler.EmitTypeBody(selfType, "}\n");
180+
Runtime.FatalError(scope $"Unsupported type '{fieldTypeName}' used in editor property {genericTypeName}.{fieldName}. BaseTypeName = {baseTypeName}. Please implement in Snapshot<T>.GenerateApply()");
181+
}
151182
}
152183
}
153184
}

src/App/Project/Transaction.bf

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,31 @@ namespace Nanoforge.App.Project
7676
public static void EmitApply()
7777
{
7878
Type selfType = typeof(Self);
79+
Type fieldType = typeof(U);
7980
Compiler.EmitTypeBody(selfType, scope $"\npublic virtual void Apply()");
8081
Compiler.EmitTypeBody(selfType, "\n{\n");
81-
switch (typeof(U))
82+
switch (fieldType)
8283
{
8384
case typeof(i8), typeof(i16), typeof(i32), typeof(i64), typeof(int), typeof(u8), typeof(u16), typeof(u32), typeof(u64), typeof(bool), typeof(f32), typeof(f64),
84-
typeof(Vec2<f32>), typeof(Vec3<f32>), typeof(Vec4<f32>), typeof(Mat2), typeof(Mat3), typeof(Mat4), typeof(Rect):
85+
typeof(Vec2<f32>), typeof(Vec3<f32>), typeof(Vec4<f32>), typeof(Mat2), typeof(Mat3), typeof(Mat4), typeof(Rect), typeof(BoundingBox):
8586
Compiler.EmitTypeBody(selfType, scope $" _target.{V} = _finalValue;\n");
8687
case typeof(String):
8788
Compiler.EmitTypeBody(selfType, scope $" _target.{V}.Set(_finalValue);\n");
8889
default:
89-
Runtime.FatalError(scope $"Unsupported type '{typeof(U).GetFullName(.. scope .())}' used in editor property {typeof(T).GetFullName(.. scope .())}.{V}. Please implement in Snapshot<T>.GenerateCommit()");
90+
if (fieldType.HasInterface(typeof(IList)))
91+
{
92+
Compiler.EmitTypeBody(selfType, scope $" _target.{V}.Set(_finalValue);\n");
93+
}
94+
else if (fieldType.BaseType == typeof(Enum) || fieldType.BaseType == typeof(EditorObject))
95+
{
96+
Compiler.EmitTypeBody(selfType, scope $" _target.{V} = _finalValue;\n");
97+
}
98+
else
99+
{
100+
Compiler.EmitTypeBody(selfType, scope $" //Failed to emit code for {typeof(U).GetFullName(.. scope .())} {V}\n");
101+
Compiler.EmitTypeBody(selfType, "}\n");
102+
Runtime.FatalError(scope $"Unsupported type '{typeof(U).GetFullName(.. scope .())}' used in editor property {typeof(T).GetFullName(.. scope .())}.{V}. Please implement in Snapshot<T>.GenerateCommit()");
103+
}
90104
}
91105
Compiler.EmitTypeBody(selfType, "}\n");
92106
}
@@ -95,17 +109,31 @@ namespace Nanoforge.App.Project
95109
public static void EmitRevert()
96110
{
97111
Type selfType = typeof(Self);
112+
Type fieldType = typeof(U);
98113
Compiler.EmitTypeBody(selfType, scope $"\npublic virtual void Revert()");
99114
Compiler.EmitTypeBody(selfType, "\n{\n");
100115
switch (typeof(U))
101116
{
102117
case typeof(i8), typeof(i16), typeof(i32), typeof(i64), typeof(int), typeof(u8), typeof(u16), typeof(u32), typeof(u64), typeof(bool), typeof(f32), typeof(f64),
103-
typeof(Vec2<f32>), typeof(Vec3<f32>), typeof(Vec4<f32>), typeof(Mat2), typeof(Mat3), typeof(Mat4), typeof(Rect):
118+
typeof(Vec2<f32>), typeof(Vec3<f32>), typeof(Vec4<f32>), typeof(Mat2), typeof(Mat3), typeof(Mat4), typeof(Rect), typeof(BoundingBox):
104119
Compiler.EmitTypeBody(selfType, scope $" _target.{V} = _initialValue;\n");
105120
case typeof(String):
106121
Compiler.EmitTypeBody(selfType, scope $" _target.{V}.Set(_initialValue);\n");
107122
default:
108-
Runtime.FatalError(scope $"Unsupported type '{typeof(U).GetFullName(.. scope .())}' used in editor property {typeof(T).GetFullName(.. scope .())}.{V}. Please implement in Snapshot<T>.GenerateRevert()");
123+
if (fieldType.HasInterface(typeof(IList)))
124+
{
125+
Compiler.EmitTypeBody(selfType, scope $" _target.{V}.Set(_initialValue);\n");
126+
}
127+
else if (fieldType.BaseType == typeof(Enum) || fieldType.BaseType == typeof(EditorObject))
128+
{
129+
Compiler.EmitTypeBody(selfType, scope $" _target.{V} = _initialValue;\n");
130+
}
131+
else
132+
{
133+
Compiler.EmitTypeBody(selfType, scope $" //Failed to emit code for {typeof(U).GetFullName(.. scope .())} {V}\n");
134+
Compiler.EmitTypeBody(selfType, "}\n");
135+
Runtime.FatalError(scope $"Unsupported type '{typeof(U).GetFullName(.. scope .())}' used in editor property {typeof(T).GetFullName(.. scope .())}.{V}. Please implement in Snapshot<T>.GenerateRevert()");
136+
}
109137
}
110138
Compiler.EmitTypeBody(selfType, "}\n");
111139
}

0 commit comments

Comments
 (0)