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; }
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; } }
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"); }
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); }
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); }
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); }
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); } }
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(); }
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); } }
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; } }
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(); }
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); } }
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); }
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)); } }
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); }
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); }
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); }
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); }
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); }
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); }
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(); }
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); }
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); }
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); } }
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)); }
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()); }
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); }
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; } }
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); } }
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); }