luv

Workshop wiki

phone.lisp

luvcraft/phone.lisp

system luvcraft/core · 39 definitions · on GitHub

The phone: a wall terminal you can carry.

#S27JKR is the design; this is what it turned into.

A phone is the first thing the player's hand can hold (BODY.LISP), and what it does is what the wall terminals do: it shows a live shell. The whole terminal display -- Ghostty terminal, PTY, glyph and cell runs, screen panel and faceplate glass -- is the one TERMINAL-WALL.LISP already builds; only its surface is new. A wall's surface is a rectangle of blocks in the world. The phone's is a rectangle in the grip frame, the hand's own coordinate space, where the screen never moves at all. What moves is the hand, and so, seen from the phone, the camera: each frame the display draws against a frame uniform whose camera is the real one re-expressed in grip coordinates. Nothing about the runs is rebuilt for motion; the same glyph instances that were right last frame are right this frame, because in their own space nothing happened.

The phone is a focus like a wall is: TAB with the phone out enters it and keys go to its shell, shift-TAB leaves. Putting the phone away pockets it with its shell still running; taking it out again brings the same shell back.

in-package#:luvcraft

The slab, in the grip frame: 0.37 wide, 0.46 tall, 0.022 thin, held in front of the palm by its lower third with the thumb up one edge and the fingers round the other. A little large for a phone, a little squat for one too -- the proportions of a small handheld console -- because what it carries is a terminal: sixty condensed columns.

defparameter*phone-half-width*0.185d0
defparameter*phone-half-height*0.230d0
defparameter*phone-half-depth*0.011d0
defparameter*phone-corner-radius*0.034d0"How far the slab's corners are rounded, in cells."
defparameter*phone-center-height*0.130d0"The slab's centre above the palm, which holds it by its lower third."
defparameter*phone-center-depth*-0.170d0"The slab's centre in front of the palm."
defparameter*phone-screen-half-width*0.168d0
defparameter*phone-screen-half-height*0.208d0
defparameter*phone-screen-depth*"The screen plane's z in the grip frame: the slab's face toward the eye."
defparameter*phone-terminal-rows*35"How many rows of shell the phone shows; the columns follow its width."
defparameter*phone-terminal-margin*0.008"The bezel between the screen's edge and its font grid, in cells."
defunphone-font-pathname
weight

The phone's font: Input Mono Condensed from the user's fonts when it is installed (its licence keeps it out of the repository), else the wall's. weight is "Regular" or "Bold".

let
installed
merge-pathnames
formatnil"Library/Fonts/InputMonoCondensed-~A.ttf"weight
user-homedir-pathname
if
probe-fileinstalled
installed

--------------------------------------------------------------------- The phone's screen as a terminal surface.

defclassphone-screen-surface
phone:initarg:phone:readerphone-screen-surface-phone
:documentation

The phone's screen rectangle in the grip frame: right is grip x, up is grip y, and outward is toward the eye, grip -z.

defmethodterminal-surface-axes
values
make-vec31.00.00.0
make-vec30.01.00.0
make-vec30.00.0-1.0
defmethodterminal-surface-current-p
&optionalsession
declare
ignoresession
t
defmethodterminal-surface-focus-score

The phone in hand is nearer than anything the crosshair could be on.

when
phone-in-hand-p
phone-screen-surface-phonesurface
session
0.0
defmethodterminal-surface-panel-frame
&optional
offset0.010

The general answer is in grip space, since that is the space the phone surface describes itself in; carry it into the world through wherever the hand is this frame.

multiple-value-bind
centerright-axisup-axisoutward
call-next-methodsurfacesessionoffset
multiple-value-bind
palmgrip-rightgrip-upgrip-forward
flet
into-world
v
make-vec3
+
*
vec3-xv
vec3-xgrip-right
*
vec3-yv
vec3-xgrip-up
*
vec3-zv
vec3-xgrip-forward
+
*
vec3-xv
vec3-ygrip-right
*
vec3-yv
vec3-ygrip-up
*
vec3-zv
vec3-ygrip-forward
+
*
vec3-xv
vec3-zgrip-right
*
vec3-yv
vec3-zgrip-up
*
vec3-zv
vec3-zgrip-forward
values
frame-pointpalmgrip-rightgrip-upgrip-forward
vec3-xcenter
vec3-ycenter
vec3-zcenter
into-worldright-axis
into-worldup-axis
into-worldoutward
defmethodterminal-surface-focus-camera-pose

The phone is wherever the hand is; the camera stays put and only the narrowed field of view says the player is looking at it.

nil

--------------------------------------------------------------------- The display: a terminal display whose camera lives in the hand.

defclassphone-terminal-display
uniform-buffers:initform
make-hash-table:test#'eq
:readerphone-terminal-display-uniform-buffers
:documentation

A wall terminal display drawn on a phone screen: the same runs, drawn against a per-frame uniform whose camera is expressed in the grip frame.

defmethodterminal-display-frame-uniform-buffer
let
buffers
phone-terminal-display-uniform-buffersdisplay
or
gethashframebuffers
setf
gethashframebuffers
create
luvcraft-session-device
terminal-display-sessiondisplay
make-buffer-descriptor:label"phone terminal frame uniform":size
block-world-camera-uniform-size
terminal-display-sessiondisplay
:usage'
:uniform
defunphone-camera-lanes

The camera's five uniform lanes, expressed in the right hand's grip frame.

