diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index 3466ec36e95..a9a04a4f621 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -699,7 +699,7 @@ proc // Creates a single icon from a given /atom or /image. Only the first argu while(TRUE) if(curIndex<=process.len) current = process[curIndex] - if(!current) + if(!current) curIndex++ //Skip this bad layer item continue currentLayer = current:layer @@ -857,3 +857,26 @@ proc/sort_atoms_by_layer(var/list/atoms) result.Swap(i, gap + i) swapped = 1 return result + +//Interface for using DrawBox() to draw 1 pixel on a coordinate. +//Returns the same icon specifed in the argument, but with the pixel drawn +/proc/DrawPixel(var/icon/I,var/colour,var/drawX,var/drawY) + if(!I) + return 0 + var/Iwidth = I.Width() + var/Iheight = I.Height() + if(drawX > Iwidth || drawX <= 0) + return 0 + if(drawY > Iheight || drawY <= 0) + return 0 + I.DrawBox(colour,drawX, drawY) + return I + +//Interface for easy drawing of one pixel on an atom. +/atom/proc/DrawPixelOn(var/colour, var/drawX, var/drawY) + var/icon/I = new(icon) + var/icon/J = DrawPixel(I, colour, drawX, drawY) + if(J) //Only set the icon if it succeeded, the icon without the pixel is 1000x better than a black square. + icon = J + return J + return 0 \ No newline at end of file diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 30ac106c1b3..3f7190e90e2 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -155,6 +155,7 @@ var/global/list/datum/stack_recipe/wood_recipes = list ( \ new/datum/stack_recipe("wooden door", /obj/structure/mineral_door/wood, 10, time = 20, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("coffin", /obj/structure/closet/coffin, 5, time = 15, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("apiary", /obj/item/apiary, 10, time = 25, one_per_turf = 0, on_floor = 0), \ + new/datum/stack_recipe("easel", /obj/structure/easel, 3, one_per_turf = 1, on_floor = 1), \ ) /obj/item/stack/sheet/wood diff --git a/code/game/objects/structures/artstuff.dm b/code/game/objects/structures/artstuff.dm new file mode 100644 index 00000000000..64f09d7e803 --- /dev/null +++ b/code/game/objects/structures/artstuff.dm @@ -0,0 +1,151 @@ +///////////////// +// NEW DEFINES // +///////////////// + +/client + var/viewingCanvas = 0 //If this is 1, as soon as client /TRIES/ to move the view resets. + +/////////// +// EASEL // +/////////// + +/obj/structure/easel + name = "easel" + desc = "only for the finest of art!" + icon = 'icons/obj/artstuff.dmi' + icon_state = "easel" + density = 1 + var/obj/item/weapon/canvas/painting = null + + +//Adding canvases +/obj/structure/easel/attackby(var/obj/item/I, var/mob/user, params) + if(istype(I, /obj/item/weapon/canvas)) + var/obj/item/weapon/canvas/C = I + user.unEquip(C) + painting = C + C.loc = get_turf(src) + C.layer = layer+0.1 + user.visible_message("[user] puts \the [C] on \the [src].","You place \the [C] on \the [src].") + return + + ..() + + +//Stick to the easel like glue +/obj/structure/easel/Move() + var/turf/T = get_turf(src) + ..() + if(painting && painting.loc == T) //Only move if it's near us. + painting.loc = get_turf(src) + else + painting = null + + +////////////// +// CANVASES // +////////////// + +#define AMT_OF_CANVASES 4 //Keep this up to date or shit will break. + +//To safe memory on making /icons we cache the blanks.. +var/global/list/globalBlankCanvases[AMT_OF_CANVASES] + +/obj/item/weapon/canvas + name = "11px by 11px canvas" + desc = "Draw out your soul on this canvas! Only crayons can draw on it. Examine it to focus on the canvas." + icon = 'icons/obj/artstuff.dmi' + icon_state = "11x11" + var/whichGlobalBackup = 1 //List index + +/obj/item/weapon/canvas/nineteenXnineteen + name = "19px by 19px canvas" + icon_state = "19x19" + whichGlobalBackup = 2 + +/obj/item/weapon/canvas/twentythreeXnineteen + name = "23px by 19px canvas" + icon_state = "23x19" + whichGlobalBackup = 3 + +/obj/item/weapon/canvas/twentythreeXtwentythree + name = "23px by 23px canvas" + icon_state = "23x23" + whichGlobalBackup = 4 + + +//Find the right size blank canvas +/obj/item/weapon/canvas/proc/getGlobalBackup() + . = null + if(globalBlankCanvases[whichGlobalBackup]) + . = globalBlankCanvases[whichGlobalBackup] + else + var/icon/I = icon(initial(icon),initial(icon_state)) + globalBlankCanvases[whichGlobalBackup] = I + . = I + + + +//One pixel increments +/obj/item/weapon/canvas/attackby(var/obj/item/I, var/mob/user, params) + //Click info + var/list/click_params = params2list(params) + var/pixX = text2num(click_params["icon-x"]) + var/pixY = text2num(click_params["icon-y"]) + + //Should always be true, otherwise you didn't click the object, but let's check because SS13~ + if(!click_params || !click_params["icon-x"] || !click_params["icon-y"]) + return + + var/icon/masterpiece = icon(icon,icon_state) + //Cleaning one pixel with a soap or rag + if(istype(I, /obj/item/weapon/soap) || istype(I, /obj/item/weapon/reagent_containers/glass/rag)) + //Pixel info created only when needed + var/thePix = masterpiece.GetPixel(pixX,pixY) + var/icon/Ico = getGlobalBackup() + if(!Ico) + qdel(masterpiece) + return + + var/theOriginalPix = Ico.GetPixel(pixX,pixY) + if(thePix != theOriginalPix) //colour changed + DrawPixelOn(theOriginalPix,pixX,pixY) + qdel(masterpiece) + return + + //Drawing one pixel with a crayon + if(istype(I, /obj/item/toy/crayon)) + var/obj/item/toy/crayon/C = I + if(masterpiece.GetPixel(pixX, pixY)) // if the located pixel isn't blank (null)) + DrawPixelOn(C.colour, pixX, pixY) + return + + ..() + +//Clean the whole canvas +/obj/item/weapon/canvas/attack_self(var/mob/user) + if(!user) + return + var/icon/blank = getGlobalBackup() + if(blank) + //it's basically a giant etch-a-sketch + icon = blank + user.visible_message("[user] cleans the canvas.","You clean the canvas.") + +//Examine to enlarge +/obj/item/weapon/canvas/examine(var/mob/user = usr) + ..() + if(in_range(user, src) && get_turf(src) && user.client && ishuman(user)) //Let only humans be the robust zoominators. I'm too spooked other mobs trying to use it may get broken huds. + if(src.loc == user || get_turf(src) == get_turf(user)) + user << "[src] has to be on the ground to focus on it!" + return + user << "You focus on \the [src]." + user.client.screen = list() //This is because screen objects go way past the view bounds we set, therefore not allowing stretch to fit to zoom in properly. + user.client.reset_stretch = winget(user.client, "mapwindow.map", "icon-size") //Remember previous icon-size + user.client.view = 3 //Decrease view + winset(user.client, "mapwindow.map", "icon-size=0") //Enable stretch-to-fit + user.client.viewingCanvas = 1 //Reset everything we just changed as soon as client tries to move + else + user << "It is too far away." + +#undef AMT_OF_CANVASES \ No newline at end of file diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm index 0dfa00ca8cf..cbfa50f0759 100644 --- a/code/modules/client/client defines.dm +++ b/code/modules/client/client defines.dm @@ -70,4 +70,6 @@ "AZERTY" = list( "on" = "AZERTYon", "off" = "AZERTYoff") - ) \ No newline at end of file + ) + + var/reset_stretch = 0 //Used by things that fiddle with client's stretch-to-fit. \ No newline at end of file diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 5afda13a9be..0407a0edc07 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -176,6 +176,17 @@ /client/Move(n, direct) + if(viewingCanvas) + view = world.view //Reset the view + winset(src, "mapwindow.map", "icon-size=[src.reset_stretch]") + viewingCanvas = 0 + mob.reset_view() + mob.button_pressed_F12() + if(!mob.hud_used.hud_shown) + mob.button_pressed_F12() + mob.update_hud() + mob.update_action_buttons() + if(mob.control_object) Move_object(direct) if(world.time < move_delay) return diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm index 970f0b139f9..d58d23f09cf 100644 --- a/code/modules/research/designs/autolathe_designs.dm +++ b/code/modules/research/designs/autolathe_designs.dm @@ -226,6 +226,38 @@ build_path = /obj/item/device/assembly/voice category = list("initial", "Miscellaneous") +/datum/design/canvas + name = "11px by 11px Canvas" + id = "canvas" + build_type = AUTOLATHE + materials = list("$metal" = 50) + build_path = /obj/item/weapon/canvas + category = list("initial", "Miscellaneous") + +/datum/design/canvas/nineteenXnineteen + name = "19px by 19px Canvas" + id = "canvas19x19" + build_type = AUTOLATHE + materials = list("$metal" = 50) + build_path = /obj/item/weapon/canvas/nineteenXnineteen + category = list("initial", "Miscellaneous") + +/datum/design/canvas/twentythreeXnineteen + name = "23px by 19px Canvas" + id = "canvas23x19" + build_type = AUTOLATHE + materials = list("$metal" = 70) + build_path = /obj/item/weapon/canvas/twentythreeXnineteen + category = list("initial", "Miscellaneous") + +/datum/design/canvas/twentythreeXtwentythree + name = "23px by 23px Canvas" + id = "canvas23x23" + build_type = AUTOLATHE + materials = list("$metal" = 100) + build_path = /obj/item/weapon/canvas/twentythreeXtwentythree + category = list("initial", "Miscellaneous") + /datum/design/camera_assembly name = "Camera Assembly" id = "camera_assembly" diff --git a/icons/obj/artstuff.dmi b/icons/obj/artstuff.dmi new file mode 100644 index 00000000000..a11d1a81d0e Binary files /dev/null and b/icons/obj/artstuff.dmi differ diff --git a/paradise.dme b/paradise.dme index a4711b96195..9741089c862 100644 --- a/paradise.dme +++ b/paradise.dme @@ -762,6 +762,7 @@ #include "code\game\objects\items\weapons\tanks\tanks.dm" #include "code\game\objects\items\weapons\tanks\watertank.dm" #include "code\game\objects\random\random.dm" +#include "code\game\objects\structures\artstuff.dm" #include "code\game\objects\structures\barsign.dm" #include "code\game\objects\structures\bedsheet_bin.dm" #include "code\game\objects\structures\coathanger.dm"