ID:1792869
 
I was helping someone on the Developer Help forum, and just came up with something I like, so I am posting it here.

This snippet let's you center an overlay on the X and Y axis.
The snippet is really sort, and probably could be achieved by other ways, but until I come with those, this is the current status of the snippet:

var/list/cached_offsets[0]
proc/get_pixel_x(base, overlay)
if(!base || !overlay) return 0

if(!cached_offsets.Find("[base]"))
cached_offsets.Add("[base]")
cached_offsets["[base]"] = list(
"[overlay]" = null
)

if(!cached_offsets["[base]"]["[overlay]"])
cached_offsets["[base]"]["[overlay]"] = list(
"x" = null,
"y" = null
)

if(cached_offsets["[base]"]["[overlay]"]["x"]==null)
cached_offsets["[base]"]["[overlay]"]["x"] = get_x_offset(icon(base), icon(overlay))

return cached_offsets["[base]"]["[overlay]"]["x"]

proc/get_pixel_y(icon/base, icon/overlay)
if(!base || !overlay) return 0

if(!cached_offsets.Find("[base]"))
cached_offsets.Add("[base]")
cached_offsets["[base]"] = list(
"[overlay]" = null
)

if(!cached_offsets["[base]"]["[overlay]"])
cached_offsets["[base]"]["[overlay]"] = list(
"x" = null,
"y" = null
)

if(cached_offsets["[base]"]["[overlay]"]["y"]==null)
cached_offsets["[base]"]["[overlay]"]["y"] = get_y_offset(icon(base), icon(overlay))

return cached_offsets["[base]"]["[overlay]"]["y"]


proc/get_x_offset(icon/base, icon/overlay)
if(!base || !overlay) return 0
return round(((base.Width() - overlay.Width()) / 2),1)

proc/get_y_offset(icon/base, icon/overlay)
if(!base || !overlay) return 0
return round(((base.Height() - overlay.Height()) / 2),1)


Those two procs returns the number of pixels on both axis, an overlay should be offset by, in order to be centered into it's holder.
The usage of the procs would be as follows:

ob/proc/overlayMe()
src.overlays += image('thebiggericon.dmi',\
pixel_x = get_pixel_x("[src.icon]", "thebiggericon.dmi"),
pixel_y = get_pixel_y("[src.icon]", "thebiggericon.dmi"))


The above snippet would center 'thebiggericon.dmi' on 'src'.
If you just want to center the overlay horizontally, you just need to remove the pixel_y line, and vice-versa.

Pixels offset are rounded, so 1.4 offset would be 1.


Happy overlaying.
A softer version of the snippet; barely improves efficiency though:

proc/get_pixel_x(icon/base,  icon/overlay)
if(!base || !overlay) return 0
return round(((base.Width() - overlay.Width()) / 2),1)

proc/get_pixel_y(icon/base, icon/overlay)
if(!base || !overlay) return 0
return round(((base.Height() - overlay.Height()) / 2),1)
Keep in mind, calling icon.Width() and icon.Height() so often will destroy your resource usage, you should cache the results as you get them.
Thanks Nadrew for pointing it out!
I have come up with the following as a solution:

var/list/cached_offsets[0]
proc/get_pixel_x(base, overlay)
if(!base || !overlay) return 0
if(!cached_offsets.Find(base))
cached_offsets["[base]"]["[overlay]"]["x"] = get_x_offset((istext(base) ? icon(base) : base), (istext(overlay) ? icon(overlay) : overlay))
return cached_offsets["[base]"]["[overlay]"]["x"]

proc/get_pixel_y(icon/base, icon/overlay)
if(!base || !overlay) return 0
if(!cached_offsets.Find(base))
cached_offsets["[base]"]["[overlay]"]["y"] = get_y_offset((istext(base) ? icon(base) : base), (istext(overlay) ? icon(overlay) : overlay))
return cached_offsets["[base]"]["[overlay]"]["y"]


proc/get_x_offset(icon/base, icon/overlay)
if(!base || !overlay) return 0
return round(((base.Width() - overlay.Width()) / 2),1)

proc/get_y_offset(icon/base, icon/overlay)
if(!base || !overlay) return 0
return round(((base.Height() - overlay.Height()) / 2),1)



The usage passes to be the following: (although similar)

mob/proc/overlayMe()
src.overlays += image('thebiggericon.dmi',\
pixel_x = get_pixel_x("[src.icon]", "thebiggericon.dmi"),
pixel_y = get_pixel_y("[src.icon]", "thebiggericon.dmi"))


As it can be seen, you now pass an icon's file name as a text string for it to be cached if needed.
Tweaked it again, it did not really work as expected.
This new version is actually working perfectly, at no cost, thanks to Nadrew for pointing out such obvious issue!

var/list/cached_offsets[0]
proc/get_pixel_x(base, overlay)
if(!base || !overlay) return 0

if(!cached_offsets.Find("[base]"))
cached_offsets.Add("[base]")
cached_offsets["[base]"] = list(
"[overlay]" = null
)

if(!cached_offsets["[base]"]["[overlay]"])
cached_offsets["[base]"]["[overlay]"] = list(
"x" = null,
"y" = null
)

if(cached_offsets["[base]"]["[overlay]"]["x"]==null)
cached_offsets["[base]"]["[overlay]"]["x"] = get_x_offset(icon(base), icon(overlay))

return cached_offsets["[base]"]["[overlay]"]["x"]

proc/get_pixel_y(icon/base, icon/overlay)
if(!base || !overlay) return 0

if(!cached_offsets.Find("[base]"))
cached_offsets.Add("[base]")
cached_offsets["[base]"] = list(
"[overlay]" = null
)

if(!cached_offsets["[base]"]["[overlay]"])
cached_offsets["[base]"]["[overlay]"] = list(
"x" = null,
"y" = null
)

if(cached_offsets["[base]"]["[overlay]"]["y"]==null)
cached_offsets["[base]"]["[overlay]"]["y"] = get_y_offset(icon(base), icon(overlay))

return cached_offsets["[base]"]["[overlay]"]["y"]


proc/get_x_offset(icon/base, icon/overlay)
if(!base || !overlay) return 0
return round(((base.Width() - overlay.Width()) / 2),1)

proc/get_y_offset(icon/base, icon/overlay)
if(!base || !overlay) return 0
return round(((base.Height() - overlay.Height()) / 2),1)



I am currently profiling the world on a local server throug DS, on a non-hosted and empty environment;

                        Profile results (total time)
Proc Name Self CPU Total CPU Real Time Calls
------------------------ --------- --------- --------- ---------
/proc/get_pixel_x 0.049 0.049 0.049 9728
/proc/get_pixel_y 0.015 0.015 0.015 9728


Average values:
                        Profile results (total time)
Proc Name Self CPU Total CPU Real Time Calls
------------------------ --------- --------- --------- ---------
/proc/get_pixel_x 0.000 0.000 0.000 9728
/proc/get_pixel_y 0.000 0.000 0.000 9728