using Godot; using System; using System.Collections.Generic; namespace Rokojori { public class SceneFileHTMLExporter { public static readonly XMLElementNodeName GD_ExternalResource = XMLElementNodeName.Create( "gd-external-resource" ); public static readonly XMLElementNodeName GD_SubResource = XMLElementNodeName.Create( "gd-sub-resource" ); public static readonly XMLElementNodeName GD_Node = XMLElementNodeName.Create( "gd-node" ); public static readonly XMLElementNodeName GD_Name = XMLElementNodeName.Create( "gd-name" ); public static readonly XMLElementNodeName GD_Type = XMLElementNodeName.Create( "gd-type" ); public static readonly XMLElementNodeName GD_Script = XMLElementNodeName.Create( "gd-script" ); public static readonly XMLElementNodeName GD_Members = XMLElementNodeName.Create( "gd-members" ); public static readonly XMLElementNodeName GD_Member = XMLElementNodeName.Create( "gd-member" ); public static readonly XMLElementNodeName GD_Children = XMLElementNodeName.Create( "gd-children" ); public static readonly XMLElementNodeName GD_Reference = XMLElementNodeName.Create( "gd-reference" ); SceneFileParser _parser; XMLDocument _htmlDoc; XMLElementNode body; XMLElementNode head; public static void Convert( string inputPath, string outputPath ) { var text = FilesSync.LoadUTF8( inputPath ); var parser = new SceneFileParser(); parser.Parse( text ); Export( parser, outputPath ); } public static void Export( SceneFileParser parser, string path ) { new SceneFileHTMLExporter().ParseAndExport( parser, path ); } public void ParseAndExport( SceneFileParser parser, string path ) { _parser = parser; CreateHTMLDocument(); AddExternalResources(); AddNodes(); var exportPath = path.EndsWith( ".html" ) ? path : ( path + ".html" ); FilesSync.SaveUTF8( exportPath, new XMLSerializer().SerializeHtml( _htmlDoc.documentElement ) ); } void CreateHTMLDocument() { var doc = XMLDocument.HTML(); var html = doc.documentElement; body = html.querySelector( HTMLElementName.body ); head = html.querySelector( HTMLElementName.head ); head.AddHTMLScript( SceneFileHTMLScriptJS.script ); head.AddHTMLStyle( SceneFileHTMLStyle.style ); _htmlDoc = doc; } void AddExternalResources() { var extResources = _parser.sceneFile.extResources; RJLog.Log( "External Resources:", extResources.Count ); for ( int i = 0; i < extResources.Count; i++ ) { var resource = extResources[ i ]; var attachmentElement = body; var resourceElement = _htmlDoc.Create( GD_ExternalResource ); resourceElement.SetAttribute( "class", "resource" ); attachmentElement.AppendChild( resourceElement ); var nameElement = resourceElement.AddElement( GD_Name, resource.path.value ); resourceElement.AddElement( GD_Type, resource.id.value + " " + resource.uid.value + " " + resource.type.value ); resourceElement.SetAttribute( "id", resource.id.value ); attachmentElement.AddElement( HTMLElementName.br ); } var subResources = _parser.sceneFile.subResources; RJLog.Log( "Sub Resources:", subResources.Count ); for ( int i = 0; i < subResources.Count; i++ ) { var resource = subResources[ i ]; var attachmentElement = body; var resourceElement = _htmlDoc.Create( GD_SubResource ); resourceElement.SetAttribute( "class", "resource" ); attachmentElement.AppendChild( resourceElement ); var nameElement = resourceElement.AddElement( GD_Name, resource.id.value + " " + resource.type.value ); var scriptOrShaderMember = resource.GetMember( "script" ); if ( scriptOrShaderMember == null ) { scriptOrShaderMember = resource.GetMember( "shader" ); } if ( scriptOrShaderMember != null ) { var scriptEntry = _parser.sceneFile.extResources.Find( e => e.id.value == scriptOrShaderMember.valueData.reference ); var scriptType = scriptEntry == null ? "Null" : scriptEntry.path.value; resourceElement.AddElement( GD_Type, scriptType + "@" + scriptOrShaderMember.valueData.reference ); } resourceElement.SetAttribute( "id", resource.id.value ); attachmentElement.AddElement( HTMLElementName.br ); } } void AddNodes() { var nodes = _parser.sceneFile.nodes; RJLog.Log( "Nodes:", nodes.Count ); var elementMap = new Dictionary(); for ( int i = 0; i < nodes.Count; i++ ) { var node = nodes[ i ]; //RJLog.Log( i, node.name.value ); var attachmentElement = body; var elementPath = node.elementPath; var parent = node.parent.value; if ( parent != null && elementMap.ContainsKey( parent ) ) { attachmentElement = elementMap[ parent ].querySelector( GD_Children ); } var nodeElement = _htmlDoc.Create( GD_Node ); nodeElement.SetAttribute( "class", "node" ); var nameElement = nodeElement.AddElement( GD_Name, node.name.value ); nameElement.SetAttribute( "class", "closeable" ); nameElement.SetAttribute( "data-close-target", ".. " + GD_Children.selector ); var scriptMember = node.GetMember( "script" ); if ( scriptMember != null ) { var scriptEntry = _parser.sceneFile.extResources.Find( e => e.id.value == scriptMember.valueData.reference ); var scriptType = scriptEntry == null ? "Null" : scriptEntry.path.value; nodeElement.AddElement( GD_Type, scriptType + "@" + scriptMember.valueData.reference + "(" + node.type.value + ")" ); } else { nodeElement.AddElement( GD_Type, node.type.value ); } string scriptValue = null ; if ( scriptValue != null ) { nodeElement.AddElement( GD_Script, scriptValue ); } var membersElement = nodeElement.AddElement( GD_Members, "" ); var memberData = node.data; memberData.ForEach( m => { if ( m.member != null ) { var mem = m.member; if ( mem.valuesData != null ) { } else if ( mem.valueData != null ) { if ( SceneFileValueType.Variant == mem.valueData.type ) { membersElement.AddElement( GD_Member, mem.name + ": " + mem.valueData ); } else { var member = membersElement.AddElement( GD_Member, mem.name ); var reference = member.AddElement( GD_Reference, mem.valueData.reference ); reference.SetAttribute( "reference", mem.valueData.reference ); } } } else { // membersElement.AddElement( GD_Member, "Type: " + m.type + " {" + m.line + "}"); } } ); nodeElement.AddElement( GD_Children ); elementMap[ elementPath ] = nodeElement; // RJLog.Log( "'" + elementPath + "'", node.name.value ); attachmentElement.AppendChild( nodeElement ); } } } }