public void LoadPackFiles(float progress0, float progress100)
        {
            string[] files = Directory.GetFiles(PackDirectory, "*.pack");

            //Load Pack files into AssetManager.
            ProgressBar(progress0, "Loading Pack Data...");

            int    packsProcessed  = 0;
            string assetProcessing = "";

            Parallel.AsyncForEach <string> parallelTask = System.Threading.Tasks.Parallel.ForEach;

            IAsyncResult result = parallelTask.BeginInvoke(files, file =>
            {
                assetProcessing = Path.GetFileName(file);

                LoadPack(file);
                Interlocked.Increment(ref packsProcessed);
            }, null, null);

            while (!result.IsCompleted)
            {
                ProgressBar(MathUtils.Remap01(packsProcessed / (float)files.Length, progress0, progress100), "Loading Pack File: " + assetProcessing);
            }

            parallelTask.EndInvoke(result);
        }
        public void LoadZoneObjects(ForgelightGame forgelightGame, string zoneName, List <Object> objects, float progressMin, float progressMax)
        {
            Parent.name += " - " + zoneName;

            //Begin processing the file
            for (int i = 0; i < objects.Count; i++)
            {
                Object zoneObject = objects[i];

                if (zoneObject.Instances.Count > 0)
                {
                    Adr actorDef = forgelightGame.GetActorDefinition(zoneObject.ActorDefinition);

                    if (actorDef == null)
                    {
                        Debug.LogWarning("Could not find Actor Definition: " + zoneObject.ActorDefinition + "!");
                        continue;
                    }

                    foreach (Object.Instance instance in zoneObject.Instances)
                    {
                        TransformData correctedTransform = MathUtils.ConvertTransform(instance.Position, instance.Rotation, instance.Scale, true, TransformMode.Standard);

                        CreateForgelightObject(forgelightGame, actorDef, correctedTransform.Position, Quaternion.Euler(correctedTransform.Rotation), correctedTransform.Scale, zoneObject.RenderDistance, instance.LODMultiplier, instance.DontCastShadows, instance.ID);
                    }
                }

                EditorUtility.DisplayProgressBar("Loading Zone: " + zoneName, "Loading Objects: " + zoneObject.ActorDefinition, MathUtils.Remap01((float)i / objects.Count, progressMin, progressMax));
            }
        }
        public void UpdateAreas(float progress0, float progress100)
        {
            ProgressBar(progress0, "Loading Area Definitions");

            List <AssetRef> xmlFiles = AssetsByType[AssetRef.Types.XML];

            AvailableAreaDefinitions = new List <Asset>();

            int    assetsProcessed    = 0;
            string lastAssetProcessed = "";
            object listLock           = new object();

            Parallel.AsyncForEach <AssetRef> parallelTask = System.Threading.Tasks.Parallel.ForEach;

            IAsyncResult result = parallelTask.BeginInvoke(xmlFiles, asset =>
            {
                Interlocked.Increment(ref assetsProcessed);

                if (asset == null)
                {
                    return;
                }

                //Names
                string assetName        = asset.Name;
                string assetDisplayName = BuildAssetName(assetName, asset.Pack.Name);

                if (!assetName.EndsWith("Areas.xml"))
                {
                    return;
                }

                //De-serialize
                using (MemoryStream memoryStream = asset.Pack.CreateAssetMemoryStreamByName(assetName))
                {
                    Areas areas = Areas.LoadFromStream(assetName, assetDisplayName, memoryStream);

                    if (areas == null)
                    {
                        return;
                    }

                    lock (listLock)
                    {
                        AvailableAreaDefinitions.Add(areas);
                        lastAssetProcessed = assetName;
                    }
                }
            }, null, null);

            while (!result.IsCompleted)
            {
                ProgressBar(MathUtils.Remap01(assetsProcessed / (float)xmlFiles.Count, progress0, progress100), "Loading Area Definitions: " + lastAssetProcessed);
            }

            parallelTask.EndInvoke(result);
            AvailableAreaDefinitions.Sort();
        }
