diff --git a/code/_helpers/overlay.dm b/code/_helpers/overlay.dm index 0515f4de0df..5a524bf4a3e 100644 --- a/code/_helpers/overlay.dm +++ b/code/_helpers/overlay.dm @@ -41,9 +41,17 @@ target.add_overlay(list(multiply, overlay)) -/proc/make_screen_overlay(icon, icon_state, brightness_factor = null) +/proc/make_screen_overlay(icon, icon_state, brightness_factor = null, glow_radius = 1) + var/icon/base = new(icon, icon_state) // forgive us, but this is to get the width/height. + var/height = base.Height() // at least this is cached in most use cases + var/width = base.Width() var/image/overlay = image(icon, icon_state) overlay.layer = EFFECTS_ABOVE_LIGHTING_LAYER + var/image/underlay = image(overlay) + underlay.alpha = 128 + underlay.transform = underlay.transform.Scale((width + glow_radius*2)/width, (height+glow_radius*2)/height) + underlay.filters = filter(type="blur", size=glow_radius) + overlay.underlays += underlay if (brightness_factor) overlay.color = list( brightness_factor, 0, 0, 0, diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index 34835e5dd7b..34d0727548c 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -252,6 +252,7 @@ /obj/item/stock_parts/scanning_module = 2, /obj/item/stock_parts/console_screen ) + var/global/image/console_overlay /obj/machinery/body_scanconsole/Destroy() if (connected) @@ -267,8 +268,9 @@ if((stat & BROKEN) || (stat & NOPOWER)) return else - var/mutable_appearance/screen_overlay = mutable_appearance(icon, "body_scannerconsole-screen", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(screen_overlay) + if(!console_overlay) + console_overlay = make_screen_overlay(icon, "body_scannerconsole-screen") + add_overlay(console_overlay) set_light(1.4, 1, COLOR_RED) /obj/machinery/body_scanconsole/proc/get_collapsed_lung_desc() diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm index b499dd3bb0b..9560aa75962 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/game/machinery/newscaster.dm @@ -50,8 +50,19 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co var/hitstaken = 0 //Death at 3 hits from an item with force>=15 var/datum/feed_channel/viewing_channel = null var/datum/feed_message/viewing_message = null + var/global/list/screen_overlays anchored = 1 +/obj/machinery/newscaster/proc/generate_overlays(var/force = 0) + if(LAZYLEN(screen_overlays) && !force) + return + LAZYINITLIST(screen_overlays) + screen_overlays["newscaster-screen"] = make_screen_overlay(icon, "newscaster-screen") + screen_overlays["newscaster-title"] = make_screen_overlay(icon, "newscaster-title") + screen_overlays["newscaster-wanted"] = make_screen_overlay(icon, "newscaster-wanted") + screen_overlays["newscaster-scanline"] = make_screen_overlay(icon, "newscaster-scanline") + for(var/i in 1 to 3) + screen_overlays["crack[i]"] = make_screen_overlay(icon, "crack[i]") /obj/machinery/newscaster/security_unit //Security unit name = "Security Newscaster" @@ -62,6 +73,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co allCasters += src src.paper_remaining = 15 // Will probably change this to something better src.unit_no = allCasters.len + 1 + src.generate_overlays() src.update_icon() //for any custom ones on the map... /obj/machinery/newscaster/Destroy() @@ -74,36 +86,30 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co set_light(FALSE) if(isbroken) //If the thing is smashed, add crack overlay on top of the unpowered sprite. cut_overlays() - add_overlay("crack3") + add_overlay(screen_overlays["crack3"]) return cut_overlays() //reset overlays - var/mutable_appearance/base_screen_overlay = mutable_appearance(icon, "newscaster-screen", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(base_screen_overlay) + add_overlay(screen_overlays["newscaster-screen"]) set_light(1.4, 1, COLOR_CYAN) if(!alert || !SSnews.wanted_issue) // since we're transparent I don't want overlay nonsense - var/mutable_appearance/screen_overlay = mutable_appearance(icon, "newscaster-title", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(screen_overlay) + add_overlay(screen_overlays["newscaster-title"]) if(SSnews.wanted_issue) //wanted icon state, there can be no overlays on it as it's a priority message - var/mutable_appearance/screen_overlay = mutable_appearance(icon, "newscaster-wanted", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(screen_overlay) + add_overlay(screen_overlays["newscaster-wanted"]) return if(alert) //new message alert overlay - var/mutable_appearance/screen_overlay = mutable_appearance(icon, "newscaster-alert", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(screen_overlay) + add_overlay(screen_overlays["newscaster-alert"]) if(hitstaken == 0) - var/mutable_appearance/screen_overlay = mutable_appearance(icon, "newscaster-scanline", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(screen_overlay) + add_overlay(screen_overlays["newscaster-scanline"]) if(hitstaken > 0) //Cosmetic damage overlay - var/mutable_appearance/screen_overlay = mutable_appearance(icon, "crack[hitstaken]", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(screen_overlay) - + add_overlay(screen_overlays["crack[hitstaken]"]) + icon_state = initial(icon_state) return diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index 008d2c8b409..8271ce4d196 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -64,6 +64,17 @@ var/list/obj/machinery/requests_console/allConsoles = list() //End Form Integration var/datum/announcement/announcement = new var/list/obj/item/device/pda/alert_pdas = list() //The PDAs we alert upon a request receipt. + var/global/list/screen_overlays + +/obj/machinery/requests_console/proc/generate_overlays(var/force = 0) + if(LAZYLEN(screen_overlays) && !force) + return + LAZYINITLIST(screen_overlays) + screen_overlays["req_comp-idle"] = make_screen_overlay(icon, "req_comp-idle") + screen_overlays["req_comp-alert"] = make_screen_overlay(icon, "req_comp-alert") + screen_overlays["req_comp-redalert"] = make_screen_overlay(icon, "req_comp-redalert") + screen_overlays["req_comp-yellowalert"] = make_screen_overlay(icon, "req_comp-yellowalert") + screen_overlays["req_comp-scanline"] = make_screen_overlay(icon, "req_comp-scanline") /obj/machinery/requests_console/power_change() ..() @@ -77,24 +88,19 @@ var/list/obj/machinery/requests_console/allConsoles = list() else switch(newmessagepriority) if(0) - var/mutable_appearance/screen_overlay = mutable_appearance(icon, "req_comp-idle", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(screen_overlay) + add_overlay(screen_overlays["req_comp-idle"]) set_light(1.4, 1, COLOR_CYAN) if(1) - var/mutable_appearance/screen_overlay = mutable_appearance(icon, "req_comp-alert", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(screen_overlay) + add_overlay(screen_overlays["req_comp-alert"]) set_light(1.4, 1, COLOR_CYAN) if(2) - var/mutable_appearance/screen_overlay = mutable_appearance(icon, "req_comp-redalert", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(screen_overlay) + add_overlay(screen_overlays["req_comp-redalert"]) set_light(1.4, 1, COLOR_ORANGE) if(3) - var/mutable_appearance/screen_overlay = mutable_appearance(icon, "req_comp-yellowalert", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(screen_overlay) + add_overlay(screen_overlays["req_comp-yellowalert"]) set_light(1.4, 1, COLOR_ORANGE) - var/mutable_appearance/screen_overlay = mutable_appearance(icon, "req_comp-scanline", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(screen_overlay) + add_overlay(screen_overlays["req_comp-scanline"]) /obj/machinery/requests_console/Initialize(mapload, var/dir, var/building = 0) . = ..() @@ -119,6 +125,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() req_console_supplies |= department if (departmentType & RC_INFO) req_console_information |= department + generate_overlays() update_icon() /obj/machinery/requests_console/Destroy() diff --git a/code/game/machinery/ringer.dm b/code/game/machinery/ringer.dm index b62583fc489..a7fc6e084b1 100644 --- a/code/game/machinery/ringer.dm +++ b/code/game/machinery/ringer.dm @@ -13,11 +13,13 @@ var/on = TRUE var/department = "Somewhere" //whatever department/desk you put this thing var/pinged = FALSE //for cooldown + var/global/list/screen_overlays /obj/machinery/ringer/Initialize() . = ..() if(id) ringers = new(id, src) + generate_overlays() update_icon() /obj/machinery/ringer/power_change() @@ -28,6 +30,15 @@ QDEL_NULL(ringers) return ..() +/obj/machinery/ringer/proc/generate_overlays(var/force = 0) + if(LAZYLEN(screen_overlays) && !force) + return + LAZYINITLIST(screen_overlays) + screen_overlays["bell-active"] = make_screen_overlay(icon, "bell-active") + screen_overlays["bell-alert"] = make_screen_overlay(icon, "bell-alert") + screen_overlays["bell-scanline"] = make_screen_overlay(icon, "bell-scanline") + screen_overlays["bell-standby"] = make_screen_overlay(icon, "bell-standby") + /obj/machinery/ringer/update_icon() cut_overlays() if(!on || stat & NOPOWER) @@ -35,19 +46,15 @@ set_light(FALSE) return if(rings_pdas || rings_pdas.len) - var/mutable_appearance/screen_overlay = mutable_appearance(icon, "bell-active", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(screen_overlay) + add_overlay(screen_overlays["bell-active"]) set_light(1.4, 1, COLOR_CYAN) if(pinged) - var/mutable_appearance/screen_overlay = mutable_appearance(icon, "bell-alert", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(screen_overlay) + add_overlay(screen_overlays["bell-alert"]) set_light(1.4, 1, COLOR_CYAN) if(on) - var/mutable_appearance/screen_overlay = mutable_appearance(icon, "bell-scanline", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(screen_overlay) + add_overlay(screen_overlays["bell-scanline"]) else - var/mutable_appearance/screen_overlay = mutable_appearance(icon, "bell-standby", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(screen_overlay) + add_overlay(screen_overlays["bell-standby"]) set_light(1.4, 1, COLOR_CYAN) /obj/machinery/ringer/attackby(obj/item/C as obj, mob/living/user as mob) diff --git a/code/game/machinery/station_holomap.dm b/code/game/machinery/station_holomap.dm index 9f142bca994..945ac8d450d 100644 --- a/code/game/machinery/station_holomap.dm +++ b/code/game/machinery/station_holomap.dm @@ -53,6 +53,7 @@ small_station_map = image(SSholomap.extra_minimaps["[HOLOMAP_EXTRA_STATIONMAPSMALL]_[original_zLevel]"], dir = dir) small_station_map.layer = EFFECTS_ABOVE_LIGHTING_LAYER + small_station_map.filters = filter(type = "drop_shadow", color = light_color + "F0", size = 1, offset = 1, x = 0, y = 0) floor_markings = image('icons/obj/machines/stationmap.dmi', "decal_station_map") floor_markings.dir = src.dir diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index d7fced8f6a4..1cc14d58683 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -106,6 +106,9 @@ var/heating_temperature = T0C + 57 //Best temp for coffee. var/vending_sound = "machines/vending/vending_drop.ogg" + + var/global/list/screen_overlays + var/exclusive_screen = TRUE // Are we not allowed to show the deny and screen states at the same time? light_range = 2 light_power = 1 @@ -123,7 +126,7 @@ if(src.product_ads) src.ads_list += text2list(src.product_ads, ";") - + add_screen_overlay() src.build_inventory() @@ -132,14 +135,20 @@ /obj/machinery/vending/proc/reset_light() set_light(initial(light_range), initial(light_power), initial(light_color)) -/obj/machinery/vending/proc/add_screen_overlay() - if("[icon_state]-screen" in icon_states(icon)) - var/mutable_appearance/screen_overlay = mutable_appearance(icon, "[icon_state]-screen", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(screen_overlay) +/obj/machinery/vending/proc/add_screen_overlay(var/deny = FALSE) + if(!LAZYLEN(screen_overlays)) + LAZYINITLIST(screen_overlays) + if(!("[icon_state]-screen" in screen_overlays) || (deny && !("[icon_state]-deny" in screen_overlays))) + var/list/states = icon_states(icon) + if ("[icon_state]-screen" in states) + screen_overlays["[icon_state]-screen"] = make_screen_overlay(icon, "[icon_state]-screen") + if ("[icon_state]-deny" in states) + screen_overlays["[icon_state]-deny"] = make_screen_overlay(icon, "[icon_state]-deny") + add_overlay(screen_overlays["[icon_state]-[deny ? "deny" : "screen"]"]) reset_light() /** - * Build src.produdct_records from the products lists + * Build src.product_records from the products lists * * src.products, src.contraband, src.premium, and src.prices allow specifying * products that the vending machine is to carry without manually populating @@ -556,11 +565,14 @@ if (href_list["vendItem"] && vend_ready && !currently_vending) if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH to_chat(usr, "Access denied.") //Unless emagged of course - var/mutable_appearance/deny_overlay = mutable_appearance(icon, "[icon_state]-deny", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(deny_overlay) - addtimer(CALLBACK(src, /atom/.proc/cut_overlay, deny_overlay), deny_time ? deny_time : 15) + if(exclusive_screen) + cut_overlays() + addtimer(CALLBACK(src, .proc/add_screen_overlay), deny_time ? deny_time : 15) + add_screen_overlay(deny = TRUE) + addtimer(CALLBACK(src, /atom/.proc/cut_overlay, screen_overlays["[icon_state]-deny"]), deny_time ? deny_time : 15) set_light(initial(light_range), initial(light_power), COLOR_RED_LIGHT) addtimer(CALLBACK(src, .proc/reset_light), deny_time ? deny_time : 15) + addtimer(CALLBACK(src, .proc/add_screen_overlay), deny_time ? deny_time : 15) return var/key = text2num(href_list["vendItem"]) @@ -599,9 +611,11 @@ if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH to_chat(usr, "Access denied.") //Unless emagged of course) - var/mutable_appearance/deny_overlay = mutable_appearance(icon, "[icon_state]-deny", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(deny_overlay) - addtimer(CALLBACK(src, /atom/.proc/cut_overlay, deny_overlay), deny_time ? deny_time : 15) + if(exclusive_screen) + cut_overlays() + addtimer(CALLBACK(src, .proc/add_screen_overlay), deny_time ? deny_time : 15) + add_screen_overlay(deny = TRUE) + addtimer(CALLBACK(src, /atom/.proc/cut_overlay, screen_overlays["[icon_state]-deny"]), deny_time ? deny_time : 15) set_light(initial(light_range), initial(light_power), COLOR_RED_LIGHT) addtimer(CALLBACK(src, .proc/reset_light), deny_time ? deny_time : 15) return diff --git a/code/game/machinery/vending_types.dm b/code/game/machinery/vending_types.dm index 2cc550eeeb0..a1ea957b586 100644 --- a/code/game/machinery/vending_types.dm +++ b/code/game/machinery/vending_types.dm @@ -116,6 +116,7 @@ random_itemcount = 0 vending_sound = "machines/vending/vending_cans.ogg" light_color = COLOR_PALE_BLUE_GRAY + exclusive_screen = FALSE /obj/machinery/vending/assist @@ -418,7 +419,7 @@ idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan. random_itemcount = 0 temperature_setting = -1 - light_color = COLOR_GREEN_GRAY + light_color = LIGHT_COLOR_GREEN //This one's from bay12 @@ -454,7 +455,7 @@ desc = "A wall-mounted version of the NanoMed." product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?" icon_state = "wallmed" - deny_time = 14 + deny_time = 15 req_access = list(access_medical) density = 0 //It is wall-mounted, and thus, not dense. --Superxpdude vend_id = "meds" @@ -475,14 +476,14 @@ ) random_itemcount = 0 temperature_setting = -1 - light_color = COLOR_GREEN_GRAY + light_color = LIGHT_COLOR_GREEN /obj/machinery/vending/wallmed2 name = "NanoMed" desc = "A wall-mounted version of the NanoMed, containing only vital first aid equipment." icon_state = "wallmed" - deny_time = 14 + deny_time = 15 req_access = list(access_medical) density = 0 //It is wall-mounted, and thus, not dense. --Superxpdude vend_id = "meds" @@ -501,7 +502,7 @@ ) random_itemcount = 0 temperature_setting = -1 - light_color = COLOR_GREEN_GRAY + light_color = LIGHT_COLOR_GREEN /obj/machinery/vending/security @@ -536,6 +537,7 @@ restock_items = 1 random_itemcount = 0 light_color = COLOR_BABY_BLUE + exclusive_screen = FALSE /obj/machinery/vending/hydronutrients diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm index 891f37cadeb..ebf0e13c4a7 100644 --- a/code/game/objects/items/devices/radio/intercom.dm +++ b/code/game/objects/items/devices/radio/intercom.dm @@ -8,6 +8,7 @@ flags = CONDUCT | NOBLOODY var/number = 0 var/obj/machinery/abstract/intercom_listener/power_interface + var/global/list/screen_overlays var/radio_sound = null clickvol = 40 @@ -49,8 +50,18 @@ /obj/item/device/radio/intercom/Initialize() . = ..() power_interface = new(loc, src) + generate_overlays() update_icon() +/obj/item/device/radio/intercom/proc/generate_overlays(var/force = 0) + if(LAZYLEN(screen_overlays) && !force) + return + LAZYINITLIST(screen_overlays) + screen_overlays["intercom_screen"] = make_screen_overlay(icon, "intercom_screen") + screen_overlays["intercom_scanline"] = make_screen_overlay(icon, "intercom_scanline") + screen_overlays["intercom_b"] = make_screen_overlay(icon, "intercom_b") + screen_overlays["intercom_l"] = make_screen_overlay(icon, "intercom_l") + /obj/item/device/radio/intercom/department/medbay/Initialize() . = ..() internal_channels = default_medbay_channels.Copy() @@ -137,17 +148,13 @@ set_light(FALSE) return else - var/mutable_appearance/screen_overlay = mutable_appearance(icon, "intercom_screen", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(screen_overlay) - var/mutable_appearance/scanline_overlay = mutable_appearance(icon, "intercom_scanline", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(scanline_overlay) + add_overlay(screen_overlays["intercom_screen"]) + add_overlay(screen_overlays["intercom_scanline"]) set_light(1.4, 1, COLOR_CYAN) if(broadcasting) - var/mutable_appearance/button_overlay = mutable_appearance(icon, "intercom_b", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(button_overlay) + add_overlay(screen_overlays["intercom_b"]) if(listening) - var/mutable_appearance/button_overlay = mutable_appearance(icon, "intercom_l", EFFECTS_ABOVE_LIGHTING_LAYER) - add_overlay(button_overlay) + add_overlay(screen_overlays["intercom_l"]) /obj/item/device/radio/intercom/broadcasting broadcasting = 1 diff --git a/code/game/objects/items/skrell.dm b/code/game/objects/items/skrell.dm index 46dac80ba98..a56fa9f0785 100644 --- a/code/game/objects/items/skrell.dm +++ b/code/game/objects/items/skrell.dm @@ -54,6 +54,13 @@ light_power = 1 light_range = 1 light_color = LIGHT_COLOR_HALOGEN + var/global/image/glow_state + +/obj/effect/temp_visual/constellation/Initialize() + . = ..() + if(!glow_state) + glow_state = make_screen_overlay(icon, icon_state) + add_overlay(glow_state) /obj/effect/temp_visual/constellation/attackby(obj/item/W as obj, mob/user as mob) visible_message("\The [src] vanishes!") diff --git a/code/modules/clothing/ears/skrell.dm b/code/modules/clothing/ears/skrell.dm index 0777c3e6507..ceff05f4175 100644 --- a/code/modules/clothing/ears/skrell.dm +++ b/code/modules/clothing/ears/skrell.dm @@ -233,6 +233,7 @@ ..() if(color) set_light(1.5,1.5,color) + filters = filter(type="drop_shadow", color = color + "F0", size = 2, offset = 1, x = 0, y = 0) /obj/item/clothing/ears/skrell/goop/Initialize() . = ..() diff --git a/html/changelogs/MDP-glow-up.yml b/html/changelogs/MDP-glow-up.yml new file mode 100644 index 00000000000..333732e7d02 --- /dev/null +++ b/html/changelogs/MDP-glow-up.yml @@ -0,0 +1,42 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +# balance +# admin +# backend +# security +# refactor +################################# + +# Your name. +author: MoondancerPnoy + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Added a glow effect to some emissive lighting sources." + - tweak: "Changed some vendor sprites slightly to better represent the fact that they have screens." diff --git a/icons/obj/radio.dmi b/icons/obj/radio.dmi index ea1f2a59d05..94105c5e3a3 100644 Binary files a/icons/obj/radio.dmi and b/icons/obj/radio.dmi differ diff --git a/icons/obj/vending.dmi b/icons/obj/vending.dmi index 36bc6e9640f..c451fd8a3d5 100755 Binary files a/icons/obj/vending.dmi and b/icons/obj/vending.dmi differ