static int CollapseInstances(VMF vmf) { #region Identify useable IDs int usableID = vmf.Body.GetHighestID() + 1; #endregion var world = vmf.Body.Where(node => node.Name == "world").Where(node => node is VBlock).Cast <VBlock>().FirstOrDefault(); if (world == null) { Console.WriteLine("Can't find \"world\""); return(-1); } int lastEntityLocation = 0; lastEntityLocation = vmf.Body.IndexOf(world) + vmf.Body.Where(node => node.Name == "entity").Count(); int autoInstance = 0; var entities = vmf.Body.Where(item => item.Name == "entity").Select(item => item as VBlock).ToList(); var instances = entities.Where(entity => entity.Body.Where(item => item.Name == "classname" && (item as VProperty).Value == "func_instance").Count() > 0).ToList(); foreach (var instance in instances) { // Get instance targetname string instanceTargetName = ""; var instanceTargetNameProperty = instance.Body.Where(node => node.Name == "targetname" && node.GetType() == typeof(VProperty)).Select(node => node as VProperty).FirstOrDefault(); if ((instanceTargetNameProperty?.Value ?? "") == "") { instanceTargetName = String.Format("AutoInstance{0}", autoInstance++); } // TODO: Give it a default name if unnamed (or not?). // Load the instance vmf var fileProp = instance.Body.Where(node => node.Name == "file" && node.GetType() == typeof(VProperty)).Select(node => node as VProperty).FirstOrDefault(); if (fileProp == null || string.IsNullOrEmpty(fileProp.Value.Trim())) { // Looks like there is no file property, or its empty continue; } if (!File.Exists(fileProp.Value)) { // TODO: What do you do when the file doesn't exist? Probably should throw up some sort of error. // Just skip it for now. continue; } var instanceVMF = new VMF(File.ReadAllLines(fileProp.Value)); // Clone the important parts // TODO: think about collapsing groups // TODO: only grab visible entities var instanceVisibleEntities = instanceVMF.Body.Where(node => node.Name == "entity").Where(node => node is VBlock).Cast <VBlock>(); var instanceVisibleSolids = instanceVMF.Body.Where(node => node.Name == "world").Where(node => node is VBlock).Cast <VBlock>() .SelectMany(node => node.Body.Where(worldNode => worldNode.Name == "solid").Where(worldNode => worldNode is VBlock).Cast <VBlock>() ); // Update each entity into the map with relative offsets and angles from the instance point, and the instance origin (defaults at 0 0 0) // angles and origin var instanceOriginProperty = instance.Body.Where(node => node.Name == "origin" && node.GetType() == typeof(VProperty)).Select(node => node as VProperty).FirstOrDefault(); var instanceAnglesProperty = instance.Body.Where(node => node.Name == "angles" && node.GetType() == typeof(VProperty)).Select(node => node as VProperty).FirstOrDefault(); var instanceOrigin = new Vector3(instanceOriginProperty?.Value ?? "0 0 0"); var instanceAngles = new Vector3(instanceAnglesProperty?.Value ?? "0 0 0"); var fixupStyle = int.Parse(instance.Body.Where(node => node.Name == "fixup_style" && node.GetType() == typeof(VProperty)).Select(node => node as VProperty).FirstOrDefault()?.Value ?? "0"); foreach (var entity in instanceVisibleEntities) { VBlock collapsedEntity = CollapseEntity(entity, fixupStyle, instanceTargetName, instanceOrigin, instanceAngles, ref usableID); vmf.Body.Insert(lastEntityLocation++, collapsedEntity); } foreach (var solid in instanceVisibleSolids) { VBlock collapsedSolid = CollapseSolid(solid, ref usableID); world.Body.Add(collapsedSolid); } // Rename all internal communication // Link external IO // Replace replaceable parameters // Replace replaceable materials // Insert into actual map // Remove instance from map vmf.Body.Remove(instance); } return(0); }
private void AddItemToScope(VBlock vBlock) { vBlock.ScopeControl?.UpdateScope(); GlobalScope.Scope.Items.Enqueue(vBlock.VCode); }
static VBlock CollapseSolid(VBlock solid, ref int highID) { // TODO: transform solid return(solid.DeepClone()); }