Exemplo n.º 1
0
        public FormStaticEditor(WadToolClass tool, DeviceManager deviceManager, Wad2 wad, WadStatic @static)
        {
            _doChangesInLighting = false;

            InitializeComponent();

            _wad    = wad;
            _tool   = tool;
            _device = deviceManager.___LegacyDevice;

            Static = @static;

            _workingStatic = @static.Clone();
            panelRendering.InitializeRendering(tool, deviceManager);

            panelRendering.Configuration = _tool.Configuration;
            panelRendering.Static        = _workingStatic;
            panelRendering.DrawGrid      = true;
            panelRendering.DrawGizmo     = true;
            panelRendering.DrawLights    = true;
            comboLightType.SelectedIndex = (int)_workingStatic.LightingType;
            UpdateVisibilityBoxUI();
            UpdateCollisionBoxUI();
            UpdatePositionUI();
            UpdateLightsList();
            UpdateLightUI();

            numAmbient.Value = (decimal)_workingStatic.AmbientLight;

            _tool.EditorEventRaised += Tool_EditorEventRaised;

            _doChangesInLighting = true;
        }
Exemplo n.º 2
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;
            }
        }
Exemplo n.º 3
0
        private void ConvertSourceToTR5MainToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Wad2 dest = WadActions.ConvertWad2ToTR5Main(_tool, this, _tool.SourceWad);

            Wad2Writer.SaveToFile(dest, "F:\\temp.wad2");
            WadActions.LoadWad(_tool, this, true, "F:\\temp.wad2");
        }
Exemplo n.º 4
0
        public static WadStatic ConvertTrLevelStaticMeshToWadStatic(Wad2 wad, TrLevel oldLevel, int staticIndex, TextureArea[] objectTextures)
        {
            tr_staticmesh oldStatic = oldLevel.StaticMeshes[staticIndex];
            var           newStatic = new WadStatic(new WadStaticId(oldStatic.ObjectID));

            // First setup collisional and visibility bounding boxes
            newStatic.CollisionBox = new BoundingBox(new Vector3(oldStatic.CollisionBox.X1,
                                                                 -oldStatic.CollisionBox.Y1,
                                                                 oldStatic.CollisionBox.Z1),
                                                     new Vector3(oldStatic.CollisionBox.X2,
                                                                 -oldStatic.CollisionBox.Y2,
                                                                 oldStatic.CollisionBox.Z2));

            newStatic.VisibilityBox = new BoundingBox(new Vector3(oldStatic.VisibilityBox.X1,
                                                                  -oldStatic.VisibilityBox.Y1,
                                                                  oldStatic.VisibilityBox.Z1),
                                                      new Vector3(oldStatic.VisibilityBox.X2,
                                                                  -oldStatic.VisibilityBox.Y2,
                                                                  oldStatic.VisibilityBox.Z2));

            // Then import the mesh. If it was already added, the mesh will not be added to the dictionary.
            newStatic.Mesh = ConvertTrLevelMeshToWadMesh(wad,
                                                         oldLevel,
                                                         oldLevel.GetMeshFromPointer(oldStatic.Mesh),
                                                         objectTextures);
            return(newStatic);
        }
Exemplo n.º 5
0
        private static TextureArea ConvertColoredFaceToTexture(Wad2 wad, TrLevel oldLevel, ushort paletteIndex, bool isTriangle)
        {
            ColorC color;

            var sixteenBitIndex = paletteIndex >> 8;

            if (oldLevel.Palette16.Count > 0 && oldLevel.Palette16.Count == oldLevel.Palette8.Count && sixteenBitIndex < oldLevel.Palette16.Count)
            {
                var trColor = oldLevel.Palette16[sixteenBitIndex];
                color = new ColorC(trColor.Red, trColor.Green, trColor.Blue, 255);
            }
            else
            {
                var trColor = oldLevel.Palette8[paletteIndex & 0xFF];
                color = new ColorC((byte)(trColor.Red * 4), (byte)(trColor.Green * 4), (byte)(trColor.Blue * 4), 255);
            }

            const int dummyTextureSize = 4;
            var       image            = ImageC.CreateNew(dummyTextureSize, dummyTextureSize);

            image.Fill(color);

            TextureArea textureArea = new TextureArea();

            textureArea.Texture     = new WadTexture(image);
            textureArea.TexCoord0   = new Vector2(0, 0);
            textureArea.TexCoord1   = new Vector2(dummyTextureSize, 0);
            textureArea.TexCoord2   = new Vector2(dummyTextureSize, dummyTextureSize);
            textureArea.TexCoord3   = new Vector2(0, dummyTextureSize);
            textureArea.BlendMode   = BlendMode.Normal;
            textureArea.DoubleSided = false;
            return(textureArea);
        }
Exemplo n.º 6
0
        public static Wad2 ConvertTrLevel(TrLevel oldLevel)
        {
            var wad = new Wad2()
            {
                GameVersion = oldLevel.Version, SoundSystem = SoundSystem.Xml
            };

            logger.Info("Converting TR level to WAD2");

            // Convert textures
            TextureArea[] objectTextures = ConvertTrLevelTexturesToWadTexture(oldLevel);
            logger.Info("Texture conversion complete.");

            // Then convert moveables and static meshes
            // Meshes will be converted inside each model
            for (int i = 0; i < oldLevel.Moveables.Count; i++)
            {
                WadMoveable moveable = ConvertTrLevelMoveableToWadMoveable(wad, oldLevel, i, objectTextures);
                wad.Moveables.Add(moveable.Id, moveable);
            }
            logger.Info("Moveable conversion complete.");

            for (int i = 0; i < oldLevel.StaticMeshes.Count; i++)
            {
                WadStatic @static = ConvertTrLevelStaticMeshToWadStatic(wad, oldLevel, i, objectTextures);
                wad.Statics.Add(@static.Id, @static);
            }
            logger.Info("Static mesh conversion complete.");

            // Convert sprites
            ConvertTrLevelSprites(wad, oldLevel);
            logger.Info("Sprite conversion complete.");

            return(wad);
        }
Exemplo n.º 7
0
        internal static void ConvertTr4Sprites(Wad2 wad, Tr4Wad oldWad)
        {
            int spriteDataSize = oldWad.SpriteData.Length;

            // Load the real sprite texture data
            int numSpriteTexturePages = spriteDataSize / 196608;

            if ((spriteDataSize % 196608) != 0)
            {
                numSpriteTexturePages++;
            }

            foreach (var oldSequence in oldWad.SpriteSequences)
            {
                int lengthOfSequence = -oldSequence.NegativeLength;
                int startIndex       = oldSequence.Offset;

                var newSequence = new WadSpriteSequence(new WadSpriteSequenceId((uint)oldSequence.ObjectID));

                for (int i = startIndex; i < startIndex + lengthOfSequence; i++)
                {
                    var oldSpriteTexture = oldWad.SpriteTextures[i];

                    int spriteWidth  = oldSpriteTexture.Width + 1;
                    int spriteHeight = oldSpriteTexture.Height + 1;
                    int spriteX      = oldSpriteTexture.X;
                    int spriteY      = oldSpriteTexture.Y;
                    var spriteImage  = ImageC.CreateNew(spriteWidth, spriteHeight);

                    for (int y = 0; y < spriteHeight; y++)
                    {
                        for (int x = 0; x < spriteWidth; x++)
                        {
                            int baseIndex = oldSpriteTexture.Tile * 196608 + 768 * (y + spriteY) + 3 * (x + spriteX);

                            byte b = oldWad.SpriteData[baseIndex + 0];
                            byte g = oldWad.SpriteData[baseIndex + 1];
                            byte r = oldWad.SpriteData[baseIndex + 2];

                            if (r == 255 && g == 0 && b == 255)
                            {
                                spriteImage.SetPixel(x, y, 0, 0, 0, 0);
                            }
                            else
                            {
                                spriteImage.SetPixel(x, y, b, g, r, 255);
                            }
                        }
                    }

                    // Add current sprite to the sequence
                    newSequence.Sprites.Add(new WadSprite {
                        Texture = new WadTexture(spriteImage)
                    });
                }

                wad.SpriteSequences.Add(newSequence.Id, newSequence);
            }
        }
