11using System ;
22using System . Collections . Generic ;
3+ using System . IO ;
34using System . Linq ;
45using System . Text ;
56using System . Threading . Tasks ;
7+ using System . Drawing ;
8+ using System . Drawing . Imaging ;
69using FreneticUtilities . FreneticExtensions ;
710using FreneticUtilities . FreneticToolkit ;
811using Newtonsoft . Json ;
@@ -12,14 +15,9 @@ namespace DenizenModelsConverter
1215{
1316 public static class BBModelReader
1417 {
15- public static bool Verbose = false ;
16-
1718 public static void Debug ( string text )
1819 {
19- if ( Verbose )
20- {
21- Console . WriteLine ( $ "[Debug] { text } ") ;
22- }
20+ Program . Debug ( text ) ;
2321 }
2422
2523 public static BBModel Interpret ( string fileContent )
@@ -40,6 +38,7 @@ public static BBModel Interpret(string fileContent)
4038 JArray textures = ( JArray ) data [ "textures" ] ;
4139 JArray outliners = ( JArray ) data [ "outliner" ] ;
4240 JArray animations = ( JArray ) data [ "animations" ] ;
41+ Dictionary < string , int > elementNames = new ( ) , outlineNames = new ( ) ;
4342 if ( elements is not null )
4443 {
4544 Debug ( "Contains elements" ) ;
@@ -48,11 +47,19 @@ public static BBModel Interpret(string fileContent)
4847 JObject jFaces = ( JObject ) jElement [ "faces" ] ;
4948 string name = ( string ) jElement . GetRequired ( "name" ) ;
5049 string type = jElement . GetString ( "type" , "cube" ) ;
50+ Guid id = Guid . Parse ( ( string ) jElement . GetRequired ( "uuid" ) ) ;
5151 if ( type != "cube" )
5252 {
53- Debug ( $ "Skip element of type '{ type } ' with name '{ name } '") ;
53+ Debug ( $ "Skip element of type '{ type } ' with name '{ name } ' and id { id } ") ;
54+ result . DiscardedIDs . Add ( id ) ;
5455 continue ;
5556 }
57+ int nameUsed = elementNames . GetValueOrDefault ( name , 0 ) ;
58+ elementNames [ name ] = nameUsed + 1 ;
59+ if ( nameUsed > 0 )
60+ {
61+ name += ( nameUsed + 1 ) ;
62+ }
5663 BBModel . Element element = new ( )
5764 {
5865 Name = name ,
@@ -71,9 +78,9 @@ public static BBModel Interpret(string fileContent)
7178 Up = ParseFaceFromJson ( jFaces . GetRequired ( "up" ) ) ,
7279 Down = ParseFaceFromJson ( jFaces . GetRequired ( "down" ) ) ,
7380 Type = type ,
74- UUID = Guid . Parse ( ( string ) jElement . GetRequired ( "uuid" ) )
81+ UUID = id
7582 } ;
76- Debug ( $ "Read element { element . Name } ") ;
83+ Debug ( $ "Read element { element . Name } as id { element . UUID } ") ;
7784 result . Elements . Add ( element ) ;
7885 }
7986 }
@@ -101,6 +108,13 @@ public static BBModel Interpret(string fileContent)
101108 throw new Exception ( $ "Cannot read model - texture { texture . Name } contains source data that isn't the expected base64 png.") ;
102109 }
103110 texture . RawImageBytes = Convert . FromBase64String ( sourceTex . After ( "data:image/png;base64," ) ) ;
111+ #pragma warning disable CA1416 // Validate platform compatibility
112+ using ( Image image = Image . FromStream ( new MemoryStream ( texture . RawImageBytes ) ) )
113+ {
114+ texture . Width = image . Width ;
115+ texture . Height = image . Height ;
116+ }
117+ #pragma warning restore CA1416 // Validate platform compatibility
104118 Debug ( $ "Read texture { texture . Name } ") ;
105119 result . Textures . Add ( texture ) ;
106120 }
@@ -110,7 +124,7 @@ public static BBModel Interpret(string fileContent)
110124 Debug ( "contains outliners" ) ;
111125 foreach ( JObject jOutliner in outliners )
112126 {
113- ReadOutliner ( result , jOutliner ) ;
127+ ReadOutliner ( result , jOutliner , outlineNames ) ;
114128 }
115129 }
116130 if ( animations is not null )
@@ -160,11 +174,20 @@ public static BBModel Interpret(string fileContent)
160174 return result ;
161175 }
162176
163- public static BBModel . Outliner ReadOutliner ( BBModel model , JObject jOutliner )
177+ public static HashSet < double > AcceptableRotations = new ( ) { 0 , 22.5 , 45 , - 22.5 , - 45 } ;
178+
179+ public static BBModel . Outliner ReadOutliner ( BBModel model , JObject jOutliner , Dictionary < string , int > names )
164180 {
181+ string name = ( string ) jOutliner . GetRequired ( "name" ) ;
182+ int nameUsed = names . GetValueOrDefault ( name , 0 ) ;
183+ names [ name ] = nameUsed + 1 ;
184+ if ( nameUsed > 0 )
185+ {
186+ name += ( nameUsed + 1 ) ;
187+ }
165188 BBModel . Outliner outline = new ( )
166189 {
167- Name = ( string ) jOutliner . GetRequired ( " name" ) ,
190+ Name = name ,
168191 Origin = ParseDVecFromArr ( jOutliner . GetRequired ( "origin" ) ) ,
169192 UUID = Guid . Parse ( ( string ) jOutliner . GetRequired ( "uuid" ) ) ,
170193 // Ignore ik_enabled, ik_chain_length, export, isOpen, locked, visibility, autouv
@@ -173,11 +196,42 @@ public static BBModel.Outliner ReadOutliner(BBModel model, JObject jOutliner)
173196 {
174197 if ( child . Type == JTokenType . String )
175198 {
176- outline . Children . Add ( Guid . Parse ( ( string ) child ) ) ;
199+ Guid id = Guid . Parse ( ( string ) child ) ;
200+ BBModel . Element element = model . GetElement ( id ) ;
201+ if ( element is null )
202+ {
203+ if ( model . DiscardedIDs . Contains ( id ) )
204+ {
205+ continue ;
206+ }
207+ throw new Exception ( $ "Cannot find required element { id } for outline { outline . Name } ") ;
208+ }
209+ if ( AcceptableRotations . Contains ( element . Rotation . X ) && AcceptableRotations . Contains ( element . Rotation . Y ) && AcceptableRotations . Contains ( element . Rotation . Z ) )
210+ {
211+ outline . Children . Add ( id ) ;
212+ }
213+ else
214+ {
215+ BBModel . Outliner specialSideOutline = new ( )
216+ {
217+ Name = $ "{ outline . Name } _auto_{ element . Name } ",
218+ Origin = outline . Origin + element . Origin ,
219+ Rotation = element . Rotation ,
220+ UUID = Guid . NewGuid ( ) ,
221+ } ;
222+ // TODO: Is this shift needed?
223+ //element.From -= element.Origin;
224+ //element.To -= element.Origin;
225+ element . Rotation = new DoubleVector ( ) ;
226+ element . Origin = new DoubleVector ( ) ;
227+ specialSideOutline . Children . Add ( element . UUID ) ;
228+ model . Outlines . Add ( specialSideOutline ) ;
229+ outline . Paired . Add ( specialSideOutline . UUID ) ;
230+ }
177231 }
178232 else
179233 {
180- BBModel . Outliner subLine = ReadOutliner ( model , ( JObject ) child ) ;
234+ BBModel . Outliner subLine = ReadOutliner ( model , ( JObject ) child , names ) ;
181235 outline . Paired . Add ( subLine . UUID ) ;
182236 outline . Paired . AddRange ( subLine . Paired ) ;
183237 }
@@ -208,7 +262,7 @@ public static BBModel.Element.Face ParseFaceFromJson(JToken jVal)
208262 TextureID = ( int ) jObj . GetRequired ( "texture" ) ,
209263 TexCoord = new BBModel . Element . Face . UV ( )
210264 {
211- ULow = ( int ) uv [ 0 ] , // TODO: Validate this ordering
265+ ULow = ( int ) uv [ 0 ] ,
212266 VLow = ( int ) uv [ 1 ] ,
213267 UHigh = ( int ) uv [ 2 ] ,
214268 VHigh = ( int ) uv [ 3 ]
0 commit comments