Browse Source

Add lights

* Each light has individual properties per light type
* Individual lights can be deleted
* Lights can be selected/delete through the same methods as props
* Light properties and position can be reset
habeebweeb 4 years ago
parent
commit
ae78f0b2a0

+ 3 - 2
COM3D2.MeidoPhotoStudio.Plugin/Config/MeidoPhotoStudio/translations.en.json

@@ -1084,9 +1084,10 @@
         "header": "Lights",
         "add": "+",
         "delete": "Del",
-        "reset": "Reset",
+        "resetPosition": "R Pos",
+        "resetProperties": "R Props",
         "clear": "Clear",
-        "color": "Color",
+        "colour": "Colour",
         "disable": "Disable"
     },
     "lightType": {

+ 1 - 1
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/GUI/Controls/MiscGUI.cs

@@ -36,7 +36,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         public static void Header(string text, params GUILayoutOption[] layoutOptions)
         {
             GUIStyle style = new GUIStyle(GUI.skin.label);
-            style.padding = new RectOffset(7, 0, 0, 0);
+            style.padding = new RectOffset(7, 0, 0, -5);
 
             GUILayout.Label(text, style, layoutOptions);
         }

+ 343 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/GUI/Panes/BackgroundWindowPanes/LightsPane.cs

@@ -0,0 +1,343 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace COM3D2.MeidoPhotoStudio.Plugin
+{
+    using static MPSLight;
+    class LightsPane : BasePane
+    {
+        private LightManager lightManager;
+        private EnvironmentManager environmentManager;
+        private static readonly string[] lightTypes = { "normal", "spot", "point" };
+        private Dictionary<LightProp, Slider> LightSlider;
+        private Dropdown lightDropdown;
+        private Button addLightButton;
+        private Button deleteLightButton;
+        private Button clearLightsButton;
+        private Button resetPropsButton;
+        private Button resetPositionButton;
+        private SelectionGrid lightTypeGrid;
+        private Toggle colorToggle;
+        private Toggle disableToggle;
+        private MPSLightType currentLightType = MPSLightType.Normal;
+        private string lightHeader;
+        private static readonly Dictionary<LightProp, SliderProp> LightSliderProp =
+            new Dictionary<LightProp, SliderProp>
+            {
+                [LightProp.LightRotX] = new SliderProp(0f, 360f, LightProperty.DefaultRotation.eulerAngles.x),
+                [LightProp.LightRotY] = new SliderProp(0f, 360f, LightProperty.DefaultRotation.eulerAngles.y),
+                [LightProp.Intensity] = new SliderProp(0f, 2f, 0.95f),
+                [LightProp.ShadowStrength] = new SliderProp(0f, 1f, 0.098f),
+                [LightProp.Range] = new SliderProp(0f, 150f, GameMain.Instance.MainLight.GetComponent<Light>().range),
+                [LightProp.SpotAngle] = new SliderProp(0f, 150f, 50f),
+                [LightProp.Red] = new SliderProp(0f, 1f, 1f),
+                [LightProp.Green] = new SliderProp(0f, 1f, 1f),
+                [LightProp.Blue] = new SliderProp(0f, 1f, 1f),
+            };
+        private static string[,] sliderNames = {
+            { "lights", "x" }, { "lights", "y" }, { "lights", "intensity" }, { "lights", "shadow" },
+            { "lights", "spot" }, { "lights", "range" }, { "backgroundWindow", "red" }, { "backgroundWindow", "green" },
+            { "backgroundWindow", "blue" }
+        };
+
+        public LightsPane(EnvironmentManager environmentManager)
+        {
+            this.lightHeader = Translation.Get("lightsPane", "header");
+
+            this.environmentManager = environmentManager;
+
+            this.lightManager = this.environmentManager.LightManager;
+            this.lightManager.Rotate += (s, a) => UpdateRotation();
+            this.lightManager.Scale += (s, a) => UpdateScale();
+            this.lightManager.Select += (s, a) => UpdateCurretLight();
+            this.lightManager.ListModified += (s, a) => UpdateList();
+
+            this.lightTypeGrid = new SelectionGrid(Translation.GetArray("lightType", lightTypes));
+            this.lightTypeGrid.ControlEvent += (s, a) => SetCurrentLightType();
+
+            this.lightDropdown = new Dropdown(new[] { "Main" });
+            this.lightDropdown.SelectionChange += (s, a) => SetCurrentLight();
+
+            this.addLightButton = new Button("+");
+            this.addLightButton.ControlEvent += (s, a) => AddLight();
+
+            this.deleteLightButton = new Button(Translation.Get("lightsPane", "delete"));
+            this.deleteLightButton.ControlEvent += (s, a) => DeleteCurrentLight();
+
+            this.disableToggle = new Toggle(Translation.Get("lightsPane", "disable"));
+            this.disableToggle.ControlEvent += (s, a) => SetCurrentLightActive();
+
+            this.clearLightsButton = new Button(Translation.Get("lightsPane", "clear"));
+            this.clearLightsButton.ControlEvent += (s, a) => ClearLights();
+
+            int numberOfLightProps = Enum.GetNames(typeof(LightProp)).Length;
+            this.LightSlider = new Dictionary<LightProp, Slider>(numberOfLightProps);
+
+            for (int i = 0; i < numberOfLightProps; i++)
+            {
+                LightProp lightProp = (LightProp)i;
+                SliderProp sliderProp = LightSliderProp[lightProp];
+                Slider slider = new Slider(Translation.Get(sliderNames[i, 0], sliderNames[i, 1]), sliderProp);
+                if (lightProp == LightProp.LightRotX || lightProp == LightProp.LightRotY)
+                {
+                    slider.ControlEvent += (s, a) => SetLightRotation();
+                }
+                else
+                {
+                    slider.ControlEvent += (s, a) => SetLightProp(lightProp, slider.Value);
+                }
+                LightSlider[lightProp] = slider;
+            }
+
+            this.colorToggle = new Toggle(Translation.Get("lightsPane", "colour"));
+            this.colorToggle.ControlEvent += (s, a) => SetColourMode();
+
+            this.resetPropsButton = new Button(Translation.Get("lightsPane", "resetProperties"));
+            this.resetPropsButton.ControlEvent += (s, a) => ResetLightProps();
+
+            this.resetPositionButton = new Button(Translation.Get("lightsPane", "resetPosition"));
+            this.resetPositionButton.ControlEvent += (s, a) => ResetLightPosition();
+        }
+
+        protected override void ReloadTranslation()
+        {
+            this.updating = true;
+            this.lightHeader = Translation.Get("lightsPane", "header");
+            this.lightTypeGrid.SetItems(Translation.GetArray("lightType", lightTypes));
+            this.lightDropdown.SetDropdownItems(this.lightManager.LightNameList);
+            this.deleteLightButton.Label = Translation.Get("lightsPane", "delete");
+            this.disableToggle.Label = Translation.Get("lightsPane", "disable");
+            this.clearLightsButton.Label = Translation.Get("lightsPane", "clear");
+            for (LightProp lightProp = LightProp.LightRotX; lightProp <= LightProp.Blue; lightProp++)
+            {
+                LightSlider[lightProp].Label =
+                    Translation.Get(sliderNames[(int)lightProp, 0], sliderNames[(int)lightProp, 1]);
+            }
+            this.colorToggle.Label = Translation.Get("lightsPane", "colour");
+            this.resetPropsButton.Label = Translation.Get("lightsPane", "resetProperties");
+            this.resetPositionButton.Label = Translation.Get("lightsPane", "resetPosition");
+            this.updating = false;
+        }
+
+        private void SetColourMode()
+        {
+            this.lightManager.SetColourModeActive(this.colorToggle.Value);
+            this.environmentManager.BGVisible = !this.colorToggle.Value;
+            this.UpdatePane();
+        }
+
+        private void ClearLights()
+        {
+            this.lightManager.ClearLights();
+            this.UpdatePane();
+        }
+
+        private void SetCurrentLight()
+        {
+            if (updating) return;
+            this.lightManager.SelectedLightIndex = this.lightDropdown.SelectedItemIndex;
+            this.UpdatePane();
+        }
+
+        private void ResetLightProps()
+        {
+            this.lightManager.CurrentLight.ResetLightProps();
+            this.UpdatePane();
+        }
+
+        private void ResetLightPosition()
+        {
+            this.lightManager.CurrentLight.ResetLightPosition();
+        }
+
+        private void AddLight()
+        {
+            this.lightManager.AddLight();
+        }
+
+        private void DeleteCurrentLight()
+        {
+            this.lightManager.DeleteActiveLight();
+        }
+
+        private void SetCurrentLightActive()
+        {
+            this.lightManager.CurrentLight.IsDisabled = this.disableToggle.Value;
+        }
+
+        private void SetCurrentLightType()
+        {
+            if (updating) return;
+
+            currentLightType = (MPSLightType)this.lightTypeGrid.SelectedItem;
+
+            LightType lightType;
+            if (currentLightType == MPSLightType.Normal)
+            {
+                lightType = LightType.Directional;
+            }
+            else if (currentLightType == MPSLightType.Spot)
+            {
+                lightType = LightType.Spot;
+            }
+            else
+            {
+                lightType = LightType.Point;
+            }
+
+            MPSLight currentLight = lightManager.CurrentLight;
+            currentLight.SetLightType(lightType);
+
+            if (lightManager.SelectedLightIndex == 0)
+            {
+                this.environmentManager.BGVisible = (currentLight.SelectedLightType != MPSLightType.Normal)
+                    || !currentLight.IsColourMode;
+            }
+
+            this.lightDropdown.SetDropdownItem(lightManager.ActiveLightName);
+            this.UpdatePane();
+        }
+
+        private void SetLightProp(LightProp prop, float value)
+        {
+            if (updating) return;
+            lightManager.CurrentLight.SetProp(prop, value);
+        }
+
+        private void SetLightRotation()
+        {
+            if (updating) return;
+            float lightRotX = LightSlider[LightProp.LightRotX].Value;
+            float lightRotY = LightSlider[LightProp.LightRotY].Value;
+            lightManager.CurrentLight.SetRotation(lightRotX, lightRotY);
+        }
+
+        private void UpdateList()
+        {
+            string[] newList = this.lightManager.LightNameList;
+            this.lightDropdown.SetDropdownItems(newList, this.lightManager.SelectedLightIndex);
+            this.UpdatePane();
+        }
+
+        private void UpdateRotation()
+        {
+            this.updating = true;
+            LightProperty prop = this.lightManager.CurrentLight.CurrentLightProperty;
+            LightSlider[LightProp.LightRotX].Value = prop.Rotation.eulerAngles.x;
+            LightSlider[LightProp.LightRotY].Value = prop.Rotation.eulerAngles.y;
+            this.updating = false;
+        }
+
+        private void UpdateScale()
+        {
+            this.updating = true;
+            LightSlider[LightProp.SpotAngle].Value = this.lightManager.CurrentLight.CurrentLightProperty.SpotAngle;
+            LightSlider[LightProp.Range].Value = this.lightManager.CurrentLight.CurrentLightProperty.Range;
+            this.updating = false;
+        }
+
+        private void UpdateCurretLight()
+        {
+            this.updating = true;
+            this.lightDropdown.SelectedItemIndex = this.lightManager.SelectedLightIndex;
+            this.updating = false;
+            this.UpdatePane();
+        }
+
+        public override void UpdatePane()
+        {
+            this.updating = true;
+            MPSLight currentLight = this.lightManager.CurrentLight;
+            this.currentLightType = currentLight.SelectedLightType;
+            this.lightTypeGrid.SelectedItem = (int)this.currentLightType;
+            this.disableToggle.Value = currentLight.IsDisabled;
+            this.LightSlider[LightProp.LightRotX].Value = currentLight.Rotation.eulerAngles.x;
+            this.LightSlider[LightProp.LightRotY].Value = currentLight.Rotation.eulerAngles.y;
+            this.LightSlider[LightProp.Intensity].Value = currentLight.Intensity;
+            this.LightSlider[LightProp.ShadowStrength].Value = currentLight.ShadowStrength;
+            this.LightSlider[LightProp.Range].Value = currentLight.Range;
+            this.LightSlider[LightProp.SpotAngle].Value = currentLight.SpotAngle;
+            this.LightSlider[LightProp.Red].Value = currentLight.LightColour.r;
+            this.LightSlider[LightProp.Green].Value = currentLight.LightColour.g;
+            this.LightSlider[LightProp.Blue].Value = currentLight.LightColour.b;
+            this.updating = false;
+        }
+
+        public override void Draw()
+        {
+            bool isMain = this.lightManager.SelectedLightIndex == 0;
+
+            MiscGUI.Header(lightHeader);
+            MiscGUI.WhiteLine();
+
+            GUILayout.BeginHorizontal();
+            this.lightDropdown.Draw(GUILayout.Width(84));
+            this.addLightButton.Draw(GUILayout.ExpandWidth(false));
+
+            GUILayout.FlexibleSpace();
+            GUI.enabled = !isMain;
+            this.deleteLightButton.Draw(GUILayout.ExpandWidth(false));
+            GUI.enabled = true;
+            this.clearLightsButton.Draw(GUILayout.ExpandWidth(false));
+            GUILayout.EndHorizontal();
+
+            bool isDisabled = !isMain && this.lightManager.CurrentLight.IsDisabled;
+            GUILayout.BeginHorizontal();
+            GUI.enabled = !isDisabled;
+            this.lightTypeGrid.Draw(GUILayout.ExpandWidth(false));
+            if (!isMain)
+            {
+                GUILayout.FlexibleSpace();
+                GUI.enabled = true;
+                this.disableToggle.Draw();
+            }
+            GUILayout.EndHorizontal();
+
+            GUI.enabled = !isDisabled;
+
+            if (currentLightType != MPSLightType.Point)
+            {
+                this.LightSlider[LightProp.LightRotX].Draw();
+                this.LightSlider[LightProp.LightRotY].Draw();
+            }
+
+            this.LightSlider[LightProp.Intensity].Draw();
+
+            if (currentLightType == MPSLightType.Normal)
+            {
+                this.LightSlider[LightProp.ShadowStrength].Draw();
+            }
+            else
+            {
+                this.LightSlider[LightProp.Range].Draw();
+            }
+
+            if (currentLightType == MPSLightType.Spot)
+            {
+                this.LightSlider[LightProp.SpotAngle].Draw();
+            }
+
+            GUILayout.BeginHorizontal();
+            this.LightSlider[LightProp.Red].Draw();
+            this.LightSlider[LightProp.Green].Draw();
+            GUILayout.EndHorizontal();
+
+            GUILayout.BeginHorizontal();
+            this.LightSlider[LightProp.Blue].Draw(GUILayout.Width(96));
+            if ((lightManager.SelectedLightIndex == 0) && (currentLightType == MPSLightType.Normal))
+            {
+                this.colorToggle.Draw();
+            }
+            GUILayout.EndHorizontal();
+
+            GUILayout.BeginHorizontal();
+            this.resetPropsButton.Draw(GUILayout.ExpandWidth(false));
+            GUILayout.FlexibleSpace();
+            this.resetPositionButton.Draw(GUILayout.ExpandWidth(false));
+            GUILayout.EndHorizontal();
+
+            GUI.enabled = true;
+        }
+    }
+}

+ 4 - 4
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/GUI/Panes/MainWindowPanes/BGWindowPane.cs

@@ -7,19 +7,19 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
     {
         private BackgroundSelectorPane backgroundSelectorPane;
         private PropsPane propsPane;
-        // private LightsPane lightsPane;
+        private LightsPane lightsPane;
 
         public BGWindowPane(EnvironmentManager environmentManager)
         {
             this.backgroundSelectorPane = new BackgroundSelectorPane(environmentManager);
             this.propsPane = new PropsPane(environmentManager.PropManager);
-            // this.lightsPane = new LightsPane(environmentManager.LightManager);
+            this.lightsPane = new LightsPane(environmentManager);
         }
         public override void Draw()
         {
             this.backgroundSelectorPane.Draw();
             this.propsPane.Draw();
-            // this.lightsPane.Draw();
+            this.lightsPane.Draw();
         }
 
         public override void UpdatePanes()
@@ -27,7 +27,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             if (ActiveWindow)
             {
                 this.propsPane.UpdatePane();
-                // this.lightsPane.UpdatePane();
+                this.lightsPane.UpdatePane();
             }
         }
     }