Ejemplo n.º 4
0
        public void LoadZoneLights(string zoneName, List <Light> lights, float progressMin, float progressMax)
        {
            Parent.name += " - " + zoneName;

            for (int i = 0; i < lights.Count; i++)
            {
                Light lightData = lights[i];

                ZoneLight instance = new GameObject(lightData.Name).AddComponent <ZoneLight>();

                UnityEngine.Light lightComponent = instance.gameObject.AddComponent <UnityEngine.Light>();
                lightComponent.intensity       = 4.0f;
                lightComponent.bounceIntensity = 0.0f;

                instance.lightObject = lightComponent;

                //Params
                TransformData correctedTransform = MathUtils.ConvertTransform(lightData.Position, lightData.Rotation, Vector3.one, true, TransformMode.Standard);

                instance.transform.position = correctedTransform.Position;
                instance.transform.rotation = Quaternion.Euler(correctedTransform.Rotation);

                instance.Name           = lightData.Name;
                instance.ColorName      = lightData.ColorName;
                instance.Type           = lightData.Type;
                instance.UnknownFloat1  = lightData.UnknownFloat1;
                instance.Range          = lightData.Range;
                instance.InnerRange     = lightData.InnerRange;
                instance.Color          = lightData.Color;
                instance.UnknownByte1   = lightData.UnknownByte1;
                instance.UnknownByte2   = lightData.UnknownByte2;
                instance.UnknownByte3   = lightData.UnknownByte3;
                instance.UnknownByte4   = lightData.UnknownByte4;
                instance.UnknownByte5   = lightData.UnknownByte5;
                instance.UnknownVector1 = lightData.UnknownVector1;
                instance.UnknownString1 = lightData.UnknownString1;
                instance.ID             = lightData.ID;

                instance.transform.parent = Parent;

                //Apply any changes we may have made.
                instance.OnValidate();

                int layer = LayerMask.NameToLayer("ForgelightZoneLight");
                instance.gameObject.layer = layer;

                foreach (Transform child in instance.transform)
                {
                    child.gameObject.layer = layer;
                }

                EditorUtility.DisplayProgressBar("Loading Zone: " + zoneName, "Loading Lights: " + lightData.Name, MathUtils.Remap01((float)i / lights.Count, progressMin, progressMax));
            }
        }
