Пример #1
0
        public void Reload(LevelSettings settings, IDialogHandler progressReporter = null)
        {
            if (string.IsNullOrEmpty(Path))
            {
                Sounds        = null;
                LoadException = new Exception("Path is empty.");
                return;
            }

            // Load the catalog
            try
            {
                var path = settings.MakeAbsolute(Path);
                if (File.Exists(path))
                {
                    WadSounds newSounds = WadSounds.ReadFromFile(path);
                    Sounds        = newSounds;
                    LoadException = null;
                }
                else
                {
                    LoadException = new Exception("File not found: " + path);
                }
            }
            catch (Exception exc)
            {
                logger.Warn(exc, "Unable to load catalog '" + Path + "'.");
                Sounds        = null;
                LoadException = exc;
            }
        }
Пример #2
0
 public LevelTexture(LevelSettings settings, string path, bool convert512PixelsToDoubleRows = false, bool replaceWithTransparency = true)
 {
     Convert512PixelsToDoubleRows   = convert512PixelsToDoubleRows;
     ReplaceMagentaWithTransparency = replaceWithTransparency;
     SetPath(settings, path);
     BumpPath = "";
 }
Пример #3
0
        public void Reload(LevelSettings settings, IDialogHandler progressReporter = null)
        {
            if (string.IsNullOrEmpty(Path))
            {
                Wad           = null;
                LoadException = new Exception("Path is empty.");
                return;
            }

            // Load wad
            try
            {
                Wad2 newWad = Wad2.ImportFromFile(
                    settings.MakeAbsolute(Path),
                    false,
                    progressReporter ?? new ProgressReporterSimple());
                Wad           = newWad;
                LoadException = null;
            }
            catch (Exception exc)
            {
                logger.Warn(exc, "Unable to load wad '" + Path + "'.");
                Wad           = null;
                LoadException = exc;
            }
        }
Пример #4
0
 public AutoStaticMeshMergeEntry(uint staticMesh, bool merge, bool interpretShadesAsEffect, bool tintAsAmbient, bool clearShades, LevelSettings parent)
 {
     this.meshId                  = staticMesh;
     this.parent                  = parent;
     this.Merge                   = merge;
     this.TintAsAmbient           = tintAsAmbient;
     this.InterpretShadesAsEffect = interpretShadesAsEffect;
     this.ClearShades             = clearShades;
 }
Пример #5
0
 public void SetReplaceMagentaWithTransparency(LevelSettings settings, bool value)
 {
     if (ReplaceMagentaWithTransparency == value)
     {
         return;
     }
     ReplaceMagentaWithTransparency = value;
     Reload(settings);
 }
Пример #6
0
 public void SetConvert512PixelsToDoubleRows(LevelSettings settings, bool value)
 {
     if (Convert512PixelsToDoubleRows == value)
     {
         return;
     }
     Convert512PixelsToDoubleRows = value;
     Reload(settings);
 }
Пример #7
0
        public LevelSettings Clone()
        {
            LevelSettings result = (LevelSettings)MemberwiseClone();

            result.Wads                 = Wads.ConvertAll(wad => wad.Clone());
            result.WadSoundPaths        = WadSoundPaths.ConvertAll(soundPath => soundPath.Clone());
            result.SoundsCatalogs       = SoundsCatalogs.ConvertAll(catalog => catalog.Clone());
            result.Textures             = Textures.ConvertAll(texture => (LevelTexture)texture.Clone());
            result.AnimatedTextureSets  = AnimatedTextureSets.ConvertAll(set => set.Clone());
            result.ImportedGeometries   = ImportedGeometries.ConvertAll(geometry => geometry.Clone());
            result.AutoStaticMeshMerges = AutoStaticMeshMerges.ConvertAll(entry => entry.Clone());
            return(result);
        }