+ 2 - 2
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/GUI/Windows/MainWindow.cs

@@ -16,7 +16,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             get
             {
                 windowRect.width = 230f;
-                windowRect.height = Screen.height * 0.8f;
+                windowRect.height = Screen.height * 0.9f;
                 windowRect.x = Mathf.Clamp(windowRect.x, 0, Screen.width - windowRect.width);
                 windowRect.y = Mathf.Clamp(windowRect.y, -windowRect.height + 30, Screen.height - 50);
                 return windowRect;
@@ -37,7 +37,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             this.meidoManager.UpdateMeido += UpdateMeido;
 
             windowPanes = new Dictionary<Constants.Window, BaseWindowPane>();
-            windowRect = new Rect(Screen.width, Screen.height * 0.08f, 230f, Screen.height * 0.8f);
+            windowRect = new Rect(Screen.width, Screen.height * 0.08f, 230f, Screen.height * 0.9f);
 
             tabsPane = new TabsPane();
             tabsPane.TabChange += (s, a) => ChangeTab();

+ 301 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/MPSLight.cs

@@ -0,0 +1,301 @@
+using System;
+using UnityEngine;
+
+namespace COM3D2.MeidoPhotoStudio.Plugin
+{
+    public class MPSLight
+    {
+        private static Camera camera = GameMain.Instance.MainCamera.GetComponent<Camera>();
+        private Light light;
+        public DragDogu DragLight { get; private set; }
+        public event EventHandler Rotate;
+        public event EventHandler Scale;
+        public event EventHandler Delete;
+        public event EventHandler Select;
+        public bool isActiveLight = false;
+        public bool IsMain { get; private set; } = false;
+        private bool isDisabled = false;
+        public string Name { get; private set; }
+        public bool IsDisabled
+        {
+            get => isDisabled;
+            set
+            {
+                this.isDisabled = value;
+                this.light.gameObject.SetActive(!this.isDisabled);
+            }
+        }
+        public LightProperty[] LightProperties = new LightProperty[]
+        {
+            new LightProperty(),
+            new LightProperty(),
+            new LightProperty()
+        };
+        private bool isColourMode = false;
+        public bool IsColourMode
+        {
+            get => isColourMode && SelectedLightType == MPSLightType.Normal;
+            set
+            {
+                this.light.color = value ? Color.white : LightColour;
+                camera.backgroundColor = value ? LightColour : Color.black;
+                this.isColourMode = value;
+                LightColour = this.isColourMode ? camera.backgroundColor : light.color;
+            }
+        }
+        public MPSLightType SelectedLightType { get; private set; } = MPSLightType.Normal;
+        public LightProperty CurrentLightProperty => LightProperties[(int)SelectedLightType];
+        public Quaternion Rotation
+        {
+            get => CurrentLightProperty.Rotation;
+            set => this.light.transform.rotation = CurrentLightProperty.Rotation = value;
+        }
+        public float Intensity
+        {
+            get => CurrentLightProperty.Intensity;
+            set => this.light.intensity = CurrentLightProperty.Intensity = value;
+        }
+        public float Range
+        {
+            get => CurrentLightProperty.Range;
+            set => this.light.range = CurrentLightProperty.Range = value;
+        }
+        public float SpotAngle
+        {
+            get => CurrentLightProperty.SpotAngle;
+            set
+            {
+                this.light.spotAngle = CurrentLightProperty.SpotAngle = value;
+                this.light.transform.localScale = Vector3.one * value;
+            }
+        }
+        public float ShadowStrength
+        {
+            get => CurrentLightProperty.ShadowStrength;
+            set => this.light.shadowStrength = CurrentLightProperty.ShadowStrength = value;
+        }
+        public float LightColorRed
+        {
+            get => IsColourMode ? camera.backgroundColor.r : CurrentLightProperty.LightColour.r;
+            set
+            {
+                Color color = IsColourMode ? camera.backgroundColor : this.light.color;
+                this.LightColour = new Color(value, color.g, color.b);
+            }
+        }
+        public float LightColorGreen
+        {
+            get => IsColourMode ? camera.backgroundColor.g : CurrentLightProperty.LightColour.r;
+            set
+            {
+                Color color = IsColourMode ? camera.backgroundColor : this.light.color;
+                this.LightColour = new Color(color.r, value, color.b);
+            }
+        }
+        public float LightColorBlue
+        {
+            get => IsColourMode ? camera.backgroundColor.b : CurrentLightProperty.LightColour.r;
+            set
+            {
+                Color color = IsColourMode ? camera.backgroundColor : this.light.color;
+                this.LightColour = new Color(color.r, color.g, value);
+            }
+        }
+        public Color LightColour
+        {
+            get => IsColourMode ? camera.backgroundColor : CurrentLightProperty.LightColour;
+            set
+            {
+                Color colour = CurrentLightProperty.LightColour = value;
+                if (IsColourMode) camera.backgroundColor = colour;
+                else this.light.color = colour;
+            }
+        }
+        public enum LightProp
+        {
+            LightRotX, LightRotY, Intensity, ShadowStrength, SpotAngle, Range, Red, Green, Blue
+        }
+
+        public enum MPSLightType
+        {
+            Normal, Spot, Point, Disabled
+        }
+
+        public MPSLight(GameObject lightGo = null, bool isMain = false)
+        {
+            this.IsMain = isMain;
+
+            GameObject gameobject = lightGo ?? new GameObject();
+            this.light = gameobject.GetComponent<Light>() ?? gameobject.AddComponent<Light>();
+
+            float spotAngle = CurrentLightProperty.SpotAngle;
+            this.light.transform.position = LightProperty.DefaultPosition;
+            this.light.transform.rotation = LightProperty.DefaultRotation;
+
+            GameObject dragPoint = BaseDrag.MakeDragPoint(
+                PrimitiveType.Cube, Vector3.one * 0.12f, BaseDrag.LightBlue
+            );
+
+            DragLight = dragPoint.AddComponent<DragDogu>();
+            DragLight.Initialize(this.light.gameObject, this.IsMain, CustomGizmo.GizmoMode.World,
+                () => this.light.transform.position,
+                () => this.light.transform.eulerAngles
+            );
+
+            DragLight.scaleFactor = 50f;
+            DragLight.Select += (s, a) => this.Select?.Invoke(this, EventArgs.Empty);
+
+            if (!isMain)
+            {
+                DragLight.Delete += (s, a) => Delete?.Invoke(this, EventArgs.Empty);
+            }
+
+            DragLight.SetDragProp(false, false, false);
+
+            SetLightType(LightType.Directional);
+        }
+
+        public static void SetLightProperties(Light light, LightProperty prop)
+        {
+            light.transform.rotation = prop.Rotation;
+            light.intensity = prop.Intensity;
+            light.range = prop.Range;
+            light.spotAngle = prop.SpotAngle;
+            light.shadowStrength = prop.ShadowStrength;
+            light.color = prop.LightColour;
+            if (light.type == LightType.Spot)
+            {
+                light.transform.localScale = Vector3.one * prop.SpotAngle;
+            }
+            else if (light.type == LightType.Point)
+            {
+                light.transform.localScale = Vector3.one * prop.Range;
+            }
+        }
+
+        public void Destroy()
+        {
+            DragLight.Rotate -= OnRotate;
+            DragLight.Scale -= OnScale;
+            GameObject.Destroy(DragLight.gameObject);
+            if (!IsMain) GameObject.Destroy(this.light.gameObject);
+        }
+
+        public void SetLightType(LightType type)
+        {
+            DragLight.Rotate -= OnRotate;
+            DragLight.Rotate -= OnScale;
+            string name = "normal";
+
+            if (type == LightType.Directional)
+            {
+                SelectedLightType = MPSLightType.Normal;
+            }
+            else if (type == LightType.Spot)
+            {
+                name = "spot";
+                SelectedLightType = MPSLightType.Spot;
+                DragLight.Scale += OnScale;
+                DragLight.Rotate += OnRotate;
+            }
+            else
+            {
+                name = "point";
+                SelectedLightType = MPSLightType.Point;
+                DragLight.Scale += OnScale;
+            }
+
+            this.light.type = type;
+
+            SetProps();
+
+            this.Name = IsMain ? "main" : name;
+        }
+
+        public void SetRotation(float x, float y)
+        {
+            this.Rotation = Quaternion.Euler(x, y, Rotation.eulerAngles.z);
+        }
+
+        public void SetProp(LightProp prop, float value)
+        {
+            switch (prop)
+            {
+                case LightProp.Intensity:
+                    Intensity = value;
+                    break;
+                case LightProp.ShadowStrength:
+                    ShadowStrength = value;
+                    break;
+                case LightProp.SpotAngle:
+                    SpotAngle = value;
+                    break;
+                case LightProp.Range:
+                    Range = value;
+                    break;
+                case LightProp.Red:
+                    LightColorRed = value;
+                    break;
+                case LightProp.Green:
+                    LightColorGreen = value;
+                    break;
+                case LightProp.Blue:
+                    LightColorBlue = value;
+                    break;
+            }
+        }
+
+        public void ResetLightProps()
+        {
+            LightProperties[(int)SelectedLightType] = new LightProperty();
+            SetProps();
+        }
+
+        public void ResetLightPosition()
+        {
+            this.light.transform.position = LightProperty.DefaultPosition;
+        }
+
+        private void SetProps()
+        {
+            SetLightProperties(this.light, CurrentLightProperty);
+            if (IsColourMode)
+            {
+                this.light.color = Color.white;
+                camera.backgroundColor = CurrentLightProperty.LightColour;
+            }
+        }
+
+        private void OnRotate(object sender, EventArgs args)
+        {
+            CurrentLightProperty.Rotation = this.light.transform.rotation;
+            OnTransformEvent(Rotate);
+        }
+
+        private void OnScale(object sender, EventArgs args)
+        {
+            float value = this.light.transform.localScale.x;
+            if (SelectedLightType == MPSLightType.Point) Range = value;
+            else if (SelectedLightType == MPSLightType.Spot) SpotAngle = value;
+
+            OnTransformEvent(Scale);
+        }
+
+        private void OnTransformEvent(EventHandler handler)
+        {
+            handler?.Invoke(this, EventArgs.Empty);
+        }
+    }
+
+    public class LightProperty
+    {
+        public static readonly Vector3 DefaultPosition = new Vector3(0f, 1.5f, 0.4f);
+        public static readonly Quaternion DefaultRotation = Quaternion.Euler(40f, 180f, 0f);
+        public Quaternion Rotation { get; set; } = DefaultRotation;
+        public float Intensity { get; set; } = 0.95f;
+        public float Range { get; set; } = GameMain.Instance.MainLight.GetComponent<Light>().range;
+        public float SpotAngle { get; set; } = 50f;
+        public float ShadowStrength { get; set; } = 0.10f;
+        public Color LightColour { get; set; } = Color.white;
+    }
+}

+ 13 - 4
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Managers/EnvironmentManager.cs

@@ -12,6 +12,16 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         public LightManager LightManager { get; set; }
         public PropManager PropManager { get; set; }
         public EffectManager EffectManager { get; set; }
+        private bool bgVisible = true;
+        public bool BGVisible
+        {
+            get => bgVisible;
+            set
+            {
+                this.bgVisible = value;
+                bgObject.SetActive(this.bgVisible);
+            }
+        }
 
         public void Activate()
         {
@@ -31,7 +41,6 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             bgObject.SetActive(true);
             GameMain.Instance.BgMgr.ChangeBg("Theater");
 
-            GameMain.Instance.MainCamera.GetComponent<Camera>().backgroundColor = new Color(0.0f, 0.0f, 0.0f);
             UltimateOrbitCamera UOCamera =
                 Utility.GetFieldValue<CameraMain, UltimateOrbitCamera>(GameMain.Instance.MainCamera, "m_UOCamera");
             UOCamera.enabled = true;
@@ -40,7 +49,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             SaveCameraInfo();
 
             PropManager.Activate();
-            // LightManager.Activate();
+            LightManager.Activate();
             // EffectManager.Activate();
         }
 
@@ -50,7 +59,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             GameObject.Destroy(subCamera);
 
             PropManager.Deactivate();
-            // LightManager.Deactivate();
+            LightManager.Deactivate();
             // EffectManager.Deactivate();
 
             bool isNight = GameMain.Instance.CharacterMgr.status.GetFlag("時間帯") == 3;
@@ -91,7 +100,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             }
 
             PropManager.Update();
