private void GenerateCommonParts(string scenesPath) { if (commonParts.Count <= 0) { return; } Action <ParsedNode, List <ParsedNode> > UniteMarkers = (dest, source) => { var markersUnion = new Dictionary <string, int>(); foreach (var n in source) { foreach (var marker in n.Markers) { if (!markersUnion.ContainsKey(marker)) { markersUnion.Add(marker, 0); } markersUnion[marker]++; } } dest.Markers.Clear(); foreach (var mkv in markersUnion) { if (mkv.Value == source.Count) { dest.Markers.Add(mkv.Key); } } }; var codeHeader = $"using Lime;\n namespace {(GetBundleNamespace(mainBundleName))}.Common\n{{\n" + $"<%GEN%>\n" + $"}}\n"; var commonDirectory = $"{scenesPath}/Common"; RetryUntilSuccessCreateDirectory(commonDirectory); foreach (var kv in commonParts) { var root = new ParsedFramesTree { ClassName = kv.Key, ParsedNode = new ParsedNode(kv.Value.First().ParsedNode), }; UniteMarkers(root.ParsedNode, kv.Value.Select(j => j.ParsedNode).ToList()); var queue = new Queue <List <ParsedFramesTree> >(); var sync = new Queue <ParsedFramesTree>(); queue.Enqueue(kv.Value); sync.Enqueue(root); while (queue.Count != 0) { var s = queue.Dequeue(); var nextRoot = sync.Dequeue(); var treeUnion = new Dictionary <string, List <ParsedFramesTree> >(); var leafUnion = new Dictionary <string, List <ParsedNode> >(); foreach (var ft in s) { foreach (var leafNode in ft.ParsedNodes) { var k = leafNode.Name + GetFullTypeOf(leafNode); if (!leafUnion.ContainsKey(k)) { leafUnion.Add(k, new List <ParsedNode>()); } leafUnion[k].Add(leafNode); } foreach (var treeNode in ft.InnerClasses) { var k = treeNode.Name + GetFullTypeOf(treeNode); if (!treeUnion.ContainsKey(k)) { treeUnion.Add(k, new List <ParsedFramesTree>()); } treeUnion[k].Add(treeNode); } } foreach (var i in leafUnion) { if (i.Value.Count == s.Count) { var leafClone = new ParsedNode(i.Value.First()) { Type = GetCommonBaseClass(i.Value.Select(j => j.Type).ToList()).Name }; UniteMarkers(leafClone, i.Value); nextRoot.ParsedNodes.Add(leafClone); } } foreach (var i in treeUnion) { if (i.Value.Count == s.Count) { var subtreeClone = new ParsedFramesTree(i.Value.First()) { ParsedNode = { Type = GetCommonBaseClass(i.Value.Select(j => j.ParsedNode.Type).ToList()).Name } }; UniteMarkers(subtreeClone.ParsedNode, i.Value.Select(j => j.ParsedNode).ToList()); nextRoot.InnerClasses.Add(subtreeClone); queue.Enqueue(i.Value); sync.Enqueue(subtreeClone); } } } if (root.InnerClasses.Count != 0 || root.ParsedNodes.Count != 0 || root.ParsedNode.Markers.Count != 0) { var code = codeHeader.Replace("<%GEN%>", root.GenerateCode(this, false) + "\n<%GEN%>"); code = code.Replace("<%GEN%>", ""); code = new CodeFormatter(code).FormattedCode; File.WriteAllText($"{commonDirectory}/{kv.Key}.cs", code); } } }
public void Start() { Console.WriteLine("Generating scenes code for {0} scenes...", scenesForProcessing.Count); var generatedScenesPath = $"{directory}/{projectName}.GeneratedScenes"; if (!Directory.Exists(generatedScenesPath)) { GenerateProjectFiles(generatedScenesPath); } var scenesPath = $@"{directory}/{projectName}.GeneratedScenes/Scenes"; RemoveOrphanedGeneratedCodeItems(); RemoveUpdatingCommonPartsFromCache(); foreach (var scenePath in allScenes) { externalSceneToOriginalScenePath.Add(Path.ChangeExtension(scenePath, null), scenePath); } var sceneToFrameTree = new List <Tuple <string, ParsedFramesTree> >(); foreach (var scene in scenesForProcessing) { var bundleName = sceneToBundleMap[scene.Key]; var bundleSourcePath = $"{scenesPath}/{bundleName}"; if (!Directory.Exists(bundleSourcePath)) { RetryUntilSuccessCreateDirectory(bundleSourcePath); } currentCookingScene = scene.Key; var parsedFramesTree = GenerateParsedFramesTree(scene.Key, scene.Value); sceneToFrameTree.Add(new Tuple <string, ParsedFramesTree>(scene.Key, parsedFramesTree)); } foreach (var kv in sceneToFrameTree) { var parsedFramesTree = kv.Item2; currentCookingScene = kv.Item1; var k = Path.ChangeExtension(kv.Item1, null); k = AssetPath.CorrectSlashes(k); var id = scenesForProcessing[kv.Item1].Id; var bundleName = sceneToBundleMap[kv.Item1]; var bundleSourcePath = $"{scenesPath}/{bundleName}"; var generatedCodePath = bundleSourcePath + "/" + parsedFramesTree.ClassName + ".cs"; var useful = parsedFramesTree.ParsedNodes.Count > 0 || parsedFramesTree.InnerClasses.Count > 0 || (id != null && (id.StartsWith("@") || id.StartsWith(">"))); if (!useful) { if (File.Exists(generatedCodePath)) { File.Delete(generatedCodePath); } continue; } var code = parsedFramesTree.GenerateCode(this); code = code.Replace("<%PROJECT_NAME%>", projectName); code = code.Replace("<%NAMESPACE%>", GetBundleNamespace(bundleName)); code = new CodeFormatter(code).FormattedCode; File.WriteAllText(generatedCodePath, code); } UpdateCache(); // Collect not loaded scenes which are also contains common parts affected by actually modified and referred to them scenes // Because we need those to correctly update common parts. i.e. to calc common parts you need all of common parts referrers List <string> reprocessScenes = new List <string>(); foreach (var kv in codeCookerCache.CommonPartToReferredScenes) { if (commonParts.ContainsKey(kv.Key)) { foreach (var scene in kv.Value) { if (!modifiedScenes.Contains(scene)) { reprocessScenes.Add(scene); } } } } foreach (var scene in reprocessScenes) { GenerateParsedFramesTree(scene, Node.CreateFromAssetBundle(scene)); } GenerateCommonParts(scenesPath); UpdateCommonPartsCache(); }