Skip to content

Default place lighting isn't set up correctly. #97

Description

@whoamimaybeme

When a place already has lighting instances before the kit is ran, the LightingManager checks some of those instances and stores their values to use as the PlaceDefault. However, this is only ran on the lighting instances that have defaults different than what Roblox uses. This means that some lighting instances may have two of them. This ain't good, because tower lighting may be inaccurate due to these instances existing.

Image

I've fixed these issues in the following code. The fixes are

  • Change local lightingInstance = if config.Type == "Lighting" then Lighting else lightingInstances[config.Type] to local lightingInstance = lightingInstances[config.Type] in the ChangeLighting function because of any lighting instance being added to the lightingInstances table
  • updates for property, value in thisConfig :: any do to resolve You can change properties on lighting items that aren't actually in the CONFIGURABLE_PROPERTIES table of the LightingManager #84, disallows Enabled from being set to Lighting since that property doesn't exist, and prevents EnumItems from being tweened because i dont think you can tween them.
  • rewrites most of the Init function
  • Adds support for ColorGradingEffect
--!strict
--!optimize 2
-- By @synnwave (09/12/24 DD/MM/YY)

--[[
--------------------------------------------------------------------------------
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
⚠️  WARNING - PLEASE READ! ⚠️
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

If you are submitting to EToH: 
PLEASE, **DO NOT** make any script edits to this script. 
This is a core script and any edits you make to this script will NOT work 
elsewhere.

If you have any suggestions, please let us know.
Thank you
--------------------------------------------------------------------------------
]]

--[=[
    @class LightingManager
    @client
    
    Manager module responsible for the functionality of Lighting Changers
    and other things generally related to lighting.
]=]

--[[
---------------------------------------------------------------------------
Services, modules and other objects
---------------------------------------------------------------------------
]]

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Lighting = game:GetService("Lighting")
local TweenService = game:GetService("TweenService")

local Framework = ReplicatedStorage.Framework
local _TDefs = require(script.TypeDefs)

--[[
---------------------------------------------------------------------------
Constants
---------------------------------------------------------------------------
]]

local CONFIGURABLE_PROPERTIES = {
	ColorCorrectionEffect = { "Brightness", "Contrast", "Saturation", "TintColor" },
	BlurEffect = { "Size" },
	Lighting = {
		"Ambient",
		"Brightness",
		"ClockTime",
		"ColorShift_Bottom",
		"ColorShift_Top",
		"EnvironmentDiffuseScale",
		"EnvironmentSpecularScale",
		"ExposureCompensation",
		"FogColor",
		"FogEnd",
		"FogStart",
		"GeographicLatitude",
		"GlobalShadows",
		"OutdoorAmbient",
		"ShadowSoftness",
		"TimeOfDay",
	},
	BloomEffect = { "Intensity", "Size", "Threshold" },
	DepthOfFieldEffect = { "FarIntensity", "FocusDistance", "InFocusRadius", "NearIntensity" },
	SunRaysEffect = { "Intensity", "Spread"},
	ColorGradingEffect = { "TonemapperPreset" },
	Atmosphere = { "Density", "Offset", "Color", "Decay", "Glare", "Haze" },
	Sky = {
		"MoonAngularSize",
		"MoonTextureId",
		"SkyboxBk",
		"SkyboxDn",
		"SkyboxFt",
		"SkyboxLf",
		"SkyboxRt",
		"SkyboxUp",
		"StarCount",
		"SunAngularSize",
		"SunTextureId",
		"SkyboxOrientation", -- eyes 👀
	},
} :: { [string]: { string } }

--[[
---------------------------------------------------------------------------
Lighting tables
---------------------------------------------------------------------------
]]

-- Default properties are set here since using Instance.new uses a different set
-- of default properties
local defaultProperties = {
	BloomEffect = { Intensity = 1, Size = 24, Threshold = 2 },
	BlurEffect = { Size = 0 },
	DepthOfFieldEffect = { FarIntensity = 0, FocusDistance = 0, InFocusRadius = 0, NearIntensity = 0 },
	SunRaysEffect = { Intensity = 0, Spread = 0 },
	Atmosphere = { Density = 0, Offset = 0 },
} :: { [string]: { [string]: any } }
local lightingTemplates = {
	PlaceDefault = defaultProperties,
}
local lightingInstances = {}

--[[
---------------------------------------------------------------------------
Main table
---------------------------------------------------------------------------
]]