Exemplo n.º 8
0
        public FormPreviewWad(Wad2 wad, RenderingDevice device, Editor editor)
        {
            _wad = wad;
            InitializeComponent();

            panelItem.Editor = editor;
            panelItem.InitializeRendering(device, editor.Configuration.RenderingItem_Antialias);
            wadTree.Wad         = wad;
            wadTree.MultiSelect = false;
            wadTree.SelectFirst();
        }
Exemplo n.º 9
0
        private static void ConvertTrLevelSprites(Wad2 wad, TrLevel oldLevel)
        {
            ImageC tiles = ImageC.FromByteArray(oldLevel.TextureMap32, 256, oldLevel.TextureMap32.Length / 1024);

            foreach (var oldSequence in oldLevel.SpriteSequences)
            {
                int lengthOfSequence = -oldSequence.NegativeLength;
                int startIndex       = oldSequence.Offset;

                var newSequence = new WadSpriteSequence(new WadSpriteSequenceId((uint)oldSequence.ObjectID));
                for (int i = startIndex; i < startIndex + lengthOfSequence; i++)
                {
                    tr_sprite_texture oldSpriteTexture = oldLevel.SpriteTextures[i];

                    int spriteX, spriteY, spriteWidth, spriteHeight;

                    int x1 = oldSpriteTexture.LeftSide;
                    int x2 = oldSpriteTexture.RightSide;
                    int y1 = oldSpriteTexture.TopSide;
                    int y2 = oldSpriteTexture.BottomSide;

                    if (oldLevel.Version == TRVersion.Game.TR1 ||
                        oldLevel.Version == TRVersion.Game.TR2 ||
                        oldLevel.Version == TRVersion.Game.TR3)
                    {
                        spriteX      = oldSpriteTexture.X;
                        spriteY      = oldSpriteTexture.Y;
                        spriteWidth  = ((oldSpriteTexture.Width - 255) / 256 + 1);
                        spriteHeight = ((oldSpriteTexture.Height - 255) / 256 + 1);
                    }
                    else
                    {
                        spriteX      = oldSpriteTexture.LeftSide;
                        spriteY      = oldSpriteTexture.TopSide;
                        spriteWidth  = ((oldSpriteTexture.Width / 256) + 1);
                        spriteHeight = ((oldSpriteTexture.Height / 256) + 1);
                    }

                    // Add current sprite to the sequence
                    var spriteImage = ImageC.CreateNew(spriteWidth, spriteHeight);
                    spriteImage.CopyFrom(0, 0, tiles, spriteX, spriteY + oldSpriteTexture.Tile * 256, spriteWidth, spriteHeight);
                    RectangleInt2 rect = new RectangleInt2(x1, y1, x2, y2);
                    newSequence.Sprites.Add(new WadSprite {
                        Texture   = new WadTexture(spriteImage),
                        Alignment = rect
                    });
                }

                wad.SpriteSequences.Add(newSequence.Id, newSequence);
            }
        }
Exemplo n.º 10
0
        public FormSelectSlot(Wad2 wad, IWadObjectId currentId, List <uint> additionalObjectsToHide = null)
        {
            InitializeComponent();

            NewId       = currentId;
            TypeClass   = currentId.GetType();
            GameVersion = wad.GameVersion.Native();

            _wad = wad;
            _additionalObjectsToHide = additionalObjectsToHide;

            if (TypeClass == typeof(WadMoveableId))
            {
                chosenId.Value = ((WadMoveableId)currentId).TypeId;
            }
            else if (TypeClass == typeof(WadStaticId))
            {
                chosenId.Value = ((WadStaticId)currentId).TypeId;
            }
            else if (TypeClass == typeof(WadSpriteSequenceId))
            {
                chosenId.Value = ((WadSpriteSequenceId)currentId).TypeId;
            }
            else if (TypeClass == typeof(WadFixedSoundInfoId))
            {
                chosenId.Value = ((WadFixedSoundInfoId)currentId).TypeId;
            }
            else if (TypeClass == typeof(WadAdditionalSoundInfoId))
            {
                chosenId.Visible      = false;
                chosenIdText.Visible  = true;
                lstSlots.Enabled      = false;
                tbSearchLabel.Enabled = false;
                tbSearch.Enabled      = false;

                chosenIdText.Text = ((WadAdditionalSoundInfoId)currentId).Name;
            }
            else
            {
                throw new NotImplementedException("The " + TypeClass + " is not implemented yet.");
            }

            ReloadSlots();
            if (lstSlots.Items.Count > 0)
            {
                chosenId.Value = (decimal)(uint)lstSlots.Items.First().Tag;
            }
        }
Exemplo n.º 11
0
        public FormSkeletonEditor(WadToolClass tool, DeviceManager manager, Wad2 wad, WadMoveableId moveableId)
        {
            InitializeComponent();

            _wad      = wad;
            _moveable = _wad.Moveables[moveableId].Clone();
            _tool     = tool;

            panelRendering.Configuration = _tool.Configuration;
            panelRendering.InitializeRendering(tool, manager);

            _tool.EditorEventRaised += Tool_EditorEventRaised;

            WadMoveable skin;
            var         skinId = new WadMoveableId(TrCatalog.GetMoveableSkin(_tool.DestinationWad.GameVersion, _moveable.Id.TypeId));

            if (_tool.DestinationWad.Moveables.ContainsKey(skinId))
            {
                skin = _tool.DestinationWad.Moveables[skinId];
            }
            else
            {
                skin = _tool.DestinationWad.Moveables[_moveable.Id];
            }

            // Clone the skeleton and load it
            _bones = new List <WadMeshBoneNode>();
            for (int i = 0; i < _moveable.Bones.Count; i++)
            {
                var boneNode = new WadMeshBoneNode(null, skin.Bones[i].Mesh, _moveable.Bones[i]);
                boneNode.Bone.Translation = _moveable.Bones[i].Translation;
                boneNode.GlobalTransform  = Matrix4x4.Identity;
                _bones.Add(boneNode);
            }

            treeSkeleton.Nodes.AddRange(LoadSkeleton());
            ExpandSkeleton();

            panelRendering.Skeleton = _bones;

            if (treeSkeleton.SelectedNodes.Count <= 0)
            {
                treeSkeleton.SelectNode(treeSkeleton.Nodes[0]);
                panelRendering.SelectedNode = (WadMeshBoneNode)treeSkeleton.SelectedNodes[0].Tag;
            }

            panelRendering.Invalidate();
        }
Exemplo n.º 12
0
        public static void EditObject(WadToolClass tool, IWin32Window owner, DeviceManager deviceManager)
        {
            Wad2       wad       = tool.GetWad(tool.MainSelection?.WadArea);
            IWadObject wadObject = wad?.TryGet(tool.MainSelection?.Id);

            if (wadObject == null || tool.MainSelection?.WadArea == WadArea.Source)
            {
                return;
            }

            if (wad == null)
            {
                tool.SendMessage("You must have a wad loaded and an object selected.", PopupType.Error);
                return;
            }

            // Choose behaviour
            if (wadObject is WadStatic)
            {
                using (var form = new FormStaticEditor(tool, deviceManager, wad, (WadStatic)wadObject))
                    if (form.ShowDialog(owner) != DialogResult.OK)
                    {
                        return;
                    }
                tool.WadChanged(tool.MainSelection.Value.WadArea);
            }
            else if (wadObject is WadMoveable)
            {
                using (var form = new FormAnimationEditor(tool, deviceManager, wad, ((WadMoveable)wadObject).Id))
                {
                    if (form.ShowDialog(owner) != DialogResult.OK)
                    {
                        return;
                    }
                    tool.WadChanged(tool.MainSelection.Value.WadArea);
                }
            }
            else if (wadObject is WadSpriteSequence)
            {
                using (var form = new FormSpriteSequenceEditor(tool, wad, (WadSpriteSequence)wadObject))
                    if (form.ShowDialog(owner) != DialogResult.OK)
                    {
                        return;
                    }
                tool.WadChanged(tool.MainSelection.Value.WadArea);
            }
        }
Exemplo n.º 13
0
        public static TextureDictionary LoadTextureDictionary(string fileName, Palette palette)
        {
            TextureDictionary textures;

            bool isWad2 = Path.GetExtension(fileName).ToLower() == ".wad";

            if (isWad2)
            {
                textures = new Wad2(fileName, palette);
            }
            else
            {
                textures = new TextureDictionary();
            }

            return(textures);
        }
Exemplo n.º 14
0
        public AnimationEditor(WadToolClass tool, Wad2 wad, WadMoveableId idToEdit)
        {
            Tool     = tool;
            Wad      = wad;
            Moveable = Wad.Moveables.ContainsKey(idToEdit) ? Wad.Moveables[idToEdit] : null;

            // NOTE: we work with a pair WadAnimation - Animation. All changes to animation data like name,
            // framerate, next animation, state changes... will be saved directly to WadAnimation.
            // All changes to keyframes will be instead stored directly in the renderer's Animation class.
            // While saving, WadAnimation and Animation will be combined and original animations will be overwritten.

            Animations = new List <AnimationNode>();
            for (int i = 0; i < Moveable.Animations.Count; i++)
            {
                var animation = Moveable.Animations[i].Clone();;
                Animations.Add(new AnimationNode(animation, Animation.FromWad2(Moveable.Bones, animation), i));
            }
        }
Exemplo n.º 15
0
        public static Wad2 ConvertTr4Wad(Tr4Wad oldWad, IDialogHandler progressReporter)
        {
            logger.Info("Converting TR4 WAD to Wad2");

            var wad = new Wad2()
            {
                SoundSystem = SoundSystem.Xml, GameVersion = TRVersion.Game.TR4
            };

            // Convert all textures
            Dictionary <int, WadTexture> textures = ConvertTr4TexturesToWadTexture(oldWad, wad);

            logger.Info("Textures read.");

            // Convert sounds
            var sfxPath = Path.GetDirectoryName(oldWad.FileName) + "\\" + Path.GetFileNameWithoutExtension(oldWad.FileName) + ".sfx";

            if (File.Exists(sfxPath))
            {
                wad.Sounds = WadSounds.ReadFromFile(sfxPath);
                logger.Info("Sounds read.");
            }

            // Convert moveables
            for (int i = 0; i < oldWad.Moveables.Count; i++)
            {
                ConvertTr4MoveableToWadMoveable(wad, oldWad, i, textures);
            }
            logger.Info("Moveables read.");

            // Convert statics
            for (int i = 0; i < oldWad.Statics.Count; i++)
            {
                ConvertTr4StaticMeshToWadStatic(wad, oldWad, i, textures);
            }
            logger.Info("Statics read.");

            // Convert sprites
            ConvertTr4Sprites(wad, oldWad);
            logger.Info("Sprites read.");

            return(wad);
        }
Exemplo n.º 16
0
        public static IWadObjectId CreateObject(WadToolClass tool, IWin32Window owner, IWadObject initialWadObject)
        {
            Wad2 destinationWad = tool.DestinationWad;

            if (destinationWad == null)
            {
                tool.SendMessage("You must have a destination wad opened.", PopupType.Error);
                return(null);
            }

            IWadObjectId result;

            using (var form = new FormSelectSlot(tool.DestinationWad, initialWadObject.Id))
            {
                if (form.ShowDialog(owner) != DialogResult.OK)
                {
                    return(null);
                }
                if (destinationWad.Contains(form.NewId))
                {
                    tool.SendMessage("The slot " + form.NewId.ToString(destinationWad.GameVersion) + " is already occupied.", PopupType.Error);
                    return(null);
                }

                if (initialWadObject is WadMoveable)
                {
                    var moveable = initialWadObject as WadMoveable;
                    var bone     = new WadBone();
                    bone.Name = "Root";
                    bone.Mesh = CreateFakeMesh("Root");
                    moveable.Bones.Add(bone);
                }

                destinationWad.Add(form.NewId, initialWadObject);
                result = form.NewId;
            }

            tool.WadChanged(WadArea.Destination);
            tool.ToggleUnsavedChanges();

            return(result);
        }
