private void UpdateTimer(object sender, EventArgs e) { if (Mode == AnimationMode.Spin) { if (MoveMultiplier < 1.0f) { MoveMultiplier += _moveAcceleration; } else { MoveMultiplier = 1.0f; } } else if (Mode != AnimationMode.Idle) { _autoMoveCurrent += _autoMoveStep; // Allow timer to overflow for 2 subsequent frames, so we // get finalizing 1.0 value at all times if (_autoMoveCurrent >= 1.0f + (_autoMoveStep * 2)) { Stop(true); } else { var newMultiplier = MathC.SmoothStep(0.0, 1.0, _autoMoveCurrent); MoveMultiplier = (float)MathC.Clamp(newMultiplier, 0.0, 1.0); } } else { Stop(true); } }
private void ChangeColorByMouse(MouseEventArgs e) { if (e.Button == MouseButtons.Left) { Focus(); _selectedColorCoord = new Point((int)MathC.Clamp((e.X / _paletteCellWidth), 0, PaletteSize.Width - 1), (int)MathC.Clamp((e.Y / _paletteCellHeight), 0, PaletteSize.Height - 1)); if (_editor.SelectedObject is LightInstance) { var light = _editor.SelectedObject as LightInstance; if (!(_editor.Level.Settings.GameVersion.Legacy() <= TRVersion.Game.TR4 && light.Type == LightType.FogBulb)) { light.Color = SelectedColor.ToFloat3Color() * 2.0f; light.Room.RebuildLighting(_editor.Configuration.Rendering3D_HighQualityLightPreview); _editor.ObjectChange(light, ObjectChangeType.Change); } } else if (_editor.SelectedObject is StaticInstance) { var instance = _editor.SelectedObject as StaticInstance; instance.Color = SelectedColor.ToFloat3Color() * 2.0f; _editor.ObjectChange(instance, ObjectChangeType.Change); } else if (_editor.Level.Settings.GameVersion == TRVersion.Game.TR5Main && _editor.SelectedObject is MoveableInstance) { var instance = _editor.SelectedObject as MoveableInstance; instance.Color = SelectedColor.ToFloat3Color() * 2.0f; _editor.ObjectChange(instance, ObjectChangeType.Change); } _editor.LastUsedPaletteColourChange(SelectedColor); Invalidate(); } }
public UndoManager(int undoDepth) { undoDepth = MathC.Clamp(undoDepth, 1, MaxUndoDepth); _undoStack = new UndoRedoStack(undoDepth); _redoStack = new UndoRedoStack(undoDepth); }
public SectorSelection?ClampToRoom(Room r, Direction?excludeBorderWallsDirection = Direction.None) { int[] c = new int[2] { 0, 0 }; // How many blocks to cut from compared area zone perimeter bool excludeAll = !excludeBorderWallsDirection.HasValue; if (excludeAll || excludeBorderWallsDirection.Value == Direction.NegativeX || excludeBorderWallsDirection.Value == Direction.PositiveX) { if ((Start.Y == 0 || Start.Y == r.NumZSectors - 1) && Area.Size.Y == 0) { return(null); } c[0] = 1; } if (excludeAll || excludeBorderWallsDirection.Value == Direction.NegativeZ || excludeBorderWallsDirection.Value == Direction.PositiveZ) { if ((Start.X == 0 || Start.X == r.NumXSectors - 1) && Area.Size.X == 0) { return(null); } c[1] = 1; } return(new SectorSelection() { Start = new VectorInt2(MathC.Clamp(Start.X, c[1], r.NumXSectors - (1 + c[1])), MathC.Clamp(Start.Y, c[0], r.NumZSectors - (1 + c[0]))), End = new VectorInt2(MathC.Clamp(End.X, c[1], r.NumXSectors - (1 + c[1])), MathC.Clamp(End.Y, c[0], r.NumZSectors - (1 + c[0]))) }); }
public static Color ToWinFormsColor(this Vector4 color, float?alpha = null) { return(Color.FromArgb( (int)Math.Max(0, Math.Min(255, Math.Round((alpha.HasValue ? MathC.Clamp(alpha.Value, 0.0, 1.0) : color.W) * 255.0f))), (int)Math.Max(0, Math.Min(255, Math.Round(color.X * 255.0f))), (int)Math.Max(0, Math.Min(255, Math.Round(color.Y * 255.0f))), (int)Math.Max(0, Math.Min(255, Math.Round(color.Z * 255.0f))))); }
public void Emboss(int xStart, int yStart, int width, int height, int weight, int size) { size = MathC.Clamp(size, 2, 8); int[,] kernel = new int[size, size]; kernel[0, 0] = -1; kernel[size - 1, size - 1] = 1; ApplyKernel(xStart, yStart, width, height, weight, kernel); }
public void Resize(int newSize) { if (newSize == _undoStack.Count) { return; } newSize = MathC.Clamp(newSize, 1, MaxUndoDepth); _undoStack.Resize(newSize); _redoStack.Resize(newSize); UndoStackChanged?.Invoke(this, new EventArgs()); }
protected Vector4 ApplyColorTransform(Vector4 color) { // Clamp each value separately to prevent overflows which are possible because TE doesn't internally // clamp its vertex lighting to 2.0f. color.X = MathC.Clamp(color.X, 0.0f, 2.0f); color.Y = MathC.Clamp(color.Y, 0.0f, 2.0f); color.Z = MathC.Clamp(color.Z, 0.0f, 2.0f); color.W = MathC.Clamp(color.W, 0.0f, 1.0f); return(new Vector4(color.X / 2.0f, color.Y / 2.0f, color.Z / 2.0f, color.W)); }
public void ApplyKernel(int xStart, int yStart, int width, int height, int weight, int[,] kernel) { ImageC oldImage = new ImageC(width, height, new byte[width * height * 4]); oldImage.CopyFrom(0, 0, this, xStart, yStart, width, height); int kernel_width = kernel.GetUpperBound(0) + 1; int kernel_height = kernel.GetUpperBound(1) + 1; for (int x = 0, xReal = xStart; x < width; x++, xReal++) { for (int y = 0, yReal = yStart; y < height; y++, yReal++) { int r = 0, g = 0, b = 0; for (int dx = 0; dx < kernel_width; dx++) { for (int dy = 0; dy < kernel_height; dy++) { int sourceX = MathC.Clamp(x + dx, 0, width - 1); int sourceY = MathC.Clamp(y + dy, 0, height - 1); ColorC clr = oldImage.GetPixel(sourceX, sourceY); r += (int)clr.R * kernel[dx, dy]; g += (int)clr.G * kernel[dx, dy]; b += (int)clr.B * kernel[dx, dy]; } } r = MathC.Clamp((int)(127 + r / weight), 0, 255); g = MathC.Clamp((int)(127 + g / weight), 0, 255); b = MathC.Clamp((int)(127 + b / weight), 0, 255); SetPixel(xReal, yReal, new ColorC((byte)r, (byte)g, (byte)b)); } } // Restore alpha for (int x = 0, xReal = xStart; x < width; x++, xReal++) { for (int y = 0, yReal = yStart; y < height; y++, yReal++) { var alpha = oldImage.GetPixel(xReal, yReal).A; var color = GetPixel(xReal, yReal); color.A = alpha; SetPixel(xReal, yReal, color); } } }
void AddMessage(float?progress, string message, bool isWarning) { if (!(bool)Invoke((Func <bool>) delegate { if (progress.HasValue) { pbStato.Value = (int)Math.Round(MathC.Clamp(progress.Value, 0, 100), 0); TaskbarProgress.SetValue(Application.OpenForms[0].Handle, progress.Value, 100); } if (!string.IsNullOrEmpty(message)) { lstLog.SelectionBackColor = isWarning ? Color.Yellow.Multiply(Colors.Brightness) : Color.Empty; lstLog.AppendText(message + "\n"); lstLog.ScrollToCaret(); } return(!_threadShouldAbort); })) { throw new OperationCanceledException(); } }
private static byte[] PackTextureMap32To16BitDithered(byte[] textureData, int pageSize) { // Stucki dithering matrix, it produces better result than Floyd-Steinberg // with gradients var ditherMatrix = new byte[, ] { { 0, 0, 0, 8, 4 }, { 2, 4, 8, 4, 2 }, { 1, 2, 4, 2, 1 } }; var seed = new Random(31459); int pixelCount = textureData.Length / 4; var height = pixelCount / pageSize; byte[] newTextureData = new byte[pixelCount * 2]; for (int i = 0; i < pixelCount; i++) { int r1 = textureData[i * 4 + 2]; int g1 = textureData[i * 4 + 1]; int b1 = textureData[i * 4 + 0]; int r2 = (byte)(r1 >> 3) << 3; int g2 = (byte)(g1 >> 3) << 3; int b2 = (byte)(b1 >> 3) << 3; int rE = r1 - r2; int bE = g1 - g2; int gE = b1 - b2; for (int row = 0; row < 3; row++) { int offsetY = (i / pageSize) + row; for (int col = 0; col < 5; col++) { int coefficient = ditherMatrix[row, col]; int offsetX = (i % pageSize) + (col - 4); if (coefficient != 0 && offsetX >= 0 && offsetX < pageSize && offsetY >= 0 && offsetY < height) { // Add some noise to coefficient to reduce banding float finalCoeff = 42 - (seed.Next(0, 15)); int offsetIndex = (offsetY * pageSize + offsetX) * 4; int newR = (int)((rE * coefficient) / finalCoeff); int newG = (int)((gE * coefficient) / finalCoeff); int newB = (int)((bE * coefficient) / finalCoeff); byte a = (byte)MathC.Clamp((textureData[offsetIndex + 3]), 0, 255); byte r = (byte)MathC.Clamp((textureData[offsetIndex + 2] + newR), 0, 255); byte g = (byte)MathC.Clamp((textureData[offsetIndex + 1] + newG), 0, 255); byte b = (byte)MathC.Clamp((textureData[offsetIndex + 0] + newB), 0, 255); if (r < 8 || a == 0) { r = 0; } if (g < 8 || a == 0) { g = 0; } if (b < 8 || a == 0) { b = 0; } if (a > 0 && a < 255) { // Convert true alpha to brightness with slight noise to prevent banding a -= (byte)seed.Next(0, MathC.Clamp((255 - a) / 20, 0, a)); r = (byte)(r * (a / 255.0f)); g = (byte)(g * (a / 255.0f)); b = (byte)(b * (a / 255.0f)); } r /= 8; g /= 8; b /= 8; ushort tmp = 0; if (r == 255 && g == 255 && b == 255) { tmp = 0xffff; } else { tmp |= (ushort)(a == 0 ? 0 : 0x8000); tmp |= (ushort)(r << 10); tmp |= (ushort)(g << 5); tmp |= (ushort)b; } newTextureData[offsetIndex / 2] = (byte)((tmp & 0x00ff)); newTextureData[offsetIndex / 2 + 1] = (byte)((tmp & 0xff00) >> 8); } } } } return(newTextureData); }
public static uint CompressColor(Vector3 color, float alpha = 1.0f, bool average = true) { float multiplier = average ? 128.0f : 255.0f; color = Vector3.Max(new Vector3(), Vector3.Min(new Vector3(255.0f), color * multiplier + new Vector3(0.5f))); return(((uint)color.X) | (((uint)color.Y) << 8) | (((uint)color.Z) << 16) | ((uint)(MathC.Clamp(alpha, 0, 1) * 255.0f) << 24)); }
private void WriteNgChunkAnimatedTextures(BinaryWriter writer) { var startOfChunk = writer.BaseStream.Position; writer.Write((ushort)0); writer.Write((ushort)0x8002); // Count number of textures with UVRotate writer.Write((byte)0x01); writer.Write(checked ((byte)_textureInfoManager.UvRotateCount)); writer.Write((short)_textureInfoManager.AnimatedTextures.Count); // Array VetInfoRangeAnim for (var i = 0; i < 40; i++) { if (i >= _textureInfoManager.AnimatedTextures.Count) { writer.Write((short)0); } else { var param = (ushort)0; var set = _textureInfoManager.AnimatedTextures[i].Key; switch (set.AnimationType) { case AnimatedTextureAnimationType.Frames: param |= (ushort)MathC.Clamp(Math.Round(1000.0f / (set.Fps == 0 ? 16 : set.Fps)), 0, 0x1fff); break; case AnimatedTextureAnimationType.PFrames: param = 0x4000; break; case AnimatedTextureAnimationType.UVRotate: param = 0x8000; param |= (ushort)(set.Fps > 31 ? 0 : (int)MathC.Clamp(Math.Round(set.Fps), 0, 0x1F) << 8); // 0 means 'MAX FPS' param |= (ushort)(set.UvRotate & 0x00FF); break; case AnimatedTextureAnimationType.RiverRotate: param = 0xA000; param |= (ushort)(set.Fps > 31 ? 0 : (int)MathC.Clamp(Math.Round(set.Fps), 0, 0x1F) << 8); // 0 means 'MAX FPS' param |= (ushort)(set.UvRotate & 0x00FF); break; case AnimatedTextureAnimationType.HalfRotate: param = 0xC000; param |= (ushort)(set.Fps > 31 ? 0 : (int)MathC.Clamp(Math.Round(set.Fps), 0, 0x1F) << 8); // 0 means 'MAX FPS' param |= (ushort)(set.UvRotate & 0x00FF); break; default: throw new NotSupportedException("Unsupported NG animation type encountered."); } writer.Write(param); } } // Array VetFromTex for (var i = 0; i < 40; i++) { if (i >= _textureInfoManager.AnimatedTextures.Count) { writer.Write((short)0); } else { var set = _textureInfoManager.AnimatedTextures[i]; writer.Write(_remappedTiles[set.Value.First()]); } } // Array VetToTex for (var i = 0; i < 40; i++) { if (i >= _textureInfoManager.AnimatedTextures.Count) { writer.Write((short)0); } else { var set = _textureInfoManager.AnimatedTextures[i]; writer.Write(_remappedTiles[set.Value.Last()]); } } var sizeDefault = (short)64; writer.Write(sizeDefault); var endOfChunk = writer.BaseStream.Position; var numWords = (endOfChunk - startOfChunk) / 2; writer.Seek((int)startOfChunk, SeekOrigin.Begin); writer.Write((ushort)numWords); writer.Seek((int)endOfChunk, SeekOrigin.Begin); }