public void write(string mapName, MapSet map, XmlWriter writer) { writer.WriteStartElement("map"); writer.WriteAttributeString("name", mapName); writeSectors(map, writer); writeLines(map, writer); writeSides(map, writer); writeThings(map, writer); writer.WriteEndElement(); }
void writeLines(MapSet map, XmlWriter writer) { writer.WriteStartElement("lines"); foreach (Linedef l in map.Linedefs) { writer.WriteStartElement("line"); writer.WriteAttributeString("idx", l.Index.ToString()); writer.WriteAttributeString("action", l.Action.ToString()); writer.WriteAttributeString("tag", l.Tag.ToString()); writer.WriteAttributeString("activate", l.Activate.ToString()); if (l.Args.Length > 0) { StringBuilder sb = new StringBuilder(); bool any = false; foreach (int i in l.Args) { if (any) sb.Append(","); sb.Append(i.ToString()); any = true; } writer.WriteAttributeString("action-args", sb.ToString()); } MapWriter.writeVertex(writer, l.Line.v1); MapWriter.writeVertex(writer, l.Line.v2); writer.WriteStartElement("flags"); foreach (String str in l.GetFlags().Keys) { bool value = l.GetFlags()[str]; if (value == false) continue; writer.WriteStartElement("flag"); writer.WriteAttributeString("name",str); writer.WriteAttributeString("value", value.ToString()); writer.WriteEndElement(); } writer.WriteEndElement(); writeFields(l.Fields, writer); writer.WriteEndElement(); } writer.WriteEndElement(); }
// Disposer public override void Dispose() { // Not already disposed? if (!isdisposed) { // Already set isdisposed so that changes can be prohibited isdisposed = true; if (map == General.Map.Map) { General.Map.UndoRedo.RecRemThing(this); } // Remove from main list map.RemoveThing(listindex); // Clean up map = null; sector = null; // Dispose base base.Dispose(); } }
public void MapSelect(int SelectItemPosition) { if (SelectItemPosition >= 0 && ExamContext != null) { //通过对应的KeyValue 里面进行取值 var SelectMapItem = lstMapLine[SelectItemPosition]; //var SelectMapItem = dataService.GetAllMapLines().Where(x=>x.Id== SelectItemPosition).FirstOrDefault(); if (SelectItemPosition == 0) { dataService.SaveDefaultMapId(0); return; } if (SelectMapItem.Points != null) { var mapSet = new MapSet(SelectMapItem.Points.ToMapPoints()); //把地图选择信息保存起来后续需要可以直接取 MapName = SelectMapItem.Name; ExamContext.Map = mapSet; dataService.SaveDefaultMapId(SelectMapItem.Id); Logger.InfoFormat("##保存地图取出序号:{0},{1}", SelectMapItem.Id, MapName); } } }
private static void CreateSprites(MapSet map, List <BuildSprite> buildsprites, List <BuildSector> sectors) { // Create sprites map.SetCapacity(0, 0, 0, 0, map.Things.Count + buildsprites.Count); for (int i = 0; i < buildsprites.Count; i++) { var bs = buildsprites[i]; // Link sector if (bs.SectorIndex < sectors.Count) { bs.Sector = sectors[bs.SectorIndex].Sector; } else { General.ErrorLogger.Add(ErrorType.Warning, "Sprite " + i + " references non-existing sector " + bs.SectorIndex); } // Create new item Thing t = map.CreateThing(); t.Update(bs); } }
// After deserialization internal void PostDeserialize(MapSet map) { triangles.PostDeserialize(map); updateneeded = true; triangulationneeded = true; }
// This moves the selected geometry relatively // Returns true when geometry has actually moved private bool MoveGeometryRelative(Vector2D offset, bool snapgrid, bool snapnearest) { Vector2D oldpos = dragitem.Position; Vector2D anchorpos = dragitemposition + offset; Vector2D tl, br; // don't move if the offset contains invalid data if (!offset.IsFinite()) { return(false); } // Find the outmost vertices tl = br = oldpositions[0]; for (int i = 0; i < oldpositions.Count; i++) { if (oldpositions[i].x < tl.x) { tl.x = (int)oldpositions[i].x; } if (oldpositions[i].x > br.x) { br.x = (int)oldpositions[i].x; } if (oldpositions[i].y > tl.y) { tl.y = (int)oldpositions[i].y; } if (oldpositions[i].y < br.y) { br.y = (int)oldpositions[i].y; } } // Snap to nearest? if (snapnearest) { // Find nearest unselected vertex within range Vertex nv = MapSet.NearestVertexSquareRange(unselectedverts, anchorpos, BuilderPlug.Me.StitchRange / renderer.Scale); if (nv != null) { // Move the dragged item dragitem.Move(nv.Position); // Adjust the offset offset = nv.Position - dragitemposition; // Do not snap to grid! snapgrid = false; } else { // Find the nearest unselected line within range Linedef nl = MapSet.NearestLinedefRange(snaptolines, anchorpos, BuilderPlug.Me.StitchRange / renderer.Scale); if (nl != null) { // Snap to grid? if (snaptogrid) { // Get grid intersection coordinates List <Vector2D> coords = nl.GetGridIntersections(); // Find nearest grid intersection float found_distance = float.MaxValue; Vector2D found_coord = new Vector2D(); foreach (Vector2D v in coords) { Vector2D delta = anchorpos - v; if (delta.GetLengthSq() < found_distance) { found_distance = delta.GetLengthSq(); found_coord = v; } } // Move the dragged item dragitem.Move(found_coord); // Align to line here offset = found_coord - dragitemposition; // Do not snap to grid anymore snapgrid = false; } else { // Move the dragged item dragitem.Move(nl.NearestOnLine(anchorpos)); // Align to line here offset = nl.NearestOnLine(anchorpos) - dragitemposition; } } } } // Snap to grid? if (snapgrid) { // Move the dragged item dragitem.Move(anchorpos); // Snap item to grid dragitem.SnapToGrid(); // Adjust the offset offset += dragitem.Position - anchorpos; } // Make sure the offset is inside the map boundaries if (offset.x + tl.x < General.Map.FormatInterface.LeftBoundary) { offset.x = General.Map.FormatInterface.LeftBoundary - tl.x; } if (offset.x + br.x > General.Map.FormatInterface.RightBoundary) { offset.x = General.Map.FormatInterface.RightBoundary - br.x; } if (offset.y + tl.y > General.Map.FormatInterface.TopBoundary) { offset.y = General.Map.FormatInterface.TopBoundary - tl.y; } if (offset.y + br.y < General.Map.FormatInterface.BottomBoundary) { offset.y = General.Map.FormatInterface.BottomBoundary - br.y; } // Drag item moved? if (!snapgrid || (dragitem.Position != oldpos)) { int i = 0; // Move selected geometry foreach (Vertex v in selectedverts) { // Move vertex from old position relative to the // mouse position change since drag start v.Move(oldpositions[i] + offset); // Next i++; } // Update labels int index = 0; foreach (Linedef l in unstablelines) { labels[index++].Move(l.Start.Position, l.End.Position); } // Moved return(true); } else { // No changes return(false); } }
// This writes the LINEDEFS to WAD file private void WriteLinedefs(MapSet map, int position, Dictionary <string, MapLumpInfo> maplumps, IDictionary <Sidedef, int> sidedefids, IDictionary <Vertex, int> vertexids) { // Create memory to write to MemoryStream mem = new MemoryStream(); BinaryWriter writer = new BinaryWriter(mem, WAD.ENCODING); // Go for all lines foreach (Linedef l in map.Linedefs) { // Convert flags int flags = 0; foreach (KeyValuePair <string, bool> f in l.Flags) { int fnum; if (f.Value && int.TryParse(f.Key, out fnum)) { flags |= fnum; } } // Add activates to flags flags |= (l.Activate & manager.Config.LinedefActivationsFilter); // Write properties to stream writer.Write((UInt16)vertexids[l.Start]); writer.Write((UInt16)vertexids[l.End]); writer.Write((UInt16)flags); writer.Write((Byte)l.Action); writer.Write((Byte)l.Args[0]); writer.Write((Byte)l.Args[1]); writer.Write((Byte)l.Args[2]); writer.Write((Byte)l.Args[3]); writer.Write((Byte)l.Args[4]); // Front sidedef ushort sid = (l.Front == null ? ushort.MaxValue : (UInt16)sidedefids[l.Front]); writer.Write(sid); // Back sidedef sid = (l.Back == null ? ushort.MaxValue : (UInt16)sidedefids[l.Back]); writer.Write(sid); } // Find insert position and remove old lump int insertpos = MapManager.RemoveSpecificLump(wad, "LINEDEFS", position, MapManager.TEMP_MAP_HEADER, maplumps); if (insertpos == -1) { insertpos = position + 1; } if (insertpos > wad.Lumps.Count) { insertpos = wad.Lumps.Count; } // Create the lump from memory Lump lump = wad.Insert("LINEDEFS", insertpos, (int)mem.Length); lump.Stream.Seek(0, SeekOrigin.Begin); mem.WriteTo(lump.Stream); }
// This writes the structures to a stream // writenamespace may be null to omit writing the namespace to the stream public void Write(MapSet map, Stream stream, string writenamespace) { Write(map.Vertices, map.Linedefs, map.Sidedefs, map.Sectors, map.Things, stream, writenamespace); }
void writeVertices(MapSet map, XmlWriter writer) { writer.WriteStartElement("vertices"); foreach (Vertex vert in map.Vertices) { writer.WriteStartElement("v"); writer.WriteAttributeString("idx", vert.Index.ToString()); writer.WriteAttributeString("x", vert.Position.x.ToString()); writer.WriteAttributeString("y", vert.Position.y.ToString()); writeFields(vert.Fields, writer); writer.WriteEndElement(); } writer.WriteEndElement(); }
// Mode starts public override void OnEngage() { Cursor.Current = Cursors.WaitCursor; base.OnEngage(); General.Interface.DisplayStatus(StatusType.Busy, "Setting up test environment..."); CleanUp(); BuilderPlug.InterfaceForm.AddToInterface(); lastviewstats = BuilderPlug.InterfaceForm.ViewStats; // Export the current map to a temporary WAD file tempfile = BuilderPlug.MakeTempFilename(".wad"); General.Map.ExportToFile(tempfile); // Load the map in VPO_DLL BuilderPlug.VPO.Start(tempfile, General.Map.Options.LevelName); // Determine map boundary mapbounds = Rectangle.Round(MapSet.CreateArea(General.Map.Map.Vertices)); // Create tiles for all points inside the map Point lt = TileForPoint(mapbounds.Left - Tile.TILE_SIZE, mapbounds.Top - Tile.TILE_SIZE); Point rb = TileForPoint(mapbounds.Right + Tile.TILE_SIZE, mapbounds.Bottom + Tile.TILE_SIZE); Rectangle tilesrect = new Rectangle(lt.X, lt.Y, rb.X - lt.X, rb.Y - lt.Y); NearestLineBlockmap blockmap = new NearestLineBlockmap(tilesrect); for (int x = tilesrect.X; x <= tilesrect.Right; x += Tile.TILE_SIZE) { for (int y = tilesrect.Y; y <= tilesrect.Bottom; y += Tile.TILE_SIZE) { // If the tile is obviously outside the map, don't create it Vector2D pc = new Vector2D(x + (Tile.TILE_SIZE >> 1), y + (Tile.TILE_SIZE >> 1)); Linedef ld = MapSet.NearestLinedef(blockmap.GetBlockAt(pc).Lines, pc); float distancesq = ld.DistanceToSq(pc, true); if (distancesq > (Tile.TILE_SIZE * Tile.TILE_SIZE)) { float side = ld.SideOfLine(pc); if ((side > 0.0f) && (ld.Back == null)) { continue; } } Point tp = new Point(x, y); tiles.Add(tp, new Tile(tp)); } } QueuePoints(0); // Make an image to draw on. // The BitmapImage for Doom Builder's resources must be Format32bppArgb and NOT using color correction, // otherwise DB will make a copy of the bitmap when LoadImage() is called! This is normally not a problem, // but we want to keep drawing to the same bitmap. int width = General.NextPowerOf2(General.Interface.Display.ClientSize.Width); int height = General.NextPowerOf2(General.Interface.Display.ClientSize.Height); canvas = new Bitmap(width, height, PixelFormat.Format32bppArgb); image = new DynamicBitmapImage(canvas, "_CANVAS_"); image.UseColorCorrection = false; image.MipMapLevels = 1; image.LoadImage(); image.CreateTexture(); // Make custom presentation CustomPresentation p = new CustomPresentation(); p.AddLayer(new PresentLayer(RendererLayer.Overlay, BlendingMode.Mask, 1f, false)); p.AddLayer(new PresentLayer(RendererLayer.Grid, BlendingMode.Mask)); p.AddLayer(new PresentLayer(RendererLayer.Geometry, BlendingMode.Alpha, 1f, true)); renderer.SetPresentation(p); // Setup processing nextupdate = DateTime.Now + new TimeSpan(0, 0, 0, 0, 100); General.Interface.EnableProcessing(); processingenabled = true; RedrawAllTiles(); Cursor.Current = Cursors.Default; General.Interface.SetCursor(Cursors.Cross); General.Interface.DisplayReady(); }
// This reads the sectors private Dictionary <int, Sector> ReadSectors(MapSet map, UniversalParser textmap) { // Get list of entries List <UniversalCollection> collections = GetNamedCollections(textmap.Root, "sector"); // Create lookup table Dictionary <int, Sector> link = new Dictionary <int, Sector>(collections.Count); // Go for all collections map.SetCapacity(0, 0, 0, map.Sectors.Count + collections.Count, 0); char[] splitter = new[] { ' ' }; //mxd for (int i = 0; i < collections.Count; i++) { // Read fields UniversalCollection c = collections[i]; string where = "sector " + i; int hfloor = GetCollectionEntry(c, "heightfloor", false, 0, where); int hceil = GetCollectionEntry(c, "heightceiling", false, 0, where); string tfloor = GetCollectionEntry(c, "texturefloor", true, "-", where); string tceil = GetCollectionEntry(c, "textureceiling", true, "-", where); int bright = GetCollectionEntry(c, "lightlevel", false, 160, where); int special = GetCollectionEntry(c, "special", false, 0, where); int tag = GetCollectionEntry(c, "id", false, 0, where); //mxd. MoreIDs List <int> tags = new List <int> { tag }; string moreids = GetCollectionEntry(c, "moreids", false, string.Empty, where); if (!string.IsNullOrEmpty(moreids)) { string[] moreidscol = moreids.Split(splitter, StringSplitOptions.RemoveEmptyEntries); foreach (string sid in moreidscol) { int id; if (int.TryParse(sid.Trim(), out id) && id != 0 && !tags.Contains(id)) { tags.Add(id); } } } if (tag == 0 && tags.Count > 1) { tags.RemoveAt(0); } //mxd. Read slopes float fslopex = GetCollectionEntry(c, "floorplane_a", false, 0.0f, where); float fslopey = GetCollectionEntry(c, "floorplane_b", false, 0.0f, where); float fslopez = GetCollectionEntry(c, "floorplane_c", false, 0.0f, where); float foffset = GetCollectionEntry(c, "floorplane_d", false, float.NaN, where); float cslopex = GetCollectionEntry(c, "ceilingplane_a", false, 0.0f, where); float cslopey = GetCollectionEntry(c, "ceilingplane_b", false, 0.0f, where); float cslopez = GetCollectionEntry(c, "ceilingplane_c", false, 0.0f, where); float coffset = GetCollectionEntry(c, "ceilingplane_d", false, float.NaN, where); //mxd. Read flags Dictionary <string, bool> stringflags = new Dictionary <string, bool>(StringComparer.Ordinal); foreach (KeyValuePair <string, string> flag in General.Map.Config.SectorFlags) { stringflags[flag.Key] = GetCollectionEntry(c, flag.Key, false, false, where); } foreach (KeyValuePair <string, string> flag in General.Map.Config.CeilingPortalFlags) { stringflags[flag.Key] = GetCollectionEntry(c, flag.Key, false, false, where); } foreach (KeyValuePair <string, string> flag in General.Map.Config.FloorPortalFlags) { stringflags[flag.Key] = GetCollectionEntry(c, flag.Key, false, false, where); } // Create new item Sector s = map.CreateSector(); if (s != null) { s.Update(hfloor, hceil, tfloor, tceil, special, stringflags, tags, bright, foffset, new Vector3D(fslopex, fslopey, fslopez).GetNormal(), coffset, new Vector3D(cslopex, cslopey, cslopez).GetNormal()); // Custom fields ReadCustomFields(c, s, "sector"); // Add it to the lookup table link.Add(i, s); } } // Return lookup table return(link); }
private void BuildMaterialsWithNormalMaps(string[] assetGUIDs, Material materialTemplate, string outputPathAssetsRelativeTrimmed) { // Assume a list size of half the assetGUIDs length, but add a small buffer in case not all textures have proper normals for them List <MapSet> textureSets = new List <MapSet>((assetGUIDs.Length + 2) / 2); List <AssetNameDetails> assetNameDetails = new List <AssetNameDetails>(assetGUIDs.Length); bool wereTextureImportSettingsEdited = false; foreach (string guid in assetGUIDs) { string assetPath = AssetDatabase.GUIDToAssetPath(guid); string assetName = EditorHelpUtilities.GetAssetNameFromPath(assetPath); string assetNameLowerCase = assetName.ToLower(); int assetNameLastDotIndex = assetName.LastIndexOf('.'); string assetNameNoFileTypeLowerCase = assetNameLowerCase.Substring(0, assetNameLastDotIndex); AssetNameDetails nameDetails = new AssetNameDetails(assetPath, assetName, assetNameLowerCase, assetNameNoFileTypeLowerCase); assetNameDetails.Add(nameDetails); } foreach (AssetNameDetails nameDetails in assetNameDetails) { bool isNormalMap = false; foreach (string normalSuffix in normalMapSuffixes) { if (nameDetails.AssetNameNoFileTypeLowerCase.EndsWith(normalSuffix)) { // Found normal map, continue search for albedo maps only isNormalMap = true; continue; } } if (isNormalMap) { continue; } Texture2D albedoTexture = AssetDatabase.LoadAssetAtPath(nameDetails.AssetPath, typeof(Texture2D)) as Texture2D; if (albedoTexture == null) { continue; } if (overrideAlphaIsTransparency) { albedoTexture.alphaIsTransparency = alphaIsTransparencyNew; TextureImporter textureImporter = AssetImporter.GetAtPath(nameDetails.AssetPath) as TextureImporter; if (textureImporter.alphaIsTransparency != alphaIsTransparencyNew) { wereTextureImportSettingsEdited = true; textureImporter.alphaIsTransparency = alphaIsTransparencyNew; } } Texture2D normalTexture = null; string normalMapAssetPath = FindNormalMapAssetPathForTextureName(assetNameDetails, nameDetails.AssetNameNoFileTypeLowerCase); if (normalMapAssetPath != null) { TextureImporter normalTextureImporter = AssetImporter.GetAtPath(normalMapAssetPath) as TextureImporter; if (normalTextureImporter.textureType != TextureImporterType.NormalMap) { normalTextureImporter.textureType = TextureImporterType.NormalMap; wereTextureImportSettingsEdited = true; } normalTexture = AssetDatabase.LoadAssetAtPath(normalMapAssetPath, typeof(Texture2D)) as Texture2D; } MapSet textureCombination = new MapSet(albedoTexture, normalTexture, nameDetails.AssetPath); textureSets.Add(textureCombination); } // Apply the changes to the normal map texture settings to the project, if there were any: if (wereTextureImportSettingsEdited) { AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } foreach (MapSet textureSet in textureSets) { try { Material currentMaterial = new Material(baseMaterial); // copies all properties SetAlbedoMapInMaterial(currentMaterial, textureSet.AlbedoMap); SetNormalMapInMaterial(currentMaterial, textureSet.NormalMap); string textureName = textureSet.AlbedoMap.name; string fileName = GetSanitizedMaterialFileName(textureName); string fullSavePath = outputPathAssetsRelativeTrimmed + "/" + fileName; if (!overrideExistingMaterials && !string.IsNullOrEmpty(AssetDatabase.AssetPathToGUID(fullSavePath))) { // if we don't allow material overwriting and there is an asset at our path (AssetDatabase.AssetPathToGUID not returning null) // just omit the asset creation Destroy(currentMaterial); continue; } // CreateAsset remark: If an asset already exists at path it will be deleted prior to creating a new asset. AssetDatabase.CreateAsset(currentMaterial, fullSavePath); } catch (System.Exception e) { Debug.LogError(string.Format("Something has gone wrong while processing texture set with albedo map at path {0}: {1}", textureSet.AlbedoMapAssetPath, e)); } } }
// This reads the things private void ReadThings(MapSet map, UniversalParser textmap) { // Get list of entries List <UniversalCollection> collections = GetNamedCollections(textmap.Root, "thing"); // Go for all collections map.SetCapacity(0, 0, 0, 0, map.Things.Count + collections.Count); for (int i = 0; i < collections.Count; i++) { // Read fields UniversalCollection c = collections[i]; int[] args = new int[Linedef.NUM_ARGS]; string where = "thing " + i; float x = GetCollectionEntry(c, "x", true, 0.0f, where); float y = GetCollectionEntry(c, "y", true, 0.0f, where); float height = GetCollectionEntry(c, "height", false, 0.0f, where); int tag = GetCollectionEntry(c, "id", false, 0, where); int angledeg = GetCollectionEntry(c, "angle", false, 0, where); int pitch = GetCollectionEntry(c, "pitch", false, 0, where); //mxd int roll = GetCollectionEntry(c, "roll", false, 0, where); //mxd float scaleX = GetCollectionEntry(c, "scalex", false, 1.0f, where); //mxd float scaleY = GetCollectionEntry(c, "scaley", false, 1.0f, where); //mxd float scale = GetCollectionEntry(c, "scale", false, 0f, where); //mxd int type = GetCollectionEntry(c, "type", true, 0, where); int special = GetCollectionEntry(c, "special", false, 0, where); args[0] = GetCollectionEntry(c, "arg0", false, 0, where); args[1] = GetCollectionEntry(c, "arg1", false, 0, where); args[2] = GetCollectionEntry(c, "arg2", false, 0, where); args[3] = GetCollectionEntry(c, "arg3", false, 0, where); args[4] = GetCollectionEntry(c, "arg4", false, 0, where); if (scale != 0) //mxd { scaleX = scale; scaleY = scale; } // Flags Dictionary <string, bool> stringflags = new Dictionary <string, bool>(StringComparer.Ordinal); foreach (KeyValuePair <string, string> flag in General.Map.Config.ThingFlags) { stringflags[flag.Key] = GetCollectionEntry(c, flag.Key, false, false, where); } foreach (FlagTranslation ft in General.Map.Config.ThingFlagsTranslation) { foreach (string field in ft.Fields) { stringflags[field] = GetCollectionEntry(c, field, false, false, where); } } // Create new item Thing t = map.CreateThing(); if (t != null) { t.Update(type, x, y, height, angledeg, pitch, roll, scaleX, scaleY, stringflags, tag, special, args); // Custom fields ReadCustomFields(c, t, "thing"); } } }
// This reads the linedefs and sidedefs private void ReadLinedefs(MapSet map, UniversalParser textmap, Dictionary <int, Vertex> vertexlink, Dictionary <int, Sector> sectorlink) { // Get list of entries List <UniversalCollection> linescolls = GetNamedCollections(textmap.Root, "linedef"); List <UniversalCollection> sidescolls = GetNamedCollections(textmap.Root, "sidedef"); // Go for all lines map.SetCapacity(0, map.Linedefs.Count + linescolls.Count, map.Sidedefs.Count + sidescolls.Count, 0, 0); char[] splitter = { ' ' }; //mxd for (int i = 0; i < linescolls.Count; i++) { // Read fields UniversalCollection lc = linescolls[i]; int[] args = new int[Linedef.NUM_ARGS]; string where = "linedef " + i; int v1 = GetCollectionEntry(lc, "v1", true, 0, where); int v2 = GetCollectionEntry(lc, "v2", true, 0, where); if (!vertexlink.ContainsKey(v1) || !vertexlink.ContainsKey(v2)) { //mxd General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references one or more invalid vertices. Linedef has been removed."); continue; } int tag = GetCollectionEntry(lc, "id", false, 0, where); int special = GetCollectionEntry(lc, "special", false, 0, where); args[0] = GetCollectionEntry(lc, "arg0", false, 0, where); args[1] = GetCollectionEntry(lc, "arg1", false, 0, where); args[2] = GetCollectionEntry(lc, "arg2", false, 0, where); args[3] = GetCollectionEntry(lc, "arg3", false, 0, where); args[4] = GetCollectionEntry(lc, "arg4", false, 0, where); int s1 = GetCollectionEntry(lc, "sidefront", false, -1, where); int s2 = GetCollectionEntry(lc, "sideback", false, -1, where); //mxd. MoreIDs List <int> tags = new List <int> { tag }; string moreids = GetCollectionEntry(lc, "moreids", false, string.Empty, where); if (!string.IsNullOrEmpty(moreids)) { string[] moreidscol = moreids.Split(splitter, StringSplitOptions.RemoveEmptyEntries); foreach (string sid in moreidscol) { int id; if (int.TryParse(sid.Trim(), out id) && id != 0 && !tags.Contains(id)) { tags.Add(id); } } } if (tag == 0 && tags.Count > 1) { tags.RemoveAt(0); } // Flags Dictionary <string, bool> stringflags = new Dictionary <string, bool>(StringComparer.Ordinal); foreach (KeyValuePair <string, string> flag in General.Map.Config.LinedefFlags) { stringflags[flag.Key] = GetCollectionEntry(lc, flag.Key, false, false, where); } foreach (FlagTranslation ft in General.Map.Config.LinedefFlagsTranslation) { foreach (string field in ft.Fields) { stringflags[field] = GetCollectionEntry(lc, field, false, false, where); } } // Activations foreach (LinedefActivateInfo activate in General.Map.Config.LinedefActivates) { stringflags[activate.Key] = GetCollectionEntry(lc, activate.Key, false, false, where); } // Check if not zero-length if (Vector2D.ManhattanDistance(vertexlink[v1].Position, vertexlink[v2].Position) > 0.0001f) { // Create new linedef Linedef l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]); if (l != null) { l.Update(stringflags, 0, tags, special, args); l.UpdateCache(); // Custom fields ReadCustomFields(lc, l, "linedef"); // Read sidedefs and connect them to the line if (s1 > -1) { if (s1 < sidescolls.Count) { ReadSidedef(map, sidescolls[s1], l, true, sectorlink, s1); } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid front sidedef " + s1 + ". Sidedef has been removed."); } } if (s2 > -1) { if (s2 < sidescolls.Count) { ReadSidedef(map, sidescolls[s2], l, false, sectorlink, s2); } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid back sidedef " + s1 + ". Sidedef has been removed."); } } } } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " is zero-length. Linedef has been removed."); } } }
// This performs the copy. Returns false when copy was cancelled. private static bool DoCopySelection(string desc) { // Check if possible to copy/paste if (General.Editing.Mode.Attributes.AllowCopyPaste) { // Let the plugins know if (General.Plugins.OnCopyBegin()) { // Ask the editing mode to prepare selection for copying. // The edit mode should mark all vertices, lines and sectors // that need to be copied. if (General.Editing.Mode.OnCopyBegin()) { General.MainWindow.DisplayStatus(StatusType.Action, desc); // Copy the marked geometry // This links sidedefs that are not linked to a marked sector to a virtual sector MapSet copyset = General.Map.Map.CloneMarked(); // Convert flags and activations to UDMF fields, if needed if (!(General.Map.FormatInterface is UniversalMapSetIO)) { copyset.TranslateToUDMF(General.Map.FormatInterface.GetType()); } // Write data to stream MemoryStream memstream = new MemoryStream(); ClipboardStreamWriter writer = new ClipboardStreamWriter(); //mxd writer.Write(copyset, memstream); try { //mxd. Set on clipboard DataObject copydata = new DataObject(); copydata.SetData(CLIPBOARD_DATA_FORMAT, memstream); Clipboard.SetDataObject(copydata, true, 5, 200); } catch (ExternalException) { General.Interface.DisplayStatus(StatusType.Warning, "Failed to perform a Clipboard operation..."); memstream.Dispose(); return(false); } // Done memstream.Dispose(); General.Editing.Mode.OnCopyEnd(); General.Plugins.OnCopyEnd(); return(true); } } } else { // Copy not allowed General.MessageBeep(MessageBeepType.Warning); } // Aborted return(false); }
// Constructor to start dragging immediately public DuplicateThingsMode(EditMode basemode, Vector2D dragstartmappos) { // Initialize this.dragstartmappos = dragstartmappos; this.basemode = basemode; Cursor.Current = Cursors.AppStarting; // Make undo for the dragging General.Map.UndoRedo.CreateUndo("Duplicate things"); // Mark what we are dragging General.Map.Map.ClearAllMarks(false); General.Map.Map.MarkSelectedThings(true, true); // Get selected things List <Thing> oldthings = General.Map.Map.GetMarkedThings(true); selectedthings = new List <Thing>(oldthings.Count); foreach (Thing t in oldthings) { Thing newt = General.Map.Map.CreateThing(); t.CopyPropertiesTo(newt); t.Selected = false; t.Marked = false; selectedthings.Add(newt); newt.Marked = true; newt.Marked = true; } unselectedthings = new List <Thing>(); foreach (Thing t in General.Map.ThingsFilter.VisibleThings) { if (!t.Marked) { unselectedthings.Add(t); } } // Get the nearest thing for snapping dragitem = MapSet.NearestThing(selectedthings, dragstartmappos); // Make old positions list // We will use this as reference to move the vertices, or to move them back on cancel oldpositions = new List <Vector2D>(selectedthings.Count); foreach (Thing t in selectedthings) { oldpositions.Add(t.Position); } // Also keep old position of the dragged item dragitemposition = dragitem.Position; // Keep view information lastoffsetx = renderer.OffsetX; lastoffsety = renderer.OffsetY; lastscale = renderer.Scale; Cursor.Current = Cursors.Default; // We have no destructor GC.SuppressFinalize(this); }
//mxd protected void AlignTextureToClosestLine(bool alignx, bool aligny) { if (!(mode.HighlightedObject is BaseVisualSector)) { return; } // Do we need to align this? (and also grab texture scale while we are at it) float scaleX, scaleY; bool isFloor = (geometrytype == VisualGeometryType.FLOOR); if (mode.HighlightedTarget is VisualFloor) { Sector target; VisualFloor vf = (VisualFloor)mode.HighlightedTarget; // Use the control sector if the floor belongs to a 3D floor if (vf.ExtraFloor == null) { target = vf.Sector.Sector; } else { target = vf.GetControlSector(); } // Check texture if (target.FloorTexture != (isFloor ? Sector.Sector.FloorTexture : Sector.Sector.CeilTexture)) { return; } scaleX = target.Fields.GetValue("xscalefloor", 1.0f); scaleY = target.Fields.GetValue("yscalefloor", 1.0f); } else { Sector target; VisualCeiling vc = (VisualCeiling)mode.HighlightedTarget; // Use the control sector if the ceiling belongs to a 3D floor if (vc.ExtraFloor == null) { target = vc.Sector.Sector; } else { target = vc.GetControlSector(); } // Check texture if (target.CeilTexture != (isFloor ? Sector.Sector.FloorTexture : Sector.Sector.CeilTexture)) { return; } scaleX = target.Fields.GetValue("xscaleceiling", 1.0f); scaleY = target.Fields.GetValue("yscaleceiling", 1.0f); } //find a linedef to align to Vector2D hitpos = mode.GetHitPosition(); if (!hitpos.IsFinite()) { return; } //align to line of highlighted sector, which is closest to hitpos Sector highlightedSector = ((BaseVisualSector)mode.HighlightedObject).Sector; List <Linedef> lines = new List <Linedef>(); foreach (Sidedef side in highlightedSector.Sidedefs) { lines.Add(side.Line); } Linedef targetLine = MapSet.NearestLinedef(lines, hitpos); if (targetLine == null) { return; } bool isFront = targetLine.SideOfLine(hitpos) > 0; Sector.Sector.Fields.BeforeFieldsChange(); //find an angle to rotate texture float sourceAngle = (float)Math.Round(General.ClampAngle(isFront ? -Angle2D.RadToDeg(targetLine.Angle) + 90 : -Angle2D.RadToDeg(targetLine.Angle) - 90), 1); if (!isFront) { sourceAngle = General.ClampAngle(sourceAngle + 180); } //update angle UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "rotationfloor" : "rotationceiling"), sourceAngle, 0f); // Scale texture if it's a slope and the appropriate option is set if (level.plane.Normal.z != 1.0f && BuilderPlug.Me.ScaleTexturesOnSlopes != 2) { Vector2D basescale = new Vector2D(1.0f, 1.0f); // User wants to use the current scale as a base? if (BuilderPlug.Me.ScaleTexturesOnSlopes == 1) { basescale.x = scaleX; basescale.y = scaleY; } // Create a unit vector of the direction of the target line in 3D space Vector3D targetlinevector = new Line3D(new Vector3D(targetLine.Start.Position, level.plane.GetZ(targetLine.Start.Position)), new Vector3D(targetLine.End.Position, level.plane.GetZ(targetLine.End.Position))).GetDelta().GetNormal(); // Get a perpendicular vector of the target line in 3D space. This is used to get the slope angle relative to the target line Vector3D targetlineperpendicular = Vector3D.CrossProduct(targetlinevector, level.plane.Normal); if (alignx) { scaleX = Math.Abs(basescale.x * (1.0f / (float)Math.Cos(targetlinevector.GetAngleZ()))); } if (aligny) { scaleY = Math.Abs(basescale.y * (1.0f / (float)Math.Cos(targetlineperpendicular.GetAngleZ()))); } } //set scale UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "xscalefloor" : "xscaleceiling"), scaleX, 1.0f); UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "yscalefloor" : "yscaleceiling"), scaleY, 1.0f); //update offset float distToStart = Vector2D.Distance(hitpos, targetLine.Start.Position); float distToEnd = Vector2D.Distance(hitpos, targetLine.End.Position); Vector2D offset = (distToStart < distToEnd ? targetLine.Start.Position : targetLine.End.Position).GetRotated(Angle2D.DegToRad(sourceAngle)); if (alignx) { if (Texture != null && Texture.IsImageLoaded) { offset.x %= Texture.Width / scaleX; } UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "xpanningfloor" : "xpanningceiling"), (float)Math.Round(-offset.x), 0f); } if (aligny) { if (Texture != null && Texture.IsImageLoaded) { offset.y %= Texture.Height / scaleY; } UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "ypanningfloor" : "ypanningceiling"), (float)Math.Round(offset.y), 0f); } //update geometry Sector.UpdateSectorGeometry(false); }
void writeSides(MapSet map, XmlWriter writer) { writer.WriteStartElement("sides"); foreach (Sidedef s in map.Sidedefs) { writer.WriteStartElement("side"); writer.WriteAttributeString("idx", s.Index.ToString()); writer.WriteAttributeString("line", s.Line.Index.ToString()); if (!s.HighTexture.Equals("-")) writer.WriteElementString("high-tex", s.HighTexture); if (!s.LowTexture.Equals("-")) writer.WriteElementString("low-tex", s.LowTexture); if (!s.MiddleTexture.Equals("-")) writer.WriteElementString("middle-tex", s.MiddleTexture); writer.WriteElementString("offset-x", s.OffsetX.ToString()); writer.WriteElementString("offset-y", s.OffsetY.ToString()); writer.WriteElementString("front", s.IsFront.ToString()); writeFields(s.Fields, writer); writer.WriteEndElement(); } writer.WriteEndElement(); }
//mxd protected void AlignTextureToClosestLine(bool alignx, bool aligny) { if (!(mode.HighlightedObject is BaseVisualSector)) { return; } // Do we need to align this? (and also grab texture scale while we are at it) float scaleX, scaleY; bool isFloor = (geometrytype == VisualGeometryType.FLOOR); if (mode.HighlightedTarget is VisualFloor) { VisualFloor target = (VisualFloor)mode.HighlightedTarget; // Check texture if (target.Sector.Sector.FloorTexture != (isFloor ? Sector.Sector.FloorTexture : Sector.Sector.CeilTexture)) { return; } scaleX = target.Sector.Sector.Fields.GetValue("xscalefloor", 1.0f); scaleY = target.Sector.Sector.Fields.GetValue("yscalefloor", 1.0f); } else { VisualCeiling target = (VisualCeiling)mode.HighlightedTarget; // Check texture if (target.Sector.Sector.CeilTexture != (isFloor ? Sector.Sector.FloorTexture : Sector.Sector.CeilTexture)) { return; } scaleX = target.Sector.Sector.Fields.GetValue("xscaleceiling", 1.0f); scaleY = target.Sector.Sector.Fields.GetValue("yscaleceiling", 1.0f); } //find a linedef to align to Vector2D hitpos = mode.GetHitPosition(); if (!hitpos.IsFinite()) { return; } //align to line of highlighted sector, which is closest to hitpos Sector highlightedSector = ((BaseVisualSector)mode.HighlightedObject).Sector; List <Linedef> lines = new List <Linedef>(); foreach (Sidedef side in highlightedSector.Sidedefs) { lines.Add(side.Line); } Linedef targetLine = MapSet.NearestLinedef(lines, hitpos); if (targetLine == null) { return; } bool isFront = targetLine.SideOfLine(hitpos) > 0; Sector.Sector.Fields.BeforeFieldsChange(); //find an angle to rotate texture float sourceAngle = (float)Math.Round(General.ClampAngle(isFront ? -Angle2D.RadToDeg(targetLine.Angle) + 90 : -Angle2D.RadToDeg(targetLine.Angle) - 90), 1); if (!isFront) { sourceAngle = General.ClampAngle(sourceAngle + 180); } //update angle UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "rotationfloor" : "rotationceiling"), sourceAngle, 0f); //set scale UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "xscalefloor" : "xscaleceiling"), scaleX, 1.0f); UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "yscalefloor" : "yscaleceiling"), scaleY, 1.0f); //update offset float distToStart = Vector2D.Distance(hitpos, targetLine.Start.Position); float distToEnd = Vector2D.Distance(hitpos, targetLine.End.Position); Vector2D offset = (distToStart < distToEnd ? targetLine.Start.Position : targetLine.End.Position).GetRotated(Angle2D.DegToRad(sourceAngle)); if (alignx) { if (Texture != null && Texture.IsImageLoaded) { offset.x %= Texture.Width / scaleX; } UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "xpanningfloor" : "xpanningceiling"), (float)Math.Round(-offset.x), 0f); } if (aligny) { if (Texture != null && Texture.IsImageLoaded) { offset.y %= Texture.Height / scaleY; } UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "ypanningfloor" : "ypanningceiling"), (float)Math.Round(offset.y), 0f); } //update geometry Sector.UpdateSectorGeometry(false); }
void writeThings(MapSet map, XmlWriter writer) { writer.WriteStartElement("things"); foreach (Thing t in map.Things) { writer.WriteStartElement("thing"); writer.WriteAttributeString("idx", t.Index.ToString()); writer.WriteAttributeString("tag", t.Tag.ToString()); writer.WriteAttributeString("type", t.Type.ToString()); writer.WriteAttributeString("action", t.Action.ToString()); writer.WriteStartElement("pos"); writer.WriteAttributeString("x", t.Position.x.ToString()); writer.WriteAttributeString("y", t.Position.y.ToString()); writer.WriteAttributeString("z", t.Position.z.ToString()); writer.WriteAttributeString("angle-float", t.Angle.ToString()); writer.WriteAttributeString("angle-int", t.AngleDoom.ToString()); writer.WriteEndElement(); writer.WriteStartElement("flags"); foreach (String str in t.GetFlags().Keys) { writer.WriteStartElement("flag"); writer.WriteAttributeString("name", str); writer.WriteAttributeString("value", t.GetFlags()[str].ToString()); writer.WriteEndElement(); } writer.WriteEndElement(); writeFields(t.Fields, writer); writer.WriteEndElement(); } writer.WriteEndElement(); }
// Mode starts public override void OnEngage() { Cursor.Current = Cursors.WaitCursor; base.OnEngage(); General.Interface.DisplayStatus(StatusType.Busy, "Setting up test environment..."); BuilderPlug.InitVPO(); //mxd CleanUp(); BuilderPlug.InterfaceForm.AddToInterface(); BuilderPlug.InterfaceForm.OnOpenDoorsChanged += OnOpenDoorsChanged; //mxd lastviewstats = BuilderPlug.InterfaceForm.ViewStats; // Export the current map to a temporary WAD file tempfile = BuilderPlug.MakeTempFilename(".wad"); if (!General.Map.ExportToFile(tempfile)) { //mxd. Abort on export fail Cursor.Current = Cursors.Default; General.Interface.DisplayStatus(StatusType.Warning, "Unable to set test environment..."); OnCancel(); return; } // Load the map in VPO_DLL BuilderPlug.VPO.Start(tempfile, General.Map.Options.LevelName); // Determine map boundary mapbounds = Rectangle.Round(MapSet.CreateArea(General.Map.Map.Vertices)); // Create tiles for all points inside the map CreateTiles(); //mxd QueuePoints(0); // Make an image to draw on. // The BitmapImage for Doom Builder's resources must be Format32bppArgb and NOT using color correction, // otherwise DB will make a copy of the bitmap when LoadImage() is called! This is normally not a problem, // but we want to keep drawing to the same bitmap. int width = General.NextPowerOf2(General.Interface.Display.ClientSize.Width); int height = General.NextPowerOf2(General.Interface.Display.ClientSize.Height); canvas = new Bitmap(width, height, PixelFormat.Format32bppArgb); image = new DynamicBitmapImage(canvas, "_CANVAS_"); image.UseColorCorrection = false; image.MipMapLevels = 1; image.LoadImageNow(); // Make custom presentation CustomPresentation p = new CustomPresentation(); p.AddLayer(new PresentLayer(RendererLayer.Overlay, BlendingMode.Mask, 1f, false)); p.AddLayer(new PresentLayer(RendererLayer.Grid, BlendingMode.Mask)); p.AddLayer(new PresentLayer(RendererLayer.Geometry, BlendingMode.Alpha, 1f, true)); renderer.SetPresentation(p); // Setup processing nextupdate = Clock.CurrentTime + 100; General.Interface.EnableProcessing(); processingenabled = true; RedrawAllTiles(); Cursor.Current = Cursors.Default; General.Interface.SetCursor(Cursors.Cross); General.Interface.DisplayReady(); }
// This updates the selection private void Update() { // Not in any modifying mode? if (mode == ModifyMode.None) { Vector2D prevdragoffset = alignoffset; alignoffset = new Vector2D(float.MinValue, float.MinValue); showalignoffset = false; // Check what grip the mouse is over // and change cursor accordingly Grip mousegrip = CheckMouseGrip(); switch (mousegrip) { case Grip.Main: int closestcorner = -1; float cornerdist = float.MaxValue; for (int i = 0; i < 4; i++) { Vector2D delta = corners[i] - mousemappos; float d = delta.GetLengthSq(); if (d < cornerdist) { closestcorner = i; cornerdist = d; } } switch (closestcorner) { // TODO: case 0: alignoffset = new Vector2D(0f, 0f); break; case 1: alignoffset = new Vector2D(texture.ScaledWidth, 0f); break; case 2: alignoffset = new Vector2D(texture.ScaledWidth, -texture.ScaledHeight); break; case 3: alignoffset = new Vector2D(0f, -texture.ScaledHeight); break; } showalignoffset = true; General.Interface.SetCursor(Cursors.Hand); break; case Grip.RotateLB: case Grip.RotateRT: alignoffset = new Vector2D(0f, 0f); showalignoffset = true; General.Interface.SetCursor(Cursors.Cross); break; case Grip.SizeH: case Grip.SizeV: alignoffset = new Vector2D(0f, 0f); showalignoffset = true; // Pick the best matching cursor depending on rotation and side float resizeangle = -(rotation + sectorinfo[0].rotation); if (mousegrip == Grip.SizeH) { resizeangle += Angle2D.PIHALF; } resizeangle = Angle2D.Normalized(resizeangle); if (resizeangle > Angle2D.PI) { resizeangle -= Angle2D.PI; } resizeangle = Math.Abs(resizeangle + Angle2D.PI / 8.000001f); int cursorindex = (int)Math.Floor((resizeangle / Angle2D.PI) * 4.0f) % 4; General.Interface.SetCursor(RESIZE_CURSORS[cursorindex]); break; default: General.Interface.SetCursor(Cursors.Default); break; } if (prevdragoffset != alignoffset) { General.Interface.RedrawDisplay(); } } else { Vector2D snappedmappos = mousemappos; bool dosnaptogrid = snaptogrid; // Options snaptogrid = General.Interface.ShiftState ^ General.Interface.SnapToGrid; snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge; // Change to crosshair cursor so we can clearly see around the mouse cursor General.Interface.SetCursor(Cursors.Cross); // Check what modifying mode we are in switch (mode) { case ModifyMode.Dragging: offset = -mousemappos - dragoffset; Vector2D transformedpos = TexToWorld(alignoffset); // Snap to nearest vertex? if (snaptonearest) { float vrange = BuilderPlug.Me.StitchRange / renderer.Scale; // Try the nearest vertex Vertex nv = MapSet.NearestVertexSquareRange(General.Map.Map.Vertices, transformedpos, vrange); if (nv != null) { // Change offset to snap to target offset -= nv.Position - transformedpos; dosnaptogrid = false; } else { // Find the nearest line within range Linedef nl = MapSet.NearestLinedefRange(General.Map.Map.Linedefs, transformedpos, vrange); if (nl != null) { // Snap to grid? if (dosnaptogrid) { // Get grid intersection coordinates List <Vector2D> coords = nl.GetGridIntersections(); // Find nearest grid intersection float found_distance = float.MaxValue; Vector2D found_pos = new Vector2D(float.NaN, float.NaN); foreach (Vector2D v in coords) { Vector2D dist = transformedpos - v; if (dist.GetLengthSq() < found_distance) { // Found a better match found_distance = dist.GetLengthSq(); found_pos = v; // Do not snap to grid anymore dosnaptogrid = false; } } // Found something? if (!float.IsNaN(found_pos.x)) { // Change offset to snap to target offset -= found_pos - transformedpos; } } else { // Change offset to snap onto the line offset -= nl.NearestOnLine(transformedpos) - transformedpos; } } } } // Snap to grid? if (dosnaptogrid) { // Change offset to align to grid offset -= General.Map.Grid.SnappedToGrid(transformedpos) - transformedpos; } break; case ModifyMode.Resizing: // Snap to nearest vertex? if (snaptonearest) { float vrange = BuilderPlug.Me.StitchRange / renderer.Scale; // Try the nearest vertex Vertex nv = MapSet.NearestVertexSquareRange(General.Map.Map.Vertices, snappedmappos, vrange); if (nv != null) { snappedmappos = nv.Position; dosnaptogrid = false; } } // Snap to grid? if (dosnaptogrid) { // Aligned to grid snappedmappos = General.Map.Grid.SnappedToGrid(snappedmappos); } float newscale = 1f / resizeaxis.GetNearestOnLine(snappedmappos); if (float.IsInfinity(newscale) || float.IsNaN(newscale)) { newscale = 99999f; } scale = (newscale * resizefilter) + scale * (1.0f - resizefilter); if (float.IsInfinity(scale.x) || float.IsNaN(scale.x)) { scale.x = 99999f; } if (float.IsInfinity(scale.y) || float.IsNaN(scale.y)) { scale.y = 99999f; } // Show the extension line so that the user knows what it is aligning to UpdateRectangleComponents(); Line2D edgeline; if (resizefilter.x > resizefilter.y) { edgeline = new Line2D(corners[1], corners[2]); } else { edgeline = new Line2D(corners[3], corners[2]); } float nearestonedge = edgeline.GetNearestOnLine(snappedmappos); if (nearestonedge > 0.5f) { extensionline = new Line2D(edgeline.v1, snappedmappos); } else { extensionline = new Line2D(edgeline.v2, snappedmappos); } break; case ModifyMode.Rotating: // Snap to nearest vertex? extensionline = new Line2D(); if (snaptonearest) { float vrange = BuilderPlug.Me.StitchRange / renderer.Scale; // Try the nearest vertex Vertex nv = MapSet.NearestVertexSquareRange(General.Map.Map.Vertices, snappedmappos, vrange); if (nv != null) { snappedmappos = nv.Position; dosnaptogrid = false; // Show the extension line so that the user knows what it is aligning to extensionline = new Line2D(corners[0], snappedmappos); } } Vector2D delta = snappedmappos - rotationcenter; float deltaangle = -delta.GetAngle(); // Snap to grid? if (dosnaptogrid) { // We make 8 vectors that the rotation can snap to float founddistance = float.MaxValue; float foundrotation = rotation; for (int i = 0; i < 8; i++) { // Make the vectors float angle = (float)i * Angle2D.PI * 0.25f; Vector2D gridvec = Vector2D.FromAngle(angle); Vector3D rotvec = Vector2D.FromAngle(deltaangle + rotationoffset); // Check distance float dist = 2.0f - Vector2D.DotProduct(gridvec, rotvec); if (dist < founddistance) { foundrotation = angle; founddistance = dist; } } // Keep rotation rotation = foundrotation - sectorinfo[0].rotation; } else { rotation = deltaangle + rotationoffset - sectorinfo[0].rotation; } break; } UpdateSectors(); General.Interface.RedrawDisplay(); } }
// This moves the selected things relatively // Returns true when things has actually moved private bool MoveThingsRelative(Vector2D offset, bool snapgrid, bool snapgridincrement, bool snapnearest, bool snapcardinal) { //mxd. If snap to cardinal directions is enabled, modify the offset if (snapcardinal) { float angle = Angle2D.DegToRad((General.ClampAngle((int)Angle2D.RadToDeg(offset.GetAngle()) + 44)) / 90 * 90); offset = new Vector2D(0, -offset.GetLength()).GetRotated(angle); snapgridincrement = true; // We don't want to move Things away from the cardinal directions } Vector2D oldpos = dragitem.Position; Vector2D tl, br; // don't move if the offset contains invalid data if (!offset.IsFinite()) { return(false); } // Find the outmost things tl = br = oldpositions[0]; for (int i = 0; i < oldpositions.Count; i++) { if (oldpositions[i].x < tl.x) { tl.x = (int)oldpositions[i].x; } if (oldpositions[i].x > br.x) { br.x = (int)oldpositions[i].x; } if (oldpositions[i].y > tl.y) { tl.y = (int)oldpositions[i].y; } if (oldpositions[i].y < br.y) { br.y = (int)oldpositions[i].y; } } // Snap to nearest? if (snapnearest) { // Find nearest unselected item within selection range Thing nearest = MapSet.NearestThingSquareRange(unselectedthings, mousemappos, BuilderPlug.Me.StitchRange / renderer.Scale); if (nearest != null) { // Move the dragged item dragitem.Move((Vector2D)nearest.Position); // Adjust the offset offset = (Vector2D)nearest.Position - dragitemposition; // Do not snap to grid! snapgrid = false; snapgridincrement = false; //mxd } } // Snap to grid? if (snapgrid || snapgridincrement) { // Move the dragged item dragitem.Move(dragitemposition + offset); // Snap item to grid increment (mxd) if (snapgridincrement) { dragitem.Move(General.Map.Grid.SnappedToGrid(dragitemposition + offset) - dragstartoffset); } else // Or to the grid itself { dragitem.SnapToGrid(); } // Adjust the offset offset += (Vector2D)dragitem.Position - (dragitemposition + offset); } // Make sure the offset is inside the map boundaries if (offset.x + tl.x < General.Map.Config.LeftBoundary) { offset.x = General.Map.Config.LeftBoundary - tl.x; } if (offset.x + br.x > General.Map.Config.RightBoundary) { offset.x = General.Map.Config.RightBoundary - br.x; } if (offset.y + tl.y > General.Map.Config.TopBoundary) { offset.y = General.Map.Config.TopBoundary - tl.y; } if (offset.y + br.y < General.Map.Config.BottomBoundary) { offset.y = General.Map.Config.BottomBoundary - br.y; } // Drag item moved? if ((!snapgrid && !snapgridincrement) || ((Vector2D)dragitem.Position != oldpos)) { int i = 0; // Move selected geometry foreach (Thing t in selectedthings) { // Move vertex from old position relative to the // mouse position change since drag start t.Move(oldpositions[i] + offset); // Next i++; } // Moved return(true); } else { // No changes return(false); } }
void writeSectors(MapSet map, XmlWriter writer) { writer.WriteStartElement("sectors"); foreach (Sector s in map.Sectors) { writer.WriteStartElement("sector"); writer.WriteAttributeString("idx", s.Index.ToString()); writer.WriteAttributeString("tag", s.Tag.ToString()); writer.WriteAttributeString("ceiling-height", s.CeilHeight.ToString()); writer.WriteAttributeString("floor-height", s.FloorHeight.ToString()); writer.WriteAttributeString("ceiling-tex", s.CeilTexture); writer.WriteAttributeString("floor-tex", s.FloorTexture); writer.WriteAttributeString("lighting", s.Brightness.ToString()); writer.WriteAttributeString("special", s.Effect.ToString()); StringBuilder sb = new StringBuilder(); bool anyWritten = false; foreach (Sidedef side in s.Sidedefs) { if (anyWritten) sb.Append(","); sb.Append(side.Index.ToString()); anyWritten = true; } writer.WriteElementString("sides", sb.ToString()); writeFields(s.Fields, writer); writer.WriteEndElement(); } writer.WriteEndElement(); }
// Mode is engaged public override void OnEngage() { base.OnEngage(); // Update projection (mxd) General.Map.CRenderer3D.CreateProjection(); // Update the used textures General.Map.Data.UpdateUsedTextures(); // Fill the blockmap FillBlockMap(); //mxd. Synch camera position to cursor position or center of the screen in 2d-mode if (General.Settings.GZSynchCameras) { // Keep previous camera position if Control is held and camera was previously moved in Visual mode if (!General.Interface.CtrlState || General.Map.VisualCamera.Position.GetLengthSq() == 0) { //If initial position is inside or nearby a sector - adjust camera.z accordingly float posz = General.Map.VisualCamera.Position.z; Sector nearestsector = General.Map.Map.GetSectorByCoordinates(initialcameraposition, blockmap); if (nearestsector == null) { Linedef nearestline = MapSet.NearestLinedef(General.Map.Map.Linedefs, initialcameraposition); if (nearestline != null) { float side = nearestline.SideOfLine(initialcameraposition); Sidedef nearestside = (side < 0.0f ? nearestline.Front : nearestline.Back) ?? (side < 0.0f ? nearestline.Back : nearestline.Front); if (nearestside != null) { nearestsector = nearestside.Sector; } } } if (nearestsector != null) { int sectorheight = nearestsector.CeilHeight - nearestsector.FloorHeight; if (sectorheight < 41) { posz = nearestsector.FloorHeight + Math.Max(16, sectorheight / 2); } else if (General.Map.VisualCamera.Position.z < nearestsector.FloorHeight + 41) { posz = nearestsector.FloorHeight + 41; // same as in doom } else if (General.Map.VisualCamera.Position.z > nearestsector.CeilHeight) { posz = nearestsector.CeilHeight - 4; } } General.Map.VisualCamera.Position = new Vector3D(initialcameraposition.x, initialcameraposition.y, posz); } } else { General.Map.VisualCamera.PositionAtThing(); } // Start special input mode General.Interface.EnableProcessing(); General.Interface.StartExclusiveMouseInput(); }
public JitterThingsForm(string editingModeName) { this.editingModeName = editingModeName; this.HelpRequested += JitterThingsForm_HelpRequested; InitializeComponent(); //have thing height? heightJitterAmmount.Enabled = General.Map.FormatInterface.HasThingHeight; bUpdateHeight.Enabled = General.Map.FormatInterface.HasThingHeight; //disable pitch/roll/scale? if (!General.Map.UDMF) { pitchAmmount.Enabled = false; rollAmmount.Enabled = false; bUpdatePitch.Enabled = false; bUpdateRoll.Enabled = false; scalegroup.Enabled = false; cbRelativePitch.Enabled = false; cbRelativeRoll.Enabled = false; cbNegativePitch.Enabled = false; cbNegativeRoll.Enabled = false; } //get selection selection = new List <Thing>(); if (editingModeName == "BaseVisualMode") { visualSelection = ((VisualMode)General.Editing.Mode).GetSelectedVisualThings(false); foreach (VisualThing t in visualSelection) { selection.Add(t.Thing); } } else { ICollection <Thing> list = General.Map.Map.GetSelectedThings(true); foreach (Thing t in list) { selection.Add(t); } } //update window header this.Text = "Randomize " + selection.Count + (selection.Count > 1 ? " things" : " thing"); //store intial properties thingData = new List <ThingData>(); foreach (Thing t in selection) { ThingData d = new ThingData(); Thing closest = MapSet.NearestThing(General.Map.Map.Things, t); if (closest != null) { d.SafeDistance = (int)Math.Round(Vector2D.Distance(t.Position, closest.Position)); } else { d.SafeDistance = 512; } if (d.SafeDistance > 0) { d.SafeDistance /= 2; } if (MaxSafeDistance < d.SafeDistance) { MaxSafeDistance = d.SafeDistance; } d.Position = t.Position; d.Angle = t.AngleDoom; d.Pitch = t.Pitch; d.Roll = t.Roll; d.ScaleX = t.ScaleX; d.ScaleY = t.ScaleY; if (General.Map.FormatInterface.HasThingHeight) { if (t.Sector == null) { t.DetermineSector(); } if (t.Sector != null) { d.SectorHeight = Math.Max(0, t.Sector.CeilHeight - (int)t.Height - t.Sector.FloorHeight); if (MaxSafeHeightDistance < d.SectorHeight) { MaxSafeHeightDistance = d.SectorHeight; } d.ZOffset = (int)t.Position.z; } } thingData.Add(d); } positionJitterAmmount.Maximum = MaxSafeDistance; heightJitterAmmount.Maximum = MaxSafeHeightDistance; //create undo General.Map.UndoRedo.ClearAllRedos(); General.Map.UndoRedo.CreateUndo("Randomize " + selection.Count + (selection.Count > 1 ? " things" : " thing")); //update controls UpdateOffsetAngles(); UpdateHeights(); UpdateRotationAngles(); UpdatePitchAngles(); UpdateRollAngles(); UpdateScaleX(); UpdateScaleY(); //apply settings cbRelativeScale.Checked = relativeScale; cbUniformScale.Checked = uniformScale; cbNegativeScaleX.Checked = allowNegativeScaleX; cbNegativeScaleY.Checked = allowNegativeScaleY; cbRelativePitch.Checked = relativePitch; cbRelativeRoll.Checked = relativeRoll; cbNegativePitch.Checked = allowNegativePitch; cbNegativeRoll.Checked = allowNegativeRoll; //add event listeners cbRelativeScale.CheckedChanged += cbRelativeScale_CheckedChanged; cbUniformScale.CheckedChanged += cbUniformScale_CheckedChanged; cbNegativeScaleX.CheckedChanged += cbNegativeScaleX_CheckedChanged; cbNegativeScaleY.CheckedChanged += cbNegativeScaleY_CheckedChanged; cbRelativePitch.CheckedChanged += cbRelativePitch_CheckedChanged; cbRelativeRoll.CheckedChanged += cbRelativeRoll_CheckedChanged; cbNegativePitch.CheckedChanged += cbNegativePitch_CheckedChanged; cbNegativeRoll.CheckedChanged += cbNegativeRoll_CheckedChanged; //disable controls if necessary if (uniformScale) { cbUniformScale_CheckedChanged(cbUniformScale, EventArgs.Empty); } //tricky way to actually store undo information... foreach (Thing t in selection) { t.Move(t.Position); } }
private static Dictionary <int, Sector> ReadSectors(MapSet map, BinaryReader reader) { int count = reader.ReadInt32(); // Create lookup table Dictionary <int, Sector> link = new Dictionary <int, Sector>(count); // Go for all collections map.SetCapacity(0, 0, 0, map.Sectors.Count + count, 0); for (int i = 0; i < count; i++) { int effect = reader.ReadInt32(); int hfloor = reader.ReadInt32(); int hceil = reader.ReadInt32(); int bright = reader.ReadInt32(); //mxd. Tags int numtags = reader.ReadInt32(); //mxd List <int> tags = new List <int>(numtags); //mxd for (int a = 0; a < numtags; a++) { tags.Add(reader.ReadInt32()); //mxd } string tfloor = ReadString(reader); string tceil = ReadString(reader); //mxd. Slopes float foffset = reader.ReadSingle(); Vector3D fslope = new Vector3D(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); float coffset = reader.ReadSingle(); Vector3D cslope = new Vector3D(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); //flags Dictionary <string, bool> stringflags = new Dictionary <string, bool>(StringComparer.Ordinal); int numFlags = reader.ReadInt32(); for (int f = 0; f < numFlags; f++) { stringflags.Add(ReadString(reader), reader.ReadBoolean()); } //add missing flags foreach (KeyValuePair <string, string> flag in General.Map.Config.SectorFlags) { if (stringflags.ContainsKey(flag.Key)) { continue; } stringflags.Add(flag.Key, false); } // Create new item Dictionary <string, UniValue> fields = ReadCustomFields(reader); Sector s = map.CreateSector(); if (s != null) { s.Update(hfloor, hceil, tfloor, tceil, effect, stringflags, tags, bright, foffset, fslope, coffset, cslope); // Add custom fields s.Fields.BeforeFieldsChange(); foreach (KeyValuePair <string, UniValue> group in fields) { s.Fields.Add(group.Key, group.Value); } // Add it to the lookup table link.Add(i, s); } } // Return lookup table return(link); }
// This reads the LINEDEFS and SIDEDEFS from WAD file private void ReadLinedefs(MapSet map, int firstindex, Dictionary <int, Vertex> vertexlink, Dictionary <int, Sector> sectorlink) { int[] args = new int[Linedef.NUM_ARGS]; // Get the linedefs lump from wad file Lump linedefslump = wad.FindLump("LINEDEFS", firstindex); if (linedefslump == null) { throw new Exception("Could not find required lump LINEDEFS!"); } // Get the sidedefs lump from wad file Lump sidedefslump = wad.FindLump("SIDEDEFS", firstindex); if (sidedefslump == null) { throw new Exception("Could not find required lump SIDEDEFS!"); } // Prepare to read the items MemoryStream linedefsmem = new MemoryStream(linedefslump.Stream.ReadAllBytes()); MemoryStream sidedefsmem = new MemoryStream(sidedefslump.Stream.ReadAllBytes()); int num = (int)linedefslump.Stream.Length / 16; int numsides = (int)sidedefslump.Stream.Length / 30; BinaryReader readline = new BinaryReader(linedefsmem); BinaryReader readside = new BinaryReader(sidedefsmem); // Read items from the lump map.SetCapacity(0, map.Linedefs.Count + num, map.Sidedefs.Count + numsides, 0, 0); for (int i = 0; i < num; i++) { // Read properties from stream int v1 = readline.ReadUInt16(); int v2 = readline.ReadUInt16(); int flags = readline.ReadUInt16(); int action = readline.ReadByte(); args[0] = readline.ReadByte(); args[1] = readline.ReadByte(); args[2] = readline.ReadByte(); args[3] = readline.ReadByte(); args[4] = readline.ReadByte(); int s1 = readline.ReadUInt16(); int s2 = readline.ReadUInt16(); // Make string flags Dictionary <string, bool> stringflags = new Dictionary <string, bool>(StringComparer.Ordinal); foreach (string f in manager.Config.SortedLinedefFlags) { int fnum; if (int.TryParse(f, out fnum)) { stringflags[f] = ((flags & fnum) == fnum); } } // Create new linedef if (vertexlink.ContainsKey(v1) && vertexlink.ContainsKey(v2)) { // Check if not zero-length if (Vector2D.ManhattanDistance(vertexlink[v1].Position, vertexlink[v2].Position) > 0.0001f) { Linedef l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]); l.Update(stringflags, (flags & manager.Config.LinedefActivationsFilter), new List <int> { 0 }, action, args); l.UpdateCache(); Sidedef s; string thigh, tmid, tlow; int offsetx, offsety, sc; // Line has a front side? if (s1 != ushort.MaxValue) { // Read front sidedef sidedefsmem.Seek(s1 * 30, SeekOrigin.Begin); if ((s1 * 30L) <= (sidedefsmem.Length - 30L)) { offsetx = readside.ReadInt16(); offsety = readside.ReadInt16(); thigh = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING); tlow = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING); tmid = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING); sc = readside.ReadUInt16(); // Create front sidedef if (sectorlink.ContainsKey(sc)) { s = map.CreateSidedef(l, true, sectorlink[sc]); s.Update(offsetx, offsety, thigh, tmid, tlow); } else { General.ErrorLogger.Add(ErrorType.Warning, "Sidedef " + s1 + " references invalid sector " + sc + ". Sidedef has been removed."); } } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid sidedef " + s1 + ". Sidedef has been removed."); } } // Line has a back side? if (s2 != ushort.MaxValue) { // Read back sidedef sidedefsmem.Seek(s2 * 30, SeekOrigin.Begin); if ((s2 * 30L) <= (sidedefsmem.Length - 30L)) { offsetx = readside.ReadInt16(); offsety = readside.ReadInt16(); thigh = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING); tlow = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING); tmid = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING); sc = readside.ReadUInt16(); // Create back sidedef if (sectorlink.ContainsKey(sc)) { s = map.CreateSidedef(l, false, sectorlink[sc]); s.Update(offsetx, offsety, thigh, tmid, tlow); } else { General.ErrorLogger.Add(ErrorType.Warning, "Sidedef " + s2 + " references invalid sector " + sc + ". Sidedef has been removed."); } } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid sidedef " + s2 + ". Sidedef has been removed."); } } } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " is zero-length. Linedef has been removed."); } } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references one or more invalid vertices. Linedef has been removed."); } } // Done linedefsmem.Dispose(); sidedefsmem.Dispose(); }
// This reads the linedefs and sidedefs private static void ReadLinedefs(MapSet map, BinaryReader reader, Dictionary <int, Vertex> vertexlink, Dictionary <int, Sector> sectorlink, Dictionary <int, SidedefData> sidedeflink) { int count = reader.ReadInt32(); // Go for all lines map.SetCapacity(0, map.Linedefs.Count + count, map.Sidedefs.Count + sidedeflink.Count, 0, 0); for (int i = 0; i < count; i++) { int[] args = new int[Linedef.NUM_ARGS]; int v1 = reader.ReadInt32(); int v2 = reader.ReadInt32(); int s1 = reader.ReadInt32(); int s2 = reader.ReadInt32(); int special = reader.ReadInt32(); for (int a = 0; a < Linedef.NUM_ARGS; a++) { args[a] = reader.ReadInt32(); } int numtags = reader.ReadInt32(); //mxd List <int> tags = new List <int>(numtags); //mxd for (int a = 0; a < numtags; a++) { tags.Add(reader.ReadInt32()); //mxd } //flags Dictionary <string, bool> stringflags = new Dictionary <string, bool>(StringComparer.Ordinal); int numFlags = reader.ReadInt32(); for (int f = 0; f < numFlags; f++) { stringflags.Add(ReadString(reader), reader.ReadBoolean()); } //add missing flags foreach (KeyValuePair <string, string> flag in General.Map.Config.LinedefFlags) { if (stringflags.ContainsKey(flag.Key)) { continue; } stringflags.Add(flag.Key, false); } //add missing activations foreach (LinedefActivateInfo activate in General.Map.Config.LinedefActivates) { if (stringflags.ContainsKey(activate.Key)) { continue; } stringflags.Add(activate.Key, false); } // Read custom fields Dictionary <string, UniValue> fields = ReadCustomFields(reader); // Check if not zero-length if (Vector2D.ManhattanDistance(vertexlink[v1].Position, vertexlink[v2].Position) > 0.0001f) { // Create new linedef Linedef l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]); if (l != null) { l.Update(stringflags, 0, tags, special, args); l.UpdateCache(); // Add custom fields l.Fields.BeforeFieldsChange(); foreach (KeyValuePair <string, UniValue> group in fields) { l.Fields.Add(group.Key, group.Value); } // Connect sidedefs to the line if (s1 > -1) { if (s1 < sidedeflink.Count) { AddSidedef(map, sidedeflink[s1], l, true, sectorlink); } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid front sidedef " + s1 + ". Sidedef has been removed."); } } if (s2 > -1) { if (s2 < sidedeflink.Count) { AddSidedef(map, sidedeflink[s2], l, false, sectorlink); } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid back sidedef " + s1 + ". Sidedef has been removed."); } } } } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " is zero-length. Linedef has been removed."); } } }
// This preforms visibility culling protected void DoCulling() { HashSet <Linedef> visiblelines = new HashSet <Linedef>(); Vector2D campos2d = General.Map.VisualCamera.Position; // Make collections visiblesectors = new Dictionary <Sector, VisualSector>(visiblesectors.Count); visiblegeometry = new List <VisualGeometry>(visiblegeometry.Capacity); visiblethings = new List <VisualThing>(visiblethings.Capacity); // Get the blocks within view range visibleblocks = blockmap.GetFrustumRange(renderer.Frustum2D); // Fill collections with geometry and things foreach (VisualBlockEntry block in visibleblocks) { if (processgeometry) { // Lines foreach (Linedef ld in block.Lines) { // Line not already processed? if (!visiblelines.Contains(ld)) { // Add line if not added yet visiblelines.Add(ld); // Which side of the line is the camera on? if (ld.SideOfLine(campos2d) < 0) { // Do front of line if (ld.Front != null) { ProcessSidedefCulling(ld.Front); } } else { // Do back of line if (ld.Back != null) { ProcessSidedefCulling(ld.Back); } } } } } if (processthings) { // Things foreach (Thing t in block.Things) { // Not filtered out? if (General.Map.ThingsFilter.IsThingVisible(t)) { VisualThing vt; if (allthings.ContainsKey(t)) { vt = allthings[t]; } else { // Create new visual thing vt = CreateVisualThing(t); allthings.Add(t, vt); } if (vt != null) { visiblethings.Add(vt); } } } } } if (processgeometry) { // Find camera sector Linedef nld = MapSet.NearestLinedef(visiblelines, campos2d); if (nld != null) { General.Map.VisualCamera.Sector = GetCameraSectorFromLinedef(nld); } else { // Exceptional case: no lines found in any nearby blocks! // This could happen in the middle of an extremely large sector and in this case // the above code will not have found any sectors/sidedefs for rendering. // Here we handle this special case with brute-force. Let's find the sector // the camera is in by searching the entire map and render that sector only. nld = General.Map.Map.NearestLinedef(campos2d); if (nld != null) { General.Map.VisualCamera.Sector = GetCameraSectorFromLinedef(nld); if (General.Map.VisualCamera.Sector != null) { foreach (Sidedef sd in General.Map.VisualCamera.Sector.Sidedefs) { float side = sd.Line.SideOfLine(campos2d); if (((side < 0) && sd.IsFront) || ((side > 0) && !sd.IsFront)) { ProcessSidedefCulling(sd); } } } else { // Too far away from the map to see anything General.Map.VisualCamera.Sector = null; } } else { // Map is empty General.Map.VisualCamera.Sector = null; } } } }
private static void ProcessNodeClick(TreeNode node) { if (node == null) { return; } List <Vector2D> points = new List <Vector2D>(); RectangleF area = MapSet.CreateEmptyArea(); if (node.Parent == null) { if (node.Tag is SoundEnvironment) { SoundEnvironment se = (SoundEnvironment)node.Tag; foreach (Sector s in se.Sectors) { foreach (Sidedef sd in s.Sidedefs) { points.Add(sd.Line.Start.Position); points.Add(sd.Line.End.Position); } } } else { // Don't zoom if the wrong nodes are selected return; } } else { if (node.Tag is Thing) { Thing t = (Thing)node.Tag; // We don't want to be zoomed too closely, so add somepadding points.Add(t.Position - 200); points.Add(t.Position + 200); } else if (node.Tag is Linedef) { Linedef ld = (Linedef)node.Tag; points.Add(ld.Start.Position); points.Add(ld.End.Position); } else { // Don't zoom if the wrong nodes are selected return; } } area = MapSet.IncreaseArea(area, points); // Add padding area.Inflate(100f, 100f); // Zoom to area ClassicMode editmode = (General.Editing.Mode as ClassicMode); editmode.CenterOnArea(area, 0.0f); }
public void Write(MapSet map, Stream stream) { Write(map.Vertices, map.Linedefs, map.Sidedefs, map.Sectors, map.Things, stream); }
// This moves the selected things relatively // Returns true when things has actually moved private bool MoveThingsRelative(Vector2D offset, bool snapgrid, bool snapnearest) { Vector2D oldpos = dragitem.Position; Vector2D tl, br; // don't move if the offset contains invalid data if (!offset.IsFinite()) { return(false); } // Find the outmost things tl = br = oldpositions[0]; for (int i = 0; i < oldpositions.Count; i++) { if (oldpositions[i].x < tl.x) { tl.x = (int)oldpositions[i].x; } if (oldpositions[i].x > br.x) { br.x = (int)oldpositions[i].x; } if (oldpositions[i].y > tl.y) { tl.y = (int)oldpositions[i].y; } if (oldpositions[i].y < br.y) { br.y = (int)oldpositions[i].y; } } // Snap to nearest? if (snapnearest) { // Find nearest unselected item within selection range Thing nearest = MapSet.NearestThingSquareRange(unselectedthings, mousemappos, BuilderPlug.Me.StitchRange / renderer.Scale); if (nearest != null) { // Move the dragged item dragitem.Move((Vector2D)nearest.Position); // Adjust the offset offset = (Vector2D)nearest.Position - dragitemposition; // Do not snap to grid! snapgrid = false; } } // Snap to grid? if (snapgrid) { // Move the dragged item dragitem.Move(dragitemposition + offset); // Snap item to grid dragitem.SnapToGrid(); // Adjust the offset offset += (Vector2D)dragitem.Position - (dragitemposition + offset); } // Make sure the offset is inside the map boundaries if (offset.x + tl.x < General.Map.FormatInterface.LeftBoundary) { offset.x = General.Map.FormatInterface.LeftBoundary - tl.x; } if (offset.x + br.x > General.Map.FormatInterface.RightBoundary) { offset.x = General.Map.FormatInterface.RightBoundary - br.x; } if (offset.y + tl.y > General.Map.FormatInterface.TopBoundary) { offset.y = General.Map.FormatInterface.TopBoundary - tl.y; } if (offset.y + br.y < General.Map.FormatInterface.BottomBoundary) { offset.y = General.Map.FormatInterface.BottomBoundary - br.y; } // Drag item moved? if (!snapgrid || ((Vector2D)dragitem.Position != oldpos)) { int i = 0; // Move selected geometry foreach (Thing t in selectedthings) { // Move vertex from old position relative to the // mouse position change since drag start t.Move(oldpositions[i] + offset); // Next i++; } // Moved return(true); } else { // No changes return(false); } }
public ListItem(MapSet imap) { map = imap; }
// Call this to zoom in on the given selection public void ZoomToObject() { List <Vector2D> points = new List <Vector2D>(); RectangleF area = MapSet.CreateEmptyArea(); // Add all points to a list foreach (MapElement obj in viewobjects) { if (obj is Vertex) { points.Add((obj as Vertex).Position); } else if (obj is Linedef) { points.Add((obj as Linedef).Start.Position); points.Add((obj as Linedef).End.Position); } else if (obj is Sidedef) { points.Add((obj as Sidedef).Line.Start.Position); points.Add((obj as Sidedef).Line.End.Position); } else if (obj is Sector) { Sector s = (obj as Sector); foreach (Sidedef sd in s.Sidedefs) { points.Add(sd.Line.Start.Position); points.Add(sd.Line.End.Position); } } else if (obj is Thing) { Thing t = (obj as Thing); Vector2D p = (Vector2D)t.Position; points.Add(p); points.Add(p + new Vector2D(t.Size * 2.0f, t.Size * 2.0f)); points.Add(p + new Vector2D(t.Size * 2.0f, -t.Size * 2.0f)); points.Add(p + new Vector2D(-t.Size * 2.0f, t.Size * 2.0f)); points.Add(p + new Vector2D(-t.Size * 2.0f, -t.Size * 2.0f)); } else { General.Fail("Unknown object given to zoom in on."); } } // Make a view area from the points foreach (Vector2D p in points) { area = MapSet.IncreaseArea(area, p); } // Make the area square, using the largest side if (area.Width > area.Height) { float delta = area.Width - area.Height; area.Y -= delta * 0.5f; area.Height += delta; } else { float delta = area.Height - area.Width; area.X -= delta * 0.5f; area.Width += delta; } // Add padding area.Inflate(100f, 100f); // Zoom to area ClassicMode editmode = (General.Editing.Mode as ClassicMode); editmode.CenterOnArea(area, 0.6f); }