From 1e1e0f7f6e82613c963ea47a29ac7d730ac6e3cb Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Wed, 10 May 2017 18:11:22 -0500 Subject: [PATCH] More /vg/lighting tweaks (#884) --- code/__DEFINES/lighting.dm | 17 +- code/controllers/subsystem/lighting.dm | 12 +- code/modules/lighting/lighting_corner.dm | 8 +- code/modules/lighting/lighting_object.dm | 24 +- code/modules/lighting/lighting_setup.dm | 2 +- code/modules/lighting/lighting_source.dm | 283 +++++++++++++---------- code/modules/lighting/lighting_turf.dm | 8 +- 7 files changed, 199 insertions(+), 155 deletions(-) diff --git a/code/__DEFINES/lighting.dm b/code/__DEFINES/lighting.dm index fd98a68e07..7cfed2b483 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 eb61e5ef39..35d8a3d08f 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 2f431e884a..c51e7feb7a 100644 --- a/code/modules/lighting/lighting_corner.dm +++ b/code/modules/lighting/lighting_corner.dm @@ -6,8 +6,8 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST, NORTHWEST)) /datum/lighting_corner - var/list/turf/masters = list() - var/list/datum/light_source/affecting = list() // Light sources affecting us. + var/list/turf/masters + var/list/datum/light_source/affecting // Light sources affecting us. var/active = FALSE // TRUE if one of our masters has dynamic lighting. var/x = 0 @@ -25,11 +25,9 @@ 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) . = ..() - + masters = list() masters[new_turf] = turn(diagonal, 180) z = new_turf.z diff --git a/code/modules/lighting/lighting_object.dm b/code/modules/lighting/lighting_object.dm index 369129fc57..b0b0b32285 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 = corners[3] || dummy_lighting_corner + cg = corners[2] || dummy_lighting_corner + cb = corners[4] || dummy_lighting_corner + ca = 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 fe9bdb5609..5086b0c9d2 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 1cf14c3c47..63457a1ce9 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_b) - (OLD * applied_lum_b) \ ); -// 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,30 +189,93 @@ 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. + LAZYINITLIST(effect_str) + if (effect_str[C]) // Already have one. REMOVE_CORNER(C) + effect_str[C] = 0 APPLY_CORNER(C) + UNSETEMPTY(effect_str) + +/datum/light_source/proc/update_corners() + var/update = FALSE + + if (!source_atom || QDELETED(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 = P + update = TRUE + + if (!isturf(source_turf)) + if (applied) + remove_lum() + return + + 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 + applied = TRUE + else if (needs_update == LIGHTING_CHECK_UPDATE) + return //nothing's changed -/datum/light_source/proc/smart_vis_update() var/list/datum/lighting_corner/corners = list() var/list/turf/turfs = list() var/thing var/datum/lighting_corner/C var/turf/T + if (source_turf) + var/oldlum = source_turf.luminosity + source_turf.luminosity = Ceiling(light_range) + for(T in view(Ceiling(light_range), source_turf)) + for (thing in T.get_corners(source_turf)) + C = thing + corners[C] = 0 + turfs += T + source_turf.luminosity = oldlum - FOR_DVIEW(T, light_range+1, source_turf, 0) - if (!T.lighting_corners_initialised) - T.generate_missing_corners() - 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,22 +288,45 @@ T = thing LAZYREMOVE(T.affecting_lights, src) + LAZYINITLIST(effect_str) + if (needs_update == LIGHTING_VIS_UPDATE) + for (thing in corners - effect_str) // New corners + C = thing + LAZYADD(C.affecting, src) + if (!C.active) + effect_str[C] = 0 + continue + APPLY_CORNER(C) + else + L = corners - effect_str + for (thing in L) // New corners + C = thing + LAZYADD(C.affecting, src) + if (!C.active) + effect_str[C] = 0 + continue + APPLY_CORNER(C) + for (thing in corners - L) // Existing corners + C = thing + if (!C.active) + effect_str[C] = 0 + continue + APPLY_CORNER(C) - for (thing in corners - effect_str) // New corners - C = thing - LAZYADD(C.affecting, src) - if (!C.active) - effect_str[C] = 0 - continue - - APPLY_CORNER(C) - - for (thing in effect_str - corners) // Old, now gone, corners. + L = effect_str - corners + for (thing in L) // Old, now gone, corners. C = thing REMOVE_CORNER(C) LAZYREMOVE(C.affecting, src) - effect_str -= C + effect_str -= L + + 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 diff --git a/code/modules/lighting/lighting_turf.dm b/code/modules/lighting/lighting_turf.dm index 65b1ec2615..ca6866c48e 100644 --- a/code/modules/lighting/lighting_turf.dm +++ b/code/modules/lighting/lighting_turf.dm @@ -33,7 +33,7 @@ return var/area/A = loc - if (!IS_DYNAMIC_LIGHTING(A)) + if (!IS_DYNAMIC_LIGHTING(A) && !light_sources) return if (!lighting_corners_initialised) @@ -113,12 +113,18 @@ lighting_clear_overlay() /turf/proc/get_corners() + if (!IS_DYNAMIC_LIGHTING(src) && !light_sources) + 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) && !light_sources) + return lighting_corners_initialised = TRUE if (!corners) corners = list(null, null, null, null)