/// <summary> /// Converts a PLightShape into this mod's namespace. /// </summary> /// <param name="otherShape">The shape from the shared data.</param> /// <returns>An equivalent shape in this mod's namespace.</returns> private static PLightShape LightToInstance(object otherShape) { var shape = otherShape as PLightShape; if (shape == null) { var trLight = Traverse.Create(otherShape); // Retrieve the ID, handler, and identifier int id = trLight.GetProperty <int>("ShapeID"); if (id > 0) { string identifer = trLight.GetProperty <string>("Identifier") ?? ("LightShape" + id); shape = new PLightShape(id, identifer, new CrossModLightWrapper(trLight). CastLight); } else { // Some invalid object got in there somehow PUtil.LogWarning("Found light shape {0} with bad ID {1:D}!".F(otherShape, id)); } } return(shape); }
/// <summary> /// Adds an octant of light. /// </summary> /// <param name="range">The range of the light.</param> /// <param name="octant">The octant to scan.</param> /// <returns>This object, for call chaining.</returns> public OctantBuilder AddOctant(int range, Octant octant) { var points = ListPool <int, OctantBuilder> .Allocate(); OCTANT_SCAN?.Invoke(null, new object[] { Grid.CellToXY(SourceCell), range, 1, octant, 1.0, 0.0, points }); // Transfer to our array using: foreach (int cell in points) { float intensity; if (SmoothLight) { // Better, not rounded falloff intensity = PLightShape.GetSmoothFalloff(Falloff, cell, SourceCell); } else { // Default falloff intensity = PLightShape.GetDefaultFalloff(Falloff, cell, SourceCell); } destination[cell] = intensity; } points.Recycle(); return(this); }
/// <summary> /// Converts a PLightShape into this mod's namespace. /// </summary> /// <param name="otherShape">The shape from the shared data.</param> /// <returns>An equivalent shape in this mod's namespace.</returns> private static PLightShape LightToInstance(object otherShape) { var shape = otherShape as PLightShape; if (shape == null) { var otherType = otherShape.GetType(); // Retrieve properties via reflection var propID = otherType.GetPropertySafe <int>(nameof(PLightShape.ShapeID), false); var propName = otherType.GetPropertySafe <string>(nameof(PLightShape. Identifier), false); var fillLight = otherType.CreateDelegate <FillLightFunc>(nameof(PLightShape. FillLight), otherShape, typeof(GameObject), typeof(int), typeof(int), typeof(BrightnessDict)); try { // Retrieve the ID, handler, and identifier if (fillLight == null) { PUtil.LogWarning("PLightSource handler has invalid method signature!"); } else if (propID.GetValue(otherShape, null) is int id && id > 0) { shape = new PLightShape(id, (propName.GetValue(otherShape, null) as string) ?? ("LightShape" + id), new CrossModLightWrapper( fillLight).CastLight); } else { // Some invalid object got in there somehow PUtil.LogWarning("Found light shape {0} with bad ID!".F(otherShape)); } } catch (TargetInvocationException e) {
/// <summary> /// Gets the brightness at a given cell for the specified light source. /// </summary> /// <param name="source">The source of the light.</param> /// <param name="location">The location to check.</param> /// <param name="state">The lighting state.</param> /// <param name="result">The brightness there.</param> /// <returns>true if that brightness is valid, or false otherwise.</returns> internal bool GetBrightness(LightGridEmitter source, int location, LightGridEmitter.State state, out int result) { bool valid; CacheEntry cacheEntry; var shape = state.shape; if (shape != LightShape.Cone && shape != LightShape.Circle) { lock (brightCache) { // Shared access to the cache valid = brightCache.TryGetValue(source, out cacheEntry); } if (valid) { valid = cacheEntry.Intensity.TryGetValue(location, out float ratio); if (valid) { result = Mathf.RoundToInt(cacheEntry.BaseLux * ratio); } else { #if DEBUG PUtil.LogDebug("GetBrightness for invalid cell at {0:D}".F(location)); #endif result = 0; } } else { #if DEBUG PUtil.LogDebug("GetBrightness for invalid emitter at {0:D}".F(location)); #endif result = 0; valid = false; } } else if (ForceSmoothLight) { // Use smooth light even for vanilla Cone and Circle result = Mathf.RoundToInt(state.intensity * PLightShape.GetSmoothFalloff( state.falloffRate, location, state.origin)); valid = true; } else { // Stock result = 0; valid = false; } return(valid); }
/// <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> /// <returns>The light shape which can be used.</returns> public static PLightShape Register(string identifier, CastLight handler) { PLightShape lightShape; // In case this call is used before the library was initialized if (!PUtil.PLibInit) { PUtil.InitLibrary(false); PUtil.LogWarning("PUtil.InitLibrary was not called before using " + "PLightShape.Register!"); } lock (PSharedData.GetLock(PRegistry.KEY_LIGHTING_LOCK)) { // Get list holding lighting information var list = PSharedData.GetData <IList <object> >(PRegistry.KEY_LIGHTING_TABLE); if (list == null) { PSharedData.PutData(PRegistry.KEY_LIGHTING_TABLE, list = new List <object>(8)); } // Try to find a match for this identifier object ls = null; int n = list.Count, index = 0; for (int i = 0; i < n; i++) { var light = list[i]; // Might be from another assembly so the types may or may not be compatible if (light != null && light.ToString() == identifier && light.GetType(). Name == typeof(PLightShape).Name) { index = i; break; } } if (ls == null) { // Not currently existing lightShape = new PLightShape(n + 1, identifier, handler); PUtil.LogDebug("Registered new light shape: " + identifier); list.Add(lightShape); } else { // Exists already PUtil.LogDebug("Found existing light shape: " + identifier); lightShape = new PLightShape(n + 1, identifier, null); } } return(lightShape); }
/// <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); }