/// <summary> /// Creates the preview for a given light. /// /// RadiationGridManager.CreatePreview has no references so no sense in patching that /// yet. /// </summary> /// <param name="origin">The starting cell.</param> /// <param name="radius">The light radius.</param> /// <param name="shape">The light shape.</param> /// <param name="lux">The base brightness in lux.</param> /// <returns>true if the lighting was handled, or false otherwise.</returns> internal bool PreviewLight(int origin, float radius, LightShape shape, int lux) { bool handled = false; if (shape != LightShape.Circle && shape != LightShape.Cone) { var cells = DictionaryPool <int, float, PLightManager> .Allocate(); // Replicate the logic of the original one... int index = shape - LightShape.Cone - 1; if (index < shapes.Count) { // Found handler! shapes[index].FillLight(CallingObject, origin, (int)radius, cells); foreach (var pair in cells) { int cell = pair.Key; if (Grid.IsValidCell(cell)) { // Allow any fraction, not just linear falloff int lightValue = (int)Math.Round(lux * pair.Value); LightGridManager.previewLightCells.Add(new Tuple <int, int>(cell, lightValue)); LightGridManager.previewLux[cell] = lightValue; } } CallingObject = null; handled = true; } cells.Recycle(); } return(handled); }
/// <summary> /// /// </summary> /// <param name="binaryReader"></param> public override void Deserialize(BinaryReader binaryReader) { base.Deserialize(binaryReader); #if UNITY_2019_1_OR_NEWER lightShape = (LightShape)binaryReader.ReadInt32(); colorTemperature = binaryReader.ReadSingle(); useColorTemperature = binaryReader.ReadBoolean(); renderingLayerMask = binaryReader.ReadInt32(); #endif lightType = (LightType)binaryReader.ReadInt32(); range = binaryReader.ReadSingle(); spotAngle = binaryReader.ReadSingle(); innerSpotAngle = binaryReader.ReadSingle(); cookieSize = binaryReader.ReadSingle(); m_colorKun = SerializerKun.DesirializeObject <ColorKun>(binaryReader); intensity = binaryReader.ReadSingle(); bounceIntensity = binaryReader.ReadSingle(); cookie = binaryReader.ReadString(); shadowsType = (LightShadows)binaryReader.ReadInt32(); shadowsStrength = binaryReader.ReadSingle(); shadowsResolution = (UnityEngine.Rendering.LightShadowResolution)binaryReader.ReadInt32(); shadowsBias = binaryReader.ReadSingle(); shadowsNormalBias = binaryReader.ReadSingle(); shadowsNearPlane = binaryReader.ReadSingle(); halo = binaryReader.ReadBoolean(); flare = binaryReader.ReadString(); renderMode = (LightRenderMode)binaryReader.ReadInt32(); cullingMask = binaryReader.ReadInt32(); }
LightUnit LightIntensityUnitPopup(LightShape shape) { LightUnit selectedLightUnit; LightUnit oldLigthUnit = (LightUnit)m_AdditionalLightData.lightUnit.enumValueIndex; EditorGUI.BeginChangeCheck(); switch (shape) { case LightShape.Directional: selectedLightUnit = (LightUnit)EditorGUILayout.EnumPopup((DirectionalLightUnit)m_AdditionalLightData.lightUnit.enumValueIndex); break; case LightShape.Point: case LightShape.Spot: selectedLightUnit = (LightUnit)EditorGUILayout.EnumPopup((PunctualLightUnit)m_AdditionalLightData.lightUnit.enumValueIndex); break; default: selectedLightUnit = (LightUnit)EditorGUILayout.EnumPopup((AreaLightUnit)m_AdditionalLightData.lightUnit.enumValueIndex); break; } if (EditorGUI.EndChangeCheck()) { ConvertLightIntensity(oldLigthUnit, selectedLightUnit); } return(selectedLightUnit); }
static LightUnit LightIntensityUnitPopup(SerializedHDLight serialized, Editor owner) { LightShape shape = serialized.editorLightShape; LightUnit selectedLightUnit; LightUnit oldLigthUnit = (LightUnit)serialized.serializedLightData.lightUnit.enumValueIndex; EditorGUI.BeginChangeCheck(); switch (shape) { case LightShape.Directional: selectedLightUnit = (LightUnit)EditorGUILayout.EnumPopup((DirectionalLightUnit)serialized.serializedLightData.lightUnit.enumValueIndex); break; case LightShape.Point: selectedLightUnit = (LightUnit)EditorGUILayout.EnumPopup((PunctualLightUnit)serialized.serializedLightData.lightUnit.enumValueIndex); break; case LightShape.Spot: if ((SpotLightShape)serialized.serializedLightData.spotLightShape.enumValueIndex == SpotLightShape.Box) selectedLightUnit = (LightUnit)EditorGUILayout.EnumPopup((DirectionalLightUnit)serialized.serializedLightData.lightUnit.enumValueIndex); else selectedLightUnit = (LightUnit)EditorGUILayout.EnumPopup((PunctualLightUnit)serialized.serializedLightData.lightUnit.enumValueIndex); break; default: selectedLightUnit = (LightUnit)EditorGUILayout.EnumPopup((AreaLightUnit)serialized.serializedLightData.lightUnit.enumValueIndex); break; } if (EditorGUI.EndChangeCheck()) ConvertLightIntensity(oldLigthUnit, selectedLightUnit, serialized, owner); return selectedLightUnit; }
/// <summary> /// Applied to LightGridManager to properly preview a new light source. /// /// RadiationGridManager.CreatePreview has no references so no sense in patching that /// yet. /// </summary> private static bool CreatePreview_Prefix(int origin_cell, float radius, LightShape shape, int lux) { var lm = PLightManager.Instance; return(lm == null || !lm.PreviewLight(origin_cell, radius, shape, lux)); }
protected override void UpdateMeshData(bool forceUpdate = false) { if (Application.isPlaying == false) { return; } if (IsPartOfStaticBatch) { return; } var objMat = transform.localToWorldMatrix; if (!objMat.FastEquals(_modelMatrix) || _oldLightOrigin != LightOrigin || _oldLightShape != Shape || forceUpdate) { _modelMatrix = objMat; _oldLightOrigin = LightOrigin; _oldLightShape = Shape; UpdatePosition(); _isMeshDirty = true; } base.UpdateMeshData(forceUpdate); }
internal PRemoteLightWrapper(object other) { if (other == null) { throw new ArgumentNullException(nameof(other)); } if (!PPatchTools.TryGetPropertyValue(other, nameof(ILightShape.KleiLightShape), out LightShape ls)) { throw new ArgumentException("Light shape is missing KleiLightShape"); } KleiLightShape = ls; if (!PPatchTools.TryGetPropertyValue(other, nameof(ILightShape.Identifier), out string id) || id == null) { throw new ArgumentException("Light shape is missing KleiLightShape"); } Identifier = id; if (!PPatchTools.TryGetPropertyValue(other, nameof(ILightShape.RayMode), out LightShape rm)) { rm = (LightShape)(-1); } RayMode = rm; var otherType = other.GetType(); fillLight = otherType.CreateDelegate <FillLightDelegate>(nameof(PLightShape. DoFillLight), other, typeof(GameObject), typeof(int), typeof(int), typeof(BrightnessDict)); if (fillLight == null) { throw new ArgumentException("Light shape is missing FillLight"); } }
/// <summary> /// Handles a lighting system call. Not intended to be used - exists as a fallback. /// </summary> /// <param name="cell">The origin cell.</param> /// <param name="visiblePoints">The location where lit points will be stored.</param> /// <param name="range">The light radius.</param> /// <param name="shape">The light shape.</param> /// <returns>true if the lighting was handled, or false otherwise.</returns> internal bool GetVisibleCells(int cell, IList <int> visiblePoints, int range, LightShape shape) { int index = shape - LightShape.Cone - 1; bool handled = false; if (index >= 0 && index < shapes.Count) { var ps = shapes[index]; // Do what we can, this only is reachable through methods we have patched var lux = DictionaryPool <int, float, PLightManager> .Allocate(); #if DEBUG PUtil.LogWarning("Unpatched call to GetVisibleCells; use LightGridEmitter." + "UpdateLitCells instead."); #endif ps.FillLight(CallingObject, cell, range, lux); // Intensity does not matter foreach (var point in lux) { visiblePoints.Add(point.Key); } lux.Recycle(); handled = true; } return(handled); }
internal PLightShape(int id, string identifier, PLightManager.CastLightDelegate handler, LightShape rayMode) { this.handler = handler ?? throw new ArgumentNullException(nameof(handler)); Identifier = identifier ?? throw new ArgumentNullException(nameof(identifier)); RayMode = rayMode; ShapeID = id; }
public RadiationGridEmitter(int cell, List <int> lit_cells, int intensity, float radius, LightShape shape, float falloffRate = 0.5f) { this.cell = cell; this.radius = radius; this.intensity = intensity; this.shape = shape; litCells = lit_cells; this.falloffRate = falloffRate; }
public LightKun(Component component) : base(component) { componentKunType = BehaviourKun.ComponentKunType.Light; cookie = ""; flare = ""; m_colorKun = new ColorKun(); var light = component as Light; if (light) { #if UNITY_2019_1_OR_NEWER lightShape = light.shape; useColorTemperature = light.useColorTemperature; colorTemperature = light.colorTemperature; renderingLayerMask = light.renderingLayerMask; #endif enabled = light.enabled; lightType = light.type; range = light.range; spotAngle = light.spotAngle; innerSpotAngle = light.spotAngle; cookieSize = light.cookieSize; if (light.cookie != null) { cookie = light.cookie.name; } else { cookie = ""; } if (light.flare != null) { flare = light.flare.name; } else { flare = ""; } color = light.color; intensity = light.intensity; bounceIntensity = light.bounceIntensity; shadowsType = light.shadows; shadowsStrength = light.shadowStrength; shadowsBias = light.shadowBias; shadowsNormalBias = light.shadowNormalBias; shadowsNormalBias = light.shadowNormalBias; // halo renderMode = light.renderMode; cullingMask = light.cullingMask; } }
/// <summary> /// Applied to DiscreteShadowCaster to handle lighting requests. /// </summary> private static bool GetVisibleCells_Prefix(int cell, List <int> visiblePoints, int range, LightShape shape) { bool exec = true; var lm = PLightManager.Instance; if (shape != LightShape.Circle && shape != LightShape.Cone && lm != null) { // This is not a customer scenario exec = !lm.GetVisibleCells(cell, visiblePoints, range, shape); } return(exec); }
/// <summary> /// Checks to see if a light has specified one of the built-in ray options to cast /// the little yellow rays around it. /// </summary> /// <param name="shape">The light shape to check.</param> /// <returns>The light shape to use for ray casting, or the original shape if it is /// a stock shape or a light shape not known to PLib Lighting.</returns> internal LightShape GetRayShape(LightShape shape) { int index = shape - LightShape.Cone - 1; ILightShape ps; if (index >= 0 && index < shapes.Count && (ps = shapes[index]) != null) { var newShape = ps.RayMode; if (newShape >= LightShape.Circle) { shape = newShape; } } return(shape); }
public Light(int x, int y, LightCircuit circuit, LightColor color, LightShape shape) { Assembly assembly = Assembly.GetExecutingAssembly(); string lightName = Enum.GetName(color.GetType(), color).ToLower(); string resourceOn = string.Format("JamesAllen.XmasLights.Images.{0}_on.png", lightName); string resourceOff = string.Format("JamesAllen.XmasLights.Images.{0}_off.png", lightName); Stream streamOn = assembly.GetManifestResourceStream(resourceOn); Stream streamOff = assembly.GetManifestResourceStream(resourceOff); imageOn = (Image)Bitmap.FromStream(streamOn); imageOff = (Image)Bitmap.FromStream(streamOff); this.position = new Point(x, y); this.circuit = circuit; this.color = color; this.shape = shape; }
void ResolveLightShape() { var type = settings.lightType; // Special case for multi-selection: don't resolve light shape or it'll corrupt lights if (type.hasMultipleDifferentValues || serializedLightData.lightTypeExtent.hasMultipleDifferentValues) { editorLightShape = (LightShape)(-1); return; } editorLightShape = ResolveLightShape( (LightTypeExtent)serializedLightData.lightTypeExtent.enumValueIndex, (LightType)type.enumValueIndex ); }
void ResolveLightShape() { var type = settings.lightType; // Special case for multi-selection: don't resolve light shape or it'll corrupt lights if (type.hasMultipleDifferentValues || m_AdditionalLightData.lightTypeExtent.hasMultipleDifferentValues) { m_LightShape = (LightShape)(-1); return; } var lightTypeExtent = (LightTypeExtent)m_AdditionalLightData.lightTypeExtent.enumValueIndex; if (lightTypeExtent == LightTypeExtent.Punctual) { switch ((LightType)type.enumValueIndex) { case LightType.Directional: m_LightShape = LightShape.Directional; break; case LightType.Point: m_LightShape = LightShape.Point; break; case LightType.Spot: m_LightShape = LightShape.Spot; break; } } else { switch (lightTypeExtent) { case LightTypeExtent.Rectangle: m_LightShape = LightShape.Rectangle; break; case LightTypeExtent.Line: m_LightShape = LightShape.Line; break; } } }
protected override void UpdateMeshData(bool forceUpdate = false) { if (IsPartOfStaticBatch) return; var objMat = transform.localToWorldMatrix; if (!objMat.FastEquals(_modelMatrix) || _oldLightOrigin != LightOrigin || _oldLightShape != Shape || forceUpdate) { _modelMatrix = objMat; _oldLightOrigin = LightOrigin; _oldLightShape = Shape; UpdatePosition(); _isMeshDirty = true; } base.UpdateMeshData(forceUpdate); }
void ResolveLightShape() { var type = m_BaseData.type; if (type.hasMultipleDifferentValues) { m_LightShape = (LightShape)(-1); return; } var lightTypeExtent = (LightTypeExtent)m_AdditionalLightData.lightTypeExtent.enumValueIndex; if (lightTypeExtent == LightTypeExtent.Punctual) { switch ((LightType)type.enumValueIndex) { case LightType.Directional: m_LightShape = LightShape.Directional; break; case LightType.Point: m_LightShape = LightShape.Point; break; case LightType.Spot: m_LightShape = LightShape.Spot; break; } } else { switch (lightTypeExtent) { case LightTypeExtent.Rectangle: m_LightShape = LightShape.Rectangle; break; case LightTypeExtent.Line: m_LightShape = LightShape.Line; break; } } }
void ResolveLightShape() { var type = settings.lightType; // Special case for multi-selection: don't resolve light shape or it'll corrupt lights if (type.hasMultipleDifferentValues || serializedLightData.lightTypeExtent.hasMultipleDifferentValues) { editorLightShape = (LightShape)(-1); return; } var lightTypeExtent = (LightTypeExtent)serializedLightData.lightTypeExtent.enumValueIndex; switch (lightTypeExtent) { case LightTypeExtent.Punctual: switch ((LightType)type.enumValueIndex) { case LightType.Directional: editorLightShape = LightShape.Directional; break; case LightType.Point: editorLightShape = LightShape.Point; break; case LightType.Spot: editorLightShape = LightShape.Spot; break; } break; case LightTypeExtent.Rectangle: editorLightShape = LightShape.Rectangle; break; case LightTypeExtent.Tube: editorLightShape = LightShape.Tube; break; } }
static void DrawLightIntensityUnitPopup(SerializedHDLight serialized, Editor owner) { LightShape shape = serialized.editorLightShape; LightUnit selectedLightUnit; LightUnit oldLigthUnit = (LightUnit)serialized.serializedLightData.lightUnit.enumValueIndex; EditorGUI.showMixedValue = serialized.serializedLightData.lightUnit.hasMultipleDifferentValues; EditorGUI.BeginChangeCheck(); switch (shape) { case LightShape.Directional: selectedLightUnit = (LightUnit)EditorGUILayout.EnumPopup((DirectionalLightUnit)serialized.serializedLightData.lightUnit.enumValueIndex); break; case LightShape.Point: selectedLightUnit = (LightUnit)EditorGUILayout.EnumPopup((PunctualLightUnit)serialized.serializedLightData.lightUnit.enumValueIndex); break; case LightShape.Spot: if ((SpotLightShape)serialized.serializedLightData.spotLightShape.enumValueIndex == SpotLightShape.Box) { selectedLightUnit = (LightUnit)EditorGUILayout.EnumPopup((DirectionalLightUnit)serialized.serializedLightData.lightUnit.enumValueIndex); } else { selectedLightUnit = (LightUnit)EditorGUILayout.EnumPopup((PunctualLightUnit)serialized.serializedLightData.lightUnit.enumValueIndex); } break; default: selectedLightUnit = (LightUnit)EditorGUILayout.EnumPopup((AreaLightUnit)serialized.serializedLightData.lightUnit.enumValueIndex); break; } EditorGUI.showMixedValue = false; if (EditorGUI.EndChangeCheck()) { ConvertLightIntensity(oldLigthUnit, selectedLightUnit, serialized, owner); serialized.serializedLightData.lightUnit.enumValueIndex = (int)selectedLightUnit; } }
public static void CreatePreview(int origin_cell, float radius, LightShape shape, int lux) { previewLightCells.Clear(); ListPool <int, RadiationGridEmitter> .PooledList pooledList = ListPool <int, RadiationGridEmitter> .Allocate(); pooledList.Add(origin_cell); DiscreteShadowCaster.GetVisibleCells(origin_cell, pooledList, (int)radius, shape); int num = 0; foreach (int item in pooledList) { if (Grid.IsValidCell(item)) { num = lux / CalculateFalloff(0.5f, item, origin_cell); previewLightCells.Add(new Tuple <int, int>(item, num)); previewLux[item] = num; } } pooledList.Recycle(); }
/// <summary> /// Registers a light shape handler. /// </summary> /// <param name="identifier">A unique identifier for this shape. If another mod has /// already registered that identifier, the previous mod will take precedence.</param> /// <param name="handler">The handler for that shape.</param> /// <param name="rayMode">The type of visual rays that are displayed from the light.</param> /// <returns>The light shape which can be used.</returns> public ILightShape Register(string identifier, CastLightDelegate handler, LightShape rayMode = (LightShape)(-1)) { if (string.IsNullOrEmpty(identifier)) { throw new ArgumentNullException(nameof(identifier)); } if (handler == null) { throw new ArgumentNullException(nameof(handler)); } ILightShape lightShape = null; RegisterForForwarding(); // Try to find a match for this identifier var registered = GetSharedData(EMPTY_SHAPES); int n = registered.Count; foreach (var obj in registered) { var light = PRemoteLightWrapper.LightToInstance(obj); // Might be from another assembly so the types may or may not be compatible if (light != null && light.Identifier == identifier) { LogLightingDebug("Found existing light shape: " + identifier + " from " + (obj.GetType().Assembly.GetNameSafe() ?? "?")); lightShape = light; break; } } if (lightShape == null) { // Not currently existing lightShape = new PLightShape(n + 1, identifier, handler, rayMode); LogLightingDebug("Registered new light shape: " + identifier); registered.Add(lightShape); } return(lightShape); }
void DrawShape() { EditorGUI.BeginChangeCheck(); // For GI we need to detect any change on additional data and call SetLightDirty + For intensity we need to detect light shape change m_LightShape = (LightShape)EditorGUILayout.Popup(s_Styles.shape, (int)m_LightShape, s_Styles.shapeNames); if (m_LightShape != LightShape.Directional) { settings.DrawRange(false); } // LightShape is HD specific, it need to drive LightType from the original LightType // when it make sense, so the GI is still in sync with the light shape switch (m_LightShape) { case LightShape.Directional: settings.lightType.enumValueIndex = (int)LightType.Directional; m_AdditionalLightData.lightTypeExtent.enumValueIndex = (int)LightTypeExtent.Punctual; break; case LightShape.Point: settings.lightType.enumValueIndex = (int)LightType.Point; m_AdditionalLightData.lightTypeExtent.enumValueIndex = (int)LightTypeExtent.Punctual; EditorGUILayout.PropertyField(m_AdditionalLightData.maxSmoothness, s_Styles.maxSmoothness); break; case LightShape.Spot: settings.lightType.enumValueIndex = (int)LightType.Spot; m_AdditionalLightData.lightTypeExtent.enumValueIndex = (int)LightTypeExtent.Punctual; EditorGUILayout.PropertyField(m_AdditionalLightData.spotLightShape, s_Styles.spotLightShape); var spotLightShape = (SpotLightShape)m_AdditionalLightData.spotLightShape.enumValueIndex; // Cone Spot if (spotLightShape == SpotLightShape.Cone) { settings.DrawSpotAngle(); EditorGUILayout.Slider(m_AdditionalLightData.spotInnerPercent, 0f, 100f, s_Styles.spotInnerPercent); } // TODO : replace with angle and ratio else if (spotLightShape == SpotLightShape.Pyramid) { settings.DrawSpotAngle(); EditorGUILayout.Slider(m_AdditionalLightData.aspectRatio, 0.05f, 20.0f, s_Styles.aspectRatioPyramid); } else if (spotLightShape == SpotLightShape.Box) { EditorGUILayout.PropertyField(m_AdditionalLightData.shapeWidth, s_Styles.shapeWidthBox); EditorGUILayout.PropertyField(m_AdditionalLightData.shapeHeight, s_Styles.shapeHeightBox); } EditorGUILayout.PropertyField(m_AdditionalLightData.maxSmoothness, s_Styles.maxSmoothness); break; case LightShape.Rectangle: // TODO: Currently if we use Area type as it is offline light in legacy, the light will not exist at runtime //m_BaseData.type.enumValueIndex = (int)LightType.Area; // In case of change, think to update InitDefaultHDAdditionalLightData() settings.lightType.enumValueIndex = (int)LightType.Point; m_AdditionalLightData.lightTypeExtent.enumValueIndex = (int)LightTypeExtent.Rectangle; EditorGUILayout.PropertyField(m_AdditionalLightData.shapeWidth, s_Styles.shapeWidthRect); EditorGUILayout.PropertyField(m_AdditionalLightData.shapeHeight, s_Styles.shapeHeightRect); m_AdditionalLightData.shapeWidth.floatValue = Mathf.Max(m_AdditionalLightData.shapeWidth.floatValue, k_MinAreaWidth); m_AdditionalLightData.shapeHeight.floatValue = Mathf.Max(m_AdditionalLightData.shapeHeight.floatValue, k_MinAreaWidth); settings.areaSizeX.floatValue = m_AdditionalLightData.shapeWidth.floatValue; settings.areaSizeY.floatValue = m_AdditionalLightData.shapeHeight.floatValue; settings.shadowsType.enumValueIndex = (int)LightShadows.None; break; case LightShape.Line: // TODO: Currently if we use Area type as it is offline light in legacy, the light will not exist at runtime //m_BaseData.type.enumValueIndex = (int)LightType.Area; settings.lightType.enumValueIndex = (int)LightType.Point; m_AdditionalLightData.lightTypeExtent.enumValueIndex = (int)LightTypeExtent.Line; EditorGUILayout.PropertyField(m_AdditionalLightData.shapeWidth, s_Styles.shapeWidthLine); m_AdditionalLightData.shapeWidth.floatValue = Mathf.Max(m_AdditionalLightData.shapeWidth.floatValue, k_MinAreaWidth); m_AdditionalLightData.shapeHeight.floatValue = Mathf.Max(m_AdditionalLightData.shapeHeight.floatValue, k_MinAreaWidth); // Fake line with a small rectangle in vanilla unity for GI settings.areaSizeX.floatValue = m_AdditionalLightData.shapeWidth.floatValue; settings.areaSizeY.floatValue = k_MinAreaWidth; settings.shadowsType.enumValueIndex = (int)LightShadows.None; break; case (LightShape)(-1): // don't do anything, this is just to handle multi selection break; default: Debug.Assert(false, "Not implemented light type"); break; } if (EditorGUI.EndChangeCheck()) { UpdateLightIntensity(); ((Light)target).SetLightDirty(); // Should be apply only to parameter that's affect GI, but make the code cleaner } }
void DrawShape() { m_LightShape = (LightShape)EditorGUILayout.Popup(s_Styles.shape, (int)m_LightShape, s_Styles.shapeNames); // LightShape is HD specific, it need to drive LightType from the original LightType // when it make sense, so the GI is still in sync with the light shape switch (m_LightShape) { case LightShape.Directional: m_BaseData.type.enumValueIndex = (int)LightType.Directional; m_AdditionalLightData.lightTypeExtent.enumValueIndex = (int)LightTypeExtent.Punctual; break; case LightShape.Point: m_BaseData.type.enumValueIndex = (int)LightType.Point; m_AdditionalLightData.lightTypeExtent.enumValueIndex = (int)LightTypeExtent.Punctual; EditorGUILayout.PropertyField(m_AdditionalLightData.maxSmoothness, s_Styles.maxSmoothness); break; case LightShape.Spot: m_BaseData.type.enumValueIndex = (int)LightType.Spot; m_AdditionalLightData.lightTypeExtent.enumValueIndex = (int)LightTypeExtent.Punctual; EditorGUILayout.PropertyField(m_AdditionalLightData.spotLightShape, s_Styles.spotLightShape); var spotLightShape = (SpotLightShape)m_AdditionalLightData.spotLightShape.enumValueIndex; // Cone Spot if (spotLightShape == SpotLightShape.Cone) { EditorGUILayout.Slider(m_BaseData.spotAngle, 0f, 179.9f, s_Styles.spotAngle); EditorGUILayout.Slider(m_AdditionalLightData.spotInnerPercent, 0f, 100f, s_Styles.spotInnerPercent); } // TODO : replace with angle and ratio else if (spotLightShape == SpotLightShape.Pyramid) { EditorGUILayout.Slider(m_BaseData.spotAngle, 0f, 179.9f, s_Styles.spotAngle); EditorGUILayout.Slider(m_AdditionalLightData.aspectRatio, 0.05f, 20.0f, s_Styles.aspectRatioPyramid); } else if (spotLightShape == SpotLightShape.Box) { EditorGUILayout.PropertyField(m_AdditionalLightData.shapeLength, s_Styles.shapeLengthBox); EditorGUILayout.PropertyField(m_AdditionalLightData.shapeWidth, s_Styles.shapeWidthBox); } EditorGUILayout.PropertyField(m_AdditionalLightData.maxSmoothness, s_Styles.maxSmoothness); break; case LightShape.Rectangle: // TODO: Currently if we use Area type as it is offline light in legacy, the light will not exist at runtime //m_BaseData.type.enumValueIndex = (int)LightType.Area; m_BaseData.type.enumValueIndex = (int)LightType.Point; m_AdditionalLightData.lightTypeExtent.enumValueIndex = (int)LightTypeExtent.Rectangle; EditorGUILayout.PropertyField(m_AdditionalLightData.shapeLength, s_Styles.shapeLengthRect); EditorGUILayout.PropertyField(m_AdditionalLightData.shapeWidth, s_Styles.shapeWidthRect); m_BaseData.areaSizeX.floatValue = m_AdditionalLightData.shapeLength.floatValue; m_BaseData.areaSizeY.floatValue = m_AdditionalLightData.shapeWidth.floatValue; m_BaseData.shadowsType.enumValueIndex = (int)LightShadows.None; break; case LightShape.Line: // TODO: Currently if we use Area type as it is offline light in legacy, the light will not exist at runtime //m_BaseData.type.enumValueIndex = (int)LightType.Area; m_BaseData.type.enumValueIndex = (int)LightType.Point; m_AdditionalLightData.lightTypeExtent.enumValueIndex = (int)LightTypeExtent.Line; EditorGUILayout.PropertyField(m_AdditionalLightData.shapeLength, s_Styles.shapeLengthLine); // Fake line with a small rectangle in vanilla unity for GI m_BaseData.areaSizeX.floatValue = m_AdditionalLightData.shapeLength.floatValue; m_BaseData.areaSizeY.floatValue = 0.01f; m_BaseData.shadowsType.enumValueIndex = (int)LightShadows.None; break; case (LightShape)(-1): // don't do anything, this is just to handle multi selection break; default: Debug.Assert(false, "Not implemented light type"); break; } }
bool IsAreaLightShape(LightShape shape) { return(shape == LightShape.Rectangle || shape == LightShape.Line); }
// private static readonly HashSet<string> _MESH_TILE_IDS = new HashSet<string> {MeshTileConfig.ID, GasPermeableMembraneConfig.ID}; public static void GetVisibleCells(int cell, List <int> visiblePoints, int range, LightShape shape) { Predicate <int> occludeFilter; // if (Patches.settings.LightThroughMeshTiles) // { // var meshCellLookup = Components.BuildingCompletes.Items // .Where(complete => _MESH_TILE_IDS.Contains(complete.PrefabID().ToString())) // .ToLookup(complete => complete.GetCell()); // occludeFilter = pointCell => // { // if (!DoesOcclude(pointCell)) return false; // // 阻塞 // var gameObject = Grid.Objects[pointCell, (int) ObjectLayer.Building]; // if (gameObject == null) return true; // var complete = gameObject.GetComponent<BuildingComplete>(); // if (complete == null) return true; // return !_MESH_TILE_IDS.Contains(complete.PrefabID().ToString()); // }; // } // else { occludeFilter = DoesOcclude; } if (occludeFilter.Invoke(cell)) { return; } var origin = Grid.CellToXY(cell); var lightArea = LightArea.Create(range, Vector2.zero); ICellEnumerator enumerator; switch (shape) { case LightShape.Circle: enumerator = new RectBorder(origin, range); break; case LightShape.Cone: enumerator = new TrapezoidLayer(origin, range); break; default: throw new ArgumentOutOfRangeException(nameof(shape), shape, null); } foreach (var point in enumerator) { /* * - 不透光,边界判断 * - 相交,扩充已有扇区 * - 不相交,添加新扇区 * - 透光,中心判断 * - 在扇区内,被遮挡 * - 在扇区外,有光 */ var deltaPoint = point - origin; if (!lightArea.InRange(deltaPoint)) { // exceed continue; } var pointCell = Grid.PosToCell(point); if (occludeFilter.Invoke(pointCell)) { // 不透光,更新障碍 lightArea.AddCellBlock(deltaPoint); } else if (!lightArea.IsBlocking(deltaPoint)) { // 透光,不被遮挡 visiblePoints.Add(pointCell); } } }
public static bool Prefix(int cell, List <int> visiblePoints, int range, LightShape shape) { LightGridTool.GetVisibleCells(cell, visiblePoints, range, shape); return(false); }
public static void GetVisibleCells(int cell, List <int> visiblePoints, int range, LightShape shape) { visiblePoints.Add(cell); Vector2I cellPos = Grid.CellToXY(cell); switch (shape) { case LightShape.Circle: ScanOctant(cellPos, range, 1, Octant.N_NW, 1.0, 0.0, visiblePoints); ScanOctant(cellPos, range, 1, Octant.N_NE, 1.0, 0.0, visiblePoints); ScanOctant(cellPos, range, 1, Octant.E_NE, 1.0, 0.0, visiblePoints); ScanOctant(cellPos, range, 1, Octant.E_SE, 1.0, 0.0, visiblePoints); ScanOctant(cellPos, range, 1, Octant.S_SE, 1.0, 0.0, visiblePoints); ScanOctant(cellPos, range, 1, Octant.S_SW, 1.0, 0.0, visiblePoints); ScanOctant(cellPos, range, 1, Octant.W_SW, 1.0, 0.0, visiblePoints); ScanOctant(cellPos, range, 1, Octant.W_NW, 1.0, 0.0, visiblePoints); break; case LightShape.Cone: ScanOctant(cellPos, range, 1, Octant.S_SE, 1.0, 0.0, visiblePoints); ScanOctant(cellPos, range, 1, Octant.S_SW, 1.0, 0.0, visiblePoints); break; } }