public void DoStaticGroundConveyorRegion(MaskData conveyorRegion, int deltaX, int deltaZ) { for (int i = 0; i < moverCount; i++) { if (moverWeDoNotMove[i]) { continue; } int moverStartX = moverInitialPositions[i].X + moverCharacterPhysics[i].startX; int moverEndX = moverInitialPositions[i].X + moverCharacterPhysics[i].endX; int moverY = moverInitialPositions[i].Y; int moverZ = moverInitialPositions[i].Z; if (conveyorRegion.IsSetInXRange(moverStartX, moverEndX, moverZ)) { int groundHeight = GetGroundHeightInXRange(moverStartX, moverEndX, moverZ, moverY, moverY + moverCharacterPhysics[i].height, moverActors[i], staticOnly: true); if (moverY == groundHeight) // <- on the ground { CharacterPhysics.TryMoveHorizontalDidHitWall(ref moverCharacterPhysics[i], this, deltaX, deltaZ, true, ref moverActors[i].position, staticOnly: true); } } } }
public void DoStaticBlowerRegion(MaskData blowerRegion, int deltaX, int deltaZ, int startY, int endY) { for (int i = 0; i < moverCount; i++) { if (moverWeDoNotMove[i]) { continue; } int moverStartX = moverInitialPositions[i].X + moverCharacterPhysics[i].startX; int moverEndX = moverInitialPositions[i].X + moverCharacterPhysics[i].endX; int moverStartY = moverInitialPositions[i].Y; int moverEndY = moverStartY + moverCharacterPhysics[i].height; int moverZ = moverInitialPositions[i].Z; if (blowerRegion.IsSetInXRange(moverStartX, moverEndX, moverZ)) { int groundHeight = GetGroundHeightInXRange(moverStartX, moverEndX, moverZ, moverStartY, moverEndY, moverActors[i], staticOnly: true); bool onGround = (groundHeight == moverStartY); if (!(moverEndY < startY || moverStartY >= endY)) // <- in the blower's Y range { CharacterPhysics.TryMoveHorizontalDidHitWall(ref moverCharacterPhysics[i], this, deltaX, deltaZ, onGround, ref moverActors[i].position, staticOnly: true); } } } }
public Enumerator(GamePhysics owner, MaskData maskData) { this.owner = owner; this.maskData = maskData; this.current = null; this.nextIndex = 0; }
// NOTE: Rendering from world heightmap is slow!! // NOTE: Much copy-pasted code from normal heightmap rendering public void DrawWorldPhysicsXZRegion(WorldPhysics worldPhysics, MaskData xzMask, SortedList <int, Color> heightColorGradient) { // Constrain rendering to the display bounds int startX = Math.Max(worldPhysics.StartX, displayBounds.Left); int endX = Math.Min(worldPhysics.EndX, displayBounds.Right); if (endX <= startX) { return; // Off screen } for (int z = worldPhysics.EndZ - 1; z >= worldPhysics.StartZ; z--) // From back to front of heightmap { for (int x = startX; x < endX; x++) { if (!xzMask.GetOrDefault(x, z)) // TODO: Fix up bounds so we never leave this area (and use regular [,] access) - PERF { continue; } int height = worldPhysics.GetGroundHeightAt(x, z, WorldPhysics.MaximumHeight, WorldPhysics.MaximumHeight, null); if (height == WorldPhysics.MaximumHeight) { continue; } int nextHeight = 0; // Height of the next Z-value (row) if (xzMask.GetOrDefault(x, z - 1)) { nextHeight = worldPhysics.GetGroundHeightAt(x, z - 1, WorldPhysics.MaximumHeight, WorldPhysics.MaximumHeight, null); } if (nextHeight != WorldPhysics.MaximumHeight && nextHeight > height) { continue; // Next row will cover this one entirely } // Draw top surface const int zTestOffset = 1; // <- The top surface should be "under" any other pixels DrawPixel(new Position(x, height, z), heightColorGradient.GetColorFromGradient(height), zTestOffset); if (nextHeight != WorldPhysics.MaximumHeight && nextHeight == height) { continue; // Next row covers this one's "solid" section } // Draw solidness for (int h = height - 1; h >= 0; h--) { Color c = Color.Lerp(heightColorGradient.GetColorFromGradient(h), Color.Black, 0.6f); DrawPixel(new Position(x, h, z), c); } } } }
public static Data2D <Color> CreateColorData(this MaskData mask, Color color) { var data = new Data2D <Color>(mask.Bounds); for (var y = data.StartY; y < data.EndY; y++) { for (var x = data.StartX; x < data.EndX; x++) { data[x, y] = mask[x, y] ? color : Color.Transparent; } } return(data); }
private static MaskData processTextures(Texture2D diffuse, Texture2D mask, string exportFileName, bool lum, bool red, bool green, bool blue, bool alpha) { try { //skip if already exists //if (File.Exists("maskExport/" + exportFileName)) //{ // MonoBehaviour.print("Skipping export due to file already existing."); // return null; //} //because KSP loads textures as GPU only (no CPU side reads), blit the inputs to new Texture2Ds that can be read. //its a round-about process, but is probably the fastest way to make it work. //could also read the existing files from disk, again, and load them into Texture2D somehow, but I'm not sure //how it handles different file formats/etc. RenderTexture diffRendTex = new RenderTexture(diffuse.width, diffuse.height, 24, RenderTextureFormat.ARGB32); Graphics.Blit(diffuse, diffRendTex); Graphics.SetRenderTarget(diffRendTex); diffuse = new Texture2D(diffuse.width, diffuse.height, TextureFormat.ARGB32, false); diffuse.ReadPixels(new Rect(0, 0, diffuse.width, diffuse.height), 0, 0); diffuse.Apply(); RenderTexture maskRendTex = new RenderTexture(mask.width, mask.height, 24, RenderTextureFormat.ARGB32); Graphics.Blit(mask, maskRendTex); Graphics.SetRenderTarget(maskRendTex); mask = new Texture2D(mask.width, mask.height, TextureFormat.ARGB32, false); mask.ReadPixels(new Rect(0, 0, mask.width, mask.height), 0, 0); mask.Apply(); Graphics.SetRenderTarget(null); MaskData mData = new MaskData(mask); mData.processMaskCount(diffuse, lum, red, green, blue, alpha); Texture2D output = new Texture2D(diffuse.width, diffuse.height, TextureFormat.RGBA32, false); mData.writeOutputs(output); Directory.CreateDirectory("maskExport/"); byte[] bytes = output.EncodeToPNG(); File.WriteAllBytes("maskExport/" + exportFileName, bytes); GameObject.DestroyImmediate(output); GameObject.DestroyImmediate(diffuse); GameObject.DestroyImmediate(mask); GameObject.DestroyImmediate(diffRendTex); GameObject.DestroyImmediate(maskRendTex); return(mData); } catch (Exception e) { MonoBehaviour.print("EXCEPTION DURING MASK CREATION\n" + e); } return(null); }
//------------------------------------------------------------ // BitSet.TestAnyRange // /// <summary> /// Returns true iff any bits in the range [ibitMin, ibitLim) are set. /// </summary> /// <param name="ibitMin"></param> /// <param name="ibitLim"></param> /// <returns></returns> //------------------------------------------------------------ internal bool TestAnyRange(int ibitMin, int ibitLim) { DebugUtil.Assert(0 <= ibitMin && ibitMin <= ibitLim); int count = ibitLim - ibitMin; if (count == 1) { return(TestBit(ibitMin)); } if (count <= 0) { return(false); } if (!FInited()) { return(false); } MaskData md = new MaskData(ibitMin, ibitLim); uint blob; if (md.iblobMin >= this.blobList.Count) { return(false); } blob = this.blobList[md.iblobMin]; if ((blob & md.blobMaskMin) != 0) { return(true); } if (md.iblobLast >= this.blobList.Count) { md.iblobLast = this.blobList.Count; } else { blob = this.blobList[md.iblobLast]; if ((blob & md.blobMaskLast) != 0) { return(true); } } return(!AreBitsZero(this.blobList, md.iblobMin + 1, md.iblobLast - md.iblobMin - 1)); }
private static void process(DirectBitmap output) { //create value cache arrays, one for each of R,G,B in each of the input masks //track min and max for reach of R,G,B for each input mask //loop through input mask textures, aggregating values int len1 = maskMaps.Length; MaskData[] data = new MaskData[len1]; for (int i = 0; i < len1; i++) { data[i] = new MaskData(maskMaps[i]); data[i].processMaskCount(inputMap); data[i].writeOutputs(output); } }
/// <param name="celAlphaMasks">Fill with masks created from Cels</param> /// <param name="allMasks">Fill with all created masks</param> public void RegenerateAlphaMask() { masks.TryRemoveBaseFallBack(); // <- it is about to be regenerated // If this frame has a single sprite-containing Cel, generate it directly if (firstLayer != null && firstLayer.next == null) { Mask mask = new Mask { data = firstLayer.spriteRef.ResolveRequire().GetAlphaMask(), isGeneratedAlphaMask = true, }; masks.Add(new TagSet(), mask); } else // ... Otherwise, try to create a mask merged from the frame's layers { List <MaskData> layerMasks = new List <MaskData>(); foreach (var cel in layers) { MaskData maskData = cel.spriteRef.ResolveRequire().GetAlphaMask(); if (maskData.Width != 0 && maskData.Height != 0) { layerMasks.Add(maskData); } } Rectangle maxBounds = Rectangle.Empty; foreach (var maskData in layerMasks) { maxBounds = RectangleExtensions.UnionIgnoreEmpty(maxBounds, maskData.Bounds); } Mask mask = new Mask() { isGeneratedAlphaMask = true }; mask.data = new MaskData(maxBounds); foreach (var layerMask in layerMasks) { Debug.Assert(!Asserts.enabled || mask.data.Bounds.Contains(layerMask.Bounds)); mask.data.SetBitwiseOrFrom(layerMask); } masks.Add(new TagSet(), mask); } }
public void Save(BinaryReverseWriter reverseWriter) { Debug.WriteLine("Layer Save started at " + reverseWriter.BaseStream.Position.ToString(CultureInfo.InvariantCulture)); reverseWriter.Write(Rect.Top); reverseWriter.Write(Rect.Left); reverseWriter.Write(Rect.Bottom); reverseWriter.Write(Rect.Right); reverseWriter.Write((Int16)Channels.Count); foreach (Channel ch in Channels) { ch.Save(reverseWriter); } const String signature = "8BIM"; reverseWriter.Write(signature.ToCharArray()); reverseWriter.Write(_blendModeKeyStr.ToCharArray()); reverseWriter.Write(Opacity); reverseWriter.Write((Byte)(Clipping ? 1 : 0)); reverseWriter.Write((Byte)_flags.Data); reverseWriter.Write((Byte)0); using (new LengthWriter(reverseWriter)) { MaskData.Save(reverseWriter); BlendingRangesData.Save(reverseWriter); Int64 namePosition = reverseWriter.BaseStream.Position; reverseWriter.WritePascalString(Name); Int32 paddingBytes = (int)((reverseWriter.BaseStream.Position - namePosition) % 4); Debug.Print("Layer {0} write padding bytes after name", paddingBytes); for (Int32 i = 0; i < paddingBytes; i++) { reverseWriter.Write((Byte)0); } foreach (AdjusmentLayerInfo info in AdjustmentInfo) { info.Save(reverseWriter); } } }
/// <summary>Deserialize into new object instance</summary> public Mask(AnimationDeserializeContext context) { if (context.Version < 37) { context.br.ReadNullableString(); // was friendly name } isGeneratedAlphaMask = context.br.ReadBoolean(); if (context.customMaskDataReader != null) { // NOTE: Matches MaskData deserializing constructor: var rect = context.br.ReadRectangle(); data = new MaskData(context.customMaskDataReader.Read(MaskData.WidthToDataWidth(rect.Width) * rect.Height), rect); } else { data = new MaskData(context.br, context.fastReadHack); } }
/// <summary>Convert color data to a trimmed 1-bit mask</summary> public static MaskData CreateMask(this Data2D <Color> data, Color color, bool inverse = false) { Rectangle trimBounds = data.FindTrimBounds(color, inverse); // TODO: Avoid this copy... Data2D <Color> trimData = data.CopyWithNewBounds(trimBounds); MaskData mask = new MaskData(trimData.Bounds); for (int y = trimData.StartY; y < trimData.EndY; y++) { for (int x = trimData.StartX; x < trimData.EndX; x++) { mask[x, y] = ((trimData[x, y] == color) != inverse); } } return(mask); }
protected void Deserialize(LevelDeserializeContext context) { mask = new MaskData(context.br, context.FastReadHack); if (context.Version >= 15) { startY = context.br.ReadInt32(); endY = context.br.ReadInt32(); if (context.Version < 17 && endY != beforeVersion17WorldPhysicsMaximumHeight) { endY++; // <- Old version had an inclusive upper bound } } else { startY = 0; endY = WorldPhysics.MaximumHeight; } regionIndex = context.nextRegionIndex++; }
public MoverInMaskEnumerable GetAllMoversInMask(MaskData maskData) { return(new MoverInMaskEnumerable(this, maskData)); }
public MoverInMaskEnumerable(GamePhysics owner, MaskData maskData) { this.owner = owner; this.maskData = maskData; }