multiple-value-bind
palmgrip-rightgrip-upgrip-forward
let*
camera
luvcraft-session-camerasession
eye
camera-positioncamera
multiple-value-bind
rightupforward
flet
local
vector
make-vec3
vec3-dotvectorgrip-right
vec3-dotvectorgrip-up
vec3-dotvectorgrip-forward
camera-lanes-uniform-data
local
make-vec3
-
vec3-xeye
vec3-xpalm
-
vec3-yeye
vec3-ypalm
-
vec3-zeye
vec3-zpalm
localright
localup
localforward
widthheight
defmethodencode-luvcraft-overlay:around
sessionpasssurface-texture
let
phone
phone-screen-surface-phone
terminal-display-surfacedisplay
when
and
>
player-body-equip-amount
luvcraft-session-bodysession
0.02d0

The camera moved relative to the hand since last frame; say where it is now, in the frame the screen was built in.

destructuring-bind
canvas-extent
luvcraft-session-contextsession
call-next-method
defmethodrelease-luvcraft-overlay:after
let
buffers
phone-terminal-display-uniform-buffersdisplay
maphash
lambda
framebuffer
declare
ignoreframe
destroybuffer
buffers
clrhashbuffers

--------------------------------------------------------------------- The phone itself.

defclassphone
display:initformnil:accessorphone-display

0 when the phone is merely held, 1 when its shell has the focus and the hand has brought it square to the centre of the view; eased.

attention:initform0d0:typedouble-float:accessorphone-attention
:documentation

A comically large phone: a graphite slab with a live terminal on its face toward the player. Held in the right hand; TAB focuses its display.

defmethodhand-item-name
itemphone

phone

defmethodemit-hand-item
itemphone
bodyverticespalmrightupforwardsky-levelblock-level

The bump and the grip are boxes; the slab has real corners.

call-next-method
defmethodhand-item-carry-pose
itemphone
body
declare
ignorebody

Up in front of the face, screen toward the eye and a little to the right of centre so the crosshair still shows past its edge; when its shell has the focus, brought square to the centre and held a little further off, where the narrowed field of view frames the whole screen. Carried: at arm's length and low, tipped back so it can be glanced at on the way somewhere without taking the view. Focused: brought up square to the centre, closer, where the narrowed field of view frames the whole screen.

lerp-pose'
0.22d0-0.50d00.72d00.55d0-0.12d00.0d0
'
0.02d0-0.13d00.80d0-0.02d00.0d00.0d0
phone-attentionitem
defmethodadvance-hand-item
itemphone
bodyseconds
declare
ignorebody
let*
display
phone-displayitem
session
anddisplay
terminal-display-sessiondisplay
target
if
andsession
eqdisplay
luvcraft-session-modal-focussession
1d00d0
current
phone-attentionitem
step
*6d0seconds
setf
phone-attentionitem
cond
>targetcurrent
mintarget
+currentstep
<targetcurrent
maxtarget
-currentstep
tcurrent
defmethodmap-hand-item-boxes
declare
ignorebody
let*

The slab itself is not a box: see emit-hand-item below.

declare
ignorabler

A camera bump on the back, high on the left as seen from behind.

funcallfunction
-hw0.06d0
+cyhh-0.07d0
+czhd0.006d0
0.030d00.045d00.006d0metal:stretch-pt

The grip takes the sides, never the screen: a thumb up the right edge, fingers round the left edge with their tips just onto the bezel.

funcallfunction
+hw0.018d0
0.05d0cz0.020d00.085d00.022d0+player-skin-tile+:tilt'
0d00d0-0.12d0
funcallfunction
-
+hw0.018d0
0.01d0cz0.020d00.075d00.030d0+player-skin-tile+
funcallfunction
+
-hw
0.008d0
0.01d0
-czhd0.005d0
0.012d00.070d00.008d0+player-skin-tile+
defunphone-in-hand-p
phonesession
eqphone
player-body-hand-item
luvcraft-session-bodysession
defvar*phone-initial-mode*:shell

The mode a phone's display starts in when it is first taken out.

The phone is a terminal like a wall is, so :SHELL is what it knows by itself. The complete luvcraft system includes the Telegram presentation and sets this to :TELEGRAM when that part loads. DEFVAR deliberately preserves that application-owned choice when LUVCRAFT/CORE is reloaded live.

defunensure-phone-display
phonesession

The phone's terminal display, made -- with a shell in it -- on first use.

or
phone-displayphone
let
surface
make-instance'phone-screen-surface:phonephone
displaynil
completed-pnil
unwind-protect
multiple-value-bind
columnsrows
setfdisplay
make-terminal-displaysessionsurfacecolumnsrows:class'phone-terminal-display:fixture"":margin*phone-terminal-margin*:font-pathname:bold-font-pathname:screen-role:phone-screen:faceplate-role:phone-glass

Publish only the complete display. In particular, a Telegram startup failure must not leave a cached display in :TELEGRAM mode with no mode overlay -- a permanently black phone which ensure-phone-display would otherwise never retry.

setf
phone-displayphone
display
completed-pt
display
unless
orcompleted-p
nulldisplay
defmethodhand-item-taken-out
itemphone
bodysession
declare
ignorebody
defmethodhand-item-put-away
itemphone
bodysession
declare
ignorebody

The shell keeps running in the pocket; only the focus lets go.

let
display
phone-displayitem
when
anddisplay
eqdisplay
luvcraft-session-modal-focussession
defuntoggle-luvcraft-phone
session

Take the session's phone out, or put it away.

toggle-hand-item
luvcraft-session-bodysession
session'phone