mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-13 00:55:20 +01:00
General maintenance for hand held camera (#95295)
## About The Pull Request - Merged a lot of procs into procs `attempt_picture()` and `interact_with_atom()` reducing proc overhead - Taking pictures will now always use the cameras internal `picture_size_x` & `picture_size_y`. It no longer accepts variable sizes as parameters - All camera operations are asynchronous and respects checks on if the target can be captured on camera or not. - A bunch of other code rearrangement that makes readability easier - Fixes the following camera bugs. They fall under the same category - Fixes #95286 - Fixes #95256 ## Changelog 🆑 fix: camera devices work again, camera flash turns on in most instances refactor: camera code has been refactored. Report bugs on github /🆑 --------- Co-authored-by: ArcaneMusic <41715314+ArcaneMusic@users.noreply.github.com>
This commit is contained in:
@@ -5,25 +5,26 @@ GLOBAL_LIST_INIT(print_types, init_print_types())
|
||||
for(var/obj/item/canvas/canvas_type as anything in typesof(/obj/item/canvas))
|
||||
var/width = canvas_type::width
|
||||
var/height = canvas_type::height
|
||||
LAZYADDASSOC(print_types, "[width]x[height]", list("[canvas_type]" = list(
|
||||
LAZYADDASSOC(print_types, "[width]x[height]", list(
|
||||
"displayText" = "Canvas ([width]x[height])",
|
||||
"typepath" = canvas_type,
|
||||
"width" = width,
|
||||
"height" = height,
|
||||
"check_callback" = CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(check_can_print_canvas)),
|
||||
"prepare_callback" = CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(prepare_canvas_from_file)),
|
||||
)))
|
||||
for(var/size in 1 to /obj/item/camera::picture_size_x_max)
|
||||
var/width = ICON_SIZE_X*(size*2-1)
|
||||
var/height = ICON_SIZE_Y*(size*2-1)
|
||||
LAZYADDASSOC(print_types, "[width]x[height]", list("[/obj/item/photo]" = list(
|
||||
"displayText" = "Photo Paper ([size*2-1]m focal length)",
|
||||
))
|
||||
for(var/size in 1 to CAMERA_PICTURE_SIZE_HARD_LIMIT)
|
||||
var/meters = APERTURE_TO_METERS(size)
|
||||
var/width = ICON_SIZE_X * meters
|
||||
var/height = ICON_SIZE_Y * meters
|
||||
LAZYADDASSOC(print_types, "[width]x[height]", list(
|
||||
"displayText" = "Photo Paper ([meters]m focal length)",
|
||||
"typepath" = /obj/item/photo,
|
||||
"width" = width,
|
||||
"height" = height,
|
||||
"check_callback" = CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(check_can_print_photo)),
|
||||
"prepare_callback" = CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(prepare_photo_from_file)),
|
||||
)))
|
||||
))
|
||||
return print_types
|
||||
|
||||
/proc/check_can_print_canvas(_typepath, _image_file, obj/item/modular_computer/computer, mob/user)
|
||||
@@ -177,11 +178,8 @@ GLOBAL_LIST_INIT(print_types, init_print_types())
|
||||
try_print(picture, params["width"], params["height"], params["offsetX"], params["offsetY"], params["typepath"], usr)
|
||||
|
||||
/datum/computer_file/program/filemanager/proc/try_print(datum/computer_file/image/picture, width, height, offset_x, offset_y, typepath, mob/user)
|
||||
var/list/print_types_for_dimensions = GLOB.print_types["[width]x[height]"]
|
||||
if(!length(print_types_for_dimensions))
|
||||
return
|
||||
var/list/print_type = print_types_for_dimensions[typepath]
|
||||
if(!print_type)
|
||||
var/list/print_type = GLOB.print_types["[width]x[height]"]
|
||||
if(!length(print_type))
|
||||
return
|
||||
var/image_width = picture.stored_icon.Width()
|
||||
var/image_height = picture.stored_icon.Height()
|
||||
@@ -203,10 +201,16 @@ GLOBAL_LIST_INIT(print_types, init_print_types())
|
||||
|
||||
/datum/computer_file/program/filemanager/ui_static_data(mob/user)
|
||||
var/list/print_types = list()
|
||||
for(var/dimensions in GLOB.print_types)
|
||||
var/list/types_for_dimensions = GLOB.print_types[dimensions]
|
||||
for(var/print_typepath in types_for_dimensions)
|
||||
print_types += list(types_for_dimensions[print_typepath])
|
||||
for(var/dimensions, types_for_dimensions in GLOB.print_types)
|
||||
var/list/typepath = types_for_dimensions["typepath"]
|
||||
if(ispath(typepath, /obj/item/canvas) && !(computer.hardware_flag & PROGRAM_CONSOLE))
|
||||
continue
|
||||
print_types += list(list(
|
||||
displayText = types_for_dimensions["displayText"],
|
||||
typepath = "[typepath]",
|
||||
width = types_for_dimensions["width"],
|
||||
height = types_for_dimensions["height"]
|
||||
))
|
||||
return list("printTypes" = print_types)
|
||||
|
||||
/datum/computer_file/program/filemanager/ui_data(mob/user)
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
var/obj/item/camera/app/internal_camera
|
||||
/// Latest picture taken by the app.
|
||||
var/datum/picture/internal_picture
|
||||
/// A mutable_appearance of the latest picture, for getting an appeance reference for the UI.
|
||||
var/mutable_appearance/picture_appearance
|
||||
/// base64 of the current taken picture
|
||||
var/internal_picture_icon
|
||||
/// How many pictures were taken already, used for the camera's TGUI photo display
|
||||
var/picture_number = 1
|
||||
/// Can we edit the metadata of the latest picture?
|
||||
@@ -29,24 +29,20 @@
|
||||
|
||||
// Special type of camera for this exact usecase to prevent harddels
|
||||
/obj/item/camera/app
|
||||
name = "internal camera"
|
||||
desc = "Specialized internal camera protected from the hellish depths of SSWardrobe. \
|
||||
Yell at coders if you somehow manage to see this"
|
||||
print_picture_on_snap = FALSE
|
||||
cooldown = 1 SECONDS
|
||||
light_range = 3
|
||||
|
||||
/datum/computer_file/program/maintenance/camera/on_install(datum/computer_file/source, obj/item/modular_computer/computer_installing, mob/user)
|
||||
. = ..()
|
||||
internal_camera = new(computer)
|
||||
internal_camera.print_picture_on_snap = FALSE
|
||||
picture_appearance = new()
|
||||
RegisterSignal(internal_camera, COMSIG_CAMERA_IMAGE_CAPTURED, PROC_REF(on_image_captured))
|
||||
|
||||
/datum/computer_file/program/maintenance/camera/Destroy()
|
||||
QDEL_NULL(internal_camera)
|
||||
internal_picture = null
|
||||
QDEL_NULL(picture_appearance)
|
||||
QDEL_NULL(internal_picture)
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/computer_file/program/maintenance/camera/tap(atom/tapped_atom, mob/living/user, list/modifiers)
|
||||
. = ..()
|
||||
take_picture(user, get_turf(tapped_atom))
|
||||
@@ -57,7 +53,7 @@
|
||||
/datum/computer_file/program/maintenance/camera/kill_program(mob/user)
|
||||
. = ..()
|
||||
UnregisterSignal(computer, COMSIG_RANGED_ITEM_INTERACTING_WITH_ATOM_SECONDARY)
|
||||
internal_picture = null
|
||||
QDEL_NULL(internal_picture)
|
||||
|
||||
/datum/computer_file/program/maintenance/camera/background_program(mob/user)
|
||||
. = ..()
|
||||
@@ -68,47 +64,21 @@
|
||||
take_picture(user, get_turf(target))
|
||||
|
||||
/datum/computer_file/program/maintenance/camera/proc/take_picture(mob/user, turf/target)
|
||||
if(internal_camera.blending)
|
||||
user.balloon_alert(user, "still blending!")
|
||||
return
|
||||
|
||||
var/spooky_camera = locate(/datum/computer_file/program/maintenance/spectre_meter) in computer.stored_files
|
||||
internal_camera.see_ghosts = spooky_camera ? CAMERA_SEE_GHOSTS_BASIC : CAMERA_NO_GHOSTS
|
||||
INVOKE_ASYNC(internal_camera, TYPE_PROC_REF(/obj/item/camera, captureimage), target, user, internal_camera.picture_size_x - 1, internal_camera.picture_size_y - 1)
|
||||
internal_camera.see_ghosts = (locate(/datum/computer_file/program/maintenance/spectre_meter) in computer.stored_files) ? CAMERA_SEE_GHOSTS_BASIC : CAMERA_NO_GHOSTS
|
||||
internal_camera.attempt_picture(target, user)
|
||||
|
||||
/datum/computer_file/program/maintenance/camera/proc/on_image_captured(cam, target, user, datum/picture/picture)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
QDEL_NULL(internal_picture)
|
||||
internal_picture = picture
|
||||
picture_appearance.icon = internal_picture.picture_image
|
||||
internal_picture_icon = icon2base64(internal_picture.picture_image)
|
||||
current_picture_name = null
|
||||
current_picture_desc = null
|
||||
current_picture_caption = null
|
||||
can_edit_metadata = TRUE
|
||||
picture_number++
|
||||
|
||||
/datum/computer_file/program/maintenance/camera/proc/save_picture(mob/user)
|
||||
var/datum/computer_file/image/photo_file = new(
|
||||
internal_picture.picture_image,
|
||||
display_name = internal_picture.picture_name || "photo[picture_number]",
|
||||
source_photo_or_painting = internal_picture
|
||||
)
|
||||
if(computer.store_file(photo_file, user))
|
||||
return FALSE
|
||||
commit_metadata()
|
||||
return TRUE
|
||||
|
||||
/datum/computer_file/program/maintenance/camera/proc/print_picture(mob/user)
|
||||
if(computer.stored_paper < PHOTO_PAPER_COST)
|
||||
return
|
||||
commit_metadata()
|
||||
var/obj/item/photo/new_photo = new(computer.physical.drop_location())
|
||||
new_photo.set_picture(internal_picture, TRUE, TRUE)
|
||||
user?.put_in_hands(new_photo)
|
||||
playsound(computer.physical, 'sound/machines/printer.ogg', 100, TRUE)
|
||||
computer.stored_paper--
|
||||
computer.visible_message(span_notice("\The [computer] prints out a paper."))
|
||||
|
||||
/datum/computer_file/program/maintenance/camera/proc/commit_metadata()
|
||||
if(can_edit_metadata)
|
||||
internal_picture.picture_name = current_picture_name
|
||||
@@ -117,105 +87,90 @@
|
||||
can_edit_metadata = FALSE
|
||||
|
||||
/datum/computer_file/program/maintenance/camera/ui_static_data(mob/user)
|
||||
return list("maxNameLength" = 32, "maxDescLength" = 128, "maxCaptionLength" = 256, "printCost" = 1)
|
||||
return list(
|
||||
"maxNameLength" = 32,
|
||||
"maxDescLength" = 128,
|
||||
"maxCaptionLength" = 256,
|
||||
"printCost" = 1,
|
||||
"minSize" = 2,
|
||||
"maxSize" = CAMERA_PICTURE_SIZE_HARD_LIMIT
|
||||
)
|
||||
|
||||
/datum/computer_file/program/maintenance/camera/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
if(!isnull(internal_picture))
|
||||
data["photo"] = REF(picture_appearance.appearance)
|
||||
data["photo"] = internal_picture_icon
|
||||
data["canEditMetadata"] = can_edit_metadata
|
||||
data["name"] = current_picture_name
|
||||
data["desc"] = current_picture_desc
|
||||
data["caption"] = current_picture_caption
|
||||
data["storedPaper"] = computer.stored_paper
|
||||
data["size"] = internal_camera.picture_size_x
|
||||
data["minSize"] = internal_camera.picture_size_x_min
|
||||
data["maxSize"] = min(internal_camera.picture_size_x_max, CAMERA_PICTURE_SIZE_HARD_LIMIT)
|
||||
|
||||
data["width"] = internal_camera.picture_size_x
|
||||
data["height"] = internal_camera.picture_size_y
|
||||
data["size"] = "[APERTURE_TO_METERS(internal_camera.picture_size_x)]x[APERTURE_TO_METERS(internal_camera.picture_size_y)]"
|
||||
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/maintenance/camera/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("adjustSize")
|
||||
var/new_size = round(params["value"], 1)
|
||||
if(!ISINRANGE(new_size, internal_camera.picture_size_x_min, min(CAMERA_PICTURE_SIZE_HARD_LIMIT, internal_camera.picture_size_x_max)))
|
||||
if("adjustWidth")
|
||||
var/new_size = text2num(params["value"])
|
||||
if(!new_size)
|
||||
return
|
||||
internal_camera.picture_size_x = new_size
|
||||
internal_camera.picture_size_y = new_size
|
||||
return internal_camera.adjust_zoom(desired_x = new_size)
|
||||
|
||||
if("adjustHeight")
|
||||
var/new_size = text2num(params["value"])
|
||||
if(!new_size)
|
||||
return
|
||||
return internal_camera.adjust_zoom(desired_y = new_size)
|
||||
|
||||
if("setName")
|
||||
if(!(internal_picture && can_edit_metadata))
|
||||
return
|
||||
return FALSE
|
||||
current_picture_name = trim(params["value"], PREVENT_CHARACTER_TRIM_LOSS(32))
|
||||
return TRUE
|
||||
|
||||
if("setDesc")
|
||||
if(!(internal_picture && can_edit_metadata))
|
||||
return
|
||||
current_picture_desc = trim(params["value"], PREVENT_CHARACTER_TRIM_LOSS(128))
|
||||
return TRUE
|
||||
|
||||
if("setCaption")
|
||||
if(!(internal_picture && can_edit_metadata))
|
||||
return
|
||||
current_picture_caption = trim(params["value"], PREVENT_CHARACTER_TRIM_LOSS(256))
|
||||
return TRUE
|
||||
|
||||
if("savePhoto")
|
||||
if(!internal_picture)
|
||||
return
|
||||
save_picture(ui.user)
|
||||
var/datum/computer_file/image/photo_file = new(
|
||||
internal_picture.picture_image,
|
||||
display_name = internal_picture.picture_name || "photo[picture_number]",
|
||||
source_photo_or_painting = internal_picture
|
||||
)
|
||||
if(computer.store_file(photo_file, ui.user))
|
||||
return FALSE
|
||||
commit_metadata()
|
||||
return TRUE
|
||||
if("printPhoto")
|
||||
if(!internal_picture)
|
||||
return
|
||||
print_picture(ui.user)
|
||||
return TRUE
|
||||
|
||||
/obj/item/circuit_component/mod_program/camera
|
||||
associated_program = /datum/computer_file/program/maintenance/camera
|
||||
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL
|
||||
|
||||
///A target to take a picture of.
|
||||
var/datum/port/input/picture_target
|
||||
///The size of the photo to take.
|
||||
var/datum/port/input/picture_size
|
||||
///The photographed target
|
||||
var/datum/port/output/photographed
|
||||
/**
|
||||
* Pinged when the image has been captured.
|
||||
* I'm not using the default trigger output here because the process is asynced,
|
||||
* even though I'm mostly sure it only sleeps if there's a set user.
|
||||
*/
|
||||
var/datum/port/output/photo_taken
|
||||
|
||||
/obj/item/circuit_component/mod_program/camera/populate_ports()
|
||||
. = ..()
|
||||
picture_target = add_input_port("Picture Target", PORT_TYPE_ATOM)
|
||||
picture_size = add_input_port("Picture Size", PORT_TYPE_NUMBER)
|
||||
photographed = add_output_port("Photographed Entity", PORT_TYPE_ATOM)
|
||||
photo_taken = add_output_port("Photo Taken", PORT_TYPE_SIGNAL)
|
||||
|
||||
/obj/item/circuit_component/mod_program/camera/register_shell(atom/movable/shell)
|
||||
. = ..()
|
||||
var/datum/computer_file/program/maintenance/camera/cam = associated_program
|
||||
RegisterSignal(cam.internal_camera, COMSIG_CAMERA_IMAGE_CAPTURED, PROC_REF(on_image_captured))
|
||||
|
||||
/obj/item/circuit_component/mod_program/camera/unregister_shell()
|
||||
var/datum/computer_file/program/maintenance/camera/cam = associated_program
|
||||
UnregisterSignal(cam.internal_camera, COMSIG_CAMERA_IMAGE_CAPTURED)
|
||||
return ..()
|
||||
|
||||
/obj/item/circuit_component/mod_program/camera/input_received(datum/port/input/port)
|
||||
if(!COMPONENT_TRIGGERED_BY(port, trigger_input))
|
||||
return
|
||||
var/atom/target = picture_target.value
|
||||
if(!target)
|
||||
var/turf/our_turf = get_location()
|
||||
target = locate(our_turf.x, our_turf.y, our_turf.z)
|
||||
if(!target)
|
||||
return
|
||||
var/datum/computer_file/program/maintenance/camera/cam = associated_program
|
||||
if(!cam.internal_camera.can_target(target))
|
||||
return
|
||||
var/pic_size = clamp(round(picture_size.value), 1, cam.internal_camera.picture_size_x_max)-1
|
||||
INVOKE_ASYNC(cam.internal_camera, TYPE_PROC_REF(/obj/item/camera, captureimage), target, null, pic_size, pic_size)
|
||||
|
||||
/obj/item/circuit_component/mod_program/camera/proc/on_image_captured(obj/item/camera/source, atom/target, mob/user)
|
||||
SIGNAL_HANDLER
|
||||
photographed.set_output(target)
|
||||
photo_taken.set_output(COMPONENT_SIGNAL)
|
||||
return FALSE
|
||||
if(computer.stored_paper < PHOTO_PAPER_COST)
|
||||
return FALSE
|
||||
commit_metadata()
|
||||
var/obj/item/photo/new_photo = new(computer.physical.drop_location())
|
||||
new_photo.set_picture(internal_picture, TRUE, TRUE)
|
||||
ui.user.put_in_hands(new_photo)
|
||||
playsound(computer.physical, 'sound/machines/printer.ogg', 100, TRUE)
|
||||
computer.stored_paper--
|
||||
computer.visible_message(span_notice("\The [computer] prints out a paper."))
|
||||
return TRUE
|
||||
|
||||
@@ -330,7 +330,7 @@ GLOBAL_LIST_EMPTY(virtual_pets_list)
|
||||
var/datum/action/cooldown/mob_cooldown/capture_photo/photo_ability = new(pet)
|
||||
photo_ability.Grant(pet)
|
||||
pet.ai_controller?.set_blackboard_key(BB_PHOTO_ABILITY, photo_ability)
|
||||
RegisterSignal(photo_ability.ability_camera, COMSIG_CAMERA_IMAGE_CAPTURED, PROC_REF(on_photo_captured))
|
||||
RegisterSignal(photo_ability.internal_camera, COMSIG_CAMERA_IMAGE_CAPTURED, PROC_REF(on_photo_captured))
|
||||
|
||||
/datum/computer_file/program/virtual_pet/proc/announce_global_updates(message)
|
||||
if(isnull(message))
|
||||
|
||||
Reference in New Issue
Block a user