private void WriteVisData(IDictionary <string, VisData> visResults, bool isTech) { string jsFileNameSuffix = isTech ? "-tech.js" : "-dependants.js"; string jsVariableSuffix = isTech ? "GraphDataTech" : "GraphDataDependants"; string jsModMappingFileName = isTech ? "TechFiles.js" : "DependantFiles.js"; string jsModMappingFileVariable = isTech ? "techDataFiles" : "dependantDataFiles"; string jsImportFileName = isTech ? "JS-Tech-Imports.txt" : "JS-Dependants-Imports.txt"; List <JSModInfo> modInfos = new List <JSModInfo>(); foreach (var(modGroup, visResult) in visResults) { var(jsFileName, jsVariable) = visResult.WriteVisDataToOneJSFile(OutputDirectoryHelper.Data, modGroup + jsFileNameSuffix, modGroup + jsVariableSuffix); modInfos.Add(new JSModInfo() { name = modGroup, jsVarable = jsVariable, fileName = jsFileName }); } VisData.WriteJavascriptObject(modInfos, OutputDirectoryHelper.Data, jsModMappingFileName, jsModMappingFileVariable); var importListing = modInfos.Select(x => x.fileName).Select(x => $"<script type=\"text/javascript\" src=\"data/{x}?v=2\"></script>").ToList(); importListing.Sort(); File.WriteAllLines(Path.Combine(OutputDirectoryHelper.Data, jsImportFileName), importListing); }
private void BspPopulate(VisData visDat, Scene scene, int level) { List <VisData> childVisData = scene.GetVisDataChildren(visDat); // if node has children get those children if (childVisData.Count > 0) // has any children? { foreach (var b in childVisData) { if (b == null) { continue; } if (b.IsLeaf) // leaves don't have children { eng.bbox.Add(new WireBox(DataConverter.ToVector3(b.bbox.Min), DataConverter.ToVector3(b.bbox.Max), Color.Magenta, 1 / 100f)); } else { // show those children in different color than the parent if (!eng.bbox2.ContainsKey(level)) { eng.bbox2.Add(level, new List <WireBox>()); } eng.bbox2[level].Add(new WireBox(DataConverter.ToVector3(b.bbox.Min), DataConverter.ToVector3(b.bbox.Max), colorLevelsOfBsp[level % colorLevelsOfBsp.Length], 1 / 100f)); BspPopulate(b, scene, level + 1); } } } }
public VisData CreateRootNotes(ModEntityData <Tech> techsAndDependencies, string imagesPath) { var result = new VisData() { ModGroup = StellarisDirectoryHelper.StellarisCoreRootDirectory }; var techAreas = Enum.GetValues(typeof(TechArea)).Cast <TechArea>(); var rootNodes = new Dictionary <TechArea, VisNode>(); var rootNodeCategories = new Dictionary <TechArea, HashSet <string> >(); foreach (var tech in techsAndDependencies.AllEntities) { rootNodeCategories.ComputeIfAbsent(tech.Area, ignored => new HashSet <string>()).AddRange(tech.Categories); } foreach (var techArea in techAreas) { var rootNode = BuildRootNode(techArea, imagesPath); rootNode.categories = rootNodeCategories.ComputeIfAbsent(techArea, ignored => new HashSet <string>()).ToArray(); rootNodes[techArea] = rootNode; } result.nodes.AddRange(rootNodes.Values); return(result); }
public VisInstance(VisData visi) { Visi = visi; leftChild = visi.leftChild; rightChild = visi.rightChild; u1 = visi.u1; ptrUnkData = visi.ptrUnkData; numQuadBlock = Visi.numQuadBlock; ptrQuadBlock = Visi.ptrQuadBlock; }
private VisData CreateDependantDataForModGroup(string modGroup, IDictionary <string, VisNode> prereqTechNodeLookup, ObjectsDependantOnTechs objectsDependantOnTechs, IEnumerable <ParseTarget> parseTargets) { var result = new VisData() { ModGroup = modGroup, }; foreach (var parseTarget in parseTargets.WithoutTechs()) { switch (parseTarget) { case ParseTarget.Buildings: { result.nodes.AddRange(objectsDependantOnTechs.Buildings.AllEntitiesForModGroup(modGroup) .Select(x => MarshalBuilding(x, prereqTechNodeLookup, outputDirectoryHelper.GetImagesPath(parseTarget.ImagesDirectory())))); result.edges.AddRange(objectsDependantOnTechs.Buildings.AllLinksForModGroup(modGroup).Select(VisHelpers.MarshalLink)); break; } case ParseTarget.ShipComponents: { result.nodes.AddRange(objectsDependantOnTechs.ShipComponentsSets.AllEntitiesForModGroup(modGroup) .Select(x => MarshallShipComponentSet(x, prereqTechNodeLookup, outputDirectoryHelper.GetImagesPath(parseTarget.ImagesDirectory())))); ISet <Link> allLinksForModGroup = objectsDependantOnTechs.ShipComponentsSets.AllLinksForModGroup(modGroup); result.edges.AddRange(allLinksForModGroup.Select(VisHelpers.MarshalLink)); break; } case ParseTarget.Decisions: { result.nodes.AddRange(objectsDependantOnTechs.Decisions.AllEntitiesForModGroup(modGroup) .Select(x => MarshalDecision(x, prereqTechNodeLookup, outputDirectoryHelper.GetImagesPath(parseTarget.ImagesDirectory())))); ISet <Link> allLinksForModGroup = objectsDependantOnTechs.Decisions.AllLinksForModGroup(modGroup); result.edges.AddRange(allLinksForModGroup.Select(VisHelpers.MarshalLink)); break; } default: throw new Exception(parseTarget.ToString()); } } return(result); }
private void BspDraw(VisData visDat, Scene scene, int level) { List <VisData> childVisData = scene.GetVisDataChildren(visDat); // if node has children get those children if (childVisData != null && childVisData.Count > 0) // has any children? { foreach (var b in childVisData) { if (b.IsLeaf) // leaves don't have children { bbox2.Add(MGConverter.ToLineList(b.bbox, Color.Magenta)); } else { BspDraw(b, scene, level + 1); // show those children in different color than the parent bbox.Add(MGConverter.ToLineList(b.bbox, colorLevelsOfBsp[level % colorLevelsOfBsp.Length])); } } } }
private Color CalculateGradient(VisData data, Gradient spectrum) { return(CalculateGradient(data.Value, data.MinValue, data.MaxValue, spectrum)); }
public void Parse(IEnumerable <ParseTarget> parseTargets) { var techTreeGraphCreator = new TechTreeGraphCreator(Localisation, CWParser, StellarisDirectoryHelper, ModDirectoryHelpers); ModEntityData <Tech> techData = techTreeGraphCreator.CreateTechnologyGraph(); Log.Logger.Debug("Processed {entityCount} techs with {linkCount} Links", techData.EntityCount, techData.LinkCount); // process technolgoies first var techImageOutputDir = OutputDirectoryHelper.GetImagesPath(ParseTarget.Technologies.ImagesDirectory()); if (CopyImages) { CopyMainImages(techData.AllEntities, ParseTarget.Technologies.ImagesDirectory(), techImageOutputDir); // because the image copying only get the most recent version of the entity, make sure that the image flag is set on all // relevant for the vanilla graph display var currentTechs = techData.AllEntitiesByKey; techData.ApplyToChain((techs, links) => { foreach (var tech in techs.Values) { tech.IconFound = currentTechs[tech.Id].IconFound; } }); var techAreas = Enum.GetValues(typeof(TechArea)).Cast <TechArea>(); var areaDir = Path.Combine(techImageOutputDir, "areas"); // tech areas Directory.CreateDirectory(areaDir); foreach (var techArea in techAreas) { var inputPath = Path.Combine(StellarisDirectoryHelper.Icons, "resources", techArea.ToString().ToLowerInvariant() + "_research.dds"); // icon to be displayed on the 3 root nodes ImageOutput.TransformAndOutputImage( inputPath, Path.Combine(techImageOutputDir, techArea + "-root.png")); // area icon ImageOutput.TransformAndOutputImage( inputPath, Path.Combine(areaDir, techArea.ToString().ToLowerInvariant() + ".png")); } // tech categories CopyCategoryImages(techImageOutputDir); } // process dependant objects ObjectsDependantOnTechs dependants = null; var parseTargetsWithoutTechs = parseTargets.WithoutTechs().ToList(); if (parseTargetsWithoutTechs.Any()) { var dependantsGraphCreator = new DependantsGraphCreator(Localisation, CWParser, StellarisDirectoryHelper, ModDirectoryHelpers, techData); dependants = dependantsGraphCreator.CreateDependantGraph(parseTargetsWithoutTechs); if (CopyImages) { foreach (var parseTarget in parseTargetsWithoutTechs) { var imageOutputDir = OutputDirectoryHelper.GetImagesPath(parseTarget.ImagesDirectory()); var entityData = dependants.Get(parseTarget); CopyMainImages(entityData, parseTarget.ImagesDirectory(), imageOutputDir); } dependants.FixImages(); } } var visDataMarshaler = new VisDataMarshaler(localisation, OutputDirectoryHelper); IDictionary <string, VisData> techVisResults = visDataMarshaler.CreateTechVisData(techData, techImageOutputDir); ModEntityData <Tech> coreGameTech = techData.FindCoreGameData(); if (coreGameTech != null) { IDictionary <string, VisData> techVisData = visDataMarshaler.CreateTechVisData(coreGameTech, techImageOutputDir); techVisResults["Stellaris-No-Mods"] = techVisData[StellarisDirectoryHelper.StellarisCoreRootDirectory]; } else { Log.Logger.Warning("Could not find core game tech files to generate vanilla tree"); } VisData rootNotes = visDataMarshaler.CreateRootNotes(techData, techImageOutputDir); techVisResults["Tech-Root-Nodes"] = rootNotes; WriteVisData(techVisResults, true); if (dependants != null) { var dependantVisResults = visDataMarshaler.CreateGroupedVisDependantData(techVisResults, dependants, parseTargetsWithoutTechs); var coreDependantsOnly = dependants.CopyOnlyCore(); // also do a no-mods lookup var stellarisNoModsTechVisResult = techVisResults["Stellaris-No-Mods"]; IDictionary <string, VisData> visLookupData = stellarisNoModsTechVisResult != null ? new Dictionary <string, VisData>() { { "Stellaris-No-Mods", stellarisNoModsTechVisResult } } : techVisResults; var coreDependantData = visDataMarshaler.CreateGroupedVisDependantData(visLookupData, coreDependantsOnly, parseTargetsWithoutTechs); if (coreDependantData.ContainsKey(StellarisDirectoryHelper.StellarisCoreRootDirectory)) { dependantVisResults["Stellaris-No-Mods"] = coreDependantData[StellarisDirectoryHelper.StellarisCoreRootDirectory]; } else { Log.Logger.Warning("Could not find core game dependant files to generate vanilla tree"); } WriteVisData(dependantVisResults, false); } }
public IDictionary <string, VisData> CreateTechVisData(ModEntityData <Tech> allTechsAndDependencies, string imagesPath) { var modGroups = allTechsAndDependencies.AllLinks.Select(x => x.To.ModGroup).Distinct().ToList(); var coreData = allTechsAndDependencies.FindCoreGameData(); // link to supernodes var results = new Dictionary <string, VisData>(); foreach (var modGroup in modGroups) { var techsForGroup = allTechsAndDependencies.FindByModGroup(modGroup).Reverse().ToList(); var current = coreData; foreach (var forGroup in techsForGroup) { current = forGroup.Copy(current); } var techsAndDependencies = current; // perform longest path analysis to find out how many levels we want in each tech var maxPathPerTier = new Dictionary <int, int>(); List <Tech> techsWithNoPrereqs = new List <Tech>(); foreach (var tech in techsAndDependencies.AllEntities) { if (!tech.Tier.HasValue) { throw new InvalidOperationException("All Techs must have Tiers to create vis data. " + tech.Id); } int pathLength = NumberOfPrereqsInSameTier(tech); var currentMaxForTier = maxPathPerTier.ComputeIfAbsent(tech.Tier.Value, ignored => 0); if (pathLength > currentMaxForTier) { maxPathPerTier[tech.Tier.Value] = pathLength; } // need to link to a supernode to make it look good if (!tech.Prerequisites.Any()) { techsWithNoPrereqs.Add(tech); } } Log.Logger.Debug("Max path per tier {@maxPaths} Number of techs with no pre-requiste {noPreqCount}", maxPathPerTier, techsWithNoPrereqs.Count); // determine the base levels in the graph that each node will be on. var minimumLevelForTier = CalculateMinimumLevelForTier(maxPathPerTier); Log.Logger.Debug("Minimum level per tier {@minLevels}", minimumLevelForTier); //sort the input by area as it produces a nicer graph. var techList = techsAndDependencies.AllEntities.ToList(); techList.Sort((tech1, tech2) => { var primary = tech1.Area - tech2.Area; return(primary != 0 ? primary : string.Compare(tech1.Id, tech2.Id, StringComparison.Ordinal)); }); var result = new VisData() { nodes = techList.Where(x => Filter(x, modGroup)).Select(x => MarshalTech(x, minimumLevelForTier, imagesPath)).ToList(), edges = techsAndDependencies.AllLinks.Where(x => Filter(x.To, modGroup)).Select(VisHelpers.MarshalLink).ToList() }; foreach (var tech in techsWithNoPrereqs.Where(x => Filter(x, modGroup))) { result.edges.Add(BuildRootLink(tech.Area, tech.Id)); } results[modGroup] = result; } return(results); }