EnvironmentManager.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using UnityEngine;
  5. using Object = UnityEngine.Object;
  6. namespace COM3D2.MeidoPhotoStudio.Plugin
  7. {
  8. using Input = InputManager;
  9. using UInput = Input;
  10. public class EnvironmentManager : IManager, ISerializable
  11. {
  12. private static readonly BgMgr bgMgr = GameMain.Instance.BgMgr;
  13. private static readonly CameraMain mainCamera = CameraUtility.MainCamera;
  14. private static readonly UltimateOrbitCamera ultimateOrbitCamera = CameraUtility.UOCamera;
  15. public const string header = "ENVIRONMENT";
  16. public const string defaultBg = "Theater";
  17. private const string myRoomPrefix = "マイルーム:";
  18. private static bool cubeActive;
  19. public static bool CubeActive
  20. {
  21. get => cubeActive;
  22. set
  23. {
  24. if (value == cubeActive) return;
  25. cubeActive = value;
  26. CubeActiveChange?.Invoke(null, EventArgs.Empty);
  27. }
  28. }
  29. private static bool cubeSmall;
  30. public static bool CubeSmall
  31. {
  32. get => cubeSmall;
  33. set
  34. {
  35. if (value == cubeSmall) return;
  36. cubeSmall = value;
  37. CubeSmallChange?.Invoke(null, EventArgs.Empty);
  38. }
  39. }
  40. private static event EventHandler CubeActiveChange;
  41. private static event EventHandler CubeSmallChange;
  42. private GameObject cameraObject;
  43. private Camera subCamera;
  44. private GameObject bgObject;
  45. private Transform bg;
  46. private DragPointBG bgDragPoint;
  47. private string currentBGAsset = defaultBg;
  48. private bool bgVisible = true;
  49. public bool BGVisible
  50. {
  51. get => bgVisible;
  52. set
  53. {
  54. bgVisible = value;
  55. bgObject.SetActive(bgVisible);
  56. }
  57. }
  58. private float defaultCameraMoveSpeed;
  59. private float defaultCameraZoomSpeed;
  60. private const float cameraFastMoveSpeed = 0.1f;
  61. private const float cameraFastZoomSpeed = 3f;
  62. private CameraInfo tempCameraInfo;
  63. private int currentCameraIndex;
  64. private const KeyCode AlphaOne = KeyCode.Alpha1;
  65. public int CameraCount => cameraInfos.Length;
  66. public EventHandler CameraChange;
  67. public int CurrentCameraIndex
  68. {
  69. get => currentCameraIndex;
  70. set
  71. {
  72. cameraInfos[currentCameraIndex] = mainCamera.GetInfo();
  73. currentCameraIndex = value;
  74. LoadCameraInfo(cameraInfos[currentCameraIndex]);
  75. }
  76. }
  77. private CameraInfo[] cameraInfos;
  78. static EnvironmentManager()
  79. {
  80. Input.Register(MpsKey.CameraLayer, KeyCode.Q, "Camera control layer");
  81. Input.Register(MpsKey.CameraSave, KeyCode.S, "Save camera transform");
  82. Input.Register(MpsKey.CameraLoad, KeyCode.A, "Load camera transform");
  83. Input.Register(MpsKey.CameraReset, KeyCode.R, "Reset camera transform");
  84. }
  85. public EnvironmentManager()
  86. {
  87. DragPointLight.EnvironmentManager = this;
  88. Activate();
  89. }
  90. public void Serialize(BinaryWriter binaryWriter) => Serialize(binaryWriter, false);
  91. public void Serialize(BinaryWriter binaryWriter, bool kankyo)
  92. {
  93. binaryWriter.Write(header);
  94. binaryWriter.Write(currentBGAsset);
  95. binaryWriter.WriteVector3(bg.position);
  96. binaryWriter.WriteQuaternion(bg.rotation);
  97. binaryWriter.WriteVector3(bg.localScale);
  98. binaryWriter.Write(kankyo);
  99. binaryWriter.WriteVector3(mainCamera.GetTargetPos());
  100. binaryWriter.Write(mainCamera.GetDistance());
  101. binaryWriter.WriteQuaternion(mainCamera.transform.rotation);
  102. CameraUtility.StopAll();
  103. }
  104. public void Deserialize(BinaryReader binaryReader)
  105. {
  106. var bgAsset = binaryReader.ReadString();
  107. var isCreative = Utility.IsGuidString(bgAsset);
  108. List<string> bgList = isCreative
  109. ? Constants.MyRoomCustomBGList.ConvertAll(kvp => kvp.Key)
  110. : Constants.BGList;
  111. var assetIndex = bgList.FindIndex(
  112. asset => asset.Equals(bgAsset, StringComparison.InvariantCultureIgnoreCase)
  113. );
  114. if (assetIndex < 0)
  115. {
  116. Utility.LogWarning($"Could not load BG '{bgAsset}'");
  117. isCreative = false;
  118. bgAsset = defaultBg;
  119. }
  120. else bgAsset = bgList[assetIndex];
  121. ChangeBackground(bgAsset, isCreative);
  122. bg.position = binaryReader.ReadVector3();
  123. bg.rotation = binaryReader.ReadQuaternion();
  124. bg.localScale = binaryReader.ReadVector3();
  125. var kankyo = binaryReader.ReadBoolean();
  126. Vector3 cameraPosition = binaryReader.ReadVector3();
  127. var cameraDistance = binaryReader.ReadSingle();
  128. Quaternion cameraRotation = binaryReader.ReadQuaternion();
  129. if (kankyo) return;
  130. mainCamera.SetTargetPos(cameraPosition);
  131. mainCamera.SetDistance(cameraDistance);
  132. mainCamera.transform.rotation = cameraRotation;
  133. CameraUtility.StopAll();
  134. }
  135. public void Activate()
  136. {
  137. BgMgrPatcher.ChangeBgBegin += OnChangeBegin;
  138. BgMgrPatcher.ChangeBgEnd += OnChangeEnd;
  139. bgObject = bgMgr.Parent;
  140. cameraObject = new GameObject("subCamera");
  141. subCamera = cameraObject.AddComponent<Camera>();
  142. subCamera.CopyFrom(mainCamera.camera);
  143. subCamera.clearFlags = CameraClearFlags.Depth;
  144. subCamera.cullingMask = 256;
  145. subCamera.depth = 1f;
  146. subCamera.transform.parent = mainCamera.transform;
  147. cameraObject.SetActive(true);
  148. bgObject.SetActive(true);
  149. ultimateOrbitCamera.enabled = true;
  150. defaultCameraMoveSpeed = ultimateOrbitCamera.moveSpeed;
  151. defaultCameraZoomSpeed = ultimateOrbitCamera.zoomSpeed;
  152. if (!MeidoPhotoStudio.EditMode)
  153. {
  154. ResetCamera();
  155. ChangeBackground(defaultBg);
  156. }
  157. else UpdateBG();
  158. SaveTempCamera();
  159. CameraInfo initalInfo = mainCamera.GetInfo();
  160. cameraInfos = new CameraInfo[5];
  161. for (var i = 0; i < CameraCount; i++) cameraInfos[i] = initalInfo;
  162. CubeSmallChange += OnCubeSmall;
  163. CubeActiveChange += OnCubeActive;
  164. }
  165. public void Deactivate()
  166. {
  167. BgMgrPatcher.ChangeBgBegin -= OnChangeBegin;
  168. BgMgrPatcher.ChangeBgEnd -= OnChangeEnd;
  169. DestroyDragPoint();
  170. Object.Destroy(cameraObject);
  171. Object.Destroy(subCamera);
  172. BGVisible = true;
  173. mainCamera.camera.backgroundColor = Color.black;
  174. ultimateOrbitCamera.moveSpeed = defaultCameraMoveSpeed;
  175. ultimateOrbitCamera.zoomSpeed = defaultCameraZoomSpeed;
  176. if (MeidoPhotoStudio.EditMode) bgMgr.ChangeBg(defaultBg);
  177. else
  178. {
  179. var isNight = GameMain.Instance.CharacterMgr.status.GetFlag("時間帯") == 3;
  180. bgMgr.ChangeBg(isNight ? "ShinShitsumu_ChairRot_Night" : "ShinShitsumu_ChairRot");
  181. mainCamera.Reset(CameraMain.CameraType.Target, true);
  182. mainCamera.SetTargetPos(new Vector3(0.5609447f, 1.380762f, -1.382336f));
  183. mainCamera.SetDistance(1.6f);
  184. mainCamera.SetAroundAngle(new Vector2(245.5691f, 6.273283f));
  185. }
  186. if (bgMgr.BgObject) bgMgr.BgObject.transform.localScale = Vector3.one;
  187. CubeSmallChange -= OnCubeSmall;
  188. CubeActiveChange -= OnCubeActive;
  189. }
  190. public void Update()
  191. {
  192. if (Input.GetKey(MpsKey.CameraLayer))
  193. {
  194. if (Input.GetKeyDown(MpsKey.CameraSave)) SaveTempCamera();
  195. else if (Input.GetKeyDown(MpsKey.CameraLoad)) LoadCameraInfo(tempCameraInfo);
  196. else if (Input.GetKeyDown(MpsKey.CameraReset)) ResetCamera();
  197. for (var i = 0; i < CameraCount; i++)
  198. {
  199. if (i != CurrentCameraIndex && UInput.GetKeyDown(AlphaOne + i)) CurrentCameraIndex = i;
  200. }
  201. }
  202. var shift = Input.Shift;
  203. ultimateOrbitCamera.moveSpeed = shift ? cameraFastMoveSpeed : defaultCameraMoveSpeed;
  204. ultimateOrbitCamera.zoomSpeed = shift ? cameraFastZoomSpeed : defaultCameraZoomSpeed;
  205. }
  206. public void ChangeBackground(string assetName, bool creative = false)
  207. {
  208. if (creative) bgMgr.ChangeBgMyRoom(assetName);
  209. else bgMgr.ChangeBg(assetName);
  210. }
  211. private void AttachDragPoint(Transform bgTransform)
  212. {
  213. bgDragPoint = DragPoint.Make<DragPointBG>(PrimitiveType.Cube, Vector3.one * 0.12f);
  214. bgDragPoint.Initialize(() => bgTransform.position, () => Vector3.zero);
  215. bgDragPoint.Set(bgTransform);
  216. bgDragPoint.AddGizmo();
  217. bgDragPoint.ConstantScale = true;
  218. bgDragPoint.gameObject.SetActive(CubeActive);
  219. }
  220. private void OnChangeBegin(object sender, EventArgs args) => DestroyDragPoint();
  221. private void OnChangeEnd(object sender, EventArgs args) => UpdateBG();
  222. private void UpdateBG()
  223. {
  224. if (!bgMgr.BgObject) return;
  225. currentBGAsset = bgMgr.GetBGName();
  226. if (currentBGAsset.StartsWith(myRoomPrefix))
  227. currentBGAsset = currentBGAsset.Replace(myRoomPrefix, string.Empty);
  228. bg = bgMgr.BgObject.transform;
  229. AttachDragPoint(bg);
  230. }
  231. private void DestroyDragPoint()
  232. {
  233. if (bgDragPoint) Object.Destroy(bgDragPoint.gameObject);
  234. }
  235. private void SaveTempCamera() => tempCameraInfo = mainCamera.GetInfo(true);
  236. public void LoadCameraInfo(CameraInfo info)
  237. {
  238. mainCamera.ApplyInfo(info, true);
  239. CameraChange?.Invoke(this, EventArgs.Empty);
  240. }
  241. private void ResetCamera()
  242. {
  243. mainCamera.Reset(CameraMain.CameraType.Target, true);
  244. mainCamera.SetTargetPos(new Vector3(0f, 0.9f, 0f));
  245. mainCamera.SetDistance(3f);
  246. CameraChange?.Invoke(this, EventArgs.Empty);
  247. }
  248. private void OnCubeSmall(object sender, EventArgs args)
  249. {
  250. bgDragPoint.DragPointScale = CubeSmall ? DragPointGeneral.smallCube : 1f;
  251. }
  252. private void OnCubeActive(object sender, EventArgs args)
  253. {
  254. bgDragPoint.gameObject.SetActive(CubeActive);
  255. }
  256. }
  257. public readonly struct CameraInfo
  258. {
  259. public Vector3 TargetPos { get; }
  260. public Quaternion Angle { get; }
  261. public float Distance { get; }
  262. public float FOV { get; }
  263. public CameraInfo(CameraMain camera)
  264. {
  265. TargetPos = camera.GetTargetPos();
  266. Angle = camera.transform.rotation;
  267. Distance = camera.GetDistance();
  268. FOV = camera.camera.fieldOfView;
  269. }
  270. }
  271. }