Пример #8
0
        public void Reload(LevelSettings settings)
        {
            LoadException = null;
            if (string.IsNullOrEmpty(Path))
            {
                Image = UnloadedPlaceholder;
                return;
            }

            // Load image
            try
            {
                ImageC image = ImageC.FromFile(settings.MakeAbsolute(Path));

                if (Convert512PixelsToDoubleRows && image.Width == 512)
                {
                    ImageC newImage = ImageC.CreateNew(256, image.Height * 2);
                    newImage.FileName = image.FileName;
                    for (int oldY = 0; oldY < image.Height; oldY += 64)
                    {
                        newImage.CopyFrom(0, oldY * 2, image, 0, oldY, 256, 64);
                        newImage.CopyFrom(0, oldY * 2 + 64, image, 256, oldY, 256, 64);
                    }
                    image = newImage;
                }

                if (ReplaceMagentaWithTransparency)
                {
                    image.ReplaceColor(new ColorC(255, 0, 255, 255), new ColorC(0, 0, 0, 0));
                }

                image.CalculatePalette();
                Image = image;

                // Resize sound array
                ResizeFootStepSounds(
                    (int)Math.Ceiling(Image.Width / FootStepSoundGranularity),
                    (int)Math.Ceiling(Image.Height / FootStepSoundGranularity));

                // Resize bump maps
                ResizeBumpMappingInfos(
                    (int)Math.Ceiling(Image.Width / BumpMappingGranularity),
                    (int)Math.Ceiling(Image.Height / BumpMappingGranularity));
            }
            catch (Exception exc)
            {
                logger.Warn(exc, "Unable to load texture '" + Path + "'.");
                Image         = UnloadedPlaceholder;
                LoadException = exc;
            }
        }
Пример #9
0
        public void MergeFrom(Level otherLevel, bool unifyData, Action <LevelSettings> applyLevelSettings = null)
        {
            IReadOnlyList <ObjectInstance> oldObjects = Rooms.Where(room => room != null).SelectMany(room => room.AnyObjects).ToList();
            IReadOnlyList <Room>           otherRooms = otherLevel.Rooms.Where(room => room != null).ToList();

            // Merge rooms
            for (int i = 0; i < otherRooms.Count; ++i)
            {
                try
                {
                    AssignRoomToFree(otherRooms[i]);
                }
                catch
                { // If we fail, roll back the changes...
                    while (i > 0)
                    {
                        DeleteRoomWithAlternate(otherRooms[--i]);
                    }
                    throw;
                }
            }

            // Merge dependencies like imported geometries, textures (and wads in the future?)
            LevelSettings newSettings = applyLevelSettings == null ? Settings : Settings.Clone();

            newSettings.Textures           = Settings.Textures.ToList(); // Make sure the same references are used.
            newSettings.ImportedGeometries = Settings.ImportedGeometries.ToList();
            var copyInstance = new Room.CopyDependentLevelSettingsArgs(oldObjects, newSettings, otherLevel.Settings, unifyData);

            foreach (Room room in otherRooms)
            {
                room.CopyDependentLevelSettings(copyInstance);
            }
            applyLevelSettings?.Invoke(newSettings);
            GlobalScriptingIdsTable.MergeFrom(otherLevel.GlobalScriptingIdsTable, @object => @object.ScriptId = null);
            foreach (Room room in otherRooms)
            {
                room.Level = this;
            }
        }
Пример #10
0
 public ReferencedSoundsCatalog(LevelSettings settings, string path, IDialogHandler progressReporter = null)
 {
     Path = path;
     Reload(settings, progressReporter);
 }
Пример #11
0
 public ImportedGeometryComparer(LevelSettings settings)
 {
     _settings = settings;
 }
Пример #12
0
 public void SetPath(LevelSettings settings, string path)
 {
     Path = path;
     Reload(settings);
 }