Exemplo n.º 17
0
        public static void DeleteObjects(WadToolClass tool, IWin32Window owner, WadArea wadArea, List <IWadObjectId> ObjectIdsToDelete)
        {
            if (ObjectIdsToDelete.Count == 0)
            {
                return;
            }
            if (DarkMessageBox.Show(owner, "You are about to delete " + ObjectIdsToDelete.Count + " objects. Are you sure?",
                                    "A question just in case...", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
            {
                return;
            }

            Wad2 wad = tool.GetWad(wadArea);

            foreach (IWadObjectId id in ObjectIdsToDelete)
            {
                wad.Remove(id);
            }
            tool.WadChanged(wadArea);
        }
Exemplo n.º 18
0
        public FormMesh(WadToolClass tool, DeviceManager deviceManager, Wad2 wad)
        {
            InitializeComponent();

            _tool          = tool;
            _wad           = wad;
            _deviceManager = deviceManager;

            panelMesh.InitializeRendering(_tool, _deviceManager);

            var moveablesNode = new DarkUI.Controls.DarkTreeNode("Moveables");

            foreach (var moveable in _wad.Moveables)
            {
                var list         = new List <DarkUI.Controls.DarkTreeNode>();
                var moveableNode = new DarkUI.Controls.DarkTreeNode(moveable.Key.ToString(_wad.GameVersion));
                for (int i = 0; i < moveable.Value.Meshes.Count(); i++)
                {
                    var wadMesh = moveable.Value.Meshes.ElementAt(i);
                    var node    = new DarkUI.Controls.DarkTreeNode(wadMesh.Name);
                    node.Tag = new MeshTreeNode(moveable.Key, wadMesh);
                    list.Add(node);
                }
                moveableNode.Nodes.AddRange(list);
                moveablesNode.Nodes.Add(moveableNode);
            }
            lstMeshes.Nodes.Add(moveablesNode);

            var staticsNode = new DarkUI.Controls.DarkTreeNode("Statics");

            foreach (var @static in _wad.Statics)
            {
                var staticNode = new DarkUI.Controls.DarkTreeNode(@static.Key.ToString(_wad.GameVersion));
                var wadMesh    = @static.Value.Mesh;
                var node       = new DarkUI.Controls.DarkTreeNode(wadMesh.Name);
                node.Tag = new MeshTreeNode(@static.Key, wadMesh);
                staticNode.Nodes.Add(node);
                staticsNode.Nodes.Add(staticNode);
            }
            lstMeshes.Nodes.Add(staticsNode);
        }
Exemplo n.º 19
0
        public static IWadObjectId ChangeSlot(WadToolClass tool, IWin32Window owner)
        {
            if (tool.MainSelection?.WadArea == WadArea.Source)
            {
                return(null);
            }

            Wad2       wad       = tool.GetWad(tool.MainSelection?.WadArea);
            IWadObject wadObject = wad?.TryGet(tool.MainSelection?.Id);

            if (wad == null || wadObject == null)
            {
                tool.SendMessage("You must have an object selected", PopupType.Error);
                return(null);
            }

            // Ask for the new slot
            using (var form = new FormSelectSlot(tool.DestinationWad, wadObject.Id))
            {
                if (form.ShowDialog(owner) != DialogResult.OK)
                {
                    return(null);
                }
                if (form.NewId == wadObject.Id)
                {
                    return(null);
                }
                if (wad.Contains(form.NewId))
                {
                    tool.SendMessage("The slot " + form.NewId.ToString(wad.GameVersion) + " is already occupied.", PopupType.Error);
                    return(null);
                }
                wad.AssignNewId(wadObject.Id, form.NewId);
            }
            tool.WadChanged(tool.MainSelection.Value.WadArea);
            return(wadObject.Id);
        }
Exemplo n.º 20
0
            public void SetUp()
            {
                DataDirectory = TestContext.Parameters["dataDirectory"];
                FgdDirectory  = TestContext.Parameters["fgdDirectory"];

                string ericwFilename = Path.Combine(FgdDirectory, "quake4ericwTools.fgd");
                var    ericw         = new QuakeFgd(ericwFilename);

                string instanceFilename = Path.Combine(FgdDirectory, "func_instance.fgd");
                var    instance         = new QuakeFgd(instanceFilename);

                Fgd = new List <DefinitionDictionary>()
                {
                    ericw, instance
                }.Stack();

                string  paletteName = "palette-quake.lmp";
                Stream  stream      = Assembly.GetAssembly(typeof(MainForm)).GetResourceStream(paletteName);
                Palette palette     = new Palette().LoadQuakePalette(stream);

                string wadFilename = Path.Combine(DataDirectory, "test.wad");

                Textures = new Wad2(wadFilename, palette);
            }
Exemplo n.º 21
0
        public FormSpriteSequenceEditor(WadToolClass tool, Wad2 wad, WadSpriteSequence spriteSequence)
        {
            InitializeComponent();

            SpriteSequence = spriteSequence;
            Wad            = wad;

            _tool        = tool;
            _currentPath = Wad.FileName;

            // Load data
            Text = "Sprite sequence '" + spriteSequence.Id.ToString(Wad.GameVersion) + "'";
            dataGridView.DataSource           = new BindingList <WadSprite>(new List <WadSprite>(spriteSequence.Sprites));
            dataGridViewControls.CreateNewRow = newObject;
            dataGridViewControls.DataGridView = dataGridView;
            dataGridViewControls.Enabled      = true;

            // Refresh initially
            if (dataGridView.Rows.Count > 0)
            {
                dataGridView.Rows[0].Selected = true;
            }
            SelectSprite();
        }
Exemplo n.º 22
0
        internal static WadMoveable ConvertTr4MoveableToWadMoveable(Wad2 wad, Tr4Wad oldWad, int moveableIndex,
                                                                    Dictionary <int, WadTexture> textures)
        {
            wad_moveable oldMoveable = oldWad.Moveables[moveableIndex];
            var          newId       = new WadMoveableId(oldMoveable.ObjectID);

            // A workaround to find out duplicated item IDs produced by StrPix unpatched for v130 wads.
            // In such case, a legacy name is used to guess real item ID, if this fails - broken item is filtered out.
            if (wad.Moveables.ContainsKey(newId))
            {
                var message = "Duplicated moveable ID " + oldMoveable.ObjectID + " was identified while loading " + oldWad.BaseName + ". ";
                if (oldWad.LegacyNames.Count - oldWad.Statics.Count < moveableIndex)
                {
                    logger.Warn(message + "Can't restore real ID by name, name table is too short. Ignoring moveable.");
                    return(null);
                }

                bool isMoveable;
                var  guessedId = TrCatalog.GetItemIndex(TRVersion.Game.TR4, oldWad.LegacyNames[moveableIndex], out isMoveable);

                if (isMoveable && guessedId.HasValue)
                {
                    newId = new WadMoveableId(guessedId.Value);
                    if (wad.Moveables.ContainsKey(newId))
                    {
                        logger.Warn(message + "Can't restore real ID by name, name table is inconsistent. Ignoring moveable.");
                        return(null);
                    }
                    else
                    {
                        logger.Warn(message + "Successfully restored real ID by name.");
                    }
                }
                else
                {
                    logger.Warn(message + "Can't find provided name in catalog. Ignoring moveable.");
                    return(null);
                }
            }

            WadMoveable newMoveable = new WadMoveable(newId);
            var         frameBases  = new Dictionary <WadAnimation, ushort[]>();

            // Load meshes
            var meshes = new List <WadMesh>();

            for (int j = 0; j < oldMoveable.NumPointers; j++)
            {
                meshes.Add(ConvertTr4MeshToWadMesh(wad, oldWad, textures,
                                                   oldWad.Meshes[(int)oldWad.RealPointers[oldMoveable.PointerIndex + j]],
                                                   (int)oldMoveable.ObjectID));
            }

            // Build the skeleton
            var root = new WadBone();

            root.Name        = "bone_0_root";
            root.Parent      = null;
            root.Translation = Vector3.Zero;
            root.Mesh        = meshes[0];

            newMoveable.Bones.Add(root);

            for (int j = 0; j < oldMoveable.NumPointers - 1; j++)
            {
                WadBone bone = new WadBone();
                bone.Name        = "bone_" + (j + 1).ToString();
                bone.Parent      = null;
                bone.Translation = Vector3.Zero;
                bone.Mesh        = meshes[j + 1];
                newMoveable.Bones.Add(bone);
            }

            for (int mi = 0; mi < (oldMoveable.NumPointers - 1); mi++)
            {
                int j = mi + 1;

                var opcode = (WadLinkOpcode)oldWad.Links[(int)(oldMoveable.LinksIndex + mi * 4)];
                int linkX  = oldWad.Links[(int)(oldMoveable.LinksIndex + mi * 4) + 1];
                int linkY  = -oldWad.Links[(int)(oldMoveable.LinksIndex + mi * 4) + 2];
                int linkZ  = oldWad.Links[(int)(oldMoveable.LinksIndex + mi * 4) + 3];

                newMoveable.Bones[j].OpCode      = opcode;
                newMoveable.Bones[j].Translation = new Vector3(linkX, linkY, linkZ);
            }

            // Convert animations
            int numAnimations = 0;
            int nextMoveable  = oldWad.GetNextMoveableWithAnimations(moveableIndex);

            if (nextMoveable == -1)
            {
                numAnimations = oldWad.Animations.Count - oldMoveable.AnimationIndex;
            }
            else
            {
                numAnimations = oldWad.Moveables[nextMoveable].AnimationIndex - oldMoveable.AnimationIndex;
            }

            for (int j = 0; j < numAnimations; j++)
            {
                if (oldMoveable.AnimationIndex == -1)
                {
                    break;
                }

                wad_animation oldAnimation = oldWad.Animations[j + oldMoveable.AnimationIndex];
                WadAnimation  newAnimation = new WadAnimation();
                newAnimation.StateId       = oldAnimation.StateId;
                newAnimation.FrameRate     = oldAnimation.FrameDuration;
                newAnimation.NextAnimation = (ushort)(oldAnimation.NextAnimation - oldMoveable.AnimationIndex);
                newAnimation.NextFrame     = oldAnimation.NextFrame;
                newAnimation.Name          = TrCatalog.GetAnimationName(TRVersion.Game.TR4, oldMoveable.ObjectID, (uint)j);

                // Fix wadmerger/wad format bug with inverted frame start/end on single-frame anims
                ushort newFrameStart = oldAnimation.FrameStart < oldAnimation.FrameEnd ? oldAnimation.FrameStart : oldAnimation.FrameEnd;
                ushort newFrameEnd   = oldAnimation.FrameStart < oldAnimation.FrameEnd ? oldAnimation.FrameEnd : newFrameStart;
                newAnimation.EndFrame = (ushort)(newFrameEnd - newFrameStart);

                for (int k = 0; k < oldAnimation.NumStateChanges; k++)
                {
                    WadStateChange   sc    = new WadStateChange();
                    wad_state_change wadSc = oldWad.Changes[(int)oldAnimation.ChangesIndex + k];
                    sc.StateId = (ushort)wadSc.StateId;

                    for (int n = 0; n < wadSc.NumDispatches; n++)
                    {
                        WadAnimDispatch   ad    = new WadAnimDispatch();
                        wad_anim_dispatch wadAd = oldWad.Dispatches[(int)wadSc.DispatchesIndex + n];

                        ad.InFrame       = (ushort)(wadAd.Low - newFrameStart);
                        ad.OutFrame      = (ushort)(wadAd.High - newFrameStart);
                        ad.NextAnimation = (ushort)((wadAd.NextAnimation - oldMoveable.AnimationIndex) % numAnimations);
                        ad.NextFrame     = (ushort)wadAd.NextFrame;

                        sc.Dispatches.Add(ad);
                    }

                    newAnimation.StateChanges.Add(sc);
                }

                if (oldAnimation.NumCommands < oldWad.Commands.Count)
                {
                    int lastCommand = oldAnimation.CommandOffset;

                    for (int k = 0; k < oldAnimation.NumCommands; k++)
                    {
                        short commandType = oldWad.Commands[lastCommand];

                        WadAnimCommand command = new WadAnimCommand();
                        command.Type = (WadAnimCommandType)commandType;
                        switch (command.Type)
                        {
                        case WadAnimCommandType.SetPosition:
                            command.Parameter1 = (short)oldWad.Commands[lastCommand + 1];
                            command.Parameter2 = (short)oldWad.Commands[lastCommand + 2];
                            command.Parameter3 = (short)oldWad.Commands[lastCommand + 3];
                            lastCommand       += 4;
                            break;

                        case WadAnimCommandType.SetJumpDistance:
                            command.Parameter1 = (short)oldWad.Commands[lastCommand + 1];
                            command.Parameter2 = (short)oldWad.Commands[lastCommand + 2];
                            lastCommand       += 3;
                            break;

                        case WadAnimCommandType.EmptyHands:
                        case WadAnimCommandType.KillEntity:
                            lastCommand += 1;
                            break;

                        case WadAnimCommandType.PlaySound:
                        case WadAnimCommandType.FlipEffect:
                            command.Parameter1 = (short)(oldWad.Commands[lastCommand + 1] - newFrameStart);
                            command.Parameter2 = (short)oldWad.Commands[lastCommand + 2];

                            // For single-frame anims, clamp frame number to first frame (another fix for WM/wad format range inversion bug)
                            if (newAnimation.EndFrame == 0 && command.Parameter1 > 0)
                            {
                                command.Parameter1 = 0;
                            }

                            lastCommand += 3;
                            break;

                        default:     // Ignore invalid anim commands (see for example karnak.wad)
                            logger.Warn("Invalid anim command " + commandType);
                            goto ExitForLoop;
                        }

                        newAnimation.AnimCommands.Add(command);
                    }
ExitForLoop:
                    ;
                }

                int  frames    = (int)oldAnimation.KeyFrameOffset / 2;
                uint numFrames = 0;
                if (oldAnimation.KeyFrameSize != 0)
                {
                    if ((j + oldMoveable.AnimationIndex) == (oldWad.Animations.Count - 1))
                    {
                        numFrames = ((uint)(2 * oldWad.KeyFrames.Count) - oldAnimation.KeyFrameOffset) / (uint)(2 * oldAnimation.KeyFrameSize);
                    }
                    else
                    {
                        numFrames = (oldWad.Animations[oldMoveable.AnimationIndex + j + 1].KeyFrameOffset - oldAnimation.KeyFrameOffset) / (uint)(2 * oldAnimation.KeyFrameSize);
                    }
                }

                for (int f = 0; f < numFrames; f++)
                {
                    WadKeyFrame frame        = new WadKeyFrame();
                    int         startOfFrame = frames;

                    frame.BoundingBox = new BoundingBox(new Vector3(oldWad.KeyFrames[frames],
                                                                    -oldWad.KeyFrames[frames + 2],
                                                                    oldWad.KeyFrames[frames + 4]),
                                                        new Vector3(oldWad.KeyFrames[frames + 1],
                                                                    -oldWad.KeyFrames[frames + 3],
                                                                    oldWad.KeyFrames[frames + 5]));
                    frames += 6;

                    frame.Offset = new Vector3(oldWad.KeyFrames[frames],
                                               (short)(-oldWad.KeyFrames[frames + 1]),
                                               oldWad.KeyFrames[frames + 2]);
                    frames += 3;

                    for (int n = 0; n < oldMoveable.NumPointers; n++)
                    {
                        frame.Angles.Add(WadKeyFrameRotation.FromTrAngle(ref frames, oldWad.KeyFrames, false, true));
                    }
                    if ((frames - startOfFrame) < oldAnimation.KeyFrameSize)
                    {
                        frames += ((int)oldAnimation.KeyFrameSize - (frames - startOfFrame));
                    }

                    newAnimation.KeyFrames.Add(frame);
                }

                // New velocities
                float acceleration = oldAnimation.Accel / 65536.0f;
                newAnimation.StartVelocity = oldAnimation.Speed / 65536.0f;

                float lateralAcceleration = oldAnimation.AccelLateral / 65536.0f;
                newAnimation.StartLateralVelocity = oldAnimation.SpeedLateral / 65536.0f;

                if (newAnimation.KeyFrames.Count != 0 && newAnimation.FrameRate != 0)
                {
                    newAnimation.EndVelocity = newAnimation.StartVelocity + acceleration *
                                               (newAnimation.KeyFrames.Count - 1) * newAnimation.FrameRate;
                    newAnimation.EndLateralVelocity = newAnimation.StartLateralVelocity + lateralAcceleration *
                                                      (newAnimation.KeyFrames.Count - 1) * newAnimation.FrameRate;
                }
                else
                {
                    // Basic foolproofness for potentially broken animations
                    newAnimation.EndVelocity        = newAnimation.StartVelocity;
                    newAnimation.EndLateralVelocity = newAnimation.StartLateralVelocity;
                }

                // Deduce real maximum frame number, based on interpolation and keyframes.
                // We need to refer this value in NextFrame-related fixes (below) because of epic WadMerger bug,
                // which incorrectly calculates NextFrame and "steals" last frame from every custom animation.
                ushort maxFrameCount = (ushort)((newAnimation.FrameRate == 1 || numFrames <= 2) ? numFrames : ((numFrames - 1) * newAnimation.FrameRate) + 1);

                // Also correct animation out-point
                if (newAnimation.EndFrame >= maxFrameCount)
                {
                    newAnimation.EndFrame = (ushort)(maxFrameCount - 1);
                }

                frameBases.Add(newAnimation, new ushort[] { newFrameStart, (ushort)(maxFrameCount - 1) });
                newMoveable.Animations.Add(newAnimation);
            }

            for (int i = 0; i < newMoveable.Animations.Count; i++)
            {
                var animation = newMoveable.Animations[i];

                if (animation.KeyFrames.Count == 0)
                {
                    animation.EndFrame = 0;
                }

                // HACK: this fixes some invalid NextAnimations values
                animation.NextAnimation %= (ushort)newMoveable.Animations.Count;

                newMoveable.Animations[i] = animation;
            }

            for (int i = 0; i < newMoveable.Animations.Count; i++)
            {
                var animation = newMoveable.Animations[i];

                // HACK: this fixes some invalid NextFrame values
                if (frameBases[newMoveable.Animations[animation.NextAnimation]][0] != 0)
                {
                    animation.NextFrame -= frameBases[newMoveable.Animations[animation.NextAnimation]][0];
                    if (animation.NextFrame > frameBases[newMoveable.Animations[animation.NextAnimation]][1])
                    {
                        animation.NextFrame = frameBases[newMoveable.Animations[animation.NextAnimation]][1];
                    }
                }

                foreach (var stateChange in animation.StateChanges)
                {
                    for (int j = 0; j < stateChange.Dispatches.Count; ++j)
                    {
                        WadAnimDispatch animDispatch = stateChange.Dispatches[j];

                        // HACK: Probably WadMerger's bug
                        if (animDispatch.NextAnimation > 32767)
                        {
                            animDispatch.NextAnimation = 0;
                            animDispatch.NextFrame     = 0;
                            continue;
                        }

                        if (frameBases[newMoveable.Animations[animDispatch.NextAnimation]][0] != 0)
                        {
                            // HACK: In some cases dispatches have invalid NextFrame.
                            // From tests it seems that's ok to make NextFrame equal to max frame number.
                            animDispatch.NextFrame -= frameBases[newMoveable.Animations[animDispatch.NextAnimation]][0];
                            if (animDispatch.NextFrame > frameBases[newMoveable.Animations[animDispatch.NextAnimation]][1])
                            {
                                animDispatch.NextFrame = frameBases[newMoveable.Animations[animDispatch.NextAnimation]][1];
                            }
                        }
                        stateChange.Dispatches[j] = animDispatch;
                    }
                }
            }

            wad.Moveables.Add(newMoveable.Id, newMoveable);
            return(newMoveable);
        }
Exemplo n.º 23
0
        internal static WadStatic ConvertTr4StaticMeshToWadStatic(Wad2 wad, Tr4Wad oldWad, int staticIndex, /*List<WadMesh> meshes*/
                                                                  Dictionary <int, WadTexture> textures)
        {
            var oldStaticMesh = oldWad.Statics[staticIndex];
            var newId         = new WadStaticId(oldStaticMesh.ObjectId);

            // A workaround to find out duplicated item IDs produced by StrPix unpatched for v130 wads.
            // In such case, a legacy name is used to guess real item ID, if this fails - broken item is filtered out.
            if (wad.Statics.ContainsKey(newId))
            {
                var message = "Duplicated static ID " + oldStaticMesh.ObjectId + " was identified while loading " + oldWad.BaseName + ". ";
                if (oldWad.LegacyNames.Count - oldWad.Moveables.Count < staticIndex)
                {
                    logger.Warn(message + "Can't restore real ID by name, name table is too short. Ignoring static.");
                    return(null);
                }

                bool isMoveable;
                var  guessedId = TrCatalog.GetItemIndex(TRVersion.Game.TR4, oldWad.LegacyNames[oldWad.Moveables.Count + staticIndex], out isMoveable);

                if (!isMoveable && guessedId.HasValue)
                {
                    newId = new WadStaticId(guessedId.Value);
                    if (wad.Statics.ContainsKey(newId))
                    {
                        logger.Warn(message + "Can't restore real ID by name, name table is inconsistent. Ignoring static.");
                        return(null);
                    }
                    else
                    {
                        logger.Warn(message + "Successfully restored real ID by name.");
                    }
                }
                else
                {
                    logger.Warn(message + "Can't find provided name in catalog. Ignoring static.");
                    return(null);
                }
            }

            var staticMesh = new WadStatic(newId);

            //staticMesh.Name = TrCatalog.GetStaticName(WadTombRaiderVersion.TR4, oldStaticMesh.ObjectId);

            // First setup collisional and visibility bounding boxes
            staticMesh.CollisionBox = new BoundingBox(new Vector3(oldStaticMesh.CollisionX1,
                                                                  -oldStaticMesh.CollisionY1,
                                                                  oldStaticMesh.CollisionZ1),
                                                      new Vector3(oldStaticMesh.CollisionX2,
                                                                  -oldStaticMesh.CollisionY2,
                                                                  oldStaticMesh.CollisionZ2));

            staticMesh.VisibilityBox = new BoundingBox(new Vector3(oldStaticMesh.VisibilityX1,
                                                                   -oldStaticMesh.VisibilityY1,
                                                                   oldStaticMesh.VisibilityZ1),
                                                       new Vector3(oldStaticMesh.VisibilityX2,
                                                                   -oldStaticMesh.VisibilityY2,
                                                                   oldStaticMesh.VisibilityZ2));

            staticMesh.Mesh = ConvertTr4MeshToWadMesh(wad, oldWad, textures,
                                                      oldWad.Meshes[(int)oldWad.RealPointers[oldStaticMesh.PointersIndex]],
                                                      (int)oldStaticMesh.ObjectId);

            wad.Statics.Add(staticMesh.Id, staticMesh);

            return(staticMesh);
        }
Exemplo n.º 24
0
        private void Tool_EditorEventRaised(IEditorEvent obj)
        {
            if (obj is InitEvent)
            {
                // At startup initialise a new Wad2
                if (_tool.Configuration.Tool_MakeEmptyWadAtStartup)
                {
                    _tool.DestinationWad = new Wad2 {
                        GameVersion = TRVersion.Game.TR4
                    };
                    _tool.RaiseEvent(new WadToolClass.DestinationWadChangedEvent());
                }
            }

            if (obj is WadToolClass.MessageEvent)
            {
                var msg = (WadToolClass.MessageEvent)obj;
                PopUpInfo.Show(popup, this, panel3D, msg.Message, msg.Type);
            }

            if (obj is WadToolClass.SelectedObjectEditedEvent || obj is InitEvent)
            {
            }

            if (obj is WadToolClass.DestinationWadChangedEvent || obj is InitEvent)
            {
                treeDestWad.Wad = _tool.DestinationWad;
                treeDestWad.UpdateContent();

                panel3D.UpdateAnimationScrollbar();
                panel3D.Invalidate();

                if (_tool.DestinationWad != null)
                {
                    labelStatistics.Text = "Moveables: " + _tool.DestinationWad.Moveables.Count + " | " +
                                           "Statics: " + _tool.DestinationWad.Statics.Count + " | " +
                                           "Sprites sequences: " + _tool.DestinationWad.SpriteSequences.Count + " | " +
                                           "Textures: " + _tool.DestinationWad.MeshTexturesUnique.Count;
                }
                else
                {
                    labelStatistics.Text = "";
                }
            }

            if (obj is WadToolClass.SourceWadChangedEvent || obj is InitEvent)
            {
                panelSource.SectionHeader = "Source";
                if (_tool?.SourceWad != null)
                {
                    panelSource.SectionHeader += (String.IsNullOrEmpty(_tool.SourceWad.FileName) ? " (Imported)" : " (" + Path.GetFileName(_tool.SourceWad.FileName) + ")");
                }

                treeSourceWad.Wad = _tool.SourceWad;
                treeSourceWad.UpdateContent();

                panel3D.UpdateAnimationScrollbar();
                panel3D.Invalidate();
            }

            if (obj is WadToolClass.MainSelectionChangedEvent ||
                obj is WadToolClass.DestinationWadChangedEvent ||
                obj is WadToolClass.SourceWadChangedEvent || obj is InitEvent)
            {
                var mainSelection = _tool.MainSelection;
                if (mainSelection == null)
                {
                    panel3D.CurrentObject = null;

                    butEditAnimations.Visible     = false;
                    butEditSkeleton.Visible       = false;
                    butEditStaticModel.Visible    = false;
                    butEditSpriteSequence.Visible = false;
                }
                else
                {
                    Wad2 wad = _tool.GetWad(mainSelection.Value.WadArea);

                    // Display the object (or set it to Lara's skin instead if it's Lara)
                    if (mainSelection.Value.Id is WadMoveableId)
                    {
                        panel3D.CurrentObject = wad.TryGet(new WadMoveableId(TrCatalog.GetMoveableSkin(wad.GameVersion, ((WadMoveableId)mainSelection.Value.Id).TypeId)));
                    }
                    else
                    {
                        panel3D.CurrentObject = wad.TryGet(mainSelection.Value.Id);
                    }

                    panel3D.AnimationIndex = 0;
                    panel3D.KeyFrameIndex  = 0;

                    // Update the toolbar below the rendering area
                    butEditAnimations.Visible     = (mainSelection.Value.Id is WadMoveableId);
                    butEditSkeleton.Visible       = (mainSelection.Value.Id is WadMoveableId);
                    butEditStaticModel.Visible    = (mainSelection.Value.Id is WadStaticId);
                    butEditSpriteSequence.Visible = (mainSelection.Value.Id is WadSpriteSequenceId);

                    panel3D.ResetCamera();
                    panel3D.Invalidate();
                }

                panel3D.UpdateAnimationScrollbar();
                panel3D.Invalidate();
            }

            if (obj is WadToolClass.ReferenceLevelChangedEvent)
            {
                if (_tool.ReferenceLevel != null)
                {
                    butCloseRefLevel.Enabled = true;
                    lblRefLevel.Enabled      = true;
                    closeReferenceLevelToolStripMenuItem.Enabled = true;
                    lblRefLevel.Text = Path.GetFileNameWithoutExtension(_tool.ReferenceLevel.Settings.LevelFilePath);
                }
                else
                {
                    butCloseRefLevel.Enabled = false;
                    lblRefLevel.Enabled      = false;
                    closeReferenceLevelToolStripMenuItem.Enabled = false;
                    lblRefLevel.Text = "(project not loaded)";
                }
            }

            if (obj is WadToolClass.UnsavedChangesEvent)
            {
                UpdateSaveUI(((WadToolClass.UnsavedChangesEvent)obj).UnsavedChanges);
            }
        }
Exemplo n.º 25
0
        private static Dictionary <int, WadTexture> ConvertTr4TexturesToWadTexture(Tr4Wad oldWad, Wad2 wad)
        {
            var textures = new ConcurrentDictionary <int, WadTexture>();

            Parallel.For(0, oldWad.Textures.Count, i =>
            {
                var oldTexture = oldWad.Textures[i];
                var startX     = (short)(oldTexture.X);
                var startY     = (short)(oldTexture.Page * 256 + oldTexture.Y);

                // Create the texture ImageC
                var image = ImageC.CreateNew(oldTexture.Width + 1, oldTexture.Height + 1);

                for (var y = 0; y < image.Height; y++)
                {
                    for (var x = 0; x < image.Width; x++)
                    {
                        var baseIndex = (startY + y) * 768 + (startX + x) * 3;
                        var r         = oldWad.TexturePages[baseIndex];
                        var g         = oldWad.TexturePages[baseIndex + 1];
                        var b         = oldWad.TexturePages[baseIndex + 2];
                        var a         = (byte)255;

                        //var color = new ColorC(r, g, b, a);
                        image.SetPixel(x, y, r, g, b, a);
                    }
                }

                // Replace magenta color with alpha transparent black
                image.ReplaceColor(new ColorC(255, 0, 255, 255), new ColorC(0, 0, 0, 0));

                textures.TryAdd(i, new WadTexture(image));
            });

            return(new Dictionary <int, WadTexture>(textures));
        }
Exemplo n.º 26
0
        public static List <IWadObjectId> CopyObject(WadToolClass tool, IWin32Window owner, List <IWadObjectId> objectIdsToMove, bool alwaysChooseId)
        {
            Wad2 sourceWad      = tool.SourceWad;
            Wad2 destinationWad = tool.DestinationWad;

            if (destinationWad == null || sourceWad == null || objectIdsToMove.Count == 0)
            {
                tool.SendMessage("You must have two wads loaded and at least one source object selected.", PopupType.Error);
                return(null);
            }

            var listInProgress = new List <uint>();

            // Figure out the new ids if there are any id collisions
            IWadObjectId[] newIds = objectIdsToMove.ToArray();

            // If destination is TR5Main, try to remap object IDs
            if (destinationWad.GameVersion == TRVersion.Game.TR5Main)
            {
                for (int i = 0; i < objectIdsToMove.Count; ++i)
                {
                    var objectId = objectIdsToMove[i];
                    if (objectId is WadMoveableId)
                    {
                        var moveableId = (WadMoveableId)objectId;

                        // Try to get a compatible slot
                        var newSlot = TrCatalog.GetMoveableTR5MainSlot(sourceWad.GameVersion, moveableId.TypeId);
                        if (newSlot == "")
                        {
                            continue;
                        }

                        // Get the new ID
                        bool isMoveable;
                        var  newId = TrCatalog.GetItemIndex(destinationWad.GameVersion, newSlot, out isMoveable);
                        if (!newId.HasValue)
                        {
                            continue;
                        }

                        // Save the new ID
                        newIds[i] = new WadMoveableId(newId.Value);
                    }
                }
            }

            for (int i = 0; i < objectIdsToMove.Count; ++i)
            {
                if (!sourceWad.Contains(objectIdsToMove[i]))
                {
                    continue;
                }
                if (!alwaysChooseId)
                {
                    if (!destinationWad.Contains(newIds[i]))
                    {
                        if (!newIds.Take(i).Contains(newIds[i])) // There also must not be collisions with the other custom assigned ids.
                        {
                            continue;
                        }
                    }
                }

                bool askConfirm = !alwaysChooseId;

                // Ask for the new slot
                do
                {
                    DialogResult dialogResult;
                    if (askConfirm)
                    {
                        dialogResult = DarkMessageBox.Show(owner, "The id " + newIds[i].ToString(destinationWad.GameVersion) + " is already occupied in the destination wad.\n" +
                                                           "Do you want to replace it (Yes) or to select another Id (No)?",
                                                           "Occupied slot", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
                    }
                    else
                    {
                        dialogResult = DialogResult.No;
                    }

                    // From this time, always ask for confirm
                    askConfirm = true;

                    if (dialogResult == DialogResult.Cancel)
                    {
                        return(null);
                    }
                    else if (dialogResult == DialogResult.No)
                    {
                        using (var form = new FormSelectSlot(destinationWad, newIds[i], listInProgress))
                        {
                            if (form.ShowDialog(owner) != DialogResult.OK)
                            {
                                return(null);
                            }
                            if (destinationWad.Contains(form.NewId) || newIds.Take(i).Contains(form.NewId))
                            {
                                destinationWad.Remove(form.NewId);
                                tool.WadChanged(WadArea.Destination);
                            }
                            newIds[i] = form.NewId;

                            if (form.NewId is WadStaticId)
                            {
                                listInProgress.Add(((WadStaticId)form.NewId).TypeId);
                            }
                            if (form.NewId is WadMoveableId)
                            {
                                listInProgress.Add(((WadMoveableId)form.NewId).TypeId);
                            }
                            if (form.NewId is WadSpriteSequenceId)
                            {
                                listInProgress.Add(((WadSpriteSequenceId)form.NewId).TypeId);
                            }

                            break;
                        }
                    }
                    else
                    {
                        destinationWad.Remove(objectIdsToMove[i]);
                        tool.WadChanged(WadArea.Destination);
                        break;
                    }
                } while (destinationWad.Contains(newIds[i]) || newIds.Take(i).Contains(newIds[i])); // There also must not be collisions with the other custom assigned ids.
            }

            // HACK: Until this is fixed... https://github.com/MontyTRC89/Tomb-Editor/issues/413
            // We just block copying of same object to another slot and warn user it's in another slot.
            var failedIdList = new List <IWadObjectId>();

            // Move objects
            for (int i = 0; i < objectIdsToMove.Count; ++i)
            {
                IWadObject obj = sourceWad.TryGet(objectIdsToMove[i]);
                if (obj == null)
                {
                    continue;
                }

                if (destinationWad.Contains(obj)) // Aforementioned HACK continues here - just add object which failed to copy to failed list
                {
                    failedIdList.Add(newIds[i]);
                }
                else
                {
                    destinationWad.Add(newIds[i], obj);

                    if (destinationWad.GameVersion == TRVersion.Game.TR5Main && obj is WadMoveable)
                    {
                        var moveable = obj as WadMoveable;
                        foreach (var animation in moveable.Animations)
                        {
                            foreach (var command in animation.AnimCommands)
                            {
                                if (command.Type == WadAnimCommandType.PlaySound)
                                {
                                    int id = command.Parameter2 & 0x3FFF;
                                    id += TrCatalog.GetTR5MainSoundMapStart(sourceWad.GameVersion);
                                    command.Parameter2 = (short)((command.Parameter2 & 0xC000) | (id & 0x3FFF));
                                }
                            }
                        }
                    }
                }
            }

            // Aforementioned HACK continues here - count amount of actually copied objects
            int actualAmountOfCopiedObjects = objectIdsToMove.Count - failedIdList.Count;

            if (actualAmountOfCopiedObjects > 0)
            {
                // Update the situation
                tool.WadChanged(WadArea.Destination);

                string infoString = (objectIdsToMove.Count == 1 ? "Object" : "Objects") + " successfully copied.";

                // Aforementioned HACK continues here - additionally inform user that some objects are in different slots.
                if (failedIdList.Count > 0)
                {
                    infoString += "\n" + failedIdList.Count + " object" +
                                  (failedIdList.Count > 1 ? "s" : "") + " weren't copied because " +
                                  (failedIdList.Count > 1 ? "they are" : "it's") + " already in different slot" +
                                  (failedIdList.Count > 1 ? "s." : ".");
                }

                // Indicate that object is copied
                tool.SendMessage(infoString, PopupType.Info);
            }

            return(newIds.Where(item => !failedIdList.Any(failed => failed == item)).ToList());
        }
Exemplo n.º 27
0
        public static Wad2 ConvertWad2ToTR5Main(WadToolClass tool, IWin32Window owner, Wad2 src)
        {
            Wad2 dest = new Wad2();

            dest.GameVersion = TRVersion.Game.TR5Main;
            dest.SoundSystem = SoundSystem.Xml;

            foreach (var moveable in src.Moveables)
            {
                var compatibleSlot = TrCatalog.GetMoveableTR5MainSlot(src.GameVersion, moveable.Key.TypeId);
                if (compatibleSlot == "")
                {
                    continue;
                }

                bool isMoveable = false;
                var  destId     = TrCatalog.GetItemIndex(TRVersion.Game.TR5Main, compatibleSlot, out isMoveable);
                if (!destId.HasValue)
                {
                    continue;
                }

                var newId = new WadMoveableId(destId.Value);

                foreach (var animation in moveable.Value.Animations)
                {
                    foreach (var command in animation.AnimCommands)
                    {
                        if (command.Type == WadAnimCommandType.PlaySound)
                        {
                            int id = command.Parameter2 & 0x3FFF;
                            id += TrCatalog.GetTR5MainSoundMapStart(src.GameVersion);
                            command.Parameter2 = (short)((command.Parameter2 & 0xC000) | (id & 0x3FFF));
                        }
                    }
                }

                dest.Add(newId, moveable.Value);
            }

            foreach (var sequence in src.SpriteSequences)
            {
                var compatibleSlot = TrCatalog.GetSpriteSequenceTR5MainSlot(src.GameVersion, sequence.Key.TypeId);
                if (compatibleSlot == "")
                {
                    continue;
                }

                bool isMoveable = false;
                var  destId     = TrCatalog.GetItemIndex(TRVersion.Game.TR5Main, compatibleSlot, out isMoveable);
                if (!destId.HasValue)
                {
                    continue;
                }

                var newId = new WadSpriteSequenceId(destId.Value);

                dest.Add(newId, sequence.Value);
            }

            foreach (var staticObject in src.Statics)
            {
                dest.Add(staticObject.Key, staticObject.Value);
            }

            return(dest);
        }
Exemplo n.º 28
0
        public static void LoadWad(WadToolClass tool, IWin32Window owner, bool destination, string fileName)
        {
            bool isWad2 = Path.GetExtension(fileName).ToLower() == ".wad2";

            // Load the WAD/Wad2
            Wad2 newWad = null;

            try
            {
                newWad = Wad2.ImportFromFile(fileName, true, new GraphicalDialogHandler(owner), tool.Configuration.Tool_AllowTRNGDecryption);
                if (isWad2 && newWad.SoundSystem == SoundSystem.Dynamic)
                {
                    if (DarkMessageBox.Show(owner, "This Wad2 is using the old dynamic sound system and needs to be converted " +
                                            "to the new Xml sound system. A backup copy will be created under the same directory. " +
                                            "Do you want to continue?",
                                            "Convert Wad2", MessageBoxButtons.YesNo,
                                            MessageBoxIcon.Question) != DialogResult.Yes)
                    {
                        return;
                    }

                    File.Copy(fileName, fileName + ".bak", true);
                    if (!FileFormatConversions.ConvertWad2ToNewSoundFormat(fileName, fileName))
                    {
                        tool.SendMessage("Converting the file failed!", PopupType.Error);
                        return;
                    }

                    if (newWad.HasUnknownData)
                    {
                        tool.SendMessage("Loaded wad2 is of newer version.\nSome data was lost. Don't save this wad2 and use newest version of Wad Tool.", PopupType.Warning);
                    }

                    newWad = Wad2.ImportFromFile(fileName, true, new GraphicalDialogHandler(owner), tool.Configuration.Tool_AllowTRNGDecryption);
                }
            }
            catch (OperationCanceledException)
            {
                return;
            }
            catch (Exception exc)
            {
                logger.Info(exc, "Unable to load " + (destination ? "destination" : "source") + " file from '" + fileName + "'.");
                tool.SendMessage("Loading the file failed! \n" + exc.Message, PopupType.Error);
                return;
            }

            // Set wad
            if (destination)
            {
                tool.DestinationWad = newWad;
                tool.ToggleUnsavedChanges(false);
            }
            else
            {
                if (!isWad2)
                {
                    newWad.FileName = fileName;           // Keep original path only for source old wad, as it's not saveable
                }
                tool.SourceWad = newWad;
            }
        }
Exemplo n.º 29
0
        public static void SaveWad(WadToolClass tool, IWin32Window owner, Wad2 wadToSave, bool ask)
        {
            if (wadToSave == null)
            {
                tool.SendMessage("You have no wad opened. Nothing to save.", PopupType.Warning);
                return;
            }

            // Figure out the output path
            string outPath = wadToSave.FileName;

            if (!string.IsNullOrWhiteSpace(wadToSave.FileName))
            {
                try
                {
                    outPath = Path.ChangeExtension(outPath, "wad2");
                }
                catch
                {
                    // ignored
                }
            }


            // Ask about it
            if (ask || string.IsNullOrWhiteSpace(outPath))
            {
                using (var dialog = new SaveFileDialog())
                {
                    if (!string.IsNullOrWhiteSpace(outPath))
                    {
                        dialog.InitialDirectory = Path.GetDirectoryName(outPath);
                        dialog.FileName         = Path.GetFileName(outPath);
                    }
                    dialog.Filter       = Wad2Writer.FileFormats.GetFilter();
                    dialog.Title        = "Save Wad2";
                    dialog.AddExtension = true;
                    if (dialog.ShowDialog(owner) != DialogResult.OK)
                    {
                        return;
                    }
                    outPath = dialog.FileName;
                }
            }

            // Save the wad2
            try
            {
                // XML_SOUND_SYSTEM
                Wad2Writer.SaveToFile(wadToSave, outPath);

                // Immediately reload new wad, if it wasn't saved before (new or imported)
                if (wadToSave.FileName == null)
                {
                    LoadWad(tool, owner, true, outPath);
                }

                // Update last actual filename and call global event to update UI etc
                wadToSave.FileName = outPath;
                tool.ToggleUnsavedChanges(false);
            }
            catch (Exception exc)
            {
                logger.Warn(exc, "Unable to save to '" + outPath + "'");
                tool.SendMessage("Unable to save to '" + outPath + "'.   " + exc, PopupType.Error);
            }
        }
Exemplo n.º 30
0
        private static TextureArea CalculateTr4UVCoordinates(Wad2 wad, Tr4Wad oldWad, wad_polygon poly, Dictionary <int, WadTexture> textures)
        {
            TextureArea textureArea = new TextureArea();

            textureArea.BlendMode   = (poly.Attributes & 0x01) != 0 ? BlendMode.Additive : BlendMode.Normal;
            textureArea.DoubleSided = false;

            int textureId = GetTr4TextureIdFromPolygon(poly);

            textureArea.Texture = textures[textureId];

            // Add the UV coordinates
            int shape   = (poly.Texture & 0x7000) >> 12;
            int flipped = (poly.Texture & 0x8000) >> 15;

            wad_object_texture texture = oldWad.Textures[textureId];

            Vector2 nw = new Vector2(0, 0);
            Vector2 ne = new Vector2(texture.Width + 1.0f, 0);
            Vector2 se = new Vector2(texture.Width + 1.0f, texture.Height + 1.0f);
            Vector2 sw = new Vector2(0, texture.Height + 1.0f);

            if (poly.Shape == 9)
            {
                if (flipped == 1)
                {
                    textureArea.TexCoord0 = ne;
                    textureArea.TexCoord1 = nw;
                    textureArea.TexCoord2 = sw;
                    textureArea.TexCoord3 = se;
                }
                else
                {
                    textureArea.TexCoord0 = nw;
                    textureArea.TexCoord1 = ne;
                    textureArea.TexCoord2 = se;
                    textureArea.TexCoord3 = sw;
                }
            }
            else
            {
                switch (shape)
                {
                case 0:
                    if (flipped == 1)
                    {
                        textureArea.TexCoord0 = ne;
                        textureArea.TexCoord1 = nw;
                        textureArea.TexCoord2 = se;
                        textureArea.TexCoord3 = textureArea.TexCoord2;
                    }
                    else
                    {
                        textureArea.TexCoord0 = nw;
                        textureArea.TexCoord1 = ne;
                        textureArea.TexCoord2 = sw;
                        textureArea.TexCoord3 = textureArea.TexCoord2;
                    }
                    break;

                case 2:
                    if (flipped == 1)
                    {
                        textureArea.TexCoord0 = nw;
                        textureArea.TexCoord1 = sw;
                        textureArea.TexCoord2 = ne;
                        textureArea.TexCoord3 = textureArea.TexCoord2;
                    }
                    else
                    {
                        textureArea.TexCoord0 = ne;
                        textureArea.TexCoord1 = se;
                        textureArea.TexCoord2 = nw;
                        textureArea.TexCoord3 = textureArea.TexCoord2;
                    }
                    break;

                case 4:
                    if (flipped == 1)
                    {
                        textureArea.TexCoord0 = sw;
                        textureArea.TexCoord1 = se;
                        textureArea.TexCoord2 = nw;
                        textureArea.TexCoord3 = textureArea.TexCoord2;
                    }
                    else
                    {
                        textureArea.TexCoord0 = se;
                        textureArea.TexCoord1 = sw;
                        textureArea.TexCoord2 = ne;
                        textureArea.TexCoord3 = textureArea.TexCoord2;
                    }
                    break;

                case 6:
                    if (flipped == 1)
                    {
                        textureArea.TexCoord0 = se;
                        textureArea.TexCoord1 = ne;
                        textureArea.TexCoord2 = sw;
                        textureArea.TexCoord3 = textureArea.TexCoord2;
                    }
                    else
                    {
                        textureArea.TexCoord0 = sw;
                        textureArea.TexCoord1 = nw;
                        textureArea.TexCoord2 = se;
                        textureArea.TexCoord3 = textureArea.TexCoord2;
                    }
                    break;

                default:
                    throw new NotImplementedException("Unknown texture shape " + shape + " found in the wad.");
                }
            }

            return(textureArea);
        }