mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 18:32:03 +00:00
Lazy lighting init, fixes, and optimizations. (#12440)
* Lazy lighting init, fixes, and optimizations. All corners are now made when first needed (some edge cases due to sloth) Makes set_light accept null for the l_color parameter. Fixes set_opacity not update has_opaque_atom on the turf. Performance optimization to the internal lighting application code. * NONSENSICAL_VALUE
This commit is contained in:
committed by
clusterfack
parent
08e26a73c1
commit
1acc8a2a6f
@@ -7,18 +7,22 @@
|
||||
var/tmp/list/light_sources // Any light sources that are "inside" of us, for example, if src here was a mob that's carrying a flashlight, that flashlight's light source would be part of this list.
|
||||
|
||||
// The proc you should always use to set the light of this atom.
|
||||
/atom/proc/set_light(var/l_range, var/l_power, var/l_color)
|
||||
// Nonesensical value for l_color default, so we can detect if it gets set to null.
|
||||
#define NONSENSICAL_VALUE -99999
|
||||
/atom/proc/set_light(var/l_range, var/l_power, var/l_color = NONSENSICAL_VALUE)
|
||||
if (l_power != null)
|
||||
light_power = l_power
|
||||
|
||||
if (l_range != null)
|
||||
light_range = l_range
|
||||
|
||||
if (l_color != null)
|
||||
if (l_color != NONSENSICAL_VALUE)
|
||||
light_color = l_color
|
||||
|
||||
update_light()
|
||||
|
||||
#undef NONSENSICAL_VALUE
|
||||
|
||||
// Will update the light (duh).
|
||||
// Creates or destroys it if needed, makes it update values, makes sure it's got the correct source turf...
|
||||
/atom/proc/update_light()
|
||||
@@ -26,9 +30,6 @@
|
||||
if (gcDestroyed)
|
||||
return
|
||||
|
||||
if (!global.lighting_corners_initialised)
|
||||
sleep(20)
|
||||
|
||||
if (!light_power || !light_range) // We won't emit light anyways, destroy the light source.
|
||||
if(light)
|
||||
light.destroy()
|
||||
@@ -73,11 +74,23 @@
|
||||
// Should always be used to change the opacity of an atom.
|
||||
// It notifies (potentially) affected light sources so they can update (if needed).
|
||||
/atom/proc/set_opacity(var/new_opacity)
|
||||
var/old_opacity = opacity
|
||||
if (new_opacity == opacity)
|
||||
return
|
||||
|
||||
opacity = new_opacity
|
||||
var/turf/T = loc
|
||||
if (old_opacity != new_opacity && istype(T))
|
||||
if (!isturf(T))
|
||||
return
|
||||
|
||||
if (new_opacity == TRUE)
|
||||
T.has_opaque_atom = TRUE
|
||||
T.reconsider_lights()
|
||||
else
|
||||
var/old_has_opaque_atom = T.has_opaque_atom
|
||||
T.recalc_atom_opacity()
|
||||
if (old_has_opaque_atom != T.has_opaque_atom)
|
||||
T.reconsider_lights()
|
||||
|
||||
|
||||
// This code makes the light be queued for update when it is moved.
|
||||
// Entered() should handle it, however Exited() can do it if it is being moved to nullspace (as there would be no Entered() call in that situation).
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/var/list/datum/lighting_corner/all_lighting_corners = list()
|
||||
/var/datum/lighting_corner/dummy/dummy_lighting_corner = new
|
||||
// Because we can control each corner of every lighting overlay.
|
||||
// And corners get shared between multiple turfs (unless you're on the corners of the map, then 1 corner doesn't).
|
||||
// For the record: these should never ever ever be deleted, even if the turf doesn't have dynamic lighting.
|
||||
@@ -26,6 +27,8 @@
|
||||
var/cache_b = 0
|
||||
var/cache_mx = 0
|
||||
|
||||
var/update_gen = 0
|
||||
|
||||
/datum/lighting_corner/New(var/turf/new_turf, var/diagonal)
|
||||
. = ..()
|
||||
|
||||
@@ -122,3 +125,7 @@
|
||||
T.lighting_overlay.needs_update = TRUE
|
||||
lighting_update_overlays += T.lighting_overlay
|
||||
#endif
|
||||
|
||||
|
||||
/datum/lighting_corner/dummy/New()
|
||||
return
|
||||
|
||||
@@ -69,10 +69,10 @@
|
||||
|
||||
// See LIGHTING_CORNER_DIAGONAL in lighting_corner.dm for why these values are what they are.
|
||||
// No I seriously cannot think of a more efficient method, fuck off Comic.
|
||||
var/datum/lighting_corner/cr = T.corners[3]
|
||||
var/datum/lighting_corner/cg = T.corners[2]
|
||||
var/datum/lighting_corner/cb = T.corners[4]
|
||||
var/datum/lighting_corner/ca = T.corners[1]
|
||||
var/datum/lighting_corner/cr = T.corners[3] || dummy_lighting_corner
|
||||
var/datum/lighting_corner/cg = T.corners[2] || dummy_lighting_corner
|
||||
var/datum/lighting_corner/cb = T.corners[4] || dummy_lighting_corner
|
||||
var/datum/lighting_corner/ca = T.corners[1] || dummy_lighting_corner
|
||||
|
||||
var/max = max(cr.cache_mx, cg.cache_mx, cb.cache_mx, ca.cache_mx)
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/var/lighting_corners_initialised = FALSE
|
||||
|
||||
/proc/create_all_lighting_overlays()
|
||||
for (var/zlevel = 1 to world.maxz)
|
||||
create_lighting_overlays_zlevel(zlevel)
|
||||
@@ -16,24 +14,3 @@
|
||||
continue
|
||||
|
||||
getFromPool(/atom/movable/lighting_overlay, T, TRUE)
|
||||
|
||||
/proc/create_all_lighting_corners()
|
||||
for (var/zlevel = 1 to world.maxz)
|
||||
create_lighting_corners_zlevel(zlevel)
|
||||
|
||||
global.lighting_corners_initialised = TRUE
|
||||
|
||||
/proc/create_lighting_corners_zlevel(var/zlevel)
|
||||
for (var/turf/T in block(locate(1, 1, zlevel), locate(world.maxx, world.maxy, zlevel)))
|
||||
if (istype(T, /turf/space)) // Don't generate corners, do it later during ChangeTurf when needed.
|
||||
continue
|
||||
|
||||
T.lighting_corners_initialised = TRUE
|
||||
for (var/i = 1 to 4)
|
||||
if (!T.corners)
|
||||
T.corners = list(null, null, null, null)
|
||||
|
||||
if (T.corners[i]) // Already have a corner on this direction.
|
||||
continue
|
||||
|
||||
T.corners[i] = new/datum/lighting_corner(T, LIGHTING_CORNER_DIAGONAL[i])
|
||||
|
||||
@@ -201,6 +201,7 @@
|
||||
#define LUM_FALLOFF(C, T) (1 - CLAMP01(sqrt((C.x - T.x) ** 2 + (C.y - T.y) ** 2 + LIGHTING_HEIGHT) / max(1, light_range)))
|
||||
|
||||
/datum/light_source/proc/apply_lum()
|
||||
var/static/update_gen = 1
|
||||
applied = 1
|
||||
|
||||
// Keep track of the last applied lum values so that the lighting can be reversed
|
||||
@@ -209,10 +210,14 @@
|
||||
applied_lum_b = lum_b
|
||||
|
||||
FOR_DVIEW(var/turf/T, light_range, source_turf, INVISIBILITY_LIGHTING)
|
||||
if (!T.lighting_corners_initialised)
|
||||
T.generate_missing_corners()
|
||||
|
||||
for (var/datum/lighting_corner/C in T.get_corners())
|
||||
if (effect_str.Find(C))
|
||||
if (C.update_gen == update_gen)
|
||||
continue
|
||||
|
||||
C.update_gen = update_gen
|
||||
C.affecting += src
|
||||
|
||||
if (!C.active)
|
||||
@@ -226,6 +231,8 @@
|
||||
T.affecting_lights += src
|
||||
affecting_turfs += T
|
||||
|
||||
update_gen++
|
||||
|
||||
/datum/light_source/proc/remove_lum()
|
||||
applied = FALSE
|
||||
|
||||
@@ -254,6 +261,8 @@
|
||||
var/list/datum/lighting_corner/corners = list()
|
||||
var/list/turf/turfs = list()
|
||||
FOR_DVIEW(var/turf/T, light_range, source_turf, 0)
|
||||
if (!T.lighting_corners_initialised)
|
||||
T.generate_missing_corners()
|
||||
corners |= T.get_corners()
|
||||
turfs += T
|
||||
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
|
||||
var/area/A = loc
|
||||
if (A.dynamic_lighting)
|
||||
if (!lighting_corners_initialised)
|
||||
generate_missing_corners()
|
||||
|
||||
getFromPool(/atom/movable/lighting_overlay, src)
|
||||
|
||||
for (var/datum/lighting_corner/C in corners)
|
||||
@@ -94,3 +97,14 @@
|
||||
return null // Since this proc gets used in a for loop, null won't be looped though.
|
||||
|
||||
return corners
|
||||
|
||||
/turf/proc/generate_missing_corners()
|
||||
lighting_corners_initialised = TRUE
|
||||
if (!corners)
|
||||
corners = list(null, null, null, null)
|
||||
|
||||
for (var/i = 1 to 4)
|
||||
if (corners[i]) // Already have a corner on this direction.
|
||||
continue
|
||||
|
||||
corners[i] = new/datum/lighting_corner(src, LIGHTING_CORNER_DIAGONAL[i])
|
||||
|
||||
Reference in New Issue
Block a user