local LightingManager = {
	__initialized = false,
	Templates = lightingTemplates,
} :: _TDefs.LightingManager

--[[
---------------------------------------------------------------------------
Functions
---------------------------------------------------------------------------
]]

--[=[
	@within LightingManager
	
	Changes the active lighting based on the given `config`.
	You can create a lighting preset by using `SetDefault` as a `string` parameter in a
	lighting changer's config module. These can then be reused by using `UseDefault`
	as a `string` parameter with the same value.
]=]
function LightingManager:ChangeLighting(config: _TDefs.LightingConfiguration)
	if CONFIGURABLE_PROPERTIES[config.Type] == nil then
		return
	end

	if not config.TweenInfo then
		config.TweenInfo = TweenInfo.new(1, Enum.EasingStyle.Linear, Enum.EasingDirection.Out)
	end

	local lightingInstance = lightingInstances[config.Type]
	local propertyTable = {}
	local thisConfig = if typeof(config.UseDefault) == "string"
		then (
			lightingTemplates[config.UseDefault] and lightingTemplates[config.UseDefault][config.Type]
			or lightingTemplates.PlaceDefault[config.Type]
		)
		elseif config.Configuration == "Default" then lightingTemplates.PlaceDefault[config.Type]
		else config.Configuration

	local saveTo = nil
	if typeof(config.SetDefault) == "string" then
		saveTo = lightingTemplates[config.SetDefault]
		if not saveTo then
			saveTo = {}
			lightingTemplates[config.SetDefault] = saveTo
		end
	end
	if saveTo and saveTo[config.Type] == nil then
		saveTo[config.Type] = {}
	end

	for property, value in thisConfig :: any do
		if not table.find(CONFIGURABLE_PROPERTIES[config.Type],property) and property ~= "Enabled" then
			continue
		end
		
		if saveTo then
			saveTo[config.Type][property] = value
		end

		if property == "Enabled" then
			if config.Type == "Atmosphere" then
				-- For atmospheres we have to parent elsewhere because there is no
				-- .Enabled property
				lightingInstance.Parent = if value then Lighting else script
				continue
			elseif config.Type == "Lighting" then
				continue -- There is no Enabled property in Lighting
			end
		end

		if typeof(value) == "string" or typeof(value) == "boolean" or typeof(value) == "EnumItem" then
			lightingInstance[property] = value
		else
			propertyTable[property] = value
		end
	end

	TweenService:Create(lightingInstance, config.TweenInfo, propertyTable):Play()
end

--[=[
	@within LightingManager
	
	Resets all lighting properties back to their default state.
]=]
function LightingManager:ResetLighting()
	for effectType in CONFIGURABLE_PROPERTIES do
		LightingManager:ChangeLighting({
			Type = effectType,
			Configuration = "Default",
		})
	end
end

--[=[
	@within LightingManager
	
	Removes the registered `preset` from the lighting template list.
	Used when the client object folder unloads.
]=]
function LightingManager:DeregisterPreset(preset: string)
	if preset:lower() == "placedefault" then
		return
	end

	for key in lightingTemplates do
		if key:lower():sub(1, preset:len()) == preset:lower() then
			lightingTemplates[key] = nil
		end
	end
end

function LightingManager:Init()
	if self.__initialized then
		return LightingManager
	end
	self.__initialized = true

	--> Setup lighting defaults
	for effect, properties in CONFIGURABLE_PROPERTIES do
		if not defaultProperties[effect] then
			defaultProperties[effect] = {}
		end
		
		local lightingEffect: Instance = nil
		
		if effect == "Lighting" then
			lightingEffect = Lighting
		else
			local lightingEffects = Lighting:QueryDescendants(`{effect}:not([Enabled = false])`)

			if #lightingEffects < 1 then
				lightingEffect = Instance.new(effect)
				lightingEffect.Parent = Lighting

				for name, value in defaultProperties[effect] do
					(lightingEffect :: any)[name] = value
				end
			else
				lightingEffect = table.remove(lightingEffects, 1) :: Instance
				
				for _, unusedEffect in lightingEffects do
					unusedEffect:Destroy()
				end
			end
		
			lightingEffect.Name = `LC{effect}`
		end
		
		for i, property in properties do
			defaultProperties[effect][property] = (lightingEffect :: any)[property]
		end
		lightingInstances[effect] = lightingEffect
	end

	return LightingManager
end

return LightingManager

btw if this is merged just remember to add the ColorGradingEffect stuff to the lighting changer repo

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions