diff --git a/code/__DEFINES/lighting.dm b/code/__DEFINES/lighting.dm index fd98a68e07e..7cfed2b483d 100644 --- a/code/__DEFINES/lighting.dm +++ b/code/__DEFINES/lighting.dm @@ -16,10 +16,10 @@ #define LIGHTING_BASE_MATRIX \ list \ ( \ - LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, 0, \ - LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, 0, \ - LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, 0, \ - LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, 0, \ + 1, 1, 1, 0, \ + 1, 1, 1, 0, \ + 1, 1, 1, 0, \ + 1, 1, 1, 0, \ 0, 0, 0, 1 \ ) \ @@ -78,4 +78,11 @@ #define DYNAMIC_LIGHTING_ENABLED 1 //dynamic lighting enabled #define DYNAMIC_LIGHTING_FORCED 2 //dynamic lighting enabled even if the area doesn't require power #define DYNAMIC_LIGHTING_IFSTARLIGHT 3 //dynamic lighting enabled only if starlight is. -#define IS_DYNAMIC_LIGHTING(A) A.dynamic_lighting \ No newline at end of file +#define IS_DYNAMIC_LIGHTING(A) A.dynamic_lighting + + +//code assumes higher numbers override lower numbers. +#define LIGHTING_NO_UPDATE 0 +#define LIGHTING_VIS_UPDATE 1 +#define LIGHTING_CHECK_UPDATE 2 +#define LIGHTING_FORCE_UPDATE 3 \ No newline at end of file diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm index eb61e5ef394..35d8a3d08fb 100644 --- a/code/controllers/subsystem/lighting.dm +++ b/code/controllers/subsystem/lighting.dm @@ -36,18 +36,10 @@ SUBSYSTEM_DEF(lighting) for (i in 1 to GLOB.lighting_update_lights.len) var/datum/light_source/L = GLOB.lighting_update_lights[i] - if (L.check() || QDELETED(L) || L.force_update) - L.remove_lum() - if (!QDELETED(L)) - L.apply_lum() + L.update_corners() - else if (L.vis_update) //We smartly update only tiles that became (in) visible to use. - L.smart_vis_update() + L.needs_update = LIGHTING_NO_UPDATE - L.vis_update = FALSE - L.force_update = FALSE - L.needs_update = FALSE - if(init_tick_checks) CHECK_TICK else if (MC_TICK_CHECK) diff --git a/code/modules/lighting/lighting_corner.dm b/code/modules/lighting/lighting_corner.dm index 2f431e884a6..8bff6e20bad 100644 --- a/code/modules/lighting/lighting_corner.dm +++ b/code/modules/lighting/lighting_corner.dm @@ -25,8 +25,6 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST, var/cache_b = LIGHTING_SOFT_THRESHOLD var/cache_mx = 0 - var/update_gen = 0 - /datum/lighting_corner/New(var/turf/new_turf, var/diagonal) . = ..() diff --git a/code/modules/lighting/lighting_object.dm b/code/modules/lighting/lighting_object.dm index 369129fc578..d2692e1de7a 100644 --- a/code/modules/lighting/lighting_object.dm +++ b/code/modules/lighting/lighting_object.dm @@ -6,6 +6,7 @@ GLOBAL_LIST_EMPTY(all_lighting_objects) // Global list of lighting objects. anchored = TRUE icon = LIGHTING_ICON + icon_state = "transparent" color = LIGHTING_BASE_MATRIX plane = LIGHTING_PLANE mouse_opacity = 0 @@ -16,7 +17,7 @@ GLOBAL_LIST_EMPTY(all_lighting_objects) // Global list of lighting objects. var/needs_update = FALSE -/atom/movable/lighting_object/Initialize(mapload, var/no_update = FALSE) +/atom/movable/lighting_object/Initialize(mapload) . = ..() verbs.Cut() GLOB.all_lighting_objects += src @@ -28,10 +29,8 @@ GLOBAL_LIST_EMPTY(all_lighting_objects) // Global list of lighting objects. for(var/turf/open/space/S in RANGE_TURFS(1, src)) //RANGE_TURFS is in code\__HELPERS\game.dm S.update_starlight() - if (no_update) - return - - update() + needs_update = TRUE + GLOB.lighting_update_objects += src /atom/movable/lighting_object/Destroy(var/force) if (force) @@ -69,10 +68,17 @@ GLOBAL_LIST_EMPTY(all_lighting_objects) // Global list of lighting objects. // See LIGHTING_CORNER_DIAGONAL in lighting_corner.dm for why these values are what they are. var/static/datum/lighting_corner/dummy/dummy_lighting_corner = new - 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/list/corners = T.corners + var/datum/lighting_corner/cr = dummy_lighting_corner + var/datum/lighting_corner/cg = dummy_lighting_corner + var/datum/lighting_corner/cb = dummy_lighting_corner + var/datum/lighting_corner/ca = dummy_lighting_corner + if (corners) //done this way for speed + cr = T.corners[3] || dummy_lighting_corner + cg = T.corners[2] || dummy_lighting_corner + cb = T.corners[4] || dummy_lighting_corner + ca = T.corners[1] || dummy_lighting_corner var/max = max(cr.cache_mx, cg.cache_mx, cb.cache_mx, ca.cache_mx) diff --git a/code/modules/lighting/lighting_setup.dm b/code/modules/lighting/lighting_setup.dm index fe9bdb56098..5086b0c9d29 100644 --- a/code/modules/lighting/lighting_setup.dm +++ b/code/modules/lighting/lighting_setup.dm @@ -8,6 +8,6 @@ if(!IS_DYNAMIC_LIGHTING(T)) continue - new/atom/movable/lighting_object(T, TRUE) + new/atom/movable/lighting_object(T) CHECK_TICK CHECK_TICK diff --git a/code/modules/lighting/lighting_source.dm b/code/modules/lighting/lighting_source.dm index 1cf14c3c47a..859f23586aa 100644 --- a/code/modules/lighting/lighting_source.dm +++ b/code/modules/lighting/lighting_source.dm @@ -26,22 +26,15 @@ var/applied = FALSE // Whether we have applied our light yet or not. - var/vis_update // Whether we should smartly recalculate visibility. and then only update tiles that became (in)visible to us. - var/needs_update // Whether we are queued for an update. - var/force_update + var/needs_update = LIGHTING_NO_UPDATE // Whether we are queued for an update. + /datum/light_source/New(var/atom/owner, var/atom/top) source_atom = owner // Set our new owner. - if (!source_atom.light_sources) - source_atom.light_sources = list() - - source_atom.light_sources += src // Add us to the lights of our owner. + LAZYADD(source_atom.light_sources, src) top_atom = top if (top_atom != source_atom) - if (!top.light_sources) - top.light_sources = list() - - top_atom.light_sources += src + LAZYADD(top_atom.light_sources, src) source_turf = top_atom pixel_turf = get_turf_pixel(top_atom) || source_turf @@ -52,20 +45,18 @@ parse_light_color() - effect_str = list() - affecting_turfs = list() - update() return ..() /datum/light_source/Destroy(force) - force_update() + remove_lum() if (source_atom) - source_atom.light_sources -= src + LAZYREMOVE(source_atom.light_sources, src) if (top_atom) - top_atom.light_sources -= src + LAZYREMOVE(top_atom.light_sources, src) + . = ..() if(!force) return QDEL_HINT_IWILLGC @@ -73,79 +64,34 @@ // Yes this doesn't align correctly on anything other than 4 width tabs. // If you want it to go switch everybody to elastic tab stops. // Actually that'd be great if you could! -#define EFFECT_UPDATE \ - if (!needs_update) \ - { \ - GLOB.lighting_update_lights += src; \ - needs_update = TRUE; \ - } +#define EFFECT_UPDATE(level) \ + if (needs_update == LIGHTING_NO_UPDATE) \ + GLOB.lighting_update_lights += src; \ + if (needs_update < level) \ + needs_update = level; \ + // This proc will cause the light source to update the top atom, and add itself to the update queue. /datum/light_source/proc/update(var/atom/new_top_atom) // This top atom is different. if (new_top_atom && new_top_atom != top_atom) if(top_atom != source_atom && top_atom.light_sources) // Remove ourselves from the light sources of that top atom. - top_atom.light_sources -= src + LAZYREMOVE(top_atom.light_sources, src) top_atom = new_top_atom if (top_atom != source_atom) LAZYADD(top_atom.light_sources, src) // Add ourselves to the light sources of our new top atom. - EFFECT_UPDATE + EFFECT_UPDATE(LIGHTING_CHECK_UPDATE) // Will force an update without checking if it's actually needed. /datum/light_source/proc/force_update() - force_update = 1 - - EFFECT_UPDATE + EFFECT_UPDATE(LIGHTING_FORCE_UPDATE) // Will cause the light source to recalculate turfs that were removed or added to visibility only. /datum/light_source/proc/vis_update() - vis_update = 1 - - EFFECT_UPDATE - -// Will check if we actually need to update, and update any variables that may need to be updated. -/datum/light_source/proc/check() - if (!source_atom || !light_range || !light_power) - qdel(src) - return 1 - - if (!top_atom) - top_atom = source_atom - . = 1 - - if (isturf(top_atom)) - if (source_turf != top_atom) - source_turf = top_atom - pixel_turf = source_turf - . = 1 - else if (top_atom.loc != source_turf) - source_turf = top_atom.loc - pixel_turf = get_turf_pixel(top_atom) - . = 1 - else - var/P = get_turf_pixel(top_atom) - if (P != pixel_turf) - . = 1 - pixel_turf = get_turf_pixel(top_atom) - - if (source_atom.light_power != light_power) - light_power = source_atom.light_power - . = 1 - - if (source_atom.light_range != light_range) - light_range = source_atom.light_range - . = 1 - - if (light_range && light_power && !applied) - . = 1 - - if (source_atom.light_color != light_color) - light_color = source_atom.light_color - parse_light_color() - . = 1 + EFFECT_UPDATE(LIGHTING_VIS_UPDATE) // Decompile the hexadecimal colour into lumcounts of each perspective. /datum/light_source/proc/parse_light_color() @@ -164,48 +110,47 @@ // As such this all gets counted as a single line. // The braces and semicolons are there to be able to do this on a single line. #define LUM_FALLOFF(C, T) (1 - CLAMP01(sqrt((C.x - T.x) ** 2 + (C.y - T.y) ** 2 + LIGHTING_HEIGHT) / max(1, light_range))) -#define APPLY_CORNER(C) \ - . = LUM_FALLOFF(C, pixel_turf); \ - \ - . *= light_power; \ - \ - effect_str[C] = .; \ - \ - C.update_lumcount \ - ( \ - . * applied_lum_r, \ - . * applied_lum_g, \ - . * applied_lum_b \ + +#define APPLY_CORNER(C) \ + . = LUM_FALLOFF(C, pixel_turf); \ + . *= light_power; \ + var/OLD = effect_str[C]; \ + \ + effect_str[C] = .; \ + \ + C.update_lumcount \ + ( \ + (. * lum_r) - (OLD * applied_lum_r), \ + (. * lum_g) - (OLD * applied_lum_g), \ + (. * lum_g) - (OLD * applied_lum_g) \ ); -// I don't need to explain what this does, do I? -#define REMOVE_CORNER(C) \ - . = -effect_str[C]; \ - C.update_lumcount \ - ( \ - . * applied_lum_r, \ - . * applied_lum_g, \ - . * applied_lum_b \ + +#define REMOVE_CORNER(C) \ + . = -effect_str[C]; \ + C.update_lumcount \ + ( \ + . * applied_lum_r, \ + . * applied_lum_g, \ + . * applied_lum_b \ ); // This is the define used to calculate falloff. - +/* /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 - applied_lum_r = lum_r - applied_lum_g = lum_g - applied_lum_b = lum_b var/thing var/datum/lighting_corner/C + var/corners = list() + LAZYINITLIST(effect_str) FOR_DVIEW(var/turf/T, light_range+1, source_turf, INVISIBILITY_LIGHTING) - if (!T.lighting_corners_initialised) - T.generate_missing_corners() + var/list/turf_corners = T.get_corners() - for (thing in T.get_corners()) + for (thing in turf_corners) C = thing if (C.update_gen == update_gen) continue @@ -220,9 +165,13 @@ APPLY_CORNER(C) LAZYADD(T.affecting_lights, src) - affecting_turfs += T + LAZYADD(affecting_turfs, T) FOR_DVIEW_END update_gen++ + applied_lum_r = lum_r + applied_lum_g = lum_g + applied_lum_b = lum_b +*/ /datum/light_source/proc/remove_lum() applied = FALSE @@ -231,7 +180,7 @@ var/turf/T = thing LAZYREMOVE(T.affecting_lights, src) - affecting_turfs.Cut() + affecting_turfs = null var/datum/lighting_corner/C for (thing in effect_str) @@ -240,7 +189,7 @@ LAZYREMOVE(C.affecting, src) - effect_str.Cut() + effect_str = null /datum/light_source/proc/recalc_corner(var/datum/lighting_corner/C) if (effect_str.Find(C)) // Already have one. @@ -248,22 +197,74 @@ APPLY_CORNER(C) -/datum/light_source/proc/smart_vis_update() +/datum/light_source/proc/update_corners() + var/update = FALSE + + if (!source_atom) + qdel(src) + return + + if (source_atom.light_power != light_power) + light_power = source_atom.light_power + update = TRUE + + if (source_atom.light_range != light_range) + light_range = source_atom.light_range + update = TRUE + + if (!top_atom) + top_atom = source_atom + update = TRUE + + if (!light_range || !light_power) + qdel(src) + return + + if (isturf(top_atom)) + if (source_turf != top_atom) + source_turf = top_atom + pixel_turf = source_turf + update = TRUE + else if (top_atom.loc != source_turf) + source_turf = top_atom.loc + pixel_turf = get_turf_pixel(top_atom) + update = TRUE + else + var/P = get_turf_pixel(top_atom) + if (P != pixel_turf) + pixel_turf = get_turf_pixel(top_atom) + update = TRUE + + if (light_range && light_power && !applied) + update = TRUE + + if (source_atom.light_color != light_color) + light_color = source_atom.light_color + parse_light_color() + update = TRUE + + else if (applied_lum_r != lum_r || applied_lum_g != lum_g || applied_lum_b != lum_b) + update = TRUE + + if (update) + needs_update = LIGHTING_CHECK_UPDATE + else if (needs_update == LIGHTING_CHECK_UPDATE) + return //nothing's changed + var/list/datum/lighting_corner/corners = list() var/list/turf/turfs = list() var/thing var/datum/lighting_corner/C var/turf/T - FOR_DVIEW(T, light_range+1, source_turf, 0) - if (!T.lighting_corners_initialised) - T.generate_missing_corners() + FOR_DVIEW(T, Ceiling(light_range), source_turf, 0) for (thing in T.get_corners(source_turf)) C = thing corners[C] = 0 turfs += T FOR_DVIEW_END + LAZYINITLIST(affecting_turfs) var/list/L = turfs - affecting_turfs // New turfs, add us to the affecting lights of them. affecting_turfs += L for (thing in L) @@ -276,9 +277,8 @@ T = thing LAZYREMOVE(T.affecting_lights, src) - - - for (thing in corners - effect_str) // New corners + LAZYINITLIST(effect_str) + for (thing in (needs_update == LIGHTING_VIS_UPDATE ? corners - effect_str : corners)) // New corners C = thing LAZYADD(C.affecting, src) if (!C.active) @@ -293,6 +293,13 @@ LAZYREMOVE(C.affecting, src) effect_str -= C + applied_lum_r = lum_r + applied_lum_g = lum_g + applied_lum_b = lum_b + + UNSETEMPTY(effect_str) + UNSETEMPTY(affecting_turfs) + #undef EFFECT_UPDATE #undef LUM_FALLOFF #undef REMOVE_CORNER diff --git a/code/modules/lighting/lighting_turf.dm b/code/modules/lighting/lighting_turf.dm index 65b1ec26158..8102246c61b 100644 --- a/code/modules/lighting/lighting_turf.dm +++ b/code/modules/lighting/lighting_turf.dm @@ -113,12 +113,18 @@ lighting_clear_overlay() /turf/proc/get_corners() + if (!IS_DYNAMIC_LIGHTING(src)) + return null + if (!lighting_corners_initialised) + generate_missing_corners() if (has_opaque_atom) return null // Since this proc gets used in a for loop, null won't be looped though. return corners /turf/proc/generate_missing_corners() + if (!IS_DYNAMIC_LIGHTING(src)) + return lighting_corners_initialised = TRUE if (!corners) corners = list(null, null, null, null)