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:
Pieter-Jan Briers
2016-11-04 02:21:33 +01:00
committed by clusterfack
parent 08e26a73c1
commit 1acc8a2a6f
9 changed files with 56 additions and 51 deletions

View File

@@ -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).

View File

@@ -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

View File

@@ -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)

View File

@@ -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])

View File

@@ -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

View File

@@ -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])