Пример #13
0
        public void Update(LevelSettings settings, Dictionary <string, Texture> absolutePathTextureLookup, ImportedGeometryInfo info)
        {
            Info          = info;
            LoadException = null;
            DirectXModel  = null;
            Textures.Clear();

            try
            {
                string importedGeometryPath      = settings.MakeAbsolute(info.Path);
                string importedGeometryDirectory = Path.GetDirectoryName(importedGeometryPath);

                // Invoke the TombLib geometry import code
                var settingsIO = new IOGeometrySettings
                {
                    Scale          = info.Scale,
                    SwapXY         = info.SwapXY,
                    SwapXZ         = info.SwapXZ,
                    SwapYZ         = info.SwapYZ,
                    FlipX          = info.FlipX,
                    FlipY          = info.FlipY,
                    FlipZ          = info.FlipZ,
                    FlipUV_V       = info.FlipUV_V,
                    InvertFaces    = info.InvertFaces,
                    UseVertexColor = true
                };

                BaseGeometryImporter importer = BaseGeometryImporter.CreateForFile(importedGeometryPath, settingsIO, absoluteTexturePath =>
                {
                    return(GetOrAddTexture(absolutePathTextureLookup, importedGeometryDirectory, absoluteTexturePath));
                });
                var tmpModel = importer.ImportFromFile(importedGeometryPath);

                SynchronizationContext.Current.Post(unused => // Synchronize DirectX, we can't 'send' because that may deadlock with the level settings reloader
                {
                    if (Device == null)
                    {
                        return;
                    }

                    // Create a new static model
                    DirectXModel             = new Model(Device, info.Scale);
                    DirectXModel.BoundingBox = tmpModel.BoundingBox;

                    // Create materials
                    foreach (var tmpMaterial in tmpModel.Materials)
                    {
                        var material              = new Material(tmpMaterial.Name);
                        material.Texture          = tmpMaterial.Texture;
                        material.AdditiveBlending = tmpMaterial.AdditiveBlending;
                        material.DoubleSided      = tmpMaterial.DoubleSided;
                        DirectXModel.Materials.Add(material);
                    }

                    // Loop for each mesh loaded in scene
                    foreach (var mesh in tmpModel.Meshes)
                    {
                        var modelMesh = new ImportedGeometryMesh(Device, mesh.Name);

                        modelMesh.HasVertexColors = (mesh.Colors.Count != 0);

                        var currentIndex = 0;
                        var currPoly     = 0;
                        foreach (var tmpSubmesh in mesh.Submeshes)
                        {
                            var material = DirectXModel.Materials[tmpModel.Materials.IndexOf(tmpSubmesh.Value.Material)];
                            var submesh  = new Submesh(material);

                            foreach (var tmpPoly in tmpSubmesh.Value.Polygons)
                            {
                                if (tmpPoly.Shape == IOPolygonShape.Quad)
                                {
                                    var vertexList = new List <ImportedGeometryVertex>();

                                    for (var i = 0; i < 4; i++)
                                    {
                                        var vertex      = new ImportedGeometryVertex();
                                        vertex.Position = mesh.Positions[tmpPoly.Indices[i]];
                                        vertex.Color    = tmpPoly.Indices[i] < mesh.Colors.Count ? mesh.Colors[tmpPoly.Indices[i]].To3() : Vector3.One;
                                        vertex.UV       = tmpPoly.Indices[i] < mesh.UV.Count ? mesh.UV[tmpPoly.Indices[i]] : Vector2.Zero;
                                        vertex.Normal   = tmpPoly.Indices[i] < mesh.Normals.Count ? mesh.Normals[tmpPoly.Indices[i]] : Vector3.Zero;
                                        vertexList.Add(vertex);
                                    }

                                    // HACK: Triangulate and disjoint quad faces for imported geometry, because otherwise another hack which joints
                                    // disjointed vertices together will fail in Rooms.cs

                                    submesh.Indices.Add(currentIndex);
                                    submesh.Indices.Add(currentIndex + 1);
                                    submesh.Indices.Add(currentIndex + 2);
                                    submesh.Indices.Add(currentIndex + 3);
                                    submesh.Indices.Add(currentIndex + 4);
                                    submesh.Indices.Add(currentIndex + 5);

                                    modelMesh.Vertices.Add(vertexList[0]);
                                    modelMesh.Vertices.Add(vertexList[1]);
                                    modelMesh.Vertices.Add(vertexList[2]);
                                    modelMesh.Vertices.Add(vertexList[0]);
                                    modelMesh.Vertices.Add(vertexList[2]);
                                    modelMesh.Vertices.Add(vertexList[3]);

                                    currentIndex += 6;
                                }
                                else
                                {
                                    for (var i = 0; i < 3; i++)
                                    {
                                        var vertex      = new ImportedGeometryVertex();
                                        vertex.Position = mesh.Positions[tmpPoly.Indices[i]];
                                        vertex.Color    = tmpPoly.Indices[i] < mesh.Colors.Count ? mesh.Colors[tmpPoly.Indices[i]].To3() : Vector3.One;
                                        vertex.UV       = tmpPoly.Indices[i] < mesh.UV.Count ? mesh.UV[tmpPoly.Indices[i]] : Vector2.Zero;
                                        vertex.Normal   = tmpPoly.Indices[i] < mesh.Normals.Count ? mesh.Normals[tmpPoly.Indices[i]] : Vector3.Zero;
                                        modelMesh.Vertices.Add(vertex);
                                        submesh.Indices.Add(currentIndex);
                                        currentIndex++;
                                    }
                                }

                                currPoly++;
                            }

                            modelMesh.Submeshes.Add(material, submesh);
                        }

                        DirectXModel.Meshes.Add(modelMesh);
                    }

                    DirectXModel.UpdateBuffers();
                }, null);
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception exc)
            {
                LoadException = exc;
                DirectXModel  = null;
                logger.Warn(exc, "Unable to load model \"" + info.Name + "\" from \"" + info.Path + "\" because an exception occurred during loading.");
            }
        }
