public virtual void LoadBrushWithBackAsset(EditorBrush brush, Editor parent, string name, string type) { string extension = EditorHelpers.GetExtensionFromBrushType(type); // Objects and NPCs must always be a front asset if (!brush.NeedsBackAsset || extension == null || type == "object" || type == "npc") { return; } StarboundAsset asset = null; // Load the background tile if (parent.AssetMap.ContainsKey(name + extension)) { asset = parent.AssetMap[name + extension]; brush.BackAsset = asset; } else { // If this is an internal asset - liquids, etc // This is a hack to display liquids until liquid parsing has been implemented // (low priority) if (name == "lava") { asset = new StarboundTile(); asset.AssetName = name; asset.Image = EditorHelpers.GetGeneratedRectangle(8, 8, 207, 16, 32, 255); } else if (name == "acid") { asset = new StarboundTile(); asset.AssetName = name; asset.Image = EditorHelpers.GetGeneratedRectangle(8, 8, 107, 141, 63, 255); } else if (name == "water") { asset = new StarboundTile(); asset.AssetName = name; asset.Image = EditorHelpers.GetGeneratedRectangle(8, 8, 0, 78, 111, 255); } else if (name == "liquidtar" || name == "tentaclejuice") { asset = new StarboundTile(); asset.AssetName = name; asset.Image = EditorHelpers.GetGeneratedRectangle(8, 8, 200, 191, 231, 255); } // Else just load the asset else { asset = parent.LoadAsset(name, type); } if (asset != null) { parent.AssetMap[name + extension] = asset; brush.BackAsset = asset; } } }
public virtual void LoadBrushWithFrontAsset(EditorBrush brush, Editor parent, string name, string type) { string extension = EditorHelpers.GetExtensionFromBrushType(type); if (!brush.NeedsFrontAsset || extension == null) { return; } StarboundAsset asset = null; // Load the foreground tile if (parent.AssetMap.ContainsKey(name + extension)) { asset = parent.AssetMap[name + extension]; brush.FrontAsset = asset; } else { asset = parent.LoadAsset(name, type); if (asset != null) { parent.AssetMap[name + extension] = asset; brush.FrontAsset = asset; } } }
// This constructor populates a two dimensional list of brushes. // It does this by translating between the provided colour map and the collection of StarboundBrushes. // This layer contains the *raw* brush information as drawn on the colour map, // and is not responsible for any validity checking. // Also sets up the collision map public EditorMapLayer(string layerName, Bitmap colourMap, Dictionary <List <byte>, EditorBrush> brushMap, EditorMapPart parent) { m_parent = parent; ColourMap = colourMap; m_name = layerName; m_width = colourMap.Width; m_height = colourMap.Height; m_brushMap = new EditorBrush[m_width, m_height]; m_collisionMap = new HashSet <List <int> > [m_width, m_height]; List <CollisionObjectBrush> brushObjList = new List <CollisionObjectBrush>(); for (int x = 0; x < m_width; ++x) { for (int y = 0; y < m_height; ++y) { Color pixel = colourMap.GetPixel(x, y); EditorBrush brush = null; List <byte> rawPixelData = new List <byte> { pixel.R, pixel.G, pixel.B, pixel.A }; if (brushMap.ContainsKey(rawPixelData)) { brush = brushMap[rawPixelData]; m_brushMap[x, y] = brush; } if (brush != null && brush.FrontAsset != null && brush.FrontAsset is StarboundObject) { // Add the object brush to a list, to process after all other tiles var objBrush = new CollisionObjectBrush(); objBrush.m_brush = brush; objBrush.m_x = x; objBrush.m_y = y; brushObjList.Add(objBrush); } else { SetCollisionAt(brush, x, y); } } } parent.UpdateCompositeCollisionMap(); foreach (CollisionObjectBrush objBrush in brushObjList) { SetCollisionAt(objBrush.m_brush, objBrush.m_x, objBrush.m_y); } }
// Sets the brush at the located area and updates the affected colour map pixel public void SetBrushAt(EditorBrush brush, int x, int y, bool updateComposite) { if (x >= m_width || x < 0 || y >= m_height || y < 0) { return; } SetCollisionAt(brush, x, y, updateComposite); m_brushMap[x, y] = brush; var colourMapBmp = (Bitmap)ColourMap; Color newPixel = Color.FromArgb(brush.Colour[3], brush.Colour[0], brush.Colour[1], brush.Colour[2]); colourMapBmp.SetPixel(x, y, newPixel); m_changed = true; }
private void CleanUp() { MainPictureBox.SetImage(null, m_gridFactor); MainPictureBox.SetSelectedBrush(null); VisualGraphicBrushImageBox.Image = null; VisualRgbaBrushImageBox.Image = null; PartTreeView.Nodes.Clear(); BrushesTreeView.Nodes.Clear(); BottomBarBrushLabel.Text = ""; BottomBarPositionLabel.Text = "Grid: "; BottomBarZoomLabel.Text = "Zoom: "; m_brushNodeMap.Clear(); m_mapNodeMap.Clear(); m_parent.CleanUpResource(); m_selectedBrush = null; SelectedMap = null; RightPanelProperties.SelectedObject = null; // Update menu items, regardless of how we ended up here UpdateUndoRedoItems(); closeToolStripMenuItem.Enabled = false; saveToolStripMenuItem.Enabled = false; saveAsToolStripMenuItem.Enabled = false; // Force the garbage collector to clean up // But it won't do it until next file load because that would be too easy GC.Collect(); }
public void SetSelectedBrush(EditorBrush brush) { m_selectedBrush = brush; string colour = m_selectedBrush.Colour.ToString(); // Tidy this display up at some point BottomBarBrushLabel.Text = m_selectedBrush.Comment; if (m_selectedBrush.FrontAsset != null) { BottomBarBrushLabel.Text += " front: " + m_selectedBrush.FrontAsset.ToString(); } if (m_selectedBrush.BackAsset != null) { BottomBarBrushLabel.Text += " back: " + m_selectedBrush.BackAsset.ToString(); } BottomBarBrushLabel.Text += " " + colour; // Populate the colour box VisualRgbaBrushImageBox.Image = EditorHelpers.GetGeneratedRectangle(1, 1, m_selectedBrush.Colour.R, m_selectedBrush.Colour.G, m_selectedBrush.Colour.B, m_selectedBrush.Colour.A); VisualGraphicBrushImageBox.Image = m_selectedBrush.GetAssetPreview(); MainPictureBox.SetSelectedBrush(m_selectedBrush); UpdatePropertiesPanel(); }
public void RedrawCanvasFromBrush(EditorBrush oldBrush, EditorBrush newBrush, int gridX, int gridY) { EditorMapLayer activeLayer = GetActiveLayer(); // We need to selectively redraw here var additionalRedrawList = new HashSet<Vec2I>(); int xmin = gridX; int xmax = gridX+1; int ymin = gridY; int ymax = gridY+1; // If the old brush was an object, we must redraw around it if (oldBrush != null && oldBrush.FrontAsset is StarboundObject) { StarboundObject sbObject = (StarboundObject)oldBrush.FrontAsset; ObjectOrientation orientation = sbObject.GetCorrectOrientation(this, gridX, gridY, oldBrush.Direction); int sizeX = orientation.GetWidth(1, oldBrush.Direction); int sizeY = orientation.GetHeight(1, oldBrush.Direction); int originX = orientation.GetOriginX(1, oldBrush.Direction); int originY = orientation.GetOriginY(1, oldBrush.Direction); xmin = Math.Min(xmin, xmin + originX); xmax = Math.Max(xmax, xmax + sizeX + originX); ymin = Math.Min(ymin, ymin + originY); ymax = Math.Max(ymax, ymax + sizeY + originY); } // Extend the range of our bounds, so we encompass the old object, AND the new object if (newBrush != null && newBrush.FrontAsset is StarboundObject) { StarboundObject sbObject = (StarboundObject)newBrush.FrontAsset; ObjectOrientation orientation = sbObject.GetCorrectOrientation(this, gridX, gridY, newBrush.Direction); int sizeX = orientation.GetWidth(1, newBrush.Direction); int sizeY = orientation.GetHeight(1, newBrush.Direction); int originX = orientation.GetOriginX(1, newBrush.Direction); int originY = orientation.GetOriginY(1, newBrush.Direction); xmin = Math.Min(xmin, xmin + originX); xmax = Math.Max(xmax, xmax + sizeX + originX); ymin = Math.Min(ymin, ymin + originY); ymax = Math.Max(ymax, ymax + sizeY + originY); } // Accumulate a list of coordinates to redraw? for (int x = xmin; x < xmax; ++x) { for (int y = ymin; y < ymax; ++y) { HashSet<Vec2I> collisions = null; if (this is EditorMapPart) { collisions = activeLayer.Parent.GetCollisionsAt(x, y); } else if (this is EditorMapLayer) { collisions = activeLayer.GetCollisionsAt(x, y); } if (collisions == null) continue; foreach (var coords in collisions.Where(coords => (coords.x != x || coords.y != y) && (coords.x != gridX || coords.y != gridY))) { additionalRedrawList.Add(coords); } } } // Selectively redraw the composite image if (this is EditorMapPart) { activeLayer.Parent.UpdateLayerImageBetween(xmin, ymin, xmax, ymax); foreach (var coords in additionalRedrawList) { activeLayer.Parent.UpdateLayerImageBetween( coords.x, coords.y, coords.x + 1, coords.y + 1); } } // Only selectively redraw the active layer else if (this is EditorMapLayer) { activeLayer.Parent.UpdateLayerImageBetween( new List<EditorMapLayer> { activeLayer }, xmin, ymin, xmax, ymax); foreach (var coords in additionalRedrawList) { activeLayer.Parent.UpdateLayerImageBetween( new List<EditorMapLayer> { activeLayer }, coords.x, coords.y, coords.x + 1, coords.y + 1); } } }
public virtual void LoadBrushWithBackAsset(EditorBrush brush, Editor.Editor parent, string name, string type) { string extension = EditorHelpers.GetExtensionFromBrushType(type); // Objects and NPCs must always be a front asset if (!brush.NeedsBackAsset || extension == null || type == "object" || type == "npc") return; // Load the background tile StarboundAsset asset = parent.LoadAsset(name, type); if ( asset == null ) { // If this is an internal asset - liquids, etc // This is a hack to display liquids until liquid parsing has been implemented // (low priority) if (name == "lava") { asset = new StarboundAsset(); //asset.AssetName = name; asset.Image = EditorHelpers.GetGeneratedRectangle(8, 8, 207, 16, 32, 255); } else if (name == "acid") { asset = new StarboundAsset(); //asset.AssetName = name; asset.Image = EditorHelpers.GetGeneratedRectangle(8, 8, 107, 141, 63, 255); } else if (name == "water") { asset = new StarboundAsset(); //asset.AssetName = name; asset.Image = EditorHelpers.GetGeneratedRectangle(8, 8, 0, 78, 111, 255); } else if (name == "liquidtar" || name == "tentaclejuice") { asset = new StarboundAsset(); //asset.AssetName = name; asset.Image = EditorHelpers.GetGeneratedRectangle(8, 8, 200, 191, 231, 255); } //parent.RegisterAsset(name, type, asset); } if (asset != null) brush.BackAsset = asset; }
public virtual void LoadBrushWithFrontAsset(EditorBrush brush, Editor.Editor parent, string name, string type) { string extension = EditorHelpers.GetExtensionFromBrushType(type); if (!brush.NeedsFrontAsset || extension == null) return; // Load the foreground tile StarboundAsset asset = parent.LoadAsset(name, type); if (asset != null) brush.FrontAsset = asset; }
// Sets the brush as per SetBrushAt but triggers an action that can be stored in the Undo/Redo system public void SetUserBrushAt(EditorBrush brush, int x, int y, bool updateComposite = true) { EditorBrush oldBrush = GetBrushAt(x, y); m_undoManager.RegisterAction(oldBrush, brush, x, y); SetBrushAt(brush, x, y, updateComposite); }
// Sets the collision at the provided x- and y- coordinates to match the provided brush // Also handles removing old collisions if the brush is being replaced public void SetCollisionAt(EditorBrush brush, int x, int y, bool updateComposite = false) { // First, remove the old collision EditorBrush oldBrush = GetBrushAt(x, y); // Remove references based on size if the old brush was an object if (oldBrush != null && oldBrush.FrontAsset != null && oldBrush.FrontAsset is StarboundObject) { StarboundObject sbObject = (StarboundObject)oldBrush.FrontAsset; ObjectOrientation orientation = sbObject.GetCorrectOrientation(m_parent, x, y, brush.Direction); int sizeX = orientation.GetWidth(1, brush.Direction); int sizeY = orientation.GetHeight(1, brush.Direction); int originX = orientation.GetOriginX(1, brush.Direction); int originY = orientation.GetOriginY(1, brush.Direction); for (int j = originX + x; j < sizeX + originX + x; ++j) { for (int k = originY + y; k < sizeY + originY + y; ++k) { var objAnchorSet = GetCollisionsAt(j, k); if (objAnchorSet != null) { // Remove from the set if we have a match objAnchorSet.RemoveWhere(coord => coord.x == x && coord.y == y); } } } } // Else just remove the tile we're at else { var tileAnchorSet = GetCollisionsAt(x, y); if (tileAnchorSet != null) { // Remove from the set if we have a match tileAnchorSet.RemoveWhere(coord => coord.x == x && coord.y == y); } } // If this tile has a front component, continue if (brush != null && brush.FrontAsset != null) { // Collisions for objects based on size if (brush.FrontAsset is StarboundObject) { var sbObject = (StarboundObject) brush.FrontAsset; ObjectOrientation orientation = sbObject.GetCorrectOrientation(m_parent, x, y, brush.Direction); int sizeX = orientation.GetWidth(1, brush.Direction); int sizeY = orientation.GetHeight(1, brush.Direction); int originX = orientation.GetOriginX(1, brush.Direction); int originY = orientation.GetOriginY(1, brush.Direction); // Set the elements at j, k to point to the anchor at x, y for (int j = originX + x; j < sizeX + originX + x; ++j) { for (int k = originY + y; k < sizeY + originY + y; ++k) { AddCollisionAt(new Vec2I(x,y), j, k); } } } // Collisions for non-special front tiles else if (!brush.IsSpecial) { AddCollisionAt(new Vec2I(x,y), x, y); } } // Ship brushes have a special flag for things that block // foreground collisions if (brush is ShipBrush && ((ShipBrush) brush).ForegroundBlock) { AddCollisionAt(new Vec2I(x,y), x, y); } // If the update composite flag is set, rebuild // the composite collision map. if (updateComposite) { Parent.UpdateCompositeCollisionMap(); } }
// Sets the brush at the located area and updates the affected colour map pixel public void SetBrushAt(EditorBrush brush, int x, int y, bool updateComposite = false) { if (x >= m_width || x < 0 || y >= m_height || y < 0) return; SetCollisionAt(brush, x, y, updateComposite); m_brushMap[x, y] = brush; var colourMapBmp = (Bitmap) ColourMap; //Color newPixel = Color.FromArgb(brush.Colour[3], brush.Colour[0], brush.Colour[1], brush.Colour[2]); colourMapBmp.SetPixel(x, y, brush.Colour); m_changed = true; }
// Sets the collision at the provided x- and y- coordinates to match the provided brush // Also handles removing old collisions if the brush is being replaced public void SetCollisionAt(EditorBrush brush, int x, int y, bool updateComposite) { // First, remove the old collision EditorBrush oldBrush = GetBrushAt(x, y); // Remove references based on size if the old brush was an object if (oldBrush != null && oldBrush.FrontAsset != null && oldBrush.FrontAsset is StarboundObject) { StarboundObject sbObject = (StarboundObject)oldBrush.FrontAsset; ObjectOrientation orientation = sbObject.GetCorrectOrientation(m_parent, x, y); int sizeX = orientation.GetWidth(brush.Direction, 1); int sizeY = orientation.GetHeight(brush.Direction, 1); int originX = orientation.GetOriginX(brush.Direction, 1); int originY = orientation.GetOriginY(brush.Direction, 1); for (int j = originX + x; j < sizeX + originX + x; ++j) { for (int k = originY + y; k < sizeY + originY + y; ++k) { HashSet <List <int> > objAnchorSet = GetCollisionsAt(j, k); if (objAnchorSet != null) { // Remove from the set if we have a match objAnchorSet.RemoveWhere(coord => coord[0] == x && coord[1] == y); } } } } // Else just remove the tile we're at else { HashSet <List <int> > tileAnchorSet = GetCollisionsAt(x, y); if (tileAnchorSet != null) { // Remove from the set if we have a match tileAnchorSet.RemoveWhere(coord => coord[0] == x && coord[1] == y); } } // If this tile has a front component, continue if (brush != null && brush.FrontAsset != null) { // Collisions for objects based on size if (brush.FrontAsset is StarboundObject) { var sbObject = (StarboundObject)brush.FrontAsset; ObjectOrientation orientation = sbObject.GetCorrectOrientation(m_parent, x, y); int sizeX = orientation.GetWidth(brush.Direction, 1); int sizeY = orientation.GetHeight(brush.Direction, 1); int originX = orientation.GetOriginX(brush.Direction, 1); int originY = orientation.GetOriginY(brush.Direction, 1); // Set the elements at j, k to point to the anchor at x, y for (int j = originX + x; j < sizeX + originX + x; ++j) { for (int k = originY + y; k < sizeY + originY + y; ++k) { List <int> list = new List <int> { x, y }; AddCollisionAt(list, j, k); } } } // Collisions for non-special front tiles else if (!brush.IsSpecial) { List <int> list = new List <int> { x, y }; AddCollisionAt(list, x, y); } } // Ship brushes have a special flag for things that block // foreground collisions if (brush is ShipBrush && ((ShipBrush)brush).ForegroundBlock) { List <int> list = new List <int> { x, y }; AddCollisionAt(list, x, y); } // If the update composite flag is set, rebuild // the composite collision map. if (updateComposite) { Parent.UpdateCompositeCollisionMap(); } }
public void SetCollisionAt(EditorBrush brush, int x, int y) { SetCollisionAt(brush, x, y, false); }
// Registers an action that changes the map layer. // @TODO: have a BrushChanged for groups of tiles for later development (selection, copy pasta, user-defined doodads, etc) public void RegisterAction(EditorBrush before, EditorBrush after, int x, int y) { m_undoBuffer.RemoveRange(m_undoIndex, m_undoBuffer.Count - m_undoIndex); // Clear the redo buffer BrushChangeInfo info = new BrushChangeInfo(); info.m_brushBefore = before; info.m_brushAfter = after; info.m_x = x; info.m_y = y; m_undoIndex++; m_undoBuffer.Add(info); }
public void SetSelectedBrush(EditorBrush brush) { StarboundAsset asset = null; if (brush != null && brush.NeedsFrontAsset && brush.FrontAsset != null) { asset = brush.FrontAsset; } else if (brush != null && brush.NeedsBackAsset && brush.BackAsset != null) { asset = brush.BackAsset; } else { asset = new StarboundAsset(); //asset.AssetName = "gridAsset.INTERNAL"; asset.Image = EditorHelpers.GetGeneratedRectangle(8, 8, 255, 255, 255, 128); } m_selectedBrush = brush; m_selectedAsset = asset; Invalidate(); }
public void SetBrushAt(EditorBrush brush, int x, int y) { SetBrushAt(brush, x, y, false); }