Ejemplo n.º 5
0
        private List <Point> OrderList(Point barycentre)
        {
            List <Point> sortPoints = new List <Point>();

            sortPoints = points.OrderBy(calculatedPoint =>
            {
                Vector3 vectorTest = calculatedPoint.GetPosition() - barycentre.GetPosition();
                return(MathUtils.AngleClockwise(Vector3.right, vectorTest));
            }).ThenBy(calculatedPoint => Vector3.Distance(barycentre.GetPosition(), calculatedPoint.GetPosition())).ToList();

            return(sortPoints);
        }
        public void UpdateZones(float progress0, float progress100)
        {
            ProgressBar(progress0, "Updating Zones...");

            List <AssetRef> zones = AssetsByType[AssetRef.Types.ZONE];

            AvailableZones = new List <Asset>(zones.Count);

            int    assetsProcessed    = 0;
            string lastAssetProcessed = "";
            object listLock           = new object();

            Parallel.AsyncForEach <AssetRef> parallelTask = System.Threading.Tasks.Parallel.ForEach;

            IAsyncResult result = parallelTask.BeginInvoke(zones, asset =>
            {
                Interlocked.Increment(ref assetsProcessed);

                if (asset == null)
                {
                    return;
                }

                //Names
                string assetName        = asset.Name;
                string assetDisplayName = BuildAssetName(assetName, asset.Pack.Name);

                //De-serialize
                using (MemoryStream memoryStream = asset.Pack.CreateAssetMemoryStreamByName(asset.Name))
                {
                    lastAssetProcessed = assetName;
                    Zone zone          = Zone.LoadFromStream(assetName, assetDisplayName, memoryStream);

                    if (zone == null)
                    {
                        return;
                    }

                    lock (listLock)
                    {
                        AvailableZones.Add(zone);
                    }
                }
            }, null, null);

            while (!result.IsCompleted)
            {
                ProgressBar(MathUtils.Remap01(assetsProcessed / (float)zones.Count, progress0, progress100), "Updating Zone: " + lastAssetProcessed);
            }

            parallelTask.EndInvoke(result);
            AvailableZones.Sort();
        }
        public void ImportModels(float progress0, float progress100)
        {
            ProgressBar(progress0, "Exporting Models...");

            List <AssetRef> modelAssets        = AssetsByType[AssetRef.Types.DME];
            int             assetsProcessed    = 0;
            string          lastAssetProcessed = "";

            Parallel.AsyncForEach <AssetRef> parallelTask = System.Threading.Tasks.Parallel.ForEach;

            IAsyncResult result = parallelTask.BeginInvoke(modelAssets, asset =>
            {
                Interlocked.Increment(ref assetsProcessed);

                if (asset == null)
                {
                    return;
                }

                //Don't export if the file already exists.
                if (File.Exists(ResourceDirectory + "/Models/" + Path.GetFileNameWithoutExtension(asset.Name) + ".obj"))
                {
                    return;
                }

                //Names
                string assetName        = asset.Name;
                string assetDisplayName = BuildAssetName(assetName, asset.Pack.Name);

                //De-serialize
                using (MemoryStream modelMemoryStream = asset.Pack.CreateAssetMemoryStreamByName(assetName))
                {
                    Model model = Model.LoadFromStream(assetName, assetDisplayName, modelMemoryStream);

                    if (model == null)
                    {
                        return;
                    }

                    ModelExporter.ExportModel(this, model, ResourceDirectory + "/Models");
                    lastAssetProcessed = assetName;
                }
            }, null, null);

            while (!result.IsCompleted)
            {
                ProgressBar(MathUtils.Remap01(assetsProcessed / (float)modelAssets.Count, progress0, progress100), "Exporting Model: " + lastAssetProcessed);
            }

            parallelTask.EndInvoke(result);
        }
Ejemplo n.º 8
0
        private void ComputeGraham()
        {
            Point bary = FindBarycentre();

            calculatedPoints = OrderList(bary);

            Point sInit = calculatedPoints[0];
            Point pivot = sInit;

            int  index = 0;
            bool goForward;

            do
            {
                Vector3 sourceAngle = calculatedPoints[index != 0 ? index - 1 : calculatedPoints.Count - 1].GetPosition() - pivot.GetPosition();

                Vector3 targetAngle = pivot.GetPosition() - calculatedPoints[(index + 1 == calculatedPoints.Count ? 0 : index + 1) % calculatedPoints.Count].GetPosition();

                float calculatedAngle = MathUtils.AngleClockwise(sourceAngle, targetAngle);
                if (calculatedAngle < 0)
                {
                    calculatedAngle = 2 * (float)Math.PI - calculatedAngle;
                }

                if (calculatedAngle < Math.PI)
                {
                    index = index + 1 >= calculatedPoints.Count ? 0 : index + 1;

                    pivot     = calculatedPoints[index];
                    goForward = true;
                }
                else
                {
                    index = index != 0 ? index - 1 : calculatedPoints.Count - 1;
                    sInit = calculatedPoints[index];
                    calculatedPoints.Remove(pivot);
                    pivot = sInit;

                    goForward = false;
                }
            } while (pivot != sInit || !goForward);
        }
