Files
Main/Assets/Editor/DIY/AnimTitleEditor/AnimTitleEditor.cs

602 lines
22 KiB
C#
Raw Normal View History

2025-01-25 04:38:09 +08:00
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
public class AnimTitleEditor : EditorWindow
{
static void SaveTex(Camera camera, string outFile)
{
var renderTex = camera.RenderToTexture(Screen.width, Screen.height);
var tex = new Texture2D(Screen.width, Screen.height, TextureFormat.ARGB32, false);
RenderTexture.active = renderTex;
tex.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0, false);
tex.Apply();
var camTex = new Texture2D(Screen.width / 4, Screen.height / 4, TextureFormat.ARGB32, false);
for(int x = 0; x < camTex.width; ++x)
{
for(int y = 0; y < camTex.height; ++y)
{
var r = 0f;
var g = 0f;
var b = 0f;
var a = 0f;
for(int ox = 0; ox < 4; ++ox)
{
for(int oy = 0; oy < 4; ++oy)
{
var pix = tex.GetPixel(x * 4 + ox, y * 4 + oy);
r += pix.r;
g += pix.g;
b += pix.b;
a += pix.a;
}
}
var color = new Color(r / 16, g / 16, b / 16, a / 16);
camTex.SetPixel(x, y, color);
}
}
GameObject.DestroyImmediate(tex);
var alphaColor = new Color(0, 0, 0, 0);
var minX = camTex.width;
var minY = camTex.height;
var maxX = 0;
var maxY = 0;
for (int x = 0; x < camTex.width; ++x)
{
for (int y = 0; y < camTex.height; ++y)
{
var color = camTex.GetPixel(x, y);
if (color.r <= 0f && color.g <= 0f && color.b <= 0)
{
camTex.SetPixel(x, y, alphaColor);
}
else
{
if (x - 1 < minX)
{
minX = x - 1;
}
if (y - 1 < minY)
{
minY = y - 1;
}
if (x + 1 > maxX)
{
maxX = x + 1;
}
if (y + 1 > maxY)
{
maxY = y + 1;
}
}
}
}
var newTex = new Texture2D(maxX - minX, maxY - minY, TextureFormat.ARGB32, false);
for (int x = 0; x < newTex.width; ++x)
{
for (int y = 0; y < newTex.height; ++y)
{
newTex.SetPixel(x, y, camTex.GetPixel(x + minX, y + minY));
}
}
File.WriteAllBytes(outFile, newTex.EncodeToPNG());
camera.targetTexture = null;
GameObject.DestroyImmediate(camTex);
GameObject.DestroyImmediate(newTex);
}
[MenuItem("Ares/渲染摄像机家具图片")]
static void OutPutCameraJiaJuTexture()
{
var select = UnityEditor.Selection.activeGameObject;
if (select == null)
{
Debug.LogError("请选择有效的摄像机脚本");
return;
}
var camera = select.GetComponent<Camera>();
if (camera == null)
{
Debug.LogError("请选择有效的摄像机脚本");
return;
}
var renderPaths = new string[] {
"BigWall", "0", //大墙壁,不旋转
"MidWall", "0", //中墙壁,不旋转
"SamWall", "0", //小墙壁,不旋转
"ObjRoot", "1", //场景物件,旋转
};
var rootGo = GameObject.Find("JiaJuRender");
if(rootGo == null)
{
Debug.LogError("没有找到渲染对象 JiaJuRender Go");
return;
}
var rootTrans = rootGo.transform;
var outPath = EditorUtility.OpenFolderPanel("选择输出目录", "", "");
if (!string.IsNullOrEmpty(outPath))
{
for(int k = 0; k < renderPaths.Length / 2; ++k)
{
var path = renderPaths[k * 2];
var mode = renderPaths[k * 2 + 1];
var trans = rootTrans.Find(path);
trans.gameObject.SetActive(true);
for (int i = 0; i < trans.transform.childCount; ++i)
{
for (int j = 0; j < trans.transform.childCount; ++j)
{
var otherTrans = trans.transform.GetChild(j);
otherTrans.gameObject.SetActive(i == j);
}
var renderTrans = trans.transform.GetChild(i);
var forCount = 4;
if(mode == "0")
{
forCount = 1;
}
for (int index = 0; index < forCount; ++index)
{
var angles = renderTrans.localEulerAngles;
angles.y = index * 90f;
renderTrans.localEulerAngles = angles;
SaveTex(camera, string.Format("{0}/{1}_{2}.png", outPath, renderTrans.name, index * 90));
}
}
trans.gameObject.SetActive(false);
}
}
}
[MenuItem("Ares/特效称号3转2")]
static void Open()
{
var win = (AnimTitleEditor)EditorWindow.GetWindow(typeof(AnimTitleEditor));
win._isPlaying = false;
win.Show();
}
private int _texWidth = 256;
private int _texHeight = 128;
private float _cameraSize = 0.2f;
private float _maxTime = 1f;
private int _titleIndex = 1;
private string _outputPath = string.Empty;
private int _frameCount = 10;
private float _addAlphaThreshold = 0.7f;
private float _addAlphaScale = 0.5f;
private bool _isPlaying = false;
private GameObject _selectTarget = null;
private float _frontUpdateTime = 0f;
private float _playTimer = 0f;
private Camera _camera = null;
private List<Texture2D> _texList = new List<Texture2D>();
private RenderTexture _targetTexture = null;
private Vector3 _goOriPos = Vector3.zero;
private int _frontSimple = -1;
private Camera _copyCamera = null;
private List<Texture2D> _copyTexList = new List<Texture2D>();
private RenderTexture _copyTargetTexture = null;
private GameObject _copyTarget = null;
private List<Material> _copyMats = new List<Material>();
private List<Texture> _copyTex = new List<Texture>();
private void OnGUI()
{
EditorGUILayout.BeginVertical();
if (_isPlaying)
{
GUILayout.Label("正在渲染");
EditorGUILayout.Slider(_playTimer, 0f, _maxTime);
this.Focus();
}
else
{
_texWidth = EditorGUILayout.IntField("图片宽", _texWidth);
_texHeight = EditorGUILayout.IntField("图片高", _texHeight);
_cameraSize = EditorGUILayout.FloatField("摄像机size", _cameraSize);
_maxTime = EditorGUILayout.FloatField("录制时间", _maxTime);
_frameCount = EditorGUILayout.IntField("帧率(N帧/秒)", _frameCount);
_addAlphaThreshold = EditorGUILayout.FloatField("AddAlpha阀值", _addAlphaThreshold);
_addAlphaScale = EditorGUILayout.FloatField("AddAlpha阀值以下缩放", _addAlphaScale);
var selectObj = UnityEditor.Selection.gameObjects;
if (selectObj != null && selectObj.Length > 0 && _frameCount > 0)
{
GUILayout.Label(selectObj[0].name);
if (GUILayout.Button("开始录制", GUILayout.Width(50)))
{
StartPlay(selectObj[0]);
}
}
}
if (_texList.Count > 0)
{
_titleIndex = EditorGUILayout.IntField("图片索引", _titleIndex);
var rect = new Rect();
rect.size = new Vector2(_texWidth, _texHeight);
var count = (int)(this.position.width / (_texWidth + 10));
if (count <= 0)
{
count = 1;
}
for (int i = 0; i < _texList.Count; ++i)
{
rect.position = new Vector2(20 + i % count * (_texWidth + 10), 200 + i / count * (_texHeight + 30));
GUI.Box(rect, _texList[i]);
}
for (int i = 0; i < _copyTexList.Count; ++i)
{
int index = i + _texList.Count;
rect.position = new Vector2(20 + index % count * (_texWidth + 10), 200 + index / count * (_texHeight + 30));
GUI.Box(rect, _copyTexList[i]);
}
if (GUILayout.Button("导出", GUILayout.Width(50)))
{
_outputPath = EditorUtility.OpenFolderPanel("选择输出路径", _outputPath, "");
if (!string.IsNullOrEmpty(_outputPath))
{
for (int i = 0; i < _texList.Count; ++i)
{
MegreAlphaTex(_texList[i], _copyTexList[i]);
var bytes = _texList[i].EncodeToPNG();
var path = string.Format("{0}/{1}_{2}.png", _outputPath, _titleIndex, i);
File.WriteAllBytes(path, bytes);
}
}
}
}
EditorGUILayout.EndVertical();
}
private void StartPlay(GameObject targetGo)
{
Stop();
_isPlaying = true;
_selectTarget = targetGo;
_playTimer = 0f;
_goOriPos = _selectTarget.transform.position;
_selectTarget.transform.position = new Vector3(0f, 5000f, 0f);
var cameraGo = new GameObject("Camera");
cameraGo.transform.position = new Vector3(0f, 5000f, 0f);
_camera = cameraGo.RequireComponent<Camera>();
_camera.clearFlags = CameraClearFlags.SolidColor;
_camera.backgroundColor = new Color(0f, 0f, 0f, 1f);
_camera.useOcclusionCulling = false;
_camera.orthographic = true;
_camera.orthographicSize = _cameraSize;
_camera.nearClipPlane = -2000;
_camera.farClipPlane = 2000;
_camera.aspect = (float)_texWidth / _texHeight;
_targetTexture = RenderTexture.GetTemporary(_texWidth, _texHeight, 24, RenderTextureFormat.RGB565);
_targetTexture.antiAliasing = 1;
_camera.targetTexture = _targetTexture;
_frontSimple = -1;
_selectTarget.SetActive(false);
_selectTarget.SetActive(true);
for (int i = 0; i < _texList.Count; ++i)
{
//RenderTexture.ReleaseTemporary(_texList[i]);
GameObject.DestroyImmediate(_texList[i]);
}
_texList.Clear();
_selectTarget.SetActive(false);
PlayVfx(_selectTarget);
cameraGo = new GameObject("CopyCamera");
cameraGo.transform.position = new Vector3(0f, 10000f, 0f);
_copyCamera = cameraGo.RequireComponent<Camera>();
_copyCamera.clearFlags = CameraClearFlags.SolidColor;
_copyCamera.backgroundColor = new Color(0f, 0f, 0f, 1f);
_copyCamera.useOcclusionCulling = false;
_copyCamera.orthographic = true;
_copyCamera.orthographicSize = _cameraSize;
_copyCamera.nearClipPlane = -2000;
_copyCamera.farClipPlane = 2000;
_copyCamera.aspect = (float)_texWidth / _texHeight;
_copyTargetTexture = RenderTexture.GetTemporary(_texWidth, _texHeight, 24, RenderTextureFormat.RGB565);
_copyTargetTexture.antiAliasing = 1;
_copyCamera.targetTexture = _copyTargetTexture;
_copyTarget = GameObject.Instantiate(_selectTarget);
_copyTarget.transform.parent = _selectTarget.transform.parent;
_copyTarget.transform.localScale = _selectTarget.transform.localScale;
_copyTarget.transform.position = new Vector3(0f, 10000f, 0f);
var renders = _copyTarget.GetComponentsInChildren<Renderer>();
for (int i = 0; i < renders.Length; ++i)
{
if (renders[i].sharedMaterials != null && renders[i].sharedMaterials.Length > 0)
{
for (int j = 0; j < renders[i].sharedMaterials.Length; ++j)
{
var mat = renders[i].materials[j];
var texNames = mat.GetTexturePropertyNames();
var drawModel = 0;
var shaderName = mat.shader.name;
if (shaderName.Contains("Additive"))
{
//add模式
drawModel = 1;
}
else if (shaderName.Contains("AlphaBlend"))
{
//混合
drawModel = 0;
}
for (int k = 0; k < texNames.Length; ++k)
{
var tex = mat.GetTexture(texNames[k]) as Texture2D;
if (tex != null)
{
var haveAlpha = false;
var texPath = AssetDatabase.GetAssetPath(tex);
var mainIm = AssetImporter.GetAtPath(texPath) as TextureImporter;
if (mainIm != null)
{
mainIm.isReadable = true;
AssetDatabase.ImportAsset(texPath, ImportAssetOptions.ForceUpdate);
tex = AssetDatabase.LoadAssetAtPath(texPath, typeof(Texture2D)) as Texture2D;
haveAlpha = mainIm.DoesSourceTextureHaveAlpha();
}
var newTex = new Texture2D(tex.width, tex.height, TextureFormat.ARGB32, false);
newTex.wrapMode = tex.wrapMode;
CopyAlphaTex(tex, newTex, drawModel, haveAlpha);
mat.SetTexture(texNames[k], newTex);
_copyTex.Add(newTex);
//mainIm.isReadable = false;
//AssetDatabase.ImportAsset(texPath, ImportAssetOptions.ForceUpdate);
}
}
}
}
}
var uitexs = _copyTarget.GetComponentsInChildren<UITexture>();
for (int i = 0; i < uitexs.Length; ++i)
{
var tex = uitexs[i].mainTexture as Texture2D;
if (tex != null)
{
var haveAlpha = false;
var texPath = AssetDatabase.GetAssetPath(tex);
var mainIm = AssetImporter.GetAtPath(texPath) as TextureImporter;
if (mainIm != null)
{
mainIm.isReadable = true;
AssetDatabase.ImportAsset(texPath, ImportAssetOptions.ForceUpdate);
tex = AssetDatabase.LoadAssetAtPath(texPath, typeof(Texture2D)) as Texture2D;
haveAlpha = mainIm.DoesSourceTextureHaveAlpha();
}
var newTex = new Texture2D(tex.width, tex.height, TextureFormat.ARGB32, false);
newTex.wrapMode = tex.wrapMode;
uitexs[i].mainTexture = newTex;
CopyAlphaTex(tex, newTex, 0, haveAlpha);
_copyTex.Add(newTex);
//mainIm.isReadable = false;
//AssetDatabase.ImportAsset(texPath, ImportAssetOptions.ForceUpdate);
}
}
for (int i = 0; i < _copyTexList.Count; ++i)
{
//RenderTexture.ReleaseTemporary(_texList[i]);
GameObject.DestroyImmediate(_copyTexList[i]);
}
_copyTexList.Clear();
_frontUpdateTime = Time.realtimeSinceStartup;
PlayVfx(_copyTarget);
}
private void PlayVfx(GameObject go)
{
go.SetActive(true);
var _particles = go.GetComponentsInChildren<ParticleSystem>();
if (_particles != null)
{
for (int i = 0; i < _particles.Length; ++i)
{
_particles[i].Play();
}
}
var _animations = go.GetComponentsInChildren<Animation>();
if (_animations != null)
{
for (int i = 0; i < _animations.Length; ++i)
{
_animations[i].Play();
}
}
var _animators = go.GetComponentsInChildren<Animator>();
if (_animators != null)
{
for (int i = 0; i < _animators.Length; ++i)
{
AnimatorStateInfo animatorStateInfo = _animators[i].GetCurrentAnimatorStateInfo(0);
_animators[i].Play(animatorStateInfo.nameHash);
}
}
}
private void CopyAlphaTex(Texture2D src, Texture2D dest, int drawModel, bool haveAlpha)
{
for (int i = 0; i < src.width; ++i)
{
for (int j = 0; j < src.height; ++j)
{
var color = src.GetPixel(i, j);
if (drawModel == 0)
{
//混合
color.r = 1f;
color.g = 0f;
color.b = 0f;
}
else if (drawModel == 1)
{
//Add
if (haveAlpha)
{
if (color.a < _addAlphaThreshold)
{
color.r = color.a * _addAlphaScale;
}
else
{
color.r = 1f;
}
}
else
{
color.r = (color.r + color.g + color.b) / 3f;
}
//color.r = 1;
color.g = 0f;
color.b = 0f;
}
//color.a = 1f;
dest.SetPixel(i, j, color);
}
}
dest.Apply();
}
private void MegreAlphaTex(Texture2D colorTex, Texture2D alpha)
{
for (int i = 0; i < colorTex.width; ++i)
{
for (int j = 0; j < colorTex.height; ++j)
{
var color = colorTex.GetPixel(i, j);
if (color.r == 0 && color.g == 0 && color.b == 0 && color.a == 1)
{
color.a = 0f;
}
else
{
var colorA = alpha.GetPixel(i, j);
color.a = colorA.r;
}
colorTex.SetPixel(i, j, color);
}
}
colorTex.Apply();
}
private void Stop()
{
_isPlaying = false;
//for(int i = 0; i < _texList.Count; ++i)
//{
// GameObject.DestroyImmediate(_texList[i]);
//}
//_texList.Clear();
if (_camera != null)
{
GameObject.DestroyImmediate(_camera.gameObject);
}
if (_copyCamera != null)
{
GameObject.DestroyImmediate(_copyCamera.gameObject);
}
if (_targetTexture != null)
{
RenderTexture.ReleaseTemporary(_targetTexture);
_targetTexture = null;
}
if (_copyTargetTexture != null)
{
RenderTexture.ReleaseTemporary(_copyTargetTexture);
_copyTargetTexture = null;
}
if (_selectTarget != null)
{
_selectTarget.transform.position = _goOriPos;
_selectTarget = null;
}
if (_copyTarget != null)
{
GameObject.DestroyImmediate(_copyTarget);
_copyTarget = null;
}
for (int i = 0; i < _copyMats.Count; ++i)
{
GameObject.DestroyImmediate(_copyMats[i]);
}
_copyMats.Clear();
for (int i = 0; i < _copyTex.Count; ++i)
{
GameObject.DestroyImmediate(_copyTex[i]);
}
_copyTex.Clear();
}
//进行采样
private void Simple()
{
var _oriParts = _selectTarget.GetComponentsInChildren<ParticleSystem>();
var _copyParts = _copyTarget.GetComponentsInChildren<ParticleSystem>();
if (_oriParts != null)
{
for (int i = 0; i < _oriParts.Length; ++i)
{
var pats = new ParticleSystem.Particle[_oriParts[i].particleCount];
_oriParts[i].GetParticles(pats);
_copyParts[i].SetParticles(pats);
}
}
var tex = new Texture2D(_texWidth, _texHeight, TextureFormat.ARGB32, false);
_camera.Render();
RenderTexture.active = _targetTexture;
tex.ReadPixels(new Rect(0, 0, _texWidth, _texHeight), 0, 0, false);
tex.Apply();
_texList.Add(tex);
tex = new Texture2D(_texWidth, _texHeight, TextureFormat.ARGB32, false);
_copyCamera.Render();
RenderTexture.active = _copyTargetTexture;
tex.ReadPixels(new Rect(0, 0, _texWidth, _texHeight), 0, 0, false);
tex.Apply();
_copyTexList.Add(tex);
}
private void Update()
{
if (_isPlaying)
{
float frameTime = 1f / _frameCount;
float dt = Time.realtimeSinceStartup - _frontUpdateTime;
_frontUpdateTime = Time.realtimeSinceStartup;
var curFrame = (int)(_playTimer / frameTime);
if (_playTimer > 0f && curFrame > _frontSimple)
{
_frontSimple = curFrame;
Simple();
}
_playTimer += dt;
if (_playTimer >= _maxTime)
{
Stop();
}
}
}
}