Files
BH3/Assets/Scripts/Assembly-CSharp/MoleMole/WeaponIconMaker.cs
2025-09-11 15:00:19 +08:00

398 lines
12 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace MoleMole
{
[ExecuteInEditMode]
public class WeaponIconMaker : MonoBehaviour
{
public enum WeaponType
{
Cannon = 0,
Katana = 1,
Pistol = 2
}
private static readonly string LONG_SWORD_NAME = "LongSword";
private static readonly string SHORT_SWORD_NAME = "ShortSword";
private static readonly string LEFT_PISTOL_NAME = "LeftPistol";
private static readonly string RIGHT_PISTOL_NAME = "RightPistol";
private static readonly string CLONE_SUFFIX = "(Clone)";
private static readonly string BOUNDING_NAME = "Bounding";
private static readonly string[] TYPE_PREFIX = new string[3] { "Weapon_Cannon", "Weapon_Katana", "Weapon_Pistol" };
public int imageSize = 512;
[Range(1f, 179f)]
public float fov = 20f;
public WeaponType weaponType;
public bool wholeForKatana;
public Camera mainCamera;
public Camera cannonCamera;
public Camera katanaCamera;
public Camera pistolCamera;
public Transform cannonHolder;
public Transform longSwordHolder;
public Transform shortSwordHolder;
public Transform leftPistolHolder;
public Transform rightPistolHolder;
private GameObject _weaponObj;
private List<GameObject> _objList;
public string outputPath;
private PostFX _postFX;
private string _weaponName
{
get
{
if (_weaponObj != null)
{
return TrimSuffix(_weaponObj.name, CLONE_SUFFIX);
}
return null;
}
}
private void Awake()
{
_objList = new List<GameObject>();
_postFX = mainCamera.GetComponent<PostFX>();
}
public string Load(string srcPath)
{
return _load(srcPath);
}
public string Generate()
{
return _generate();
}
private string _load(string srcPath)
{
Screen.SetResolution(imageSize, imageSize, false);
GameObject gameObject = Miscs.LoadResource<GameObject>(srcPath);
if (gameObject == null)
{
return "Fail to load prefab at " + srcPath;
}
foreach (GameObject obj in _objList)
{
if (obj != null)
{
UnityEngine.Object.DestroyImmediate(obj);
}
}
_objList.Clear();
_weaponObj = UnityEngine.Object.Instantiate(gameObject);
string text = CheckType();
if (!string.IsNullOrEmpty(text))
{
return text;
}
ClearTransform(_weaponObj);
_objList.Add(_weaponObj);
if (weaponType == WeaponType.Cannon)
{
mainCamera.CopyFrom(cannonCamera);
_weaponObj.transform.SetParent(cannonHolder, false);
ClearTransform(_weaponObj);
AdjustTransform(_weaponObj, cannonHolder.Find(BOUNDING_NAME).gameObject);
_weaponObj.transform.SetParent(null);
SetCannonMaterial(_weaponObj);
}
else if (weaponType == WeaponType.Katana)
{
mainCamera.CopyFrom(katanaCamera);
GameObject gameObject2 = _weaponObj.transform.Find(LONG_SWORD_NAME).gameObject;
GameObject gameObject3 = _weaponObj.transform.Find(SHORT_SWORD_NAME).gameObject;
if (gameObject2 == null || gameObject3 == null)
{
return "Sword missing";
}
gameObject2.transform.SetParent(longSwordHolder, false);
ClearTransform(gameObject2);
if (wholeForKatana)
{
AdjustTransform(gameObject2, longSwordHolder.Find(BOUNDING_NAME).gameObject);
}
gameObject2.transform.SetParent(_weaponObj.transform);
gameObject3.transform.SetParent(shortSwordHolder, false);
ClearTransform(gameObject3);
if (wholeForKatana)
{
AdjustTransform(gameObject3, longSwordHolder.Find(BOUNDING_NAME).gameObject);
}
gameObject3.transform.SetParent(_weaponObj.transform);
SetKatanaMaterial(_weaponObj);
}
else
{
mainCamera.CopyFrom(pistolCamera);
GameObject gameObject4 = _weaponObj.transform.Find(LEFT_PISTOL_NAME).gameObject;
GameObject gameObject5 = _weaponObj.transform.Find(RIGHT_PISTOL_NAME).gameObject;
if (gameObject4 == null || gameObject5 == null)
{
return "Missing pistol";
}
gameObject4.transform.SetParent(leftPistolHolder, false);
ClearTransform(gameObject4);
AdjustTransform(gameObject4, leftPistolHolder.Find(BOUNDING_NAME).gameObject);
gameObject4.transform.SetParent(_weaponObj.transform);
gameObject5.transform.SetParent(rightPistolHolder, false);
ClearTransform(gameObject5);
AdjustTransform(gameObject5, rightPistolHolder.Find(BOUNDING_NAME).gameObject);
gameObject5.transform.SetParent(_weaponObj.transform);
SetPistolMaterial(_weaponObj);
}
fov = mainCamera.fieldOfView;
return null;
}
private string _generate()
{
if (_weaponObj == null)
{
return "Please load prefab first";
}
if (weaponType == WeaponType.Cannon)
{
SaveImage(_weaponName);
}
else if (weaponType == WeaponType.Katana)
{
GameObject gameObject = _weaponObj.transform.Find(LONG_SWORD_NAME).gameObject;
GameObject gameObject2 = _weaponObj.transform.Find(SHORT_SWORD_NAME).gameObject;
if (gameObject == null || gameObject2 == null)
{
return "Sword missing";
}
gameObject.SetActive(true);
gameObject2.SetActive(false);
SaveImage(_weaponName + "_" + LONG_SWORD_NAME);
gameObject.SetActive(false);
gameObject2.SetActive(true);
SaveImage(_weaponName + "_" + SHORT_SWORD_NAME);
gameObject.SetActive(true);
gameObject2.SetActive(true);
}
else
{
GameObject gameObject3 = _weaponObj.transform.Find(LEFT_PISTOL_NAME).gameObject;
GameObject gameObject4 = _weaponObj.transform.Find(RIGHT_PISTOL_NAME).gameObject;
if (gameObject3 == null || gameObject4 == null)
{
return "Missing pistol";
}
gameObject3.SetActive(true);
gameObject4.SetActive(false);
SaveImage(_weaponName + "_" + LEFT_PISTOL_NAME);
gameObject3.SetActive(false);
gameObject4.SetActive(true);
SaveImage(_weaponName + "_" + RIGHT_PISTOL_NAME);
gameObject3.SetActive(true);
gameObject4.SetActive(true);
SaveImage(_weaponName);
}
return null;
}
private void SetCannonMaterial(GameObject obj)
{
Renderer[] componentsInChildren = obj.GetComponentsInChildren<Renderer>(true);
foreach (Renderer renderer in componentsInChildren)
{
Material[] materials = renderer.materials;
foreach (Material material in materials)
{
if (material.HasProperty("_ColorTransFactor"))
{
material.SetFloat("_ColorTransFactor", 1f);
}
if (material.HasProperty("_Opaqueness"))
{
material.SetFloat("_Opaqueness", 1f);
}
}
}
}
private void SetPistolMaterial(GameObject obj)
{
Renderer[] componentsInChildren = obj.GetComponentsInChildren<Renderer>(true);
foreach (Renderer renderer in componentsInChildren)
{
for (int j = 0; j < renderer.materials.Length; j++)
{
renderer.materials[j] = new Material(renderer.materials[j]);
renderer.materials[j].name += "(Instance)";
}
}
}
private void SetKatanaMaterial(GameObject obj)
{
Renderer[] componentsInChildren = obj.GetComponentsInChildren<Renderer>(true);
foreach (Renderer renderer in componentsInChildren)
{
for (int j = 0; j < renderer.materials.Length; j++)
{
renderer.materials[j] = new Material(renderer.materials[j]);
renderer.materials[j].name += "(Instance)";
}
}
}
private void MakeSingle(GameObject obj, Transform holder, bool needAdjust = false)
{
_objList.Add(obj);
obj.transform.SetParent(holder, false);
ClearTransform(obj);
if (needAdjust)
{
AdjustTransform(obj, holder.Find(BOUNDING_NAME).gameObject);
}
}
private Rect GetBoundsInScreen(GameObject obj, ref float xMinZ)
{
Rect result = default(Rect);
bool flag = true;
MeshFilter[] componentsInChildren = obj.GetComponentsInChildren<MeshFilter>(true);
foreach (MeshFilter meshFilter in componentsInChildren)
{
Mesh sharedMesh = meshFilter.sharedMesh;
for (int j = 0; j < sharedMesh.vertexCount; j++)
{
Vector3 position = sharedMesh.vertices[j];
Vector3 vector = mainCamera.WorldToScreenPoint(meshFilter.transform.TransformPoint(position));
if (flag)
{
result.min = vector;
result.max = vector;
xMinZ = vector.z;
flag = false;
continue;
}
if (result.xMin > vector.x)
{
result.xMin = vector.x;
xMinZ = vector.z;
}
result.xMax = Mathf.Max(result.xMax, vector.x);
result.yMin = Mathf.Min(result.yMin, vector.y);
result.yMax = Mathf.Max(result.yMax, vector.y);
}
}
return result;
}
private void AdjustTransform(GameObject obj, GameObject boundObj)
{
float xMinZ = 0f;
Rect boundsInScreen = GetBoundsInScreen(boundObj, ref xMinZ);
Rect boundsInScreen2 = GetBoundsInScreen(obj, ref xMinZ);
Vector3 position = new Vector3(boundsInScreen2.xMin, boundsInScreen2.center.y, xMinZ);
Vector3 position2 = new Vector3(boundsInScreen.xMin, boundsInScreen.center.y, xMinZ);
obj.transform.position += mainCamera.ScreenToWorldPoint(position2) - mainCamera.ScreenToWorldPoint(position);
boundsInScreen2 = GetBoundsInScreen(obj, ref xMinZ);
float num = ((!(boundsInScreen2.width / boundsInScreen2.height < boundsInScreen.width / boundsInScreen.height)) ? (boundsInScreen.width / boundsInScreen2.width) : (boundsInScreen.height / boundsInScreen2.height));
obj.transform.SetLocalScaleX(num);
obj.transform.SetLocalScaleY(num);
obj.transform.SetLocalScaleZ(num);
boundsInScreen2 = GetBoundsInScreen(obj, ref xMinZ);
position = new Vector3(boundsInScreen2.xMin, boundsInScreen2.center.y, xMinZ);
obj.transform.position += mainCamera.ScreenToWorldPoint(position2) - mainCamera.ScreenToWorldPoint(position);
}
public void SetFOV(float targetFOV)
{
Vector3 position = _weaponObj.transform.position;
position = mainCamera.worldToCameraMatrix.MultiplyPoint(position);
float num = Mathf.Tan(mainCamera.fieldOfView * ((float)Math.PI / 180f) * 0.5f);
float num2 = Mathf.Tan(targetFOV * ((float)Math.PI / 180f) * 0.5f);
position.z *= num / num2;
position = mainCamera.cameraToWorldMatrix.MultiplyPoint(position);
_weaponObj.transform.position = position;
mainCamera.fieldOfView = targetFOV;
}
private string CheckType()
{
for (int i = 0; i < TYPE_PREFIX.Length; i++)
{
if (_weaponName.StartsWith(TYPE_PREFIX[i]))
{
weaponType = (WeaponType)i;
return null;
}
}
return "Invalid weapon type";
}
private static void ClearTransform(GameObject obj)
{
obj.transform.localPosition = Vector3.zero;
obj.transform.localScale = Vector3.one;
obj.transform.localRotation = Quaternion.identity;
}
private IEnumerator _waitForEndOfFrame()
{
yield return new WaitForEndOfFrame();
}
private static string TrimSuffix(string s, string suffix)
{
if (s.EndsWith(suffix))
{
return s.Substring(0, s.Length - suffix.Length);
}
return s;
}
private void SaveImage(string fileName)
{
RenderTextureWrapper renderTexture = GraphicsUtils.GetRenderTexture(imageSize, imageSize, 0, RenderTextureFormat.ARGB32);
mainCamera.targetTexture = renderTexture;
_postFX.WriteAlpha = true;
mainCamera.Render();
_postFX.WriteAlpha = false;
mainCamera.targetTexture = null;
RenderTexture.active = renderTexture;
Texture2D texture2D = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.ARGB32, false);
texture2D.ReadPixels(new Rect(0f, 0f, renderTexture.width, renderTexture.height), 0, 0);
texture2D.Apply();
byte[] bytes = texture2D.EncodeToPNG();
File.WriteAllBytes(string.Format("{0}/{1}.png", outputPath, fileName), bytes);
UnityEngine.Object.Destroy(texture2D);
GraphicsUtils.ReleaseRenderTexture(renderTexture);
}
}
}