Ejemplo n.º 9
0
        public void WriteToZone(Zone zone)
        {
            ValidateObjectUIDs();

            zone.Lights.Clear();

            foreach (ZoneLight zoneLight in Resources.FindObjectsOfTypeAll <ZoneLight>())
            {
                if (zoneLight.hideFlags == HideFlags.NotEditable || zoneLight.hideFlags == HideFlags.HideAndDontSave || EditorUtility.IsPersistent(zoneLight))
                {
                    continue;
                }

                Light light = new Light();

                TransformData correctedTransform = MathUtils.ConvertTransform(zoneLight.transform.position, zoneLight.transform.rotation.eulerAngles, Vector3.one, false, TransformMode.Standard);
                light.Position = correctedTransform.Position;
                Vector3 rotationData = correctedTransform.Rotation.ToRadians();
                light.Rotation = new Vector4(rotationData.x, rotationData.y, rotationData.z, 1);

                light.Name           = zoneLight.Name;
                light.ColorName      = zoneLight.ColorName;
                light.Type           = zoneLight.Type;
                light.UnknownFloat1  = zoneLight.UnknownFloat1;
                light.Range          = zoneLight.Range;
                light.InnerRange     = zoneLight.InnerRange;
                light.Color          = zoneLight.Color;
                light.UnknownByte1   = zoneLight.UnknownByte1;
                light.UnknownByte2   = zoneLight.UnknownByte2;
                light.UnknownByte3   = zoneLight.UnknownByte3;
                light.UnknownByte4   = zoneLight.UnknownByte4;
                light.UnknownByte5   = zoneLight.UnknownByte5;
                light.UnknownVector1 = zoneLight.UnknownVector1;
                light.UnknownString1 = zoneLight.UnknownString1;
                light.ID             = zoneLight.ID;

                zone.Lights.Add(light);
            }
        }
        public void LoadAreaDefinitions(Areas areas, float progressMin, float progressMax)
        {
            string areasName = Path.GetFileNameWithoutExtension(areas.Name);

            Parent.name += " - " + areasName;

            for (int i = 0; i < areas.AreaDefinitions.Count; i++)
            {
                AreaDefinition areaDefinition = areas.AreaDefinitions[i];
                AreaObject     instance       = null;

                switch (areaDefinition.Shape)
                {
                case "sphere":
                    instance = GameObject.CreatePrimitive(PrimitiveType.Sphere).AddComponent <AreaObject>();

                    TransformData correctedSphereTransform = MathUtils.ConvertTransform(areaDefinition.Pos1, Vector4.zero, new Vector4(areaDefinition.Radius, areaDefinition.Radius, areaDefinition.Radius), false, TransformMode.Area);
                    instance.transform.position   = correctedSphereTransform.Position;
                    instance.transform.rotation   = Quaternion.Euler(correctedSphereTransform.Rotation);
                    instance.transform.localScale = correctedSphereTransform.Scale;

                    instance.Radius = areaDefinition.Radius;
                    break;

                case "box":
                    instance = GameObject.CreatePrimitive(PrimitiveType.Cube).AddComponent <AreaObject>();
                    Vector3 pos1 = areaDefinition.Pos1;
                    Vector3 pos2 = areaDefinition.Pos2;

                    Vector3 fScale = pos2 - pos1;
                    fScale.x = Mathf.Abs(fScale.x);
                    fScale.y = Mathf.Abs(fScale.y);
                    fScale.z = Mathf.Abs(fScale.z);

                    Vector3 fPos = (pos1 + pos2) * 0.5f;
                    Vector4 fRot = areaDefinition.Rot;

                    TransformData correctedBoxMatrix = MathUtils.ConvertTransform(fPos, fRot, fScale, true, TransformMode.Area);
                    instance.transform.position   = correctedBoxMatrix.Position;
                    instance.transform.rotation   = Quaternion.Euler(correctedBoxMatrix.Rotation);
                    instance.transform.localScale = correctedBoxMatrix.Scale;

                    instance.Pos2 = areaDefinition.Pos2;
                    instance.Rot  = areaDefinition.Rot;
                    break;
                }

                instance.name = areaDefinition.Name;

                int layer = LayerMask.NameToLayer("ForgelightAreas");
                instance.gameObject.layer = layer;

                foreach (Transform child in instance.transform)
                {
                    child.gameObject.layer = layer;
                }

                instance.ID    = areaDefinition.ID;
                instance.Name  = areaDefinition.Name;
                instance.Shape = areaDefinition.Shape;
                instance.Pos1  = areaDefinition.Pos1;

                instance.transform.SetParent(Parent.transform, true);

                //We color the area definition based on its parameter type.
                Renderer renderer = instance.GetComponent <Renderer>();
                renderer.shadowCastingMode = ShadowCastingMode.Off;
                renderer.receiveShadows    = false;

                Color color = new Color(1.0f, 1.0f, 1.0f, 0.5f);

                if (areaDefinition.Properties != null && areaDefinition.Properties.Count > 0)
                {
                    instance.Properties = new List <string>();

                    foreach (Property property in areaDefinition.Properties)
                    {
                        instance.Properties.Add(property.Type + "_" + property.ID + ": " + property.Parameters.Attributes());
                    }

                    MD5 md5 = MD5.Create();

                    byte[] hash = md5.ComputeHash(Encoding.UTF8.GetBytes(areaDefinition.Properties[0].Type));

                    color.r = hash[0] / 255.0f;
                    color.g = hash[1] / 255.0f;
                    color.b = hash[2] / 255.0f;
                }

                if (cachedMaterials.ContainsKey(color))
                {
                    renderer.sharedMaterial = cachedMaterials[color];
                }
                else
                {
                    renderer.sharedMaterial       = new Material(Shader.Find("Custom/Areas"));
                    renderer.sharedMaterial.color = color;

                    cachedMaterials[color] = renderer.sharedMaterial;
                }

                EditorUtility.DisplayProgressBar("Loading " + areasName, "Loading Area Definition: " + areaDefinition.Name, MathUtils.Remap01((float)i / areas.AreaDefinitions.Count, progressMin, progressMax));
            }
        }
