Files
ScienceLab.FrictionForce/Assets/Scripts/ChalkDrawer.cs
2026-05-29 18:30:19 +03:00

192 lines
5.4 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ChalkDrawer : MonoBehaviour
{
[SerializeField] private Camera _camera;
[SerializeField] private RenderTexture _boardTexture;
[SerializeField] private float _brushSize = 0.02f;
[SerializeField] private float _eraserSize = 0.05f;
[SerializeField] private Color _chalkColor = Color.white;
[SerializeField] private float _holdDistance = 1.5f;
[SerializeField] private float _followSpeed = 12f;
public bool IsHoldingChalk => _holdingChalk;
private bool _holdingChalk = false;
private bool _isErasing = false;
private GameObject _chalkObject = null;
private Rigidbody _chalkRb = null;
private Collider _chalkCollider = null;
private Texture2D _drawTexture;
private bool _textureReady = false;
private Vector3 _originalPosition;
private void Start()
{
InitTexture();
}
private void InitTexture()
{
if (_boardTexture == null) return;
_drawTexture = new Texture2D(_boardTexture.width, _boardTexture.height, TextureFormat.RGBA32, false);
Color[] pixels = new Color[_boardTexture.width * _boardTexture.height];
for (int i = 0; i < pixels.Length; i++)
pixels[i] = Color.black;
_drawTexture.SetPixels(pixels);
_drawTexture.Apply();
Graphics.Blit(_drawTexture, _boardTexture);
GameObject board = GameObject.FindGameObjectWithTag("Board");
if (board != null)
{
MeshRenderer boardRenderer = board.GetComponent<MeshRenderer>();
if (boardRenderer != null)
boardRenderer.material.mainTexture = _boardTexture;
}
_textureReady = true;
}
private void Update()
{
if (!_holdingChalk) return;
HandleHolding();
HandleDrawing();
if (Input.GetMouseButtonDown(1))
DropChalk();
}
public void PickupChalk(GameObject chalk)
{
_originalPosition = chalk.transform.position;
_chalkObject = chalk;
_chalkRb = chalk.GetComponent<Rigidbody>();
_chalkCollider = chalk.GetComponent<Collider>();
if (_chalkRb != null)
{
_chalkRb.useGravity = false;
_chalkRb.velocity = Vector3.zero;
_chalkRb.angularVelocity = Vector3.zero;
}
if (_chalkCollider != null)
_chalkCollider.enabled = false;
_isErasing = false;
_holdingChalk = true;
}
public void PickupTowel(GameObject towel)
{
_originalPosition = towel.transform.position;
_chalkObject = towel;
_chalkRb = towel.GetComponent<Rigidbody>();
_chalkCollider = towel.GetComponent<Collider>();
if (_chalkRb != null)
{
_chalkRb.useGravity = false;
_chalkRb.velocity = Vector3.zero;
_chalkRb.angularVelocity = Vector3.zero;
}
if (_chalkCollider != null)
_chalkCollider.enabled = false;
_isErasing = true;
_holdingChalk = true;
}
private void HandleHolding()
{
if (_chalkObject == null) return;
Ray ray = _camera.ScreenPointToRay(Input.mousePosition);
Vector3 targetPos = ray.origin + ray.direction * _holdDistance;
_chalkObject.transform.position = Vector3.Lerp(
_chalkObject.transform.position,
targetPos,
Time.deltaTime * _followSpeed
);
}
private void HandleDrawing()
{
if (!_textureReady) return;
if (Input.GetMouseButton(0))
{
Ray ray = _camera.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit))
{
if (hit.collider.CompareTag("Board"))
DrawOnTexture(hit.textureCoord);
}
}
}
private void DrawOnTexture(Vector2 uv)
{
Color paintColor = _isErasing ? Color.black : _chalkColor;
float size = _isErasing ? _eraserSize : _brushSize;
int x = (int)(uv.x * _drawTexture.width);
int y = (int)(uv.y * _drawTexture.height);
int radius = Mathf.Max(1, (int)(size * _drawTexture.width));
for (int i = -radius; i <= radius; i++)
{
for (int j = -radius; j <= radius; j++)
{
if (i * i + j * j <= radius * radius)
{
int px = Mathf.Clamp(x + i, 0, _drawTexture.width - 1);
int py = Mathf.Clamp(y + j, 0, _drawTexture.height - 1);
_drawTexture.SetPixel(px, py, paintColor);
}
}
}
_drawTexture.Apply();
Graphics.Blit(_drawTexture, _boardTexture);
}
private void DropChalk()
{
if (_chalkObject == null) return;
if (_chalkRb != null)
{
_chalkRb.useGravity = false;
_chalkRb.velocity = Vector3.zero;
_chalkRb.angularVelocity = Vector3.zero;
}
_chalkObject.transform.position = _originalPosition;
if (_chalkRb != null)
{
_chalkRb.useGravity = true;
_chalkRb.WakeUp();
}
if (_chalkCollider != null)
_chalkCollider.enabled = true;
_holdingChalk = false;
_isErasing = false;
_chalkObject = null;
_chalkRb = null;
_chalkCollider = null;
}
}