-            // LightManager.Update();
+            LightManager.Update();
             // EffectManager.Update();
         }
 

+ 218 - 1
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Managers/LightManager.cs

@@ -6,21 +6,238 @@ using UnityEngine.Rendering;
 
 namespace COM3D2.MeidoPhotoStudio.Plugin
 {
+    using static MPSLight;
     public class LightManager
     {
-        public LightManager()
+        private List<MPSLight> LightList { get; set; } = new List<MPSLight>();
+        private int selectedLightIndex = 0;
+        public int SelectedLightIndex
         {
+            get => selectedLightIndex;
+            set
+            {
+                selectedLightIndex = Mathf.Clamp(value, 0, LightList.Count - 1);
+                LightList[SelectedLightIndex].isActiveLight = true;
+            }
+        }
+        public string[] LightNameList => LightList.Select(light => LightName(light.Name)).ToArray();
+        public string ActiveLightName => LightName(LightList[SelectedLightIndex].Name);
+        public MPSLight CurrentLight
+        {
+            get
+            {
+                return LightList[SelectedLightIndex];
+            }
+        }
+        public event EventHandler Rotate;
+        public event EventHandler Scale;
+        public event EventHandler ListModified;
+        public event EventHandler Select;
+        private DragType dragTypeOld = DragType.None;
+        private DragType currentDragType = DragType.None;
+        private bool gizmoActive = false;
+        enum DragType
+        {
+            None, Move, Rotate, Scale, Delete, Select
+        }
 
+        public void Activate()
+        {
+            GameMain.Instance.MainCamera.GetComponent<Camera>().backgroundColor = Color.black;
+            AddLight(GameMain.Instance.MainLight.gameObject, true);
         }
 
         public void Deactivate()
         {
+            for (int i = 0; i < LightList.Count; i++)
+            {
+                DestroyLight(LightList[i]);
+            }
+            selectedLightIndex = 0;
+            LightList.Clear();
+
+            GameMain.Instance.MainLight.Reset();
 
+            Light mainLight = GameMain.Instance.MainLight.GetComponent<Light>();
+            mainLight.type = LightType.Directional;
+            MPSLight.SetLightProperties(mainLight, new LightProperty());
         }
 
         public void Update()
         {
+            if (Input.GetKey(KeyCode.Z))
+            {
+                currentDragType = DragType.Move;
+            }
+            else if (Input.GetKey(KeyCode.X))
+            {
+                currentDragType = DragType.Rotate;
+            }
+            else if (Input.GetKey(KeyCode.C))
+            {
+                currentDragType = DragType.Scale;
+            }
+            else if (Input.GetKey(KeyCode.D))
+            {
+                currentDragType = DragType.Delete;
+            }
+            else if (Input.GetKey(KeyCode.A))
+            {
+                currentDragType = DragType.Select;
+            }
+            else
+            {
+                currentDragType = DragType.None;
+            }
+
+            if (currentDragType != dragTypeOld) UpdateDragType();
+
+            dragTypeOld = currentDragType;
+        }
+
+        private void UpdateDragType()
+        {
+            foreach (MPSLight light in LightList)
+            {
+                bool active;
+                if (currentDragType >= DragType.Delete || currentDragType == DragType.None)
+                {
+                    if (currentDragType == DragType.Delete)
+                    {
+                        active = !light.IsMain;
+                    }
+                    else
+                    {
+                        active = currentDragType == DragType.Select;
+                    }
+                }
+                else
+                {
+                    if (light.SelectedLightType == MPSLightType.Normal)
+                    {
+                        active = false;
+                    }
+                    else if (light.SelectedLightType == MPSLightType.Point)
+                    {
+                        active = currentDragType != DragType.Rotate;
+                    }
+                    else
+                    {
+                        active = true;
+                    }
+                }
+                light.DragLight.SetDragProp(gizmoActive && active, active, active);
+            }
+        }
+
+        public void AddLight(GameObject lightGo = null, bool isMain = false)
+        {
+            MPSLight light = new MPSLight(lightGo, isMain);
+            light.Rotate += OnRotate;
+            light.Scale += OnScale;
+            light.Delete += OnDelete;
+            light.Select += OnSelect;
+            LightList.Add(light);
+
+            LightList[SelectedLightIndex].isActiveLight = false;
+            SelectedLightIndex = LightList.Count;
+            OnListModified();
+        }
+
+        public void DeleteActiveLight()
+        {
+            if (selectedLightIndex == 0) return;
+
+            DeleteLight(SelectedLightIndex);
+        }
+
+        public void DeleteLight(int lightIndex, bool noUpdate = false)
+        {
+            if (lightIndex == 0) return;
+
+            DestroyLight(LightList[lightIndex]);
+            LightList.RemoveAt(lightIndex);
+
+            if (lightIndex <= SelectedLightIndex) SelectedLightIndex -= 1;
 
+            if (noUpdate) return;
+            OnListModified();
+        }
+
+        public void SetColourModeActive(bool isColourMode)
+        {
+            LightList[0].IsColourMode = isColourMode;
+        }
+
+        public void ClearLights()
+        {
+            for (int i = LightList.Count - 1; i > 0; i--)
+            {
+                DeleteLight(i);
+            }
+            selectedLightIndex = 0;
+        }
+
+        private void DestroyLight(MPSLight light)
+        {
+            light.Rotate -= OnRotate;
+            light.Scale -= OnScale;
+            light.Delete -= OnDelete;
+            light.Select -= OnSelect;
+            light.Destroy();
+        }
+
+        private string LightName(string name)
+        {
+            return Translation.Get("lightType", name);
+        }
+
+        private void OnDelete(object sender, EventArgs args)
+        {
+            MPSLight theLight = (MPSLight)sender;
+            for (int i = 1; i < LightList.Count; i++)
+            {
+                MPSLight light = LightList[i];
+                if (light == theLight)
+                {
+                    DeleteLight(i);
+                    return;
+                }
+            }
+        }
+
+        private void OnRotate(object sender, EventArgs args)
+        {
+            OnTransformEvent((MPSLight)sender, Rotate);
+        }
+
+        private void OnScale(object sender, EventArgs args)
+        {
+            OnTransformEvent((MPSLight)sender, Scale);
+        }
+
+        private void OnTransformEvent(MPSLight light, EventHandler handler)
+        {
+            if (light.isActiveLight)
+            {
+                handler?.Invoke(this, EventArgs.Empty);
+            }
+        }
+
+        private void OnSelect(object sender, EventArgs args)
+        {
+            MPSLight theLight = (MPSLight)sender;
+            int select = LightList.FindIndex(light => light == theLight);
+            if (select >= 0)
+            {
+                this.SelectedLightIndex = select;
+                this.Select?.Invoke(this, EventArgs.Empty);
+            }
+        }
+
+        private void OnListModified()
+        {
+            ListModified?.Invoke(this, EventArgs.Empty);
         }
     }
 }

+ 3 - 3
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/MeidoPhotoStudio.cs

@@ -18,7 +18,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         private MeidoManager meidoManager;
         private EnvironmentManager environmentManager;
         private PropManager propManager;
-        // private LightManager lightManager;
+        private LightManager lightManager;
         // private EffectManager effectManager;
         private MessageWindowManager messageWindowManager;
         private Constants.Scene currentScene;
@@ -143,11 +143,11 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
 
             meidoManager = new MeidoManager();
             propManager = new PropManager();
-            // lightManager = new LightManager();
+            lightManager = new LightManager();
             environmentManager = new EnvironmentManager()
             {
                 PropManager = propManager,
-                // LightManager = lightManager
+                LightManager = lightManager
             };
 
             messageWindowManager = new MessageWindowManager();