Ejemplo n.º 11
0
        //TODO Less Code Duplication.
        //TODO Update CNK0 Parsing. The current format seems to be incorrect.
        public void ImportTerrain(float progress0, float progress100)
        {
            int    chunksProcessed = 0;
            string assetProcessing = "";

            //CNK0 (Geo)
            //List<AssetRef> terrainAssetsCnk0 = AssetsByType[AssetRef.Types.CNK0];

            //Parallel.AsyncForEach<AssetRef> parallelTask = System.Threading.Tasks.Parallel.ForEach;
            //IAsyncResult result = parallelTask.BeginInvoke(terrainAssetsCnk0, asset =>
            //{
            //    if (asset == null)
            //    {
            //        return;
            //    }

            //    //Names
            //    string assetName = asset.Name;
            //    string assetDisplayName = BuildAssetName(assetName, asset.Pack.Name);

            //    //De-serialize
            //    using (MemoryStream terrainMemoryStream = asset.Pack.CreateAssetMemoryStreamByName(asset.Name))
            //    {
            //        Cnk0 chunk = Cnk0.LoadFromStream(assetName, assetDisplayName, terrainMemoryStream);

            //        if (chunk != null)
            //        {
            //            ChunkExporter.ExportChunk(this, chunk, ResourceDirectory + "/Terrain");
            //            assetProcessing = assetName;
            //        }

            //        Interlocked.Increment(ref chunksProcessed);
            //    }
            //}, null, null);

            //while (!result.IsCompleted)
            //{
            //    ProgressBar(MathUtils.Remap01(chunksProcessed / ((float)terrainAssetsCnk0.Count), progress0, progress100), "Exporting Chunk: " + assetProcessing);
            //}

            //chunksProcessed = 0;
            //texturesProcessed = 0;

            //CNK1 (Geo)
            List <AssetRef> terrainAssetsCnk1 = AssetsByType[AssetRef.Types.CNK1];

            object texLock = new object();

            Parallel.AsyncForEach <AssetRef> parallelTask = System.Threading.Tasks.Parallel.ForEach;
            IAsyncResult result = parallelTask.BeginInvoke(terrainAssetsCnk1, asset =>
            {
                Interlocked.Increment(ref chunksProcessed);

                if (asset == null)
                {
                    return;
                }

                //Names
                string assetName        = asset.Name;
                string assetDisplayName = BuildAssetName(assetName, asset.Pack.Name);

                //De-serialize
                using (MemoryStream terrainMemoryStream = asset.Pack.CreateAssetMemoryStreamByName(assetName))
                {
                    CnkLOD chunk = CnkLOD.LoadFromStream(assetName, assetDisplayName, terrainMemoryStream);

                    if (chunk != null)
                    {
                        ChunkExporter.ExportChunk(this, chunk, ResourceDirectory + "/Terrain");

                        lock (texLock)
                        {
                            ChunkExporter.ExportTextures(this, chunk, ResourceDirectory + "/Terrain");
                        }
                    }

                    assetProcessing = assetName;
                }
            }, null, null);

            while (!result.IsCompleted)
            {
                ProgressBar(MathUtils.Remap01((float)chunksProcessed / terrainAssetsCnk1.Count, progress0, progress100), "Exporting Chunk: " + assetProcessing);
            }

            parallelTask.EndInvoke(result);

            ////CNK2
            //ProgressBar(progress0 + MathUtils.RemapProgress(0.50f, progress0, progress100), "Exporting Terrain Data (LOD 2)...");
            //List<Asset> terrainAssetsCnk2 = AssetsByType[Asset.Types.CNK2];
            //int terrainAssetsCnk2Processed = 0;

            //Parallel.ForEach(terrainAssetsCnk2, asset =>
            //{
            //    using (MemoryStream terrainMemoryStream = asset.Pack.CreateAssetMemoryStreamByName(asset.Name))
            //    {
            //        CnkLOD chunk = CnkLOD.LoadFromStream(asset.Name, terrainMemoryStream);
            //    }

            //    Interlocked.Increment(ref terrainAssetsCnk2Processed);
            //    //ProgressBar(MathUtils.RemapProgress((float)terrainAssetsCnk2Processed / (float)terrainAssetsCnk2.Count, progress0, progress100), "Exporting Chunk (LOD2): " + Path.GetFileName(asset.Name));
            //});

            ////CNK3
            //ProgressBar(progress0 + MathUtils.RemapProgress(0.75f, progress0, progress100), "Exporting Terrain Data (LOD 3)...");
            //List<Asset> terrainAssetsCnk3 = AssetsByType[Asset.Types.CNK3];
            //int terrainAssetsCnk3Processed = 0;

            //Parallel.ForEach(terrainAssetsCnk3, asset =>
            //{
            //    using (MemoryStream terrainMemoryStream = asset.Pack.CreateAssetMemoryStreamByName(asset.Name))
            //    {
            //        CnkLOD chunk = CnkLOD.LoadFromStream(asset.Name, terrainMemoryStream);
            //    }

            //    Interlocked.Increment(ref terrainAssetsCnk3Processed);
            //    //ProgressBar(MathUtils.RemapProgress((float)terrainAssetsCnk3Processed / (float)terrainAssetsCnk3.Count, progress0, progress100), "Exporting Chunk (LOD3): " + Path.GetFileName(asset.Name));
            //});
        }
        public void WriteToZone(Zone zone)
        {
            //Objects
            Dictionary <string, List <ZoneObject> > actorInstances = new Dictionary <string, List <ZoneObject> >();

            //Check to make sure we don't have duplicate ID's
            ValidateObjectUIDs();

            foreach (ZoneObject zoneObject in Resources.FindObjectsOfTypeAll <ZoneObject>())
            {
                if (zoneObject.hideFlags == HideFlags.NotEditable || zoneObject.hideFlags == HideFlags.HideAndDontSave || EditorUtility.IsPersistent(zoneObject))
                {
                    continue;
                }

                string actorDef = zoneObject.actorDefinition;
                if (!actorInstances.ContainsKey(actorDef))
                {
                    actorInstances.Add(actorDef, new List <ZoneObject>());
                }

                actorInstances[actorDef].Add(zoneObject);
            }

            zone.Objects.Clear();
            foreach (var actorInstanceList in actorInstances)
            {
                Object zoneObj = new Object();

                zoneObj.ActorDefinition = actorInstanceList.Key;
                zoneObj.RenderDistance  = actorInstanceList.Value[0].renderDistance;

                zoneObj.Instances = new List <Object.Instance>();

                foreach (ZoneObject zoneObject in actorInstanceList.Value)
                {
                    //Make sure we don't have a parent.
                    Transform objectParent = zoneObject.transform.parent;
                    if (objectParent != null)
                    {
                        zoneObject.transform.SetParent(null);
                    }

                    Object.Instance instance = new Object.Instance();

                    TransformData correctedTransform = MathUtils.ConvertTransform(zoneObject.transform.position, zoneObject.transform.rotation.eulerAngles, zoneObject.transform.localScale, false, TransformMode.Standard);

                    instance.Position = correctedTransform.Position;
                    instance.Rotation = correctedTransform.Rotation.ToRadians();
                    instance.Scale    = correctedTransform.Scale;

                    instance.ID = (uint)zoneObject.ID;
                    instance.DontCastShadows = zoneObject.DontCastShadows;
                    instance.LODMultiplier   = zoneObject.lodMultiplier;

                    zoneObj.Instances.Add(instance);

                    //If we had a parent, reset our parent to the original.

                    if (objectParent != null)
                    {
                        zoneObject.transform.SetParent(objectParent);
                    }
                }

                zone.Objects.Add(zoneObj);
            }
        }
