diff --git a/Assets/Art/UIPrefab/UIDraw.prefab b/Assets/Art/UIPrefab/UIDraw.prefab index c6a18998..dbc3e5dc 100644 --- a/Assets/Art/UIPrefab/UIDraw.prefab +++ b/Assets/Art/UIPrefab/UIDraw.prefab @@ -187,6 +187,7 @@ MonoBehaviour: m_EditorClassIdentifier: captureBGImg: {fileID: 1613795782999759057} RawImg: {fileID: 3350589312635769069} + TempImg: {fileID: 0} Content: {fileID: 6174875567737795578} ClearBtn: {fileID: 2761790485595999517} BackBtn: {fileID: 8433557736356431636} diff --git a/Assets/Draw/Scripts/ScreenShotPainter.cs b/Assets/Draw/Scripts/ScreenShotPainter.cs index dd7dc443..35346780 100644 --- a/Assets/Draw/Scripts/ScreenShotPainter.cs +++ b/Assets/Draw/Scripts/ScreenShotPainter.cs @@ -3,9 +3,12 @@ using System; using System.Collections; using System.Collections.Generic; using System.Net; +using System.Security.Cryptography; +using UnityEditor.Rendering; using UnityEngine; using UnityEngine.Events; using UnityEngine.EventSystems; +using UnityEngine.Rendering; using UnityEngine.UI; using static UnityEditor.Progress; @@ -14,14 +17,14 @@ public class ScreenShotPainter : MonoBehaviour { public class LineSegment { - public List Points { get; set; } + public RenderTexture Texture { get; set; } public Color Color { get; set; } public float Width { get; set; } public bool IsEraser { get; set; } public LineSegment(Color color, float width, bool isEraser) { - Points = new List(); + Texture = RenderTexture.GetTemporary(Screen.width, Screen.height, 24); Color = color; Width = width; IsEraser = isEraser; @@ -44,11 +47,11 @@ public class ScreenShotPainter : MonoBehaviour /// /// 涂鸦的RenderTexture图片 /// - private RenderTexture _blitRenderTexture; + private RenderTexture _currentRenderTexture; /// /// 涂鸦的RenderTexture图片 /// - private RenderTexture _tempRenderTexture; + //private RenderTexture _historyRenderTexture; /// /// 截图灰化背景图 /// @@ -229,6 +232,14 @@ public class ScreenShotPainter : MonoBehaviour bool isInited = false; Status status = Status.Pen; + + + private CommandBuffer _commandBuffer; + + + private float _lastPaintTime; + private float _paintInterval = 0.02f; // 每0.02秒绘制一次 + void Awake() { instance = this; @@ -239,6 +250,9 @@ public class ScreenShotPainter : MonoBehaviour if (isInited == false) { isInited = true; + _commandBuffer = new CommandBuffer(); + _commandBuffer.name = "PaintCommandBuffer"; + _bgRawImage = bgRawImg; _paintCanvasImg = drawImg; @@ -274,13 +288,12 @@ public class ScreenShotPainter : MonoBehaviour _eraserBrushMat.SetFloat("_SizeY", _eraserSize * (float)_screenHeight / (float)_screenWidth); - _tempRenderTexture = RenderTexture.GetTemporary(_screenWidth, _screenHeight, 24); - _blitRenderTexture = RenderTexture.GetTemporary(_screenWidth, _screenHeight, 24); - _paintCanvasImg.texture = _blitRenderTexture; + _currentRenderTexture = RenderTexture.GetTemporary(_screenWidth, _screenHeight, 24); + _paintCanvasImg.texture = _currentRenderTexture; // 激活渲染纹理,确保它可以被写入 - RenderTexture.active = _blitRenderTexture; + RenderTexture.active = _currentRenderTexture; GL.Clear(true, true, Color.clear); //给画布添加事件 @@ -306,7 +319,7 @@ public class ScreenShotPainter : MonoBehaviour paintEventTrigger.triggers.Add(beginDrawEntry); // 使用 Graphics.Blit 清除渲染纹理 - Graphics.Blit(null, _blitRenderTexture, _clearBrushMat); + Graphics.Blit(null, _currentRenderTexture, _clearBrushMat); // 恢复默认的渲染纹理 RenderTexture.active = null; @@ -338,7 +351,7 @@ public class ScreenShotPainter : MonoBehaviour _leftDownConnerPoint = Vector2.zero; _rightUpConnerPoint = Vector2.zero; _rightDownConnerPoint = Vector2.zero; - _blitRenderTexture.Release(); + _currentRenderTexture.Release(); _bgRawImage.material.SetVector("_Rect", new Vector4(0, 0, 0, 0)); _eraserFlag = false; //Graphics.Blit(_blitRenderTexture, _blitRenderTexture, _clearBrushMat); //清除一下 @@ -458,11 +471,12 @@ public class ScreenShotPainter : MonoBehaviour void OnPostRender() { + Debug.LogError(" OnPostRender"); if (!enabled) return; if (_drawRegionRect) { - + Debug.LogError("111"); //如果材质球不存在 if (!_lineMaterial) { @@ -555,7 +569,7 @@ public class ScreenShotPainter : MonoBehaviour #endif //Texture2D CombineTex = new Texture2D(_renderTex.width, _renderTex.height, TextureFormat.ARGB32, false); RenderTexture prev = RenderTexture.active; - RenderTexture.active = _blitRenderTexture; + RenderTexture.active = _currentRenderTexture; Texture2D BliTexture2D = new Texture2D((int)width, (int)height, TextureFormat.ARGB32, false); @@ -613,7 +627,6 @@ public class ScreenShotPainter : MonoBehaviour case Status.Pen: break; case Status.Line: - case Status.Rect: if (Input.GetMouseButton(0)) { @@ -621,24 +634,18 @@ public class ScreenShotPainter : MonoBehaviour { _currentLine = new LineSegment(_paintBrushMat.GetColor("_Color"), _brushSize, _eraserFlag); } - _currentLine.Points.Add(Input.mousePosition); LerpPaint(Input.mousePosition, _eraserFlag); } break; case Status.Circle: - - if (_currentLine == null) - { - if (_currentLine == null) - { - _currentLine = new LineSegment(_paintBrushMat.GetColor("_Color"), _brushSize, _eraserFlag); - } - _lastPoint = Input.mousePosition; - } - - + _currentLine = new LineSegment(_paintBrushMat.GetColor("_Color"), _brushSize, _eraserFlag); + _lastPoint = Input.mousePosition; + break; + case Status.Rect: + fixedPoint = Input.mousePosition; + prePoint = fixedPoint; break; } } @@ -650,52 +657,59 @@ public class ScreenShotPainter : MonoBehaviour ChangeToEraser(this.status == Status.Eraser); } + Vector2 fixedPoint = default; + Vector2 prePoint = default; + bool needUndo = false; private void PaintDragging(BaseEventData data) { if (_enabled && _haveRegion) { - if (Input.GetMouseButton(0)) + if (Input.GetMouseButton(0) && Time.time - _lastPaintTime > _paintInterval) { - switch (status) + _lastPaintTime = Time.time; + // 绘制逻辑 + if (Input.GetMouseButton(0)) { - case Status.Pen: - case Status.Eraser: - - - if (_currentLine == null) - { - _currentLine = new LineSegment(_paintBrushMat.GetColor("_Color"), _brushSize, _eraserFlag); - } - _currentLine.Points.Add(Input.mousePosition); - LerpPaint(Input.mousePosition, _eraserFlag); - - - break; - //case Status.Line: - // if (_currentLine != null) - // { - // if (_currentLine.Points.Count <= 0) - // { - // _currentLine.Points.Add(Input.mousePosition); - // LerpPaint(Input.mousePosition, false); - // } - // } - // break; - //case Status.Rect: - // if (_currentLine != null) - // { - // if (_currentLine.Points.Count <= 0) - // { - // _currentLine.Points.Add(Input.mousePosition); - // LerpPaint(Input.mousePosition, false); - // } - // } - // break; + switch (status) + { + case Status.Pen: + case Status.Eraser: + if (_currentLine == null) + { + _currentLine = new LineSegment(_paintBrushMat.GetColor("_Color"), _brushSize, _eraserFlag); + } + LerpPaint(Input.mousePosition, _eraserFlag); + break; + case Status.Rect: + if (needUndo) + { + if (_lineStack.Count > 0) + { + Undo(); + } + else + { + Clear(); + } + needUndo = false; + } + if (Vector2.Distance(prePoint, Input.mousePosition) > 1) + { + prePoint = Input.mousePosition; + _currentLine = new LineSegment(_paintBrushMat.GetColor("_Color"), _brushSize, _eraserFlag); + _lastPoint = fixedPoint; + RectFactory(); + needUndo = true; + } + break; + } } } } } + + private void OnPaintEndDrag(BaseEventData data) { if (_enabled && _haveRegion) @@ -708,56 +722,40 @@ public class ScreenShotPainter : MonoBehaviour { FinishedRaw(); } - break; + case Status.Line: if (_currentLine != null) { - _currentLine.Points.Add(Input.mousePosition); LerpPaint(Input.mousePosition, false); + FinishedRaw(); - } - break; + case Status.Rect: - { - if (_currentLine != null) - { - var points = GenerateRectanglePoints(_lastPoint, Input.mousePosition); - - - - _currentLine.Points.Add(points[1]); - LerpPaint(points[1], false); - _currentLine.Points.Add(Input.mousePosition); - LerpPaint(Input.mousePosition, false); - _currentLine.Points.Add(points[2]); - LerpPaint(points[2], false); - - _currentLine.Points.Add(_lastPoint); - LerpPaint(points[0], false); - - FinishedRaw(); - - } - } + fixedPoint = default; + needUndo = false; break; + case Status.Circle: + if (_currentLine != null) { float radius = Vector2.Distance(_lastPoint, Input.mousePosition); var points = GenerateCirclePoints(_lastPoint, radius); _lastPoint = default; + foreach (var item in points) { - _currentLine.Points.Add(item); LerpPaint(item, false); } - _currentLine.Points.Add(points[0]); LerpPaint(points[0], false); FinishedRaw(); + + } break; + default: break; } @@ -777,40 +775,57 @@ public class ScreenShotPainter : MonoBehaviour } return points; } - Vector2[] GenerateRectanglePoints(Vector2 start, Vector2 end) + + public void RectFactory() + { + if (_lastPoint != default) + { + var points = GenerateRectanglePoints(_lastPoint, Input.mousePosition); + + LerpPaint(points[0], false); + LerpPaint(points[1], false); + LerpPaint(points[2], false); + LerpPaint(points[3], false); + LerpPaint(points[0], false); + FinishedRaw(); + } + } + + public Vector2[] GenerateRectanglePoints(Vector2 start, Vector2 thirdPoint) { Vector2[] points = new Vector2[4]; points[0] = start; - points[3] = end; + // 原本的 end 点(这里用 thirdPoint 替代)作为数组的第三个元素 + points[2] = thirdPoint; - if (start.x < end.x) + if (start.x < thirdPoint.x) { - if (start.y < end.y) + if (start.y < thirdPoint.y) { // 从左下方到右上方 - points[1] = new Vector2(end.x, start.y); - points[2] = new Vector2(start.x, end.y); + points[1] = new Vector2(thirdPoint.x, start.y); + points[3] = new Vector2(start.x, thirdPoint.y); } else { // 从左上方到右下方 - points[1] = new Vector2(end.x, start.y); - points[2] = new Vector2(start.x, end.y); + points[1] = new Vector2(thirdPoint.x, start.y); + points[3] = new Vector2(start.x, thirdPoint.y); } } else { - if (start.y < end.y) + if (start.y < thirdPoint.y) { // 从右下方到左上方 - points[1] = new Vector2(start.x, end.y); - points[2] = new Vector2(end.x, start.y); + points[1] = new Vector2(start.x, thirdPoint.y); + points[3] = new Vector2(thirdPoint.x, start.y); } else { // 从右上方到左下方 - points[1] = new Vector2(start.x, end.y); - points[2] = new Vector2(end.x, start.y); + points[1] = new Vector2(start.x, thirdPoint.y); + points[3] = new Vector2(thirdPoint.x, start.y); } } @@ -820,56 +835,64 @@ public class ScreenShotPainter : MonoBehaviour public void FinishedRaw() { - if (_currentLine != null) { + // 保存当前纹理到 LineSegment + RenderTexture.active = _currentLine.Texture; + Graphics.Blit(_currentRenderTexture, _currentLine.Texture); + RenderTexture.active = null; + _lineStack.Push(_currentLine); + _paintCanvasImg.texture = _currentLine.Texture; _currentLine = null; } - _lastPoint = Vector2.zero; - } + _lastPoint = Vector2.zero; + + } public void Undo() { if (_lineStack.Count > 0) { - Clear(); - // 移除最后一条线 var line = _lineStack.Pop(); - //重新绘制所有剩余的线条 - foreach (var item in _lineStack) + // 如果栈中还有剩余的线条,切换到上一个线条的纹理 + if (_lineStack.Count > 0) { - - _paintBrushMat.SetColor("_Color", item.Color); - foreach (var point in item.Points) - { - LerpPaint(point, item.IsEraser); - } - _lastPoint = Vector2.zero; + var previousLine = _lineStack.Peek(); + RenderTexture.active = _currentRenderTexture; + Graphics.Blit(previousLine.Texture, _currentRenderTexture); + RenderTexture.active = null; + _paintCanvasImg.texture = previousLine.Texture; + } + else + { + Clear(); } } } public void Clear() { - _blitRenderTexture = RenderTexture.GetTemporary(_screenWidth, _screenHeight, 24); - _tempRenderTexture = RenderTexture.GetTemporary(_screenWidth, _screenHeight, 24); + // 重新分配 RenderTexture + _currentRenderTexture = RenderTexture.GetTemporary(_screenWidth, _screenHeight, 24); - _paintCanvasImg.texture = _blitRenderTexture; + // 更新画布的纹理 + _paintCanvasImg.texture = _currentRenderTexture; + + // 清空线条栈 _lineStack.Clear(); } - - /// /// 绘画进行插值 /// /// + Vector2[] vector2s = new Vector2[10000]; private void LerpPaint(Vector2 point, bool isEraser) { - Paint(point, isEraser); + Paint(isEraser, point); if (_lastPoint == Vector2.zero) { @@ -881,42 +904,41 @@ public class ScreenShotPainter : MonoBehaviour if (dis > _brushLerpSize) { Vector2 dir = (point - _lastPoint).normalized; - int num = (int)(dis / _brushLerpSize); + int num = (int)(dis / (_brushLerpSize)); for (int i = 0; i < num; i++) { - Vector2 newPoint = _lastPoint + dir * (i + 1) * _brushLerpSize; - Paint(newPoint, isEraser); + vector2s[i] = _lastPoint + dir * (i + 1) * _brushLerpSize; + Paint(isEraser, vector2s[i]); } + Debug.LogError(num); } _lastPoint = point; } // 画点方法 - private void Paint(Vector2 point, bool isDraser) + private void Paint(bool isEraser, Vector2 point) { + Material material = null; if (point.x < _leftDownConnerPoint.x || point.x > _rightUpConnerPoint.x || point.y < _leftDownConnerPoint.y || point.y > _rightUpConnerPoint.y) return; + Vector2 uv = new Vector2(point.x / (float)_screenWidth, point.y / (float)_screenHeight); - Vector2 uv = new Vector2(point.x / (float)_screenWidth, - point.y / (float)_screenHeight); - - if (isDraser) + if (isEraser) { _eraserBrushMat.SetVector("_UV", uv); - // 先将源纹理内容渲染到临时纹理 - Graphics.Blit(_blitRenderTexture, _tempRenderTexture, _eraserBrushMat); - // 再将临时纹理内容复制回源纹理 - Graphics.Blit(_tempRenderTexture, _blitRenderTexture); + material = _eraserBrushMat; } else { _paintBrushMat.SetVector("_UV", uv); - // 先将源纹理内容渲染到临时纹理 - Graphics.Blit(_blitRenderTexture, _tempRenderTexture, _paintBrushMat); - // 再将临时纹理内容复制回源纹理 - Graphics.Blit(_tempRenderTexture, _blitRenderTexture); + material = _paintBrushMat; } - } + + _commandBuffer.Blit(_currentRenderTexture, _currentRenderTexture, material); + + Graphics.ExecuteCommandBuffer(_commandBuffer); + _commandBuffer.Clear(); + } public Vector2 GetCaptureViewLeftDownConnerPoint() { Vector2 vec = new Vector2(Mathf.Min(_startPoint.x, _endPoint.x), Mathf.Min(_startPoint.y, _endPoint.y)); @@ -1003,7 +1025,7 @@ public class ScreenShotPainter : MonoBehaviour _drawRegionRect = false; _haveRegion = false; _haveCirmformRectStarPoint = false; - _blitRenderTexture.Release(); + _currentRenderTexture.Release(); _startPoint = Vector2.zero; _endPoint = Vector2.zero; _leftUpConnerPoint = Vector2.zero; diff --git a/Assets/Scripts/UI/UIDraw.Designer.cs b/Assets/Scripts/UI/UIDraw.Designer.cs index 19a40dba..6e3578b2 100644 --- a/Assets/Scripts/UI/UIDraw.Designer.cs +++ b/Assets/Scripts/UI/UIDraw.Designer.cs @@ -5,7 +5,7 @@ using QFramework; namespace QFramework.Example { - // Generate Id:4d840482-3ece-436e-9579-de5573072430 + // Generate Id:f3b60a04-6dce-45f6-968a-cb101a31a0c9 public partial class UIDraw { public const string Name = "UIDraw";