Пример #14
0
 public ItemType(WadMoveableId moveableId, LevelSettings levelSettings) // wad can be null
     : this(moveableId, levelSettings?.GameVersion ?? TRVersion.Game.TR4)
 {
 }
Пример #15
0
 public ItemType(WadStaticId staticId, LevelSettings levelSettings) // wad can be null
     : this(staticId, levelSettings?.GameVersion ?? TRVersion.Game.TR4)
 {
 }
Пример #16
0
 public void ApplyNewLevelSettings(LevelSettings newSettings) => ApplyNewLevelSettings(newSettings, s => { });
Пример #17
0
        public void ApplyNewLevelSettings(LevelSettings newSettings, Action <ObjectInstance> objectChangedNotification)
        {
            LevelSettings oldSettings = Settings;

            Settings = newSettings;

            // Imported geometry
            {
                // Reuse old imported geometry objects to keep references up to date
                var oldLookup = new Dictionary <ImportedGeometry.UniqueIDType, ImportedGeometry>();
                foreach (ImportedGeometry oldImportedGeometry in oldSettings.ImportedGeometries)
                {
                    oldLookup.Add(oldImportedGeometry.UniqueID, oldImportedGeometry);
                }
                for (int i = 0; i < newSettings.ImportedGeometries.Count; ++i)
                {
                    ImportedGeometry newImportedGeometry = newSettings.ImportedGeometries[i];
                    ImportedGeometry oldImportedGeometry;
                    if (oldLookup.TryGetValue(newImportedGeometry.UniqueID, out oldImportedGeometry))
                    {
                        oldImportedGeometry.Assign(newImportedGeometry);
                        newSettings.ImportedGeometries[i] = oldImportedGeometry;
                        oldLookup.Remove(oldImportedGeometry.UniqueID); // The same object shouldn't be matched multiple times.
                    }
                }

                // Reset imported geometry objects if any objects are now missing
                if (oldLookup.Count != 0)
                {
                    foreach (Room room in Rooms.Where(room => room != null))
                    {
                        foreach (var instance in room.Objects.OfType <ImportedGeometryInstance>())
                        {
                            if (instance.Model != null && oldLookup.ContainsKey(instance.Model.UniqueID))
                            {
                                instance.Model = null;
                                objectChangedNotification(instance);
                            }
                        }
                    }
                }
            }

            // Level texture
            {
                // Reuse old level texture objects to keep references up to date
                var oldLookup = new Dictionary <LevelTexture.UniqueIDType, LevelTexture>();
                foreach (LevelTexture oldLevelTexture in oldSettings.Textures)
                {
                    oldLookup.Add(oldLevelTexture.UniqueID, oldLevelTexture);
                }
                for (int i = 0; i < newSettings.Textures.Count; ++i)
                {
                    LevelTexture newLevelTexture = newSettings.Textures[i];
                    LevelTexture oldLevelTexture;
                    if (oldLookup.TryGetValue(newLevelTexture.UniqueID, out oldLevelTexture))
                    {
                        oldLevelTexture.Assign(newLevelTexture);
                        newSettings.Textures[i] = oldLevelTexture;
                        oldLookup.Remove(oldLevelTexture.UniqueID); // The same object shouldn't be matched multiple times.
                    }
                }

                // Reset level texture objects if any objects are now missing
                if (oldLookup.Count != 0)
                {
                    RemoveTextures(texture => oldLookup.ContainsKey(texture.UniqueID));
                }
            }
        }