Ejemplo n.º 13
0
        public bool RunImport(ForgelightGame forgelightGame, float progress0, float progress100)
        {
            ForgelightGame = forgelightGame;
            ResourceDir    = forgelightGame.GameInfo.FullResourceDirectory;

            // Progress Bar
            AssetsProcessed    = 0;
            LastAssetProcessed = "";

            // Operation Items
            object oLock = new object();

            assetsToProcess = new ConcurrentQueue <AssetRef>(forgelightGame.AssetsByType[AssetType]);
            int totalAssetCount = assetsToProcess.Count;

            Parallel.AsyncForEach <bool> parallelTask = System.Threading.Tasks.Parallel.ForEach;
            bool cancel = false;

            IAsyncResult result = parallelTask.BeginInvoke(WorkComplete(), job =>
            {
                // Setup the Thread
                T2 threadData = new T2();

                // Process all available jobs.
                while (!cancel && JobsAvailable())
                {
                    AssetRef currentJob;
                    assetsToProcess.TryDequeue(out currentJob);

                    if (currentJob == null)
                    {
                        continue;
                    }

                    Import(currentJob, threadData, oLock);
                    Interlocked.Increment(ref AssetsProcessed);
                    LastAssetProcessed = currentJob.Name;
                }
            }, null, null);

            while (!RunBackgroundTasks() || !result.IsCompleted)
            {
                cancel = EditorUtility.DisplayCancelableProgressBar("Forgelight - " + forgelightGame.GameInfo.Name, ProgressItemPrefix + LastAssetProcessed, MathUtils.Remap01(AssetsProcessed / (float)totalAssetCount, progress0, progress100));
            }

            parallelTask.EndInvoke(result);

            if (cancel)
            {
                EditorUtility.ClearProgressBar();
            }
            return(!cancel);
        }